From 8954fa3ad75d56d9419c2ccb33e697563f8165f0 Mon Sep 17 00:00:00 2001 From: Alex Jenkins Date: Tue, 14 Apr 2026 07:07:58 -0400 Subject: [PATCH] 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. --- docs/README.api-docs.ar.md | 61 + docs/README.api-docs.es.md | 53 + docs/README.api-docs.he.md | 53 + docs/README.api-docs.hi.md | 61 + docs/README.api-docs.md | 6 +- docs/README.api-docs.pt.md | 54 + docs/README.api-docs.ru.md | 53 + docs/README.api-docs.sw.md | 62 + docs/README.api-docs.tr.md | 54 + docs/README.api-docs.zh-cn.md | 53 + docs/README.ar.md | 35 + docs/README.es.md | 28 + docs/README.he.md | 34 + docs/README.hi.md | 35 + docs/README.md | 7 +- docs/README.pt.md | 28 + docs/README.ru.md | 28 + docs/README.sw.md | 28 + docs/README.tr.md | 28 + docs/README.zh-cn.md | 28 + docs/api-gateway-changes-v1.8-to-v2.1.ar.md | 108 + docs/api-gateway-changes-v1.8-to-v2.1.es.md | 108 + docs/api-gateway-changes-v1.8-to-v2.1.he.md | 106 + docs/api-gateway-changes-v1.8-to-v2.1.hi.md | 108 + docs/api-gateway-changes-v1.8-to-v2.1.pt.md | 116 + docs/api-gateway-changes-v1.8-to-v2.1.ru.md | 108 + docs/api-gateway-changes-v1.8-to-v2.1.sw.md | 114 + docs/api-gateway-changes-v1.8-to-v2.1.tr.md | 116 + .../api-gateway-changes-v1.8-to-v2.1.zh-cn.md | 108 + docs/cli-changes-v1.8-to-v2.1.ar.md | 119 + docs/cli-changes-v1.8-to-v2.1.es.md | 120 + docs/cli-changes-v1.8-to-v2.1.he.md | 119 + docs/cli-changes-v1.8-to-v2.1.hi.md | 119 + docs/cli-changes-v1.8-to-v2.1.pt.md | 120 + docs/cli-changes-v1.8-to-v2.1.ru.md | 119 + docs/cli-changes-v1.8-to-v2.1.sw.md | 123 + docs/cli-changes-v1.8-to-v2.1.tr.md | 120 + docs/cli-changes-v1.8-to-v2.1.zh-cn.md | 119 + docs/contributor-licence-agreement.ar.md | 16 + docs/contributor-licence-agreement.es.md | 16 + docs/contributor-licence-agreement.he.md | 16 + docs/contributor-licence-agreement.hi.md | 24 + docs/contributor-licence-agreement.md | 7 +- docs/contributor-licence-agreement.pt.md | 26 + docs/contributor-licence-agreement.ru.md | 16 + docs/contributor-licence-agreement.sw.md | 24 + docs/contributor-licence-agreement.tr.md | 26 + docs/contributor-licence-agreement.zh-cn.md | 16 + docs/lang-index-ar.md | 10 + docs/lang-index-es.md | 10 + docs/lang-index-he.md | 10 + docs/lang-index-hi.md | 10 + docs/lang-index-pt.md | 10 + docs/lang-index-ru.md | 10 + docs/lang-index-sw.md | 10 + docs/lang-index-tr.md | 10 + docs/lang-index-zh-cn.md | 10 + docs/python-api.ar.md | 4078 +++++++++++++++++ docs/python-api.es.md | 4078 +++++++++++++++++ docs/python-api.he.md | 4078 +++++++++++++++++ docs/python-api.hi.md | 4078 +++++++++++++++++ docs/python-api.md | 7 +- docs/python-api.pt.md | 4078 +++++++++++++++++ docs/python-api.ru.md | 4078 +++++++++++++++++ docs/python-api.sw.md | 4078 +++++++++++++++++ docs/python-api.tr.md | 4078 +++++++++++++++++ docs/python-api.zh-cn.md | 4078 +++++++++++++++++ docs/tech-specs/__TEMPLATE.ar.md | 135 + docs/tech-specs/__TEMPLATE.es.md | 135 + docs/tech-specs/__TEMPLATE.he.md | 135 + docs/tech-specs/__TEMPLATE.hi.md | 135 + docs/tech-specs/__TEMPLATE.md | 6 + docs/tech-specs/__TEMPLATE.pt.md | 135 + docs/tech-specs/__TEMPLATE.ru.md | 135 + docs/tech-specs/__TEMPLATE.sw.md | 135 + docs/tech-specs/__TEMPLATE.tr.md | 135 + docs/tech-specs/__TEMPLATE.zh-cn.md | 135 + docs/tech-specs/agent-explainability.ar.md | 280 ++ docs/tech-specs/agent-explainability.es.md | 280 ++ docs/tech-specs/agent-explainability.he.md | 280 ++ docs/tech-specs/agent-explainability.hi.md | 280 ++ docs/tech-specs/agent-explainability.md | 6 + docs/tech-specs/agent-explainability.pt.md | 280 ++ docs/tech-specs/agent-explainability.ru.md | 280 ++ docs/tech-specs/agent-explainability.sw.md | 280 ++ docs/tech-specs/agent-explainability.tr.md | 280 ++ docs/tech-specs/agent-explainability.zh-cn.md | 280 ++ docs/tech-specs/agent-orchestration.md | 6 + docs/tech-specs/architecture-principles.ar.md | 113 + docs/tech-specs/architecture-principles.es.md | 113 + docs/tech-specs/architecture-principles.he.md | 113 + docs/tech-specs/architecture-principles.hi.md | 113 + docs/tech-specs/architecture-principles.md | 7 +- docs/tech-specs/architecture-principles.pt.md | 113 + docs/tech-specs/architecture-principles.ru.md | 113 + docs/tech-specs/architecture-principles.sw.md | 113 + docs/tech-specs/architecture-principles.tr.md | 113 + .../architecture-principles.zh-cn.md | 135 + docs/tech-specs/cassandra-consolidation.ar.md | 339 ++ docs/tech-specs/cassandra-consolidation.es.md | 249 + docs/tech-specs/cassandra-consolidation.he.md | 339 ++ docs/tech-specs/cassandra-consolidation.hi.md | 339 ++ docs/tech-specs/cassandra-consolidation.md | 8 +- docs/tech-specs/cassandra-consolidation.pt.md | 339 ++ docs/tech-specs/cassandra-consolidation.ru.md | 339 ++ docs/tech-specs/cassandra-consolidation.sw.md | 339 ++ docs/tech-specs/cassandra-consolidation.tr.md | 339 ++ .../cassandra-consolidation.zh-cn.md | 339 ++ .../cassandra-performance-refactor.ar.md | 687 +++ .../cassandra-performance-refactor.es.md | 687 +++ .../cassandra-performance-refactor.he.md | 687 +++ .../cassandra-performance-refactor.hi.md | 687 +++ .../cassandra-performance-refactor.md | 6 + .../cassandra-performance-refactor.pt.md | 687 +++ .../cassandra-performance-refactor.ru.md | 687 +++ .../cassandra-performance-refactor.sw.md | 687 +++ .../cassandra-performance-refactor.tr.md | 687 +++ .../cassandra-performance-refactor.zh-cn.md | 687 +++ docs/tech-specs/collection-management.ar.md | 410 ++ docs/tech-specs/collection-management.es.md | 410 ++ docs/tech-specs/collection-management.he.md | 410 ++ docs/tech-specs/collection-management.hi.md | 410 ++ docs/tech-specs/collection-management.md | 7 +- docs/tech-specs/collection-management.pt.md | 410 ++ docs/tech-specs/collection-management.ru.md | 410 ++ docs/tech-specs/collection-management.sw.md | 410 ++ docs/tech-specs/collection-management.tr.md | 410 ++ .../tech-specs/collection-management.zh-cn.md | 410 ++ docs/tech-specs/config-push-poke.md | 6 + .../document-embeddings-chunk-id.ar.md | 144 + .../document-embeddings-chunk-id.es.md | 144 + .../document-embeddings-chunk-id.he.md | 144 + .../document-embeddings-chunk-id.hi.md | 144 + .../document-embeddings-chunk-id.md | 6 + .../document-embeddings-chunk-id.pt.md | 144 + .../document-embeddings-chunk-id.ru.md | 144 + .../document-embeddings-chunk-id.sw.md | 144 + .../document-embeddings-chunk-id.tr.md | 144 + .../document-embeddings-chunk-id.zh-cn.md | 144 + .../embeddings-batch-processing.ar.md | 675 +++ .../embeddings-batch-processing.es.md | 675 +++ .../embeddings-batch-processing.he.md | 675 +++ .../embeddings-batch-processing.hi.md | 675 +++ .../tech-specs/embeddings-batch-processing.md | 6 + .../embeddings-batch-processing.pt.md | 675 +++ .../embeddings-batch-processing.ru.md | 675 +++ .../embeddings-batch-processing.sw.md | 675 +++ .../embeddings-batch-processing.tr.md | 675 +++ .../embeddings-batch-processing.zh-cn.md | 675 +++ docs/tech-specs/entity-centric-graph.ar.md | 268 ++ docs/tech-specs/entity-centric-graph.es.md | 269 ++ docs/tech-specs/entity-centric-graph.he.md | 269 ++ docs/tech-specs/entity-centric-graph.hi.md | 268 ++ docs/tech-specs/entity-centric-graph.md | 7 +- docs/tech-specs/entity-centric-graph.pt.md | 269 ++ docs/tech-specs/entity-centric-graph.ru.md | 268 ++ docs/tech-specs/entity-centric-graph.sw.md | 268 ++ docs/tech-specs/entity-centric-graph.tr.md | 269 ++ docs/tech-specs/entity-centric-graph.zh-cn.md | 269 ++ docs/tech-specs/explainability-cli.ar.md | 178 + docs/tech-specs/explainability-cli.es.md | 188 + docs/tech-specs/explainability-cli.he.md | 228 + docs/tech-specs/explainability-cli.hi.md | 228 + docs/tech-specs/explainability-cli.md | 6 + docs/tech-specs/explainability-cli.pt.md | 228 + docs/tech-specs/explainability-cli.ru.md | 228 + docs/tech-specs/explainability-cli.sw.md | 228 + docs/tech-specs/explainability-cli.tr.md | 228 + docs/tech-specs/explainability-cli.zh-cn.md | 192 + docs/tech-specs/extraction-flows.ar.md | 355 ++ docs/tech-specs/extraction-flows.es.md | 355 ++ docs/tech-specs/extraction-flows.he.md | 355 ++ docs/tech-specs/extraction-flows.hi.md | 355 ++ docs/tech-specs/extraction-flows.md | 6 + docs/tech-specs/extraction-flows.pt.md | 355 ++ docs/tech-specs/extraction-flows.ru.md | 355 ++ docs/tech-specs/extraction-flows.sw.md | 355 ++ docs/tech-specs/extraction-flows.tr.md | 355 ++ docs/tech-specs/extraction-flows.zh-cn.md | 355 ++ .../extraction-provenance-subgraph.ar.md | 265 ++ .../extraction-provenance-subgraph.es.md | 213 + .../extraction-provenance-subgraph.he.md | 243 + .../extraction-provenance-subgraph.hi.md | 260 ++ .../extraction-provenance-subgraph.md | 6 + .../extraction-provenance-subgraph.pt.md | 247 + .../extraction-provenance-subgraph.ru.md | 268 ++ .../extraction-provenance-subgraph.sw.md | 258 ++ .../extraction-provenance-subgraph.tr.md | 275 ++ .../extraction-provenance-subgraph.zh-cn.md | 267 ++ .../extraction-time-provenance.ar.md | 886 ++++ .../extraction-time-provenance.es.md | 803 ++++ .../extraction-time-provenance.he.md | 830 ++++ .../extraction-time-provenance.hi.md | 767 ++++ docs/tech-specs/extraction-time-provenance.md | 6 + .../extraction-time-provenance.pt.md | 758 +++ .../extraction-time-provenance.ru.md | 770 ++++ .../extraction-time-provenance.sw.md | 935 ++++ .../extraction-time-provenance.tr.md | 797 ++++ .../extraction-time-provenance.zh-cn.md | 837 ++++ docs/tech-specs/flow-class-definition.ar.md | 311 ++ docs/tech-specs/flow-class-definition.es.md | 304 ++ docs/tech-specs/flow-class-definition.he.md | 328 ++ docs/tech-specs/flow-class-definition.hi.md | 328 ++ docs/tech-specs/flow-class-definition.md | 8 +- docs/tech-specs/flow-class-definition.pt.md | 317 ++ docs/tech-specs/flow-class-definition.ru.md | 313 ++ docs/tech-specs/flow-class-definition.sw.md | 399 ++ docs/tech-specs/flow-class-definition.tr.md | 326 ++ .../tech-specs/flow-class-definition.zh-cn.md | 317 ++ .../flow-configurable-parameters.ar.md | 619 +++ .../flow-configurable-parameters.es.md | 644 +++ .../flow-configurable-parameters.he.md | 590 +++ .../flow-configurable-parameters.hi.md | 598 +++ .../flow-configurable-parameters.md | 6 + .../flow-configurable-parameters.pt.md | 596 +++ .../flow-configurable-parameters.ru.md | 613 +++ .../flow-configurable-parameters.sw.md | 712 +++ .../flow-configurable-parameters.tr.md | 633 +++ .../flow-configurable-parameters.zh-cn.md | 586 +++ docs/tech-specs/graph-contexts.ar.md | 344 ++ docs/tech-specs/graph-contexts.es.md | 394 ++ docs/tech-specs/graph-contexts.he.md | 324 ++ docs/tech-specs/graph-contexts.hi.md | 376 ++ docs/tech-specs/graph-contexts.md | 6 + docs/tech-specs/graph-contexts.pt.md | 678 +++ docs/tech-specs/graph-contexts.ru.md | 415 ++ docs/tech-specs/graph-contexts.sw.md | 359 ++ docs/tech-specs/graph-contexts.tr.md | 775 ++++ docs/tech-specs/graph-contexts.zh-cn.md | 425 ++ docs/tech-specs/graphql-query.ar.md | 531 +++ docs/tech-specs/graphql-query.es.md | 467 ++ docs/tech-specs/graphql-query.he.md | 465 ++ docs/tech-specs/graphql-query.hi.md | 533 +++ docs/tech-specs/graphql-query.md | 8 +- docs/tech-specs/graphql-query.pt.md | 501 ++ docs/tech-specs/graphql-query.ru.md | 530 +++ docs/tech-specs/graphql-query.sw.md | 585 +++ docs/tech-specs/graphql-query.tr.md | 482 ++ docs/tech-specs/graphql-query.zh-cn.md | 438 ++ .../graphrag-performance-optimization.ar.md | 770 ++++ .../graphrag-performance-optimization.es.md | 309 ++ .../graphrag-performance-optimization.he.md | 807 ++++ .../graphrag-performance-optimization.hi.md | 759 +++ .../graphrag-performance-optimization.md | 6 + .../graphrag-performance-optimization.pt.md | 758 +++ .../graphrag-performance-optimization.ru.md | 745 +++ .../graphrag-performance-optimization.sw.md | 899 ++++ .../graphrag-performance-optimization.tr.md | 726 +++ ...graphrag-performance-optimization.zh-cn.md | 774 ++++ .../import-export-graceful-shutdown.ar.md | 717 +++ .../import-export-graceful-shutdown.es.md | 725 +++ .../import-export-graceful-shutdown.he.md | 713 +++ .../import-export-graceful-shutdown.hi.md | 718 +++ .../import-export-graceful-shutdown.md | 8 +- .../import-export-graceful-shutdown.pt.md | 710 +++ .../import-export-graceful-shutdown.ru.md | 717 +++ .../import-export-graceful-shutdown.sw.md | 738 +++ .../import-export-graceful-shutdown.tr.md | 729 +++ .../import-export-graceful-shutdown.zh-cn.md | 725 +++ docs/tech-specs/jsonl-prompt-output.ar.md | 540 +++ docs/tech-specs/jsonl-prompt-output.es.md | 524 +++ docs/tech-specs/jsonl-prompt-output.he.md | 548 +++ docs/tech-specs/jsonl-prompt-output.hi.md | 561 +++ docs/tech-specs/jsonl-prompt-output.md | 6 + docs/tech-specs/jsonl-prompt-output.pt.md | 504 ++ docs/tech-specs/jsonl-prompt-output.ru.md | 491 ++ docs/tech-specs/jsonl-prompt-output.sw.md | 626 +++ docs/tech-specs/jsonl-prompt-output.tr.md | 556 +++ docs/tech-specs/jsonl-prompt-output.zh-cn.md | 532 +++ docs/tech-specs/large-document-loading.ar.md | 992 ++++ docs/tech-specs/large-document-loading.es.md | 1097 +++++ docs/tech-specs/large-document-loading.he.md | 992 ++++ docs/tech-specs/large-document-loading.hi.md | 992 ++++ docs/tech-specs/large-document-loading.md | 6 + docs/tech-specs/large-document-loading.pt.md | 1105 +++++ docs/tech-specs/large-document-loading.ru.md | 992 ++++ docs/tech-specs/large-document-loading.sw.md | 1311 ++++++ docs/tech-specs/large-document-loading.tr.md | 992 ++++ .../large-document-loading.zh-cn.md | 992 ++++ docs/tech-specs/logging-strategy.ar.md | 358 ++ docs/tech-specs/logging-strategy.es.md | 215 + docs/tech-specs/logging-strategy.he.md | 358 ++ docs/tech-specs/logging-strategy.hi.md | 358 ++ docs/tech-specs/logging-strategy.md | 6 + docs/tech-specs/logging-strategy.pt.md | 358 ++ docs/tech-specs/logging-strategy.ru.md | 213 + docs/tech-specs/logging-strategy.sw.md | 358 ++ docs/tech-specs/logging-strategy.tr.md | 358 ++ docs/tech-specs/logging-strategy.zh-cn.md | 231 + docs/tech-specs/mcp-tool-arguments.ar.md | 163 + docs/tech-specs/mcp-tool-arguments.es.md | 168 + docs/tech-specs/mcp-tool-arguments.he.md | 126 + docs/tech-specs/mcp-tool-arguments.hi.md | 264 ++ docs/tech-specs/mcp-tool-arguments.md | 6 + docs/tech-specs/mcp-tool-arguments.pt.md | 264 ++ docs/tech-specs/mcp-tool-arguments.ru.md | 128 + docs/tech-specs/mcp-tool-arguments.sw.md | 264 ++ docs/tech-specs/mcp-tool-arguments.tr.md | 264 ++ docs/tech-specs/mcp-tool-arguments.zh-cn.md | 203 + docs/tech-specs/mcp-tool-bearer-token.ar.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.es.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.he.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.hi.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.md | 6 + docs/tech-specs/mcp-tool-bearer-token.pt.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.ru.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.sw.md | 562 +++ docs/tech-specs/mcp-tool-bearer-token.tr.md | 562 +++ .../tech-specs/mcp-tool-bearer-token.zh-cn.md | 562 +++ docs/tech-specs/minio-to-s3-migration.ar.md | 266 ++ docs/tech-specs/minio-to-s3-migration.es.md | 266 ++ docs/tech-specs/minio-to-s3-migration.he.md | 266 ++ docs/tech-specs/minio-to-s3-migration.hi.md | 266 ++ docs/tech-specs/minio-to-s3-migration.md | 6 + docs/tech-specs/minio-to-s3-migration.pt.md | 266 ++ docs/tech-specs/minio-to-s3-migration.ru.md | 266 ++ docs/tech-specs/minio-to-s3-migration.sw.md | 266 ++ docs/tech-specs/minio-to-s3-migration.tr.md | 266 ++ .../tech-specs/minio-to-s3-migration.zh-cn.md | 266 ++ docs/tech-specs/more-config-cli.ar.md | 159 + docs/tech-specs/more-config-cli.es.md | 165 + docs/tech-specs/more-config-cli.he.md | 151 + docs/tech-specs/more-config-cli.hi.md | 203 + docs/tech-specs/more-config-cli.md | 8 +- docs/tech-specs/more-config-cli.pt.md | 287 ++ docs/tech-specs/more-config-cli.ru.md | 210 + docs/tech-specs/more-config-cli.sw.md | 205 + docs/tech-specs/more-config-cli.tr.md | 287 ++ docs/tech-specs/more-config-cli.zh-cn.md | 186 + docs/tech-specs/multi-tenant-support.ar.md | 780 ++++ docs/tech-specs/multi-tenant-support.es.md | 780 ++++ docs/tech-specs/multi-tenant-support.he.md | 780 ++++ docs/tech-specs/multi-tenant-support.hi.md | 780 ++++ docs/tech-specs/multi-tenant-support.md | 6 + docs/tech-specs/multi-tenant-support.pt.md | 780 ++++ docs/tech-specs/multi-tenant-support.ru.md | 780 ++++ docs/tech-specs/multi-tenant-support.sw.md | 780 ++++ docs/tech-specs/multi-tenant-support.tr.md | 780 ++++ docs/tech-specs/multi-tenant-support.zh-cn.md | 780 ++++ .../neo4j-user-collection-isolation.ar.md | 198 + .../neo4j-user-collection-isolation.es.md | 217 + .../neo4j-user-collection-isolation.he.md | 196 + .../neo4j-user-collection-isolation.hi.md | 367 ++ .../neo4j-user-collection-isolation.md | 8 +- .../neo4j-user-collection-isolation.pt.md | 367 ++ .../neo4j-user-collection-isolation.ru.md | 223 + .../neo4j-user-collection-isolation.sw.md | 192 + .../neo4j-user-collection-isolation.tr.md | 367 ++ .../neo4j-user-collection-isolation.zh-cn.md | 210 + .../tech-specs/ontology-extract-phase-2.ar.md | 769 ++++ .../tech-specs/ontology-extract-phase-2.es.md | 769 ++++ .../tech-specs/ontology-extract-phase-2.he.md | 769 ++++ .../tech-specs/ontology-extract-phase-2.hi.md | 769 ++++ docs/tech-specs/ontology-extract-phase-2.md | 6 + .../tech-specs/ontology-extract-phase-2.pt.md | 769 ++++ .../tech-specs/ontology-extract-phase-2.ru.md | 769 ++++ .../tech-specs/ontology-extract-phase-2.sw.md | 769 ++++ .../tech-specs/ontology-extract-phase-2.tr.md | 769 ++++ .../ontology-extract-phase-2.zh-cn.md | 769 ++++ docs/tech-specs/ontology.ar.md | 179 + docs/tech-specs/ontology.es.md | 277 ++ docs/tech-specs/ontology.he.md | 208 + docs/tech-specs/ontology.hi.md | 188 + docs/tech-specs/ontology.md | 8 +- docs/tech-specs/ontology.pt.md | 294 ++ docs/tech-specs/ontology.ru.md | 160 + docs/tech-specs/ontology.sw.md | 155 + docs/tech-specs/ontology.tr.md | 294 ++ docs/tech-specs/ontology.zh-cn.md | 241 + docs/tech-specs/ontorag.ar.md | 1075 +++++ docs/tech-specs/ontorag.es.md | 1075 +++++ docs/tech-specs/ontorag.he.md | 1075 +++++ docs/tech-specs/ontorag.hi.md | 1075 +++++ docs/tech-specs/ontorag.md | 6 + docs/tech-specs/ontorag.pt.md | 1075 +++++ docs/tech-specs/ontorag.ru.md | 1075 +++++ docs/tech-specs/ontorag.sw.md | 1075 +++++ docs/tech-specs/ontorag.tr.md | 1075 +++++ docs/tech-specs/ontorag.zh-cn.md | 1075 +++++ docs/tech-specs/openapi-spec.ar.md | 239 + docs/tech-specs/openapi-spec.es.md | 239 + docs/tech-specs/openapi-spec.he.md | 239 + docs/tech-specs/openapi-spec.hi.md | 239 + docs/tech-specs/openapi-spec.md | 6 + docs/tech-specs/openapi-spec.pt.md | 239 + docs/tech-specs/openapi-spec.ru.md | 239 + docs/tech-specs/openapi-spec.sw.md | 239 + docs/tech-specs/openapi-spec.tr.md | 239 + docs/tech-specs/openapi-spec.zh-cn.md | 239 + docs/tech-specs/pubsub-abstraction.md | 7 +- docs/tech-specs/pubsub.ar.md | 965 ++++ docs/tech-specs/pubsub.es.md | 965 ++++ docs/tech-specs/pubsub.he.md | 965 ++++ docs/tech-specs/pubsub.hi.md | 965 ++++ docs/tech-specs/pubsub.md | 7 +- docs/tech-specs/pubsub.pt.md | 965 ++++ docs/tech-specs/pubsub.ru.md | 965 ++++ docs/tech-specs/pubsub.sw.md | 965 ++++ docs/tech-specs/pubsub.tr.md | 965 ++++ docs/tech-specs/pubsub.zh-cn.md | 965 ++++ docs/tech-specs/python-api-refactor.ar.md | 1516 ++++++ docs/tech-specs/python-api-refactor.es.md | 1516 ++++++ docs/tech-specs/python-api-refactor.he.md | 1516 ++++++ docs/tech-specs/python-api-refactor.hi.md | 1516 ++++++ docs/tech-specs/python-api-refactor.md | 6 + docs/tech-specs/python-api-refactor.pt.md | 1516 ++++++ docs/tech-specs/python-api-refactor.ru.md | 1516 ++++++ docs/tech-specs/python-api-refactor.sw.md | 1516 ++++++ docs/tech-specs/python-api-refactor.tr.md | 1516 ++++++ docs/tech-specs/python-api-refactor.zh-cn.md | 1516 ++++++ .../query-time-explainability.ar.md | 271 ++ .../query-time-explainability.es.md | 208 + .../query-time-explainability.he.md | 187 + .../query-time-explainability.hi.md | 271 ++ docs/tech-specs/query-time-explainability.md | 6 + .../query-time-explainability.pt.md | 271 ++ .../query-time-explainability.ru.md | 271 ++ .../query-time-explainability.sw.md | 271 ++ .../query-time-explainability.tr.md | 271 ++ .../query-time-explainability.zh-cn.md | 233 + docs/tech-specs/rag-streaming-support.ar.md | 174 + docs/tech-specs/rag-streaming-support.es.md | 196 + docs/tech-specs/rag-streaming-support.he.md | 176 + docs/tech-specs/rag-streaming-support.hi.md | 296 ++ docs/tech-specs/rag-streaming-support.md | 6 + docs/tech-specs/rag-streaming-support.pt.md | 296 ++ docs/tech-specs/rag-streaming-support.ru.md | 180 + docs/tech-specs/rag-streaming-support.sw.md | 296 ++ docs/tech-specs/rag-streaming-support.tr.md | 296 ++ .../tech-specs/rag-streaming-support.zh-cn.md | 199 + .../schema-refactoring-proposal.ar.md | 99 + .../schema-refactoring-proposal.es.md | 99 + .../schema-refactoring-proposal.he.md | 99 + .../schema-refactoring-proposal.hi.md | 99 + .../tech-specs/schema-refactoring-proposal.md | 8 +- .../schema-refactoring-proposal.pt.md | 99 + .../schema-refactoring-proposal.ru.md | 99 + .../schema-refactoring-proposal.sw.md | 99 + .../schema-refactoring-proposal.tr.md | 99 + .../schema-refactoring-proposal.zh-cn.md | 99 + docs/tech-specs/sparql-query.md | 6 + docs/tech-specs/streaming-llm-responses.ar.md | 578 +++ docs/tech-specs/streaming-llm-responses.es.md | 578 +++ docs/tech-specs/streaming-llm-responses.he.md | 578 +++ docs/tech-specs/streaming-llm-responses.hi.md | 578 +++ docs/tech-specs/streaming-llm-responses.md | 6 + docs/tech-specs/streaming-llm-responses.pt.md | 578 +++ docs/tech-specs/streaming-llm-responses.ru.md | 578 +++ docs/tech-specs/streaming-llm-responses.sw.md | 578 +++ docs/tech-specs/streaming-llm-responses.tr.md | 578 +++ .../streaming-llm-responses.zh-cn.md | 578 +++ docs/tech-specs/structured-data-2.ar.md | 621 +++ docs/tech-specs/structured-data-2.es.md | 621 +++ docs/tech-specs/structured-data-2.he.md | 621 +++ docs/tech-specs/structured-data-2.hi.md | 621 +++ docs/tech-specs/structured-data-2.md | 6 + docs/tech-specs/structured-data-2.pt.md | 621 +++ docs/tech-specs/structured-data-2.ru.md | 621 +++ docs/tech-specs/structured-data-2.sw.md | 621 +++ docs/tech-specs/structured-data-2.tr.md | 621 +++ docs/tech-specs/structured-data-2.zh-cn.md | 621 +++ .../structured-data-descriptor.ar.md | 567 +++ .../structured-data-descriptor.es.md | 567 +++ .../structured-data-descriptor.he.md | 567 +++ .../structured-data-descriptor.hi.md | 567 +++ docs/tech-specs/structured-data-descriptor.md | 8 +- .../structured-data-descriptor.pt.md | 567 +++ .../structured-data-descriptor.ru.md | 567 +++ .../structured-data-descriptor.sw.md | 567 +++ .../structured-data-descriptor.tr.md | 567 +++ .../structured-data-descriptor.zh-cn.md | 567 +++ docs/tech-specs/structured-data-schemas.ar.md | 139 + docs/tech-specs/structured-data-schemas.es.md | 145 + docs/tech-specs/structured-data-schemas.he.md | 147 + docs/tech-specs/structured-data-schemas.hi.md | 147 + docs/tech-specs/structured-data-schemas.md | 6 + docs/tech-specs/structured-data-schemas.pt.md | 147 + docs/tech-specs/structured-data-schemas.ru.md | 147 + docs/tech-specs/structured-data-schemas.sw.md | 130 + docs/tech-specs/structured-data-schemas.tr.md | 147 + .../structured-data-schemas.zh-cn.md | 147 + docs/tech-specs/structured-data.ar.md | 260 ++ docs/tech-specs/structured-data.es.md | 260 ++ docs/tech-specs/structured-data.he.md | 260 ++ docs/tech-specs/structured-data.hi.md | 258 ++ docs/tech-specs/structured-data.md | 7 +- docs/tech-specs/structured-data.pt.md | 260 ++ docs/tech-specs/structured-data.ru.md | 260 ++ docs/tech-specs/structured-data.sw.md | 260 ++ docs/tech-specs/structured-data.tr.md | 260 ++ docs/tech-specs/structured-data.zh-cn.md | 260 ++ docs/tech-specs/structured-diag-service.ar.md | 281 ++ docs/tech-specs/structured-diag-service.es.md | 281 ++ docs/tech-specs/structured-diag-service.he.md | 281 ++ docs/tech-specs/structured-diag-service.hi.md | 281 ++ docs/tech-specs/structured-diag-service.md | 8 +- docs/tech-specs/structured-diag-service.pt.md | 281 ++ docs/tech-specs/structured-diag-service.ru.md | 281 ++ docs/tech-specs/structured-diag-service.sw.md | 281 ++ docs/tech-specs/structured-diag-service.tr.md | 281 ++ .../structured-diag-service.zh-cn.md | 281 ++ docs/tech-specs/tool-group.ar.md | 499 ++ docs/tech-specs/tool-group.es.md | 499 ++ docs/tech-specs/tool-group.he.md | 499 ++ docs/tech-specs/tool-group.hi.md | 499 ++ docs/tech-specs/tool-group.md | 6 + docs/tech-specs/tool-group.pt.md | 499 ++ docs/tech-specs/tool-group.ru.md | 499 ++ docs/tech-specs/tool-group.sw.md | 499 ++ docs/tech-specs/tool-group.tr.md | 499 ++ docs/tech-specs/tool-group.zh-cn.md | 499 ++ docs/tech-specs/tool-services.ar.md | 479 ++ docs/tech-specs/tool-services.es.md | 479 ++ docs/tech-specs/tool-services.he.md | 479 ++ docs/tech-specs/tool-services.hi.md | 479 ++ docs/tech-specs/tool-services.md | 6 + docs/tech-specs/tool-services.pt.md | 479 ++ docs/tech-specs/tool-services.ru.md | 479 ++ docs/tech-specs/tool-services.sw.md | 479 ++ docs/tech-specs/tool-services.tr.md | 479 ++ docs/tech-specs/tool-services.zh-cn.md | 479 ++ docs/tech-specs/universal-decoder.ar.md | 419 ++ docs/tech-specs/universal-decoder.es.md | 404 ++ docs/tech-specs/universal-decoder.he.md | 404 ++ docs/tech-specs/universal-decoder.hi.md | 404 ++ docs/tech-specs/universal-decoder.md | 6 + docs/tech-specs/universal-decoder.pt.md | 404 ++ docs/tech-specs/universal-decoder.ru.md | 200 + docs/tech-specs/universal-decoder.sw.md | 228 + docs/tech-specs/universal-decoder.tr.md | 404 ++ docs/tech-specs/universal-decoder.zh-cn.md | 297 ++ docs/tech-specs/vector-store-lifecycle.ar.md | 307 ++ docs/tech-specs/vector-store-lifecycle.es.md | 307 ++ docs/tech-specs/vector-store-lifecycle.he.md | 307 ++ docs/tech-specs/vector-store-lifecycle.hi.md | 307 ++ docs/tech-specs/vector-store-lifecycle.md | 6 + docs/tech-specs/vector-store-lifecycle.pt.md | 307 ++ docs/tech-specs/vector-store-lifecycle.ru.md | 307 ++ docs/tech-specs/vector-store-lifecycle.sw.md | 307 ++ docs/tech-specs/vector-store-lifecycle.tr.md | 307 ++ .../vector-store-lifecycle.zh-cn.md | 307 ++ tests/conftest.py | 14 +- tests/unit/test_base/test_i18n.py | 40 + tests/unit/test_gateway/test_endpoint_i18n.py | 75 + trustgraph-base/pyproject.toml | 3 + trustgraph-base/trustgraph/i18n/__init__.py | 156 + .../trustgraph/i18n/packs/__init__.py | 1 + trustgraph-base/trustgraph/i18n/packs/ar.json | 54 + trustgraph-base/trustgraph/i18n/packs/en.json | 54 + trustgraph-base/trustgraph/i18n/packs/es.json | 54 + trustgraph-base/trustgraph/i18n/packs/he.json | 54 + trustgraph-base/trustgraph/i18n/packs/hi.json | 54 + trustgraph-base/trustgraph/i18n/packs/pt.json | 54 + trustgraph-base/trustgraph/i18n/packs/ru.json | 54 + trustgraph-base/trustgraph/i18n/packs/sw.json | 54 + trustgraph-base/trustgraph/i18n/packs/tr.json | 54 + .../trustgraph/i18n/packs/zh-cn.json | 54 + .../trustgraph/cli/verify_system_status.py | 174 +- .../trustgraph/gateway/endpoint/i18n.py | 51 + .../trustgraph/gateway/endpoint/manager.py | 5 + 560 files changed, 236300 insertions(+), 99 deletions(-) create mode 100644 docs/README.api-docs.ar.md create mode 100644 docs/README.api-docs.es.md create mode 100644 docs/README.api-docs.he.md create mode 100644 docs/README.api-docs.hi.md create mode 100644 docs/README.api-docs.pt.md create mode 100644 docs/README.api-docs.ru.md create mode 100644 docs/README.api-docs.sw.md create mode 100644 docs/README.api-docs.tr.md create mode 100644 docs/README.api-docs.zh-cn.md create mode 100644 docs/README.ar.md create mode 100644 docs/README.es.md create mode 100644 docs/README.he.md create mode 100644 docs/README.hi.md create mode 100644 docs/README.pt.md create mode 100644 docs/README.ru.md create mode 100644 docs/README.sw.md create mode 100644 docs/README.tr.md create mode 100644 docs/README.zh-cn.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.ar.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.es.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.he.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.hi.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.pt.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.ru.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.sw.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.tr.md create mode 100644 docs/api-gateway-changes-v1.8-to-v2.1.zh-cn.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.ar.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.es.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.he.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.hi.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.pt.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.ru.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.sw.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.tr.md create mode 100644 docs/cli-changes-v1.8-to-v2.1.zh-cn.md create mode 100644 docs/contributor-licence-agreement.ar.md create mode 100644 docs/contributor-licence-agreement.es.md create mode 100644 docs/contributor-licence-agreement.he.md create mode 100644 docs/contributor-licence-agreement.hi.md create mode 100644 docs/contributor-licence-agreement.pt.md create mode 100644 docs/contributor-licence-agreement.ru.md create mode 100644 docs/contributor-licence-agreement.sw.md create mode 100644 docs/contributor-licence-agreement.tr.md create mode 100644 docs/contributor-licence-agreement.zh-cn.md create mode 100644 docs/lang-index-ar.md create mode 100644 docs/lang-index-es.md create mode 100644 docs/lang-index-he.md create mode 100644 docs/lang-index-hi.md create mode 100644 docs/lang-index-pt.md create mode 100644 docs/lang-index-ru.md create mode 100644 docs/lang-index-sw.md create mode 100644 docs/lang-index-tr.md create mode 100644 docs/lang-index-zh-cn.md create mode 100644 docs/python-api.ar.md create mode 100644 docs/python-api.es.md create mode 100644 docs/python-api.he.md create mode 100644 docs/python-api.hi.md create mode 100644 docs/python-api.pt.md create mode 100644 docs/python-api.ru.md create mode 100644 docs/python-api.sw.md create mode 100644 docs/python-api.tr.md create mode 100644 docs/python-api.zh-cn.md create mode 100644 docs/tech-specs/__TEMPLATE.ar.md create mode 100644 docs/tech-specs/__TEMPLATE.es.md create mode 100644 docs/tech-specs/__TEMPLATE.he.md create mode 100644 docs/tech-specs/__TEMPLATE.hi.md create mode 100644 docs/tech-specs/__TEMPLATE.pt.md create mode 100644 docs/tech-specs/__TEMPLATE.ru.md create mode 100644 docs/tech-specs/__TEMPLATE.sw.md create mode 100644 docs/tech-specs/__TEMPLATE.tr.md create mode 100644 docs/tech-specs/__TEMPLATE.zh-cn.md create mode 100644 docs/tech-specs/agent-explainability.ar.md create mode 100644 docs/tech-specs/agent-explainability.es.md create mode 100644 docs/tech-specs/agent-explainability.he.md create mode 100644 docs/tech-specs/agent-explainability.hi.md create mode 100644 docs/tech-specs/agent-explainability.pt.md create mode 100644 docs/tech-specs/agent-explainability.ru.md create mode 100644 docs/tech-specs/agent-explainability.sw.md create mode 100644 docs/tech-specs/agent-explainability.tr.md create mode 100644 docs/tech-specs/agent-explainability.zh-cn.md create mode 100644 docs/tech-specs/architecture-principles.ar.md create mode 100644 docs/tech-specs/architecture-principles.es.md create mode 100644 docs/tech-specs/architecture-principles.he.md create mode 100644 docs/tech-specs/architecture-principles.hi.md create mode 100644 docs/tech-specs/architecture-principles.pt.md create mode 100644 docs/tech-specs/architecture-principles.ru.md create mode 100644 docs/tech-specs/architecture-principles.sw.md create mode 100644 docs/tech-specs/architecture-principles.tr.md create mode 100644 docs/tech-specs/architecture-principles.zh-cn.md create mode 100644 docs/tech-specs/cassandra-consolidation.ar.md create mode 100644 docs/tech-specs/cassandra-consolidation.es.md create mode 100644 docs/tech-specs/cassandra-consolidation.he.md create mode 100644 docs/tech-specs/cassandra-consolidation.hi.md create mode 100644 docs/tech-specs/cassandra-consolidation.pt.md create mode 100644 docs/tech-specs/cassandra-consolidation.ru.md create mode 100644 docs/tech-specs/cassandra-consolidation.sw.md create mode 100644 docs/tech-specs/cassandra-consolidation.tr.md create mode 100644 docs/tech-specs/cassandra-consolidation.zh-cn.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.ar.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.es.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.he.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.hi.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.pt.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.ru.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.sw.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.tr.md create mode 100644 docs/tech-specs/cassandra-performance-refactor.zh-cn.md create mode 100644 docs/tech-specs/collection-management.ar.md create mode 100644 docs/tech-specs/collection-management.es.md create mode 100644 docs/tech-specs/collection-management.he.md create mode 100644 docs/tech-specs/collection-management.hi.md create mode 100644 docs/tech-specs/collection-management.pt.md create mode 100644 docs/tech-specs/collection-management.ru.md create mode 100644 docs/tech-specs/collection-management.sw.md create mode 100644 docs/tech-specs/collection-management.tr.md create mode 100644 docs/tech-specs/collection-management.zh-cn.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.ar.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.es.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.he.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.hi.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.pt.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.ru.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.sw.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.tr.md create mode 100644 docs/tech-specs/document-embeddings-chunk-id.zh-cn.md create mode 100644 docs/tech-specs/embeddings-batch-processing.ar.md create mode 100644 docs/tech-specs/embeddings-batch-processing.es.md create mode 100644 docs/tech-specs/embeddings-batch-processing.he.md create mode 100644 docs/tech-specs/embeddings-batch-processing.hi.md create mode 100644 docs/tech-specs/embeddings-batch-processing.pt.md create mode 100644 docs/tech-specs/embeddings-batch-processing.ru.md create mode 100644 docs/tech-specs/embeddings-batch-processing.sw.md create mode 100644 docs/tech-specs/embeddings-batch-processing.tr.md create mode 100644 docs/tech-specs/embeddings-batch-processing.zh-cn.md create mode 100644 docs/tech-specs/entity-centric-graph.ar.md create mode 100644 docs/tech-specs/entity-centric-graph.es.md create mode 100644 docs/tech-specs/entity-centric-graph.he.md create mode 100644 docs/tech-specs/entity-centric-graph.hi.md create mode 100644 docs/tech-specs/entity-centric-graph.pt.md create mode 100644 docs/tech-specs/entity-centric-graph.ru.md create mode 100644 docs/tech-specs/entity-centric-graph.sw.md create mode 100644 docs/tech-specs/entity-centric-graph.tr.md create mode 100644 docs/tech-specs/entity-centric-graph.zh-cn.md create mode 100644 docs/tech-specs/explainability-cli.ar.md create mode 100644 docs/tech-specs/explainability-cli.es.md create mode 100644 docs/tech-specs/explainability-cli.he.md create mode 100644 docs/tech-specs/explainability-cli.hi.md create mode 100644 docs/tech-specs/explainability-cli.pt.md create mode 100644 docs/tech-specs/explainability-cli.ru.md create mode 100644 docs/tech-specs/explainability-cli.sw.md create mode 100644 docs/tech-specs/explainability-cli.tr.md create mode 100644 docs/tech-specs/explainability-cli.zh-cn.md create mode 100644 docs/tech-specs/extraction-flows.ar.md create mode 100644 docs/tech-specs/extraction-flows.es.md create mode 100644 docs/tech-specs/extraction-flows.he.md create mode 100644 docs/tech-specs/extraction-flows.hi.md create mode 100644 docs/tech-specs/extraction-flows.pt.md create mode 100644 docs/tech-specs/extraction-flows.ru.md create mode 100644 docs/tech-specs/extraction-flows.sw.md create mode 100644 docs/tech-specs/extraction-flows.tr.md create mode 100644 docs/tech-specs/extraction-flows.zh-cn.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.ar.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.es.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.he.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.hi.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.pt.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.ru.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.sw.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.tr.md create mode 100644 docs/tech-specs/extraction-provenance-subgraph.zh-cn.md create mode 100644 docs/tech-specs/extraction-time-provenance.ar.md create mode 100644 docs/tech-specs/extraction-time-provenance.es.md create mode 100644 docs/tech-specs/extraction-time-provenance.he.md create mode 100644 docs/tech-specs/extraction-time-provenance.hi.md create mode 100644 docs/tech-specs/extraction-time-provenance.pt.md create mode 100644 docs/tech-specs/extraction-time-provenance.ru.md create mode 100644 docs/tech-specs/extraction-time-provenance.sw.md create mode 100644 docs/tech-specs/extraction-time-provenance.tr.md create mode 100644 docs/tech-specs/extraction-time-provenance.zh-cn.md create mode 100644 docs/tech-specs/flow-class-definition.ar.md create mode 100644 docs/tech-specs/flow-class-definition.es.md create mode 100644 docs/tech-specs/flow-class-definition.he.md create mode 100644 docs/tech-specs/flow-class-definition.hi.md create mode 100644 docs/tech-specs/flow-class-definition.pt.md create mode 100644 docs/tech-specs/flow-class-definition.ru.md create mode 100644 docs/tech-specs/flow-class-definition.sw.md create mode 100644 docs/tech-specs/flow-class-definition.tr.md create mode 100644 docs/tech-specs/flow-class-definition.zh-cn.md create mode 100644 docs/tech-specs/flow-configurable-parameters.ar.md create mode 100644 docs/tech-specs/flow-configurable-parameters.es.md create mode 100644 docs/tech-specs/flow-configurable-parameters.he.md create mode 100644 docs/tech-specs/flow-configurable-parameters.hi.md create mode 100644 docs/tech-specs/flow-configurable-parameters.pt.md create mode 100644 docs/tech-specs/flow-configurable-parameters.ru.md create mode 100644 docs/tech-specs/flow-configurable-parameters.sw.md create mode 100644 docs/tech-specs/flow-configurable-parameters.tr.md create mode 100644 docs/tech-specs/flow-configurable-parameters.zh-cn.md create mode 100644 docs/tech-specs/graph-contexts.ar.md create mode 100644 docs/tech-specs/graph-contexts.es.md create mode 100644 docs/tech-specs/graph-contexts.he.md create mode 100644 docs/tech-specs/graph-contexts.hi.md create mode 100644 docs/tech-specs/graph-contexts.pt.md create mode 100644 docs/tech-specs/graph-contexts.ru.md create mode 100644 docs/tech-specs/graph-contexts.sw.md create mode 100644 docs/tech-specs/graph-contexts.tr.md create mode 100644 docs/tech-specs/graph-contexts.zh-cn.md create mode 100644 docs/tech-specs/graphql-query.ar.md create mode 100644 docs/tech-specs/graphql-query.es.md create mode 100644 docs/tech-specs/graphql-query.he.md create mode 100644 docs/tech-specs/graphql-query.hi.md create mode 100644 docs/tech-specs/graphql-query.pt.md create mode 100644 docs/tech-specs/graphql-query.ru.md create mode 100644 docs/tech-specs/graphql-query.sw.md create mode 100644 docs/tech-specs/graphql-query.tr.md create mode 100644 docs/tech-specs/graphql-query.zh-cn.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.ar.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.es.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.he.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.hi.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.pt.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.ru.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.sw.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.tr.md create mode 100644 docs/tech-specs/graphrag-performance-optimization.zh-cn.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.ar.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.es.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.he.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.hi.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.pt.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.ru.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.sw.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.tr.md create mode 100644 docs/tech-specs/import-export-graceful-shutdown.zh-cn.md create mode 100644 docs/tech-specs/jsonl-prompt-output.ar.md create mode 100644 docs/tech-specs/jsonl-prompt-output.es.md create mode 100644 docs/tech-specs/jsonl-prompt-output.he.md create mode 100644 docs/tech-specs/jsonl-prompt-output.hi.md create mode 100644 docs/tech-specs/jsonl-prompt-output.pt.md create mode 100644 docs/tech-specs/jsonl-prompt-output.ru.md create mode 100644 docs/tech-specs/jsonl-prompt-output.sw.md create mode 100644 docs/tech-specs/jsonl-prompt-output.tr.md create mode 100644 docs/tech-specs/jsonl-prompt-output.zh-cn.md create mode 100644 docs/tech-specs/large-document-loading.ar.md create mode 100644 docs/tech-specs/large-document-loading.es.md create mode 100644 docs/tech-specs/large-document-loading.he.md create mode 100644 docs/tech-specs/large-document-loading.hi.md create mode 100644 docs/tech-specs/large-document-loading.pt.md create mode 100644 docs/tech-specs/large-document-loading.ru.md create mode 100644 docs/tech-specs/large-document-loading.sw.md create mode 100644 docs/tech-specs/large-document-loading.tr.md create mode 100644 docs/tech-specs/large-document-loading.zh-cn.md create mode 100644 docs/tech-specs/logging-strategy.ar.md create mode 100644 docs/tech-specs/logging-strategy.es.md create mode 100644 docs/tech-specs/logging-strategy.he.md create mode 100644 docs/tech-specs/logging-strategy.hi.md create mode 100644 docs/tech-specs/logging-strategy.pt.md create mode 100644 docs/tech-specs/logging-strategy.ru.md create mode 100644 docs/tech-specs/logging-strategy.sw.md create mode 100644 docs/tech-specs/logging-strategy.tr.md create mode 100644 docs/tech-specs/logging-strategy.zh-cn.md create mode 100644 docs/tech-specs/mcp-tool-arguments.ar.md create mode 100644 docs/tech-specs/mcp-tool-arguments.es.md create mode 100644 docs/tech-specs/mcp-tool-arguments.he.md create mode 100644 docs/tech-specs/mcp-tool-arguments.hi.md create mode 100644 docs/tech-specs/mcp-tool-arguments.pt.md create mode 100644 docs/tech-specs/mcp-tool-arguments.ru.md create mode 100644 docs/tech-specs/mcp-tool-arguments.sw.md create mode 100644 docs/tech-specs/mcp-tool-arguments.tr.md create mode 100644 docs/tech-specs/mcp-tool-arguments.zh-cn.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.ar.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.es.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.he.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.hi.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.pt.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.ru.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.sw.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.tr.md create mode 100644 docs/tech-specs/mcp-tool-bearer-token.zh-cn.md create mode 100644 docs/tech-specs/minio-to-s3-migration.ar.md create mode 100644 docs/tech-specs/minio-to-s3-migration.es.md create mode 100644 docs/tech-specs/minio-to-s3-migration.he.md create mode 100644 docs/tech-specs/minio-to-s3-migration.hi.md create mode 100644 docs/tech-specs/minio-to-s3-migration.pt.md create mode 100644 docs/tech-specs/minio-to-s3-migration.ru.md create mode 100644 docs/tech-specs/minio-to-s3-migration.sw.md create mode 100644 docs/tech-specs/minio-to-s3-migration.tr.md create mode 100644 docs/tech-specs/minio-to-s3-migration.zh-cn.md create mode 100644 docs/tech-specs/more-config-cli.ar.md create mode 100644 docs/tech-specs/more-config-cli.es.md create mode 100644 docs/tech-specs/more-config-cli.he.md create mode 100644 docs/tech-specs/more-config-cli.hi.md create mode 100644 docs/tech-specs/more-config-cli.pt.md create mode 100644 docs/tech-specs/more-config-cli.ru.md create mode 100644 docs/tech-specs/more-config-cli.sw.md create mode 100644 docs/tech-specs/more-config-cli.tr.md create mode 100644 docs/tech-specs/more-config-cli.zh-cn.md create mode 100644 docs/tech-specs/multi-tenant-support.ar.md create mode 100644 docs/tech-specs/multi-tenant-support.es.md create mode 100644 docs/tech-specs/multi-tenant-support.he.md create mode 100644 docs/tech-specs/multi-tenant-support.hi.md create mode 100644 docs/tech-specs/multi-tenant-support.pt.md create mode 100644 docs/tech-specs/multi-tenant-support.ru.md create mode 100644 docs/tech-specs/multi-tenant-support.sw.md create mode 100644 docs/tech-specs/multi-tenant-support.tr.md create mode 100644 docs/tech-specs/multi-tenant-support.zh-cn.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.ar.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.es.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.he.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.hi.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.pt.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.ru.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.sw.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.tr.md create mode 100644 docs/tech-specs/neo4j-user-collection-isolation.zh-cn.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.ar.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.es.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.he.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.hi.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.pt.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.ru.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.sw.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.tr.md create mode 100644 docs/tech-specs/ontology-extract-phase-2.zh-cn.md create mode 100644 docs/tech-specs/ontology.ar.md create mode 100644 docs/tech-specs/ontology.es.md create mode 100644 docs/tech-specs/ontology.he.md create mode 100644 docs/tech-specs/ontology.hi.md create mode 100644 docs/tech-specs/ontology.pt.md create mode 100644 docs/tech-specs/ontology.ru.md create mode 100644 docs/tech-specs/ontology.sw.md create mode 100644 docs/tech-specs/ontology.tr.md create mode 100644 docs/tech-specs/ontology.zh-cn.md create mode 100644 docs/tech-specs/ontorag.ar.md create mode 100644 docs/tech-specs/ontorag.es.md create mode 100644 docs/tech-specs/ontorag.he.md create mode 100644 docs/tech-specs/ontorag.hi.md create mode 100644 docs/tech-specs/ontorag.pt.md create mode 100644 docs/tech-specs/ontorag.ru.md create mode 100644 docs/tech-specs/ontorag.sw.md create mode 100644 docs/tech-specs/ontorag.tr.md create mode 100644 docs/tech-specs/ontorag.zh-cn.md create mode 100644 docs/tech-specs/openapi-spec.ar.md create mode 100644 docs/tech-specs/openapi-spec.es.md create mode 100644 docs/tech-specs/openapi-spec.he.md create mode 100644 docs/tech-specs/openapi-spec.hi.md create mode 100644 docs/tech-specs/openapi-spec.pt.md create mode 100644 docs/tech-specs/openapi-spec.ru.md create mode 100644 docs/tech-specs/openapi-spec.sw.md create mode 100644 docs/tech-specs/openapi-spec.tr.md create mode 100644 docs/tech-specs/openapi-spec.zh-cn.md create mode 100644 docs/tech-specs/pubsub.ar.md create mode 100644 docs/tech-specs/pubsub.es.md create mode 100644 docs/tech-specs/pubsub.he.md create mode 100644 docs/tech-specs/pubsub.hi.md create mode 100644 docs/tech-specs/pubsub.pt.md create mode 100644 docs/tech-specs/pubsub.ru.md create mode 100644 docs/tech-specs/pubsub.sw.md create mode 100644 docs/tech-specs/pubsub.tr.md create mode 100644 docs/tech-specs/pubsub.zh-cn.md create mode 100644 docs/tech-specs/python-api-refactor.ar.md create mode 100644 docs/tech-specs/python-api-refactor.es.md create mode 100644 docs/tech-specs/python-api-refactor.he.md create mode 100644 docs/tech-specs/python-api-refactor.hi.md create mode 100644 docs/tech-specs/python-api-refactor.pt.md create mode 100644 docs/tech-specs/python-api-refactor.ru.md create mode 100644 docs/tech-specs/python-api-refactor.sw.md create mode 100644 docs/tech-specs/python-api-refactor.tr.md create mode 100644 docs/tech-specs/python-api-refactor.zh-cn.md create mode 100644 docs/tech-specs/query-time-explainability.ar.md create mode 100644 docs/tech-specs/query-time-explainability.es.md create mode 100644 docs/tech-specs/query-time-explainability.he.md create mode 100644 docs/tech-specs/query-time-explainability.hi.md create mode 100644 docs/tech-specs/query-time-explainability.pt.md create mode 100644 docs/tech-specs/query-time-explainability.ru.md create mode 100644 docs/tech-specs/query-time-explainability.sw.md create mode 100644 docs/tech-specs/query-time-explainability.tr.md create mode 100644 docs/tech-specs/query-time-explainability.zh-cn.md create mode 100644 docs/tech-specs/rag-streaming-support.ar.md create mode 100644 docs/tech-specs/rag-streaming-support.es.md create mode 100644 docs/tech-specs/rag-streaming-support.he.md create mode 100644 docs/tech-specs/rag-streaming-support.hi.md create mode 100644 docs/tech-specs/rag-streaming-support.pt.md create mode 100644 docs/tech-specs/rag-streaming-support.ru.md create mode 100644 docs/tech-specs/rag-streaming-support.sw.md create mode 100644 docs/tech-specs/rag-streaming-support.tr.md create mode 100644 docs/tech-specs/rag-streaming-support.zh-cn.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.ar.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.es.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.he.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.hi.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.pt.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.ru.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.sw.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.tr.md create mode 100644 docs/tech-specs/schema-refactoring-proposal.zh-cn.md create mode 100644 docs/tech-specs/streaming-llm-responses.ar.md create mode 100644 docs/tech-specs/streaming-llm-responses.es.md create mode 100644 docs/tech-specs/streaming-llm-responses.he.md create mode 100644 docs/tech-specs/streaming-llm-responses.hi.md create mode 100644 docs/tech-specs/streaming-llm-responses.pt.md create mode 100644 docs/tech-specs/streaming-llm-responses.ru.md create mode 100644 docs/tech-specs/streaming-llm-responses.sw.md create mode 100644 docs/tech-specs/streaming-llm-responses.tr.md create mode 100644 docs/tech-specs/streaming-llm-responses.zh-cn.md create mode 100644 docs/tech-specs/structured-data-2.ar.md create mode 100644 docs/tech-specs/structured-data-2.es.md create mode 100644 docs/tech-specs/structured-data-2.he.md create mode 100644 docs/tech-specs/structured-data-2.hi.md create mode 100644 docs/tech-specs/structured-data-2.pt.md create mode 100644 docs/tech-specs/structured-data-2.ru.md create mode 100644 docs/tech-specs/structured-data-2.sw.md create mode 100644 docs/tech-specs/structured-data-2.tr.md create mode 100644 docs/tech-specs/structured-data-2.zh-cn.md create mode 100644 docs/tech-specs/structured-data-descriptor.ar.md create mode 100644 docs/tech-specs/structured-data-descriptor.es.md create mode 100644 docs/tech-specs/structured-data-descriptor.he.md create mode 100644 docs/tech-specs/structured-data-descriptor.hi.md create mode 100644 docs/tech-specs/structured-data-descriptor.pt.md create mode 100644 docs/tech-specs/structured-data-descriptor.ru.md create mode 100644 docs/tech-specs/structured-data-descriptor.sw.md create mode 100644 docs/tech-specs/structured-data-descriptor.tr.md create mode 100644 docs/tech-specs/structured-data-descriptor.zh-cn.md create mode 100644 docs/tech-specs/structured-data-schemas.ar.md create mode 100644 docs/tech-specs/structured-data-schemas.es.md create mode 100644 docs/tech-specs/structured-data-schemas.he.md create mode 100644 docs/tech-specs/structured-data-schemas.hi.md create mode 100644 docs/tech-specs/structured-data-schemas.pt.md create mode 100644 docs/tech-specs/structured-data-schemas.ru.md create mode 100644 docs/tech-specs/structured-data-schemas.sw.md create mode 100644 docs/tech-specs/structured-data-schemas.tr.md create mode 100644 docs/tech-specs/structured-data-schemas.zh-cn.md create mode 100644 docs/tech-specs/structured-data.ar.md create mode 100644 docs/tech-specs/structured-data.es.md create mode 100644 docs/tech-specs/structured-data.he.md create mode 100644 docs/tech-specs/structured-data.hi.md create mode 100644 docs/tech-specs/structured-data.pt.md create mode 100644 docs/tech-specs/structured-data.ru.md create mode 100644 docs/tech-specs/structured-data.sw.md create mode 100644 docs/tech-specs/structured-data.tr.md create mode 100644 docs/tech-specs/structured-data.zh-cn.md create mode 100644 docs/tech-specs/structured-diag-service.ar.md create mode 100644 docs/tech-specs/structured-diag-service.es.md create mode 100644 docs/tech-specs/structured-diag-service.he.md create mode 100644 docs/tech-specs/structured-diag-service.hi.md create mode 100644 docs/tech-specs/structured-diag-service.pt.md create mode 100644 docs/tech-specs/structured-diag-service.ru.md create mode 100644 docs/tech-specs/structured-diag-service.sw.md create mode 100644 docs/tech-specs/structured-diag-service.tr.md create mode 100644 docs/tech-specs/structured-diag-service.zh-cn.md create mode 100644 docs/tech-specs/tool-group.ar.md create mode 100644 docs/tech-specs/tool-group.es.md create mode 100644 docs/tech-specs/tool-group.he.md create mode 100644 docs/tech-specs/tool-group.hi.md create mode 100644 docs/tech-specs/tool-group.pt.md create mode 100644 docs/tech-specs/tool-group.ru.md create mode 100644 docs/tech-specs/tool-group.sw.md create mode 100644 docs/tech-specs/tool-group.tr.md create mode 100644 docs/tech-specs/tool-group.zh-cn.md create mode 100644 docs/tech-specs/tool-services.ar.md create mode 100644 docs/tech-specs/tool-services.es.md create mode 100644 docs/tech-specs/tool-services.he.md create mode 100644 docs/tech-specs/tool-services.hi.md create mode 100644 docs/tech-specs/tool-services.pt.md create mode 100644 docs/tech-specs/tool-services.ru.md create mode 100644 docs/tech-specs/tool-services.sw.md create mode 100644 docs/tech-specs/tool-services.tr.md create mode 100644 docs/tech-specs/tool-services.zh-cn.md create mode 100644 docs/tech-specs/universal-decoder.ar.md create mode 100644 docs/tech-specs/universal-decoder.es.md create mode 100644 docs/tech-specs/universal-decoder.he.md create mode 100644 docs/tech-specs/universal-decoder.hi.md create mode 100644 docs/tech-specs/universal-decoder.pt.md create mode 100644 docs/tech-specs/universal-decoder.ru.md create mode 100644 docs/tech-specs/universal-decoder.sw.md create mode 100644 docs/tech-specs/universal-decoder.tr.md create mode 100644 docs/tech-specs/universal-decoder.zh-cn.md create mode 100644 docs/tech-specs/vector-store-lifecycle.ar.md create mode 100644 docs/tech-specs/vector-store-lifecycle.es.md create mode 100644 docs/tech-specs/vector-store-lifecycle.he.md create mode 100644 docs/tech-specs/vector-store-lifecycle.hi.md create mode 100644 docs/tech-specs/vector-store-lifecycle.pt.md create mode 100644 docs/tech-specs/vector-store-lifecycle.ru.md create mode 100644 docs/tech-specs/vector-store-lifecycle.sw.md create mode 100644 docs/tech-specs/vector-store-lifecycle.tr.md create mode 100644 docs/tech-specs/vector-store-lifecycle.zh-cn.md create mode 100644 tests/unit/test_base/test_i18n.py create mode 100644 tests/unit/test_gateway/test_endpoint_i18n.py create mode 100644 trustgraph-base/trustgraph/i18n/__init__.py create mode 100644 trustgraph-base/trustgraph/i18n/packs/__init__.py create mode 100644 trustgraph-base/trustgraph/i18n/packs/ar.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/en.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/es.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/he.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/hi.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/pt.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/ru.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/sw.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/tr.json create mode 100644 trustgraph-base/trustgraph/i18n/packs/zh-cn.json create mode 100644 trustgraph-flow/trustgraph/gateway/endpoint/i18n.py diff --git a/docs/README.api-docs.ar.md b/docs/README.api-docs.ar.md new file mode 100644 index 00000000..3880e0e0 --- /dev/null +++ b/docs/README.api-docs.ar.md @@ -0,0 +1,61 @@ +--- +layout: default +title: "إنشاء الوثائق تلقائيًا" +parent: "Arabic (Beta)" +--- + +**تعليمات مهمة:** + +- الحفاظ على جميع تنسيقات Markdown، والعناوين، والروابط، وعلامات HTML. +- لا تقم بترجمة الكود الموجود داخل علامات backticks أو كتل الكود. +- قم بإخراج النص المترجم فقط، بدون مقدمات أو تفسيرات. + +النص المراد ترجمته: + +# إنشاء الوثائق تلقائيًا + +> **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. + +## وثائق واجهة برمجة تطبيقات REST و WebSocket + +- `specs/build-docs.sh` - يقوم بإنشاء وثائق REST و WebSocket من مواصفات OpenAPI و AsyncAPI. + +## وثائق واجهة برمجة تطبيقات Python + +يتم إنشاء وثائق واجهة برمجة تطبيقات Python من سلاسل التوثيق باستخدام نص برمجي Python مخصص يقوم بتحليل حزمة `trustgraph.api`. + +### المتطلبات الأساسية + +يجب أن تكون حزمة trustgraph قابلة للاستيراد. إذا كنت تعمل في بيئة تطوير: + +```bash +cd trustgraph-base +pip install -e . +``` + +### إنشاء الوثائق + +من دليل الوثائق: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +يولد هذا ملف Markdown واحد يحتوي على وثائق واجهة برمجة تطبيقات كاملة، ويظهر: +- دليل التثبيت والإرشادات السريعة +- عبارات الاستيراد لكل فئة/نوع +- سلاسل التوثيق الكاملة مع أمثلة +- جدول محتويات مُنظمة حسب الفئة + +### أسلوب الوثائق + +تتبع جميع سلاسل التوثيق تنسيق Google: +- ملخص موجز في سطر واحد +- وصف تفصيلي +- قسم Args مع أوصاف المعلمات +- قسم Returns +- قسم Raises (عندما يكون ذلك مناسبًا) +- كتل كود مع تمييز نحوي مناسب + +تعرض الوثائق التي تم إنشاؤها واجهة برمجة التطبيقات العامة تمامًا كما يستوردها المستخدمون من `trustgraph.api`، دون الكشف عن هيكل الوحدة الداخلية. diff --git a/docs/README.api-docs.es.md b/docs/README.api-docs.es.md new file mode 100644 index 00000000..46d48496 --- /dev/null +++ b/docs/README.api-docs.es.md @@ -0,0 +1,53 @@ +--- +layout: default +title: "Generación automática de documentación" +parent: "Spanish (Beta)" +--- + +# Generación automática de documentación + +> **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. + +## Documentación de la API REST y WebSocket + +- `specs/build-docs.sh` - Genera la documentación de la API REST y WebSocket a partir de las especificaciones OpenAPI y AsyncAPI. + +## Documentación de la API Python + +La documentación de la API Python se genera a partir de los docstrings utilizando un script de Python personalizado que introspecciona el paquete `trustgraph.api`. + +### Requisitos previos + +El paquete `trustgraph` debe ser importable. Si estás trabajando en un entorno de desarrollo: + +```bash +cd trustgraph-base +pip install -e . +``` + +### Generación de documentación + +Desde el directorio `docs`: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +Esto genera un único archivo Markdown con documentación de la API completa, mostrando: +- Guía de instalación y inicio rápido +- Declaraciones de importación para cada clase/tipo +- Docstrings completos con ejemplos +- Tabla de contenidos organizada por categoría + +### Estilo de documentación + +Todos los docstrings siguen el formato de Google: +- Resumen breve de una línea +- Descripción detallada +- Sección Args con descripciones de parámetros +- Sección Returns +- Sección Raises (cuando corresponda) +- Bloques de código de ejemplo con resaltado de sintaxis adecuado + +La documentación generada muestra la API pública exactamente como los usuarios la importan desde `trustgraph.api`, sin exponer la estructura interna del módulo. diff --git a/docs/README.api-docs.he.md b/docs/README.api-docs.he.md new file mode 100644 index 00000000..be612d83 --- /dev/null +++ b/docs/README.api-docs.he.md @@ -0,0 +1,53 @@ +--- +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. + +## תיעוד REST ו-WebSocket API + +- `specs/build-docs.sh` - יוצר את תיעוד ה-REST וה-WebSocket מהמפרטים של OpenAPI ו-AsyncAPI. + +## תיעוד API בפייתון + +תיעוד ה-API בפייתון נוצר מתוך מחרוזות תיאור (docstrings) באמצעות סקריפט פייתון מותאם, אשר סוקר את החבילה `trustgraph.api`. + +### תנאים מוקדמים + +חבילת `trustgraph` חייבת להיות ניתנת לייבוא. אם אתם עובדים בסביבת פיתוח: + +```bash +cd trustgraph-base +pip install -e . +``` + +### יצירת תיעוד + +מתוך תיקיית התיעוד: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +זה יוצר קובץ Markdown אחד עם תיעוד API מלא, המציג: +- מדריך התקנה והתחלה מהירה +- הצהרות ייבוא עבור כל מחלקה/סוג +- מחרוזות תיאור מלאות עם דוגמאות +- תוכן עזר מאורגן לפי קטגוריות + +### סגנון התיעוד + +כל מחרוזות התיאור עוקבות אחר פורמט Google: +- סיכום קצר בשורה אחת +- תיאור מפורט +- סעיף "Args" עם תיאורי פרמטרים +- סעיף "Returns" +- סעיף "Raises" (במידת הצורך) +- בלוקי קוד לדוגמה עם הדגשת תחביר מתאימה + +התיעוד שנוצר מציג את ה-API הציבורי בדיוק כפי שהמשתמשים מייבאים אותו מ-`trustgraph.api`, מבלי לחשוף את המבנה הפנימי של המודול. diff --git a/docs/README.api-docs.hi.md b/docs/README.api-docs.hi.md new file mode 100644 index 00000000..74ef9faa --- /dev/null +++ b/docs/README.api-docs.hi.md @@ -0,0 +1,61 @@ +--- +layout: default +title: "स्वचालित रूप से दस्तावेज़ उत्पन्न करना" +parent: "Hindi (Beta)" +--- + +**महत्वपूर्ण निर्देश:** + +- सभी Markdown फॉर्मेटिंग, हेडर, लिंक और HTML टैग को बरकरार रखें। +- बैक टिक (` `) या कोड ब्लॉक के अंदर के कोड का अनुवाद न करें। +- केवल अनुवादित पाठ प्रस्तुत करें, बिना किसी प्रारंभिक या स्पष्टीकरण के। + +अनुवाद करने के लिए पाठ: + +# स्वचालित रूप से दस्तावेज़ उत्पन्न करना + +> **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. + +## REST और WebSocket API दस्तावेज़ + +- `specs/build-docs.sh` - OpenAPI और AsyncAPI विनिर्देशों से REST और WebSocket दस्तावेज़ बनाता है। + +## पायथन API दस्तावेज़ + +पायथन API दस्तावेज़, `trustgraph.api` पैकेज का विश्लेषण करके एक कस्टम पायथन स्क्रिप्ट का उपयोग करके docstrings से उत्पन्न होते हैं। + +### पूर्व आवश्यकताएँ + +trustgraph पैकेज आयात करने योग्य होना चाहिए। यदि आप एक विकास वातावरण में काम कर रहे हैं, तो: + +```bash +cd trustgraph-base +pip install -e . +``` + +### दस्तावेज़ उत्पन्न करना + +दस्तावेज़ निर्देशिका से: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +यह एक एकल Markdown फ़ाइल उत्पन्न करता है जिसमें संपूर्ण API दस्तावेज़ शामिल है, जिसमें निम्नलिखित शामिल हैं: +- स्थापना और त्वरित शुरुआत गाइड +- प्रत्येक वर्ग/प्रकार के लिए आयात कथन +- पूर्ण docstrings के साथ उदाहरण +- श्रेणियों द्वारा व्यवस्थित सामग्री तालिका + +### दस्तावेज़ शैली + +सभी docstrings Google-शैली का पालन करते हैं: +- संक्षिप्त एक-पंक्ति सारांश +- विस्तृत विवरण +- पैरामीटर विवरण के साथ Args अनुभाग +- रिटर्न अनुभाग +- प्रासंगिक होने पर Raises अनुभाग +- उचित सिंटैक्स हाइलाइटिंग के साथ उदाहरण कोड ब्लॉक + +उत्पन्न दस्तावेज़ सार्वजनिक API को ठीक उसी तरह दिखाता है जैसे उपयोगकर्ता इसे `trustgraph.api` से आयात करते हैं, आंतरिक मॉड्यूल संरचना को उजागर किए बिना। diff --git a/docs/README.api-docs.md b/docs/README.api-docs.md index 8f7fecb8..06f4e2f0 100644 --- a/docs/README.api-docs.md +++ b/docs/README.api-docs.md @@ -1,3 +1,8 @@ +--- +layout: default +title: "Auto-generating docs" +nav_order: 2 +--- # Auto-generating docs @@ -45,4 +50,3 @@ All docstrings follow Google-style format: - Example code blocks with proper syntax highlighting The generated documentation shows the public API exactly as users import it from `trustgraph.api`, without exposing internal module structure. - diff --git a/docs/README.api-docs.pt.md b/docs/README.api-docs.pt.md new file mode 100644 index 00000000..250d7eb6 --- /dev/null +++ b/docs/README.api-docs.pt.md @@ -0,0 +1,54 @@ +--- +layout: default +title: "Geração automática de documentação" +parent: "Portuguese (Beta)" +--- + +# Geração automática de documentação + +> **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. + +## Documentação da API REST e WebSocket + +`specs/build-docs.sh` - Constrói a documentação REST e WebSocket a partir das + especificações OpenAPI e AsyncAPI. + +## Documentação da API Python + +A documentação da API Python é gerada a partir de docstrings usando um script Python personalizado que inspeciona o pacote `trustgraph.api`. + +### Pré-requisitos + +O pacote trustgraph deve ser importável. Se você estiver trabalhando em um ambiente de desenvolvimento: + +```bash +cd trustgraph-base +pip install -e . +``` + +### Gerando Documentação + +A partir do diretório de documentação: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +Isso gera um único arquivo Markdown com documentação completa da API, mostrando: +Instruções de instalação e guia de início rápido +Declarações de importação para cada classe/tipo +Documentação completa com exemplos +Sumário organizado por categoria + +### Estilo da Documentação + +Todas as documentações seguem o formato do Google: +Resumo breve de uma linha +Descrição detalhada +Seção "Args" com descrições dos parâmetros +Seção "Returns" +Seção "Raises" (quando aplicável) +Blocos de código de exemplo com realce de sintaxe adequado + +A documentação gerada mostra a API pública exatamente como os usuários a importam de `trustgraph.api`, sem expor a estrutura interna do módulo. diff --git a/docs/README.api-docs.ru.md b/docs/README.api-docs.ru.md new file mode 100644 index 00000000..b15f961c --- /dev/null +++ b/docs/README.api-docs.ru.md @@ -0,0 +1,53 @@ +--- +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. + +## Документация REST и WebSocket API + +- `specs/build-docs.sh` - Создает документацию для REST и WebSocket API на основе спецификаций OpenAPI и AsyncAPI. + +## Документация Python API + +Документация Python API генерируется из docstrings с использованием пользовательского скрипта Python, который анализирует пакет `trustgraph.api`. + +### Требования + +Пакет `trustgraph` должен быть импортируемым. Если вы работаете в среде разработки: + +```bash +cd trustgraph-base +pip install -e . +``` + +### Генерация документации + +Из каталога `docs`: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +Это создает один файл Markdown с полной документацией API, в котором показаны: +- Инструкции по установке и быстрому запуску +- Заявления импорта для каждого класса/типа +- Полные docstrings с примерами +- Содержание, организованное по категориям + +### Стиль документации + +Все docstrings следуют формату Google-style: +- Краткое однострочное описание +- Подробное описание +- Раздел "Args" с описаниями параметров +- Раздел "Returns" +- Раздел "Raises" (при необходимости) +- Блоки с примерами кода с правильной подсветкой синтаксиса + +Сгенерированная документация отображает публичный API точно так, как его импортируют из `trustgraph.api`, не раскрывая внутреннюю структуру модуля. diff --git a/docs/README.api-docs.sw.md b/docs/README.api-docs.sw.md new file mode 100644 index 00000000..b05af7d1 --- /dev/null +++ b/docs/README.api-docs.sw.md @@ -0,0 +1,62 @@ +--- +layout: default +title: "Kuunda hati moja kwa moja" +parent: "Swahili (Beta)" +--- + +**MAELEZI MUHIMU:** + +- Hifadhi KILA muundo wa Markdown, vichwa, viungo, na alama za HTML. +- EISI tafsiri code ndani ya ` ` au katika mistari ya code. +- Toa KAMA, tu maandishi iliyotumwa bila maelezo au maelekezo. + +Maandishi ya kutafsiri: + +# Kuunda hati moja kwa moja + +> **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. + +## Ufafanuzi wa API za REST na WebSocket + +- `specs/build-docs.sh` - Inaunda hati za REST na WebSocket kutoka kwenye + maelezo za OpenAPI na AsyncAPI. + +## Ufafanuzi wa API ya Python + +Ufafanuzi wa API ya Python unaoandaliwa kutoka kwa maelezo (docstrings) kwa kutumia skripti ya Python inayotumia, ambayo inaangalia pakiti `trustgraph.api`. + +### Vigezo + +Pakiti ya trustgraph lazima iweze kuagizwa. Ikiwa unatumia mazingira ya utengenezaji: + +```bash +cd trustgraph-base +pip install -e . +``` + +### Kuunda hati + +Kutoka kwenye orodha ya hati: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +Hii inaunda faili moja ya markdown yenye hati kamili ya API, inayoeleza: +- Mwongozo wa usanidi na wa kuanza +- Maelezo za kuagiza kwa kila sinema/aina +- Maelezo kamili (docstrings) na mifano +- Orodha ya maudhui iliyopangwa kwa kategoria + +### Mtindo wa hati + +Maelezo yote (docstrings) yanatumia mtindo wa Google: +- Muhtasari wa mstari moja +- Maelezo kamili +- Kitengo cha "Args" na maelezo ya thamani +- Kitengo cha "Returns" +- Kitengo cha "Raises" (kama inatumika) +- Mistari ya code na umbo sahihi + +Hati iliyoundwa inaonyesha API iliyo na umbo, kama watumiaji wanavyoagiza kutoka kwa `trustgraph.api`, bila kuonyesha muundo wa moduli. diff --git a/docs/README.api-docs.tr.md b/docs/README.api-docs.tr.md new file mode 100644 index 00000000..444ddb3d --- /dev/null +++ b/docs/README.api-docs.tr.md @@ -0,0 +1,54 @@ +--- +layout: default +title: "Otomatik olarak dokümantasyon oluşturma" +parent: "Turkish (Beta)" +--- + +# Otomatik olarak dokümantasyon oluşturma + +> **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. + +## REST ve WebSocket API Dokümantasyonu + +`specs/build-docs.sh` - REST ve websocket dokümantasyonunu OpenAPI ve AsyncAPI özelliklerinden oluşturur. + +## Python API Dokümantasyonu + + +Python API dokümantasyonu, `trustgraph.api` paketini inceleyen özel bir Python betiği kullanılarak, dokümantasyon dizelerinden (docstrings) oluşturulur. + +### Ön Koşullar + +trustgraph paketi içe aktarılabilir olmalıdır. Geliştirme ortamında çalışıyorsanız: + +```bash +cd trustgraph-base +pip install -e . +``` + +### Belgeler Oluşturma + +"docs" dizininden: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +Bu, eksiksiz API dokümantasyonunu içeren tek bir Markdown dosyası oluşturur ve şunları gösterir: +Kurulum ve hızlı başlangıç kılavuzu +Her sınıf/tip için içe aktarma ifadeleri +Örneklerle birlikte tam dokümanlar +Kategoriye göre düzenlenmiş içindekiler tablosu + +### Dokümantasyon Stili + +Tüm dokümanlar, Google stili biçimini izler: +Kısa, tek satırlık özet +Ayrıntılı açıklama +Parametre açıklamalarıyla birlikte "Args" bölümü +"Returns" bölümü +"Raises" bölümü (uygulanabilir olduğunda) +Doğru sözdizimi vurgulamasıyla birlikte örnek kod blokları + +Oluşturulan dokümantasyon, kullanıcıların `trustgraph.api`'dan içe aktardığı şekilde, tam olarak kamu API'sini gösterir ve dahili modül yapısını ortaya çıkarmaz. diff --git a/docs/README.api-docs.zh-cn.md b/docs/README.api-docs.zh-cn.md new file mode 100644 index 00000000..b28f2555 --- /dev/null +++ b/docs/README.api-docs.zh-cn.md @@ -0,0 +1,53 @@ +--- +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. + +## REST 和 WebSocket API 文档 + +- `specs/build-docs.sh` - 从 OpenAPI 和 AsyncAPI 规范生成 REST 和 WebSocket 文档。 + +## Python API 文档 + +Python API 文档是从 docstrings 使用自定义 Python 脚本生成的,该脚本会反向解析 `trustgraph.api` 包。 + +### 预先条件 + +`trustgraph` 包必须可导入。 如果您在开发环境中工作,请执行以下操作: + +```bash +cd trustgraph-base +pip install -e . +``` + +### 生成文档 + +从 `docs` 目录: + +```bash +cd docs +python3 generate-api-docs.py > python-api.md +``` + +这将生成一个包含完整 API 文档的单个 Markdown 文件,其中包含: +- 安装和快速入门指南 +- 每个类/类型的导入语句 +- 完整的 docstrings(包含示例) +- 按类别组织的目录 + +### 文档风格 + +所有 docstrings 均遵循 Google 风格: +- 简短的一行摘要 +- 详细描述 +- 参数描述的 Args 部分 +- Returns 部分 +- Raises 部分(如果适用) +- 带有正确语法高亮的代码块(示例) + +生成的文档显示了用户从 `trustgraph.api` 中导入的公共 API,而无需暴露内部模块结构。 diff --git a/docs/README.ar.md b/docs/README.ar.md new file mode 100644 index 00000000..4025bd30 --- /dev/null +++ b/docs/README.ar.md @@ -0,0 +1,35 @@ +--- +layout: default +title: "وثائق TrustGraph" +parent: "Arabic (Beta)" +--- + +**تعليمات مهمة:** + +- الحفاظ على جميع تنسيقات Markdown، والعناوين، والروابط، ووسوم HTML. +- لا تترجم أي كود داخل علامات التنصيص المزدوجة أو كتل الكود. +- قم بإخراج النص المترجم فقط، بدون أي مقدمات أو تفسيرات. + +النص المراد ترجمته: +# وثائق TrustGraph + +> **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! للحصول على وثائق شاملة، يرجى زيارة: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +يتضمن الموقع الرئيسي الوثائق: + +- **[نظرة عامة](https://docs.trustgraph.ai/overview)** - مقدمة لمفاهيم وهيكل TrustGraph +- **[دليل المستخدم](https://docs.trustgraph.ai/guides)** - دروس تعليمية خطوة بخطوة وإرشادات +- **[التثبيت](https://docs.trustgraph.ai/deployment)** - خيارات التثبيت والإعداد +- **[مرجع](https://docs.trustgraph.ai/reference)** - مواصفات API ووثائق سطر الأوامر + +## البدء + +**هل أنت جديد في TrustGraph؟** ابدأ بـ [نظرة عامة](https://docs.trustgraph.ai/overview) لفهم النظام. + +**هل أنت مستعد للتثبيت؟** تحقق من [دليل التثبيت](https://docs.trustgraph.ai/deployment). + +**هل تقوم بدمج الكود؟** راجع [مرجع API](https://docs.trustgraph.ai/reference) للحصول على وثائق REST و WebSocket و SDK. diff --git a/docs/README.es.md b/docs/README.es.md new file mode 100644 index 00000000..cad181b6 --- /dev/null +++ b/docs/README.es.md @@ -0,0 +1,28 @@ +--- +layout: default +title: "Documentación de TrustGraph" +parent: "Spanish (Beta)" +--- + +# Documentación de TrustGraph + +> **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. + +¡Bienvenido a TrustGraph! Para una documentación completa, por favor visite: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +El sitio principal de documentación incluye: + +- **[Descripción general](https://docs.trustgraph.ai/overview)** - Introducción a los conceptos y la arquitectura de TrustGraph +- **[Guías](https://docs.trustgraph.ai/guides)** - Tutoriales paso a paso y guías de cómo hacerlo +- **[Implementación](https://docs.trustgraph.ai/deployment)** - Opciones de implementación y configuración +- **[Referencia](https://docs.trustgraph.ai/reference)** - Especificaciones de la API y documentación de la línea de comandos + +## Primeros Pasos + +**¿Eres nuevo en TrustGraph?** Comienza con la [Descripción general](https://docs.trustgraph.ai/overview) para comprender el sistema. + +**¿Listo para implementar?** Consulta la [Guía de implementación](https://docs.trustgraph.ai/deployment). + +**¿Integrando con código?** Consulta la [Referencia de la API](https://docs.trustgraph.ai/reference) para la documentación de REST, WebSocket y SDK. diff --git a/docs/README.he.md b/docs/README.he.md new file mode 100644 index 00000000..62ecf440 --- /dev/null +++ b/docs/README.he.md @@ -0,0 +1,34 @@ +--- +layout: default +title: "TrustGraph Documentation" +parent: "Hebrew (Beta)" +--- + +**הוראות חשובות:** +- שמרו על כל הפורמט של Markdown, כותרות, קישורים ותגי HTML. +- אל תתרגמו קוד בתוך סימוני backticks או בלוקי קוד. +- צרו רק את הטקסט המתורגם, ללא הקדמה או הסברים. + +טקסט לתרגום: +# TrustGraph Documentation + +> **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! עבור תיעוד מקיף, אנא בקרו ב: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +אתר התיעוד הראשי כולל: + +- **[סקירה](https://docs.trustgraph.ai/overview)** - מבוא להגדרות ואדריכלות של TrustGraph +- **[מדריכים](https://docs.trustgraph.ai/guides)** - מדריכים וורסטיים +- **[התקנה](https://docs.trustgraph.ai/deployment)** - אפשרויות התקנה והגדרות +- **[מדריך](https://docs.trustgraph.ai/reference)** - ספקציפיות API ותיעוד CLI + +## התחלה + +**חדש ב-TrustGraph?** התחילו עם [הסקירה](https://docs.trustgraph.ai/overview) כדי להבין את המערכת. + +**מוכנים להתקין?** בדקו את [מדריך ההתקנה](https://docs.trustgraph.ai/deployment). + +**שילוב עם קוד?** עיינו ב-[מדריך ה-API](https://docs.trustgraph.ai/reference) עבור תיעוד REST, WebSocket ו-SDK. diff --git a/docs/README.hi.md b/docs/README.hi.md new file mode 100644 index 00000000..e9e5b69f --- /dev/null +++ b/docs/README.hi.md @@ -0,0 +1,35 @@ +--- +layout: default +title: "ट्रस्टग्राफ दस्तावेज़" +parent: "Hindi (Beta)" +--- + +**महत्वपूर्ण निर्देश:** + +- सभी Markdown स्वरूपण, हेडर, लिंक और HTML टैग को बरकरार रखें। +- बैकटिक या कोड ब्लॉक के अंदर मौजूद कोड का अनुवाद न करें। +- केवल अनुवादित टेक्स्ट प्रदान करें, बिना किसी संवाद पूर्व-परिभाषा या स्पष्टीकरण के। + +अनुवाद के लिए पाठ: +# ट्रस्टग्राफ दस्तावेज़ + +> **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. + +ट्रस्टग्राफ में आपका स्वागत है! व्यापक दस्तावेज़ के लिए, कृपया इस पर जाएँ: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +मुख्य दस्तावेज़ साइट में शामिल हैं: + +- **[अवलोकन](https://docs.trustgraph.ai/overview)** - ट्रस्टग्राफ अवधारणाओं और वास्तुकला का परिचय +- **[निर्देश](https://docs.trustgraph.ai/guides)** - चरण-दर-चरण ट्यूटोरियल और कैसे करें गाइड +- **[परिनियोजन](https://docs.trustgraph.ai/deployment)** - परिनियोजन विकल्प और कॉन्फ़िगरेशन +- **[संदर्भ](https://docs.trustgraph.ai/reference)** - एपीआई विनिर्देश और कमांड-लाइन दस्तावेज़ + +## शुरुआत कैसे करें + +**क्या आप ट्रस्टग्राफ के नए हैं?** सिस्टम को समझने के लिए [अवलोकन](https://docs.trustgraph.ai/overview) से शुरुआत करें। + +**क्या आप परिनियोजित करने के लिए तैयार हैं?** [परिनियोजन गाइड](https://docs.trustgraph.ai/deployment) देखें। + +**कोड के साथ एकीकृत करना?** REST, WebSocket और SDK दस्तावेज़ के लिए [एपीआई संदर्भ](https://docs.trustgraph.ai/reference) देखें। diff --git a/docs/README.md b/docs/README.md index 35d70763..4c22c9b5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Home" +nav_order: 1 +--- + # TrustGraph Documentation Welcome to TrustGraph! For comprehensive documentation, please visit: @@ -18,4 +24,3 @@ The main documentation site includes: **Ready to deploy?** Check out the [Deployment Guide](https://docs.trustgraph.ai/deployment). **Integrating with code?** See the [API Reference](https://docs.trustgraph.ai/reference) for REST, WebSocket, and SDK documentation. - diff --git a/docs/README.pt.md b/docs/README.pt.md new file mode 100644 index 00000000..747bfa70 --- /dev/null +++ b/docs/README.pt.md @@ -0,0 +1,28 @@ +--- +layout: default +title: "Documentação do TrustGraph" +parent: "Portuguese (Beta)" +--- + +# Documentação do TrustGraph + +> **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. + +Bem-vindo ao TrustGraph! Para documentação completa, visite: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +O site de documentação principal inclui: + +**[Visão Geral](https://docs.trustgraph.ai/overview)** - Introdução aos conceitos e arquitetura do TrustGraph +**[Guias](https://docs.trustgraph.ai/guides)** - Tutoriais passo a passo e guias de como fazer +**[Implantação](https://docs.trustgraph.ai/deployment)** - Opções de implantação e configuração +**[Referência](https://docs.trustgraph.ai/reference)** - Especificações da API e documentação da CLI + +## Começando + +**Novo no TrustGraph?** Comece com a [Visão Geral](https://docs.trustgraph.ai/overview) para entender o sistema. + +**Pronto para implantar?** Consulte o [Guia de Implantação](https://docs.trustgraph.ai/deployment). + +**Integrando com código?** Consulte a [Referência da API](https://docs.trustgraph.ai/reference) para documentação REST, WebSocket e SDK. diff --git a/docs/README.ru.md b/docs/README.ru.md new file mode 100644 index 00000000..b7ea6c3c --- /dev/null +++ b/docs/README.ru.md @@ -0,0 +1,28 @@ +--- +layout: default +title: "Документация TrustGraph" +parent: "Russian (Beta)" +--- + +# Документация TrustGraph + +> **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! Для получения исчерпывающей документации, пожалуйста, посетите: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +Основной сайт документации включает: + +- **[Обзор](https://docs.trustgraph.ai/overview)** - Введение в концепции и архитектуру TrustGraph +- **[Руководства](https://docs.trustgraph.ai/guides)** - Пошаговые руководства и инструкции +- **[Развертывание](https://docs.trustgraph.ai/deployment)** - Варианты развертывания и конфигурация +- **[Справочник](https://docs.trustgraph.ai/reference)** - Спецификации API и документация CLI + +## Начало работы + +**Вы новичок в TrustGraph?** Начните с [Обзора](https://docs.trustgraph.ai/overview), чтобы понять систему. + +**Готовы к развертыванию?** Обратитесь к [Руководству по развертыванию](https://docs.trustgraph.ai/deployment). + +**Интеграция с кодом?** Посмотрите [Справочник по API](https://docs.trustgraph.ai/reference) для документации REST, WebSocket и SDK. diff --git a/docs/README.sw.md b/docs/README.sw.md new file mode 100644 index 00000000..910577c4 --- /dev/null +++ b/docs/README.sw.md @@ -0,0 +1,28 @@ +--- +layout: default +title: "Miongozo ya TrustGraph" +parent: "Swahili (Beta)" +--- + +# Miongozo ya TrustGraph + +> **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. + +Karibu kwenye TrustGraph! Kwa miongozo kamili, tafadhali tembelea: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +Tovuti kuu ya miongozo inajumuisha: + +**[Mawasilisho](https://docs.trustgraph.ai/overview)** - Utangulizi wa dhana na muundo wa TrustGraph +**[Mwongozo](https://docs.trustgraph.ai/guides)** - Mafunzo ya hatua kwa hatua na mwongozo wa jinsi ya +**[Ufungaji](https://docs.trustgraph.ai/deployment)** - Chaguo za ufungaji na usanidi +**[Marejeleo](https://docs.trustgraph.ai/reference)** - Vipimo vya API na miongozo ya CLI + +## Kuanza + +**Je, wewe ni mpya katika TrustGraph?** Anza na [Mawasilisho](https://docs.trustgraph.ai/overview) ili kuelewa mfumo. + +**Uko tayari kufunga?** Angalia [Mwongozo wa Ufungaji](https://docs.trustgraph.ai/deployment). + +**Je, unataka kuunganisha na programu?** Angalia [Marejeleo ya API](https://docs.trustgraph.ai/reference) kwa miongozo ya REST, WebSocket, na SDK. diff --git a/docs/README.tr.md b/docs/README.tr.md new file mode 100644 index 00000000..1b582d6e --- /dev/null +++ b/docs/README.tr.md @@ -0,0 +1,28 @@ +--- +layout: default +title: "TrustGraph Belgeleri" +parent: "Turkish (Beta)" +--- + +# TrustGraph Belgeleri + +> **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'a hoş geldiniz! Kapsamlı belgeler için lütfen şu adresi ziyaret edin: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +Ana belge sitesi şunları içerir: + +**[Genel Bakış](https://docs.trustgraph.ai/overview)** - TrustGraph kavramlarına ve mimarisine giriş +**[Kılavuzlar](https://docs.trustgraph.ai/guides)** - Adım adım eğitimler ve nasıl yapılır kılavuzları +**[Dağıtım](https://docs.trustgraph.ai/deployment)** - Dağıtım seçenekleri ve yapılandırma +**[Referans](https://docs.trustgraph.ai/reference)** - API özellikleri ve CLI belgeleri + +## Başlangıç + +**TrustGraph'e yeni mi geldiniz?** Sistemi anlamak için [Genel Bakış](https://docs.trustgraph.ai/overview) bölümüne bakın. + +**Dağıtıma hazır mısınız?** [Dağıtım Kılavuzu](https://docs.trustgraph.ai/deployment) bölümüne göz atın. + +**Koduyla entegre mi olmak istiyorsunuz?** REST, WebSocket ve SDK belgeleri için [API Referansı](https://docs.trustgraph.ai/reference) bölümüne bakın. diff --git a/docs/README.zh-cn.md b/docs/README.zh-cn.md new file mode 100644 index 00000000..91e31a25 --- /dev/null +++ b/docs/README.zh-cn.md @@ -0,0 +1,28 @@ +--- +layout: default +title: "TrustGraph 文档" +parent: "Chinese (Beta)" +--- + +# TrustGraph 文档 + +> **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!为了获得全面的文档,请访问: + +## 📖 [https://docs.trustgraph.ai](https://docs.trustgraph.ai) + +主文档站点包含: + +- **[概述](https://docs.trustgraph.ai/overview)** - 介绍 TrustGraph 的概念和架构 +- **[指南](https://docs.trustgraph.ai/guides)** - 逐步教程和操作指南 +- **[部署](https://docs.trustgraph.ai/deployment)** - 部署选项和配置 +- **[参考](https://docs.trustgraph.ai/reference)** - API 规范和 CLI 文档 + +## 快速入门 + +**您是 TrustGraph 的新手吗?** 请从 [概述](https://docs.trustgraph.ai/overview) 开始,了解系统。 + +**准备部署了吗?** 请查看 [部署指南](https://docs.trustgraph.ai/deployment)。 + +**要与代码集成?** 请查看 [API 参考](https://docs.trustgraph.ai/reference),其中包含 REST、WebSocket 和 SDK 文档。 diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.ar.md b/docs/api-gateway-changes-v1.8-to-v2.1.ar.md new file mode 100644 index 00000000..d7d87ef3 --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.ar.md @@ -0,0 +1,108 @@ +--- +layout: default +title: "تغييرات في واجهة برمجة التطبيقات: v1.8 إلى v2.1" +parent: "Arabic (Beta)" +--- + +# تغييرات في واجهة برمجة التطبيقات: v1.8 إلى v2.1 + +> **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. + +## ملخص + +حصلت واجهة برمجة التطبيقات على مُسِير خدمات WebSocket الجديدة لإرسال استعلامات "التضمين"، ونقطة نهاية REST الجديدة للتدفق لمحتوى المستند، وتم إجراء تغيير كبير في تنسيق الكود من "القيمة" إلى "الحد". تم إعادة تسمية خدمة "الكائنات" إلى "الصفوف". + +--- + +## مُسِير خدمات WebSocket الجديدة + +هذه هي خدمات طلب/استجابة جديدة متاحة من خلال مُضاعِف WebSocket في `/api/v1/socket` (محدد على مستوى التدفق): + +| مفتاح الخدمة | الوصف | +|---|---| +| `document-embeddings` | استعلام عن أجزاء المستند بناءً على التشابه النصي. يستخدم الطلب/الاستجابة مخططات `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse`. | +| `row-embeddings` | استعلام عن صفوف البيانات المنظمة بناءً على التشابه النصي في الحقول المفهرسة. يستخدم الطلب/الاستجابة مخططات `RowEmbeddingsRequest`/`RowEmbeddingsResponse`. | + +تضاف إلى مُسِير "graph-embeddings" الحالي (الذي كان موجودًا بالفعل في v1.8 ولكنه قد تم تحديثه). + +### قائمة كاملة بمُسِير خدمات تدفق WebSocket (v2.1) + +خدمات طلب/استجابة (عبر `/api/v1/flow/{flow}/service/{kind}` أو مُضاعِف WebSocket): + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## نقطة نهاية REST الجديدة + +| الطريقة | المسار | الوصف | +|---|---|---| +| `GET` | `/api/v1/document-stream` | تدفق محتوى المستند من المكتبة كبيانات خام. معلمات الاستعلام: `user` (مطلوب)، `document-id` (مطلوب)، `chunk-size` (اختياري، القيمة الافتراضية 1 ميجابايت). يُرجع محتوى المستند بتنسيق نقل متقطع، مع فك ترميزه من base64 داخليًا. | + +--- + +## إعادة تسمية الخدمة: "objects" إلى "rows" + +| v1.8 | v2.1 | الملاحظات | +|---|---|---| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | تغير المخطط من `ObjectsQueryRequest`/`ObjectsQueryResponse` إلى `RowsQueryRequest`/`RowsQueryResponse`. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | مُسِير الاستيراد للبيانات المنظمة. | + +تغير مفتاح خدمة WebSocket من `"objects"` إلى `"rows"`, وتغير مفتاح مُسِير الاستيراد بشكل مشابه من `"objects"` إلى `"rows"`. + +--- + +## تغيير تنسيق الكود: Value إلى Term + +تم إعادة كتابة طبقة التسلسل (serialize.py) لاستخدام النوع الجديد "Term" بدلاً من النوع القديم "Value". + +### التنسيق القديم (v1.8 — Value) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: القيمة (سلسلة) +- `e`: علامة منطقية تشير إلى ما إذا كانت القيمة عبارة عن URI + +### التنسيق الجديد (v2.1 — Term) + +IRIs: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +Literals: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +Quoted triples (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: مُحدد النوع — `"i"` (URI)، `"l"` (حرف)، `"r"` (ثلاثي مُقتبس)، `"b"` (عقدة فارغة) +- الآن يتم تفويض التسلسل إلى `TermTranslator` و `TripleTranslator` من `trustgraph.messaging.translators.primitives` + +### تغييرات التسلسل الأخرى + +| الحقل | v1.8 | v2.1 | +|---|---|---| +| البيانات الوصفية | `metadata.metadata` (البريد الفرعي) | `metadata.root` (قيمة بسيطة) | +| كيان تضمينات الرسم البياني | `entity.vectors` (مجموع) | `entity.vector` (مفرد) | +| جزء تضمين المستند | `chunk.vectors` + `chunk.chunk` (النص) | `chunk.vector` + `chunk.chunk_id` (مرجع المعرّف) | + +--- + +## تغييرات في الكسر + +- **تنسيق الكود Value إلى Term**: يجب على جميع العملاء الذين يرسلون/يستقبلون ثلاثيات أو سياقات الكائنات أو التضمينات من خلال واجهة برمجة التطبيقات تحديثها إلى التنسيق الجديد Term. +- **إعادة تسمية "objects" إلى "rows"**: تغير مفتاح خدمة WebSocket ومفتاح الاستيراد. +- **تغيير حقل البيانات الوصفية**: تم استبدال `metadata.metadata` (مجموعة فرعية مُسلسلة) بـ `metadata.root` (قيمة بسيطة). +- **تغييرات حقول التضمين**: أصبح `vectors` (مجموع) هو `vector` (مفرد)، وتستخدم تضمينات المستند الآن `chunk_id` بدلاً من النص المضمن. +- **نقطة نهاية جديدة `/api/v1/document-stream`**: إضافية، وليست مُفسرة. diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.es.md b/docs/api-gateway-changes-v1.8-to-v2.1.es.md new file mode 100644 index 00000000..7128333f --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.es.md @@ -0,0 +1,108 @@ +--- +layout: default +title: "Cambios en el API Gateway: v1.8 a v2.1" +parent: "Spanish (Beta)" +--- + +# Cambios en el API Gateway: v1.8 a v2.1 + +> **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 + +El gateway de API ha obtenido nuevos despachadores de servicios WebSocket para consultas de incrustaciones, un nuevo punto final REST para el streaming de contenido de documentos, y ha experimentado un cambio significativo en el formato del cableado de `Value` a `Term`. El "servicio de objetos" se ha renombrado a "filas". + +--- + +## Nuevos Despachadores de Servicios WebSocket + +Estos son nuevos servicios de solicitud/respuesta disponibles a través del multiplexador WebSocket en `/api/v1/socket` (con ámbito de flujo): + +| Clave de servicio | Descripción | +|-------------|-------------| +| `document-embeddings` | Consulta fragmentos de documentos por similitud de texto. La solicitud/respuesta utiliza los esquemas `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse`. | +| `row-embeddings` | Consulta filas de datos estructurados por similitud de texto en campos indexados. La solicitud/respuesta utiliza los esquemas `RowEmbeddingsRequest`/`RowEmbeddingsResponse`. | + +Estos se unen al existente `graph-embeddings` dispatcher (que ya estaba presente en v1.8 pero puede que se haya actualizado). + +### Lista completa de despachadores de servicios de flujo WebSocket (v2.1) + +Servicios de solicitud/respuesta (a través de `/api/v1/flow/{flow}/service/{kind}` o multiplexador WebSocket): + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## Nuevo Punto Final REST + +| Método | Ruta | Descripción | +|--------|------|-------------| +| `GET` | `/api/v1/document-stream` | Transmite contenido de documentos desde la biblioteca como bytes brutos. Parámetros de consulta: `user` (obligatorio), `document-id` (obligatorio), `chunk-size` (opcional, predeterminado 1MB). Devuelve el contenido del documento con el codificado de transferencia en fragmentos, decodificado internamente en base64. | + +--- + +## Servicio Renombrado: "objects" a "rows" + +| v1.8 | v2.1 | Notas | +|------|------|-------| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | El esquema cambiado de `ObjectsQueryRequest`/`ObjectsQueryResponse` a `RowsQueryRequest`/`RowsQueryResponse`. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | Despachador de importación para datos estructurados. | + +La clave del servicio WebSocket cambió de `"objects"` a `"rows"`, y la clave del despachador de importación cambió de `"objects"` a `"rows"`. + +--- + +## Cambio de Formato del Cable: Value a Term + +La capa de serialización (`serialize.py`) se ha reescrito para utilizar el nuevo tipo `Term` en lugar del antiguo tipo `Value`. + +### Formato antiguo (v1.8 — `Value`) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: el valor (cadena) +- `e`: indicador booleano que indica si el valor es un URI + +### Formato nuevo (v2.1 — `Term`) + +IRIs: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +Literales: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +Triples con comillas (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: discriminador de tipo — `"i"` (URI), `"l"` (literal), `"r"` (triple con comillas), `"b"` (nodo en blanco) +- La serialización ahora delega a `TermTranslator` y `TripleTranslator` de `trustgraph.messaging.translators.primitives` + +### Otros cambios en la serialización + +| Campo | v1.8 | v2.1 | +|-------|------|------| +| Metadatos | `metadata.metadata` (subgrafo) | `metadata.root` (valor simple) | +| Entidad de incrustación | `entity.vectors` (plural) | `entity.vector` (singular) | +| Fragmento de incrustación de documento | `chunk.vectors` + `chunk.chunk` (texto) | `chunk.vector` + `chunk.chunk_id` (ID de referencia) | + +--- + +## Cambios que Rompen + +- **Cambio de formato del cable `Value` a `Term`**: Todos los clientes que envían/reciben triples, incrustaciones o contextos de entidad a través del gateway deben actualizar al nuevo formato Term. +- **Cambio de nombre de `objects` a `rows`**: Se ha modificado la clave del servicio WebSocket y la clave del despachador de importación. +- **Cambio del campo de metadatos**: `metadata.metadata` (un subgrafo serializado) reemplazado por `metadata.root` (un valor simple). +- **Cambios en los campos de incrustación**: `vectors` (plural) se convirtió en `vector` (singular); las incrustaciones de documentos ahora hacen referencia a `chunk_id` en lugar de a `chunk` de texto. +- **Nuevo punto final `/api/v1/document-stream`**: Aditivo, no rompe. diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.he.md b/docs/api-gateway-changes-v1.8-to-v2.1.he.md new file mode 100644 index 00000000..0f0f93d3 --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.he.md @@ -0,0 +1,106 @@ +--- +layout: default +title: "שינויים ב-API Gateway: v1.8 ל-v2.1" +parent: "Hebrew (Beta)" +--- + +# שינויים ב-API Gateway: v1.8 ל-v2.1 + +> **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. + +## תקציר + +ה-API Gateway קיבל ספקי שירות WebSocket חדשים עבור שאילתות של "embeddings", סוף שירות REST חדש להעברת תוכן מסמך, וכן שינוי משמעותי בפורמט של קוד: מ-"Value" ל-"Term". השירות "objects" שונה לשם "rows". + +--- + +## ספקי שירות WebSocket חדשים + +אלו הם שירותי בקשה/תגובה חדשים הזמינים דרך המולטיפלקסר של WebSocket בכתובת `/api/v1/socket` (הקשור למערכת זרימה): + +| מפתח שירות | תיאור | +|---|---| +| `document-embeddings` | מבקש חלקים של מסמך על סמך דמיון טקסט. הבקשה/תגובה משתמשים בתבניות `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse`. | +| `row-embeddings` | מבקש שורות של נתונים מובנים על סמך דמיון טקסט בשדות המצביעים. הבקשה/תגובה משתמשות בתבניות `RowEmbeddingsRequest`/`RowEmbeddingsResponse`. | + +הם מצטרפים למספק הקיים `graph-embeddings` (שהיה קיים כבר ב-v1.8 אך ייתכן ששונה), + +### רשימה מלאה של ספקי שירות זרימה של WebSocket (v2.1) + +שירותי בקשה/תגובה (דרך `/api/v1/flow/{flow}/service/{kind}` או מולטיפלקסר WebSocket): + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## סוף שירות REST חדש + +| שיטה | נתיב | תיאור | +|---|---|---| +| `GET` | `/api/v1/document-stream` | מעביר תוכן מסמך מהספרייה כביטים גולמיים. פרמטרי שאילתה: `user` (חובה), `document-id` (חובה), `chunk-size` (אופציונלי, ברירת מחדל 1MB). מחזיר את תוכן המסמך בתבנית העברת ביטים, לאחר פעולת Base64 פנימית. | + +--- + +## שינוי שם שירות: "objects" ל-"rows" + +| v1.8 | v2.1 | הערות | +|---|---|---| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | התבנית שונתה מ-`ObjectsQueryRequest`/`ObjectsQueryResponse` ל-`RowsQueryRequest`/`RowsQueryResponse`. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | ספק ייבוא לנתונים מובנים. | + +מפתח השירות של WebSocket שונה מ-"objects" ל-"rows", וממילא מפתח ספק הייבוא שונה מ-"objects" ל-"rows". + +--- + +## שינוי פורמט קוד: Value ל-Term + +שכבת הסריאליזציה (`serialize.py`) שונתה כדי להשתמש בסוג ה-"Term" החדש במקום בסוג ה-"Value" הישן. + +### פורמט ישן (v1.8 — Value) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: הערך (מחרוזת) +- `e`: דגל בוליאני המציין אם הערך הוא URI + +### פורמט חדש (v2.1 — Term) + +- IRI: +```json +{"t": "i", "i": "http://example.org/entity"} +``` +- רשימות: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` +- טריפלים מוערים (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: מחלקת סוג — `"i"` (IRI), `"l"` (רשימה), `"r"` (טריפל מוער), `"b"` (צומת ריק) +- הסריאליזציה כעת מקפלת ל-`TermTranslator` ו-`TripleTranslator` מ-`trustgraph.messaging.translators.primitives + +### שינויי סריאליזציה אחרים + +| שדה | v1.8 | v2.1 | +|---|---|---| +| Metadata | `metadata.metadata` (סופר-גרף) | `metadata.root` (ערך פשוט) | +| סוגי embeddings | `entity.vectors` (רשימה) | `entity.vector` (יחיד) | +| חלקים של embeddings | `chunk.vectors` + `chunk.chunk` (טקסט) | `chunk.vector` + `chunk.chunk_id` (מזהה התייחסות) | + +--- + +## שינויים משמעותיים + +- **פורמט קוד Value ל-Term:** כל לקוחות המשדרים/מקבלים טריפלים, embeddings או הקשרים של ישויות דרך ה-gateway צריכים לעדכן לפורמט ה-Term החדש. +- **שינוי שם של "objects" ל-"rows":** שינוי מפתח שירות של WebSocket ומפתח ייבוא. +- **שינוי שדה Metadata:** `metadata.metadata` (גרף סריאלי) הוחלף ב-`metadata.root` (ערך פשוט). +- **שינויים בשדות Embeddings:** `vectors` (רשימה) הפך ל-`vector` (יחיד); embeddings של מסמכים כעת מתייחסים ל-`chunk_id` במקום הטקסט של ה-`chunk` +- **סוף שירות חדש `/api/v1/document-stream`**: נוסף, לא משבש. diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.hi.md b/docs/api-gateway-changes-v1.8-to-v2.1.hi.md new file mode 100644 index 00000000..9f8d747d --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.hi.md @@ -0,0 +1,108 @@ +--- +layout: default +title: "Api Gateway Changes V1.8 To V2.1.Hi" +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. + +## API गेटवे में बदलाव: v1.8 से v2.1 + +## सारांश + +API गेटवे में एम्बेडिंग प्रश्नों के लिए नए WebSocket सेवा डिस्पैचर, दस्तावेज़ सामग्री के लिए एक नया REST स्ट्रीमिंग एंडपॉइंट, और `Value` से `Term` में एक महत्वपूर्ण वायर प्रारूप परिवर्तन शामिल है। "ऑब्जेक्ट्स" सेवा को "रो" के रूप में पुनः नाम दिया गया। + +--- + +## नए WebSocket सेवा डिस्पैचर + +ये `/api/v1/socket` पर उपलब्ध नए अनुरोध/प्रतिक्रिया सेवाएँ हैं (फ्लो-स्कोप): + +| सेवा कुंजी | विवरण | +|---|---| +| `document-embeddings` | टेक्स्ट समानता के आधार पर दस्तावेज़ टुकड़ों के लिए क्वेरी करता है। अनुरोध/प्रतिक्रिया `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse` स्कीमा का उपयोग करते हैं। | +| `row-embeddings` | इंडेक्स किए गए फ़ील्ड में टेक्स्ट समानता के आधार पर संरचित डेटा पंक्तियों के लिए क्वेरी करता है। अनुरोध/प्रतिक्रिया `RowEmbeddingsRequest`/`RowEmbeddingsResponse` स्कीमा का उपयोग करते हैं। | + +ये मौजूदा `graph-embeddings` डिस्पैचर (जो पहले से ही v1.8 में मौजूद है, लेकिन अपडेट किया जा सकता है) के साथ जुड़ते हैं। + +### WebSocket फ़्लो सेवा डिस्पैचर की पूरी सूची (v2.1) + +अनुरोध/प्रतिक्रिया सेवाएँ (`/api/v1/flow/{flow}/service/{kind}` या WebSocket मक्स) के माध्यम से: + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## नया REST एंडपॉइंट + +| विधि | पथ | विवरण | +|---|---|---| +| `GET` | `/api/v1/document-stream` | लाइब्रेरी से मूल बाइट के रूप में दस्तावेज़ सामग्री स्ट्रीम करता है। क्वेरी पैरामीटर: `user` (आवश्यक), `document-id` (आवश्यक), `chunk-size` (वैकल्पिक, डिफ़ॉल्ट 1MB)। आंतरिक रूप से base64 से डिकोड करके दस्तावेज़ सामग्री को chunked transfer encoding में लौटाता है। | + +--- + +## पुनः नामकरण की गई सेवा: "objects" से "rows" + +| v1.8 | v2.1 | नोट्स | +|---|---|---| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | `ObjectsQueryRequest`/`ObjectsQueryResponse` से `RowsQueryRequest`/`RowsQueryResponse` स्कीमा में बदलाव। | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | संरचित डेटा के लिए आयात डिस्पैचर। | + +WebSocket सेवा कुंजी `"objects"` से `"rows"` में बदल गई है, और आयात डिस्पैचर कुंजी `"objects"` से `"rows"` में बदल गई है। + +--- + +## वायर प्रारूप में बदलाव: Value से Term + +`serialize.py` में serialization लेयर को नए `Term` प्रकार का उपयोग करने के लिए फिर से लिखा गया है, बजाय पुराने `Value` प्रकार का। + +### पुराना प्रारूप (v1.8 — `Value`) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: मान (स्ट्रिंग) +- `e`: एक बूलियन ध्वज जो दर्शाता है कि मान एक URI है या नहीं + +### नया प्रारूप (v2.1 — `Term`) + +IRI: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +प्रत्यक्ष: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +कोटेड ट्रिपल (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: प्रकार डिस्‍क्रिमिनेटर — `"i"` (IRI), `"l"` (प्रत्यक्ष), `"r"` (कोटेड ट्रिपल), `"b"` (ब्लैंक नोड) +- serialization अब `trustgraph.messaging.translators.primitives` से `TermTranslator` और `TripleTranslator` को सौंपता है। + +### अन्य serialization में बदलाव + +| फ़ील्ड | v1.8 | v2.1 | +|---|---|---| +| मेटाडेटा | `metadata.metadata` (उप-ग्राफ) | `metadata.root` (सरल मान) | +| ग्राफ एम्बेडिंग इकाई | `entity.vectors` (बहु) | `entity.vector` (एकल) | +| दस्तावेज़ एम्बेडिंग टुकड़ा | `chunk.vectors` + `chunk.chunk` (टेक्स्ट) | `chunk.vector` + `chunk.chunk_id` (आईडी संदर्भ) | + +--- + +## महत्वपूर्ण बदलाव + +- **`Value` से `Term` वायर प्रारूप**: गेटवे के माध्यम से ट्रिपल, एम्बेडिंग या इकाई संदर्भ भेजने/प्राप्त करने वाले सभी क्लाइंट को नए Term प्रारूप के साथ अपडेट करना होगा। +- **`objects` से `rows` का नामकरण**: WebSocket सेवा कुंजी और आयात कुंजी में बदलाव। +- **मेटाडेटा फ़ील्ड में बदलाव**: `metadata.metadata` (एक serialized उप-ग्राफ) को `metadata.root` (एक सरल मान) से बदला गया। +- **एम्बेडिंग फ़ील्ड में बदलाव**: `vectors` (बहु) को `vector` (एकल) से बदला गया; दस्तावेज़ एम्बेडिंग अब `chunk_id` को संदर्भित करती हैं, बजाय inline `chunk` टेक्स्ट के। +- **नया `/api/v1/document-stream` एंडपॉइंट**: यह एक अतिरिक्त परिवर्तन है, जो पहले से ही मौजूद है। diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.pt.md b/docs/api-gateway-changes-v1.8-to-v2.1.pt.md new file mode 100644 index 00000000..a4488bad --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.pt.md @@ -0,0 +1,116 @@ +--- +layout: default +title: "Alterações no API Gateway: da versão 1.8 para a versão 2.1" +parent: "Portuguese (Beta)" +--- + +# Alterações no API Gateway: da versão 1.8 para a versão 2.1 + +> **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. + +## Resumo + +O gateway de API ganhou novos distribuidores de serviços WebSocket para consultas de incorporações +e um novo endpoint REST para streaming de conteúdo de documentos, e passou por +uma mudança significativa no formato de comunicação, de `Value` para `Term`. O serviço "objects" +foi renomeado para "rows". + +-- + +## Novos Distribuidores de Serviços WebSocket + +Estes são novos serviços de solicitação/resposta disponíveis através do +multiplexador WebSocket em `/api/v1/socket` (com escopo de fluxo): + +| Chave do Serviço | Descrição | +|-------------|-------------| +| `document-embeddings` | Consulta de trechos de documentos por similaridade de texto. Solicitação/resposta usa os esquemas `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse`. | +| `row-embeddings` | Consulta de linhas de dados estruturados por similaridade de texto em campos indexados. Solicitação/resposta usa os esquemas `RowEmbeddingsRequest`/`RowEmbeddingsResponse`. | + +Estes se juntam ao distribuidor existente `graph-embeddings` (que já +estava presente na versão 1.8, mas pode ter sido atualizado). + +### Lista completa de distribuidores de serviços de fluxo WebSocket (versão 2.1) + +Serviços de solicitação/resposta (via `/api/v1/flow/{flow}/service/{kind}` ou +multiplexador WebSocket): + +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +`row-embeddings` + +-- + +## Novo Endpoint REST + +| Método | Caminho | Descrição | +|--------|------|-------------| +| `GET` | `/api/v1/document-stream` | Transmite o conteúdo do documento da biblioteca como bytes brutos. Parâmetros de consulta: `user` (obrigatório), `document-id` (obrigatório), `chunk-size` (opcional, padrão 1MB). Retorna o conteúdo do documento em codificação de transferência em blocos, decodificado de base64 internamente. | + +-- + +## Serviço Renomeado: "objects" para "rows" + +| v1.8 | v2.1 | Notas | +|------|------|-------| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | Esquema alterado de `ObjectsQueryRequest`/`ObjectsQueryResponse` para `RowsQueryRequest`/`RowsQueryResponse`. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | Distribuidor de importação para dados estruturados. | + +A chave do serviço WebSocket foi alterada de `"objects"` para `"rows"`, e a +chave do distribuidor de importação foi alterada de `"objects"` para `"rows"`. + +-- + +## Mudança no Formato de Comunicação: Valor para Termo + +A camada de serialização (`serialize.py`) foi reescrita para usar o novo tipo `Term` +em vez do tipo antigo `Value`. + +### Formato antigo (v1.8 — `Value`) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +`v`: o valor (string) +`e`: flag booleano que indica se o valor é um URI + +### Novo formato (v2.1 — `Term`) + +IRIs: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +Literais: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +Triplas citadas (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +`t`: tipo de discriminador — `"i"` (IRI), `"l"` (literal), `"r"` (tripla entre aspas), `"b"` (nó vazio) +A serialização agora delega para `TermTranslator` e `TripleTranslator` a partir de `trustgraph.messaging.translators.primitives` + +### Outras alterações de serialização + +| Campo | v1.8 | v2.1 | +|-------|------|------| +| Metadados | `metadata.metadata` (subgrafo) | `metadata.root` (valor simples) | +| Incorporação de entidade | `entity.vectors` (plural) | `entity.vector` (singular) | +| Incorporação de fragmento de documento | `chunk.vectors` + `chunk.chunk` (texto) | `chunk.vector` + `chunk.chunk_id` (referência de ID) | + +-- + +## Alterações Incompatíveis + +**Formato de fio de `Value` para `Term`**: Todos os clientes que enviam ou recebem triplas, incorporações ou contextos de entidade através do gateway devem atualizar para o novo formato de Termo. +**Renomeação de `objects` para `rows`**: A chave do serviço WebSocket e a chave de importação foram alteradas. +**Alteração do campo de metadados**: `metadata.metadata` (um subgrafo serializado) foi substituído por `metadata.root` (um valor simples). +**Alterações nos campos de incorporação**: `vectors` (plural) se tornou `vector` (singular); as incorporações de documento agora fazem referência a `chunk_id` em vez de texto `chunk` inline. +**Novo endpoint `/api/v1/document-stream`**: Aditivo, não quebra a compatibilidade. diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.ru.md b/docs/api-gateway-changes-v1.8-to-v2.1.ru.md new file mode 100644 index 00000000..2d6c6875 --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.ru.md @@ -0,0 +1,108 @@ +--- +layout: default +title: "Изменения в API Gateway: v1.8 до v2.1" +parent: "Russian (Beta)" +--- + +# Изменения в API Gateway: v1.8 до v2.1 + +> **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. + +## Обзор + +API Gateway получил новые диспетчеры WebSocket для запросов на основе встраивания, новый REST-endpoint для потоковой передачи содержимого документов, и претерпел значительные изменения в формате представления данных, перейдя с `Value` на `Term`. Сервис "objects" был переименован в "rows". + +--- + +## Новые диспетчеры WebSocket + +Это новые сервисы запросов/ответов, доступные через WebSocket-мультиплексор по адресу `/api/v1/socket` (с фокусом на flow): + +| Ключ сервиса | Описание | +|---|---| +| `document-embeddings` | Запросы на фрагменты документов по текстовому сходству. Используются схемы `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse`. | +| `row-embeddings` | Запросы на структурированные данные по текстовому сходству по индексированным полям. Используются схемы `RowEmbeddingsRequest`/`RowEmbeddingsResponse`. | + +Эти диспетчеры работают вместе с существующим диспетчером `graph-embeddings` (который уже был в v1.8, но мог быть обновлен). + +### Полный список диспетчеров WebSocket (v2.1) + +Сервисы запросов/ответов (через `/api/v1/flow/{flow}/service/{kind}` или WebSocket-мультиплексор): + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## Новый REST Endpoint + +| Метод | Путь | Описание | +|---|---|---| +| `GET` | `/api/v1/document-stream` | Потоковая передача содержимого документов из библиотеки в виде сырых байтов. Параметры запроса: `user` (обязательно), `document-id` (обязательно), `chunk-size` (необязательно, значение по умолчанию 1MB). Возвращает содержимое документа в коде transfer encoding, который декодируется из base64 внутри. | + +--- + +## Переименованный сервис: "objects" в "rows" + +| v1.8 | v2.1 | Примечания | +|---|---|---| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | Схема изменена с `ObjectsQueryRequest`/`ObjectsQueryResponse` на `RowsQueryRequest`/`RowsQueryResponse`. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | Импорт для структурированных данных. | + +Ключ WebSocket-сервиса изменился с `"objects"` на `"rows"`, а ключ импорт-диспатчера аналогично — с `"objects"` на `"rows"`. + +--- + +## Изменение формата представления данных: Value на Term + +Слой сериализации (`serialize.py`) был переписан для использования нового типа `Term` вместо старого типа `Value`. + +### Старый формат (v1.8 — `Value`) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: значение (строка) +- `e`: булевский флаг, указывающий, является ли значение URI + +### Новый формат (v2.1 — `Term`) + +URI: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +Литералы: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +Тройки, указанные в кавычках (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: дискриминатор типа — `"i"` (URI), `"l"` (литерал), `"r"` (тройка), `"b"` (blank node) +- Сериализация теперь делегируется `TermTranslator` и `TripleTranslator` из `trustgraph.messaging.translators.primitives` + +### Другие изменения в сериализации + +| Поле | v1.8 | v2.1 | +|---|---|---| +| Metadata | `metadata.metadata` (подграфа) | `metadata.root` (простое значение) | +| Graph embeddings entity | `entity.vectors` (множественное) | `entity.vector` (одиночное) | +| Document embeddings chunk | `chunk.vectors` + `chunk.chunk` (текст) | `chunk.vector` + `chunk.chunk_id` (ссылка на ID) | + +--- + +## Изменения, требующие внимания + +- **Формат представления данных Value в Term**: Все клиенты, отправляющие/получающие тройки, встраивания или контексты сущностей через gateway, должны обновиться до нового формата Term. +- **Переименование объектов в rows**: Изменился ключ WebSocket-сервиса и ключ импорт-диспатчера. +- **Изменение поля metadata**: `metadata.metadata` (сериализованная подграфа) заменено на `metadata.root` (простое значение). +- **Изменения полей embeddings**: `vectors` (множественное) стало `vector` (одиночное); теперь встраивания документов ссылаются на `chunk_id` вместо inline `chunk`. +- **Новый endpoint `/api/v1/document-stream`**: Дополнительный, не является "breaking". diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.sw.md b/docs/api-gateway-changes-v1.8-to-v2.1.sw.md new file mode 100644 index 00000000..cfb56112 --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.sw.md @@ -0,0 +1,114 @@ +--- +layout: default +title: "Mabadiliko ya API Gateway: v1.8 hadi v2.1" +parent: "Swahili (Beta)" +--- + +**MAELEZO MAZOE:** +- Weka ВИWAMU za muundo, vichungi, viungo na alama za HTML. +- Usitafsiri nakala ndani ya alama za ``` au katika blok za nakala. +- Toa NA TUJUI tu, bila utangulizi au maelezo. + +Nakala inayohitajika: +# Mabadiliko ya API Gateway: v1.8 hadi v2.1 + +> **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 + +API gateway imepata mpya wa huduma za WebSocket kwa ajili ya majabuzi, kiungo cha mpya cha REST kwa maudhui, na imepitia mabadiliko muhimu katika muundo wa data kutoka `Value` hadi `Term`. Huduma "objects" imebadilishwa na "rows". + +--- + +## Wengine Wepya wa Huduma za WebSocket + +Hizi ni huduma mpya za ombi/majibu zinazopatikana kupitia multiplexer ya WebSocket katika `/api/v1/socket` (na msingi wa "flow"): + +| Key ya Huduma | Maelezo | +|-------------|-------------| +| `document-embeddings` | Inatafuta sehemu za hati kwa utofauti wa maandishi. Ombi/majibu hutumia miundo `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse`. | +| `row-embeddings` | Inatafuta data iliyoandaliwa kwa utofauti wa maandishi kwenye majina iliyosawazwa. Ombi/majibu hutumia miundo `RowEmbeddingsRequest`/`RowEmbeddingsResponse`. | + +Hizi zinaunganishwa na `graph-embeddings` iliyopo tayari katika v1.8, lakini inaweza kuwa imeboreshwa. + +### Orodha kamili ya huduma za WebSocket (v2.1) + +Huduma za ombi/majibu (kupitia `/api/v1/flow/{flow}/service/{kind}` au WebSocket mux): + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## Kiungo cha REST cha Mpya + +| Njia | Path | Maelezo | +|--------|------|-------------| +| `GET` | `/api/v1/document-stream` | Inatoa maudhui ya hati kutoka kwenye makala kama data ya msingi. Parametari za ombi: `user` (lazima), `document-id` (lazima), `chunk-size` (bora, chaguo, 1MB). Inarudisha maudhui ya hati kama data iliyobadilishwa, na inatumia teknolojia ya "chunked transfer encoding" ya base64. | + +--- + +## Huduma iliyobadilishwa: "objects" hadi "rows" + +| v1.8 | v2.1 | Maelezo | +|------|------|-------| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | Muundo umebadilishwa kutoka `ObjectsQueryRequest`/`ObjectsQueryResponse` hadi `RowsQueryRequest`/`RowsQueryResponse`. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | Huduma ya import kwa data iliyoandaliwa. | + +Key ya huduma ya WebSocket imebadilishwa kutoka "objects" hadi "rows", na key ya import pia imebadilishwa. + +--- + +## Mabadiliko ya Muundo: Value hadi Term + +Sura ya usimamizaji (`serialize.py`) imeandikwa upya ili kutumia aina mpya ya "Term" badala ya aina ya "Value" iliyokuwa. + +### Sura ya awali (v1.8 — Value) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: thamani (string) +- `e`: bendera ya booleani inayoeleza kama thamani ni URI + +### Sura mpya (v2.1 — Term) + +IRIs: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +Literals: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +Triple za mlangano (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: makazi - `"i"` (URI), `"l"` (thamini), `"r"` (triple), `"b"` (blank node) +- Usimamizi sasa unaendeleza kwa `TermTranslator` na `TripleTranslator` kutoka `trustgraph.messaging.translators.primitives` + +### Mabadiliko mengine ya usimamizaji + +| Kipa | v1.8 | v2.1 | +|-------|------|------| +| Metadata | `metadata.metadata` (subgraph) | `metadata.root` (thamini rahisi) | +| Graph embeddings entity | `entity.vectors` (pl) | `entity.vector` (singular) | +| Document embeddings chunk | `chunk.vectors` + `chunk.chunk` (text) | `chunk.vector` + `chunk.chunk_id` (ID reference) | + +--- + +## Mabadiliko Muhimu + +- **Muundo Value hadi Term**: Wote wa wateja wanaotumia nakala, ujumizi, au maudhui wanapaswa kubadilishwa kwa muundo mpya wa Term. +- **"objects" hadi "rows"**: Key ya huduma na key ya import zimebadilishwa. +- **Mabadiliko ya key ya Metadata**: `metadata.metadata` (subgraph iliyosimamizwa) imebadilishwa na `metadata.root` (thamini rahisi). +- **Mabadiliko ya key ya Embeddings**: `vectors` (plural) imebadilishwa na `vector` (singular); ujumizi wa hati sasa inaangalia `chunk_id` badala ya "chunk" ya msingi. +- **Kiungo cha mpya `/api/v1/document-stream`**: Haiathiri. diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.tr.md b/docs/api-gateway-changes-v1.8-to-v2.1.tr.md new file mode 100644 index 00000000..5f646fa7 --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.tr.md @@ -0,0 +1,116 @@ +--- +layout: default +title: "API Ağ Geçidi Değişiklikleri: v1.8'den v2.1'e" +parent: "Turkish (Beta)" +--- + +# API Ağ Geçidi Değişiklikleri: v1.8'den v2.1'e + +> **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. + +## Özet + +API ağ geçidi, gömülü sorgular için yeni WebSocket hizmet yönlendiricileri, belge içeriği için yeni bir REST akış uç noktası kazandı ve ⟦CODE_0⟧'dan ⟦CODE_1⟧'e önemli bir veri formatı değişikliğine uğradı. "objects" hizmeti "rows" olarak yeniden adlandırıldı. +sorguları, belge içeriği için yeni bir REST akış uç noktası ve aşağıdaki değişiklikleri içerdi: +önemli bir tel format değişikliği, `Value`'dan `Term`'e geçiş. "Nesneler" + + +-- + +## Yeni WebSocket Hizmet Yönlendiricileri + +Bunlar, WebSocket üzerinden sunulan yeni istek/yanıt servisleridir. +`/api/v1/socket` adresindeki çoklayıcı (akış kapsamlı): + +| Servis Anahtarı | Açıklama | +|-------------|-------------| +| `document-embeddings` | Metin benzerliği ile belge parçalarını sorgular. İstek/yanıt, `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse` şemalarını kullanır. | +| `row-embeddings` | İndekslenmiş alanlarda metin benzerliği ile yapılandırılmış veri satırlarını sorgular. İstek/yanıt, `RowEmbeddingsRequest`/`RowEmbeddingsResponse` şemalarını kullanır. | + +Bunlar, mevcut `graph-embeddings` dağıtım aracına (v1.8'de zaten +bulunan ancak güncellenmiş olabilecek) eklenir. + +### WebSocket akış hizmeti dağıtım araçlarının tam listesi (v2.1) + +İstek/yanıt hizmetleri (`/api/v1/flow/{flow}/service/{kind}` veya +WebSocket çoklayıcısı aracılığıyla): + +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +`row-embeddings` + +-- + +## Yeni REST Uç Noktası + +| Yöntem | Yol | Açıklama | +|--------|------|-------------| +| `GET` | `/api/v1/document-stream` | Kütüphaneden belge içeriğini ham baytlar olarak aktarır. Sorgu parametreleri: `user` (gerekli), `document-id` (gerekli), `chunk-size` (isteğe bağlı, varsayılan 1MB). Belge içeriğini, dahili olarak base64'ten çözülmüş olarak, parçalı aktarım kodlamasıyla döndürür. | + +-- + +## Yeniden Adlandırılan Hizmet: "objects" -> "rows" + +| v1.8 | v2.1 | Notlar | +|------|------|-------| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | Şema, `ObjectsQueryRequest`/`ObjectsQueryResponse`'den `RowsQueryRequest`/`RowsQueryResponse`'ye dönüştürüldü. | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | Yapılandırılmış veri için import yöneticisi. | + +WebSocket hizmet anahtarı `"objects"`'dan `"rows"`'e değişti ve +import yöneticisi anahtarı da benzer şekilde `"objects"`'dan `"rows"`'e değişti. + +-- + +## Kablo Formatındaki Değişiklik: Değerden Terime + +Seri hale getirme katmanı (`serialize.py`), yeni `Term`'i kullanmak üzere yeniden yazıldı. +eski `Value` türünün yerine bu türü kullanın. + +### Eski format (v1.8 — `Value`) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +`v`: değer (string) +`e`: değerin bir URI olup olmadığını gösteren boolean işaretleyici + +### Yeni format (v2.1 — `Term`) + +IRIs: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +Sabitler: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +Tırnak içinde belirtilen üçlüler (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +`t`: tür belirleyici — `"i"` (IRI), `"l"` (literal), `"r"` (tırnak içinde belirtilmiş üçlü), `"b"` (boş düğüm) +Serileştirme artık `trustgraph.messaging.translators.primitives`'den `TermTranslator` ve `TripleTranslator`'e devrediliyor. + +### Diğer serileştirme değişiklikleri + +| Alan | v1.8 | v2.1 | +|-------|------|------| +| Meta veri | `metadata.metadata` (alt grafik) | `metadata.root` (basit değer) | +| Grafik gömme varlığı | `entity.vectors` (çoğul) | `entity.vector` (tekil) | +| Belge gömme parçası | `chunk.vectors` + `chunk.chunk` (metin) | `chunk.vector` + `chunk.chunk_id` (ID referansı) | + +-- + +## Uyumsuz Değişiklikler + +**`Value`'dan `Term`'e kablo formatı**: Ağ geçidi üzerinden üçlü, gömme veya varlık bağlamı gönderen/alan tüm istemcilerin, yeni Terim formatına güncellenmesi gerekir. +**`objects`'dan `rows`'e yeniden adlandırma**: WebSocket hizmet anahtarı ve içe aktarma anahtarı değiştirildi. +**Meta veri alanı değişikliği**: `metadata.metadata` (serileştirilmiş bir alt grafik), `metadata.root` (basit bir değer) ile değiştirildi. +**Gömme alanı değişiklikleri**: `vectors` (çoğul), `vector` (tekil) haline geldi; belge gömmeleri artık iç içe `chunk` metni yerine `chunk_id`'yi referans alıyor. +**Yeni `/api/v1/document-stream` uç noktası**: Uyumsuz değil, eklemeli. diff --git a/docs/api-gateway-changes-v1.8-to-v2.1.zh-cn.md b/docs/api-gateway-changes-v1.8-to-v2.1.zh-cn.md new file mode 100644 index 00000000..447df209 --- /dev/null +++ b/docs/api-gateway-changes-v1.8-to-v2.1.zh-cn.md @@ -0,0 +1,108 @@ +--- +layout: default +title: "API 网关变更:v1.8 到 v2.1" +parent: "Chinese (Beta)" +--- + +# API 网关变更:v1.8 到 v2.1 + +> **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. + +## 摘要 + +API 网关新增了用于嵌入查询的 WebSocket 服务分发器,新增了 REST 串流端点,用于文档内容,并进行了重要的 Wire 格式变化,从 `Value` 变为 `Term`。 "对象" 服务已被重命名为 "行"。 + +--- + +## 新的 WebSocket 服务分发器 + +这些是可通过 WebSocket 多路复用器 `/api/v1/socket` (范围限定) 访问的新请求/响应服务: + +| 服务键 | 描述 | +|---|---| +| `document-embeddings` | 通过文本相似性查询文档块。 请求/响应使用 `DocumentEmbeddingsRequest`/`DocumentEmbeddingsResponse` 模式。 | +| `row-embeddings` | 通过在索引字段上对结构化数据行进行文本相似性查询。 请求/响应使用 `RowEmbeddingsRequest`/`RowEmbeddingsResponse` 模式。 | + +这些与现有的 `graph-embeddings` 分发器 (已存在于 v1.8 但可能已被更新) 关联。 + +### WebSocket 流程服务分发器的完整列表 (v2.1) + +请求/响应服务 (通过 `/api/v1/flow/{flow}/service/{kind}` 或 WebSocket 多路复用器): + +- `agent`, `text-completion`, `prompt`, `mcp-tool` +- `graph-rag`, `document-rag` +- `embeddings`, `graph-embeddings`, `document-embeddings` +- `triples`, `rows`, `nlp-query`, `structured-query`, `structured-diag` +- `row-embeddings` + +--- + +## 新的 REST 端点 + +| 方法 | 路径 | 描述 | +|---|---|---| +| `GET` | `/api/v1/document-stream` | 从库中流式传输文档内容为原始字节。 查询参数:`user` (必需), `document-id` (必需), `chunk-size` (可选, 默认 1MB)。 返回文档内容,通过内部进行 base64 解码,并以块传输编码传输。 | + +--- + +## 重命名服务: "objects" 为 "rows" + +| v1.8 | v2.1 | 备注 | +|---|---|---| +| `objects_query.py` / `ObjectsQueryRequestor` | `rows_query.py` / `RowsQueryRequestor` | 模式从 `ObjectsQueryRequest`/`ObjectsQueryResponse` 变为 `RowsQueryRequest`/`RowsQueryResponse`。 | +| `objects_import.py` / `ObjectsImport` | `rows_import.py` / `RowsImport` | 结构化数据导入分发器。 | + +WebSocket 服务键已从 `"objects"` 变为 `"rows"`,以及导入分发器的键也从 `"objects"` 变为 `"rows"`。 + +--- + +## Wire 格式变化: Value 为 Term + +`serialize.py` (序列化层) 已重写为使用新的 `Term` 类型,而不是旧的 `Value` 类型。 + +### 旧格式 (v1.8 - `Value`) + +```json +{"v": "http://example.org/entity", "e": true} +``` + +- `v`: 值 (字符串) +- `e`: 布尔标志,指示值是否为 URI + +### 新格式 (v2.1 - `Term`) + +IRI: +```json +{"t": "i", "i": "http://example.org/entity"} +``` + +字面量: +```json +{"t": "l", "v": "some text", "d": "datatype-uri", "l": "en"} +``` + +带引号的三元组 (RDF-star): +```json +{"t": "r", "r": {"s": {...}, "p": {...}, "o": {...}}} +``` + +- `t`: 类型区分值 — `"i"` (IRI), `"l"` (字面量), `"r"` (带引号的三元组), `"b"` (空节点) +- 序列化现在委托给 `trustgraph.messaging.translators.primitives` 中的 `TermTranslator` 和 `TripleTranslator` + +### 其他序列化更改 + +| 字段 | v1.8 | v2.1 | +|---|---|---| +| 元数据 | `metadata.metadata` (子图) | `metadata.root` (简单值) | +| 图嵌入实体 | `entity.vectors` (复数) | `entity.vector` (单数) | +| 文档嵌入块 | `chunk.vectors` + `chunk.chunk` (文本) | `chunk.vector` + `chunk.chunk_id` (ID 引用) | + +--- + +## 破坏性变更 + +- **Value 到 Term 的 Wire 格式**: 任何通过网关发送/接收三元组、嵌入或实体上下文的客户端都必须更新为新的 Term 格式。 +- **objects 到 rows 的重命名**: WebSocket 服务键和导入键已更改。 +- **元数据字段更改**: `metadata.metadata` (序列化的子图) 已被 `metadata.root` (简单值) 替换。 +- **嵌入字段更改**: `vectors` (复数) 变为 `vector` (单数);文档嵌入现在引用 `chunk_id` 而不是内联 `chunk` 文本。 +- **新的 `/api/v1/document-stream` 端点**: 添加的,非破坏性。 diff --git a/docs/cli-changes-v1.8-to-v2.1.ar.md b/docs/cli-changes-v1.8-to-v2.1.ar.md new file mode 100644 index 00000000..c9daba1f --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.ar.md @@ -0,0 +1,119 @@ +--- +layout: default +title: "تغييرات واجهة سطر الأوامر: من v1.8 إلى v2.1" +parent: "Arabic (Beta)" +--- + +# تغييرات واجهة سطر الأوامر: من v1.8 إلى v2.1 + +> **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-cli`)، مع التركيز على ثلاثة مجالات: +**القابلية للتفسير/الأصل،** **الوصول إلى التضمينات،** و **استعلامات الرسم البياني.** +تم إزالة أدوات قديمة، وتم تغيير اسم أداة واحدة، وحصلت العديد من الأدوات الموجودة على قدرات جديدة. + +--- + +## أدوات واجهة سطر الأوامر الجديدة + +### القابلية للتفسير والأصل + +| الأمر | الوصف | +|---|---| +| `tg-list-explain-traces` | يسرد جميع جلسات القابلية للتفسير (GraphRAG و Agent) في المجموعة، مع عرض معرفات الجلسة ونوعها ونص السؤال وتوقيتات الإصدار. | +| `tg-show-explain-trace` | يعرض مسار القابلية للتفسير الكامل لجلسة. لـ GraphRAG: مرحلة السؤال، والبحث/التنقيب، والتركيز، والتوليف. لـ Agent: مرحلة الجلسة، والتكرارات (فكر/عمل/ملاحظة)، والإجابة النهائية. يكتشف تلقائيًا نوع المسار. يدعم الخيارات `--show-provenance` لتتبع الحواف مرة أخرى إلى المستندات المصدر. | +| `tg-show-extraction-provenance` | بالنظر إلى معرف المستند، فإنه يتتبع سلسلة الأصل: المستند -> الصفحات -> القطع -> الحواف، باستخدام علاقات `prov:wasDerivedFrom`. يدعم الخيارات `--show-content` و `--max-content`. | + +### التضمينات + +| الأمر | الوصف | +|---|---| +| `tg-invoke-embeddings` | يحول النص إلى تضمين متجه عبر خدمة التضمينات. يقبل إدخالات نصية واحدة أو أكثر، ويعيد المتجهات كمصفوفات من الأرقام العشرية. | +| `tg-invoke-graph-embeddings` | يستعلم عن الكيانات في الرسم البياني باستخدام التضمينات النصية. يعيد الكيانات المطابقة مع درجات التشابه. | +| `tg-invoke-document-embeddings` | يستعلم عن قطع المستند باستخدام التضمينات النصية. يعيد معرّفات القطع المطابقة مع درجات التشابه. | +| `tg-invoke-row-embeddings` | يستعلم عن صفوف البيانات المهيكلة باستخدام التشابه النصي على الحقول الفهرسية. يعيد الصفوف المطابقة مع قيم الفهرس ودرجاتها. يتطلب `--schema-name` ويدعم `--index-name`. | + +### استعلام الرسم البياني + +| الأمر | الوصف | +|---|---| +| `tg-query-graph` | استعلام مخزن ثلاثي يعتمد على الأنماط. على عكس `tg-show-graph` (الذي يعرض كل شيء)، فإنه يسمح بالاستعلامات الانتقائية باستخدام أي مجموعة من الموضوع والصفة والكائن والرسم البياني. يكتشف تلقائيًا أنواع القيم: IRIs (`http://...`, `urn:...`, `<...>`)، ثلاثيات مُقتبسة (`<>`)، والمفردات. | +| `tg-get-document-content` | يسترجع محتوى المستند من المكتبة بمعرف المستند. يمكن إخراجها إلى ملف أو stdout، ويدعم كلًا من المحتوى النصي والمحتوى الثنائي. | + +--- + +## أدوات واجهة سطر الأوامر المحذوفة + +| الأمر | الملاحظات | +|---|---| +| `tg-load-pdf` | تم حذفه. يتم الآن التعامل مع تحميل المستند من خلال المكتبة/مسار المعالجة. | +| `tg-load-text` | تم حذفه. يتم الآن التعامل مع تحميل المستند من خلال المكتبة/مسار المعالجة. | + +--- + +## تغيير أسماء أدوات واجهة سطر الأوامر + +| الاسم القديم | الاسم الجديد | الملاحظات | +|---|---|---| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | يعكس تغيير التسمية من "الكائنات" إلى "الصفوف" للبيانات المهيكلة. | + +--- + +## تغييرات كبيرة في الأدوات الموجودة + +### `tg-invoke-graph-rag` + +- **دعم القابلية للتفسير:** يدعم الآن مسار قابلية تفسير مكون من 4 مراحل (السؤال، والبحث/التنقيب، والتركيز، والتوليف) مع عرض متكامل للأحداث المتعلقة بالأصل. +- **الاستمرارية:** يستخدم بث WebSocket لإخراج في الوقت الفعلي. +- **تتبع الأصل:** يمكن تتبع الحواف المحددة مرة أخرى إلى المستندات المصدر من خلال إعادة التشكيل و سلاسل `prov:wasDerivedFrom`. +- زادت من حوالي 30 سطرًا إلى 760 سطرًا لاستيعاب مسار القابلية للتفسير الكامل. + +### `tg-invoke-document-rag` + +- **دعم القابلية للتفسير:** أضاف وضع `question_explainable()` الذي يخرج استجابات RAG للمستند مع أحداث الأصل المتداخلة (مراحل السؤال، والبحث، والتنقيب، والتوليف). + +### `tg-invoke-agent` + +- **دعم القابلية للتفسير:** أضاف وضع `question_explainable()` الذي يعرض أحداث الأصل المتداخلة أثناء تنفيذ الوكيل (مراحل السؤال، والتحليل، والاستنتاج، و AgentThought، و AgentObservation، و AgentAnswer). +- يظهر الوضع التفصيلي سلاسل فكر/ملاحظة مع بادئات رموز تعبيرية. + +### `tg-show-graph` + +- **وضع الاستمرارية:** يستخدم الآن `triples_query_stream()` مع أحجام دفع قابلة للتكوين للحصول على النتيجة الأولى في أدنى وقت وتقليل الحمل الزائد للذاكرة. +- **دعم الرسم البياني المسمى:** خيار جديد `--graph`. يكتشف الرسوم البيانية المسماة: + - الرسم البياني الافتراضي (فارغ): حقائق المعرفة الأساسية. + - `urn:graph:source`: الأصل لاستخراج + - `urn:graph:retrieval`: استعلام في وقت التشغيل للقابلية للتفسير +- **عرض عمود الرسم البياني:** علامة جديدة `--show-graph` لعرض الرسم البياني المسماة لكل ثلاثي. +- **حدود قابلة للتكوين:** خيارات جديدة `--limit` و `--batch-size`. + +### `tg-graph-to-turtle` + +- **دعم RDF-star:** يتعامل الآن مع الثلاثيات المقتبسة (إعادة تشكيل RDF-star). +- **وضع الاستمرارية:** يستخدم الاستمرارية للتحقيق في وقت المعالجة في أدنى وقت. +- **معالجة تنسيق الكابل:** تم تحديثه لاستخدام تنسيق الكابل الجديد (`{"t": "i", "i": uri}` لـ IRIs، و `{"t": "l", "v": value}` للمفردات، و `{"t": "r", "r": {...}}` للاثلاثيات المقتبسة). +- **دعم الرسم البياني المسمى:** خيار جديد `--graph`. + +### `tg-set-tool` + +- **نوع أداة جديد:** `row-embeddings-query` للبحث الدلالي عن فهارس البيانات المهيكلة. +- **خيارات جديدة:** `--schema-name` و `--index-name` و `--limit` لتكوين أدوات استعلام تضمينات الصفوف. + +### `tg-show-tools` + +- يعرض نوع الأداة الجديد `row-embeddings-query` مع حقول `schema-name` و `index-name` و `limit`. + +### `tg-load-knowledge` + +- **إعداد التقارير عن التقدم:** الآن يحسب ويسجل عدد ثلاثيات وسياقات الكيانات التي تم تحميلها لكل ملف بشكل إجمالي. +- **تحديث تنسيق المصطلح:** تتضمن سياقات الكيانات الآن تنسيق المصطلح الجديد (`{"t": "i", "i": uri}`) بدلاً من تنسيق القيمة القديم (`{"v": entity, "e": True}`). + +--- + +## تغييرات مدمرة + +- **تغيير التسمية:** تم تغيير اسم مخطط `Value` إلى `Term` في جميع أنحاء النظام (PR #622). وهذا يؤثر على الأدوات التي تتفاعل مع مخزن الرسم البياني والتي تستخدم تنسيق الكابل الجديد. يستخدم التنسيق الجديد `{"t": "i", "i": uri}` لـ IRIs و `{"t": "l", "v": value}` للمفردات، بدلاً من التنسيق القديم `{"v": ..., "e": ...}`. +- **`tg-invoke-objects-query` تم تغيير الاسم** إلى `tg-invoke-rows-query`. +- تم حذف `tg-load-pdf` و `tg-load-text`. diff --git a/docs/cli-changes-v1.8-to-v2.1.es.md b/docs/cli-changes-v1.8-to-v2.1.es.md new file mode 100644 index 00000000..c9121a4e --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.es.md @@ -0,0 +1,120 @@ +--- +layout: default +title: "Cambios en la CLI: v1.8 a v2.1" +parent: "Spanish (Beta)" +--- + +# Cambios en la CLI: v1.8 a v2.1 + +> **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 + +La CLI (`trustgraph-cli`) tiene importantes adiciones centradas en tres temas: +**explicabilidad/origen**, **acceso a embeddings** y **consultas en el grafo**. +Se eliminaron dos herramientas heredadas, una se renombró y varias herramientas existentes +adquirieron nuevas capacidades. + +--- + +## Nuevas Herramientas CLI + +### Explicabilidad y Origen + +| Comando | Descripción | +|---------|-------------| +| `tg-list-explain-traces` | Lista todas las sesiones de explicabilidad (GraphRAG y Agent) en una colección, mostrando los IDs de sesión, tipo, texto de la pregunta y marcas de tiempo. | +| `tg-show-explain-trace` | Muestra la traza completa de explicabilidad para una sesión. Para GraphRAG: Etapas de Pregunta, Exploración, Enfoque, Síntesis. Para Agent: Etapas de Sesión, Iteraciones (pensamiento/acción/observación), Respuesta Final. Detecta automáticamente el tipo de traza. Soporta la opción `--show-provenance` para rastrear los bordes de vuelta a los documentos originales. | +| `tg-show-extraction-provenance` | Dados un ID de documento, recorre la cadena de origen: Documento -> Páginas -> Bloques -> Bordes, utilizando las relaciones `prov:wasDerivedFrom`. Soporta las opciones `--show-content` y `--max-content`. | + +### Embeddings + +| Comando | Descripción | +|---------|-------------| +| `tg-invoke-embeddings` | Convierte texto en un embedding vectorial a través del servicio de embeddings. Acepta uno o más entradas de texto, devuelve vectores como listas de flotantes. | +| `tg-invoke-graph-embeddings` | Consulta entidades del grafo por similitud de texto utilizando embeddings vectoriales. Devuelve las entidades coincidentes con puntuaciones de similitud. | +| `tg-invoke-document-embeddings` | Consulta fragmentos de documentos por similitud de texto utilizando embeddings vectoriales. Devuelve los IDs de fragmentos coincidentes con puntuaciones de similitud. | +| `tg-invoke-row-embeddings` | Consulta filas de datos estructurados por similitud de texto en campos indexados. Devuelve las filas coincidentes con valores de índice y puntuaciones. Requiere `--schema-name` y soporta `--index-name`. | + +### Consultas en el grafo + +| Comando | Descripción | +|---------|-------------| +| `tg-query-graph` | Consulta basada en patrones para el almacén de triples. A diferencia de `tg-show-graph` (que muestra todo), esto permite consultas selectivas para cualquier combinación de sujeto, predicado, objeto y grafo. Detecta automáticamente los tipos de valor: IRIs (`http://...`, `urn:...`, `<...>`), triples anclados (`<>`), y literales. | +| `tg-get-document-content` | Recupera el contenido del documento de la biblioteca por ID de documento. Puede mostrar en un archivo o en stdout, maneja tanto contenido de texto como binario. | + +--- + +## Herramientas CLI eliminadas + +| Comando | Notas | +|---------|-------| +| `tg-load-pdf` | Eliminado. La carga de documentos ahora se maneja a través de la biblioteca/pipeline de procesamiento. | +| `tg-load-text` | Eliminado. La carga de documentos ahora se maneja a través de la biblioteca/pipeline de procesamiento. | + +--- + +## Herramientas CLI renombradas + +| Nombre antiguo | Nombre nuevo | Notas | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | Refleja el cambio de terminología de "objetos" a "filas" para datos estructurados. | + +--- + +## Cambios Significativos en Herramientas Existentes + +### `tg-invoke-graph-rag` + +- **Soporte de explicabilidad**: Ahora soporta una tubería de explicabilidad de 4 etapas (Pregunta, Fundamentación/Exploración, Enfoque, Síntesis) con visualización de eventos de origen en línea. +- **Streaming**: Utiliza el streaming de WebSocket para la salida en tiempo real. +- **Rastreo de origen**: Puede rastrear bordes seleccionados de vuelta a los documentos originales a través de la reificación y cadenas `prov:wasDerivedFrom`. +- Crecer de ~30 líneas a ~760 líneas para acomodar la tubería de explicabilidad completa. + +### `tg-invoke-document-rag` + +- **Soporte de explicabilidad**: Añadido el modo `question_explainable()` que transmite las respuestas de RAG de Documento con eventos de origen en línea (etapas de Pregunta, Fundamentación, Exploración, Síntesis). + +### `tg-invoke-agent` + +- **Soporte de explicabilidad**: Añadido el modo `question_explainable()` que muestra los eventos de origen en línea durante la ejecución del agente (etapas de Pregunta, Análisis, Conclusión, AgentThought, AgentObservation, AgentAnswer). +- El modo verboso muestra las transmisiones de pensamentos/observaciones con prefijos de emojis. + +### `tg-show-graph` + +- **Modo de streaming**: Ahora utiliza `triples_query_stream()` con tamaños de lote configurables para un tiempo de primer resultado más bajo y una menor sobrecarga de memoria. +- **Soporte de grafo nombrado**: Nueva opción `--graph` de filtro. Reconoce grafos nombrados: + - Grafo predeterminado (vacío): Hechos de conocimiento básicos + - `urn:graph:source`: Origen de extracción + - `urn:graph:retrieval`: Explicabilidad en tiempo de consulta +- **Mostrar columna de grafo**: Nueva bandera `--show-graph` para mostrar el grafo nombrado para cada triple. +- **Límites configurables**: Nuevas opciones `--limit` y `--batch-size`. + +### `tg-graph-to-turtle` + +- **Soporte de RDF-star**: Ahora maneja triples anclados (reificación de RDF-star). +- **Modo de streaming**: Utiliza streaming para un tiempo de procesamiento más rápido. +- **Manejo del formato de cable**: Actualizado para utilizar el nuevo formato de cable (`{"t": "i", "i": uri}` para IRIs, `{"t": "l", "v": value}` para literales, `{"t": "r", "r": {...}}` para triples anclados) +- **Soporte de grafo nombrado**: Nueva opción `--graph` de filtro. + +### `tg-set-tool` + +- **Nuevo tipo de herramienta**: `row-embeddings-query` para búsqueda semántica en índices de datos estructurados. +- **Nuevas opciones**: `--schema-name`, `--index-name`, `--limit` para configurar herramientas de consulta de embeddings de fila. + +### `tg-show-tools` + +- Muestra el nuevo tipo de herramienta `row-embeddings-query` con sus campos `schema-name`, `index-name` y `limit`. + +### `tg-load-knowledge` + +- **Informes de progreso**: Ahora cuenta y reporta los triples y contextos de entidad cargados por archivo y en total. +- **Actualización del formato de término**: Los contextos de entidad ahora utilizan el nuevo formato de término (`{"t": "i", "i": uri}`) en lugar del formato de valor antiguo (`{"v": ..., "e": ...}`). + +--- + +## Cambios de rompimiento + +- **Cambio de terminología**: El esquema `Value` se renombró a `Term` en todo el sistema (PR #622). Esto afecta al formato de cable utilizado por las herramientas CLI que interactúan con el almacén de grafos. El nuevo formato utiliza `{"t": "i", "i": uri}` para IRIs y `{"t": "l", "v": value}` para literales, reemplazando el formato antiguo `{"v": ..., "e": ...}`. +- **`tg-invoke-objects-query` renombrado** a `tg-invoke-rows-query`. +- **`tg-load-pdf` y `tg-load-text` eliminados**. diff --git a/docs/cli-changes-v1.8-to-v2.1.he.md b/docs/cli-changes-v1.8-to-v2.1.he.md new file mode 100644 index 00000000..07c9d6c7 --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.he.md @@ -0,0 +1,119 @@ +--- +layout: default +title: "שינויים ב-CLI: מ-v1.8 ל-v2.1" +parent: "Hebrew (Beta)" +--- + +# שינויים ב-CLI: מ-v1.8 ל-v2.1 + +> **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-cli`) כולל שינויים משמעותיים המתמקדים בשלוש תחומים: +**הסבר/מקוריות**, **גישה להטמעות**, ו**שאילתות גרף**. +שני כלי ישנים הוסרו, אחד שונה שמו, ורבים מכלי קיימים קיבלו יכולות חדשות. + +--- + +## כלים חדשים ב-CLI + +### הסבר ומקוריות + +| פקודה | תיאור | +|---|---| +| `tg-list-explain-traces` | רשימת כל סשנים של הסבר (GraphRAG ו-Agent) בקולקציה, המציגים מזהי סשן, סוג, טקסט שאלה, וחותמות זמן. | +| `tg-show-explain-trace` | מציג את הרשומת ההסבר המלאה לסשן. עבור GraphRAG: שלב השאלה, החקירה, ההתמקדות, והסינתזה. עבור Agent: שלב הסשן, איטרציות (מחשבה/פעולה/תצפית), התשובה הסופית. מזהה אוטומטית את סוג הרשומת. תומך באפשרות `--show-provenance` כדי לעקוב אחר קצוות בחזרה לתיקי המסמך המקוריים. | +| `tg-show-extraction-provenance` | בהתבסס על מזהה מסמך, עובר על שרשרת המקוריות: מסמך -> עמודים -> קטעים -> קצוות, תוך שימוש ביחסים של `prov:wasDerivedFrom`. תומך באפשרויות `--show-content` ו-`--max-content`. | + +### הטמעות + +| פקודה | תיאור | +|---|---| +| `tg-invoke-embeddings` | ממיר טקסט לייצוג וקטורי באמצעות שירות ההטמעות. מקבל אחד או יותר של קלדי טקסט, ומחזיר וקטורים כרשימות של מספרים ממשיים. | +| `tg-invoke-graph-embeddings` | שאילת ישויות גרף באמצעות טקסט על סמך ייצוגים וקטוריים. מחזיר ישויות תואמות עם ציוני דמיון. | +| `tg-invoke-document-embeddings` | שאילת קטעי מסמך באמצעות טקסט על סמך ייצוגים וקטוריים. מחזיר מזהי קטעים תואמים עם ציוני דמיון. | +| `tg-invoke-row-embeddings` | שאילת שורות של נתונים מובנים על סמך טקסט על שדות מסומנים. מחזיר שורות תואמות עם ערכי אינדקס וציון. דורש `--schema-name` ומקבל תמיכה ב-`--index-name`. | + +### שאילתות גרף + +| פקודה | תיאור | +|---|---| +| `tg-query-graph` | שאילתת אחסון טריפלים מבוססת תבנית. בניגוד ל-`tg-show-graph` (שמציג הכל), זה מאפשר שאילתות סלקטיביות באמצעות כל שילוב של נושא, תחביר, אובייקט וגרף. מזהה באופן אוטומטי סוגי ערכים: IRI (`http://...`, `urn:...`, `<...>`), טריפלים מוטבעים (`<>`), וערכים. | +| `tg-get-document-content` | אחזר תוכן מסמך מהספרייה על סמך מזהה מסמך. יכול להפיק לתיק או ל-stdout, ומטפל גם בתוכן טקסט וגם בתוכן בינארי. | + +--- + +## כלים שהוסרו ב-CLI + +| פקודה | הערות | +|---|---| +| `tg-load-pdf` | הוסר. טעינת מסמך מטופלת כעת באמצעות הספריה/צינור העיבוד. | +| `tg-load-text` | הוסר. טעינת מסמך מטופלת כעת באמצעות הספריה/צינור העיבוד. | + +--- + +## שמות כלים חדשים + +| שם ישן | שם חדש | הערות | +|---|---|---| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | משקף את השינוי בשם המושג מ"אובייקטים" ל"שורות" עבור נתונים מובנים. | + +--- + +## שינויים משמעותיים בכלים קיימים + +### `tg-invoke-graph-rag` + +- **תמיכה בהסבר**: תומך כעת בפונקציית הסבר של 4 שלבים (שאלה, חקירה/התמקדות, סינתזה) עם הצגת אירועי מקוריות מקומיים. +- **זרם**: משתמש בזרם WebSocket עבור פלט בזמן אמת. +- **מעקב אחר מקוריות**: יכול לעקוב אחר קצוות שנבחרו בחזרה למסמכים מקוריים באמצעות ריפוי ושרשראות של `prov:wasDerivedFrom`. +- גדל מ-~30 שורות ל-~760 שורות כדי להסב את כל פונקציית ההסבר. + +### `tg-invoke-document-rag` + +- **תמיכה בהסבר**: הוספה של מצב `question_explainable()` המפיק תגובות של RAG עבור מסמכים עם אירועי מקוריות מקומיים (שלבי שאלה, חקירה, התמקדות, סינתזה). + +### `tg-invoke-agent` + +- **תמיכה בהסבר**: הוספת מצב `question_explainable()` המציג אירועי מקוריות במהלך ביצוע סוכן (שלבי שאלה, ניתוח, מסקנה, AgentThought, AgentObservation, AgentAnswer). +- מצב מפורט מציג זרימות של מחשבה/תצפית עם קידומים של סמלים. + +### `tg-show-graph` + +- **מצב זרימה**: משתמש כעת ב-`triples_query_stream()` עם גדלי אצווה מוגדרים כדי להפחית את זמן התגובה הראשון ולהקטין את צריכת הזיכרון. +- **תמיכה בגרף משמות**: אפשרות חדשה `--graph`. מזהה גרפים משמות: + - גרף ברירת מחדל (ריק): עובדות ידע בסיסיות + - `urn:graph:source`: מקוריות של הסתרה + - `urn:graph:retrieval`: הסבר בזמן שאילתה +- **הצגת עמוד גרף**: תגית חדשה `--show-graph` להצגת הגרף המשמות לכל טריפל. +- **גבולות ניתנים להתאמה**: אפשרויות חדשות `--limit` ו-`--batch-size`. + +### `tg-graph-to-turtle` + +- **תמיכה ב-RDF-star**: מטפל בטריפלים מוטבעים (ריפוי RDF-star). +- **מצב זרימה**: משתמש בזרם להפחתת זמן התגובה הראשון. +- **טיפול בפורמט חוטי**: מעודכן כדי להשתמש בפורמט החוט החדש (`{"t": "i", "i": uri}` עבור IRI, `{"t": "l", "v": value}` עבור ערכים, `{"t": "r", "r": {...}}` עבור טריפלים מוטבעים). +- **תמיכה בגרף משמות**: אפשרות חדשה `--graph`. + +### `tg-set-tool` + +- **סוג כלי חדש**: `row-embeddings-query` לשאילתות סמנטיות על אינדקסים של נתונים מובנים. +- **אפשרויות חדשות**: `--schema-name`, `--index-name`, `--limit` כדי להגדיר כלים לשאילתות הטמעות שורות. + +### `tg-show-tools` + +- מציג את סוג הכלי החדש `row-embeddings-query` עם השדות שלו `schema-name`, `index-name`, ו-`limit`. + +### `tg-load-knowledge` + +- **דיווח התקדמות**: סופר ומדווח על מספר הטרפולים ועל הקטעי של ישויות המועמסים, לפי קובץ וגם בסך הכל. +- **עדכון פורמט מונח**: קטעי ישויות משתמשים כעת בפורמט המונח החדש (`{"t": "i", "i": uri}`) במקום בפורמט הערך הישן (`{"v": entity, "e": True}`). + +--- + +## שינויים שבורים + +- **שינוי שמות**: הסכימה `Value` שונתה לשם `Term` בכל המערכת (PR #622). זה משפיע על הציוד שמשתמש בכלי ה-CLI שמתקשר עם מאגר הגרף. הפורמט החדש משתמש ב-`{"t": "i", "i": uri}` עבור IRI ו-`{"t": "l", "v": value}` עבור ערכים, במקום הפורמט הישן `{"v": ..., "e": ...}`. +- **השינוי בשם של `tg-invoke-objects-query`** ל- `tg-invoke-rows-query`. +- **הוסרו `tg-load-pdf` ו-`tg-load-text`. diff --git a/docs/cli-changes-v1.8-to-v2.1.hi.md b/docs/cli-changes-v1.8-to-v2.1.hi.md new file mode 100644 index 00000000..c9928ee6 --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.hi.md @@ -0,0 +1,119 @@ +--- +layout: default +title: "CLI में परिवर्तन: v1.8 से v2.1" +parent: "Hindi (Beta)" +--- + +# CLI में परिवर्तन: v1.8 से v2.1 + +> **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-cli`) में तीन मुख्य क्षेत्रों पर ध्यान केंद्रित किए गए महत्वपूर्ण परिवर्धन शामिल हैं: +**व्याख्यात्मकता/उत्पत्ति, एम्बेडिंग एक्सेस, और ग्राफ़ क्वेरी।** +दो पुरानी उपकरण हटा दिए गए थे, एक का नाम बदल दिया गया, और कई मौजूदा उपकरणों में नई क्षमताएं जोड़ी गईं। + +--- + +## नए CLI उपकरण + +### व्याख्यात्मकता और उत्पत्ति + +| कमांड | विवरण | +|---------|-------------| +| `tg-list-explain-traces` | एक संग्रह में सभी व्याख्या सत्रों (GraphRAG और एजेंट) की सूची, जिसमें सत्र आईडी, प्रकार, प्रश्न पाठ और टाइमस्टैम्प शामिल हैं। | +| `tg-show-explain-trace` | किसी सत्र के लिए पूरी व्याख्यात्मक ट्रेस प्रदर्शित करता है। GraphRAG के लिए: प्रश्न, खोज, ध्यान केंद्रित, संश्लेषण चरण। एजेंट के लिए: सत्र, पुनरावृत्तियाँ (सोच/क्रिया/अवलोकन), अंतिम उत्तर। स्वचालित रूप से ट्रेस प्रकार का पता लगाता है। `--show-provenance` का उपयोग करके स्रोत दस्तावेजों तक किनारों को ट्रेस करने का समर्थन करता है। | +| `tg-show-extraction-provenance` | एक दस्तावेज़ आईडी दिए जाने पर, `prov:wasDerivedFrom` संबंधों का उपयोग करके उत्पत्ति श्रृंखला को पार करता है: दस्तावेज़ -> पृष्ठ -> खंड -> किनारे। `--show-content` और `--max-content` विकल्पों का समर्थन करता है। | + +### एम्बेडिंग + +| कमांड | विवरण | +|---------|-------------| +| `tg-invoke-embeddings` | एम्बेडिंग सेवा के माध्यम से टेक्स्ट को वेक्टर एम्बेडिंग में परिवर्तित करता है। एक या अधिक टेक्स्ट इनपुट स्वीकार करता है, और फ़्लोट की सूची के रूप में वेक्टर लौटाता है। | +| `tg-invoke-graph-embeddings` | वेक्टर एम्बेडिंग का उपयोग करके ग्राफ संस्थाओं को क्वेरी करता है। मिलान संस्थाओं और समानता स्कोर लौटाता है। | +| `tg-invoke-document-embeddings` | वेक्टर एम्बेडिंग का उपयोग करके दस्तावेज़ खंडों को क्वेरी करता है। मिलान खंड आईडी और समानता स्कोर लौटाता है। | +| `tg-invoke-row-embeddings` | इंडेक्स किए गए फ़ील्ड पर टेक्स्ट समानता का उपयोग करके संरचित डेटा पंक्तियों को क्वेरी करता है। मिलान पंक्तियों और स्कोर लौटाता है। `--schema-name` और `--index-name` का समर्थन करता है। | + +### ग्राफ़ क्वेरी + +| कमांड | विवरण | +|---------|-------------| +| `tg-query-graph` | पैटर्न-आधारित ट्रिपल स्टोर क्वेरी। `tg-show-graph` (जो सब कुछdumps करता है) के विपरीत, यह किसी भी संयोजन के विषय, विधेय, वस्तु और ग्राफ़ द्वारा चयनशील क्वेरी की अनुमति देता है। स्वचालित रूप से मूल्य प्रकार का पता लगाता है: IRI (`http://...`, `urn:...`, `<...>`), उद्धृत ट्रिपल (`<>`), और अक्षर। | +| `tg-get-document-content` | लाइब्रेरी से दस्तावेज़ आईडी द्वारा दस्तावेज़ सामग्री प्राप्त करता है। फ़ाइल या stdout पर आउटपुट कर सकता है, और टेक्स्ट और बाइनरी सामग्री दोनों को संभालता है। | + +--- + +## हटाए गए CLI उपकरण + +| कमांड | नोट्स | +|---------|-------| +| `tg-load-pdf` | हटा दिया गया। दस्तावेज़ लोडिंग अब लाइब्रेरी/प्रसंस्करण पाइपलाइन के माध्यम से संभाली जाती है। | +| `tg-load-text` | हटा दिया गया। दस्तावेज़ लोडिंग अब लाइब्रेरी/प्रसंस्करण पाइपलाइन के माध्यम से संभाली जाती है। | + +--- + +## नाम बदले गए CLI उपकरण + +| पुराना नाम | नया नाम | नोट्स | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | संरचित डेटा के लिए "ऑब्जेक्ट" से "पंक्ति" के शब्दावली में बदलाव को दर्शाता है। | + +--- + +## मौजूदा उपकरणों में महत्वपूर्ण परिवर्तन + +### `tg-invoke-graph-rag` + +- **व्याख्यात्मकता समर्थन**: 4-चरण व्याख्यात्मक पाइपलाइन (प्रश्न, ग्राउंडिंग/खोज, ध्यान केंद्रित, संश्लेषण) का समर्थन करता है जिसमें इनलाइन उत्पत्ति घटना प्रदर्शन भी शामिल है। +- **स्ट्रीमिंग**: वास्तविक समय के आउटपुट के लिए WebSocket स्ट्रीमिंग का उपयोग करता है। +- **उत्पत्ति ट्रेसिंग**: पुनरावर्तन और `prov:wasDerivedFrom` श्रृंखलाओं के माध्यम से चयनित किनारों को स्रोत दस्तावेजों तक ट्रेस कर सकता है। +- ~30 पंक्तियों से ~760 पंक्तियों तक बढ़ गया है ताकि पूरे व्याख्यात्मक पाइपलाइन को समायोजित किया जा सके। + +### `tg-invoke-document-rag` + +- **व्याख्यात्मकता समर्थन**: `question_explainable()` मोड जोड़ा गया जो दस्तावेज़ RAG प्रतिक्रियाओं को इनलाइन उत्पत्ति घटनाओं (प्रश्न, ग्राउंडिंग, खोज, संश्लेषण चरण) के साथ प्रवाहित करता है। + +### `tg-invoke-agent` + +- **व्याख्यात्मकता समर्थन**: `question_explainable()` मोड जोड़ा गया जो एजेंट निष्पादन के दौरान इनलाइन उत्पत्ति घटनाओं (प्रश्न, विश्लेषण, निष्कर्ष, एजेंटसोच, एजेंटअवलोकन, एजेंटउत्तर) को प्रदर्शित करता है। +- वर्बोस मोड में, इमोजी उपसर्ग के साथ सोच/अवलोकन धाराओं को दिखाया जाता है। + +### `tg-show-graph` + +- **स्ट्रीमिंग मोड**: `triples_query_stream()` का उपयोग करता है जिसमें कम समय-से-पहले-परिणाम और कम मेमोरी ओवरहेड के लिए कॉन्फ़िगरेबल बैच आकार होते हैं। +- **नाम वाले ग्राफ़ समर्थन**: नया `--graph` फ़िल्टर विकल्प। निम्नलिखित नाम वाले ग्राफ़ को पहचानता है: + - डिफ़ॉल्ट ग्राफ़ (खाली): मुख्य ज्ञान तथ्य + - `urn:graph:source`: निष्कर्षण उत्पत्ति + - `urn:graph:retrieval`: क्वेरी-समय व्याख्यात्मकता +- **ग्राफ़ कॉलम दिखाना**: `--show-graph` ध्वज जोड़ा गया। +- **कॉन्फ़िगरेबल सीमाएँ**: नए `--limit` और `--batch-size` विकल्प। + +### `tg-graph-to-turtle` + +- **RDF-स्टार समर्थन**: उद्धृत ट्रिपल (RDF-स्टार पुनरावर्तन) को संभालता है। +- **स्ट्रीमिंग मोड**: कम समय-से-पहले-प्रसंस्करण के लिए स्ट्रीमिंग का उपयोग करता है। +- **वायर फॉर्मेट हैंडलिंग**: नई वायर फॉर्मेट (`{"t": "i", "i": uri}` के लिए IRI, `{"t": "l", "v": value}` के लिए अक्षर, `{"t": "r", "r": {...}}` के लिए उद्धृत ट्रिपल) का उपयोग करने के लिए अपडेट किया गया है। +- **नाम वाले ग्राफ़ समर्थन**: नया `--graph` फ़िल्टर विकल्प। + +### `tg-set-tool` + +- **नया उपकरण प्रकार**: संरचित डेटा सूचकांकों पर अर्थपूर्ण खोज के लिए `row-embeddings-query`। +- **नया विकल्प**: संरचित डेटा क्वेरी टूल के लिए `--schema-name`, `--index-name`, `--limit` विकल्प जोड़े गए। + +### `tg-show-tools` + +- `row-embeddings-query` के नए उपकरण प्रकार और उसके `schema-name`, `index-name` और `limit` फ़ील्ड को प्रदर्शित करता है। + +### `tg-load-knowledge` + +- **प्रगति रिपोर्टिंग**: प्रत्येक फ़ाइल और कुल में लोड किए गए ट्रिपल और संस्था संदर्भों की गणना और रिपोर्ट करता है। +- **टर्म फॉर्मेट अपडेट**: संस्था संदर्भ अब नए टर्म फॉर्मेट (`{"t": "i", "i": uri}`) का उपयोग करते हैं, जबकि पुराने मूल्य फॉर्मेट (`{"v": entity, "e": True}`) का उपयोग किया जाता था। + +--- + +## ब्रेकिंग परिवर्तन + +- **शब्दावली का नाम बदलना**: `Value` स्कीम को पूरे सिस्टम में `Term` नाम दिया गया है (PR #622)। यह CLI टूल के लिए जो ग्राफ स्टोर के साथ इंटरैक्ट करते हैं, उनके वायर फॉर्मेट को प्रभावित करता है। नया फॉर्मेट `{"t": "i", "i": uri}` IRI के लिए और `{"t": "l", "v": value}` अक्षर के लिए, पिछले `{"v": ..., "e": ...}` फॉर्मेट के स्थान पर उपयोग करता है। +- **`tg-invoke-objects-query` को `tg-invoke-rows-query` में नाम बदला गया**। +- **`tg-load-pdf` और `tg-load-text` हटा दिए गए**। diff --git a/docs/cli-changes-v1.8-to-v2.1.pt.md b/docs/cli-changes-v1.8-to-v2.1.pt.md new file mode 100644 index 00000000..3aa7401a --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.pt.md @@ -0,0 +1,120 @@ +--- +layout: default +title: "Alterações na CLI: da v1.8 para v2.1" +parent: "Portuguese (Beta)" +--- + +# Alterações na CLI: da v1.8 para v2.1 + +> **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. + +## Resumo + +A CLI (`trustgraph-cli`) possui adições significativas focadas em três temas: +**explicabilidade/proveniência**, **acesso a embeddings** e **consulta de grafos**. +Duas ferramentas legadas foram removidas, uma foi renomeada e várias ferramentas existentes +adquiriram novas funcionalidades. + +-- + +## Novas Ferramentas da CLI + +### Explicabilidade e Proveniência + +| Comando | Descrição | +|---------|-------------| +| `tg-list-explain-traces` | Lista todas as sessões de explicabilidade (GraphRAG e Agent) em uma coleção, mostrando IDs de sessão, tipo, texto da pergunta e carimbos de data/hora. | +| `tg-show-explain-trace` | Exibe o rastreamento completo de explicabilidade para uma sessão. Para GraphRAG: Estágios de Pergunta, Exploração, Foco, Síntese. Para Agent: Sessão, Iterações (pensamento/ação/observação), Resposta Final. Detecta automaticamente o tipo de rastreamento. Suporta `--show-provenance` para rastrear arestas de volta para documentos de origem. | +| `tg-show-extraction-provenance` | Dado um ID de documento, percorre a cadeia de proveniência: Documento -> Páginas -> Trechos -> Arestas, usando relacionamentos `prov:wasDerivedFrom`. Suporta opções `--show-content` e `--max-content`. | + +### Embeddings + +| Comando | Descrição | +|---------|-------------| +| `tg-invoke-embeddings` | Converte texto em um embedding vetorial por meio do serviço de embeddings. Aceita uma ou mais entradas de texto, retorna vetores como listas de floats. | +| `tg-invoke-graph-embeddings` | Consulta entidades de grafo por similaridade de texto usando embeddings vetoriais. Retorna entidades correspondentes com pontuações de similaridade. | +| `tg-invoke-document-embeddings` | Consulta trechos de documentos por similaridade de texto usando embeddings vetoriais. Retorna IDs de trechos correspondentes com pontuações de similaridade. | +| `tg-invoke-row-embeddings` | Consulta linhas de dados estruturados por similaridade de texto em campos indexados. Retorna linhas correspondentes com valores de índice e pontuações. Requer `--schema-name` e suporta `--index-name`. | + +### Consulta de Grafos + +| Comando | Descrição | +|---------|-------------| +| `tg-query-graph` | Consulta de grafo baseada em padrões. Diferentemente de `tg-show-graph` (que despeja tudo), isso permite consultas seletivas por qualquer combinação de sujeito, predicado, objeto e grafo. Detecta automaticamente os tipos de valor: IRIs (`http://...`, `urn:...`, `<...>`), triplas entre aspas (`<>`) e literais. | +| `tg-get-document-content` | Recupera o conteúdo do documento da biblioteca por ID do documento. Pode ser direcionado para um arquivo ou stdout, lida com conteúdo de texto e binário. | + +-- + +## Ferramentas da CLI Removidas + +| Comando | Notas | +|---------|-------| +| `tg-load-pdf` | Removido. O carregamento de documentos é agora tratado por meio do pipeline de biblioteca/processamento. | +| `tg-load-text` | Removido. O carregamento de documentos é agora tratado por meio do pipeline de biblioteca/processamento. | + +-- + +## Ferramentas da CLI Renomeadas + +| Nome Antigo | Novo Nome | Notas | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | Reflete a alteração de terminologia de "objetos" para "linhas" para dados estruturados. | + +-- + +## Mudanças Significativas em Ferramentas Existentes + +### `tg-invoke-graph-rag` + +**Suporte para explicabilidade**: Agora suporta um pipeline de explicabilidade de 4 etapas (Pergunta, Fundamentação/Exploração, Foco, Síntese) com exibição inline de eventos de rastreabilidade. +**Streaming**: Utiliza streaming WebSocket para saída em tempo real. +**Rastreabilidade**: Pode rastrear arestas selecionadas de volta para documentos de origem por meio de reificação e cadeias `prov:wasDerivedFrom`. +Cresceu de ~30 linhas para ~760 linhas para acomodar o pipeline completo de explicabilidade. + +### `tg-invoke-document-rag` + +**Suporte para explicabilidade**: Adicionado modo `question_explainable()` que transmite respostas do Document RAG com eventos de rastreabilidade inline (etapas de Pergunta, Fundamentação, Exploração, Síntese). + +### `tg-invoke-agent` + +**Suporte para explicabilidade**: Adicionado modo `question_explainable()` que exibe eventos de rastreabilidade inline durante a execução do agente (etapas de Pergunta, Análise, Conclusão, AgentThought, AgentObservation, AgentAnswer). +O modo verboso exibe fluxos de pensamento/observação com prefixos de emoji. + +### `tg-show-graph` + +**Modo de streaming**: Agora usa `triples_query_stream()` com tamanhos de lote configuráveis para um tempo de primeiro resultado menor e menor sobrecarga de memória. +**Suporte para grafos nomeados**: Nova opção de filtro `--graph`. Reconhece grafos nomeados: + Grafo padrão (vazio): Fatos de conhecimento principais + `urn:graph:source`: Rastreabilidade de extração + `urn:graph:retrieval`: Explicabilidade no momento da consulta +**Mostrar coluna do grafo**: Nova flag `--show-graph` para exibir o grafo nomeado para cada tripla. +**Limites configuráveis**: Novas opções `--limit` e `--batch-size`. + +### `tg-graph-to-turtle` + +**Suporte para RDF-star**: Agora lida com triplas citadas (reificação RDF-star). +**Modo de streaming**: Utiliza streaming para um tempo de processamento inicial menor. +**Manipulação de formato de fio**: Atualizado para usar o novo formato de fio de termos (`{"t": "i", "i": uri}` para IRIs, `{"t": "l", "v": value}` para literais, `{"t": "r", "r": {...}}` para triplas citadas). +**Suporte para grafos nomeados**: Nova opção de filtro `--graph`. + +### `tg-set-tool` + +**Novo tipo de ferramenta**: `row-embeddings-query` para pesquisa semântica em índices de dados estruturados. +**Novas opções**: `--schema-name`, `--index-name`, `--limit` para configurar ferramentas de consulta de incorporações de linhas. + +### `tg-show-tools` + +Exibe o novo tipo de ferramenta `row-embeddings-query` com seus campos `schema-name`, `index-name` e `limit`. + +### `tg-load-knowledge` + +**Relatório de progresso**: Agora conta e relata triplas e contextos de entidade carregados por arquivo e no total. +**Atualização do formato de termo**: Os contextos de entidade agora usam o novo formato de Termo (`{"t": "i", "i": uri}`) em vez do formato de Valor antigo (`{"v": entity, "e": True}`). + +-- + +## Mudanças Incompatíveis + +**Renomeação de terminologia**: O esquema `Value` foi renomeado para `Term` em todo o sistema (PR #622). Isso afeta o formato de fio usado por ferramentas de linha de comando que interagem com o armazenamento de grafo. O novo formato usa `{"t": "i", "i": uri}` para IRIs e `{"t": "l", "v": value}` para literais, substituindo o formato antigo `{"v": ..., "e": ...}`. +**`tg-invoke-objects-query` renomeado** para `tg-invoke-rows-query`. +**`tg-load-pdf` e `tg-load-text` removidos**. diff --git a/docs/cli-changes-v1.8-to-v2.1.ru.md b/docs/cli-changes-v1.8-to-v2.1.ru.md new file mode 100644 index 00000000..99b1e8ce --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.ru.md @@ -0,0 +1,119 @@ +--- +layout: default +title: "Изменения в CLI: v1.8 to v2.1" +parent: "Russian (Beta)" +--- + +# Изменения в CLI: v1.8 to v2.1 + +> **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-cli`) включает в себя значительные дополнения, ориентированные на три основные темы: +**объяснимость/происхождение**, **доступ к вложениям** и **запросы к графу**. +Два устарелых инструмента были удалены, один был переименован, а несколько существующих инструментов получили новые возможности. + +--- + +## Новые инструменты CLI + +### Объяснимость и происхождение + +| Команда | Описание | +|---------|-------------| +| `tg-list-explain-traces` | Перечисляет все сеансы объяснения (GraphRAG и Agent) в коллекции, показывая идентификаторы сеансов, тип, текст вопроса и временные метки. | +| `tg-show-explain-trace` | Отображает полный трас сеанса объяснения. Для GraphRAG: этапы Вопрос, Исследование, Фокусировка, Синтез. Для Agent: этапы Сеанс, Итерации (мысль/действие/наблюдение), Конечный ответ. Автоматически определяет тип траса. Поддерживает опцию `--show-provenance` для отслеживания связей обратно к исходным документам. | +| `tg-show-extraction-provenance` | Принимает идентификатор документа, проходящего по цепочке происхождения: Документ -> Страницы -> Блоки -> Связи, используя отношения `prov:wasDerivedFrom`. Поддерживает опции `--show-content` и `--max-content`. | + +### Вложения + +| Команда | Описание | +|---------|-------------| +| `tg-invoke-embeddings` | Преобразует текст в векторное представление посредством сервиса вложений. Принимает один или несколько текстовых входных данных, возвращает векторы в виде списков чисел с плавающей точкой. | +| `tg-invoke-graph-embeddings` | Запрашивает сущности графа по текстовому сходству с использованием векторных представлений. Возвращает соответствующие сущности со значениями сходства. | +| `tg-invoke-document-embeddings` | Запрашивает текстовые блоки документа по текстовому сходству с использованием векторных представлений. Возвращает идентификаторы соответствующих текстовых блоков со значениями сходства. | +| `tg-invoke-row-embeddings` | Запрашивает структурированные данные строк по текстовому сходству в индексированных полях. Возвращает соответствующие строки со значениями индексов и значениями сходства. Требует опции `--schema-name` и поддерживает `--index-name`. | + +### Запросы к графу + +| Команда | Описание | +|---------|-------------| +| `tg-query-graph` | Запрос хранилища троек на основе шаблона. В отличие от `tg-show-graph` (который отображает всё), это позволяет осуществлять выборочные запросы с использованием любой комбинации субъекта, предиката, объекта и графа. Автоматически определяет типы значений: URI (`http://...`, `urn:...`, `<...>`), закодированные тройки (`<>`) и литералы. | +| `tg-get-document-content` | Получает содержимое документа из библиотеки по идентификатору документа. Может отображать в файл или stdout, обрабатывает как текст, так и двоичные данные. | + +--- + +## Удаленные инструменты CLI + +| Команда | Примечания | +|---------|-------| +| `tg-load-pdf` | Удалено. Загрузка документов теперь осуществляется через библиотеку/процессную цепочку. | +| `tg-load-text` | Удалено. Загрузка документов теперь осуществляется через библиотеку/процессную цепочку. | + +--- + +## Переименованные инструменты CLI + +| Старое имя | Новое имя | Примечания | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | Отражает изменение терминологии с "объектов" на "строки" для структурированных данных. | + +--- + +## Значительные изменения существующих инструментов + +### `tg-invoke-graph-rag` + +- **Поддержка объяснимости:** Поддерживает четырехэтапную пайплайн объяснения (Вопрос, Поиск/Исследование, Фокусировка, Синтез) с отображением событий происхождения. +- **Стриминг:** Использует стриминг WebSocket для получения результатов в реальном времени. +- **Отслеживание происхождения:** Может отслеживать выбранные связи обратно к исходным документам с использованием рефикации и цепочек `prov:wasDerivedFrom`. +- Увеличился размер кода с ~30 строк до ~760 строк, чтобы вместить полный пайплайн объяснения. + +### `tg-invoke-document-rag` + +- **Поддержка объяснимости:** Добавлен режим `question_explainable()`, который отображает ответы RAG для документов со встроенными событиями происхождения (этапы Вопрос, Поиск, Исследование, Синтез). + +### `tg-invoke-agent` + +- **Поддержка объяснимости:** Добавлен режим `question_explainable()`, который отображает происхождение во время выполнения агента (этапы Вопрос, Анализ, Вывод, AgentThought, AgentObservation, AgentAnswer). +- Режим "verbose" показывает потоки мыслей/наблюдений с префиксами эмодзи. + +### `tg-show-graph` + +- **Режим стриминга:** Теперь использует `triples_query_stream()` с настраиваемыми размерами пакетов для более быстрого получения первого результата и снижения использования памяти. +- **Поддержка именованного графа:** Новая опция `--graph`. Распознает именованные графы: + - Основной граф (пустой): Основные факты знаний + - `urn:graph:source`: Происхождение извлечения + - `urn:graph:retrieval`: Объяснение в момент запроса +- **Отображение столбца графа:** Ножная опция `--show-graph` для отображения именованного графа для каждой тройки. +- **Конфигурируемые лимиты:** Новые опции `--limit` и `--batch-size`. + +### `tg-graph-to-turtle` + +- **Поддержка RDF-star:** Теперь обрабатывает закодированные тройки (рефикация RDF-star). +- **Режим стриминга:** Использует стриминг для более быстрого получения первого результата. +- **Обработка формата wire:** Обновлено для использования нового формата wire (`{"t": "i", "i": uri}` для URI, `{"t": "l", "v": value}` для литералов, `{"t": "r", "r": {...}}` для закодированных троек). +- **Поддержка именованного графа:** Новая опция `--graph`. + +### `tg-set-tool` + +- **Новый тип инструмента:** `row-embeddings-query` для семантического поиска по индексированным структурированным данным. +- **Новые опции:** `--schema-name`, `--index-name`, `--limit` для настройки инструментов запроса вложений строк. + +### `tg-show-tools` + +- Отображает новый тип инструмента `row-embeddings-query` с его полями `schema-name`, `index-name` и `limit`. + +### `tg-load-knowledge` + +- **Отчет о прогрессе:** Теперь считает и отображает количество загруженных троек и контекстов сущностей в файл и в целом. +- **Обновление формата термина:** Контексты сущностей теперь используют новый формат термина (`{"t": "i", "i": uri}`) вместо старого формата значения (`{"v": ..., "e": ...}`). + +--- + +## Разрывные изменения + +- **Переименование терминологии:** Схема `Value` была переименована в `Term` во всей системе (PR #622). Это влияет на формат wire, используемый инструментами CLI, взаимодействующими с хранилищем графов. Новый формат использует `{"t": "i", "i": uri}` для URI и `{"t": "l", "v": value}` для литералов, заменяя старый формат `{"v": ..., "e": ...}`. +- **`tg-invoke-objects-query` переименовано** в `tg-invoke-rows-query`. +- **`tg-load-pdf` и `tg-load-text` удалены**. diff --git a/docs/cli-changes-v1.8-to-v2.1.sw.md b/docs/cli-changes-v1.8-to-v2.1.sw.md new file mode 100644 index 00000000..e96863dc --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.sw.md @@ -0,0 +1,123 @@ +--- +layout: default +title: "Mabadiliko ya CLI: v1.8 hadi v2.1" +parent: "Swahili (Beta)" +--- + +**MAELEMAZO MAKUUUUU:** +- Hifadhi FORMATI YOTE ya Markdown, vichungi, viungo na alama za HTML. +- Usitafsiri code ndani ya apostrophe au makundi ya code. +- Onyesho TU MAELEZO bila maelezo au maelezo. + +MAELEZO YA KUTAFSIRI: +# Mabadiliko ya CLI: v1.8 hadi v2.1 + +> **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 + +CLI (`trustgraph-cli`) ina ongezeko kubwa, iliyoangazia vipande tatu: +**ufafanuzi/asili,** **ufaa wa data,** na **utafutaji wa graphs.** +Zochorwa zote, mojawapo ilibadilishwa, na zochorwa za soko zimepata uwezo mpya. + +--- + +## Zochorwa Mpya za CLI + +### Ufafanuzi na Asili +| Amri | Maelezo | +|---------|-------------| +| `tg-list-explain-traces` | Inaorodha zote za ufafanuzi (GraphRAG na Agent) katika mkusanyiko, inaonyesha ID za mkusanyiko, aina, maandishi ya swali, na tarehe. | +| `tg-show-explain-trace` | Inaonyesha mstari kamili wa ufafanuzi kwa mkusanyiko. Kwa GraphRAG: Swali, Tafuta, Futa, na Safu za Mfumo. Kwa Agent: Mkusanyiko, Iterasi (fikra/hatua/taarifa), Jibu. Inaagizwa moja kwa moja. Inaunga mkono `--show-provenance` ili kurudisha miisho kwenye hati za asili. | +| `tg-show-extraction-provenance` | Ikiwa na ID ya hati, inaendesha mkondo wa asili: Hati -> Kurasa -> Chunks -> Miisho, kwa kutumia mahusiano ya `prov:wasDerivedFrom`. Inaunga mkono chaguzi `--show-content` na `--max-content`. | + +### Data +| Amri | Maelezo | +|---------|-------------| +| `tg-invoke-embeddings` | Hufanya maandishi kuwa na upinzani wa vector kupitia huduma ya upinzani. Inasoma moja au zaidi maandishi, inaondoa vipindi kama orodha. | +| `tg-invoke-graph-embeddings` | Inaweka maandishi na graphs kupitia upinzani. Inaondoa vipindi kama orodha. | +| `tg-invoke-document-embeddings` | Inaweka maandishi kupitia upinzani. Inaondoa vipindi kama orodha. | +| `tg-invoke-row-embeddings` | Inaweka data iliyoandaliwa kupitia upinzani. Inaondoa vipindi kama orodha. | + +### Tafutaji wa Graphs + +| Amri | Maelezo | +|---------|-------------| +| `tg-query-graph` | Tafutaji la triple store. Mbali na `tg-show-graph` (ambayo inatumia kila kitu), inawezesha tafuta maalum kwa uwingi wa majimbo, mahusiano, na graphs. Inaagiza orodha moja kwa moja. Inaunga mkono `http://...`, `urn:...`, na `<...>`. | +| `tg-get-document-content` | Inaagiza maudhui ya hati kutoka kwenye library kupitia ID ya hati. Inaweza kuonyesha kwenye faili au stdout, na inaweza kuuza maandishi na data. | + +--- + +## Zochorwa Zilizoondolewa za CLI + +| Amri | Maelezo | +|---------|-------| +| `tg-load-pdf` | Imeondolewa. Utoaaji wa hati sasa unaendesha kupitia pipeline ya library/utumiaji. | +| `tg-load-text` | Imeondolewa. Utoaaji wa hati sasa unaendesha kupitia pipeline ya library/utumiaji. | + +--- + +## Zochorwa Zilizo badilishwa za CLI + +| Jina la Zamani | Jina la mpya | Maelezo | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | Ina maelezo kuhusu jina. | + +--- + +## Mabadiliko Makubwa katika Zochorwa za Soko + +### `tg-invoke-graph-rag` + +- **Ufafanuzi**: Sasa ina 4-stage pipeline ya ufafanuzi (Swali, Tafuta/Tafuta, Futa, Mfumo) na maonyesho ya matukio ya asili. +- **Streami**: Inaendesha WebSocket kwa matokeo ya muda halisi. +- **Ufafanuzi**: Inawezesha kufuatilia miisho kwenye hati za asili kupitia reification na miisho ya `prov:wasDerivedFrom`. +- Imebadilishwa na ~30 mistari hadi ~760 mistari ili kukidhi pipeline ya ufafanuzi. + +### `tg-invoke-document-rag` + +- **Ufafanuzi**: Inaongeza mode `question_explainable()` ambayo inatumia Graph RAG na maonyesho ya matukio ya asili. + +### `tg-invoke-agent` + +- **Ufafanuzi**: Inaongeza mode `question_explainable()` inayoeleza matukio ya asili wakati wa utumiaji wa agent (Swali, Tafuta, Mfumo, AgentThought, AgentObservation, AgentAnswer). +- Mode ya verbose inaonyesha miisho za fikra/taarifa na prefixes za emoji. + +### `tg-show-graph` + +- **Mode ya Streami**: Inaendesha `triples_query_stream()` na ukubwa wa chombo configurable kwa muda wa matokeo wa kwanza na uzoefu wa kughushi. +- **Uunganisho wa graph**: Mpya `--graph` chaguo. Inaagiza graphs: + - Graph chungu (tupu): Hekalu + - `urn:graph:source`: Asili + - `urn:graph:retrieval`: Tafuta +- **Maonyesho ya graph**: Mpya `--show-graph` flag. Inaonyesha graph iliyochorwa kwa kila triple. +- **Ukubwa wa Chaguzi**: Mpya `--limit` na chaguzi `--batch-size`. + +### `tg-graph-to-turtle` + +- **RDF-star support**: Inaendesha miisho za apostrophe (RDF-star reification). +- **Mode ya Streami**: Inaendesha stream kwa muda wa matokezo wa kwanza. +- **Uhandishi wa format**: Inaendesha format mpya (`{"t": "i", "i": uri}` kwa IRIs, `{"t": "l", "v": value}` kwa literals, `{"t": "r", "r": {...}}` kwa miisho). +- **Uunganisho wa graph**: Mpya `--graph` chaguo. + +### `tg-set-tool` + +- **Aina mpya ya tool**: `row-embeddings-query` kwa utafutaji wa semantic kwenye data iliyoandaliwa. +- **Chaguzi mpya**: `--schema-name`, `--index-name`, `--limit` kwa kuunda zochorwa za upinzani. + +### `tg-show-tools` + +- Inaonyesha zochorwa za mpya za `row-embeddings-query` na chaguzi zake. + +### `tg-load-knowledge` + +- **Ripoti za Maendeleo**: Inahesabu na inaonyesha miisho na miisho za entity za ililoandaliwa kwa kila faili na kwa jumla. +- **Mbadilisho wa format**: Miisho za entity sasa inaformat mpya (`{"t": "i", "i": uri}`) badala ya format ya awali (`{"v": ..., "e": ...}`). + +--- + +## Mabadiliko Masharti + +- **Jina la jumla**: Jina la `Value` lilibadilishwa kuwa `Term` katika mfumo kote (PR #622). Hii inafanya na format mpya `{"t": "i", "i": uri}` kwa IRIs na `{"t": "l", "v": value}` kwa literals, badala ya format ya zamani `{"v": ..., "e": ...}`. +- **`tg-invoke-objects-query`** lilibadilishwa kuwa `tg-invoke-rows-query`. +- **`tg-load-pdf`** na **`tg-load-text`** liliondolewa. diff --git a/docs/cli-changes-v1.8-to-v2.1.tr.md b/docs/cli-changes-v1.8-to-v2.1.tr.md new file mode 100644 index 00000000..0b801676 --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.tr.md @@ -0,0 +1,120 @@ +--- +layout: default +title: "CLI Değişiklikleri: v1.8'den v2.1'e" +parent: "Turkish (Beta)" +--- + +# CLI Değişiklikleri: v1.8'den v2.1'e + +> **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. + +## Özet + +CLI (`trustgraph-cli`), üç tema üzerine odaklanmış önemli eklemeler içerir: +**açıklanabilirlik/kaynak**, **gömme erişimi** ve **graf sorgulama**. +İki eski araç kaldırıldı, biri yeniden adlandırıldı ve birkaç mevcut araç +yeni yetenekler kazandı. + +-- + +## Yeni CLI Araçları + +### Açıklanabilirlik ve Kaynak + +| Komut | Açıklama | +|---------|-------------| +| `tg-list-explain-traces` | Bir koleksiyondaki tüm açıklanabilirlik oturumlarını (GraphRAG ve Agent) listeler, oturum kimliklerini, türü, soru metnini ve zaman damgalarını gösterir. | +| `tg-show-explain-trace` | Bir oturum için tam açıklanabilirlik izini görüntüler. GraphRAG için: Soru, Keşif, Odak, Sentez aşamaları. Agent için: Oturum, Yinelemeler (düşünce/eylem/gözlem), Son Cevap. İz türünü otomatik olarak algılar. `--show-provenance` ile kaynak belgelere kadar kenarları izlemeyi destekler. | +| `tg-show-extraction-provenance` | Bir belge kimliği verildiğinde, kaynak zincirini izler: Belge -> Sayfalar -> Parçalar -> Kenarlar, `prov:wasDerivedFrom` ilişkilerini kullanarak. `--show-content` ve `--max-content` seçeneklerini destekler. | + +### Gömme (Embeddings) + +| Komut | Açıklama | +|---------|-------------| +| `tg-invoke-embeddings` | Metni, gömme hizmeti aracılığıyla bir vektör gömmesine dönüştürür. Bir veya daha fazla metin girişi alır, vektörleri kayan nokta listeleri olarak döndürür. | +| `tg-invoke-graph-embeddings` | Vektör gömmelerini kullanarak grafik varlıklarını metin benzerliğiyle sorgular. Eşleşen varlıkları benzerlik puanlarıyla döndürür. | +| `tg-invoke-document-embeddings` | Vektör gömmelerini kullanarak belge parçalarını metin benzerliğiyle sorgular. Eşleşen parça kimliklerini benzerlik puanlarıyla döndürür. | +| `tg-invoke-row-embeddings` | Vektör gömmelerini kullanarak dizinlenmiş alanlarda yapılandırılmış veri satırlarını metin benzerliğiyle sorgular. Eşleşen satırları, indeks değerlerini ve puanları döndürür. `--schema-name` gerektirir ve `--index-name`'yi destekler. | + +### Graf Sorgulama + +| Komut | Açıklama | +|---------|-------------| +| `tg-query-graph` | Desen tabanlı üçlü depolama sorgusu. `tg-show-graph`'in aksine (her şeyi dökerek), bu, herhangi bir konu, yüklem, nesne ve graf kombinasyonuyla seçici sorgular yapmayı sağlar. Değer türlerini otomatik olarak algılar: IRI'lar (`http://...`, `urn:...`, `<...>`), tırnak işaretli üçlüler (`<>`) ve literal'lar. | +| `tg-get-document-content` | Belge kimliğine göre kütüphaneden belge içeriğini alır. Dosyaya veya standart çıktıya yazabilir, hem metin hem de ikili içeriği işler. | + +-- + +## Kaldırılan CLI Araçları + +| Komut | Notlar | +|---------|-------| +| `tg-load-pdf` | Kaldırıldı. Belge yükleme artık kütüphane/işlem hattı aracılığıyla yapılır. | +| `tg-load-text` | Kaldırıldı. Belge yükleme artık kütüphane/işlem hattı aracılığıyla yapılır. | + +-- + +## Yeniden Adlandırılan CLI Araçları + +| Eski Ad | Yeni Ad | Notlar | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | Yapılandırılmış veri için "nesneler" teriminin "satırlar" terimine dönüştürülmesini yansıtır. | + +-- + +## Mevcut Araçlara Yönelik Önemli Değişiklikler + +### `tg-invoke-graph-rag` + +**Açıklanabilirlik desteği**: Artık, yerleşik kaynak olay gösterimiyle (Question, Grounding/Exploration, Focus, Synthesis) 4 aşamalı bir açıklanabilirlik işlem hattını destekler. +**Akış**: Gerçek zamanlı çıktı için WebSocket akışını kullanır. +**Kaynak takibi**: Seçilen kenarları yeniden yapılandırma ve `prov:wasDerivedFrom` zincirleri aracılığıyla kaynak belgelere kadar izleyebilir. +Tam açıklanabilirlik işlem hattını barındırmak için ~30 satırdan ~760 satıra yükseldi. + +### `tg-invoke-document-rag` + +**Açıklanabilirlik desteği**: İçerik tabanlı yanıtları (Document RAG) yerleşik kaynak olaylarıyla (Question, Grounding, Exploration, Synthesis aşamaları) akışla gönderen `question_explainable()` modunu ekledi. + +### `tg-invoke-agent` + +**Açıklanabilirlik desteği**: Ajan yürütülmesi sırasında kaynak olaylarını yerleşik olarak gösteren `question_explainable()` modunu ekledi (Question, Analysis, Conclusion, AgentThought, AgentObservation, AgentAnswer). +Ayrıntılı mod, düşünce/gözlem akışlarını emoji ön ekleriyle gösterir. + +### `tg-show-graph` + +**Akış modu**: Daha düşük ilk sonuç süresi ve azaltılmış bellek yükü için yapılandırılabilir toplu boyutlarla `triples_query_stream()`'ı kullanır. +**Adlandırılmış grafik desteği**: Yeni `--graph` filtre seçeneği. Adlandırılmış grafikleri tanır: + Varsayılan grafik (boş): Temel bilgi gerçekleri + `urn:graph:source`: Çıkarma kaynağı + `urn:graph:retrieval`: Sorgu zamanı açıklanabilirliği +**Grafik sütununu göster**: Her üçlü için adlandırılmış grafiği görüntülemek için yeni `--show-graph` bayrağı. +**Yapılandırılabilir sınırlar**: Yeni `--limit` ve `--batch-size` seçenekleri. + +### `tg-graph-to-turtle` + +**RDF-star desteği**: Artık tırnaklı üçlüleri (RDF-star yeniden yapılandırması) işler. +**Akış modu**: Daha düşük ilk işleme süresi için akışı kullanır. +**Tel formatı işleme**: IRIs için `{"t": "i", "i": uri}`, literal'lar için `{"t": "l", "v": value}` ve tırnaklı üçlüler için `{"t": "r", "r": {...}}` kullanan yeni terim tel formatını kullanmak üzere güncellendi. +**Adlandırılmış grafik desteği**: Yeni `--graph` filtre seçeneği. + +### `tg-set-tool` + +**Yeni araç türü**: Yapılandırılmış veri dizinlerinde semantik arama için `row-embeddings-query`. +**Yeni seçenekler**: Satır gömme sorgu araçlarını yapılandırmak için `--schema-name`, `--index-name`, `--limit`. + +### `tg-show-tools` + +`schema-name`, `index-name` ve `limit` alanlarıyla yeni `row-embeddings-query` araç türünü görüntüler. + +### `tg-load-knowledge` + +**İlerleme raporlama**: Her dosya ve toplamda yüklenen üçlü ve varlık bağlamlarının sayısını sayar ve raporlar. +**Terim formatı güncellemesi**: Varlık bağlamları artık eski Değer formatının (`{"v": entity, "e": True}`) yerine yeni Terim formatını (`{"t": "i", "i": uri}`) kullanır. + +-- + +## Uyumluluk Sorunları + +**Terminoloji yeniden adlandırması**: `Value` şeması, sistem genelinde `Term` olarak yeniden adlandırıldı (PR #622). Bu, grafik deposuyla etkileşimde bulunan CLI araçları tarafından kullanılan tel formatını etkiler. Yeni format, eski `{"v": ..., "e": ...}` formatının yerini alarak IRIs için `{"t": "i", "i": uri}` ve literal'lar için `{"t": "l", "v": value}` kullanır. +`tg-invoke-objects-query` yeniden adlandırıldı `tg-invoke-rows-query`. +`tg-load-pdf` ve `tg-load-text` kaldırıldı. diff --git a/docs/cli-changes-v1.8-to-v2.1.zh-cn.md b/docs/cli-changes-v1.8-to-v2.1.zh-cn.md new file mode 100644 index 00000000..661082fc --- /dev/null +++ b/docs/cli-changes-v1.8-to-v2.1.zh-cn.md @@ -0,0 +1,119 @@ +--- +layout: default +title: "CLI 修改:v1.8 到 v2.1" +parent: "Chinese (Beta)" +--- + +# CLI 修改:v1.8 到 v2.1 + +> **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-cli`) 包含大量新增功能,主要集中在以下三个方面: +**可解释性/来源追溯**, **嵌入式访问**, 和 **图查询**。 +移除两个旧工具,一个重命名,并且多个现有工具获得了新的功能。 + +--- + +## 新的 CLI 工具 + +### 可解释性 & 来源追溯 + +| 命令 | 描述 | +|---------|-------------| +| `tg-list-explain-traces` | 列出集合中所有 Explain 实例(GraphRAG 和 Agent),显示实例 ID、类型、问题文本和时间戳。 | +| `tg-show-explain-trace` | 显示 Explain 实例的完整追溯信息。 对于 GraphRAG:问题、探索、聚焦、合成阶段。 对于 Agent:会话、迭代(思考/行动/观察)、最终答案。 自动检测追溯类型。 支持 `--show-provenance` 选项,用于追溯边缘到源文档。 | +| `tg-show-extraction-provenance` | 给出文档 ID,遍历来源链:文档 -> 页面 -> 块 -> 边缘,使用 `prov:wasDerivedFrom` 关系。 支持 `--show-content` 和 `--max-content` 选项。 | + +### 嵌入式 + +| 命令 | 描述 | +|---------|-------------| +| `tg-invoke-embeddings` | 通过嵌入服务将文本转换为向量嵌入。 接受一个或多个文本输入,返回向量为浮点数的列表。 | +| `tg-invoke-graph-embeddings` | 使用向量嵌入根据文本相似性查询图实体。 返回匹配的实体以及相似度得分。 | +| `tg-invoke-document-embeddings` | 使用向量嵌入根据文本相似性查询文档块。 返回匹配的块 ID 以及相似度得分。 | +| `tg-invoke-row-embeddings` | 使用在索引字段上进行的文本相似性查询,查询结构化数据行。 返回与索引值和得分匹配的行。 需要 `--schema-name` 且支持 `--index-name`。 | + +### 图查询 + +| 命令 | 描述 | +|---------|-------------| +| `tg-query-graph` | 基于模式的图存储查询。 与 `tg-show-graph` 不同(它会显示所有内容),这允许通过任何组合的子句、谓词、对象和图进行选择性查询。 自动检测值类型:IRI (`http://...`, `urn:...`, `<...>`)、带有引号的三重 (`<>`) 和字面量。 | +| `tg-get-document-content` | 从库中通过文档 ID 获取文档内容。 可以输出到文件或 stdout,支持文本和二进制内容。 | + +--- + +## 已移除的 CLI 工具 + +| 命令 | 备注 | +|---------|-------| +| `tg-load-pdf` | 已移除。 文档加载现在通过库/处理流程进行。 | +| `tg-load-text` | 已移除。 文档加载现在通过库/处理流程进行。 | + +--- + +## 重命名后的 CLI 工具 + +| 旧名称 | 新名称 | 备注 | +|----------|----------|-------| +| `tg-invoke-objects-query` | `tg-invoke-rows-query` | 反映了从 "对象" 到 "行" 的术语重命名,用于结构化数据。 | + +--- + +## 现有工具的重要变更 + +### `tg-invoke-graph-rag` + +- **可解释性支持**: 现在支持 4 阶段的可解释性管道(问题、基础/探索、聚焦、合成),并显示内联来源事件。 +- **流式传输**: 使用 WebSocket 流式传输实现实时输出。 +- **来源追溯**: 可以通过重构和 `prov:wasDerivedFrom` 链,追溯选定的边缘回源文档。 +- 从约 30 行增长到约 760 行,以适应完整的可解释性管道。 + +### `tg-invoke-document-rag` + +- **可解释性支持**: 添加了 `question_explainable()` 模式,可以流式传输带有内联来源事件的文档 RAG 响应(问题、基础、探索、合成阶段)。 + +### `tg-invoke-agent` + +- **可解释性支持**: 添加了 `question_explainable()` 模式,在执行代理时显示内联来源事件(问题、分析、结论、AgentThought、AgentObservation、AgentAnswer)。 +- 详细模式显示了带有表情符号前缀的思考/观察流。 + +### `tg-show-graph` + +- **流式传输模式**: 现在使用 `triples_query_stream()` 与可配置的批次大小,实现更快的首次结果时间和减少内存开销。 +- **命名图支持**: 新的 `--graph` 过滤选项。 识别命名图: + - 默认图 (空): 核心知识的事实 + - `urn:graph:source`: 提取来源 + - `urn:graph:retrieval`: 查询时追溯 +- **显示图列**: 新的 `--show-graph` 标志,显示每个三元组的命名图。 +- **可配置的限制**: 新的 `--limit` 和 `--batch-size` 选项。 + +### `tg-graph-to-turtle` + +- **RDF-star 支持**: 现在可以处理带有引号的三元 (`RDF-star reification`)。 +- **流式传输模式**: 使用流式传输实现更快的首次处理时间。 +- **Wire 格式处理**: 已更新为使用新的 wire 格式 (`{"t": "i", "i": uri}` 用于 IRI,`{"t": "l", "v": value}` 用于字面量,`{"t": "r", "r": {...}}` 用于带有引号的三元),代替旧的 `{"v": ..., "e": ...}` 格式。 +- **命名图支持**: 新的 `--graph` 过滤选项。 + +### `tg-set-tool` + +- **新的工具类型**: `row-embeddings-query` 用于在结构化数据索引上进行语义搜索。 +- **新的选项**: `--schema-name`, `--index-name`, `--limit` 用于配置 `row-embeddings-query` 工具。 + +### `tg-show-tools` + +- 显示新的 `row-embeddings-query` 工具类型及其 `schema-name`、`index-name` 和 `limit` 字段。 + +### `tg-load-knowledge` + +- **进度报告**: 现在统计并报告每个文件的加载三元和实体上下文的数量,以及总数。 +- **术语格式更新**: 实体上下文现在使用新的术语格式 (`{"t": "i", "i": uri}`) 代替旧的 Value 格式 (`{"v": entity, "e": True}`)。 + +--- + +## 破坏性变更 + +- **术语重命名**: `Value` 模式已重命名为 `Term`,该重命名影响了与图存储交互的 CLI 工具。 新格式使用 `{"t": "i", "i": uri}` 用于 IRI,`{"t": "l", "v": value}` 用于字面量,代替旧的 `{"v": ..., "e": ...}` 格式。 +- **`tg-invoke-objects-query` 重命名**为 `tg-invoke-rows-query`。 +- **`tg-load-pdf` 和 `tg-load-text` 已移除**。 diff --git a/docs/contributor-licence-agreement.ar.md b/docs/contributor-licence-agreement.ar.md new file mode 100644 index 00000000..c8385416 --- /dev/null +++ b/docs/contributor-licence-agreement.ar.md @@ -0,0 +1,16 @@ +--- +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 ترخيصًا دائمًا، وخاليًا من الرسوم، لتوزيع مساهمتك بموجب ترخيص [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) الخاص بالمشروع، وتؤكد أن لديك الحق في تقديم المساهمة. وهذا يحمي المشروع ومستخدميه من خلال ضمان أن لكل مساهمة الأساس القانوني الواضح. + +عندما تفتح طلب سحب، سيقوم روبوت اتفاقية الترخيص بنشر تعليق يطلب منك مراجعة وتوقيع الاتفاقية المناسبة - ويستغرق ذلك لحظة فقط، وعليك القيام بذلك مرة واحدة فقط عبر جميع مستودعات TrustGraph. + +- المساهمة ك**فرد**؟ قم بتوقيع [اتفاقية الترخيص الفردية](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +- المساهمة **بالنيابة عن شركة أو منظمة**؟ قم بتوقيع [اتفاقية الترخيص التنظيمية](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/contributor-licence-agreement.es.md b/docs/contributor-licence-agreement.es.md new file mode 100644 index 00000000..208b9957 --- /dev/null +++ b/docs/contributor-licence-agreement.es.md @@ -0,0 +1,16 @@ +--- +layout: default +title: "Acuerdo de Licencia para Contribuyentes" +parent: "Spanish (Beta)" +--- + +# Acuerdo de Licencia para Contribuyentes + +> **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. + +Solicitamos que todos los contribuyentes firmen un Acuerdo de Licencia para Contribuyentes antes de que podamos fusionar una solicitud de extracción. El acuerdo **no** transfiere la propiedad del copyright; usted mantiene la propiedad total de su trabajo. Simplemente otorga al proyecto TrustGraph una licencia perpetua, sin regalías, para distribuir su contribución bajo la licencia [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0), y confirma que tiene el derecho de hacer la contribución. Esto protege tanto al proyecto como a sus usuarios, garantizando que cada contribución tenga una base legal clara. + +Cuando abra una solicitud de extracción, el bot de CLA publicará un comentario solicitándole que revise y firme el acuerdo correspondiente; solo requiere un momento y solo necesita hacerlo una vez en todos los repositorios de TrustGraph. + +- ¿Contribuyendo como **individuo**? Firme el [Acuerdo de Licencia para Contribuyentes Individual](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +- ¿Contribuyendo en nombre de una **empresa o organización**? Firme el [Acuerdo de Licencia para Contribuyentes de Entidad](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/contributor-licence-agreement.he.md b/docs/contributor-licence-agreement.he.md new file mode 100644 index 00000000..182ccc47 --- /dev/null +++ b/docs/contributor-licence-agreement.he.md @@ -0,0 +1,16 @@ +--- +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 רישיון נצחי, ללא תמלוגים, להפצת התרומה שלכם על פי הרישיון [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0), וכן מאשר שאתם רשאים להעביר את התרומה. זה מגן הן על הפרויקט והן על המשתמשים שלו, על ידי הבטחת שכל תרומה תהיה בעלת בסיס משפטי ברור. + +כשאתם פותחים בקשת פול, בוט ה-CLA יפרסם הערה המבקש מכם לבדוק ולחתום על ההסכם המתאים – זה לוקח רק רגע, ואתם צריכים לעשות זאת רק פעם אחת בכל מאגרי ה-TrustGraph. + +- תורמים כ**אינדיבידואל**? חתמו על [הסכם רישיון אינדיבידואלי](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +- תורמים **מטעמ חברה או ארגון**? חתמו על [הסכם רישיון עבור ארגון](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/contributor-licence-agreement.hi.md b/docs/contributor-licence-agreement.hi.md new file mode 100644 index 00000000..88dab727 --- /dev/null +++ b/docs/contributor-licence-agreement.hi.md @@ -0,0 +1,24 @@ +--- +layout: default +title: "योगदानकर्ता लाइसेंस समझौता (CLA)" +parent: "Hindi (Beta)" +--- + +**महत्वपूर्ण निर्देश:** + +- सभी Markdown फॉर्मेटिंग, हेडर, लिंक और HTML टैग को बनाए रखें। +- बैक टिक (` `) या कोड ब्लॉक के अंदर मौजूद कोड का अनुवाद न करें। +- केवल अनुवादित टेक्स्ट को ही आउटपुट करें, जिसमें कोई भी प्रारंभिक या स्पष्टीकरण शामिल न हों। + +अनुवाद करने के लिए पाठ: + +# योगदानकर्ता लाइसेंस समझौता (CLA) + +> **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. + +हम हर योगदानकर्ता से एक योगदानकर्ता लाइसेंस समझौते पर हस्ताक्षर करने का अनुरोध करते हैं, इससे पहले कि हम किसी पुल अनुरोध को मर्ज कर सकें। CLA कॉपीराइट को **नहीं** हस्तांतरित करता है — आप अपने कार्य का पूर्ण स्वामित्व बनाए रखते हैं। यह केवल TrustGraph परियोजना को आपके योगदान को परियोजना के [Apache 2.0 लाइसेंस](https://www.apache.org/licenses/LICENSE-2.0) के तहत वितरित करने का एक स्थायी, रॉयल्टी-मुक्त लाइसेंस प्रदान करता है, और यह पुष्टि करता है कि आपके पास योगदान करने का अधिकार है। यह परियोजना और उसके उपयोगकर्ताओं दोनों की रक्षा करता है, यह सुनिश्चित करके कि प्रत्येक योगदान का एक स्पष्ट कानूनी आधार है। + +जब आप एक पुल अनुरोध खोलते हैं, तो CLA बॉट आपसे उचित समझौते की समीक्षा और हस्ताक्षर करने के लिए एक टिप्पणी पोस्ट करेगा - इसमें केवल एक पल लगता है और आपको इसे ट्रस्टग्राफ रिपॉजिटरी के सभी में केवल एक बार करने की आवश्यकता है। + +- एक **व्यक्ति** के रूप में योगदान कर रहे हैं? [व्यक्तिगत CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) पर हस्ताक्षर करें। +- एक **कंपनी या संगठन** की ओर से योगदान कर रहे हैं? [कंपनी CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) पर हस्ताक्षर करें। diff --git a/docs/contributor-licence-agreement.md b/docs/contributor-licence-agreement.md index 48314516..7d247116 100644 --- a/docs/contributor-licence-agreement.md +++ b/docs/contributor-licence-agreement.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Contributor Licence Agreement (CLA)" +nav_order: 4 +--- + # Contributor Licence Agreement (CLA) We ask every contributor to sign a Contributor Licence Agreement before @@ -16,4 +22,3 @@ and you only need to do it once across all TrustGraph repositories. - Contributing as an **individual**? Sign the [Individual CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) - Contributing on behalf of a **company or organisation**? Sign the [Entity CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) - diff --git a/docs/contributor-licence-agreement.pt.md b/docs/contributor-licence-agreement.pt.md new file mode 100644 index 00000000..f3a39fc7 --- /dev/null +++ b/docs/contributor-licence-agreement.pt.md @@ -0,0 +1,26 @@ +--- +layout: default +title: "Acordo de Licença para Contribuintes (CLA)" +parent: "Portuguese (Beta)" +--- + +# Acordo de Licença para Contribuintes (CLA) + +> **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. + +Pedimos a cada contribuinte que assine um Acordo de Licença para Contribuintes antes +que possamos mesclar um pull request. O CLA não transfere os direitos autorais — +você mantém a propriedade total do seu trabalho. Ele simplesmente concede ao projeto TrustGraph +uma licença perpétua e sem royalties para distribuir sua +contribuição sob a licença +[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) do projeto, e +confirma que você tem o direito de fazer a contribuição. Isso protege +tanto o projeto quanto seus usuários, garantindo que cada contribuição tenha +uma base legal clara. + +Quando você abre um pull request, o bot do CLA postará um comentário pedindo que você +revise e assine o acordo apropriado — leva apenas um momento +e você só precisa fazer isso uma vez em todos os repositórios do TrustGraph. + +Contribuindo como um **indivíduo**? Assine o [CLA Individual](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +Contribuindo em nome de uma **empresa ou organização**? Assine o [CLA para Entidades](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/contributor-licence-agreement.ru.md b/docs/contributor-licence-agreement.ru.md new file mode 100644 index 00000000..be047f66 --- /dev/null +++ b/docs/contributor-licence-agreement.ru.md @@ -0,0 +1,16 @@ +--- +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 пожизненную, без роялти лицензию на распространение вашего вклада в соответствии с лицензией [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0), а также подтверждает, что у вас есть право внести вклад. Это защищает как проект, так и его пользователей, обеспечивая, чтобы каждый вклад имел четкое юридическое обоснование. + +Когда вы создаёте запрос на слияние, бот CLA опубликует комментарий, в котором попросит вас ознакомиться и подписать соответствующий договор — это занимает всего несколько минут, и вам нужно сделать это только один раз для всех репозиториев TrustGraph. + +- Вклад в качестве **индивидуального** участника? Подпишите [Индивидуальный договор лицензии](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +- Вклад от имени **компании или организации**? Подпишите [Организационный договор лицензии](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/contributor-licence-agreement.sw.md b/docs/contributor-licence-agreement.sw.md new file mode 100644 index 00000000..6e6ebe46 --- /dev/null +++ b/docs/contributor-licence-agreement.sw.md @@ -0,0 +1,24 @@ +--- +layout: default +title: "Mkataba wa Lisensi wa Mhudumu (CLA)" +parent: "Swahili (Beta)" +--- + +**MAELEZI MUHIMU:** +- Hifadhi KILA muundo wa Markdown, vichwa, viungo, na lebo za HTML. +- EISIUSHA kutafsiri kodio iliyo ndani ya leseni (`code`) au katika blok za kodio. +- Toa TU matini iliyotafsiri bila maelezo au utangulizi. + +Matini ya kutafsiri: +# Mkataba wa Lisensi wa Mhudumu (CLA) + +> **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. + +Tunatoa ombi kwa kila mhudumu kusaini Mkataba wa Lisensi wa Mhudumu kabla +tunaweza kuingiza ombi la "pull". Mkataba huu **sisi** huhamisha haki za udani — +unaendelea kuwa mmiliki kamili wa kazi yako. Hii kwa upande wake huipa Mradi wa TrustGraph lisensi ya kudumu, bila malipo, ya kusambaza mchango wako chini ya lisensi ya [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0), na ina hakikisha kuwa una haki ya kufanya mchango. Hii inalinda kila mmoja, mradi na watumiaji, kwa kuhakikisha kwamba kila mchango una msingi wa kisheria. + +Unapouingiza ombi la "pull", bot ya CLA italeta maoni ya kukuelekeza kukagua na kusaini mkataba unaofaa— hili lina kuchukua tu dakika nadra, na unahitaji kufanya hivyo mara moja kwenye lahat ya TrustGraph. + +- Kichango kama **mshiriki binafsi**? Saini [Mkataba wa Lisensi wa Mshiriki](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +- Kichango kwa niaba ya **kampuni au shirika**? Saini [Mkataba wa Lisensi wa Shirika](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/contributor-licence-agreement.tr.md b/docs/contributor-licence-agreement.tr.md new file mode 100644 index 00000000..d10ee8f9 --- /dev/null +++ b/docs/contributor-licence-agreement.tr.md @@ -0,0 +1,26 @@ +--- +layout: default +title: "Katkıda Bulunanlar Lisans Sözleşmesi (KBL)" +parent: "Turkish (Beta)" +--- + +# Katkıda Bulunanlar Lisans Sözleşmesi (KBL) + +> **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. + +Her katkıda bulunan kişiden, bir çekme isteğini (pull request) birleştirmeden önce, bir Katkıda Bulunan Lisans Sözleşmesi (Contributor Licence Agreement) imzalamasını rica ediyoruz. +CLA, telif hakkını devretmez; +siz, yaptığınız işin tam mülkiyetini koruyorsunuz. Sadece TrustGraph +projesine, katkınızı projenin +altında dağıtmak için kalıcı, telifsiz bir lisans verir. +[Apache 2.0 lisansı](https://www.apache.org/licenses/LICENSE-2.0) ve +katkıyı yapma hakkınız olduğunu teyit eder. Bu, her katkının açık bir yasal temele sahip olmasını sağlayarak hem projeyi hem de kullanıcılarını korur. + + + +Bir çekme isteği (pull request) açtığınızda, CLA bot'u size uygun sözleşmeyi incelemeniz ve imzalamanız için bir yorum yayınlayacaktır; bu sadece birkaç dakika sürer. +Ve bunu yalnızca TrustGraph'taki tüm depolarda bir kez yapmanız gerekir. + + +**Bireysel** olarak katkıda bulunuyor musunuz? [Bireysel CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) sözleşmesini imzalayın. +Bir **şirket veya kuruluş** adına katkıda bulunuyor musunuz? [Kuruluş CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) sözleşmesini imzalayın. diff --git a/docs/contributor-licence-agreement.zh-cn.md b/docs/contributor-licence-agreement.zh-cn.md new file mode 100644 index 00000000..94c29ce1 --- /dev/null +++ b/docs/contributor-licence-agreement.zh-cn.md @@ -0,0 +1,16 @@ +--- +layout: default +title: "贡献者许可协议 (CLA)" +parent: "Chinese (Beta)" +--- + +# 贡献者许可协议 (CLA) + +> **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 项目一项永久、免版税的使用许可,以在项目的 [Apache 2.0 许可](https://www.apache.org/licenses/LICENSE-2.0) 下分发您的贡献,并确认您有权进行贡献。这既保护了项目本身,也保护了其用户,确保每个贡献都有明确的法律依据。 + +当您提交拉取请求时,CLA 机器人会发布一条评论,要求您审查并签署相应的协议——这只需要几秒钟,您只需要在所有 TrustGraph 仓库中执行一次。 + +- 作为**个人**贡献?请签署 [个人 CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Fiduciary-Contributor-License-Agreement.md) +- 代表**公司或组织**贡献?请签署 [实体 CLA](https://github.com/trustgraph-ai/contributor-license-agreement/blob/main/Entity-Fiduciary-Contributor-License-Agreement.md) diff --git a/docs/lang-index-ar.md b/docs/lang-index-ar.md new file mode 100644 index 00000000..e560ca4f --- /dev/null +++ b/docs/lang-index-ar.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Arabic (Beta)" +has_children: true +nav_order: 99 +--- + +# Arabic (Beta) Documentation + +> **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. diff --git a/docs/lang-index-es.md b/docs/lang-index-es.md new file mode 100644 index 00000000..ef9a51e9 --- /dev/null +++ b/docs/lang-index-es.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Spanish (Beta)" +has_children: true +nav_order: 99 +--- + +# Spanish (Beta) Documentation + +> **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. diff --git a/docs/lang-index-he.md b/docs/lang-index-he.md new file mode 100644 index 00000000..3e6e1cba --- /dev/null +++ b/docs/lang-index-he.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Hebrew (Beta)" +has_children: true +nav_order: 99 +--- + +# Hebrew (Beta) Documentation + +> **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. diff --git a/docs/lang-index-hi.md b/docs/lang-index-hi.md new file mode 100644 index 00000000..cc1d3fa3 --- /dev/null +++ b/docs/lang-index-hi.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Hindi (Beta)" +has_children: true +nav_order: 99 +--- + +# Hindi (Beta) Documentation + +> **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. diff --git a/docs/lang-index-pt.md b/docs/lang-index-pt.md new file mode 100644 index 00000000..b146d03e --- /dev/null +++ b/docs/lang-index-pt.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Portuguese (Beta)" +has_children: true +nav_order: 99 +--- + +# Portuguese (Beta) Documentation + +> **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. diff --git a/docs/lang-index-ru.md b/docs/lang-index-ru.md new file mode 100644 index 00000000..d456fc65 --- /dev/null +++ b/docs/lang-index-ru.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Russian (Beta)" +has_children: true +nav_order: 99 +--- + +# Russian (Beta) Documentation + +> **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. diff --git a/docs/lang-index-sw.md b/docs/lang-index-sw.md new file mode 100644 index 00000000..a5178afa --- /dev/null +++ b/docs/lang-index-sw.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Swahili (Beta)" +has_children: true +nav_order: 99 +--- + +# Swahili (Beta) Documentation + +> **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. diff --git a/docs/lang-index-tr.md b/docs/lang-index-tr.md new file mode 100644 index 00000000..c1458416 --- /dev/null +++ b/docs/lang-index-tr.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Turkish (Beta)" +has_children: true +nav_order: 99 +--- + +# Turkish (Beta) Documentation + +> **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. diff --git a/docs/lang-index-zh-cn.md b/docs/lang-index-zh-cn.md new file mode 100644 index 00000000..5c9c3889 --- /dev/null +++ b/docs/lang-index-zh-cn.md @@ -0,0 +1,10 @@ +--- +layout: default +title: "Chinese (Beta)" +has_children: true +nav_order: 99 +--- + +# Chinese (Beta) Documentation + +> **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. diff --git a/docs/python-api.ar.md b/docs/python-api.ar.md new file mode 100644 index 00000000..0d534502 --- /dev/null +++ b/docs/python-api.ar.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "مرجع واجهة برمجة التطبيقات (API) الخاصة بـ TrustGraph بلغة بايثون." +parent: "Arabic (Beta)" +--- + +# مرجع واجهة برمجة التطبيقات (API) الخاصة بـ TrustGraph بلغة بايثون. + +> **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. + +## التثبيت + +```bash +pip install trustgraph +``` + +## البدء السريع + +يتم استيراد جميع الفئات والأنواع من الحزمة `trustgraph.api`: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## جدول المحتويات + +### الأساس + +[Api](#api) + +### عملاء التدفق + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### عملاء WebSocket + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### العمليات المجمعة + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### المقاييس + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### أنواع البيانات + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### الاستثناءات + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +عميل واجهة برمجة التطبيقات (API) الرئيسي لـ TrustGraph للعمليات المتزامنة وغير المتزامنة. + +توفر هذه الفئة الوصول إلى جميع خدمات TrustGraph بما في ذلك إدارة التدفق، +وعمليات الرسم البياني المعرفي، ومعالجة المستندات، واستعلامات RAG، والمزيد. وهي تدعم +أنماط الاتصال القائمة على REST والقائمة على WebSocket. + +يمكن استخدام العميل كمدير سياق للتنظيف التلقائي للموارد: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### الطرق + +### `__aenter__(self)` + +أدخل مدير السياق غير المتزامن. + +### `__aexit__(self, *args)` + +اخرج من مدير السياق غير المتزامن وأغلق الاتصالات. + +### `__enter__(self)` + +أدخل مدير السياق المتزامن. + +### `__exit__(self, *args)` + +اخرج من مدير السياق المتزامن وأغلق الاتصالات. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +تهيئة عميل واجهة برمجة تطبيقات TrustGraph. + +**الوسائط:** + +`url`: عنوان URL الأساسي لواجهة برمجة تطبيقات TrustGraph (الافتراضي: "http://localhost:8088/"") +`timeout`: المهلة الزمنية للطلبات بالثواني (الافتراضي: 60) +`token`: رمز مميز اختياري للمصادقة + +**مثال:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +إغلاق جميع اتصالات العميل غير المتزامنة. + +تقوم هذه الطريقة بإغلاق اتصالات WebSocket غير المتزامنة، والعمليات المجمعة، واتصالات التدفق. +يتم استدعاؤها تلقائيًا عند الخروج من مدير السياق غير المتزامن. + +**مثال:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +احصل على عميل لعمليات مجمعة غير متزامنة. + +يوفر عمليات استيراد وتصدير مجمعة بنمط async/await عبر WebSocket +للتعامل بكفاءة مع مجموعات البيانات الكبيرة. + +**المرتجعات:** AsyncBulkClient: عميل للعمليات المجمعة غير المتزامنة. + +**مثال:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +احصل على عميل تدفق قائم على REST غير متزامن. + +يوفر وصولاً بنمط async/await إلى عمليات التدفق. هذا هو الخيار المفضل +لتطبيقات وأطر عمل Python غير المتزامنة (FastAPI، aiohttp، إلخ). + +**المرتجعات:** AsyncFlow: عميل تدفق غير متزامن + +**مثال:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +احصل على عميل مقاييس غير متزامن. + +يوفر وصولاً بنمط async/await إلى مقاييس Prometheus. + +**المرتجعات:** AsyncMetrics: عميل مقاييس غير متزامن. + +**مثال:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +احصل على عميل WebSocket غير متزامن لعمليات البث. + +يوفر وصول WebSocket بنمط async/await مع دعم البث. +هذه هي الطريقة المفضلة للبث غير المتزامن في Python. + +**المرتجعات:** AsyncSocketClient: عميل WebSocket غير متزامن. + +**مثال:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +احصل على عميل لعمليات مجمعة متزامنة للاستيراد/التصدير. + +تسمح العمليات المجمعة بنقل فعال لمجموعات بيانات كبيرة عبر اتصالات WebSocket، بما في ذلك الثلاثيات، والتضمينات، وسياقات الكيانات، والكائنات. + +**الإرجاع:** BulkClient: عميل للعمليات المجمعة المتزامنة. + +**مثال:** + + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +إغلاق جميع اتصالات العملاء المتزامنة. + +تقوم هذه الطريقة بإغلاق اتصالات WebSocket والعمليات المجمعة. +يتم استدعاؤها تلقائيًا عند الخروج من مدير السياق. + +**مثال:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +احصل على عميل المجموعة لإدارة مجموعات البيانات. + +تقوم المجموعات بتنظيم المستندات وبيانات الرسم البياني المعرفي في +تجمعات منطقية للعزل والتحكم في الوصول. + +**الإرجاع:** Collection: عميل إدارة المجموعة. + +**مثال:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +احصل على عميل إعدادات لتنظيم إعدادات التكوين. + +**المرتجعات:** Config: عميل إدارة التكوين. + +**مثال:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +احصل على عميل Flow لإدارة والتفاعل مع التدفقات. + +التدفقات هي الوحدات الأساسية للتنفيذ في TrustGraph، وتوفر الوصول إلى +الخدمات مثل الوكلاء، واستعلامات RAG، والتضمينات، ومعالجة المستندات. + +**الإرجاع:** Flow: عميل إدارة التدفق. + +**مثال:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +احصل على عميل Knowledge لإدارة نوى الرسم البياني للمعرفة. + +**المرتجعات:** عميل إدارة الرسم البياني للمعرفة: Knowledge + +**مثال:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +احصل على عميل مكتبة لإدارة المستندات. + +توفر المكتبة تخزين المستندات، وإدارة البيانات الوصفية، و +تنسيق سير العمل للمعالجة. + +**المرتجعات:** Library: عميل إدارة مكتبة المستندات. + +**مثال:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +احصل على عميل مقاييس متزامن للمراقبة. + +يسترجع مقاييس بتنسيق Prometheus من خدمة TrustGraph +للمراقبة والرؤية. + +**الإرجاع:** المقاييس: عميل المقاييس المتزامن + +**مثال:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +إجراء طلب واجهة برمجة تطبيقات REST منخفض المستوى. + +هذه الطريقة مخصصة بشكل أساسي للاستخدام الداخلي ولكن يمكن استخدامها للوصول المباشر إلى +واجهة برمجة التطبيقات عند الحاجة. + +**الوسائط:** + +`path`: مسار نقطة نهاية واجهة برمجة التطبيقات (بالنسبة لعنوان URL الأساسي) +`request`: حمولة الطلب كقاموس + +**الإرجاع:** dict: كائن الاستجابة + +**يُثير:** + +`ProtocolException`: إذا لم يكن رمز حالة الاستجابة 200 أو إذا لم تكن الاستجابة بتنسيق JSON +`ApplicationException`: إذا احتوت الاستجابة على خطأ + +**مثال:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +احصل على عميل WebSocket متزامن لعمليات البث. + +توفر اتصالات WebSocket دعمًا للبث لعمليات الاستجابة في الوقت الفعلي +من الوكلاء، واستعلامات RAG، وإكمال النصوص. تُرجع هذه الطريقة غلافًا متزامنًا +حول بروتوكول WebSocket. + +**الإرجاع:** SocketClient: عميل WebSocket متزامن. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +عميل إدارة التدفق للعمليات المتعلقة بقوالب التدفق ومثيلات التدفق. + +توفر هذه الفئة طرقًا لإدارة قوالب التدفق (القوالب) و +مثيلات التدفق (التدفقات قيد التشغيل). تحدد القوالب الهيكل و +معلمات التدفقات، بينما تمثل المثيلات التدفقات النشطة التي يمكن +أن تنفذ الخدمات. + +### الطرق + +### `__init__(self, api)` + +تهيئة عميل التدفق. + +**الوسائط:** + +`api`: مثيل واجهة برمجة التطبيقات (API) الأب لإجراء الطلبات. + +### `delete_blueprint(self, blueprint_name)` + +حذف قالب تدفق. + +**الوسائط:** + +`blueprint_name`: اسم القالب المراد حذفه. + +**مثال:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +الحصول على تعريف لمثيل عملية قيد التشغيل. + +**الوسائط:** + +`id`: معرف مثيل العملية + +**الإرجاع:** قاموس: تعريف مثيل العملية + +**مثال:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +الحصول على تعريف مخطط تدفق بالاسم. + +**الوسائط:** + +`blueprint_name`: اسم المخطط المراد استرجاعه. + +**الإرجاع:** قاموس: تعريف المخطط كقاموس. + +**مثال:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +الحصول على مثيل تدفق لتنفيذ العمليات على تدفق معين. + +**الوسائط:** + +`id`: مُعرّف التدفق (الافتراضي: "default") + +**الإرجاع:** FlowInstance: مثيل التدفق لعمليات الخدمة + +**مثال:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +عرض جميع مثيلات التدفق النشطة. + +**النتائج:** list[str]: قائمة بمعرفات مثيلات التدفق. + +**مثال:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +عرض جميع مخططات سير العمل المتاحة. + +**النتائج:** list[str]: قائمة بأسماء المخططات. + +**مثال:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +إنشاء أو تحديث مخطط سير العمل. + +**الوسائط:** + +`blueprint_name`: اسم للمخطط. +`definition`: قاموس تعريف المخطط. + +**مثال:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +إرسال طلب واجهة برمجة تطبيقات (API) ضمن نطاق التدفق. + +**الوسائط:** + +`path`: لاحقة مسار اختيارية لنقاط نهاية التدفق. +`request`: قاموس حمولة الطلب. + +**الإرجاع:** dict: كائن الاستجابة. + +**الاستثناءات:** + +`RuntimeError`: إذا لم يتم تحديد معلمة الطلب. + +### `start(self, blueprint_name, id, description, parameters=None)` + +بدء مثيل تدفق جديد من مخطط. + +**الوسائط:** + +`blueprint_name`: اسم المخطط المراد إنشاؤه. +`id`: معرف فريد لمثيل التدفق. +`description`: وصف يمكن قراءته بواسطة الإنسان. +`parameters`: قاموس اختياري للمعلمات. + +**مثال:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +إيقاف مثيل تدفق قيد التشغيل. + +**الوسائط:** + +`id`: معرف مثيل التدفق الذي سيتم إيقافه. + +**مثال:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +عميل مثيل التدفق لتنفيذ الخدمات في تدفق معين. + +توفر هذه الفئة الوصول إلى جميع خدمات TrustGraph بما في ذلك: +إكمال النص والتضمينات. +عمليات الوكيل مع إدارة الحالة. +استعلامات Graph و RAG للوثائق. +عمليات الرسم البياني المعرفي (ثلاثيات، كائنات). +تحميل الوثائق ومعالجتها. +تحويل اللغة الطبيعية إلى استعلام GraphQL. +تحليل البيانات المنظمة واكتشاف المخطط. +تنفيذ أداة MCP. +قالب المطالبات. + +يتم الوصول إلى الخدمات من خلال مثيل تدفق قيد التشغيل يتم تحديده بواسطة معرّف. + +### الطرق + +### `__init__(self, api, id)` + +تهيئة FlowInstance. + +**الوسائط:** + +`api`: عميل التدفق الرئيسي. +`id`: معرّف مثيل التدفق. + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +تنفيذ عملية وكيل مع قدرات الاستدلال واستخدام الأدوات. + +يمكن للوكلاء إجراء استدلال متعدد الخطوات، واستخدام الأدوات، والحفاظ على حالة المحادثة +عبر التفاعلات. هذه نسخة متزامنة وغير متدفقة. + +**الوسائط:** + +`question`: سؤال المستخدم أو التعليمات. +`user`: معرف المستخدم (افتراضي: "trustgraph"). +`state`: قاموس حالة اختياري للمحادثات التي تحتفظ بالحالة. +`group`: معرف مجموعة اختياري للسياقات متعددة المستخدمين. +`history`: سجل محادثة اختياري كقائمة من قواميس الرسائل. + +**الإرجاع:** str: إجابة الوكيل النهائية. + +**مثال:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +اكتشاف نوع البيانات لعينة بيانات منظمة. + +**الوسائط:** + +`sample`: عينة البيانات المراد تحليلها (محتوى نصي) + +**النتائج:** قاموس يحتوي على detected_type و confidence و بيانات وصفية اختيارية. + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +إجراء تشخيص بيانات مدمج: اكتشاف النوع وإنشاء وصف. + +**الوسائط:** + +`sample`: عينة البيانات المراد تحليلها (محتوى نصي) +`schema_name`: اسم المخطط المستهدف الاختياري لإنشاء الوصف. +`options`: معلمات اختيارية (مثل فاصل CSV). + +**النتائج:** قاموس يحتوي على detected_type و confidence و descriptor و بيانات وصفية. + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +الاستعلام عن أجزاء المستندات باستخدام التشابه الدلالي. + +يجد أجزاء المستندات التي يكون محتوىها متشابهًا دلاليًا مع +النص المدخل، باستخدام تضمينات المتجهات. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي. +`user`: معرف المستخدم/المساحة. +`collection`: معرف المجموعة. +`limit`: الحد الأقصى لعدد النتائج (افتراضي: 10). + +**النتائج:** قاموس: نتائج الاستعلام مع الأجزاء التي تحتوي على chunk_id و score. + +**مثال:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +تنفيذ استعلام استرجاع مُعزز بالبيانات (RAG) يعتمد على المستندات. + +يستخدم استرجاع البيانات المُعزز بالبيانات (RAG) تضمينات المتجهات للعثور على أجزاء المستندات ذات الصلة، +ثم يقوم بإنشاء استجابة باستخدام نموذج لغوي كبير (LLM) مع استخدام تلك الأجزاء كسياق. + +**الوسائط:** + +`query`: استعلام بلغة طبيعية. +`user`: مُعرّف المستخدم/مساحة المفاتيح (الافتراضي: "trustgraph"). +`collection`: مُعرّف المجموعة (الافتراضي: "default"). +`doc_limit`: الحد الأقصى لعدد أجزاء المستندات التي سيتم استرجاعها (الافتراضي: 10). + +**الإرجاع:** str: الاستجابة التي تم إنشاؤها والتي تتضمن سياق المستند. + +**مثال:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +توليد تضمينات متجهة لنص أو أكثر. + +تحويل النصوص إلى تمثيلات متجهة كثيفة مناسبة للبحث الدلالي +ومقارنة التشابه. + +**الوسائط:** + +`texts`: قائمة بالنصوص المدخلة المراد تضمينها. + +**النتائج:** list[list[list[float]]]: تضمينات متجهة، مجموعة واحدة لكل نص مدخل. + +**مثال:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +إنشاء وصف لربط البيانات المهيكلة بمخطط معين. + +**الوسائط:** + +`sample`: عينة البيانات لتحليلها (محتوى نصي) +`data_type`: نوع البيانات (csv، json، xml) +`schema_name`: اسم المخطط المستهدف لإنشاء الوصف +`options`: معلمات اختيارية (مثل فاصل CSV) + +**الإرجاع:** قاموس يحتوي على الوصف والبيانات الوصفية + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +الاستعلام عن كيانات الرسم البياني المعرفي باستخدام التشابه الدلالي. + +يجد الكيانات في الرسم البياني المعرفي والتي تكون أوصافها متشابهة دلاليًا +مع النص المدخل، باستخدام تضمينات المتجهات. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`user`: معرف المستخدم/المساحة +`collection`: معرف المجموعة +`limit`: الحد الأقصى لعدد النتائج (افتراضي: 10) + +**الإرجاع:** قاموس: نتائج الاستعلام مع الكيانات المشابهة + +**مثال:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +تنفيذ استعلام يعتمد على الرسم البياني لإنشاء استجابات مُعززة بالاسترجاع (RAG). + +يستخدم الرسم البياني RAG هيكل الرسم البياني للمعرفة للعثور على السياق ذي الصلة من خلال +استكشاف علاقات الكيانات، ثم يقوم بإنشاء استجابة باستخدام نموذج لغوي كبير (LLM). + +**الوسائط:** + +`query`: استعلام بلغة طبيعية. +`user`: مُعرّف المستخدم/مساحة المفاتيح (الافتراضي: "trustgraph"). +`collection`: مُعرّف المجموعة (الافتراضي: "default"). +`entity_limit`: الحد الأقصى للكيانات التي سيتم استرجاعها (الافتراضي: 50). +`triple_limit`: الحد الأقصى للثلاثيات لكل كيان (الافتراضي: 30). +`max_subgraph_size`: الحد الأقصى لإجمالي عدد الثلاثيات في الرسم البياني الفرعي (الافتراضي: 150). +`max_path_length`: الحد الأقصى لعمق الاستكشاف (الافتراضي: 2). + +**الإرجاع:** str: الاستجابة التي تم إنشاؤها والتي تتضمن سياق الرسم البياني. + +**مثال:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +تحميل مستند ثنائي للمعالجة. + +تحميل مستند (PDF، DOCX، صور، إلخ) لاستخراج ومعالجة +من خلال مسار المستند الخاص بالتدفق. + +**الوسائط:** + +`document`: محتوى المستند كبايت. +`id`: مُعرّف المستند الاختياري (يتم إنشاؤه تلقائيًا إذا كان فارغًا). +`metadata`: بيانات وصفية اختيارية (قائمة من الثلاثيات أو كائن مع طريقة الإرسال). +`user`: مُعرّف المستخدم/مساحة المفاتيح (اختياري). +`collection`: مُعرّف المجموعة (اختياري). + +**الإرجاع:** قاموس: استجابة المعالجة. + +**يُثير:** + +`RuntimeError`: إذا تم توفير البيانات الوصفية بدون مُعرّف. + +**مثال:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +تحميل محتوى نصي للمعالجة. + +تحميل محتوى نصي لاستخلاصه ومعالجته من خلال مسار المعالجة النصية. + + +**الوسائط:** + +`text`: محتوى نصي كبايت. +`id`: مُعرّف المستند الاختياري (يتم إنشاؤه تلقائيًا إذا كان فارغًا). +`metadata`: بيانات وصفية اختيارية (قائمة من الثلاثيات أو كائن مع طريقة الإرسال). +`charset`: ترميز الأحرف (افتراضي: "utf-8"). +`user`: مُعرّف المستخدم/مساحة المفاتيح (اختياري). +`collection`: مُعرّف المجموعة (اختياري). + +**الإرجاع:** قاموس: استجابة المعالجة. + +**الأخطاء:** + +`RuntimeError`: إذا تم توفير البيانات الوصفية بدون مُعرّف. + +**مثال:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +تنفيذ أداة بروتوكول سياق النموذج (MCP). + +توفر أدوات MCP وظائف قابلة للتوسيع للوكلاء وسير العمل، +مما يسمح بالتكامل مع الأنظمة والخدمات الخارجية. + +**الوسائط:** + +`name`: اسم/معرّف الأداة. +`parameters`: قاموس معلمات الأداة (الافتراضي: {}). + +**الإرجاع:** str أو dict: نتيجة تنفيذ الأداة. + +**يُثير:** + +`ProtocolException`: إذا كان تنسيق الاستجابة غير صالح. + +**مثال:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +تحويل سؤال بلغة طبيعية إلى استعلام GraphQL. + +**الوسائط:** + +`question`: سؤال بلغة طبيعية +`max_results`: الحد الأقصى لعدد النتائج المراد إرجاعها (افتراضي: 100) + +**الإرجاع:** قاموس يحتوي على graphql_query و variables و detected_schemas و confidence + +### `prompt(self, id, variables)` + +تنفيذ نموذج مطالبة مع استبدال المتغيرات. + +تسمح نماذج المطالبات بأنماط مطالبات قابلة لإعادة الاستخدام مع متغيرات ديناميكية +استبدال، وهو مفيد لهندسة المطالبات المتسقة. + +**الوسائط:** + +`id`: معرف نموذج المطالبة +`variables`: قاموس لتعيين اسم المتغير إلى القيمة + +**الإرجاع:** سلسلة أو قاموس: نتيجة المطالبة المعروضة (نص أو كائن منظم) + +**يسبب:** + +`ProtocolException`: إذا كان تنسيق الاستجابة غير صالح + +**مثال:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +قم بإنشاء طلب خدمة في هذه نسخة التدفق. + +**الوسائط:** + +`path`: مسار الخدمة (مثل: "service/text-completion") +`request`: قاموس حمولة الطلب + +**الإرجاع:** dict: استجابة الخدمة + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +استعلام عن بيانات الصفوف باستخدام التشابه الدلالي في الحقول المفهرسة. + +يجد الصفوف التي تكون فيها قيم الحقول المفهرسة متشابهة دلاليًا مع +النص المدخل، باستخدام تضمينات المتجهات. هذا يتيح المطابقة التقريبية/الدلالية +على البيانات المنظمة. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`schema_name`: اسم المخطط للبحث داخله +`user`: معرف المستخدم/مساحة المفاتيح (افتراضي: "trustgraph") +`collection`: معرف المجموعة (افتراضي: "default") +`index_name`: اسم الفهرس الاختياري لتصفية البحث في فهرس معين +`limit`: الحد الأقصى لعدد النتائج (افتراضي: 10) + +**الإرجاع:** dict: نتائج الاستعلام مع المطابقات التي تحتوي على index_name و index_value و text و score + +**مثال:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +تنفيذ استعلام GraphQL مقابل الصفوف المنظمة في الرسم البياني المعرفي. + +الاستعلام عن البيانات المنظمة باستخدام بناء جملة GraphQL، مما يسمح باستعلامات معقدة +مع التصفية والتجميع وتجاوز العلاقات. + +**الوسائط:** + +`query`: سلسلة استعلام GraphQL +`user`: معرف المستخدم/مساحة الاسم (الافتراضي: "trustgraph") +`collection`: معرف المجموعة (الافتراضي: "default") +`variables`: قاموس اختياري لمتغيرات الاستعلام +`operation_name`: اسم عملية اختياري للمستندات متعددة العمليات + +**الإرجاع:** dict: استجابة GraphQL مع حقول 'data' و 'errors' و/أو 'extensions' + +**يثير:** + +`ProtocolException`: إذا حدث خطأ على مستوى النظام + +**مثال:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +تحديد مخططات مطابقة لعينة بيانات باستخدام تحليل المطالبات. + +**الوسائط:** + +`sample`: عينة البيانات المراد تحليلها (محتوى نصي) +`options`: معلمات اختيارية + +**الإرجاع:** قاموس يحتوي على مصفوفة schema_matches والبيانات الوصفية. + +### `structured_query(self, question, user='trustgraph', collection='default')` + +تنفيذ سؤال بلغة طبيعية مقابل بيانات منظمة. +يجمع بين تحويل استعلام معالجة اللغة الطبيعية وتنفيذ GraphQL. + +**الوسائط:** + +`question`: سؤال بلغة طبيعية +`user`: معرف مساحة مفاتيح Cassandra (افتراضي: "trustgraph") +`collection`: معرف مجموعة البيانات (افتراضي: "default") + +**الإرجاع:** قاموس يحتوي على البيانات والأخطاء الاختيارية. + +### `text_completion(self, system, prompt)` + +تنفيذ إكمال نص باستخدام نموذج اللغة الكبير (LLM) الخاص بالتدفق. + +**الوسائط:** + +`system`: مطالبة النظام التي تحدد سلوك المساعد +`prompt`: مطالبة المستخدم/سؤال + +**الإرجاع:** نص: النص الذي تم إنشاؤه. + +**مثال:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +البحث في ثلاثيات الرسم البياني المعرفي باستخدام مطابقة الأنماط. + +تبحث عن ثلاثيات RDF تتطابق مع الموضوع والفاعل والمفعول به المحددة. تعمل المعلمات غير المحددة كرموز بدل. + + +**الوسائط:** + +`s`: معرف الموضوع (اختياري، استخدم None للرمز بدل) +`p`: معرف الفاعل (اختياري، استخدم None للرمز بدل) +`o`: معرف المفعول به أو حرفي (اختياري، استخدم None للرمز بدل) +`user`: معرف المستخدم/مساحة المفاتيح (اختياري) +`collection`: معرف المجموعة (اختياري) +`limit`: الحد الأقصى للنتائج المراد إرجاعها (افتراضي: 10000) + +**الإرجاع:** list[Triple]: قائمة بكائنات Triple المطابقة + +**يسبب أخطاء:** + +`RuntimeError`: إذا كان s أو p ليس Uri، أو o ليس Uri/Literal + +**مثال:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +عميل إدارة التدفق غير المتزامن باستخدام واجهة برمجة تطبيقات REST. + +يوفر عمليات إدارة التدفق المستندة إلى `async/await` بما في ذلك عمليات القائمة، +والبدء، والإيقاف، وإدارة تعريفات فئات التدفق. كما يوفر +الوصول إلى الخدمات الخاصة بنطاق التدفق مثل الوكلاء، وRAG، والاستعلامات عبر نقاط نهاية REST غير متدفقة. + + +ملاحظة: للحصول على دعم التدفق، استخدم `AsyncSocketClient` بدلاً من ذلك. + +### الطرق + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +تهيئة عميل التدفق غير المتزامن. + +**الوسائط:** + +`url`: عنوان URL الأساسي لواجهة برمجة تطبيقات TrustGraph. +`timeout`: المهلة المطلوبة بالثواني. +`token`: رمز مميز اختياري للمصادقة. + +### `aclose(self) -> None` + +إغلاق العميل غير المتزامن وتنظيف الموارد. + +ملاحظة: يتم التعامل مع التنظيف تلقائيًا بواسطة مديري سياق جلسة `aiohttp`. +تم توفير هذه الطريقة لضمان الاتساق مع العملاء غير المتزامنين الآخرين. + +### `delete_class(self, class_name: str)` + +حذف تعريف فئة تدفق. + +يزيل مخطط فئة التدفق من النظام. لا يؤثر على +مثيلات التدفق قيد التشغيل. + +**الوسائط:** + +`class_name`: اسم فئة التدفق المراد حذفها. + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +الحصول على تعريف التدفق. + +يسترجع التكوين الكامل للتدفق بما في ذلك اسم الفئة الخاص به، +والوصف، والمعلمات. + +**الوسائط:** + +`id`: مُعرّف التدفق + +**الإرجاع:** dict: كائن تعريف التدفق + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +الحصول على تعريف الفئة التدفق. + +يسترجع تعريف النموذج لفئة التدفق، بما في ذلك +مخطط التكوين وارتباطات الخدمة. + +**الوسائط:** + +`class_name`: اسم فئة التدفق + +**الإرجاع:** dict: كائن تعريف فئة التدفق + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +احصل على مثيل عميل التدفق غير المتزامن. + +يُرجع عميلاً للتفاعل مع خدمات تدفق معين (وكيل، واسترجاع المعلومات، والاستعلامات، والتضمينات، إلخ). + + +**الوسائط:** + +`flow_id`: مُعرّف التدفق + +**الإرجاع:** AsyncFlowInstance: عميل للعمليات الخاصة بالتدفق + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +قم بإدراج جميع معرفات التدفق. + +يسترجع معرفات جميع التدفقات المنشورة حاليًا في النظام. + +**الإرجاع:** list[str]: قائمة بمعرفات التدفق. + +**مثال:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +قم بإدراج جميع أسماء فئات التدفق. + +يسترجع أسماء جميع فئات التدفق (القوالب) المتاحة في النظام. + +**الإرجاع:** list[str]: قائمة بأسماء فئات التدفق. + +**مثال:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +إنشاء أو تحديث تعريف لفئة التدفق. + +يخزن مخططًا لفئة التدفق يمكن استخدامه لإنشاء مثيلات التدفق. + +**الوسائط:** + +`class_name`: اسم فئة التدفق +`definition`: كائن تعريف فئة التدفق + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +إرسال طلب HTTP POST غير متزامن إلى واجهة برمجة التطبيقات (API) الخاصة بالبوابة. + +طريقة داخلية لإجراء طلبات مصادقة إلى واجهة برمجة التطبيقات (API) الخاصة بـ TrustGraph. + +**الوسائط:** + +`path`: مسار نقطة نهاية واجهة برمجة التطبيقات (API) (بالنسبة إلى عنوان URL الأساسي). +`request_data`: قاموس حمولة الطلب. + +**الإرجاع:** dict: كائن الاستجابة من واجهة برمجة التطبيقات (API). + +**يُصدر:** + +`ProtocolException`: إذا كان رمز حالة HTTP ليس 200 أو إذا كانت الاستجابة ليست JSON صالحة. +`ApplicationException`: إذا أرجع الـ API استجابة خطأ. + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +ابدأ نسخة جديدة من التدفق. + +ينشئ ويبدأ تدفقًا من تعريف فئة التدفق مع المعلمات المحددة. + + +**الوسائط:** + +`class_name`: اسم فئة التدفق المراد إنشاؤه. +`id`: معرف للنسخة الجديدة من التدفق. +`description`: وصف قابل للقراءة البشرية للتدفق. +`parameters`: معلمات تكوين اختيارية للتدفق. + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +إيقاف عملية جارية. + +يوقف ويحذف نسخة من العملية، ويحرر مواردها. + +**الوسائط:** + +`id`: مُعرّف العملية المراد إيقافها. + +**مثال:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +عميل مثيل التدفق غير المتزامن. + +يوفر الوصول إلى الخدمات ذات النطاق التدريجي باستخدام آليات المزامنة (async/await)، بما في ذلك الوكلاء، +واستعلامات RAG، والتضمينات، واستعلامات الرسم البياني. تُرجع جميع العمليات استجابات كاملة (غير متدفقة). + + +ملاحظة: للحصول على دعم التدفق، استخدم AsyncSocketFlowInstance بدلاً من ذلك. + +### الطرق + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +تهيئة مثيل التدفق غير المتزامن. + +**الوسائط:** + +`flow`: عميل التدفق غير المتزامن الرئيسي. +`flow_id`: معرف التدفق. + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +تنفيذ عملية وكيل (غير متدفقة). + +يقوم بتشغيل وكيل للإجابة على سؤال، مع حالة محادثة وسجل اختياري. تُرجع الاستجابة الكاملة بعد انتهاء الوكيل من +المعالجة. + + +ملاحظة: لا تدعم هذه الطريقة التدفق. للحصول على أفكار وملاحظات الوكيل في الوقت الفعلي، استخدم AsyncSocketFlowInstance.agent() بدلاً من ذلك. + + +**الوسائط:** + +`question`: سؤال المستخدم أو التعليمات. +`user`: معرف المستخدم. +`state`: قاموس حالة اختياري لسياق المحادثة. +`group`: معرف مجموعة اختياري لإدارة الجلسة. +`history`: قائمة سجل المحادثة الاختيارية. +`**kwargs`: معلمات إضافية خاصة بالخدمة. + +**الإرجاع:** dict: استجابة الوكيل الكاملة بما في ذلك الإجابة والبيانات الوصفية. + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +تنفيذ استعلام RAG المستند إلى المستندات (غير متدفق). + +يقوم بتنفيذ توليد معزز بالاسترجاع باستخدام تضمينات المستندات. +يسترجع أجزاء المستندات ذات الصلة من خلال البحث الدلالي، ثم يقوم بإنشاء +استجابة تستند إلى المستندات المسترجعة. يُرجع الاستجابة الكاملة. + +ملاحظة: لا تدعم هذه الطريقة التدفق. للاستجابات المتدفقة لـ RAG، +استخدم AsyncSocketFlowInstance.document_rag() بدلاً من ذلك. + +**الوسائط:** + +`query`: نص استعلام المستخدم. +`user`: معرف المستخدم. +`collection`: معرف المجموعة التي تحتوي على المستندات. +`doc_limit`: الحد الأقصى لعدد أجزاء المستندات التي سيتم استرجاعها (افتراضي: 10). +`**kwargs`: معلمات إضافية خاصة بالخدمة. + +**الإرجاع:** str: الاستجابة الكاملة التي تم إنشاؤها والتي تستند إلى بيانات المستند. + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +توليد تضمينات للنصوص المدخلة. + +تحويل النصوص إلى تمثيلات متجهة رقمية باستخدام نموذج التضمين المُكوّن في التدفق. +مفيد للبحث الدلالي ومقارنات التشابه. + + +**الوسائط:** + +`texts`: قائمة بالنصوص المدخلة المراد تضمينها. +`**kwargs`: معلمات إضافية خاصة بالخدمة. + +**الإرجاع:** dict: استجابة تحتوي على متجهات التضمين. + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +البحث عن تضمينات الرسم البياني للاستعلام عن الكيانات الدلالية. + +يقوم بإجراء بحث دلالي عبر تضمينات الكيانات في الرسم البياني للعثور على الكيانات +الأكثر صلة بالنص المدخل. يُرجع الكيانات مرتبة حسب التشابه. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`user`: معرف المستخدم +`collection`: معرف المجموعة التي تحتوي على تضمينات الرسم البياني +`limit`: الحد الأقصى لعدد النتائج المراد إرجاعها (افتراضي: 10) +`**kwargs`: معلمات إضافية خاصة بالخدمة + +**الإرجاع:** dict: استجابة تحتوي على تطابقات الكيانات المرتبة مع درجات التشابه + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +تنفيذ استعلام RAG المستند إلى الرسم البياني (غير متدفق). + +يقوم بتنفيذ توليد مُعزز بالاسترجاع باستخدام بيانات الرسم البياني المعرفي. +يحدد الكيانات ذات الصلة وعلاقاتها، ثم يقوم بإنشاء +استجابة تستند إلى هيكل الرسم البياني. يُرجع الاستجابة الكاملة. + +ملاحظة: لا تدعم هذه الطريقة التدفق. للاستجابات المتدفقة لـ RAG، +استخدم AsyncSocketFlowInstance.graph_rag() بدلاً من ذلك. + +**الوسائط:** + +`query`: نص استعلام المستخدم. +`user`: مُعرّف المستخدم. +`collection`: مُعرّف المجموعة التي تحتوي على الرسم البياني المعرفي. +`max_subgraph_size`: الحد الأقصى لعدد الثلاثيات لكل رسم بياني فرعي (افتراضي: 1000). +`max_subgraph_count`: الحد الأقصى لعدد الرسوم البيانية الفرعية المراد استرجاعها (افتراضي: 5). +`max_entity_distance`: أقصى مسافة للرسم البياني لتوسيع الكيانات (افتراضي: 3). +`**kwargs`: معلمات إضافية خاصة بالخدمة. + +**الإرجاع:** str: الاستجابة الكاملة التي تم إنشاؤها والتي تستند إلى بيانات الرسم البياني. + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +إرسال طلب إلى خدمة ذات نطاق محدد. + +طريقة داخلية لاستدعاء الخدمات داخل مثيل التدفق هذا. + +**الوسائط:** + +`service`: اسم الخدمة (مثل، "agent"، "graph-rag"، "triples") +`request_data`: حمولة طلب الخدمة + +**الإرجاع:** dict: كائن استجابة الخدمة + +**يُصدر:** + +`ProtocolException`: إذا فشل الطلب أو كانت الاستجابة غير صالحة +`ApplicationException`: إذا أرجعت الخدمة خطأ + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +الاستعلام عن تضمينات الصفوف للبحث الدلالي عن البيانات المهيكلة. + +يقوم بإجراء بحث دلالي عبر تضمينات فهرس الصفوف للعثور على الصفوف التي +تكون قيم الحقول المفهرسة فيها الأكثر تشابهًا مع النص المدخل. يتيح +المطابقة التقريبية/الدلالية على البيانات المهيكلة. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`schema_name`: اسم المخطط للبحث داخله +`user`: معرف المستخدم (افتراضي: "trustgraph") +`collection`: معرف المجموعة (افتراضي: "default") +`index_name`: اسم الفهرس الاختياري لتصفية البحث في فهرس معين +`limit`: الحد الأقصى لعدد النتائج المراد إرجاعها (افتراضي: 10) +`**kwargs`: معلمات إضافية خاصة بالخدمة + +**الإرجاع:** dict: استجابة تحتوي على التطابقات مع index_name و index_value و text و score + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +تنفيذ استعلام GraphQL على الصفوف المخزنة. + +تستخدم الاستعلامات صفوف البيانات المهيكلة باستخدام بناء جملة GraphQL. تدعم الاستعلامات المعقدة +مع المتغيرات والعمليات المسماة. + +**الوسائط:** + +`query`: سلسلة استعلام GraphQL +`user`: معرف المستخدم +`collection`: معرف المجموعة التي تحتوي على الصفوف +`variables`: متغيرات استعلام GraphQL اختيارية +`operation_name`: اسم العملية الاختياري للاستعلامات متعددة العمليات +`**kwargs`: معلمات إضافية خاصة بالخدمة + +**الإرجاع:** dict: استجابة GraphQL مع البيانات و/أو الأخطاء + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +توليد إكمال النص (غير متدفق). + +يقوم بإنشاء استجابة نصية من نموذج لغوي كبير (LLM) بناءً على موجه النظام وموجه المستخدم. +يُرجع النص الكامل للاستجابة. + +ملاحظة: هذه الطريقة لا تدعم التدفق. لتوليد النص المتدفق، +استخدم AsyncSocketFlowInstance.text_completion() بدلاً من ذلك. + +**الوسائط:** + +`system`: موجه النظام الذي يحدد سلوك نموذج اللغة الكبير. +`prompt`: موجه المستخدم أو السؤال. +`**kwargs`: معلمات إضافية خاصة بالخدمة. + +**الإرجاع:** str: النص الكامل للاستجابة التي تم إنشاؤها. + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +الاستعلام عن ثلاثيات RDF باستخدام مطابقة الأنماط. + +تبحث عن ثلاثيات تتطابق مع الموضوع والفاعل والمفعول به المحددة. تستخدم الأنماط "None" كحرف بدل لمطابقة أي قيمة. + + +**الوسائط:** + +`s`: نمط الموضوع (None للجميع) +`p`: نمط الفاعل (None للجميع) +`o`: نمط المفعول به (None للجميع) +`user`: معرف المستخدم (None لجميع المستخدمين) +`collection`: معرف المجموعة (None لجميع المجموعات) +`limit`: الحد الأقصى لعدد الثلاثيات المراد إرجاعها (الافتراضي: 100) +`**kwargs`: معلمات إضافية خاصة بالخدمة + +**الإرجاع:** dict: استجابة تحتوي على الثلاثيات المتطابقة + +**مثال:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +عميل WebSocket متزامن لعمليات البث. + +يوفر واجهة متزامنة لخدمات TrustGraph القائمة على WebSocket، +مع تغليف مكتبة WebSocket غير المتزامنة باستخدام مولدات متزامنة لسهولة الاستخدام. +يدعم عمليات البث من الوكلاء، واستعلامات RAG، وإكمال النصوص. + +ملاحظة: هذا هو غلاف متزامن لعمليات WebSocket غير المتزامنة. للحصول على دعم غير متزامن حقيقي، استخدم AsyncSocketClient بدلاً من ذلك. + +### الطرق + + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +تهيئة عميل WebSocket متزامن. + +**الوسائط:** + +`url`: عنوان URL الأساسي لواجهة برمجة تطبيقات TrustGraph (سيتم تحويل HTTP/HTTPS إلى WS/WSS). +`timeout`: مهلة WebSocket بالثواني. +`token`: رمز مميز اختياري للمصادقة. + +### `close(self) -> None` + +إغلاق اتصالات WebSocket. + +ملاحظة: تتم معالجة التنظيف تلقائيًا بواسطة مديري السياق في التعليمات البرمجية غير المتزامنة. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +الحصول على مثيل تدفق لعمليات بث WebSocket. + +**الوسائط:** + +`flow_id`: معرف التدفق. + +**الإرجاع:** SocketFlowInstance: مثيل التدفق مع طرق البث. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +مثال على تدفق WebSocket المتزامن لعمليات البث. + +يوفر نفس الواجهة مثل FlowInstance الخاص بـ REST ولكنه يدعم +بثًا يعتمد على WebSocket للاستجابات في الوقت الفعلي. تدعم جميع الطرق معلمة اختيارية +`streaming` لتمكين تسليم النتائج التدريجي. + +### الطرق + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +تهيئة مثيل تدفق المقبس. + +**الوسائط:** + +`client`: عميل المقبس الأبوي. +`flow_id`: معرف التدفق. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +تنفيذ عملية وكيل مع دعم البث. + +يمكن للوكلاء إجراء عمليات استدلال متعددة الخطوات مع استخدام الأدوات. تقوم هذه الطريقة دائمًا +بإرجاع أجزاء البث (الأفكار والملاحظات والإجابات) حتى عندما +يكون streaming=False، لإظهار عملية تفكير الوكيل. + +**الوسائط:** + +`question`: سؤال المستخدم أو التعليمات. +`user`: معرف المستخدم. +`state`: قاموس حالة اختياري للمحادثات التي تعتمد على الحالة. +`group`: معرف مجموعة اختياري للسياقات متعددة المستخدمين. +`history`: سجل محادثة اختياري كقائمة من قواميس الرسائل. +`streaming`: تمكين وضع البث (افتراضي: False). +`**kwargs`: معلمات إضافية يتم تمريرها إلى خدمة الوكيل. + +**الإرجاع:** Iterator[StreamingChunk]: سلسلة من أفكار الوكيل وملاحظاته وإجاباته. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +تنفيذ عملية وكيل مع دعم الشفافية. + +يقوم بإرسال كل من أجزاء المحتوى (أفكار الوكيل، ملاحظات الوكيل، إجابات الوكيل) +وأحداث المصدر (ProvenanceEvent). تحتوي أحداث المصدر على عناوين URI +يمكن استردادها باستخدام ExplainabilityClient للحصول على معلومات تفصيلية +حول عملية تفكير الوكيل. + +يتكون تتبع الوكيل من: +الجلسة: السؤال الأولي وبيانات تعريف الجلسة. +التكرارات: كل دورة من الأفكار/الإجراءات/الملاحظات. +الاستنتاج: الإجابة النهائية. + +**الوسائط:** + +`question`: سؤال المستخدم أو التعليمات. +`user`: معرف المستخدم. +`collection`: معرف المجموعة لتخزين المصادر. +`state`: قاموس حالة اختياري للمحادثات التي تعتمد على الحالة. +`group`: معرف المجموعة الاختياري للسياقات متعددة المستخدمين. +`history`: سجل المحادثة الاختياري كقائمة من قواميس الرسائل. +`**kwargs`: معلمات إضافية يتم تمريرها إلى خدمة الوكيل. +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: أجزاء الوكيل وأحداث المصدر. + +**مثال:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +الاستعلام عن أجزاء المستندات باستخدام التشابه الدلالي. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة +`limit`: الحد الأقصى لعدد النتائج (افتراضي: 10) +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**الإرجاع:** قاموس: نتائج الاستعلام مع معرفات الأجزاء لأجزاء المستندات المطابقة + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +تنفيذ استعلام RAG يعتمد على المستندات مع خيار التدفق. + +يستخدم تضمينات المتجهات للعثور على أجزاء المستندات ذات الصلة، ثم يقوم بإنشاء +استجابة باستخدام نموذج لغوي كبير. يوفر وضع التدفق النتائج بشكل تدريجي. + +**الوسائط:** + +`query`: استعلام بلغة طبيعية +`user`: معرف المستخدم/مساحة الاسم +`collection`: معرف المجموعة +`doc_limit`: الحد الأقصى لعدد أجزاء المستندات التي سيتم استرجاعها (افتراضي: 10) +`streaming`: تمكين وضع التدفق (افتراضي: False) +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**الإرجاع:** Union[str, Iterator[str]]: الاستجابة الكاملة أو سلسلة من أجزاء النص + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +تنفيذ استعلام RAG يعتمد على المستند مع دعم الشفافية. + +يقوم بإرسال كل من أجزاء المحتوى (RAGChunk) وأحداث المصدر (ProvenanceEvent). +تحتوي أحداث المصدر على عناوين URI يمكن استردادها باستخدام ExplainabilityClient +للحصول على معلومات تفصيلية حول كيفية إنشاء الاستجابة. + +يتكون تتبع RAG للمستند من: +السؤال: استعلام المستخدم. +الاستكشاف: الأجزاء المستردة من مستودع المستندات (عدد الأجزاء). +التوليف: الإجابة التي تم إنشاؤها. + +**الوسائط:** + +`query`: استعلام بلغة طبيعية. +`user`: معرف المستخدم/المساحة. +`collection`: معرف المجموعة. +`doc_limit`: الحد الأقصى لعدد أجزاء المستندات التي سيتم استردادها (افتراضي: 10). +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: أجزاء المحتوى وأحداث المصدر. + +**مثال:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +توليد تضمينات متجهة لنص أو أكثر. + +**الوسائط:** + +`texts`: قائمة بالنصوص المدخلة لإنشاء التضمينات. +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. + +**الإرجاع:** قاموس: استجابة تحتوي على المتجهات (مجموعة واحدة لكل نص مدخل). + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +الاستعلام عن كيانات الرسم البياني المعرفي باستخدام التشابه الدلالي. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة +`limit`: الحد الأقصى لعدد النتائج (افتراضي: 10) +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**الإرجاع:** dict: نتائج الاستعلام مع الكيانات المشابهة + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +تنفيذ استعلام RAG يعتمد على الرسم البياني مع خيار التدفق. + +يستخدم هيكل الرسم البياني للمعرفة للعثور على السياق ذي الصلة، ثم يقوم بإنشاء +استجابة باستخدام نموذج لغوي كبير. يوفر وضع التدفق النتائج بشكل تدريجي. + +**الوسائط:** + +`query`: استعلام بلغة طبيعية +`user`: معرف المستخدم/مساحة الاسم +`collection`: معرف المجموعة +`max_subgraph_size`: الحد الأقصى لإجمالي الثلاثيات في الرسم البياني الفرعي (افتراضي: 1000) +`max_subgraph_count`: الحد الأقصى لعدد الرسوم البيانية الفرعية (افتراضي: 5) +`max_entity_distance`: الحد الأقصى لعمق المسار (افتراضي: 3) +`streaming`: تمكين وضع التدفق (افتراضي: False) +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**الإرجاع:** Union[str, Iterator[str]]: الاستجابة الكاملة أو سلسلة من أجزاء النص + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +تنفيذ استعلام RAG المستند إلى الرسم البياني مع دعم الشفافية. + +يقوم بإرسال كل من أجزاء المحتوى (RAGChunk) وأحداث المصدر (ProvenanceEvent). +تحتوي أحداث المصدر على معرفات URI يمكن استردادها باستخدام ExplainabilityClient +للحصول على معلومات تفصيلية حول كيفية إنشاء الاستجابة. + +**الوسائط:** + +`query`: استعلام بلغة طبيعية. +`user`: معرف المستخدم/المساحة. +`collection`: معرف المجموعة. +`max_subgraph_size`: الحد الأقصى لإجمالي الثلاثيات في الرسم البياني الفرعي (افتراضي: 1000). +`max_subgraph_count`: الحد الأقصى لعدد الرسوم البيانية الفرعية (افتراضي: 5). +`max_entity_distance`: الحد الأقصى لعمق المسار (افتراضي: 3). +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: أجزاء المحتوى وأحداث المصدر. + +**مثال:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +تنفيذ أداة بروتوكول سياق النموذج (MCP). + +**الوسائط:** + +`name`: اسم/معرّف الأداة +`parameters`: قاموس معلمات الأداة +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**النتائج:** dict: نتيجة تنفيذ الأداة + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +تنفيذ قالب إرشادي مع إمكانية التدفق الاختياري. + +**الوسائط:** + +`id`: مُعرّف قالب الإرشادي. +`variables`: قاموس لربط أسماء المتغيرات بقيمها. +`streaming`: تفعيل وضع التدفق (افتراضي: False). +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. + +**الإرجاع:** Union[str, Iterator[str]]: الاستجابة الكاملة أو سلسلة من أجزاء النص. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +استعلام عن بيانات الصفوف باستخدام التشابه الدلالي على الحقول المفهرسة. + +يجد الصفوف التي تكون فيها قيم الحقول المفهرسة متشابهة دلاليًا مع +النص المدخل، وذلك باستخدام تضمينات المتجهات. هذا يتيح المطابقة التقريبية/الدلالية +على البيانات المنظمة. + +**الوسائط:** + +`text`: نص الاستعلام للبحث الدلالي +`schema_name`: اسم المخطط للبحث داخله +`user`: معرف المستخدم/مساحة المفاتيح (الافتراضي: "trustgraph") +`collection`: معرف المجموعة (الافتراضي: "default") +`index_name`: اسم الفهرس الاختياري لتصفية البحث في فهرس معين +`limit`: الحد الأقصى لعدد النتائج (الافتراضي: 10) +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**الإرجاع:** dict: نتائج الاستعلام مع التطابقات التي تحتوي على index_name و index_value و text و score + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +تنفيذ استعلام GraphQL مقابل الصفوف المنظمة. + +**الوسائط:** + +`query`: سلسلة استعلام GraphQL +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة +`variables`: قاموس اختياري لمتغيرات الاستعلام +`operation_name`: اسم العملية الاختياري للمستندات متعددة العمليات +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة + +**الإرجاع:** dict: استجابة GraphQL مع البيانات والأخطاء و/أو الامتدادات + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +تنفيذ إكمال النص مع خيار التدفق. + +**الوسائط:** + +`system`: نص النظام الذي يحدد سلوك المساعد. +`prompt`: نص المستخدم/سؤال. +`streaming`: تمكين وضع التدفق (افتراضي: False). +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. + +**الإرجاع:** Union[str, Iterator[str]]: الاستجابة الكاملة أو سلسلة من أجزاء النص. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +الاستعلام عن ثلاثيات الرسم البياني المعرفي باستخدام مطابقة الأنماط. + +**الوسائط:** + +`s`: عامل تصفية الموضوع - سلسلة URI، أو قاموس مصطلحات، أو None للرمز البري. +`p`: عامل تصفية المسند - سلسلة URI، أو قاموس مصطلحات، أو None للرمز البري. +`o`: عامل تصفية الكائن - سلسلة URI/حرفية، أو قاموس مصطلحات، أو None للرمز البري. +`g`: عامل تصفية الرسم البياني المسمى - سلسلة URI أو None لجميع الرسوم البيانية. +`user`: معرف المستخدم/مساحة المفاتيح (اختياري). +`collection`: معرف المجموعة (اختياري). +`limit`: الحد الأقصى للنتائج المراد إرجاعها (الافتراضي: 100). +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. + +**الإرجاع:** List[Dict]: قائمة بالثلاثيات المتطابقة بتنسيق السلك. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +الاستعلام عن ثلاثيات الرسم البياني المعرفي باستخدام دفعات متدفقة. + +ينتج دفعات من الثلاثيات أثناء وصولها، مما يقلل من الوقت اللازم للحصول على النتيجة الأولى +وتقليل الحمل الزائد للذاكرة لمجموعات النتائج الكبيرة. + +**الوسائط:** + +`s`: عامل تصفية الموضوع - سلسلة URI، أو قاموس مصطلحات، أو None للرمز البرمجي. +`p`: عامل تصفية المسند - سلسلة URI، أو قاموس مصطلحات، أو None للرمز البرمجي. +`o`: عامل تصفية الكائن - سلسلة URI/حرفية، أو قاموس مصطلحات، أو None للرمز البرمجي. +`g`: عامل تصفية الرسم البياني المسمى - سلسلة URI أو None لجميع الرسوم البيانية. +`user`: معرف المستخدم/مساحة المفاتيح (اختياري). +`collection`: معرف المجموعة (اختياري). +`limit`: الحد الأقصى للنتائج المراد إرجاعها (الافتراضي: 100). +`batch_size`: الثلاثيات لكل دفعة (الافتراضي: 20). +`**kwargs`: معلمات إضافية يتم تمريرها إلى الخدمة. +`Yields`: +`List[Dict]`: دفعات من الثلاثيات بتنسيق السلك. + +**مثال:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +عميل WebSocket غير متزامن. + +### الطرق. + +### `__init__(self, url: str, timeout: int, token: str | None)` + +تهيئة الكائن الذاتي. راجع help(type(self)) للحصول على التوقيع الدقيق. + +### `aclose(self)` + +إغلاق اتصال WebSocket. + +### `flow(self, flow_id: str)` + +الحصول على مثيل التدفق غير المتزامن لعمليات WebSocket. + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +مثيل تدفق WebSocket غير متزامن. + +### الطرق + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +تهيئة الكائن الذاتي. راجع help(type(self)) للحصول على التوقيع الدقيق. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +وكيل مع تدفق اختياري. + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +توثيق RAG مع تدفق اختياري. + +### `embeddings(self, texts: list, **kwargs)` + +إنشاء تضمينات نصية. + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +الاستعلام عن تضمينات الرسم البياني للبحث الدلالي. + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +RAG للرسم البياني مع تدفق اختياري. + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +تنفيذ أداة MCP. + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +تنفيذ موجه مع تدفق اختياري. + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +الاستعلام عن تضمينات الصفوف للبحث الدلالي على البيانات المنظمة. + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +استعلام GraphQL عن الصفوف المنظمة. + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +إكمال النص مع تدفق اختياري. + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +استعلام نمط ثلاثي. + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +إنشاء قاموس Term بتنسيق سلكي من قيمة. + +قواعد الكشف التلقائي (عندما يكون term_type هو None): + إذا كان بالفعل قاموسًا مع مفتاح 't' -> إرجاعه كما هو (قاموس Term بالفعل) + يبدأ بـ http://, https://, urn: -> IRI + محاط بأقواس الزاوية (مثل ) -> IRI (إزالة أقواس الزاوية) + أي شيء آخر -> حرفي + +**الوسائط:** + +`value`: قيمة المصطلح (سلسلة، قاموس، أو None) +`term_type`: واحد من 'iri'، 'literal'، أو None للكشف التلقائي +`datatype`: نوع البيانات للكائنات الحرفية (مثل xsd:integer) +`language`: علامة اللغة للكائنات الحرفية (مثل en) + +**الإرجاع:** قاموس: قاموس Term بتنسيق سلكي، أو None إذا كانت القيمة هي None + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +عميل للعمليات المجمعة المتزامنة للاستيراد/التصدير. + +يوفر نقل بيانات مجمع فعال عبر WebSocket لمجموعات البيانات الكبيرة. +يغلف عمليات WebSocket غير المتزامنة باستخدام مولدات متزامنة لسهولة الاستخدام. + +ملاحظة: للحصول على دعم غير متزامن حقيقي، استخدم AsyncBulkClient بدلاً من ذلك. + +### الطرق + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +تهيئة عميل مجمع متزامن. + +**الوسائط:** + +`url`: عنوان URL الأساسي لواجهة برمجة تطبيقات TrustGraph (سيتم تحويل HTTP/HTTPS إلى WS/WSS). +`timeout`: مهلة WebSocket بالثواني. +`token`: رمز مميز اختياري للمصادقة. + +### `close(self) -> None` + +إغلاق الاتصالات. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +تصدير مجمّع لتضمينات المستندات من تدفق. + +يقوم بتنزيل جميع تضمينات أجزاء المستندات بكفاءة عبر بث WebSocket. + +**الوسائط:** + +`flow`: معرف التدفق. +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**الإرجاع:** Iterator[Dict[str, Any]]: دفق من قواميس التضمين. + +**مثال:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +تصدير كميات كبيرة من سياقات الكيانات من تدفق. + +يقوم بتنزيل جميع معلومات سياق الكيانات بكفاءة عبر بث WebSocket. + +**الوسائط:** + +`flow`: مُعرّف التدفق +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي) + +**الإرجاع:** Iterator[Dict[str, Any]]: سلسلة من قواميس السياق + +**مثال:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +تصدير جماعي لتمثيلات الرسم البياني من تدفق. + +يقوم بتنزيل جميع تمثيلات الكيانات في الرسم البياني بكفاءة عبر بث WebSocket. + +**الوسائط:** + +`flow`: مُعرّف التدفق. +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**الإرجاع:** Iterator[Dict[str, Any]]: تدفق لقواميس التمثيل. + +**مثال:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +تصدير كميات كبيرة من الثلاثيات RDF من تدفق. + +يقوم بتنزيل جميع الثلاثيات بكفاءة عبر بث WebSocket. + +**الوسائط:** + +`flow`: مُعرّف التدفق. +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**الإرجاع:** Iterator[Triple]: دفق لكائنات Triple. + +**مثال:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد كميات كبيرة من تضمينات المستندات إلى مسار عمل. + +يقوم بتحميل تضمينات أجزاء المستندات بكفاءة عبر بث WebSocket +لاستخدامها في استعلامات استرجاع المعلومات من المستندات (RAG). + +**الوسائط:** + +`flow`: مُعرّف مسار العمل. +`embeddings`: مُكرّر ينتج قواميس التضمين. +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**مثال:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +استيراد كميات كبيرة من سياقات الكيانات إلى تدفق. + +يقوم بتحميل معلومات سياق الكيانات بكفاءة عبر بث WebSocket. +توفر سياقات الكيانات سياقًا نصيًا إضافيًا حول كيانات الرسم البياني +لتحسين أداء RAG. + +**الوسائط:** + +`flow`: مُعرّف التدفق. +`contexts`: مُكرّر ينتج قواميس السياق. +`metadata`: قاموس بيانات التعريف مع id و metadata والمستخدم والمجموعة. +`batch_size`: عدد السياقات لكل دفعة (افتراضي 100). +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**مثال:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد كميات كبيرة من تضمينات الرسم البياني إلى مسار عمل. + +يقوم بتحميل تضمينات كيانات الرسم البياني بكفاءة عبر بث WebSocket. + +**الوسائط:** + +`flow`: مُعرّف مسار العمل. +`embeddings`: مُكرّر ينتج قواميس التضمين. +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**مثال:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد كميات كبيرة من الصفوف المنظمة إلى مسار عمل. + +يقوم بتحميل بيانات منظمة بكفاءة عبر بث WebSocket +للاستخدام في استعلامات GraphQL. + +**الوسائط:** + +`flow`: مُعرّف مسار العمل. +`rows`: مُكرّر ينتج قواميس الصفوف. +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**مثال:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +استيراد كميات كبيرة من الثلاثيات RDF إلى تدفق. + +يقوم بتحميل أعداد كبيرة من الثلاثيات بكفاءة عبر بث WebSocket. + +**الوسائط:** + +`flow`: مُعرّف التدفق. +`triples`: مُكرّر ينتج كائنات Triple. +`metadata`: قاموس بيانات وصفية بمعرف، وبيانات وصفية، ومستخدم، ومجموعة. +`batch_size`: عدد الثلاثيات لكل دفعة (افتراضي 100). +`**kwargs`: معلمات إضافية (محجوزة للاستخدام المستقبلي). + +**مثال:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +عميل العمليات المجمعة غير المتزامنة. + +### الطرق + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +تهيئة الكائن الذاتي. راجع help(type(self)) للحصول على التوقيع الدقيق. + +### `aclose(self) -> None` + +إغلاق الاتصالات. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +تصدير مجمّع لتمثيلات المستندات عبر WebSocket. + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +تصدير مجمّع لسياقات الكيانات عبر WebSocket. + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +تصدير مجمّع لتمثيلات الرسم البياني عبر WebSocket. + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +تصدير مجمّع للثلاثيات عبر WebSocket. + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد مجمّع لتمثيلات المستندات عبر WebSocket. + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد مجمّع لسياقات الكيانات عبر WebSocket. + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد مجمّع لتمثيلات الرسم البياني عبر WebSocket. + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +استيراد مجمّع للصفوف عبر WebSocket. + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +استيراد مجمّع للثلاثيات عبر WebSocket. + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +عميل المقاييس المتزامنة. + +### الطرق. + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +قم بتهيئة `self`. راجع `help(type(self))` للحصول على التوقيع الدقيق. + +### `get(self) -> str` + +احصل على مقاييس بروميثيوس كنص. + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +عميل المقاييس غير المتزامن. + +### الطرق. + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +قم بتهيئة `self`. راجع `help(type(self))` للحصول على التوقيع الدقيق. + +### `aclose(self) -> None` + +أغلق الاتصالات. + +### `get(self) -> str` + +احصل على مقاييس Prometheus كنص. + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +عميل لجلب كيانات التفسير مع معالجة الاتساق النهائي. + +يستخدم اكتشاف حالة السكون: الجلب، الانتظار، الجلب مرة أخرى، المقارنة. +إذا كانت النتائج متطابقة، فإن البيانات مستقرة. + +### الطرق + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +تهيئة عميل التفسير. + +**الوسائط:** + +`flow_instance`: مثيل SocketFlowInstance للاستعلام عن الثلاثيات. +`retry_delay`: التأخير بين عمليات إعادة المحاولة بالثواني (افتراضي: 0.2). +`max_retries`: الحد الأقصى لعدد محاولات إعادة المحاولة (افتراضي: 10). + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +الكشف عما إذا كانت الجلسة من نوع GraphRAG أو Agent. + +**الوسائط:** + +`session_uri`: عنوان URI للجلسة/السؤال. +`graph`: الرسم البياني المسمى. +`user`: معرف المستخدم/مساحة المفاتيح. +`collection`: معرف المجموعة. + +**الإرجاع:** "graphrag" أو "agent". + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +جلب مسار Agent الكامل بدءًا من عنوان URI للجلسة. + +يتبع سلسلة الأصل: سؤال -> تحليل (قائمة التحليلات) -> استنتاج. + +**الوسائط:** + +`session_uri`: عنوان URI لجلسة/سؤال الوكيل. +`graph`: الرسم البياني المسمى (افتراضي: urn:graph:retrieval). +`user`: معرف المستخدم/مساحة المفاتيح. +`collection`: معرف المجموعة. +`api`: مثيل TrustGraph Api للوصول إلى أمين المكتبة (اختياري). +`max_content`: الحد الأقصى لطول المحتوى للاستنتاج. + +**الإرجاع:** قاموس يحتوي على السؤال والتكرارات (قائمة التحليلات) والكيانات الاستنتاجية. + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +جلب مسار DocumentRAG الكامل بدءًا من عنوان URI للسؤال. + +يتبع سلسلة الأصل: + سؤال -> تثبيت -> استكشاف -> توليف. + +**الوسائط:** + +`question_uri`: عنوان URI لكيان السؤال. +`graph`: الرسم البياني المسمى (افتراضي: urn:graph:retrieval). +`user`: معرف المستخدم/مساحة المفاتيح. +`collection`: معرف المجموعة. +`api`: مثيل TrustGraph Api للوصول إلى أمين المكتبة (اختياري). +`max_content`: الحد الأقصى لطول المحتوى للتوليف. + +**الإرجاع:** قاموس يحتوي على السؤال والتثبيت والاستكشاف والكيانات التوليفية. + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +جلب المحتوى من أمين المكتبة بواسطة عنوان URI للمستند. + +**الوسائط:** + +`document_uri`: عنوان URI للمستند في أمين المكتبة. +`api`: مثيل TrustGraph Api للوصول إلى أمين المكتبة. +`user`: معرف المستخدم لأمين المكتبة. +`max_content`: الحد الأقصى لطول المحتوى المراد إرجاعه. + +**الإرجاع:** محتوى المستند كسلسلة. + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +جلب كيان تحديد الحافة (يستخدم بواسطة Focus). + +**الوسائط:** + +`uri`: عنوان URI لتحديد الحافة. +`graph`: الرسم البياني المسمى للاستعلام عنه. +`user`: معرف المستخدم/مساحة المفاتيح. +`collection`: معرف المجموعة. + +**الإرجاع:** EdgeSelection أو None إذا لم يتم العثور عليه. + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +جلب كيان قابل للتفسير باستخدام عنوان URI مع معالجة الاتساق النهائي. + +يستخدم اكتشاف حالة السكون: +1. جلب الثلاثيات لعنوان URI +2. إذا كانت النتائج صفرًا، أعد المحاولة +3. إذا كانت النتائج غير صفرية، انتظر وجلب مرة أخرى +4. إذا كانت النتائج هي نفسها، فإن البيانات مستقرة - قم بتحليلها وأرجعها +5. إذا كانت النتائج مختلفة، لا تزال البيانات قيد الكتابة - أعد المحاولة + +**الوسائط:** + +`uri`: عنوان URI للكيان المراد جلبه +`graph`: الرسم البياني المسمى للاستعلام (مثل "urn:graph:retrieval") +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة + +**الإرجاع:** فئة ExplainEntity أو None إذا لم يتم العثور عليها + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +جلب كيان Focus وجميع اختيارات الحواف الخاصة به. + +**الوسائط:** + +`uri`: عنوان URI لكيان Focus +`graph`: الرسم البياني المسمى للاستعلام +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة + +**الإرجاع:** Focus مع اختيارات الحواف المعبأة، أو None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +جلب مسار GraphRAG الكامل بدءًا من عنوان URI لسؤال. + +يتبع سلسلة الأصل: سؤال -> تجسيد -> استكشاف -> Focus -> توليف + +**الوسائط:** + +`question_uri`: عنوان URI لكيان السؤال +`graph`: الرسم البياني (افتراضي: urn:graph:retrieval) +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة +`api`: مثيل TrustGraph Api للوصول إلى أمين المكتبة (اختياري) +`max_content`: أقصى طول للمحتوى للتوليف + +**الإرجاع:** قاموس يحتوي على كيانات السؤال والتجسيد والاستكشاف وFocus والتوليف + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +سرد جميع جلسات التفسير (الأسئلة) في مجموعة. + +**الوسائط:** + +`graph`: الرسم البياني (افتراضي: urn:graph:retrieval) +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة +`limit`: الحد الأقصى لعدد الجلسات المراد إرجاعها + +**الإرجاع:** قائمة بكيانات السؤال مرتبة حسب الطابع الزمني (الأحدث أولاً) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +حل تسميات جميع مكونات ثلاثية الحافة. + +**الوسائط:** + +`edge`: قاموس مع مفاتيح "s" و "p" و "o" +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة + +**الإرجاع:** مجموعة من (s_label, p_label, o_label) + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +حل rdfs:label لعنوان URI، مع التخزين المؤقت. + +**الوسائط:** + +`uri`: عنوان URI للحصول على التسمية +`user`: معرف المستخدم/مساحة المفاتيح +`collection`: معرف المجموعة + +**الإرجاع:** التسمية إذا تم العثور عليها، وإلا فإن عنوان URI نفسه + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +الفئة الأساسية لكائنات التفسير. + +**الحقول:** + +`uri`: +`entity_type`: + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +تهيئة الكائن الذاتي. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +كيان السؤال - استعلام المستخدم الذي بدأ الجلسة. + +**الحقول:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +كيان الاستكشاف - الحواف/الأجزاء المسترجعة من مستودع المعرفة. + +**الحقول:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +الكيان المستهدف - الحواف المحددة مع الاستدلال باستخدام نماذج اللغة الكبيرة (GraphRAG فقط). + +**الحقول:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +الكيان التجميعي - الإجابة النهائية. + +**الحقول:** + +`uri`: +`entity_type`: +`document`: + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +كيان التحليل - دورة تفكير/فعل/ملاحظة واحدة (للوكيل فقط). + +**الحقول:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +الخلاصة: الإجابة النهائية (للممثل فقط). + +**الحقول:** + +`uri`: +`entity_type`: +`document`: + +### الطرق + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +حافة محددة مع شرح من خطوة GraphRAG Focus. + +**الحقول:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### الطرق + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +تحويل الثلاثيات بتنسيق الأسلاك إلى صفوف (s, p, o). + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +استخراج القيمة من قاموس Term بتنسيق الأسلاك. + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +ثلاثية RDF تمثل عبارة في رسم بياني للمعرفة. + +**الحقول:** + +`s`: +`p`: +`o`: + +### الطرق + +### `__init__(self, s: str, p: str, o: str) -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +إنشاء كائن سلسلة جديد من الكائن المعطى. إذا تم تحديد ترميز أو +معالج أخطاء، فيجب أن يعرض الكائن مخزن بيانات سيتم فك ترميزه باستخدام الترميز ومعالج الأخطاء المحددين. +بخلاف ذلك، يتم إرجاع نتيجة object.__str__() (إذا تم تعريفه) +أو repr(object). +الترميز الافتراضي هو 'utf-8'. +معالج الأخطاء الافتراضي هو 'strict'. + + +### الطرق + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +إنشاء كائن سلسلة جديد من الكائن المعطى. إذا تم تحديد ترميز أو +معالجة الأخطاء، فيجب أن يعرض الكائن مخزن بيانات سيتم فك ترميزه باستخدام الترميز ومعالج الأخطاء المحدد. +بخلاف ذلك، يتم إرجاع نتيجة object.__str__() (إذا تم تعريفه) +أو repr(object). +الترميز الافتراضي هو 'utf-8'. +معالجة الأخطاء الافتراضية هي 'strict'. + + +### الطرق + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +مُعرّف مفتاح التكوين. + +**الحقول:** + +`type`: +`key`: + +### الطرق + +### `__init__(self, type: str, key: str) -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +زوج مفتاح-قيمة للتكوين. + +**الحقول:** + +`type`: +`key`: +`value`: + +### الطرق + +### `__init__(self, type: str, key: str, value: str) -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +بيانات وصفية لـمستند في المكتبة. + +**الخصائص:** + +`parent_id: Parent document ID for child documents (empty for top`: (مستوى المستندات) + +**الحقول:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### الطرق + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +تهيئة self. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +بيانات وصفية لعملية معالجة مستند نشطة. + +**الحقول:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### الطرق + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +تهيئة الـ self. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +بيانات وصفية لمجموعة بيانات. + +توفر المجموعات تجميعًا منطقيًا وعزلًا للمستندات وبيانات الرسم البياني المعرفي. + + +**الخصائص:** + +`name: Human`: اسم المجموعة الذي يمكن قراءته. + +**الحقول:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### الطرق + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +الفئة الأساسية لمعالجة أجزاء الاستجابة المتدفقة. + +تُستخدم لعمليات التدفق المستندة إلى WebSocket حيث يتم تسليم الاستجابات +بشكل تدريجي أثناء إنشائها. + +**الحقول:** + +`content`: +`end_of_message`: + +### الطرق + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +تهيئة الكائن الذاتي. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +جزء من تفكير أو عملية استنتاج الوكيل. + +يمثل خطوات التفكير أو التخطيط الداخلية للوكيل أثناء التنفيذ. +تُظهر هذه الأجزاء كيف يفكر الوكيل في المشكلة. + +**الحقول:** + +`content`: +`end_of_message`: +`chunk_type`: + +### الطرق + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +جزء من ملاحظات تنفيذ أداة الوكيل. + +يمثل النتيجة أو الملاحظة الناتجة عن تنفيذ أداة أو إجراء. +تُظهر هذه الأجزاء ما تعلمه الوكيل من استخدام الأدوات. + +**الحقول:** + +`content`: +`end_of_message`: +`chunk_type`: + +### الطرق + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +الجزء النهائي للإجابة من الوكيل. + +يمثل الاستجابة النهائية للوكيل للمستخدم بعد الانتهاء من +عملية التفكير واستخدام الأدوات. + +**الخصائص:** + +`chunk_type: Always "final`: answer" + +**الحقول:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### الطرق + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +تهيئة الـ self. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +تدفق جزء (Chunk) لـ RAG (الجيل المعزز بالاسترجاع). + +يُستخدم لإرسال الاستجابات من مخطط RAG، و RAG المستندات، وإكمال النصوص، +والخدمات التوليدية الأخرى. + +**الحقول:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### الطرق + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +تهيئة الذات (self). راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +حدث التتبع الأصلي لغرض التوضيح. + +يتم إصداره أثناء استعلامات GraphRAG عندما يكون وضع التوضيح مفعلاً. +يمثل كل حدث عقدة تتبع أصل تم إنشاؤها أثناء معالجة الاستعلام. + +**الحقول:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### الطرق + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +تهيئة الذات. راجع help(type(self)) للحصول على التوقيع الدقيق. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +يتم إطلاق هذا الحدث عند حدوث أخطاء في بروتوكول WebSocket. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +الفئة الأساسية لجميع أخطاء خدمة TrustGraph. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +خطأ في خدمة الوكيل. + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +خطأ في خدمة التكوين. + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +خطأ استرجاع المستندات. + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +خطأ في إدارة التدفق. + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +خطأ في بوابة واجهة برمجة التطبيقات (API Gateway). + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +خطأ استرجاع الرسوم البيانية. + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +خطأ في خدمة نموذج اللغة الكبير. + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +خطأ في تحميل البيانات. + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +خطأ في البحث/الاستعلام. + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +خطأ في خدمة الاستعلام عن معالجة اللغة الطبيعية. + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +خطأ في خدمة استعلام الصفوف. + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +خطأ في معالجة الطلب. + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +خطأ في خدمة الاستعلامات المنظمة. + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +خطأ غير متوقع/مجهول. + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +الفئة الأساسية لجميع أخطاء خدمة TrustGraph. + + +-- diff --git a/docs/python-api.es.md b/docs/python-api.es.md new file mode 100644 index 00000000..78302da5 --- /dev/null +++ b/docs/python-api.es.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "Referencia de la API de Python de TrustGraph" +parent: "Spanish (Beta)" +--- + +# Referencia de la API de Python de TrustGraph + +> **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. + +## Instalación + +```bash +pip install trustgraph +``` + +## Inicio rápido + +Todas las clases y tipos se importan del paquete `trustgraph.api`: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## Tabla de Contenidos + +### Núcleo + +[Api](#api) + +### Clientes de Flujo + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### Clientes de WebSocket + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### Operaciones Masivas + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### Métricas + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### Tipos de Datos + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### Excepciones + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +Cliente principal de la API TrustGraph para operaciones sincrónicas y asincrónicas. + +Esta clase proporciona acceso a todos los servicios de TrustGraph, incluyendo la gestión de flujos, +operaciones de grafos de conocimiento, procesamiento de documentos, consultas RAG y más. Soporta +tanto patrones de comunicación basados en REST como en WebSocket. + +El cliente se puede utilizar como un administrador de contexto para la limpieza automática de recursos: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### Métodos + +### `__aenter__(self)` + +Ingrese al administrador de contexto asíncrono. + +### `__aexit__(self, *args)` + +Salga del administrador de contexto asíncrono y cierre las conexiones. + +### `__enter__(self)` + +Ingrese al administrador de contexto síncrono. + +### `__exit__(self, *args)` + +Salga del administrador de contexto síncrono y cierre las conexiones. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +Inicialice el cliente de la API TrustGraph. + +**Argumentos:** + +`url`: URL base para la API TrustGraph (por defecto: "http://localhost:8088/"") +`timeout`: Tiempo de espera de la solicitud en segundos (por defecto: 60) +`token`: Token de portador opcional para la autenticación + +**Ejemplo:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +Cerrar todas las conexiones de cliente asíncronas. + +Este método cierra las conexiones asíncronas de WebSocket, las operaciones masivas y los flujos. +Se llama automáticamente al salir de un administrador de contexto asíncrono. + +**Ejemplo:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +Obtenga un cliente para operaciones masivas asíncronas. + +Proporciona operaciones de importación/exportación masivas en estilo async/await a través de WebSocket +para un manejo eficiente de grandes conjuntos de datos. + +**Devuelve:** AsyncBulkClient: Cliente para operaciones masivas asíncronas. + +**Ejemplo:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +Obtenga un cliente de flujo basado en REST asíncrono. + +Proporciona acceso al estilo async/await a las operaciones de flujo. Esto es preferible +para aplicaciones y marcos de trabajo de Python asíncronos (FastAPI, aiohttp, etc.). + +**Devuelve:** AsyncFlow: Cliente de flujo asíncrono + +**Ejemplo:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +Obtenga un cliente de métricas asíncrono. + +Proporciona acceso al estilo async/await a las métricas de Prometheus. + +**Retorna:** AsyncMetrics: Cliente de métricas asíncrono + +**Ejemplo:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +Obtenga un cliente WebSocket asíncrono para operaciones de transmisión. + +Proporciona acceso a WebSocket con estilo async/await y soporte para transmisión. +Este es el método preferido para la transmisión asíncrona en Python. + +**Retorna:** AsyncSocketClient: Cliente WebSocket asíncrono + +**Ejemplo:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +Obtenga un cliente de operaciones masivas sincrónicas para la importación/exportación. + +Las operaciones masivas permiten la transferencia eficiente de grandes conjuntos de datos a través de conexiones WebSocket, +incluyendo triples, incrustaciones, contextos de entidades y objetos. + +**Devuelve:** BulkClient: Cliente de operaciones masivas sincrónicas. + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +Cerrar todas las conexiones de cliente sincrónicas. + +Este método cierra las conexiones de WebSocket y de operaciones masivas. +Se llama automáticamente al salir de un administrador de contexto. + +**Ejemplo:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +Obtenga un cliente de Collection para administrar colecciones de datos. + +Las colecciones organizan documentos y datos de grafos de conocimiento en +agrupaciones lógicas para el aislamiento y el control de acceso. + +**Devuelve:** Collection: Cliente de administración de colecciones + +**Ejemplo:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +Obtenga un cliente de Config para administrar la configuración. + +**Retorna:** Config: Cliente de administración de configuración + +**Ejemplo:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +Obtenga un cliente de Flow para administrar e interactuar con flujos. + +Los flujos son las unidades de ejecución principales en TrustGraph, y proporcionan acceso a +servicios como agentes, consultas RAG, incrustaciones y procesamiento de documentos. + +**Devuelve:** Flow: Cliente de administración de flujos. + +**Ejemplo:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +Obtenga un cliente de Knowledge para administrar los núcleos de grafos de conocimiento. + +**Retorna:** Knowledge: Cliente de administración de grafos de conocimiento. + +**Ejemplo:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +Obtenga un cliente de la biblioteca para la gestión de documentos. + +La biblioteca proporciona almacenamiento de documentos, gestión de metadatos y +coordinación del flujo de trabajo de procesamiento. + +**Devuelve:** Biblioteca: Cliente de gestión de la biblioteca de documentos + +**Ejemplo:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +Obtiene un cliente de métricas sincrónico para la monitorización. + +Recupera métricas en formato Prometheus del servicio TrustGraph +para la monitorización y la observabilidad. + +**Devuelve:** Métricas: Cliente de métricas sincrónico + +**Ejemplo:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +Realizar una solicitud de API REST de bajo nivel. + +Este método se utiliza principalmente para uso interno, pero se puede utilizar para acceder directamente +a la API cuando sea necesario. + +**Argumentos:** + +`path`: Ruta del punto final de la API (relativa a la URL base) +`request`: Carga útil de la solicitud como un diccionario + +**Retorna:** dict: Objeto de respuesta + +**Lanza:** + +`ProtocolException`: Si el estado de la respuesta no es 200 o la respuesta no es JSON +`ApplicationException`: Si la respuesta contiene un error + +**Ejemplo:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +Obtenga un cliente WebSocket síncrono para operaciones de transmisión. + +Las conexiones WebSocket proporcionan soporte de transmisión para respuestas en tiempo real +de agentes, consultas RAG y finalizaciones de texto. Este método devuelve un +envoltorio síncrono alrededor del protocolo WebSocket. + +**Retorna:** SocketClient: Cliente WebSocket síncrono + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +Cliente de gestión de flujo para operaciones de planos de flujo y instancias de flujo. + +Esta clase proporciona métodos para administrar planos de flujo (plantillas) y +instancias de flujo (flujos en ejecución). Los planos definen la estructura y +los parámetros de los flujos, mientras que las instancias representan flujos activos que +pueden ejecutar servicios. + +### Métodos + +### `__init__(self, api)` + +Inicializar el cliente de flujo. + +**Argumentos:** + +`api`: Instancia de Api principal para realizar solicitudes. + +### `delete_blueprint(self, blueprint_name)` + +Eliminar un plano de flujo. + +**Argumentos:** + +`blueprint_name`: Nombre del plano a eliminar. + +**Ejemplo:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +Obtener la definición de una instancia de flujo en ejecución. + +**Argumentos:** + +`id`: ID de la instancia de flujo + +**Retorna:** dict: Definición de la instancia de flujo + +**Ejemplo:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +Obtener una definición de diagrama de flujo por nombre. + +**Argumentos:** + +`blueprint_name`: Nombre del diagrama de flujo a recuperar + +**Retorna:** dict: Definición del diagrama de flujo como un diccionario + +**Ejemplo:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +Obtener una instancia de FlowInstance para ejecutar operaciones en un flujo específico. + +**Argumentos:** + +`id`: Identificador del flujo (predeterminado: "default") + +**Retorna:** FlowInstance: Instancia de flujo para operaciones de servicio + +**Ejemplo:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +Listar todas las instancias de flujo activas. + +**Retorna:** list[str]: Lista de identificadores de instancias de flujo. + +**Ejemplo:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +Listar todos los planos de flujo disponibles. + +**Retorna:** list[str]: Lista de nombres de planos. + +**Ejemplo:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +Crear o actualizar un esquema de flujo. + +**Argumentos:** + +`blueprint_name`: Nombre para el esquema. +`definition`: Diccionario de definición del esquema. + +**Ejemplo:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +Realizar una solicitud de API con ámbito de flujo. + +**Argumentos:** + +`path`: Sufijo de ruta opcional para los puntos finales de flujo. +`request`: Diccionario de carga útil de la solicitud. + +**Retorna:** dict: Objeto de respuesta. + +**Genera:** + +`RuntimeError`: Si no se especifica el parámetro de solicitud. + +### `start(self, blueprint_name, id, description, parameters=None)` + +Iniciar una nueva instancia de flujo a partir de un plano. + +**Argumentos:** + +`blueprint_name`: Nombre del plano a instanciar. +`id`: Identificador único para la instancia de flujo. +`description`: Descripción legible por humanos. +`parameters`: Diccionario de parámetros opcionales. + +**Ejemplo:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +Detener una instancia de flujo en ejecución. + +**Argumentos:** + +`id`: ID de la instancia de flujo a detener. + +**Ejemplo:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +Cliente de instancia de flujo para ejecutar servicios en un flujo específico. + +Esta clase proporciona acceso a todos los servicios de TrustGraph, incluyendo: +Completado de texto y embeddings +Operaciones de agentes con gestión de estado +Consultas RAG de gráficos y documentos +Operaciones de grafos de conocimiento (triples, objetos) +Carga y procesamiento de documentos +Conversión de lenguaje natural a consulta GraphQL +Análisis de datos estructurados y detección de esquemas +Ejecución de herramientas MCP +Plantillas de prompts + +Los servicios se acceden a través de una instancia de flujo en ejecución identificada por ID. + +### Métodos + +### `__init__(self, api, id)` + +Inicializar FlowInstance. + +**Argumentos:** + +`api`: Cliente de flujo padre +`id`: Identificador de la instancia de flujo + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +Ejecutar una operación de agente con capacidades de razonamiento y uso de herramientas. + +Los agentes pueden realizar razonamiento en múltiples pasos, usar herramientas y mantener el +estado de la conversación en las interacciones. Esta es una versión síncrona no basada en streaming. + +**Argumentos:** + +`question`: Pregunta o instrucción del usuario +`user`: Identificador del usuario (por defecto: "trustgraph") +`state`: Diccionario de estado opcional para conversaciones con estado +`group`: Identificador de grupo opcional para contextos multiusuario +`history`: Historial de conversación opcional como lista de diccionarios de mensajes + +**Retorna:** str: Respuesta final del agente + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +Detectar el tipo de datos de una muestra de datos estructurados. + +**Argumentos:** + +`sample`: Muestra de datos a analizar (contenido de cadena) + +**Retorna:** diccionario con detected_type, confidence y metadatos opcionales. + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +Realizar un diagnóstico de datos combinado: detectar el tipo y generar un descriptor. + +**Argumentos:** + +`sample`: Muestra de datos a analizar (contenido de cadena) +`schema_name`: Nombre de esquema de destino opcional para la generación del descriptor. +`options`: Parámetros opcionales (por ejemplo, delimitador para CSV). + +**Retorna:** diccionario con detected_type, confidence, descriptor y metadatos. + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +Consultar fragmentos de documentos utilizando similitud semántica. + +Encuentra fragmentos de documentos cuyo contenido sea semánticamente similar al +texto de entrada, utilizando incrustaciones vectoriales. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica. +`user`: Identificador de usuario/espacio de claves. +`collection`: Identificador de colección. +`limit`: Número máximo de resultados (por defecto: 10). + +**Retorna:** diccionario: Resultados de la consulta con fragmentos que contienen chunk_id y score. + +**Ejemplo:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +Ejecutar una consulta de Generación Aumentada por Recuperación (RAG) basada en documentos. + +RAG basada en documentos utiliza incrustaciones vectoriales para encontrar fragmentos de documentos relevantes, +y luego genera una respuesta utilizando un LLM con esos fragmentos como contexto. + +**Argumentos:** + +`query`: Consulta en lenguaje natural +`user`: Identificador de usuario/espacio de claves (por defecto: "trustgraph") +`collection`: Identificador de colección (por defecto: "default") +`doc_limit`: Número máximo de fragmentos de documentos a recuperar (por defecto: 10) + +**Retorna:** str: Respuesta generada que incorpora el contexto del documento + +**Ejemplo:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +Genera incrustaciones vectoriales para uno o más textos. + +Convierte textos en representaciones vectoriales densas adecuadas para la +búsqueda semántica y la comparación de similitud. + +**Argumentos:** + +`texts`: Lista de textos de entrada para incrustar + +**Retorna:** list[list[list[float]]]: Incrustaciones vectoriales, un conjunto por texto de entrada + +**Ejemplo:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +Generar un descriptor para el mapeo de datos estructurados a un esquema específico. + +**Argumentos:** + +`sample`: Muestra de datos a analizar (contenido de cadena) +`data_type`: Tipo de datos (csv, json, xml) +`schema_name`: Nombre del esquema de destino para la generación del descriptor +`options`: Parámetros opcionales (por ejemplo, delimitador para CSV) + +**Retorna:** diccionario con el descriptor y metadatos + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +Consultar entidades de un grafo de conocimiento utilizando similitud semántica. + +Encuentra entidades en el grafo de conocimiento cuyas descripciones son semánticamente +similares al texto de entrada, utilizando incrustaciones vectoriales. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`limit`: Número máximo de resultados (por defecto: 10) + +**Retorna:** diccionario: Resultados de la consulta con entidades similares + +**Ejemplo:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +Ejecutar una consulta de Generación Aumentada por Recuperación (RAG) basada en grafos. + +Graph RAG utiliza la estructura del grafo de conocimiento para encontrar el contexto relevante mediante +el recorrido de las relaciones entre entidades, y luego genera una respuesta utilizando un LLM. + +**Argumentos:** + +`query`: Consulta en lenguaje natural +`user`: Identificador de usuario/espacio de claves (por defecto: "trustgraph") +`collection`: Identificador de colección (por defecto: "default") +`entity_limit`: Número máximo de entidades a recuperar (por defecto: 50) +`triple_limit`: Número máximo de triples por entidad (por defecto: 30) +`max_subgraph_size`: Número máximo total de triples en el subgrafo (por defecto: 150) +`max_path_length`: Profundidad máxima de recorrido (por defecto: 2) + +**Retorna:** str: Respuesta generada que incorpora el contexto del grafo + +**Ejemplo:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +Cargar un documento binario para su procesamiento. + +Sube un documento (PDF, DOCX, imágenes, etc.) para la extracción y +procesamiento a través de la canalización de documentos del flujo. + +**Argumentos:** + +`document`: Contenido del documento como bytes +`id`: Identificador de documento opcional (se genera automáticamente si es None) +`metadata`: Metadatos opcionales (lista de Triples o objeto con método emit) +`user`: Identificador de usuario/espacio de claves (opcional) +`collection`: Identificador de colección (opcional) + +**Retorna:** dict: Respuesta de procesamiento + +**Lanza:** + +`RuntimeError`: Si se proporcionan metadatos sin id + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +Cargar contenido de texto para su procesamiento. + +Carga contenido de texto para la extracción y el procesamiento a través de la +canalización de texto del flujo. + +**Argumentos:** + +`text`: Contenido de texto como bytes +`id`: Identificador de documento opcional (se genera automáticamente si es None) +`metadata`: Metadatos opcionales (lista de Triples o objeto con método emit) +`charset`: Codificación de caracteres (predeterminado: "utf-8") +`user`: Identificador de usuario/espacio de claves (opcional) +`collection`: Identificador de colección (opcional) + +**Retorna:** dict: Respuesta de procesamiento + +**Genera:** + +`RuntimeError`: Si se proporcionan metadatos sin id + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +Ejecutar una herramienta de Protocolo de Contexto de Modelo (MCP). + +Las herramientas MCP proporcionan funcionalidades extensibles para agentes y flujos de trabajo, +permitiendo la integración con sistemas y servicios externos. + +**Argumentos:** + +`name`: Nombre/identificador de la herramienta +`parameters`: Diccionario de parámetros de la herramienta (por defecto: {}) + +**Retorna:** str o dict: Resultado de la ejecución de la herramienta + +**Genera:** + +`ProtocolException`: Si el formato de la respuesta no es válido + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +Convertir una pregunta en lenguaje natural en una consulta GraphQL. + +**Argumentos:** + +`question`: Pregunta en lenguaje natural +`max_results`: Número máximo de resultados a devolver (por defecto: 100) + +**Retorna:** diccionario con graphql_query, variables, detected_schemas, confidence + +### `prompt(self, id, variables)` + +Ejecutar una plantilla de prompt con sustitución de variables. + +Las plantillas de solicitud permiten patrones de solicitud reutilizables con variables dinámicas. +de sustitución, útiles para una ingeniería de solicitudes consistente. + +**Argumentos:** + +`id`: Identificador de la plantilla de solicitud. +`variables`: Diccionario de mapeos de nombres de variables a valores. + +**Retorna:** str o dict: Resultado de la solicitud renderizada (texto u objeto estructurado). + +**Genera:** + +`ProtocolException`: Si el formato de la respuesta no es válido. + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +Realice una solicitud de servicio en esta instancia de flujo. + +**Argumentos:** + +`path`: Ruta del servicio (por ejemplo, "service/text-completion") +`request`: Diccionario de carga útil de la solicitud + +**Retorna:** dict: Respuesta del servicio + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +Consulta datos de fila utilizando similitud semántica en campos indexados. + +Encuentra filas cuyos valores de campo indexados son semánticamente similares al +texto de entrada, utilizando incrustaciones vectoriales. Esto permite la coincidencia difusa/semántica +en datos estructurados. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica +`schema_name`: Nombre del esquema para buscar +`user`: Identificador de usuario/espacio de claves (predeterminado: "trustgraph") +`collection`: Identificador de colección (predeterminado: "default") +`index_name`: Nombre de índice opcional para filtrar la búsqueda a un índice específico +`limit`: Número máximo de resultados (predeterminado: 10) + +**Retorna:** dict: Resultados de la consulta con coincidencias que contienen index_name, index_value, text y score + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +Ejecutar una consulta GraphQL contra filas estructuradas en el grafo de conocimiento. + +Consulta datos estructurados utilizando la sintaxis GraphQL, lo que permite consultas complejas +con filtrado, agregación y recorrido de relaciones. + +**Argumentos:** + +`query`: Cadena de consulta GraphQL +`user`: Identificador de usuario/espacio de claves (por defecto: "trustgraph") +`collection`: Identificador de colección (por defecto: "default") +`variables`: Diccionario opcional de variables de consulta +`operation_name`: Nombre de operación opcional para documentos de múltiples operaciones + +**Retorna:** dict: Respuesta GraphQL con los campos 'data', 'errors' y/o 'extensions' + +**Genera:** + +`ProtocolException`: Si ocurre un error a nivel del sistema + +**Ejemplo:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +Seleccionar esquemas coincidentes para una muestra de datos utilizando análisis de consultas. + +**Argumentos:** + +`sample`: Muestra de datos a analizar (contenido de cadena) +`options`: Parámetros opcionales + +**Retorna:** diccionario con el array schema_matches y metadatos + +### `structured_query(self, question, user='trustgraph', collection='default')` + +Ejecutar una pregunta en lenguaje natural contra datos estructurados. +Combina la conversión de consultas NLP y la ejecución de GraphQL. + +**Argumentos:** + +`question`: Pregunta en lenguaje natural +`user`: Identificador de keyspace de Cassandra (por defecto: "trustgraph") +`collection`: Identificador de colección de datos (por defecto: "default") + +**Retorna:** diccionario con datos y posibles errores + +### `text_completion(self, system, prompt)` + +Ejecutar la finalización de texto utilizando el LLM del flujo. + +**Argumentos:** + +`system`: Prompt del sistema que define el comportamiento del asistente +`prompt`: Prompt/pregunta del usuario + +**Retorna:** str: Texto de respuesta generado + +**Ejemplo:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +Consultar tripletas del grafo de conocimiento utilizando la coincidencia de patrones. + +Busca tripletas RDF que coincidan con los patrones de sujeto, predicado y/o +objeto dados. Los parámetros no especificados actúan como comodines. + +**Argumentos:** + +`s`: URI del sujeto (opcional, usar None para comodín) +`p`: URI del predicado (opcional, usar None para comodín) +`o`: URI del objeto o Literal (opcional, usar None para comodín) +`user`: Identificador de usuario/espacio de claves (opcional) +`collection`: Identificador de colección (opcional) +`limit`: Número máximo de resultados a devolver (por defecto: 10000) + +**Devuelve:** list[Triple]: Lista de objetos Triple coincidentes + +**Genera:** + +`RuntimeError`: Si s o p no son un Uri, o o no es un Uri/Literal + +**Ejemplo:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +Cliente de gestión de flujos asíncronos que utiliza la API REST. + +Proporciona operaciones de gestión de flujos basadas en async/await, incluyendo listar, +iniciar, detener flujos y gestionar definiciones de clases de flujos. También proporciona +acceso a servicios específicos del flujo, como agentes, RAG y consultas, a través de +puntos finales REST no basados en transmisión. + +Nota: Para el soporte de transmisión, utilice AsyncSocketClient en su lugar. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializa el cliente de flujo asíncrono. + +**Argumentos:** + +`url`: URL base para la API de TrustGraph +`timeout`: Tiempo de espera de la solicitud en segundos +`token`: Token de portador opcional para la autenticación + +### `aclose(self) -> None` + +Cierra el cliente asíncrono y libera recursos. + +Nota: La limpieza se gestiona automáticamente por los administradores de contexto de sesión de aiohttp. +Este método se proporciona para mantener la coherencia con otros clientes asíncronos. + +### `delete_class(self, class_name: str)` + +Elimina una definición de clase de flujo. + +Elimina una plantilla de clase de flujo del sistema. No afecta a +instancias de flujo en ejecución. + +**Argumentos:** + +`class_name`: Nombre de la clase de flujo a eliminar + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +Obtener la definición del flujo. + +Recupera la configuración completa del flujo, incluyendo su nombre de clase, +descripción y parámetros. + +**Argumentos:** + +`id`: Identificador del flujo + +**Retorna:** dict: Objeto de definición del flujo + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +Obtener la definición de la clase de flujo. + +Recupera la definición del esquema para una clase de flujo, incluyendo su +esquema de configuración y enlaces de servicio. + +**Argumentos:** + +`class_name`: Nombre de la clase de flujo + +**Retorna:** dict: Objeto de definición de la clase de flujo + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +Obtener una instancia de cliente de flujo asíncrono. + +Devuelve un cliente para interactuar con los servicios de un flujo específico +(agente, RAG, consultas, incrustaciones, etc.). + +**Argumentos:** + +`flow_id`: Identificador del flujo + +**Devuelve:** AsyncFlowInstance: Cliente para operaciones específicas del flujo + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +Listar todos los identificadores de flujo. + +Recupera los ID de todos los flujos actualmente implementados en el sistema. + +**Retorna:** list[str]: Lista de identificadores de flujo. + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +Listar todos los nombres de las clases de flujo. + +Recupera los nombres de todas las clases de flujo (plantillas) disponibles en el sistema. + +**Retorna:** list[str]: Lista de nombres de clases de flujo. + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +Crear o actualizar una definición de clase de flujo. + +Almacena un esquema de clase de flujo que se puede utilizar para instanciar flujos. + +**Argumentos:** + +`class_name`: Nombre de la clase de flujo +`definition`: Objeto de definición de la clase de flujo + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Realizar una solicitud HTTP POST asíncrona a la API de Gateway. + +Método interno para realizar solicitudes autenticadas a la API de TrustGraph. + +**Argumentos:** + +`path`: Ruta de punto final de la API (relativa a la URL base) +`request_data`: Diccionario de carga útil de la solicitud + +**Retorna:** dict: Objeto de respuesta de la API + +**Genera:** + +`ProtocolException`: Si el estado HTTP no es 200 o la respuesta no es un JSON válido +`ApplicationException`: Si la API devuelve una respuesta de error + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +Inicia una nueva instancia de flujo. + +Crea e inicia un flujo a partir de una definición de clase de flujo con los +parámetros especificados. + +**Argumentos:** + +`class_name`: Nombre de la clase de flujo a instanciar +`id`: Identificador para la nueva instancia de flujo +`description`: Descripción legible por humanos del flujo +`parameters`: Parámetros de configuración opcionales para el flujo + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +Detener un flujo en ejecución. + +Detiene y elimina una instancia de flujo, liberando sus recursos. + +**Argumentos:** + +`id`: Identificador del flujo a detener + +**Ejemplo:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +Cliente de instancia de flujo asíncrono. + +Proporciona acceso async/await a servicios con ámbito de flujo, incluyendo agentes, +consultas RAG, incrustaciones y consultas de grafos. Todas las operaciones devuelven +respuestas completas (no en streaming). + +Nota: Para soporte de streaming, utilice AsyncSocketFlowInstance en su lugar. + +### Métodos + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +Inicializa una instancia de flujo asíncrono. + +**Argumentos:** + +`flow`: Cliente AsyncFlow padre +`flow_id`: Identificador de flujo + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +Ejecuta una operación de agente (no en streaming). + +Ejecuta un agente para responder a una pregunta, con un estado de conversación opcional y +historial. Devuelve la respuesta completa después de que el agente haya terminado de +procesar. + +Nota: Este método no admite streaming. Para los pensamientos y observaciones del agente en tiempo real, +utilice AsyncSocketFlowInstance.agent() en su lugar. + +**Argumentos:** + +`question`: Pregunta o instrucción del usuario +`user`: Identificador del usuario +`state`: Diccionario de estado opcional para el contexto de la conversación +`group`: Identificador de grupo opcional para la gestión de sesiones +`history`: Lista de historial de conversación opcional +`**kwargs`: Parámetros adicionales específicos del servicio + +**Devuelve:** dict: Respuesta completa del agente, incluyendo la respuesta y los metadatos + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +Ejecutar consulta RAG basada en documentos (no en streaming). + +Realiza Generación Aumentada por Recuperación utilizando incrustaciones de documentos. +Recupera fragmentos de documentos relevantes mediante búsqueda semántica y luego genera +una respuesta basada en los documentos recuperados. Devuelve la respuesta completa. + +Nota: Este método no admite el streaming. Para respuestas RAG en streaming, +utilice AsyncSocketFlowInstance.document_rag() en su lugar. + +**Argumentos:** + +`query`: Texto de la consulta del usuario +`user`: Identificador del usuario +`collection`: Identificador de la colección que contiene los documentos +`doc_limit`: Número máximo de fragmentos de documentos a recuperar (por defecto: 10) +`**kwargs`: Parámetros adicionales específicos del servicio + +**Devuelve:** str: Respuesta generada completa basada en los datos del documento + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +Generar incrustaciones (embeddings) para textos de entrada. + +Convierte textos en representaciones vectoriales numéricas utilizando el modelo de incrustación configurado en el flujo. Útil para la búsqueda semántica y comparaciones de similitud. + + + +**Argumentos:** + +`texts`: Lista de textos de entrada para incrustar +`**kwargs`: Parámetros adicionales específicos del servicio + +**Retorna:** dict: Respuesta que contiene vectores de incrustación + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +Consulta incrustaciones de grafos para la búsqueda semántica de entidades. + +Realiza una búsqueda semántica sobre las incrustaciones de entidades de grafos para encontrar entidades +más relevantes para el texto de entrada. Devuelve entidades clasificadas por similitud. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica +`user`: Identificador de usuario +`collection`: Identificador de la colección que contiene las incrustaciones de grafos +`limit`: Número máximo de resultados a devolver (por defecto: 10) +`**kwargs`: Parámetros adicionales específicos del servicio + +**Devuelve:** dict: Respuesta que contiene coincidencias de entidades clasificadas con puntuaciones de similitud + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +Ejecutar consulta RAG basada en grafos (no en streaming). + +Realiza la generación aumentada con recuperación utilizando datos de grafos de conocimiento. +Identifica entidades relevantes y sus relaciones, y luego genera una +respuesta basada en la estructura del grafo. Devuelve la respuesta completa. + +Nota: Este método no admite el streaming. Para respuestas RAG en streaming, +utilice AsyncSocketFlowInstance.graph_rag() en su lugar. + +**Argumentos:** + +`query`: Texto de la consulta del usuario +`user`: Identificador del usuario +`collection`: Identificador de la colección que contiene el grafo de conocimiento +`max_subgraph_size`: Número máximo de triples por subgrafo (por defecto: 1000) +`max_subgraph_count`: Número máximo de subgrafos a recuperar (por defecto: 5) +`max_entity_distance`: Distancia máxima del grafo para la expansión de entidades (por defecto: 3) +`**kwargs`: Parámetros adicionales específicos del servicio + +**Devuelve:** str: Respuesta completa generada basada en datos del grafo + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Realizar una solicitud a un servicio con ámbito de flujo. + +Método interno para llamar a servicios dentro de esta instancia de flujo. + +**Argumentos:** + +`service`: Nombre del servicio (por ejemplo, "agent", "graph-rag", "triples") +`request_data`: Carga útil de la solicitud al servicio + +**Retorna:** dict: Objeto de respuesta del servicio + +**Lanza:** + +`ProtocolException`: Si la solicitud falla o la respuesta es inválida +`ApplicationException`: Si el servicio devuelve un error + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +Consultar incrustaciones de filas para la búsqueda semántica en datos estructurados. + +Realiza una búsqueda semántica sobre las incrustaciones del índice de filas para encontrar filas cuyas +valores de campo indexados sean más similares al texto de entrada. Permite +la coincidencia difusa/semántica en datos estructurados. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica +`schema_name`: Nombre del esquema para buscar +`user`: Identificador de usuario (por defecto: "trustgraph") +`collection`: Identificador de colección (por defecto: "default") +`index_name`: Nombre de índice opcional para filtrar la búsqueda a un índice específico +`limit`: Número máximo de resultados a devolver (por defecto: 10) +`**kwargs`: Parámetros adicionales específicos del servicio + +**Retorna:** dict: Respuesta que contiene coincidencias con index_name, index_value, text y score + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +Ejecutar una consulta GraphQL en filas almacenadas. + +Consulta filas de datos estructurados utilizando la sintaxis GraphQL. Soporta consultas complejas +con variables y operaciones con nombre. + +**Argumentos:** + +`query`: Cadena de consulta GraphQL +`user`: Identificador de usuario +`collection`: Identificador de la colección que contiene las filas +`variables`: Variables de consulta GraphQL opcionales +`operation_name`: Nombre de operación opcional para consultas con múltiples operaciones +`**kwargs`: Parámetros adicionales específicos del servicio + +**Retorna:** dict: Respuesta GraphQL con datos y/o errores + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +Generar finalización de texto (no en tiempo real). + +Genera una respuesta de texto a partir de un modelo de lenguaje grande (LLM) dado un mensaje del sistema y un mensaje del usuario. +Devuelve el texto de la respuesta completo. + +Nota: Este método no admite la transmisión. Para la generación de texto en tiempo real, +utilice AsyncSocketFlowInstance.text_completion() en su lugar. + +**Argumentos:** + +`system`: Mensaje del sistema que define el comportamiento del LLM. +`prompt`: Mensaje del usuario o pregunta. +`**kwargs`: Parámetros adicionales específicos del servicio. + +**Devuelve:** str: Respuesta de texto generada completa. + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +Consultar triples RDF utilizando la coincidencia de patrones. + +Busca triples que coincidan con los patrones especificados de sujeto, predicado y/o +objeto. Los patrones utilizan None como comodín para coincidir con cualquier valor. + +**Argumentos:** + +`s`: Patrón de sujeto (None para comodín) +`p`: Patrón de predicado (None para comodín) +`o`: Patrón de objeto (None para comodín) +`user`: Identificador de usuario (None para todos los usuarios) +`collection`: Identificador de colección (None para todas las colecciones) +`limit`: Número máximo de triples a devolver (por defecto: 100) +`**kwargs`: Parámetros adicionales específicos del servicio + +**Devuelve:** dict: Respuesta que contiene los triples coincidentes + +**Ejemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +Cliente WebSocket sincrónico para operaciones de transmisión. + +Proporciona una interfaz sincrónica a los servicios TrustGraph basados en WebSocket, +envolviendo la biblioteca de WebSockets asíncronos con generadores sincrónicos para facilitar su uso. +Admite respuestas de transmisión de agentes, consultas RAG y finalizaciones de texto. + +Nota: Este es un envoltorio sincrónico alrededor de operaciones de WebSocket asíncronas. Para +un soporte asíncrono real, utilice AsyncSocketClient en su lugar. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializa el cliente WebSocket sincrónico. + +**Argumentos:** + +`url`: URL base para la API de TrustGraph (HTTP/HTTPS se convertirá a WS/WSS) +`timeout`: Tiempo de espera de WebSocket en segundos +`token`: Token de portador opcional para la autenticación + +### `close(self) -> None` + +Cierra las conexiones WebSocket. + +Nota: La limpieza se gestiona automáticamente por los administradores de contexto en el código asíncrono. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +Obtiene una instancia de flujo para operaciones de transmisión de WebSocket. + +**Argumentos:** + +`flow_id`: Identificador de flujo + +**Devuelve:** SocketFlowInstance: Instancia de flujo con métodos de transmisión + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +Instancia de flujo WebSocket sincrónico para operaciones de transmisión. + +Proporciona la misma interfaz que FlowInstance de REST, pero con soporte de transmisión basado en WebSocket +para respuestas en tiempo real. Todos los métodos admiten un parámetro opcional +`streaming` para habilitar la entrega incremental de resultados. + +### Métodos + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +Inicializar instancia de flujo de socket. + +**Argumentos:** + +`client`: SocketClient padre +`flow_id`: Identificador de flujo + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +Ejecutar una operación de agente con soporte de transmisión. + +Los agentes pueden realizar razonamientos de varios pasos con el uso de herramientas. Este método siempre +devuelve fragmentos de transmisión (pensamientos, observaciones, respuestas) incluso cuando +streaming=False, para mostrar el proceso de razonamiento del agente. + +**Argumentos:** + +`question`: Pregunta o instrucción del usuario +`user`: Identificador del usuario +`state`: Diccionario de estado opcional para conversaciones con estado +`group`: Identificador de grupo opcional para contextos multiusuario +`history`: Historial de conversación opcional como lista de diccionarios de mensajes +`streaming`: Habilitar el modo de transmisión (predeterminado: False) +`**kwargs`: Parámetros adicionales pasados al servicio del agente + +**Devuelve:** Iterator[StreamingChunk]: Flujo de pensamientos, observaciones y respuestas del agente + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +Ejecutar una operación de agente con soporte de explicabilidad. + +Transmite tanto los fragmentos de contenido (AgentThought, AgentObservation, AgentAnswer) +como los eventos de procedencia (ProvenanceEvent). Los eventos de procedencia contienen URIs +que se pueden recuperar utilizando ExplainabilityClient para obtener información detallada +sobre el proceso de razonamiento del agente. + +El rastro del agente consiste en: +Sesión: La pregunta inicial y los metadatos de la sesión. +Iteraciones: Cada ciclo de pensamiento/acción/observación. +Conclusión: La respuesta final. + +**Argumentos:** + +`question`: Pregunta o instrucción del usuario. +`user`: Identificador del usuario. +`collection`: Identificador de la colección para el almacenamiento de la procedencia. +`state`: Diccionario de estado opcional para conversaciones con estado. +`group`: Identificador de grupo opcional para contextos multiusuario. +`history`: Historial de conversación opcional como una lista de diccionarios de mensajes. +`**kwargs`: Parámetros adicionales pasados al servicio del agente. +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: Fragmentos del agente y eventos de procedencia. + +**Ejemplo:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Consultar fragmentos de documentos utilizando similitud semántica. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`limit`: Número máximo de resultados (por defecto: 10) +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** dict: Resultados de la consulta con los ID de los fragmentos de los documentos coincidentes + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Ejecutar una consulta RAG basada en documentos con transmisión opcional. + +Utiliza incrustaciones vectoriales para encontrar fragmentos de documentos relevantes y luego genera +una respuesta utilizando un LLM. El modo de transmisión entrega resultados de forma incremental. + +**Argumentos:** + +`query`: Consulta en lenguaje natural +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`doc_limit`: Número máximo de fragmentos de documentos a recuperar (predeterminado: 10) +`streaming`: Habilitar el modo de transmisión (predeterminado: Falso) +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** Union[str, Iterator[str]]: Respuesta completa o flujo de fragmentos de texto + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Ejecutar una consulta RAG basada en documentos con soporte para la explicabilidad. + +Transmite tanto los fragmentos de contenido (RAGChunk) como los eventos de procedencia (ProvenanceEvent). +Los eventos de procedencia contienen URIs que se pueden recuperar utilizando ExplainabilityClient +para obtener información detallada sobre cómo se generó la respuesta. + +El rastro RAG del documento consiste en: +Pregunta: La consulta del usuario +Exploración: Fragmentos recuperados de la tienda de documentos (chunk_count) +Síntesis: La respuesta generada + +**Argumentos:** + +`query`: Consulta en lenguaje natural +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`doc_limit`: Número máximo de fragmentos de documento a recuperar (por defecto: 10) +`**kwargs`: Parámetros adicionales pasados al servicio +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Fragmentos de contenido y eventos de procedencia + +**Ejemplo:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +Generar incrustaciones vectoriales para uno o más textos. + +**Argumentos:** + +`texts`: Lista de textos de entrada para incrustar. +`**kwargs`: Parámetros adicionales pasados al servicio. + +**Retorna:** dict: Respuesta que contiene vectores (un conjunto por texto de entrada). + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Consultar entidades de un grafo de conocimiento utilizando similitud semántica. + +**Argumentos:** + +`text`: Texto de la consulta para la búsqueda semántica +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`limit`: Número máximo de resultados (por defecto: 10) +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** dict: Resultados de la consulta con entidades similares + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Ejecutar una consulta RAG basada en grafos con transmisión opcional. + +Utiliza la estructura del grafo de conocimiento para encontrar el contexto relevante y luego genera +una respuesta utilizando un LLM. El modo de transmisión entrega los resultados de forma incremental. + +**Argumentos:** + +`query`: Consulta en lenguaje natural +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`max_subgraph_size`: Número máximo total de triples en el subgrafo (por defecto: 1000) +`max_subgraph_count`: Número máximo de subgrafos (por defecto: 5) +`max_entity_distance`: Profundidad máxima de recorrido (por defecto: 3) +`streaming`: Habilitar el modo de transmisión (por defecto: False) +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** Union[str, Iterator[str]]: Respuesta completa o flujo de fragmentos de texto + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Ejecutar consulta RAG basada en grafos con soporte de explicabilidad. + +Transmite tanto fragmentos de contenido (RAGChunk) como eventos de procedencia (ProvenanceEvent). +Los eventos de procedencia contienen URIs que se pueden recuperar utilizando ExplainabilityClient +para obtener información detallada sobre cómo se generó la respuesta. + +**Argumentos:** + +`query`: Consulta en lenguaje natural +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`max_subgraph_size`: Número máximo total de triples en el subgrafo (predeterminado: 1000) +`max_subgraph_count`: Número máximo de subgrafos (predeterminado: 5) +`max_entity_distance`: Profundidad máxima de recorrido (predeterminado: 3) +`**kwargs`: Parámetros adicionales pasados al servicio +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Fragmentos de contenido y eventos de procedencia + +**Ejemplo:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +Ejecutar una herramienta de Protocolo de Contexto de Modelo (MCP). + +**Argumentos:** + +`name`: Nombre/identificador de la herramienta +`parameters`: Diccionario de parámetros de la herramienta +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** dict: Resultado de la ejecución de la herramienta + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Ejecutar una plantilla de prompt con transmisión opcional. + +**Argumentos:** + +`id`: Identificador de la plantilla de prompt. +`variables`: Diccionario de mapeos de nombres de variables a valores. +`streaming`: Habilitar el modo de transmisión (predeterminado: False). +`**kwargs`: Parámetros adicionales pasados al servicio. + +**Retorna:** Union[str, Iterator[str]]: Respuesta completa o flujo de fragmentos de texto. + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Consulta datos de filas utilizando la similitud semántica en campos indexados. + +Encuentra filas cuyos valores de campos indexados son semánticamente similares a +el texto de entrada, utilizando incrustaciones vectoriales. Esto permite la coincidencia difusa/semántica +en datos estructurados. + +**Argumentos:** + +`text`: Texto de consulta para la búsqueda semántica +`schema_name`: Nombre del esquema para buscar +`user`: Identificador de usuario/espacio de claves (predeterminado: "trustgraph") +`collection`: Identificador de colección (predeterminado: "default") +`index_name`: Nombre de índice opcional para filtrar la búsqueda a un índice específico +`limit`: Número máximo de resultados (predeterminado: 10) +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** dict: Resultados de la consulta con coincidencias que contienen index_name, index_value, text y score + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +Ejecutar una consulta GraphQL contra filas estructuradas. + +**Argumentos:** + +`query`: Cadena de consulta GraphQL +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`variables`: Diccionario opcional de variables de consulta +`operation_name`: Nombre de operación opcional para documentos de múltiples operaciones +`**kwargs`: Parámetros adicionales pasados al servicio + +**Retorna:** dict: Respuesta GraphQL con datos, errores y/o extensiones + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +Ejecutar la finalización de texto con transmisión opcional. + +**Argumentos:** + +`system`: Instrucción del sistema que define el comportamiento del asistente. +`prompt`: Instrucción/pregunta del usuario. +`streaming`: Habilitar el modo de transmisión (predeterminado: False). +`**kwargs`: Parámetros adicionales pasados al servicio. + +**Retorna:** Union[str, Iterator[str]]: Respuesta completa o flujo de fragmentos de texto. + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +Consultar triples del grafo de conocimiento utilizando la coincidencia de patrones. + +**Argumentos:** + +`s`: Filtro de sujeto - Cadena URI, diccionario de términos o None para comodín. +`p`: Filtro de predicado - Cadena URI, diccionario de términos o None para comodín. +`o`: Filtro de objeto - Cadena URI/literal, diccionario de términos o None para comodín. +`g`: Filtro de grafo con nombre - Cadena URI o None para todos los grafos. +`user`: Identificador de usuario/espacio de claves (opcional). +`collection`: Identificador de colección (opcional). +`limit`: Número máximo de resultados a devolver (por defecto: 100). +`**kwargs`: Parámetros adicionales pasados al servicio. + +**Retorna:** List[Dict]: Lista de triples coincidentes en formato de cable. + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +Consultar triples del grafo de conocimiento con lotes de transmisión. + +Produce lotes de triples a medida que llegan, reduciendo el tiempo para obtener el primer resultado +y la sobrecarga de memoria para conjuntos de resultados grandes. + +**Argumentos:** + +`s`: Filtro de sujeto - Cadena URI, diccionario de términos o None para comodín +`p`: Filtro de predicado - Cadena URI, diccionario de términos o None para comodín +`o`: Filtro de objeto - Cadena URI/literal, diccionario de términos o None para comodín +`g`: Filtro de grafo con nombre - Cadena URI o None para todos los grafos +`user`: Identificador de usuario/espacio de claves (opcional) +`collection`: Identificador de colección (opcional) +`limit`: Número máximo de resultados a devolver (por defecto: 100) +`batch_size`: Triples por lote (por defecto: 20) +`**kwargs`: Parámetros adicionales pasados al servicio +`Yields`: +`List[Dict]`: Lotes de triples en formato de cable + +**Ejemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +Cliente WebSocket asíncrono + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None)` + +Inicializar self. Consulte help(type(self)) para obtener la firma precisa. + +### `aclose(self)` + +Cerrar conexión WebSocket + +### `flow(self, flow_id: str)` + +Obtener la instancia de flujo asíncrono para operaciones de WebSocket + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +Flujo de WebSocket asíncrono. + +### Métodos + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +Inicializar self. Consulte help(type(self)) para obtener la firma correcta. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +Agente con transmisión opcional. + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +Documento RAG con transmisión opcional. + +### `embeddings(self, texts: list, **kwargs)` + +Generar incrustaciones de texto. + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +Consultar incrustaciones de grafos para búsqueda semántica. + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +RAG de grafos con transmisión opcional. + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +Ejecutar herramienta MCP. + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +Ejecutar prompt con transmisión opcional. + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +Consultar incrustaciones de filas para búsqueda semántica en datos estructurados. + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +Consulta GraphQL contra filas estructuradas. + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +Completar texto con transmisión opcional. + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +Consulta de patrones triples. + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +Construir un diccionario de términos en formato de cable a partir de un valor. + +Reglas de detección automática (cuando term_type es None): + Ya es un diccionario con la clave 't' -> devolver tal cual (ya es un Term) + Comienza con http://, https://, urn: -> IRI + Está encerrado entre < (por ejemplo, ) -> IRI (se eliminan los corchetes) + Cualquier otra cosa -> literal + +**Argumentos:** + +`value`: El valor del término (cadena, diccionario o None). +`term_type`: Uno de 'iri', 'literal' o None para la detección automática. +`datatype`: Tipo de datos para objetos literales (por ejemplo, xsd:integer). +`language`: Etiqueta de idioma para objetos literales (por ejemplo, en). + +**Devuelve:** dict: Diccionario de términos en formato de cable, o None si el valor es None. + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +Cliente para operaciones masivas sincrónicas para la importación/exportación. + +Proporciona una transferencia de datos masiva eficiente a través de WebSocket para conjuntos de datos grandes. +Envuelve las operaciones asíncronas de WebSocket con generadores sincrónicos para facilitar su uso. + +Nota: Para un soporte asíncrono real, utilice AsyncBulkClient en su lugar. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializa el cliente de operaciones masivas sincrónico. + +**Argumentos:** + +`url`: URL base para la API de TrustGraph (HTTP/HTTPS se convertirá a WS/WSS) +`timeout`: Tiempo de espera de WebSocket en segundos +`token`: Token de portador opcional para la autenticación + +### `close(self) -> None` + +Cierra las conexiones. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Exporta masivamente las incrustaciones de documentos desde un flujo. + +Descarga de forma eficiente todas las incrustaciones de fragmentos de documentos a través de la transmisión de WebSocket. + +**Argumentos:** + +`flow`: Identificador del flujo +`**kwargs`: Parámetros adicionales (reservados para uso futuro) + +**Devuelve:** Iterator[Dict[str, Any]]: Flujo de diccionarios de incrustaciones + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Exportación masiva de contextos de entidades desde un flujo. + +Descarga de manera eficiente toda la información del contexto de la entidad a través de transmisión WebSocket. + +**Argumentos:** + +`flow`: Identificador del flujo. +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Retorna:** Iterator[Dict[str, Any]]: Flujo de diccionarios de contexto. + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Exportación masiva de incrustaciones de grafos desde un flujo. + +Descarga de manera eficiente todas las incrustaciones de entidades de grafos a través de transmisión WebSocket. + +**Argumentos:** + +`flow`: Identificador del flujo. +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Retorna:** Iterator[Dict[str, Any]]: Flujo de diccionarios de incrustaciones. + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +Exportación masiva de triples RDF desde un flujo. + +Descarga de manera eficiente todos los triples a través de transmisión WebSocket. + +**Argumentos:** + +`flow`: Identificador del flujo. +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Retorna:** Iterator[Triple]: Flujo de objetos Triple. + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de incrustaciones de documentos en un flujo. + +Carga de manera eficiente las incrustaciones de fragmentos de documentos a través de transmisión WebSocket +para su uso en consultas RAG de documentos. + +**Argumentos:** + +`flow`: Identificador del flujo. +`embeddings`: Iterador que produce diccionarios de incrustaciones. +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Importación masiva de contextos de entidades en un flujo. + +Carga de manera eficiente la información del contexto de la entidad a través de transmisión WebSocket. +Los contextos de entidades proporcionan un contexto textual adicional sobre las entidades del gráfico +para mejorar el rendimiento de RAG. + +**Argumentos:** + +`flow`: Identificador del flujo. +`contexts`: Iterador que devuelve diccionarios de contexto. +`metadata`: Diccionario de metadatos con id, metadatos, usuario, colección. +`batch_size`: Número de contextos por lote (por defecto 100). +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de incrustaciones de grafos en un flujo. + +Carga de manera eficiente las incrustaciones de entidades de grafos a través de transmisión WebSocket. + +**Argumentos:** + +`flow`: Identificador del flujo. +`embeddings`: Iterador que produce diccionarios de incrustaciones. +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de filas estructuradas en un flujo. + +Carga de manera eficiente datos estructurados a través de transmisión WebSocket +para su uso en consultas GraphQL. + +**Argumentos:** + +`flow`: Identificador del flujo +`rows`: Iterador que produce diccionarios de filas +`**kwargs`: Parámetros adicionales (reservados para uso futuro) + +**Ejemplo:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Importación masiva de triples RDF en un flujo. + +Carga de manera eficiente un gran número de triples a través de transmisión WebSocket. + +**Argumentos:** + +`flow`: Identificador del flujo. +`triples`: Iterador que produce objetos Triple. +`metadata`: Diccionario de metadatos con id, metadatos, usuario, colección. +`batch_size`: Número de triples por lote (por defecto 100). +`**kwargs`: Parámetros adicionales (reservados para uso futuro). + +**Ejemplo:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +Cliente para operaciones masivas asíncronas. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma precisa. + +### `aclose(self) -> None` + +Cerrar conexiones. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Exportación masiva de incrustaciones de documentos a través de WebSocket. + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Exportación masiva de contextos de entidades a través de WebSocket. + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Exportación masiva de incrustaciones de grafos a través de WebSocket. + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +Exportación masiva de triples a través de WebSocket. + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de incrustaciones de documentos a través de WebSocket. + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de contextos de entidades a través de WebSocket. + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de incrustaciones de grafos a través de WebSocket. + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importación masiva de filas a través de WebSocket. + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +Importación masiva de triples a través de WebSocket. + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +Cliente de métricas sincrónicas + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma precisa. + +### `get(self) -> str` + +Obtener métricas de Prometheus como texto + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +Cliente de métricas asíncronas + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma correcta. + +### `aclose(self) -> None` + +Cerrar conexiones + +### `get(self) -> str` + +Obtener métricas de Prometheus como texto + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +Cliente para obtener entidades de explicabilidad con manejo de consistencia eventual. + +Utiliza la detección de quiescencia: obtener, esperar, obtener de nuevo, comparar. +Si los resultados son los mismos, los datos son estables. + +### Métodos + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +Inicializar el cliente de explicabilidad. + +**Argumentos:** + +`flow_instance`: Una instancia de SocketFlowInstance para consultar triples. +`retry_delay`: Retraso entre reintentos en segundos (por defecto: 0.2). +`max_retries`: Número máximo de intentos de reintento (por defecto: 10). + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +Detectar si una sesión es de tipo GraphRAG o Agent. + +**Argumentos:** + +`session_uri`: La URI de la sesión/pregunta. +`graph`: Grafo nombrado. +`user`: Identificador de usuario/espacio de claves. +`collection`: Identificador de colección. + +**Retorna:** "graphrag" o "agent". + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Obtener el rastro completo del Agent a partir de una URI de sesión. + +Sigue la cadena de procedencia: Pregunta -> Análisis(es) -> Conclusión. + +**Argumentos:** + +`session_uri`: La URI de la sesión/pregunta del agente. +`graph`: Grafo nombrado (por defecto: urn:graph:retrieval). +`user`: Identificador de usuario/espacio de claves. +`collection`: Identificador de colección. +`api`: Instancia de la API de TrustGraph para el acceso al bibliotecario (opcional). +`max_content`: Longitud máxima del contenido para la conclusión. + +**Retorna:** Diccionario con la pregunta, las iteraciones (lista de Análisis) y las entidades de conclusión. + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Obtener el rastro completo de DocumentRAG a partir de una URI de pregunta. + +Sigue la cadena de procedencia: + Pregunta -> Fundamentación -> Exploración -> Síntesis. + +**Argumentos:** + +`question_uri`: La URI de la entidad de pregunta. +`graph`: Grafo nombrado (por defecto: urn:graph:retrieval). +`user`: Identificador de usuario/espacio de claves. +`collection`: Identificador de colección. +`api`: Instancia de la API de TrustGraph para el acceso al bibliotecario (opcional). +`max_content`: Longitud máxima del contenido para la síntesis. + +**Retorna:** Diccionario con la pregunta, la fundamentación, la exploración y las entidades de síntesis. + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +Obtener contenido del bibliotecario por URI de documento. + +**Argumentos:** + +`document_uri`: La URI del documento en el bibliotecario. +`api`: Instancia de la API de TrustGraph para el acceso al bibliotecario. +`user`: Identificador de usuario para el bibliotecario. +`max_content`: Longitud máxima del contenido a retornar. + +**Retorna:** El contenido del documento como una cadena. + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +Obtener una entidad de selección de borde (utilizada por Focus). + +**Argumentos:** + +`uri`: La URI de la selección de borde. +`graph`: Grafo nombrado a consultar. +`user`: Identificador de usuario/espacio de claves. +`collection`: Identificador de colección. + +**Retorna:** EdgeSelection o None si no se encuentra. + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +Obtener una entidad de explicabilidad por URI con manejo de consistencia eventual. + +Utiliza la detección de quiescencia: +1. Obtener triples para el URI +2. Si no hay resultados, reintentar +3. Si hay resultados, esperar y obtener de nuevo +4. Si los resultados son los mismos, los datos son estables: analizar y devolver +5. Si los resultados son diferentes, los datos aún se están escribiendo: reintentar + +**Argumentos:** + +`uri`: El URI de la entidad a obtener +`graph`: Grafo con nombre para consultar (por ejemplo, "urn:graph:retrieval") +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección + +**Devuelve:** Subclase ExplainEntity o None si no se encuentra + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +Obtener una entidad Focus y todas sus selecciones de aristas. + +**Argumentos:** + +`uri`: El URI de la entidad Focus +`graph`: Grafo con nombre para consultar +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección + +**Devuelve:** Focus con edge_selections pobladas, o None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Obtener el rastro completo de GraphRAG a partir de un URI de pregunta. + +Sigue la cadena de procedencia: Pregunta -> Grounding -> Exploración -> Focus -> Síntesis + +**Argumentos:** + +`question_uri`: El URI de la entidad de pregunta +`graph`: Grafo (por defecto: urn:graph:retrieval) +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`api`: Instancia de la API TrustGraph para el acceso de bibliotecario (opcional) +`max_content`: Longitud máxima del contenido para la síntesis + +**Devuelve:** Diccionario con las entidades de pregunta, grounding, exploración, focus y síntesis + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +Listar todas las sesiones de explicabilidad (preguntas) en una colección. + +**Argumentos:** + +`graph`: Grafo (por defecto: urn:graph:retrieval) +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección +`limit`: Número máximo de sesiones a devolver + +**Devuelve:** Lista de entidades de Pregunta ordenadas por marca de tiempo (más reciente primero) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +Resolver las etiquetas para todos los componentes de una tripleta de arista. + +**Argumentos:** + +`edge`: Diccionario con claves "s", "p" y "o" +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección + +**Devuelve:** Tupla de (s_label, p_label, o_label) + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +Resolver rdfs:label para un URI, con almacenamiento en caché. + +**Argumentos:** + +`uri`: El URI para obtener la etiqueta +`user`: Identificador de usuario/espacio de claves +`collection`: Identificador de colección + +**Devuelve:** La etiqueta si se encuentra, de lo contrario, el propio URI + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +Clase base para entidades de explicabilidad. + +**Campos:** + +`uri`: +`entity_type`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +Entidad de pregunta: la consulta del usuario que inició la sesión. + +**Campos:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +Entidad de exploración: bordes/fragmentos recuperados del almacén de conocimiento. + +**Campos:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +Entidad de enfoque: bordes seleccionados con razonamiento LLM (solo GraphRAG). + +**Campos:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +Inicializa self. Consulta help(type(self)) para obtener la firma precisa. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +Entidad de síntesis: la respuesta final. + +**Campos:** + +`uri`: +`entity_type`: +`document`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Inicializa self. Consulta help(type(self)) para obtener la firma precisa. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +Entidad de análisis: un ciclo de pensar/actuar/observar (solo para el Agente). + +**Campos:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma correcta. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +Conclusión de la entidad - respuesta final (solo para el agente). + +**Campos:** + +`uri`: +`entity_type`: +`document`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Inicializa self. Consulta help(type(self)) para obtener la firma precisa. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +Un borde seleccionado con razonamiento del paso GraphRAG Focus. + +**Campos:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### Métodos + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +Inicializa self. Consulta help(type(self)) para obtener la firma precisa. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +Convierte las triples en formato de cable a tuplas (s, p, o). + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +Extrae el valor de un diccionario de términos en formato de cable. + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +Triple RDF que representa una declaración de un grafo de conocimiento. + +**Campos:** + +`s`: +`p`: +`o`: + +### Métodos + +### `__init__(self, s: str, p: str, o: str) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Crea un nuevo objeto de cadena a partir del objeto dado. Si se especifica encoding o +errors, entonces el objeto debe exponer un búfer de datos +que se decodificará utilizando la codificación y el controlador de errores especificados. +De lo contrario, devuelve el resultado de object.__str__() (si está definido) +o repr(object). +encoding tiene como valor predeterminado 'utf-8'. +errors tiene como valor predeterminado 'strict'. + +### Métodos + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Crea un nuevo objeto de cadena a partir del objeto dado. Si se especifica encoding o +errors, entonces el objeto debe exponer un búfer de datos +que se decodificará utilizando la codificación y el controlador de errores especificados. +De lo contrario, devuelve el resultado de object.__str__() (si está definido) +o repr(object). +encoding tiene como valor predeterminado 'utf-8'. +errors tiene como valor predeterminado 'strict'. + +### Métodos + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +Identificador de clave de configuración. + +**Campos:** + +`type`: +`key`: + +### Métodos + +### `__init__(self, type: str, key: str) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +Par clave-valor de configuración. + +**Campos:** + +`type`: +`key`: +`value`: + +### Métodos + +### `__init__(self, type: str, key: str, value: str) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +Metadatos para un documento en la biblioteca. + +**Atributos:** + +`parent_id: Parent document ID for child documents (empty for top`: level docs) + +**Campos:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### Métodos + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma correcta. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +Metadatos para un trabajo de procesamiento de documentos activo. + +**Campos:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### Métodos + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma correcta. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +Metadatos para una colección de datos. + +Las colecciones proporcionan un agrupamiento lógico y un aislamiento para documentos y +datos de grafos de conocimiento. + +**Atributos:** + +`name: Human`: nombre de colección legible + +**Campos:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### Métodos + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +Clase base para fragmentos de respuesta de transmisión. + +Se utiliza para operaciones de transmisión basadas en WebSocket, donde las respuestas se entregan +de forma incremental a medida que se generan. + +**Campos:** + +`content`: +`end_of_message`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +Fragmento del razonamiento/proceso de pensamiento del agente. + +Representa el razonamiento interno o los pasos de planificación del agente durante la ejecución. +Estos fragmentos muestran cómo el agente está pensando sobre el problema. + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +Fragmento de observación de la ejecución de la herramienta del agente. + +Representa el resultado u observación de la ejecución de una herramienta o acción. +Estos fragmentos muestran lo que el agente aprendió al usar herramientas. + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +Fragmento de la respuesta final del agente. + +Representa la respuesta final del agente al usuario después de completar +su razonamiento y el uso de herramientas. + +**Atributos:** + +`chunk_type: Always "final`: answer" + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +Fragmento de transmisión RAG (Generación Aumentada por Recuperación). + +Utilizado para transmitir respuestas de RAG de grafos, RAG de documentos, finalización de texto, +y otros servicios generativos. + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +Inicializa self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +Evento de procedencia para la explicabilidad. + +Emitido durante las consultas de GraphRAG cuando el modo de explicabilidad está habilitado. +Cada evento representa un nodo de procedencia creado durante el procesamiento de la consulta. + +**Campos:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### Métodos + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +Inicializar self. Consulte help(type(self)) para obtener la firma precisa. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +Se genera cuando ocurren errores en el protocolo WebSocket. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +Clase base para todos los errores del servicio TrustGraph. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +Error en el servicio del agente + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +Error del servicio de configuración + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +Error de recuperación de documentos RAG. + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +Error de gestión de flujo + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +Error de la API Gateway + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +Error de recuperación de Graph RAG. + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +Error del servicio de modelo de lenguaje grande. + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +Error de carga de datos + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +Error de búsqueda/consulta + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +Error en el servicio de consulta de procesamiento del lenguaje natural. + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +Error en el servicio de consulta de filas. + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +Error en el procesamiento de la solicitud. + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +Error en el servicio de consulta estructurada. + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +Error inesperado/desconocido + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +Clase base para todos los errores del servicio TrustGraph. + + +-- diff --git a/docs/python-api.he.md b/docs/python-api.he.md new file mode 100644 index 00000000..f309eafe --- /dev/null +++ b/docs/python-api.he.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "מדריך הפניות ל-API של TrustGraph בפייתון" +parent: "Hebrew (Beta)" +--- + +# מדריך הפניות ל-API של TrustGraph בפייתון + +> **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. + +## התקנה + +```bash +pip install trustgraph +``` + +## התחלה מהירה + +כל המחלקות והטיפוסים מיובאים מהחבילה `trustgraph.api`: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## תוכן עניינים + +### ליבה + +[Api](#api) + +### לקוחות זרימה + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### לקוחות WebSocket + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### פעולות מרובות + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### מדדים + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### סוגי נתונים + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### חריגות + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +לקוח API הראשי של TrustGraph לפעולות סינכרוניות ואסינכרוניות. + +מחלקה זו מספקת גישה לכל שירותי TrustGraph, כולל ניהול זרימות, +פעולות גרף ידע, עיבוד מסמכים, שאילתות RAG ועוד. היא תומכת +הן בדפוסי תקשורת מבוססי REST והן בדפוסי תקשורת מבוססי WebSocket. + +ניתן להשתמש בלקוח כמנהל הקשר לניקוי אוטומטי של משאבים: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### שיטות + +### `__aenter__(self)` + +כניסה למנהל הקשר אסינכרוני. + +### `__aexit__(self, *args)` + +יציאה ממנהל הקשר האסינכרוני וסגירת חיבורים. + +### `__enter__(self)` + +כניסה למנהל הקשר סינכרוני. + +### `__exit__(self, *args)` + +יציאה ממנהל הקשר הסינכרוני וסגירת חיבורים. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +אתחול לקוח ה-API של TrustGraph. + +**ארגומנטים:** + +`url`: כתובת הבסיס עבור ה-API של TrustGraph (ברירת מחדל: "http://localhost:8088/"") +`timeout`: זמן אחזור מקסימלי בשניות (ברירת מחדל: 60) +`token`: טוקן bearer אופציונלי לאימות + +**דוגמה:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +סגור את כל החיבורים של הלקוח האסינכרוניים. + +שיטה זו סוגרת חיבורי WebSocket אסינכרוניים, פעולות סיטונאיות וחיבורי זרימה. +היא נקראת אוטומטית כאשר יוצאים מתוך מנהל הקשר האסינכרוני. + +**דוגמה:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +קבל לקוח לפעולות אסינכרוניות מרובות. + +מספק פעולות ייבוא/ייצוא מרובות בסגנון async/await באמצעות WebSocket +לטיפול יעיל בערכות נתונים גדולות. + +**מחזיר:** AsyncBulkClient: לקוח לפעולות אסינכרוניות מרובות. + +**דוגמה:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +קבל לקוח זרימה מבוסס REST אסינכרוני. + +מספק גישה בסגנון async/await לפעולות זרימה. זה מועדף +עבור יישומי ומסגרות Python אסינכרוניות (FastAPI, aiohttp, וכו'). + +**מחזיר:** AsyncFlow: לקוח זרימה אסינכרוני + +**דוגמה:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +קבל לקוח מדדים אסינכרוני. + +מספק גישה בסגנון async/await למדדי Prometheus. + +**מחזיר:** AsyncMetrics: לקוח מדדים אסינכרוני + +**דוגמה:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +קבל לקוח WebSocket אסינכרוני לפעולות סטרימינג. + +מספק גישה ל-WebSocket בסגנון async/await עם תמיכה בסטרימינג. +זוהי השיטה המועדפת לסטרימינג אסינכרוני בפייתון. + +**מחזיר:** AsyncSocketClient: לקוח WebSocket אסינכרוני. + +**דוגמה:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +קבל לקוח לפעולות סינכרוניות מרובות לצורך ייבוא/ייצוא. + +פעולות מרובות מאפשרות העברת כמויות גדולות של נתונים בצורה יעילה באמצעות חיבורי WebSocket, כולל משולשות, הטמעות, הקשרים של ישויות ואובייקטים. + +**מחזיר:** BulkClient: לקוח לפעולות סינכרוניות מרובות. + +**דוגמה:** + + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +סגור את כל החיבורים של הלקוח הסינכרוניים. + +שיטה זו סוגרת חיבורי WebSocket וחיבורים לפעולות מרובות. +היא נקראת באופן אוטומטי כאשר יוצאים מתוך מנהל הקשר. + +**דוגמה:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +קבלת לקוח Collection לניהול אוספי נתונים. + +אוספים מארגנים מסמכים ונתוני גרף ידע לקבוצות +לוגיות לצורך בידוד ובקרת גישה. + +**מחזיר:** Collection: לקוח לניהול אוספים + +**דוגמה:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +קבל לקוח Config לניהול הגדרות תצורה. + +**מחזיר:** Config: לקוח לניהול תצורה + +**דוגמה:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +קבל לקוח Flow לניהול ולביצוע אינטראקציה עם זרימות. + +זרימות הן יחידות הביצוע העיקריות ב-TrustGraph, המספקות גישה ל +שירותים כמו סוכנים, שאילתות RAG, הטמעות ועיבוד מסמכים. + +**מחזיר:** Flow: לקוח לניהול זרימות + +**דוגמה:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +קבל לקוח Knowledge לניהול ליבות גרף ידע. + +**מחזיר:** לקוח לניהול גרף ידע: Knowledge + +**דוגמה:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +קבלת לקוח לספרייה לניהול מסמכים. + +הספרייה מספקת אחסון מסמכים, ניהול מטא-דאטה ו +תיאום זרימת עבודה לעיבוד. + +**החזר:** Library: לקוח לניהול ספריית מסמכים + +**דוגמה:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +קבל לקוח מדדים סינכרוני למטרות ניטור. + +שולף מדדים בפורמט Prometheus מהשירות TrustGraph +לצורך ניטור וניתוח. + +**מחזיר:** מדדים: לקוח מדדים סינכרוני + +**דוגמה:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +ביצוע בקשת REST ברמה נמוכה. + +שיטה זו מיועדת בעיקר לשימוש פנימי, אך ניתן להשתמש בה לגישה ישירה +ל-API כאשר נדרש. + +**ארגומנטים:** + +`path`: נתיב נקודת הקצה של ה-API (ביחס לכתובת הבסיס) +`request`: מטען הבקשה כמילון + +**החזרות:** dict: אובייקט תגובה + +**מעלה:** + +`ProtocolException`: אם מצב התגובה אינו 200 או שהתגובה אינה JSON +`ApplicationException`: אם התגובה מכילה שגיאה + +**דוגמה:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +קבל לקוח WebSocket סינכרוני לפעולות סטרימינג. + +חיבורי WebSocket מספקים תמיכה בסטרימינג לתגובות בזמן אמת +מסוכנים, שאילתות RAG והשלמות טקסט. שיטה זו מחזירה עטיפה סינכרונית +סביב פרוטוקול ה-WebSocket. + +**מחזיר:** SocketClient: לקוח WebSocket סינכרוני + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +לקוח לניהול זרימות עבור פעולות על תוכניות זרימה ומצבי זרימה. + +מחלקה זו מספקת שיטות לניהול תוכניות זרימה (תבניות) ו- +מצבי זרימה (זרימות פעילות). תוכניות זרימה מגדירות את המבנה ואת +הפרמטרים של הזרימות, בעוד שמצבי זרימה מייצגים זרימות פעילות שניתן +להפעיל שירותים. + +### שיטות + +### `__init__(self, api)` + +אתחול לקוח זרימה. + +**ארגומנטים:** + +`api`: מופע Api הורה לביצוע בקשות + +### `delete_blueprint(self, blueprint_name)` + +מחיקת תוכנית זרימה. + +**ארגומנטים:** + +`blueprint_name`: שם התוכנית למחיקה + +**דוגמה:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +קבלת ההגדרה של מופע זרימה פעיל. + +**ארגומנטים:** + +`id`: מזהה מופע זרימה + +**החזר:** dict: הגדרת מופע זרימה + +**דוגמה:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +קבלת הגדרה של תבנית זרימה לפי שם. + +**ארגומנטים:** + +`blueprint_name`: שם התבנית שיש לשלוף + +**החזר:** dict: הגדרת התבנית כמילון + +**דוגמה:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +קבלת מופע FlowInstance לביצוע פעולות על זרימה ספציפית. + +**ארגומנטים:** + +`id`: מזהה זרימה (ברירת מחדל: "default") + +**החזרות:** FlowInstance: מופע זרימה לפעולות שירות + +**דוגמה:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +רשום את כל מופעי ה-flow הפעילים. + +**מחזיר:** list[str]: רשימה של מזהי מופעי flow + +**דוגמה:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +רשום את כל תבניות העבודה הזמינות. + +**מחזיר:** list[str]: רשימה של שמות תבניות. + +**דוגמה:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +יצירת או עדכון תבנית זרימה. + +**ארגומנטים:** + +`blueprint_name`: שם עבור התבנית +`definition`: מילון הגדרת התבנית + +**דוגמה:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +ביצוע בקשת API בתחום (flow). + +**ארגומנטים:** + +`path`: סיומת נתיב אופציונלית עבור נקודות קצה של flow. +`request`: מילון מטען בקשה. + +**מחזיר:** dict: אובייקט תגובה. + +**מעלה:** + +`RuntimeError`: אם פרמטר הבקשה לא מצוין. + +### `start(self, blueprint_name, id, description, parameters=None)` + +התחלת מופע flow חדש מתבנית (blueprint). + +**ארגומנטים:** + +`blueprint_name`: שם התבנית (blueprint) לשימוש. +`id`: מזהה ייחודי למופע ה-flow. +`description`: תיאור קריא. +`parameters`: מילון פרמטרים אופציונלי. + +**דוגמה:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +עצירת מופע זרימה פעיל. + +**ארגומנטים:** + +`id`: מזהה של מופע הזרימה שיש לעצור. + +**דוגמה:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +מופע לקוח של Flow לביצוע שירותים ב-flow ספציפי. + +מחלקה זו מספקת גישה לכל שירותי TrustGraph, כולל: +השלמת טקסט והטמעות +פעולות סוכן עם ניהול מצב +שאילתות RAG עבור גרפים ומסמכים +פעולות גרף ידע (טריפלטים, אובייקטים) +טעינה ועיבוד מסמכים +המרה משפה טבעית לשאילתת GraphQL +ניתוח נתונים מובנים וזיהוי סכימה +ביצוע כלי MCP +תבניות הנחיה + +לשירותים ניגשים באמצעות מופע Flow פעיל, המזוהה באמצעות מזהה. + +### שיטות + +### `__init__(self, api, id)` + +אתחול FlowInstance. + +**ארגומנטים:** + +`api`: לקוח Flow ראשי +`id`: מזהה מופע Flow + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +ביצוע פעולת סוכן עם יכולות חשיבה ושימוש בכלים. + +סוכנים יכולים לבצע חשיבה רב-שלבית, להשתמש בכלים ולשמור על שיחה +מצב בין אינטראקציות. זו גרסה סינכרונית שאינה זורמת. + +**ארגומנטים:** + +`question`: שאלה או הוראה של משתמש +`user`: מזהה משתמש (ברירת מחדל: "trustgraph") +`state`: מילון מצב אופציונלי לשיחות עם מצב +`group`: מזהה קבוצה אופציונלי עבור הקשרים מרובי משתמשים +`history`: היסטוריית שיחה אופציונלית כרשימה של מילוני הודעות + +**מחזיר:** str: תשובה סופית של הסוכן + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +זיהוי סוג הנתונים של דוגמת נתונים מובנים. + +**ארגומנטים:** + +`sample`: דוגמת נתונים לניתוח (תוכן מחרוזת) + +**החזרות:** מילון עם detected_type, confidence, ומטא-נתונים אופציונליים + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +ביצוע אבחון נתונים משולב: זיהוי סוג ויצירת תיאור. + +**ארגומנטים:** + +`sample`: דוגמת נתונים לניתוח (תוכן מחרוזת) +`schema_name`: שם סכימה יעד אופציונלי ליצירת תיאור +`options`: פרמטרים אופציונליים (לדוגמה, מפריד עבור CSV) + +**החזרות:** מילון עם detected_type, confidence, descriptor, ומטא-נתונים + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +שאילתת מקטעי מסמכים באמצעות דמיון סמנטי. + +מוצאת מקטעי מסמכים שהתוכן שלהם דומה מבחינה סמנטית לטקסט +הקלט, תוך שימוש בהטמעות וקטוריות. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`limit`: מספר מקסימלי של תוצאות (ברירת מחדל: 10) + +**החזרות:** מילון: תוצאות שאילתה עם מקטעים המכילים chunk_id וציון + +**דוגמה:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +הפעל שאילתה של יצירת טקסט מבוססת אחזור מוגבר (RAG) על מסמכים. + +RAG מבוסס מסמכים משתמש בהטמעות וקטוריות כדי למצוא מקטעי מסמכים רלוונטיים, +ולאחר מכן מייצר תגובה באמצעות מודל שפה גדול (LLM) תוך שימוש במקטעים אלה כהקשר. + +**ארגומנטים:** + +`query`: שאילתה בשפה טבעית +`user`: מזהה משתמש/מרחב מפתחות (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף (ברירת מחדל: "default") +`doc_limit`: מספר מקסימלי של מקטעי מסמכים שיש לשלוף (ברירת מחדל: 10) + +**החזרות:** str: תגובה שנוצרה המשלבת הקשר של מסמכים + +**דוגמה:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +יצירת הטמעות וקטוריות עבור טקסט אחד או יותר. + +ממיר טקסטים לייצוגים וקטוריים צפופים המתאימים לחיפוש סמנטי +והשוואת דמיון. + +**ארגומנטים:** + +`texts`: רשימה של טקסטים קלט ליצירת הטמעות + +**החזרות:** list[list[list[float]]]: הטמעות וקטוריות, סט אחד לכל טקסט קלט + +**דוגמה:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +יצירת תיאור עבור מיפוי נתונים מובנים לתוך סכימה ספציפית. + +**ארגומנטים:** + +`sample`: דוגמת נתונים לניתוח (תוכן מחרוזת) +`data_type`: סוג נתונים (csv, json, xml) +`schema_name`: שם הסכימה המיועדת ליצירת התיאור +`options`: פרמטרים אופציונליים (לדוגמה, מפריד עבור CSV) + +**החזרות:** מילון עם התיאור ומטא-נתונים + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +שאילתת ישויות גרף ידע באמצעות דמיון סמנטי. + +מציאת ישויות בגרף הידע שעבורן התיאורים שלהן דומים מבחינה סמנטית +לטקסט הקלט, תוך שימוש בהטמעות וקטוריות. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`limit`: מספר מקסימלי של תוצאות (ברירת מחדל: 10) + +**החזרות:** מילון: תוצאות שאילתה עם ישויות דומות + +**דוגמה:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +הפעל שאילתה מבוססת גרפים של יצירת טקסט משופרת באמצעות אחזור (RAG). + +Graph RAG משתמש במבנה של גרף ידע כדי למצוא הקשר רלוונטי על ידי +מעבר בין קשרים של ישויות, ולאחר מכן מייצר תגובה באמצעות מודל שפה גדול (LLM). + +**ארגומנטים:** + +`query`: שאילתה בשפה טבעית +`user`: מזהה משתמש/מרחב מפתחות (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף (ברירת מחדל: "default") +`entity_limit`: מספר הישויות המקסימלי שיש להחזיר (ברירת מחדל: 50) +`triple_limit`: מספר הטריפלים המקסימלי לישות (ברירת מחדל: 30) +`max_subgraph_size`: מספר הטריפלים הכולל המקסימלי בתת-גרף (ברירת מחדל: 150) +`max_path_length`: עומק מעבר מקסימלי (ברירת מחדל: 2) + +**החזרות:** str: תגובה שנוצרה המשלבת הקשר גרפי + +**דוגמה:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +טען מסמך בינארי לעיבוד. + +העלאת מסמך (PDF, DOCX, תמונות וכו') לצורך חילוץ ו +עיבוד דרך צינור המסמכים של ה-flow. + +**ארגומנטים:** + +`document`: תוכן המסמך כבייטים +`id`: מזהה מסמך אופציונלי (נוצר אוטומטית אם לא קיים) +`metadata`: מטא-דאטה אופציונלי (רשימה של טריפלטים או אובייקט עם שיטת emit) +`user`: מזהה משתמש/מרחב מפתחות (אופציונלי) +`collection`: מזהה אוסף (אופציונלי) + +**החזרות:** dict: תגובת עיבוד + +**מעלה:** + +`RuntimeError`: אם סופק מטא-דאטה ללא מזהה + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +טעינת תוכן טקסטואלי לצורך עיבוד. + +העלאת תוכן טקסטואלי לצורך חילוץ ועיבוד דרך צינור הטקסט של ה-flow. + + +**ארגומנטים:** + +`text`: תוכן טקסטואלי בפורמט של בתים +`id`: מזהה מסמך אופציונלי (נוצר אוטומטית אם לא סופק) +`metadata`: מטא-דאטה אופציונלי (רשימה של טריפלטים או אובייקט עם שיטת emit) +`charset`: קידוד תווים (ברירת מחדל: "utf-8") +`user`: מזהה משתמש/מרחב מפתחות (אופציונלי) +`collection`: מזהה אוסף (אופציונלי) + +**החזרות:** dict: תגובת עיבוד + +**גורם לשגיאה:** + +`RuntimeError`: אם סופק מטא-דאטה ללא מזהה + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +הפעלת כלי פרוטוקול הקשר מודל (Model Context Protocol - MCP). + +כלי MCP מספקים פונקציונליות ניתנת להרחבה עבור סוכנים ותהליכי עבודה, +ומאפשרים שילוב עם מערכות ושירותים חיצוניים. + +**ארגומנטים:** + +`name`: שם/מזהה הכלי +`parameters`: מילון פרמטרים של הכלי (ברירת מחדל: {}) + +**החזרות:** str או dict: תוצאת ביצוע הכלי + +**מעלה:** + +`ProtocolException`: אם פורמט התגובה אינו תקין + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +המרת שאלה בשפה טבעית לשאילתת GraphQL. + +**ארגומנטים:** + +`question`: שאלה בשפה טבעית +`max_results`: מספר מקסימלי של תוצאות להחזרה (ברירת מחדל: 100) + +**החזרות:** מילון עם graphql_query, variables, detected_schemas, confidence + +### `prompt(self, id, variables)` + +ביצוע תבנית שאילתה עם החלפת משתנים. + +תבניות שאילתה מאפשרות דפוסי שאילתה לשימוש חוזר עם החלפת משתנים דינמית, +שימושי עבור הנדסת שאילתות עקבית. + +**ארגומנטים:** + +`id`: מזהה תבנית שאילתה +`variables`: מילון של התאמות בין שם משתנה לערך + +**החזרות:** מחרוזת או מילון: תוצאת שאילתה מעובדת (טקסט או אובייקט מובנה) + +**מעלה:** + +`ProtocolException`: אם פורמט התגובה אינו תקין + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +הגשת בקשה לשירות במקרה זה. + +**ארגומנטים:** + +`path`: נתיב השירות (לדוגמה, "service/text-completion") +`request`: מילון מטען הבקשה + +**החזר:** dict: תגובת השירות + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +שאילתת נתוני שורה באמצעות דמיון סמנטי בשדות ממופים. + +מוצאת שורות שבהן ערכי השדות הממופים דומים מבחינה סמנטית לטקסט +הקלט, תוך שימוש בהטמעות וקטוריות. זה מאפשר התאמה מעורפלת/סמנטית +בנתונים מובנים. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`schema_name`: שם הסכימה לחיפוש בתוכה +`user`: מזהה משתמש/אזור מפתחות (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף (ברירת מחדל: "default") +`index_name`: שם אינדקס אופציונלי לסינון החיפוש לאינדקס ספציפי +`limit`: מספר מקסימלי של תוצאות (ברירת מחדל: 10) + +**החזר:** dict: תוצאות שאילתה עם התאמות המכילות index_name, index_value, text ו-score + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +הפעל שאילתת GraphQL על שורות מובנות בגרף הידע. + +שאילתות נתונים מובנים באמצעות תחביר GraphQL, המאפשר שאילתות מורכבות +עם סינון, אגרגציה וניווט ביחסים. + +**ארגומנטים:** + +`query`: מחרוזת שאילתת GraphQL +`user`: מזהה משתמש/מרחב (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף (ברירת מחדל: "default") +`variables`: מילון אופציונלי של משתני שאילתה +`operation_name`: שם פעולה אופציונלי עבור מסמכים מרובי פעולות + +**החזרות:** dict: תגובת GraphQL עם השדות 'data', 'errors' ו/או 'extensions' + +**מעלה:** + +`ProtocolException`: אם מתרחשת שגיאה ברמת המערכת + +**דוגמה:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +בחירת סכימות מתאימות עבור מדגם נתונים באמצעות ניתוח שאילתות. + +**ארגומנטים:** + +`sample`: מדגם נתונים לניתוח (תוכן מחרוזת) +`options`: פרמטרים אופציונליים + +**החזרות:** מילון עם מערך schema_matches ומטא-נתונים + +### `structured_query(self, question, user='trustgraph', collection='default')` + +ביצוע שאילתה בשפה טבעית על נתונים מובנים. +משלב המרת שאילתות NLP וביצוע GraphQL. + +**ארגומנטים:** + +`question`: שאילתה בשפה טבעית +`user`: מזהה מרחב מפתחות Cassandra (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף נתונים (ברירת מחדל: "default") + +**החזרות:** מילון עם נתונים ושגיאות אופציונליות + +### `text_completion(self, system, prompt)` + +ביצוע השלמת טקסט באמצעות מודל LLM של ה-flow. + +**ארגומנטים:** + +`system`: הנחיה מערכתית המגדירה את התנהגות העוזר +`prompt`: הנחיה/שאלה של משתמש + +**החזרות:** מחרוזת: טקסט תגובה שנוצר + +**דוגמה:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +שאילת משולשים בגרף ידע באמצעות התאמת תבניות. + +מחפש משולשים RDF התואמים לתבניות נתונות של נושא, נשוא ואובייקט. +פרמטרים לא מוגדרים פועלים כתווים מתחלפים. + +**ארגומנטים:** + +`s`: מזהה URI של נושא (אופציונלי, השתמש ב-None עבור תו מתחלף) +`p`: מזהה URI של נשוא (אופציונלי, השתמש ב-None עבור תו מתחלף) +`o`: מזהה URI של אובייקט או ליטרל (אופציונלי, השתמש ב-None עבור תו מתחלף) +`user`: מזהה משתמש/מרחב מפתחות (אופציונלי) +`collection`: מזהה אוסף (אופציונלי) +`limit`: מספר תוצאות מקסימלי להחזרה (ברירת מחדל: 10000) + +**מחזיר:** list[Triple]: רשימה של אובייקטי Triple התואמים + +**מעלה:** + +`RuntimeError`: אם s או p אינם Uri, או o אינם Uri/Literal + +**דוגמה:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +לקוח לניהול זרימות אסינכרוניות באמצעות ממשק REST API. + +מספק פעולות ניהול זרימות מבוססות async/await, כולל הצגת רשימה, +התחלה, עצירה וניהול הגדרות של סוגי זרימות. כמו כן, מספק +גישה לשירותים הקשורים לזרימה, כגון סוכנים, RAG ושאילתות, באמצעות נקודות קצה (endpoints) של REST שאינן מבוססות סטרימינג. + + +הערה: לתמיכה בסטרימינג, השתמשו ב-AsyncSocketClient. + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +אתחול לקוח זרימות אסינכרוני. + +**ארגומנטים:** + +`url`: כתובת URL בסיסית עבור ממשק ה-API של TrustGraph +`timeout`: זמן אחזור (timeout) לבקשות בשניות +`token`: טוקן bearer אופציונלי לאימות + +### `aclose(self) -> None` + +סגירת הלקוח האסינכרוני ושחרור משאבים. + +הערה: ניקוי (cleanup) מטופל באופן אוטומטי על ידי מנהלי הקשר (context managers) של aiohttp. +שיטה זו מסופקת לשמירה על עקביות עם לקוחות אסינכרוניים אחרים. + +### `delete_class(self, class_name: str)` + +מחיקת הגדרת סוג זרימה. + +מסירה תבנית (blueprint) של סוג זרימה מהמערכת. אינה משפיעה על +מופעי זרימה פעילים. + +**ארגומנטים:** + +`class_name`: שם סוג הזרימה למחיקה + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +קבלת הגדרת זרימה. + +מאחזר את תצורת הזרימה המלאה, כולל שם המחלקה שלה, +התיאור שלה והפרמטרים שלה. + +**ארגומנטים:** + +`id`: מזהה זרימה + +**החזרות:** dict: אובייקט הגדרת זרימה + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +קבלת הגדרת מחלקת זרימה. + +מאחזר את הגדרת התוכנית עבור מחלקת זרימה, כולל +הסכימה שלה והקישורים לשירותים. + +**ארגומנטים:** + +`class_name`: שם מחלקת הזרימה + +**החזרות:** dict: אובייקט הגדרת מחלקת זרימה + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +קבלת מופע לקוח של זרימה אסינכרונית. + +מחזיר לקוח לצורך אינטראקציה עם השירותים של זרימה ספציפית (סוכן, RAG, שאילתות, הטמעות, וכו'). + + +**ארגומנטים:** + +`flow_id`: מזהה זרימה + +**מחזיר:** AsyncFlowInstance: לקוח לפעולות ספציפיות לזרימה + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +רשום את כל מזהי הזרימות. + +שולף את ה-IDs של כל הזרימות הפרוסות כרגע במערכת. + +**מחזיר:** list[str]: רשימה של מזהי זרימות + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +רשום את כל שמות מחלקות הזרימה. + +שולף את שמות כל מחלקות הזרימה (תבניות) הזמינות במערכת. + +**מחזיר:** list[str]: רשימה של שמות מחלקות זרימה. + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +יצירה או עדכון של הגדרה של מחלקת זרימה. + +מאחסן תוכנית אב למחלקת זרימה שניתן להשתמש בה כדי ליצור מופעים של זרימות. + +**ארגומנטים:** + +`class_name`: שם מחלקת הזרימה +`definition`: אובייקט הגדרת מחלקת הזרימה + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +ביצוע בקשת HTTP POST אסינכרונית ל-API של ה-Gateway. + +שיטה פנימית לביצוע בקשות מאומתות ל-API של TrustGraph. + +**ארגומנטים:** + +`path`: נתיב נקודת הקצה של ה-API (ביחס לכתובת הבסיס) +`request_data`: מילון מטען הבקשה + +**מחזיר:** dict: אובייקט תגובה מה-API + +**מעלה:** + +`ProtocolException`: אם קוד ה-HTTP אינו 200 או שהתגובה אינה JSON חוקי. +`ApplicationException`: אם ה-API מחזיר תגובת שגיאה. + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +התחל מופע זרימה חדש. + +יוצר ומפעיל זרימה מתוך הגדרת מחלקת זרימה עם הפרמטרים שצוינו. + + +**ארגומנטים:** + +`class_name`: שם המחלקה של הזרימה שצריך ליצור מופע עבורה. +`id`: מזהה עבור מופע הזרימה החדש. +`description`: תיאור קריא של הזרימה. +`parameters`: פרמטרי תצורה אופציונליים עבור הזרימה. + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +עצירת תהליך פעיל. + +עוצרת ומסירה מופע של תהליך, תוך שחרור המשאבים שלו. + +**ארגומנטים:** + +`id`: מזהה של התהליך שיש לעצור + +**דוגמה:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +לקוח מופע זרימה אסינכרוני. + +מספק גישה ל-async/await לשירותים המוגדרים בזרימה, כולל סוכנים, +שאילתות RAG, הטמעות ושאילתות גרף. כל הפעולות מחזירות +תגובות מלאות (לא בסטרימינג). + +הערה: לצורך תמיכה בסטרימינג, השתמשו ב-AsyncSocketFlowInstance. + +### שיטות + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +אתחול מופע זרימה אסינכרוני. + +**ארגומנטים:** + +`flow`: לקוח AsyncFlow הראשי +`flow_id`: מזהה הזרימה + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +ביצוע פעולה של סוכן (לא בסטרימינג). + +מפעיל סוכן כדי לענות על שאלה, עם מצב שיחה ואפשרויות +היסטוריה. מחזיר את התגובה המלאה לאחר שהסוכן סיים +לעבד. + +הערה: שיטה זו אינה תומכת בסטרימינג. לצורך מחשבות ותצפיות של הסוכן בזמן אמת, +השתמשו ב-AsyncSocketFlowInstance.agent() במקום. + +**ארגומנטים:** + +`question`: שאלה או הוראה של המשתמש +`user`: מזהה המשתמש +`state`: מילון מצב אופציונלי עבור הקשר שיחה +`group`: מזהה קבוצה אופציונלי לניהול סשנים +`history`: רשימת היסטוריית שיחה אופציונלית +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**מחזיר:** dict: תגובת סוכן מלאה הכוללת תשובה ומטא-נתונים + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +ביצוע שאילתת RAG מבוססת מסמכים (לא סטרימינג). + +מבצע יצירת טקסט מועשרת באמצעות הטמעות מסמכים. +שולף קטעי מסמכים רלוונטיים באמצעות חיפוש סמנטי, ולאחר מכן מייצר +תשובה המבוססת על המסמכים שנשלפו. מחזיר תשובה מלאה. + +הערה: שיטה זו אינה תומכת בסטרימינג. עבור תגובות RAG בסטרימינג, +השתמשו ב-AsyncSocketFlowInstance.document_rag() במקום זאת. + +**ארגומנטים:** + +`query`: טקסט השאילתה של המשתמש +`user`: מזהה המשתמש +`collection`: מזהה האוסף המכיל מסמכים +`doc_limit`: מספר מרבי של קטעי מסמכים לשליפה (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזרות:** str: תשובה מלאה שנוצרה המבוססת על נתוני המסמכים + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +יצירת הטמעות עבור טקסטים קלט. + +ממיר טקסטים לייצוגים וקטוריים מספריים באמצעות מודל ההטמעה המוגדר של ה-flow. +שימושי לחיפוש סמנטי והשוואות דמיון. + + +**ארגומנטים:** + +`texts`: רשימה של טקסטים קלט ליצירת הטמעה +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזרות:** dict: תגובה המכילה וקטורי הטמעה + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +שאילתת הטמעות גרף לחיפוש ישויות סמנטי. + +מבצעת חיפוש סמנטי על הטמעות ישויות גרף כדי למצוא ישויות +הרלוונטיות ביותר לטקסט הקלט. מחזירה ישויות מדורגות לפי מידת הדמיון. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`user`: מזהה משתמש +`collection`: מזהה אוסף המכיל הטמעות גרף +`limit`: מספר מקסימלי של תוצאות להחזרה (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזרות:** dict: תגובה המכילה התאמות ישויות מדורגות עם ציוני דמיון + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +ביצוע שאילתת RAG מבוססת גרפים (לא בסטרימינג). + +מבצע יצירת טקסט מועשרת באמצעות נתוני גרף ידע. +מזהה ישויות רלוונטיות ויחסים ביניהן, ולאחר מכן מייצר +תשובה המבוססת על מבנה הגרף. מחזיר תשובה מלאה. + +הערה: שיטה זו אינה תומכת בסטרימינג. עבור תשובות RAG בסטרימינג, +השתמשו ב-AsyncSocketFlowInstance.graph_rag() במקום זאת. + +**ארגומנטים:** + +`query`: טקסט השאילתה של המשתמש +`user`: מזהה המשתמש +`collection`: מזהה אוסף המכיל את גרף הידע +`max_subgraph_size`: מספר מקסימלי של משולשים לכל תת-גרף (ברירת מחדל: 1000) +`max_subgraph_count`: מספר מקסימלי של תת-גרפים לשליפה (ברירת מחדל: 5) +`max_entity_distance`: מרחק גרף מקסימלי עבור הרחבת ישויות (ברירת מחדל: 3) +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזרות:** str: תשובה מלאה שנוצרה המבוססת על נתוני גרף + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +בקשת שימוש בשירות המוגדר בתוך ה-flow. + +שיטה פנימית לביצוע קריאות לשירותים בתוך מופע ה-flow הנוכחי. + +**ארגומנטים:** + +`service`: שם השירות (לדוגמה, "agent", "graph-rag", "triples") +`request_data`: עומס (payload) של הבקשה לשירות + +**החזר:** dict: אובייקט תגובה מהשירות + +**יוצא מכלל אפשרות (Raises):** + +`ProtocolException`: אם הבקשה נכשלת או שהתגובה אינה תקינה +`ApplicationException`: אם השירות מחזיר שגיאה + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +שאילתת הטמעות שורות לחיפוש סמנטי בנתונים מובנים. + +מבצעת חיפוש סמנטי על הטמעות אינדקס השורות כדי למצוא שורות שעבורן +ערכי השדות המאונדקסים דומים ביותר לטקסט הקלט. מאפשרת +התאמה מעורפלת/סמנטית על נתונים מובנים. + +**ארגומנטים:** + +`text`: טקסט השאילתה לחיפוש סמנטי +`schema_name`: שם הסכימה לחיפוש בתוכה +`user`: מזהה משתמש (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף (ברירת מחדל: "default") +`index_name`: שם אינדקס אופציונלי לסינון החיפוש לאינדקס ספציפי +`limit`: מספר מקסימלי של תוצאות להחזרה (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזר:** dict: תגובה המכילה התאמות עם index_name, index_value, text ו-score + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +הפעלת שאילתת GraphQL על שורות שמורות. + +שאילתות שורות נתונים מובנים באמצעות תחביר GraphQL. תומך בשאילתות מורכבות +עם משתנים ופעולות בעלות שם. + +**ארגומנטים:** + +`query`: מחרוזת שאילתת GraphQL +`user`: מזהה משתמש +`collection`: מזהה אוסף המכיל שורות +`variables`: משתנים אופציונליים לשאילתת GraphQL +`operation_name`: שם פעולה אופציונלי עבור שאילתות מרובות פעולות +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזרות:** dict: תגובת GraphQL עם נתונים ושגיאות + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +יצירת השלמת טקסט (לא בזמן אמת). + +מייצרת תגובת טקסט ממודל שפה גדול (LLM) בהתבסס על הנחיה מערכתית והנחיה ממשתמש. +מחזירה את טקסט התגובה השלם. + +הערה: שיטה זו אינה תומכת בסטרימינג. לטקסט שנוצר בזמן אמת, +השתמשו ב-AsyncSocketFlowInstance.text_completion() במקום זאת. + +**ארגומנטים:** + +`system`: הנחיה מערכתית המגדירה את התנהגות ה-LLM. +`prompt`: הנחיה ממשתמש או שאלה. +`**kwargs`: פרמטרים נוספים ספציפיים לשירות. + +**מחזיר:** str: תגובת טקסט שנוצרת בשלמותה. + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +שאילת משולשות RDF באמצעות התאמת תבניות. + +מחפשת משולשות התואמות לתבניות הנקובות עבור הנושא, הנשוא ו/או +האובייקט. תבניות משתמשות ב-None כתווית מתקן כדי להתאים לכל ערך. + +**ארגומנטים:** + +`s`: תבנית נושא (None עבור תווית מתקן) +`p`: תבנית נשוא (None עבור תווית מתקן) +`o`: תבנית אובייקט (None עבור תווית מתקן) +`user`: מזהה משתמש (None עבור כל המשתמשים) +`collection`: מזהה אוסף (None עבור כל האוספים) +`limit`: מספר מקסימלי של משולשות להחזרה (ברירת מחדל: 100) +`**kwargs`: פרמטרים נוספים ספציפיים לשירות + +**החזרות:** dict: תגובה המכילה משולשות תואמות + +**דוגמה:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +לקוח WebSocket סינכרוני לפעולות סטרימינג. + +מספק ממשק סינכרוני לשירותי TrustGraph המבוססים על WebSocket, +תוך שימוש בספריית websockets אסינכרונית עם גנרטורים סינכרוניים לנוחות השימוש. +תומך בתגובות סטרימינג מסוכנים, שאילתות RAG והשלמות טקסט. + +הערה: זהו עטיפה סינכרונית סביב פעולות WebSocket אסינכרוניות. לצורך +תמיכה אסינכרונית אמיתית, השתמש ב-AsyncSocketClient. + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +אתחול לקוח WebSocket סינכרוני. + +**ארגומנטים:** + +`url`: כתובת URL בסיסית עבור ממשק ה-API של TrustGraph (HTTP/HTTPS יומרו ל-WS/WSS) +`timeout`: זמן קצוב של WebSocket בשניות +`token`: טוקן bearer אופציונלי לאימות + +### `close(self) -> None` + +סגירת חיבורי WebSocket. + +הערה: ניקוי מתבצע באופן אוטומטי על ידי מנהלי הקשר באסינכרוני. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +קבלת מופע זרימה לפעולות סטרימינג של WebSocket. + +**ארגומנטים:** + +`flow_id`: מזהה זרימה + +**מחזיר:** SocketFlowInstance: מופע זרימה עם שיטות סטרימינג + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +מופע של זרימת WebSocket סינכרונית עבור פעולות סטרימינג. + +מספק את אותו ממשק כמו FlowInstance של REST, אך עם תמיכה בסטרימינג מבוסס WebSocket +עבור תגובות בזמן אמת. כל השיטות תומכות בפרמטר אופציונלי +`streaming` כדי לאפשר שליחת תוצאות מצטברות. + +### שיטות + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +אתחול מופע זרימת שקע. + +**ארגומנטים:** + +`client`: שרת שקעים הורה (Parent SocketClient) +`flow_id`: מזהה זרימה + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +ביצוע פעולת סוכן עם תמיכה בסטרימינג. + +סוכנים יכולים לבצע ניתוח רב-שלבי עם שימוש בכלים. שיטה זו תמיד +מחזירה מקטעי סטרימינג (מחשבות, תצפיות, תשובות), גם כאשר +streaming=False, כדי להציג את תהליך החשיבה של הסוכן. + +**ארגומנטים:** + +`question`: שאלה או הוראה מהמשתמש +`user`: מזהה משתמש +`state`: מילון מצב אופציונלי לשיחות עם מצב (stateful) +`group`: מזהה קבוצה אופציונלי עבור הקשרים מרובי משתמשים +`history`: היסטוריית שיחה אופציונלית כרשימה של מילוני הודעות +`streaming`: הפעלת מצב סטרימינג (ברירת מחדל: False) +`**kwargs`: פרמטרים נוספים המועברים לשירות הסוכן + +**מחזיר:** Iterator[StreamingChunk]: זרם של מחשבות, תצפיות ותשובות של הסוכן + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +הפעל פעולה של סוכן עם תמיכה בהסבר. + +מעביר גם חלקי תוכן (AgentThought, AgentObservation, AgentAnswer) +וגם אירועי מקור (ProvenanceEvent). אירועי מקור מכילים URI שניתן לשלוף +באמצעות ExplainabilityClient כדי לקבל מידע מפורט על תהליך החשיבה של הסוכן. + + +מעקב אחר הסוכן מורכב מ: +Session: השאלה הראשונית ומטא-נתונים של הסשן +Iterations: כל מחזור מחשבה/פעולה/תצפית +Conclusion: התשובה הסופית + +**ארגומנטים:** + +`question`: שאלה או הוראה של המשתמש +`user`: מזהה משתמש +`collection`: מזהה אוסף לאחסון מקור +`state`: מילון מצב אופציונלי לשיחות עם מצב +`group`: מזהה קבוצה אופציונלי עבור הקשרים מרובי משתמשים +`history`: היסטוריית שיחה אופציונלית כרשימה של מילוני הודעות +`**kwargs`: פרמטרים נוספים המועברים לשירות הסוכן +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: חלקי סוכן ואירועי מקור + +**דוגמה:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +שאילתת מקטעי מסמכים באמצעות דמיון סמנטי. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`limit`: מספר מקסימלי של תוצאות (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** dict: תוצאות שאילתה עם מזהי מקטעים של מקטעי מסמכים תואמים + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +הפעל שאילתת RAG מבוססת מסמכים עם אפשרות של סטרימינג. + +משתמש בהטמעות וקטוריות כדי למצוא מקטעי מסמכים רלוונטיים, ולאחר מכן מייצר +תגובה באמצעות מודל שפה גדול (LLM). מצב הסטרימינג מספק תוצאות באופן מצטבר. + +**ארגומנטים:** + +`query`: שאילתה בשפה טבעית +`user`: מזהה משתמש/מרחב +`collection`: מזהה אוסף +`doc_limit`: מספר מקסימלי של מקטעי מסמכים לשליפה (ברירת מחדל: 10) +`streaming`: הפעל מצב סטרימינג (ברירת מחדל: False) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** Union[str, Iterator[str]]: תגובה מלאה או זרם של מקטעי טקסט + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +הפעל שאילתת RAG מבוססת מסמכים עם תמיכה בהסבר. + +מעביר גם מקטעי תוכן (RAGChunk) וגם אירועי מקור (ProvenanceEvent). +אירועי מקור מכילים URI שניתן לשלוף באמצעות ExplainabilityClient +כדי לקבל מידע מפורט על האופן שבו התגובה נוצרה. + +מעקב RAG של מסמך מורכב מ: +שאלה: השאילתה של המשתמש +חיפוש: מקטעים שנשלפו ממאגר המסמכים (chunk_count) +סינתזה: התשובה שנוצרה + +**ארגומנטים:** + +`query`: שאילתה בשפה טבעית +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`doc_limit`: מספר מקסימלי של מקטעי מסמכים לשליפה (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים המועברים לשירות +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: מקטעי תוכן ואירועי מקור + +**דוגמה:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +יצירת הטמעות וקטוריות עבור טקסט אחד או יותר. + +**ארגומנטים:** + +`texts`: רשימה של טקסטים קלט ליצירת הטמעות +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** dict: תגובה המכילה וקטורים (סט אחד לכל טקסט קלט) + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +שאילת שאילתות לישות גרף ידע באמצעות דמיון סמנטי. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`limit`: מספר מקסימלי של תוצאות (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** dict: תוצאות שאילתה עם ישויות דומות + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +הפעל שאילתת RAG מבוססת גרפים עם סטרימינג אופציונלי. + +משתמש במבנה גרף ידע כדי למצוא הקשר רלוונטי, ולאחר מכן מייצר +תגובה באמצעות מודל שפה גדול (LLM). מצב הסטרימינג מספק תוצאות באופן מצטבר. + +**ארגומנטים:** + +`query`: שאילתה בשפה טבעית +`user`: מזהה משתמש/מרחב +`collection`: מזהה אוסף +`max_subgraph_size`: מספר מקסימלי של משולשים בסך הכל בגרף המשנה (ברירת מחדל: 1000) +`max_subgraph_count`: מספר מקסימלי של גרפים משניים (ברירת מחדל: 5) +`max_entity_distance`: עומק מעבר מקסימלי (ברירת מחדל: 3) +`streaming`: הפעל מצב סטרימינג (ברירת מחדל: False) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**מחזיר:** Union[str, Iterator[str]]: תגובה מלאה או זרם של פיסות טקסט + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +הפעל שאילתת RAG מבוססת גרפים עם תמיכה בהסבר. + +מעביר גם מקטעי תוכן (RAGChunk) וגם אירועי מקור (ProvenanceEvent). +אירועי מקור מכילים URI שניתן לשלוף באמצעות ExplainabilityClient +כדי לקבל מידע מפורט על האופן שבו התגובה נוצרה. + +**ארגומנטים:** + +`query`: שאילתה בשפה טבעית +`user`: מזהה משתמש/מרחב +`collection`: מזהה אוסף +`max_subgraph_size`: מספר מקסימלי של משולשים בסך הכל בגרף המשנה (ברירת מחדל: 1000) +`max_subgraph_count`: מספר מקסימלי של גרפי משנה (ברירת מחדל: 5) +`max_entity_distance`: עומק מעבר מקסימלי (ברירת מחדל: 3) +`**kwargs`: פרמטרים נוספים המועברים לשירות +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: מקטעי תוכן ואירועי מקור + +**דוגמה:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +הפעלת כלי פרוטוקול הקשר מודל (MCP). + +**ארגומנטים:** + +`name`: שם/מזהה הכלי +`parameters`: מילון פרמטרים של הכלי +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזר:** dict: תוצאת ביצוע הכלי + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +הפעל תבנית פקודה עם אפשרות של סטרימינג. + +**ארגומנטים:** + +`id`: מזהה של תבנית הפקודה +`variables`: מילון של התאמות בין שם משתנה לערך +`streaming`: הפעל מצב סטרימינג (ברירת מחדל: False) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזר:** Union[str, Iterator[str]]: תגובה מלאה או סטרימינג של פיסות טקסט + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +שליפת נתוני שורה באמצעות דמיון סמנטי בשדות ממופים. + +מאתר שורות שבהן ערכי השדות הממופים דומים מבחינה סמנטית ל- +הטקסט הקלט, תוך שימוש בהטמעות וקטוריות. זה מאפשר התאמה מעורפלת/סמנטית +לנתונים מובנים. + +**ארגומנטים:** + +`text`: טקסט שאילתה לחיפוש סמנטי +`schema_name`: שם הסכימה לחיפוש בתוכה +`user`: מזהה משתמש/אזור מפתחות (ברירת מחדל: "trustgraph") +`collection`: מזהה אוסף (ברירת מחדל: "default") +`index_name`: שם אינדקס אופציונלי לסינון החיפוש לאינדקס ספציפי +`limit`: מספר מקסימלי של תוצאות (ברירת מחדל: 10) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** dict: תוצאות שאילתה עם התאמות המכילות index_name, index_value, text ו-score + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +הפעלת שאילתת GraphQL על שורות מובנות. + +**ארגומנטים:** + +`query`: מחרוזת שאילתת GraphQL +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`variables`: מילון אופציונלי של משתני שאילתה +`operation_name`: שם פעולה אופציונלי עבור מסמכים מרובי פעולות +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** dict: תגובת GraphQL עם נתונים, שגיאות ו/או הרחבות + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +הפעלת השלמת טקסט עם אפשרות של סטרימינג. + +**ארגומנטים:** + +`system`: הנחיה למערכת המגדירה את התנהגות העוזר. +`prompt`: הנחיה/שאלה מהמשתמש. +`streaming`: הפעל מצב סטרימינג (ברירת מחדל: False). +`**kwargs`: פרמטרים נוספים המועברים לשירות. + +**החזר:** Union[str, Iterator[str]]: תשובה מלאה או סטרימינג של פיסות טקסט. + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +שאילתת משולשים בגרף ידע באמצעות התאמת תבניות. + +**ארגומנטים:** + +`s`: מסנן נושא - מחרוזת URI, מילון מונחים, או None עבור wildcard +`p`: מסנן נשוא - מחרוזת URI, מילון מונחים, או None עבור wildcard +`o`: מסנן אובייקט - מחרוזת URI/literal, מילון מונחים, או None עבור wildcard +`g`: מסנן גרף מוגדר - מחרוזת URI או None עבור כל הגרפים +`user`: מזהה משתמש/מרחב מפתחות (אופציונלי) +`collection`: מזהה אוסף (אופציונלי) +`limit`: מספר תוצאות מקסימלי להחזרה (ברירת מחדל: 100) +`**kwargs`: פרמטרים נוספים המועברים לשירות + +**החזרות:** List[Dict]: רשימה של משולשים תואמים בפורמט פנימי + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +שאילת משולשים בגרף ידע באמצעות אצוות סטרימינג. + +מחזירה אצוות של משולשים כשהם מגיעים, מה שמקטין את הזמן לקבלת התוצאה הראשונה +ואת צריכת הזיכרון עבור קבוצות תוצאות גדולות. + +**ארגומנטים:** + +`s`: מסנן נושא - מחרוזת URI, מילון מונחים, או None עבור wildcard +`p`: מסנן נשוא - מחרוזת URI, מילון מונחים, או None עבור wildcard +`o`: מסנן אובייקט - מחרוזת URI/ליטרל, מילון מונחים, או None עבור wildcard +`g`: מסנן גרף מוגדר - מחרוזת URI או None עבור כל הגרפים +`user`: מזהה משתמש/מרחב מפתחות (אופציונלי) +`collection`: מזהה אוסף (אופציונלי) +`limit`: מספר תוצאות מקסימלי להחזרה (ברירת מחדל: 100) +`batch_size`: משולשים לאצווה (ברירת מחדל: 20) +`**kwargs`: פרמטרים נוספים המועברים לשירות +`Yields`: +`List[Dict]`: אצוות של משולשים בפורמט wire + +**דוגמה:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +לקוח WebSocket אסינכרוני + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None)` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + +### `aclose(self)` + +סגירת חיבור WebSocket + +### `flow(self, flow_id: str)` + +קבלת מופע זרימה אסינכרוני עבור פעולות WebSocket + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +מופע של זרימת WebSocket אסינכרונית + +### שיטות + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +אתחול של self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +סוכן עם סטרימינג אופציונלי + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +תיעוד RAG עם סטרימינג אופציונלי + +### `embeddings(self, texts: list, **kwargs)` + +יצירת הטמעות טקסט + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +שאילתא של הטמעות גרף לחיפוש סמנטי + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +RAG גרפי עם סטרימינג אופציונלי + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +הרצת כלי MCP + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +הרצת שאילתא עם סטרימינג אופציונלי + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +שאילתא של הטמעות שורות לחיפוש סמנטי על נתונים מובנים + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +שאילתא GraphQL על שורות מובנות + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +השלמת טקסט עם סטרימינג אופציונלי + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +שאילתא של תבנית משולשת + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +בניית מילון Term בפורמט wire מתוך ערך. + +כללי זיהוי אוטומטיים (כאשר term_type הוא None): + כבר מילון עם מפתח 't' -> החזר כפי שהוא (כבר Term) + מתחיל עם http://, https://, urn: -> IRI + עטוף בסוגריים זוויתיים (לדוגמה, ) -> IRI (סוגריים זוויתיים מוסרים) + כל דבר אחר -> מילולי + +**ארגומנטים:** + +`value`: ערך ה-term (מחרוזת, מילון או None) +`term_type`: אחד מ-'iri', 'literal' או None לזיהוי אוטומטי +`datatype`: סוג נתונים עבור אובייקטים מילוליים (לדוגמה, xsd:integer) +`language`: תג שפה עבור אובייקטים מילוליים (לדוגמה, en) + +**החזרות:** dict: מילון Term בפורמט wire, או None אם הערך הוא None + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +לקוח לפעולות מרובות סינכרוניות לייבוא/ייצוא. + +מספק העברת נתונים מרובה יעילה באמצעות WebSocket עבור מערכי נתונים גדולים. +עוטף פעולות WebSocket אסינכרוניות עם גנרטורים סינכרוניים לנוחות השימוש. + +הערה: לתמיכה אסינכרונית אמיתית, השתמש ב-AsyncBulkClient במקום. + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +אתחול לקוח מרובה סינכרוני. + +**ארגומנטים:** + +`url`: כתובת URL בסיסית עבור ממשק ה-API של TrustGraph (HTTP/HTTPS יומרו ל-WS/WSS) +`timeout`: זמן קצוב של WebSocket בשניות +`token`: טוקן bearer אופציונלי לאימות + +### `close(self) -> None` + +סגירת חיבורים + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +ייצוא מרובה של הטמעות מסמכים מתוך זרימה. + +מוריד ביעילות את כל הטמעות חלקי המסמכים באמצעות סטרימינג של WebSocket. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**מחזיר:** Iterator[Dict[str, Any]]: זרם של מילוני הטמעה + +**דוגמה:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +ייצוא בכמות גדולה של הקשרים של ישויות מתוך זרימה. + +מוריד ביעילות את כל מידע ההקשר של הישויות באמצעות סטרימינג WebSocket. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**מחזיר:** Iterator[Dict[str, Any]]: זרם של מילוני הקשר + +**דוגמה:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +ייצוא המוני של הטמעות גרפים מתוך זרימה. + +מוריד ביעילות את כל הטמעות ישויות הגרף באמצעות סטרימינג WebSocket. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**מחזיר:** Iterator[Dict[str, Any]]: זרם של מילוני הטמעות + +**דוגמה:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +ייצוא בכמות גדולה של משולשים RDF מתוך זרימה. + +מוריד ביעילות את כל המשולשים באמצעות סטרימינג WebSocket. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**מחזיר:** Iterator[Triple]: זרם של אובייקטי Triple + +**דוגמה:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא המוני של הטמעות מסמכים לתוך זרימה. + +העלאה יעילה של הטמעות מקטעי מסמכים באמצעות סטרימינג WebSocket +לשימוש בשאילתות RAG של מסמכים. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`embeddings`: איטרטור המפיק מילוני הטמעות +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**דוגמה:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +ייבוא בכמות גדולה של הקשרים של ישויות לתוך זרימה. + +מעלה ביעילות מידע על הקשר של ישויות באמצעות סטרימינג WebSocket. +הקשרים של ישויות מספקים הקשר טקסטואלי נוסף לגבי ישויות גרף +לשיפור ביצועי RAG. + +**ארגומנטים:** + +`flow`: מזהה של זרימה +`contexts`: איטרטור המפיק מילוני הקשר +`metadata`: מילון מטא-נתונים עם id, מטא-נתונים, משתמש, אוסף +`batch_size`: מספר הקשרים בכל אצווה (ברירת מחדל 100) +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**דוגמה:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא המוני של הטמעות גרפים לתוך זרימה. + +העלאה יעילה של הטמעות ישויות גרפים באמצעות סטרימינג WebSocket. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`embeddings`: איטרטור המפיק מילוני הטמעות +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**דוגמה:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא בכמות גדולה של שורות מובנות לתוך זרימה. + +העלאה יעילה של שורות נתונים מובנים באמצעות סטרימינג WebSocket +לשימוש בשאילתות GraphQL. + +**ארגומנטים:** + +`flow`: מזהה זרימה +`rows`: איטרטור המפיק מילוני שורות +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**דוגמה:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +ייבוא בכמות גדולה של משולשים RDF לתוך זרימה. + +מעלה ביעילות מספר גדול של משולשים באמצעות סטרימינג WebSocket. + +**ארגומנטים:** + +`flow`: מזהה של הזרימה +`triples`: איטרטור המפיק אובייקטי Triple +`metadata`: מילון מטא-דאטה עם מזהה, מטא-דאטה, משתמש, אוסף +`batch_size`: מספר המשולשים בכל אצווה (ברירת מחדל 100) +`**kwargs`: פרמטרים נוספים (שמורים לשימוש עתידי) + +**דוגמה:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +לקוח לפעולות אסינכרוניות בכמות גדולה + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +אתחול של self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + +### `aclose(self) -> None` + +סגירת חיבורים + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +ייצוא בכמות גדולה של הטמעות מסמכים באמצעות WebSocket + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +ייצוא בכמות גדולה של הקשרים של ישויות באמצעות WebSocket + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +ייצוא בכמות גדולה של הטמעות גרפים באמצעות WebSocket + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +ייצוא בכמות גדולה של משולשות באמצעות WebSocket + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא בכמות גדולה של הטמעות מסמכים באמצעות WebSocket + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא בכמות גדולה של הקשרים של ישויות באמצעות WebSocket + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא בכמות גדולה של הטמעות גרפים באמצעות WebSocket + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +ייבוא בכמות גדולה של שורות באמצעות WebSocket + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +ייבוא בכמות גדולה של משולשות באמצעות WebSocket + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +לקוח למדדי סינכרוניים + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +אתחול של self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + +### `get(self) -> str` + +קבלת מדדי Prometheus כטקסט + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +לקוח מדדים אסינכרוני + +### שיטות + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + +### `aclose(self) -> None` + +סגירת חיבורים + +### `get(self) -> str` + +קבלת מדדי Prometheus כטקסט + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +לקוח לשליפת ישויות הסברתיות עם טיפול בעקביות סופית. + +משתמש בגילוי שקט: שליפה, המתנה, שליפה חוזרת, השוואה. +אם התוצאות זהות, הנתונים יציבים. + +### שיטות + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +אתחול לקוח הסברתי. + +**ארגומנטים:** + +`flow_instance`: מופע SocketFlowInstance לשליפת משולשות +`retry_delay`: השהייה בין ניסיונות חוזרים בשניות (ברירת מחדל: 0.2) +`max_retries`: מספר מקסימלי של ניסיונות חוזרים (ברירת מחדל: 10) + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +זיהוי האם סשן הוא מסוג GraphRAG או Agent. + +**ארגומנטים:** + +`session_uri`: ה-URI של הסשן/שאלה +`graph`: גרף מוגדר +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף + +**מחזיר:** "graphrag" או "agent" + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +שליפת רצף ה-Agent השלם החל מ-URI של סשן. + +עוקב אחר שרשרת המוצא: שאלה -> ניתוח (ים) -> מסקנה + +**ארגומנטים:** + +`session_uri`: ה-URI של סשן/שאלה של ה-agent +`graph`: גרף מוגדר (ברירת מחדל: urn:graph:retrieval) +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`api`: מופע TrustGraph Api לגישה לספרן (אופציונלי) +`max_content`: אורך תוכן מקסימלי למסקנה + +**מחזיר:** מילון עם שאלה, איטרציות (רשימת ניתוחים), ישויות מסקנה + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +שליפת רצף ה-DocumentRAG השלם החל מ-URI של שאלה. + +עוקב אחר שרשרת המוצא: + שאלה -> עיגון -> חקירה -> סינתזה + +**ארגומנטים:** + +`question_uri`: ה-URI של ישות השאלה +`graph`: גרף מוגדר (ברירת מחדל: urn:graph:retrieval) +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`api`: מופע TrustGraph Api לגישה לספרן (אופציונלי) +`max_content`: אורך תוכן מקסימלי לסינתזה + +**מחזיר:** מילון עם שאלה, עיגון, חקירה, ישויות סינתזה + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +שליפת תוכן מהספרן לפי URI של מסמך. + +**ארגומנטים:** + +`document_uri`: ה-URI של המסמך בספרן +`api`: מופע TrustGraph Api לגישה לספרן +`user`: מזהה משתמש עבור הספרן +`max_content`: אורך תוכן מקסימלי להחזרה + +**מחזיר:** התוכן של המסמך כרצף + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +שליפת ישות בחירת קצה (משמשת על ידי Focus). + +**ארגומנטים:** + +`uri`: ה-URI של בחירת הקצה +`graph`: גרף מוגדר לשליפה +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף + +**מחזיר:** EdgeSelection או None אם לא נמצא + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +שליפת ישות הסברות באמצעות URI עם טיפול בעקביות סופית. + +משתמש בגילוי שקטות: +1. שליפת משולשים עבור URI +2. אם אין תוצאות, לנסות שוב +3. אם יש תוצאות, לחכות ולשלוף שוב +4. אם התוצאות זהות, הנתונים יציבים - לנתח ולהחזיר +5. אם התוצאות שונות, הנתונים עדיין נכתבים - לנסות שוב + +**ארגומנטים:** + +`uri`: ה-URI של הישות שיש לשלוף +`graph`: גרף בעל שם לשאילתה (לדוגמה, "urn:graph:retrieval") +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף + +**החזרות:** תת-מחלקה של ExplainEntity או None אם לא נמצא + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +שליפת ישות Focus וכל בחירות הקצוות שלה. + +**ארגומנטים:** + +`uri`: ה-URI של ישות ה-Focus +`graph`: גרף בעל שם לשאילתה +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף + +**החזרות:** Focus עם edge_selections מאוכלס, או None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +שליפת עקבות GraphRAG מלאים החל מ-URI של שאלה. + +עוקבים אחר שרשרת המוצא: שאלה -> עיגון -> חקירה -> Focus -> סינתזה + +**ארגומנטים:** + +`question_uri`: ה-URI של ישות השאלה +`graph`: גרף (ברירת מחדל: urn:graph:retrieval) +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`api`: מופע של TrustGraph Api לגישה לספרן (אופציונלי) +`max_content`: אורך תוכן מקסימלי לסינתזה + +**החזרות:** מילון עם ישויות שאלה, עיגון, חקירה, focus, סינתזה + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +רשימת כל סשנים של הסברות (שאלות) באוסף. + +**ארגומנטים:** + +`graph`: גרף (ברירת מחדל: urn:graph:retrieval) +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף +`limit`: מספר הסשנים המקסימלי להחזרה + +**החזרות:** רשימה של ישויות שאלה ממוינות לפי חותם זמן (חדש ביותר קודם) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +פתרון תוויות עבור כל רכיבים של משולש קצה. + +**ארגומנטים:** + +`edge`: מילון עם מפתחות "s", "p", "o" +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף + +**החזרות:** טאפל של (s_label, p_label, o_label) + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +פתרון rdfs:label עבור URI, עם שמירה במטמון. + +**ארגומנטים:** + +`uri`: ה-URI לקבלת התווית +`user`: מזהה משתמש/מרחב מפתחות +`collection`: מזהה אוסף + +**החזרות:** התווית אם נמצאה, אחרת ה-URI עצמו + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +מחלקה בסיסית עבור ישויות הסברתיות. + +**שדות:** + +`uri`: +`entity_type`: + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +שאילתת משתמש - השאלה שהתחילה את הסשן. + +**שדות:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +ישות חקירה - קצוות/חלקים שאוחזרו ממאגר הידע. + +**שדות:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +ישות ממוקדת - קצוות נבחרים עם ניתוח באמצעות מודל שפה גדול (GraphRAG בלבד). + +**שדות:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +ישות סינתטית - התשובה הסופית. + +**שדות:** + +`uri`: +`entity_type`: +`document`: + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +ישות ניתוח - מחזור מחשבה/פעולה/תצפית (לסוכן בלבד). + +**שדות:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +סיכום - תשובה סופית (לסוכן בלבד). + +**שדות:** + +`uri`: +`entity_type`: +`document`: + +### שיטות + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +צומת שנבחר עם הסבר משלב GraphRAG Focus. + +**שדות:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### שיטות + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +המרת משולשות בפורמט wire לטופלים (s, p, o). + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +חילוץ ערך ממילון Term בפורמט wire. + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +משפט גרף ידע המיוצג על ידי טריפל RDF. + +**שדות:** + +`s`: +`p`: +`o`: + +### שיטות + +### `__init__(self, s: str, p: str, o: str) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +יצירת אובייקט מחרוזת חדש מהאובייקט הנתון. אם צוינו קידוד (encoding) או +טיפול בשגיאות (errors), אז האובייקט חייב לחשוף מאגר נתונים +שייקוד באמצעות הקידוד ומטפל השגיאות שצוינו. +אחרת, מוחזר התוצאה של object.__str__() (אם מוגדר) +או repr(object). +ברירת המחדל של הקידוד היא 'utf-8'. +ברירת המחדל של טיפול בשגיאות היא 'strict'. + +### שיטות + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +יצירת אובייקט מחרוזת חדש מהאובייקט הנתון. אם צוינו קידוד (encoding) או +טיפול בשגיאות (errors), אז האובייקט חייב לחשוף מאגר נתונים +שייקוד באמצעות הקידוד ומטפל השגיאות שצוינו. +אחרת, מוחזר התוצאה של object.__str__() (אם מוגדר) +או repr(object). +ברירת המחדל של קידוד היא 'utf-8'. +ברירת המחדל של טיפול בשגיאות היא 'strict'. + +### שיטות + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +מזהה מפתח תצורה. + +**שדות:** + +`type`: +`key`: + +### שיטות + +### `__init__(self, type: str, key: str) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +זוג מפתח-ערך של תצורה. + +**שדות:** + +`type`: +`key`: +`value`: + +### שיטות + +### `__init__(self, type: str, key: str, value: str) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +מטא-נתונים עבור מסמך בספרייה. + +**תכונות:** + +`parent_id: Parent document ID for child documents (empty for top`: level docs) + +**שדות:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### שיטות + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +מטא-נתונים עבור משימת עיבוד מסמכים פעילה. + +**שדות:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### שיטות + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +מטא-נתונים עבור אוסף נתונים. + +אוספים מספקים קיבוץ והפרדה לוגיים עבור מסמכים ונתוני גרף ידע. + + +**תכונות:** + +`name: Human`: שם אוסף הניתן לקריאה + +**שדות:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### שיטות + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +מחלקה בסיסית עבור חלקי תגובה בסטרימינג. + +משמשת לפעולות סטרימינג מבוססות WebSocket שבהן התגובות מועברות +בהדרגה כשהן נוצרות. + +**שדות:** + +`content`: +`end_of_message`: + +### שיטות + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +קטע של נימוקים/תהליך חשיבה של הסוכן. + +מייצג את תהליך החשיבה או שלבי התכנון הפנימיים של הסוכן במהלך הביצוע. +קטעים אלה מראים כיצד הסוכן חושב על הבעיה. + +**שדות:** + +`content`: +`end_of_message`: +`chunk_type`: + +### שיטות + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +קטע תצפית על ביצוע כלי. + +מייצג את התוצאה או התצפית מהפעלת כלי או פעולה. +קטעים אלה מציגים מה שהסוכן למד משימוש בכלים. + +**שדות:** + +`content`: +`end_of_message`: +`chunk_type`: + +### שיטות + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +חלק תשובה סופי של הסוכן. + +מייצג את התגובה הסופית של הסוכן למשאלה של המשתמש לאחר השלמת +הניתוח והשימוש בכלי. + +**מאפיינים:** + +`chunk_type: Always "final`: answer" + +**שדות:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### שיטות + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +מקטע סטרימינג של RAG (יצירת טקסט מועשרת בשליפה). + +משמש למענה סטרימינג מ-RAG גרפי, RAG של מסמכים, השלמת טקסט, +ושירותי יצירה אחרים. + +**שדות:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### שיטות + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +אתחול עצמי. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +אירוע מקור עבור הסברתיות. + +נשלח במהלך שאילתות GraphRAG כאשר מצב ההסבר מופעל. +כל אירוע מייצג צומת מקור שנוצר במהלך עיבוד השאילתה. + +**שדות:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### שיטות + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +אתחול self. עיין ב-help(type(self)) לקבלת חתימה מדויקת. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +מופעל כאשר מתרחשות שגיאות בפרוטוקול WebSocket. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +מחלקה בסיסית עבור כל שגיאות השירות של TrustGraph. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +שגיאת שירות סוכן + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +שגיאת שירות תצורה + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +שגיאת שליפה של מסמכים. + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +שגיאת ניהול זרימה + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +שגיאת שער API + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +שגיאת שליפה של גרף RAG + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +שגיאת שירות מודל שפה גדול (LLM). + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +שגיאת טעינת נתונים + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +שגיאת חיפוש/איתור + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +שגיאת שירות שאילתות NLP. + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +שגיאת שירות שאילתות שורות + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +שגיאת עיבוד בקשה + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +שגיאת שירות שאילתות מובנה. + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +שגיאה בלתי צפויה/לא ידועה + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +מחלקה בסיסית עבור כל שגיאות השירות של TrustGraph. + + +-- diff --git a/docs/python-api.hi.md b/docs/python-api.hi.md new file mode 100644 index 00000000..78873cb6 --- /dev/null +++ b/docs/python-api.hi.md @@ -0,0 +1,4078 @@ +--- +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. + +## स्थापना + +```bash +pip install trustgraph +``` + +## त्वरित शुरुआत + +सभी कक्षाएं और प्रकार `trustgraph.api` पैकेज से आयात किए गए हैं: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## सामग्री तालिका + +### मुख्य भाग + +[Api](#api) + +### फ्लो क्लाइंट + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### वेबसॉकेट क्लाइंट + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### बल्क ऑपरेशन + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### मेट्रिक्स + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### डेटा प्रकार + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### अपवाद + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +सिंक्रोनस और एसिंक्रोनस कार्यों के लिए मुख्य ट्रस्टग्राफ एपीआई क्लाइंट। + +यह क्लास सभी ट्रस्टग्राफ सेवाओं तक पहुंच प्रदान करती है, जिसमें फ्लो प्रबंधन, +नॉलेज ग्राफ ऑपरेशन, दस्तावेज़ प्रसंस्करण, आरएजी क्वेरी और बहुत कुछ शामिल हैं। यह +रेस्ट-आधारित और वेबसॉकेट-आधारित दोनों संचार पैटर्न का समर्थन करता है। + +क्लाइंट का उपयोग स्वचालित संसाधन सफाई के लिए एक संदर्भ प्रबंधक के रूप में किया जा सकता है: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### विधियाँ + +### `__aenter__(self)` + +एसिंक्रोनस संदर्भ प्रबंधक में प्रवेश करें। + +### `__aexit__(self, *args)` + +एसिंक्रोनस संदर्भ प्रबंधक से बाहर निकलें और कनेक्शन बंद करें। + +### `__enter__(self)` + +सिंक्रोनस संदर्भ प्रबंधक में प्रवेश करें। + +### `__exit__(self, *args)` + +सिंक्रोनस संदर्भ प्रबंधक से बाहर निकलें और कनेक्शन बंद करें। + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +ट्रस्टग्राफ एपीआई क्लाइंट को आरंभ करें। + +**तर्क:** + +`url`: ट्रस्टग्राफ एपीआई के लिए आधार यूआरएल (डिफ़ॉल्ट: "http://localhost:8088/"") +`timeout`: सेकंड में अनुरोध समय-सीमा (डिफ़ॉल्ट: 60) +`token`: प्रमाणीकरण के लिए वैकल्पिक बेयरर टोकन + +**उदाहरण:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +सभी एसिंक्रोनस क्लाइंट कनेक्शन बंद करें। + +यह विधि एसिंक्रोनस वेबसॉकेट, बल्क ऑपरेशन और फ्लो कनेक्शन को बंद करती है। +यह स्वचालित रूप से तब कॉल किया जाता है जब किसी एसिंक्रोनस कॉन्टेक्स्ट मैनेजर से बाहर निकलते हैं। + +**उदाहरण:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +एसिंक्रोनस बल्क ऑपरेशंस क्लाइंट प्राप्त करें। + +वेबसॉकेट के माध्यम से एसिंक्रोनस/अवेइट शैली के बल्क इम्पोर्ट/एक्सपोर्ट ऑपरेशंस प्रदान करता है +बड़े डेटासेट के कुशल प्रबंधन के लिए। + +**रिटर्न:** AsyncBulkClient: एसिंक्रोनस बल्क ऑपरेशंस क्लाइंट + +**उदाहरण:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +एक एसिंक्रोनस, REST-आधारित फ्लो क्लाइंट प्राप्त करें। + +यह फ्लो ऑपरेशन्स तक एसिंक्रोनस/अवेइट शैली में एक्सेस प्रदान करता है। यह एसिंक्रोनस पायथन एप्लिकेशन और फ्रेमवर्क (फास्टएपीआई, एआईओएचटीटीपी, आदि) के लिए पसंदीदा है। + + +**रिटर्न:** AsyncFlow: एसिंक्रोनस फ्लो क्लाइंट + +**उदाहरण:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +एक एसिंक्रोनस मेट्रिक्स क्लाइंट प्राप्त करें। + +प्रोमेथियस मेट्रिक्स तक एसिंक्रोनस/अवेइट शैली में पहुँच प्रदान करता है। + +**वापसी:** AsyncMetrics: एसिंक्रोनस मेट्रिक्स क्लाइंट + +**उदाहरण:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +स्ट्रीमिंग कार्यों के लिए एक एसिंक्रोनस वेबसॉकेट क्लाइंट प्राप्त करें। + +यह स्ट्रीमिंग समर्थन के साथ एसिंक/अवेट शैली वेबसॉकेट एक्सेस प्रदान करता है। +यह पायथन में एसिंक स्ट्रीमिंग के लिए पसंदीदा तरीका है। + +**रिटर्न:** AsyncSocketClient: एसिंक्रोनस वेबसॉकेट क्लाइंट + +**उदाहरण:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +आयात/निर्यात के लिए एक सिंक्रोनस बल्क ऑपरेशंस क्लाइंट प्राप्त करें। + +बल्क ऑपरेशंस, वेबसॉकेट कनेक्शन के माध्यम से बड़े डेटासेट के कुशल हस्तांतरण की अनुमति देते हैं, जिसमें ट्रिपल, एम्बेडिंग, एंटिटी कॉन्टेक्स्ट और ऑब्जेक्ट शामिल हैं। + +**रिटर्न:** BulkClient: सिंक्रोनस बल्क ऑपरेशंस क्लाइंट + +**उदाहरण:** + + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +सभी सिंक्रोनस क्लाइंट कनेक्शन बंद करें। + +यह विधि WebSocket और बल्क ऑपरेशन कनेक्शन बंद करती है। +यह स्वचालित रूप से तब कॉल किया जाता है जब किसी कॉन्टेक्स्ट मैनेजर से बाहर निकलते हैं। + +**उदाहरण:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +डेटा संग्रहों को प्रबंधित करने के लिए एक कलेक्शन क्लाइंट प्राप्त करें। + +कलेक्शन दस्तावेजों और नॉलेज ग्राफ डेटा को व्यवस्थित करते हैं +तार्किक समूहों में, अलगाव और एक्सेस नियंत्रण के लिए। + +**रिटर्न:** कलेक्शन: कलेक्शन प्रबंधन क्लाइंट + +**उदाहरण:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +कॉन्फ़िगरेशन सेटिंग्स को प्रबंधित करने के लिए एक कॉन्फ़िग क्लाइंट प्राप्त करें। + +**रिटर्न:** कॉन्फ़िग: कॉन्फ़िगरेशन प्रबंधन क्लाइंट + +**उदाहरण:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +फ्लो को प्रबंधित करने और उसके साथ इंटरैक्ट करने के लिए एक फ्लो क्लाइंट प्राप्त करें। + +फ्लो, ट्रस्टग्राफ में प्राथमिक निष्पादन इकाइयाँ हैं, जो एजेंट, आरएजी क्वेरी, एम्बेडिंग और दस्तावेज़ प्रसंस्करण जैसी सेवाओं तक पहुंच प्रदान करती हैं। + +**रिटर्न:** फ्लो: फ्लो प्रबंधन क्लाइंट + +**उदाहरण:** + + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +ज्ञान ग्राफ कोर को प्रबंधित करने के लिए एक नॉलेज क्लाइंट प्राप्त करें। + +**रिटर्न:** नॉलेज: ज्ञान ग्राफ प्रबंधन क्लाइंट + +**उदाहरण:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +दस्तावेज़ प्रबंधन के लिए एक लाइब्रेरी क्लाइंट प्राप्त करें। + +यह लाइब्रेरी दस्तावेज़ भंडारण, मेटाडेटा प्रबंधन और +प्रसंस्करण कार्यप्रवाह समन्वय प्रदान करती है। + +**रिटर्न:** लाइब्रेरी: दस्तावेज़ लाइब्रेरी प्रबंधन क्लाइंट + +**उदाहरण:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +निगरानी के लिए एक सिंक्रोनस मेट्रिक्स क्लाइंट प्राप्त करें। + +यह ट्रस्टग्राफ सेवा से प्रोमेथियस-स्वरूपित मेट्रिक्स प्राप्त करता है +निगरानी और अवलोकन के लिए। + +**रिटर्न:** मेट्रिक्स: सिंक्रोनस मेट्रिक्स क्लाइंट + +**उदाहरण:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +एक निम्न-स्तरीय REST API अनुरोध करें। + +यह विधि मुख्य रूप से आंतरिक उपयोग के लिए है, लेकिन जब आवश्यक हो तो इसका उपयोग सीधे +API एक्सेस के लिए किया जा सकता है। + +**तर्क:** + +`path`: API एंडपॉइंट पथ (बेस URL के सापेक्ष) +`request`: अनुरोध पेलोड एक डिक्शनरी के रूप में + +**रिटर्न:** dict: प्रतिक्रिया ऑब्जेक्ट + +**अपवाद:** + +`ProtocolException`: यदि प्रतिक्रिया स्थिति 200 नहीं है या प्रतिक्रिया JSON नहीं है +`ApplicationException`: यदि प्रतिक्रिया में कोई त्रुटि है + +**उदाहरण:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +स्ट्रीमिंग कार्यों के लिए एक सिंक्रोनस वेबसॉकेट क्लाइंट प्राप्त करें। + +वेबसॉकेट कनेक्शन वास्तविक समय प्रतिक्रियाओं के लिए स्ट्रीमिंग समर्थन प्रदान करते हैं +एजेंटों, आरएजी प्रश्नों और टेक्स्ट पूर्णता से। यह विधि वेबसॉकेट प्रोटोकॉल के चारों ओर एक सिंक्रोनस रैपर लौटाती है। + + +**रिटर्न:** SocketClient: सिंक्रोनस वेबसॉकेट क्लाइंट + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +ब्लूप्रिंट और फ्लो इंस्टेंस ऑपरेशन्स के लिए फ्लो मैनेजमेंट क्लाइंट। + +यह क्लास फ्लो ब्लूप्रिंट (टेम्प्लेट) और +फ्लो इंस्टेंस (चल रहे फ्लो) को प्रबंधित करने के लिए विधियाँ प्रदान करती है। ब्लूप्रिंट फ्लो की संरचना और +पैरामीटर को परिभाषित करते हैं, जबकि इंस्टेंस सक्रिय फ्लो का प्रतिनिधित्व करते हैं जो +सेवाओं को निष्पादित कर सकते हैं। + +### विधियाँ + +### `__init__(self, api)` + +फ्लो क्लाइंट को इनिशियलाइज़ करें। + +**तर्क:** + +`api`: अनुरोध करने के लिए पैरेंट एपीआई इंस्टेंस। + +### `delete_blueprint(self, blueprint_name)` + +एक फ्लो ब्लूप्रिंट को हटाएं। + +**तर्क:** + +`blueprint_name`: हटाने के लिए ब्लूप्रिंट का नाम। + +**उदाहरण:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +एक चल रहे फ्लो इंस्टेंस की परिभाषा प्राप्त करें। + +**तर्क:** + +`id`: फ्लो इंस्टेंस आईडी + +**वापसी:** डिक्ट: फ्लो इंस्टेंस परिभाषा + +**उदाहरण:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +नाम से एक फ्लो ब्लूप्रिंट परिभाषा प्राप्त करें। + +**तर्क:** + +`blueprint_name`: प्राप्त करने के लिए ब्लूप्रिंट का नाम + +**वापसी:** dict: ब्लूप्रिंट परिभाषा एक शब्दकोश के रूप में + +**उदाहरण:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +किसी विशिष्ट प्रवाह पर संचालन निष्पादित करने के लिए एक फ्लोइंस्टेंस प्राप्त करें। + +**तर्क:** + +`id`: प्रवाह पहचानकर्ता (डिफ़ॉल्ट: "default") + +**वापसी:** फ्लोइंस्टेंस: सेवा संचालन के लिए फ्लो इंस्टेंस + +**उदाहरण:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +सभी सक्रिय फ्लो इंस्टेंस की सूची बनाएं। + +**रिटर्न:** list[str]: फ्लो इंस्टेंस आईडी की सूची + +**उदाहरण:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +उपलब्ध सभी फ्लो ब्लूप्रिंट की सूची बनाएं। + +**रिटर्न:** list[str]: ब्लूप्रिंट नामों की सूची + +**उदाहरण:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +एक फ्लो ब्लूप्रिंट बनाएं या अपडेट करें। + +**तर्क:** + +`blueprint_name`: ब्लूप्रिंट के लिए नाम +`definition`: ब्लूप्रिंट परिभाषा डिक्शनरी + +**उदाहरण:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +एक फ्लो-स्कोपेड एपीआई अनुरोध करें। + +**तर्क:** + +`path`: फ्लो एंडपॉइंट्स के लिए वैकल्पिक पथ प्रत्यय +`request`: अनुरोध पेलोड डिक्शनरी + +**रिटर्न:** डिक्ट: प्रतिक्रिया ऑब्जेक्ट + +**अपवाद:** + +`RuntimeError`: यदि अनुरोध पैरामीटर निर्दिष्ट नहीं है + +### `start(self, blueprint_name, id, description, parameters=None)` + +एक ब्लूप्रिंट से एक नया फ्लो इंस्टेंस शुरू करें। + +**तर्क:** + +`blueprint_name`: इंस्टेंट करने के लिए ब्लूप्रिंट का नाम +`id`: फ्लो इंस्टेंस के लिए अद्वितीय पहचानकर्ता +`description`: मानव-पठनीय विवरण +`parameters`: वैकल्पिक पैरामीटर डिक्शनरी + +**उदाहरण:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +एक चल रहे फ्लो इंस्टेंस को रोकें। + +**तर्क:** + +`id`: रोकने के लिए फ्लो इंस्टेंस आईडी + +**उदाहरण:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +किसी विशिष्ट प्रवाह पर सेवाओं को निष्पादित करने के लिए फ्लो इंस्टेंस क्लाइंट। + +यह क्लास सभी ट्रस्टग्राफ सेवाओं तक पहुंच प्रदान करता है, जिनमें शामिल हैं: +टेक्स्ट पूर्णता और एम्बेडिंग +राज्य प्रबंधन के साथ एजेंट ऑपरेशन +ग्राफ और दस्तावेज़ RAG क्वेरी +नॉलेज ग्राफ ऑपरेशन (ट्रिपल्स, ऑब्जेक्ट) +दस्तावेज़ लोडिंग और प्रोसेसिंग +प्राकृतिक भाषा से GraphQL क्वेरी रूपांतरण +संरचित डेटा विश्लेषण और स्कीमा डिटेक्शन +MCP टूल निष्पादन +प्रॉम्प्ट टेम्पलेटिंग + +सेवाओं को एक चल रहे फ्लो इंस्टेंस के माध्यम से एक्सेस किया जाता है जिसकी पहचान ID से होती है। + +### विधियाँ + +### `__init__(self, api, id)` + +फ्लोइंस्टेंस को इनिशियलाइज़ करें। + +**तर्क:** + +`api`: पैरेंट फ्लो क्लाइंट +`id`: फ्लो इंस्टेंस पहचानकर्ता + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +तर्क और टूल उपयोग क्षमताओं के साथ एक एजेंट ऑपरेशन निष्पादित करें। + +एजेंट बहु-चरणीय तर्क कर सकते हैं, टूल का उपयोग कर सकते हैं और बातचीत में संवादी +स्थिति को बनाए रख सकते हैं। यह एक सिंक्रोनस, नॉन-स्ट्रीमिंग संस्करण है। + +**तर्क:** + +`question`: उपयोगकर्ता का प्रश्न या निर्देश +`user`: उपयोगकर्ता पहचानकर्ता (डिफ़ॉल्ट: "trustgraph") +`state`: राज्यपूर्ण वार्तालापों के लिए वैकल्पिक राज्य शब्दकोश +`group`: बहु-उपयोगकर्ता संदर्भों के लिए वैकल्पिक समूह पहचानकर्ता +`history`: संदेशों की सूची के रूप में वैकल्पिक वार्तालाप इतिहास + +**रिटर्न:** str: एजेंट का अंतिम उत्तर + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +संरचित डेटा नमूने के डेटा प्रकार का पता लगाएं। + +**तर्क:** + +`sample`: विश्लेषण करने के लिए डेटा नमूना (स्ट्रिंग सामग्री) + +**रिटर्न:** detected_type, confidence और वैकल्पिक मेटाडेटा के साथ एक डिक्शनरी। + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +संयुक्त डेटा निदान करें: प्रकार का पता लगाएं और विवरणिका उत्पन्न करें। + +**तर्क:** + +`sample`: विश्लेषण करने के लिए डेटा नमूना (स्ट्रिंग सामग्री) +`schema_name`: विवरणिका पीढ़ी के लिए वैकल्पिक लक्ष्य स्कीमा नाम। +`options`: वैकल्पिक पैरामीटर (जैसे, CSV के लिए विभाजक)। + +**वापसी:** `detected_type`, `confidence`, `descriptor` और `metadata` के साथ एक डिक्शनरी। + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +सिमेंटिक समानता का उपयोग करके दस्तावेज़ के टुकड़ों को क्वेरी करें। + +वे दस्तावेज़ के टुकड़े खोजें जिनके सामग्री वेक्टर एम्बेडिंग का उपयोग करके इनपुट टेक्स्ट के सिमेंटिक रूप से समान हैं। + + +**तर्क:** + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट। +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता। +`collection`: संग्रह पहचानकर्ता। +`limit`: अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10)। + +**वापसी:** `dict`: क्वेरी परिणाम जिनमें `chunk_id` और `score` वाले टुकड़े शामिल हैं। + +**उदाहरण:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +दस्तावेज़-आधारित पुनर्प्राप्ति-संवर्धित पीढ़ी (RAG) क्वेरी निष्पादित करें। + +दस्तावेज़ RAG प्रासंगिक दस्तावेज़ अंशों को खोजने के लिए वेक्टर एम्बेडिंग का उपयोग करता है, +फिर उन अंशों को संदर्भ के रूप में उपयोग करके एक LLM के साथ एक प्रतिक्रिया उत्पन्न करता है। + +**तर्क:** + +`query`: प्राकृतिक भाषा क्वेरी +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (डिफ़ॉल्ट: "ट्रस्टग्राफ") +`collection`: संग्रह पहचानकर्ता (डिफ़ॉल्ट: "डिफ़ॉल्ट") +`doc_limit`: पुनर्प्राप्त किए जाने वाले अधिकतम दस्तावेज़ अंश (डिफ़ॉल्ट: 10) + +**रिटर्न:** स्ट्रिंग: दस्तावेज़ संदर्भ को शामिल करने वाली उत्पन्न प्रतिक्रिया + +**उदाहरण:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +एक या अधिक ग्रंथों के लिए वेक्टर एम्बेडिंग उत्पन्न करें। + +ग्रंथों को घने वेक्टर निरूपण में परिवर्तित करता है जो सिमेंटिक +खोज और समानता तुलना के लिए उपयुक्त है। + +**तर्क:** + +`texts`: एम्बेड करने के लिए इनपुट ग्रंथों की सूची + +**रिटर्न:** list[list[list[float]]]: वेक्टर एम्बेडिंग, प्रत्येक इनपुट टेक्स्ट के लिए एक सेट + +**उदाहरण:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +संरचित डेटा के लिए एक विवरण उत्पन्न करें जो एक विशिष्ट स्कीमा से मेल खाता हो। + +**तर्क:** + +`sample`: विश्लेषण करने के लिए डेटा नमूना (स्ट्रिंग सामग्री) +`data_type`: डेटा प्रकार (csv, json, xml) +`schema_name`: विवरण पीढ़ी के लिए लक्षित स्कीमा नाम +`options`: वैकल्पिक पैरामीटर (जैसे, CSV के लिए विभाजक) + +**रिटर्न:** विवरण और मेटाडेटा के साथ डिक्ट + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +सिमेंटिक समानता का उपयोग करके नॉलेज ग्राफ एंटिटीज को क्वेरी करें। + +नॉलेज ग्राफ में उन एंटिटीज को खोजें जिनके विवरण इनपुट टेक्स्ट के समान अर्थ वाले हों, +वेक्टर एम्बेडिंग का उपयोग करके। + +**तर्क:** + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`limit`: अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10) + +**रिटर्न:** डिक्ट: समान एंटिटीज के साथ क्वेरी परिणाम + +**उदाहरण:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +ग्राफ-आधारित रिट्रीवल-ऑगमेंटेड जनरेशन (RAG) क्वेरी निष्पादित करें। + +ग्राफ RAG प्रासंगिक संदर्भ खोजने के लिए नॉलेज ग्राफ संरचना का उपयोग करता है, +एंटिटी संबंधों को पार करके, और फिर एक एलएलएम का उपयोग करके एक प्रतिक्रिया उत्पन्न करता है। + +**तर्क:** + +`query`: प्राकृतिक भाषा क्वेरी +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (डिफ़ॉल्ट: "ट्रस्टग्राफ") +`collection`: संग्रह पहचानकर्ता (डिफ़ॉल्ट: "डिफ़ॉल्ट") +`entity_limit`: पुनः प्राप्त करने के लिए अधिकतम एंटिटीज (डिफ़ॉल्ट: 50) +`triple_limit`: प्रति एंटिटी अधिकतम ट्रिपल (डिफ़ॉल्ट: 30) +`max_subgraph_size`: सबग्राफ में अधिकतम कुल ट्रिपल (डिफ़ॉल्ट: 150) +`max_path_length`: अधिकतम ट्रैवर्सल गहराई (डिफ़ॉल्ट: 2) + +**रिटर्न:** स्ट्र: ग्राफ संदर्भ को शामिल करने वाली उत्पन्न प्रतिक्रिया + +**उदाहरण:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +प्रसंस्करण के लिए एक बाइनरी दस्तावेज़ लोड करें। + +एक दस्तावेज़ (पीडीएफ, डॉक्स, चित्र, आदि) को निष्कर्षण और +प्रसंस्करण के लिए अपलोड करें, जो प्रवाह के दस्तावेज़ पाइपलाइन के माध्यम से होता है। + +**तर्क:** + +`document`: बाइट्स के रूप में दस्तावेज़ सामग्री +`id`: वैकल्पिक दस्तावेज़ पहचानकर्ता (यदि None है तो स्वचालित रूप से उत्पन्न) +`metadata`: वैकल्पिक मेटाडेटा (ट्रिपल्स की सूची या emit विधि वाला ऑब्जेक्ट) +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (वैकल्पिक) +`collection`: संग्रह पहचानकर्ता (वैकल्पिक) + +**रिटर्न:** dict: प्रसंस्करण प्रतिक्रिया + +**अपवाद:** + +`RuntimeError`: यदि आईडी के बिना मेटाडेटा प्रदान किया गया है + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +प्रसंस्करण के लिए पाठ सामग्री लोड करें। + +प्रवाह के पाठ पाइपलाइन के माध्यम से निष्कर्षण और प्रसंस्करण के लिए पाठ सामग्री अपलोड करें। +पाठ पाइपलाइन। + +**तर्क:** + +`text`: बाइट्स के रूप में पाठ सामग्री +`id`: वैकल्पिक दस्तावेज़ पहचानकर्ता (यदि None है तो स्वचालित रूप से उत्पन्न) +`metadata`: वैकल्पिक मेटाडेटा (ट्रिपल की सूची या emit विधि वाला ऑब्जेक्ट) +`charset`: वर्ण एन्कोडिंग (डिफ़ॉल्ट: "utf-8") +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (वैकल्पिक) +`collection`: संग्रह पहचानकर्ता (वैकल्पिक) + +**रिटर्न:** dict: प्रसंस्करण प्रतिक्रिया + +**अपवाद:** + +`RuntimeError`: यदि आईडी के बिना मेटाडेटा प्रदान किया गया है + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +एक मॉडल कॉन्टेक्स्ट प्रोटोकॉल (MCP) टूल को निष्पादित करें। + +MCP टूल एजेंटों और वर्कफ़्लो के लिए विस्तारित कार्यक्षमता प्रदान करते हैं, +जो बाहरी प्रणालियों और सेवाओं के साथ एकीकरण की अनुमति देते हैं। + +**तर्क:** + +`name`: टूल का नाम/पहचानकर्ता +`parameters`: टूल पैरामीटर डिक्शनरी (डिफ़ॉल्ट: {}) + +**रिटर्न:** स्ट्र या डिक्ट: टूल निष्पादन परिणाम + +**अपवाद:** + +`ProtocolException`: यदि प्रतिक्रिया प्रारूप अमान्य है + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +एक प्राकृतिक भाषा प्रश्न को GraphQL क्वेरी में बदलें। + +**तर्क:** + +`question`: प्राकृतिक भाषा प्रश्न +`max_results`: वापस करने के लिए अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 100) + +**वापसी:** graphql_query, variables, detected_schemas, confidence के साथ एक शब्दकोश। + +### `prompt(self, id, variables)` + +चर प्रतिस्थापन के साथ एक प्रॉम्प्ट टेम्पलेट निष्पादित करें। + +प्रॉम्प्ट टेम्प्लेट, गतिशील चर के साथ पुन: प्रयोज्य प्रॉम्प्ट पैटर्न की अनुमति देते हैं, जो सुसंगत प्रॉम्प्ट इंजीनियरिंग के लिए उपयोगी है। +चर प्रतिस्थापन, सुसंगत प्रॉम्प्ट इंजीनियरिंग के लिए उपयोगी। + +**तर्क:** + +`id`: प्रॉम्प्ट टेम्प्लेट पहचानकर्ता +`variables`: चर नाम से मान मैपिंग का शब्दकोश + +**रिटर्न:** स्ट्र या डिक्ट: प्रस्तुत प्रॉम्प्ट परिणाम (टेक्स्ट या संरचित ऑब्जेक्ट) + +**अपवाद:** + +`ProtocolException`: यदि प्रतिक्रिया प्रारूप अमान्य है + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +इस फ्लो इंस्टेंस पर एक सेवा अनुरोध करें। + +**तर्क:** + +`path`: सेवा पथ (उदाहरण के लिए, "service/text-completion") +`request`: अनुरोध पेलोड डिक्शनरी + +**रिटर्न:** डिक्ट: सेवा प्रतिक्रिया + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +अनुक्रमित फ़ील्ड पर सिमेंटिक समानता का उपयोग करके पंक्ति डेटा क्वेरी करें। + +उन पंक्तियों को खोजता है जिनके अनुक्रमित फ़ील्ड मान इनपुट टेक्स्ट के अर्थ के समान हों, वेक्टर एम्बेडिंग का उपयोग करके। यह संरचित डेटा पर अस्पष्ट/अर्थ संबंधी मिलान को सक्षम बनाता है। + +**तर्क:** + + + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट। +`schema_name`: खोज करने के लिए स्कीमा का नाम। +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (डिफ़ॉल्ट: "trustgraph")। +`collection`: संग्रह पहचानकर्ता (डिफ़ॉल्ट: "default")। +`index_name`: वैकल्पिक इंडेक्स नाम, जिससे खोज को विशिष्ट इंडेक्स तक सीमित किया जा सके। +`limit`: अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10)। + +**रिटर्न:** डिक्ट: क्वेरी परिणाम जिनमें index_name, index_value, text और score शामिल हैं। + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +ज्ञान ग्राफ में संरचित पंक्तियों के विरुद्ध एक GraphQL क्वेरी निष्पादित करें। + +यह GraphQL सिंटैक्स का उपयोग करके संरचित डेटा पर क्वेरी करता है, जो जटिल क्वेरी की अनुमति देता है +फ़िल्टरिंग, एग्रीगेशन और संबंध ट्रैवर्सल के साथ। + +**तर्क:** + +`query`: GraphQL क्वेरी स्ट्रिंग +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (डिफ़ॉल्ट: "trustgraph") +`collection`: संग्रह पहचानकर्ता (डिफ़ॉल्ट: "default") +`variables`: वैकल्पिक क्वेरी चर शब्दकोश +`operation_name`: मल्टी-ऑपरेशन दस्तावेज़ों के लिए वैकल्पिक ऑपरेशन नाम + +**रिटर्न:** dict: 'data', 'errors' और/या 'extensions' फ़ील्ड के साथ GraphQL प्रतिक्रिया + +**अपवाद:** + +`ProtocolException`: यदि सिस्टम-स्तरीय त्रुटि होती है + +**उदाहरण:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +प्रॉम्प्ट विश्लेषण का उपयोग करके डेटा नमूने के लिए मिलान करने वाले स्कीमा का चयन करें। + +**तर्क:** + +`sample`: विश्लेषण करने के लिए डेटा नमूना (स्ट्रिंग सामग्री) +`options`: वैकल्पिक पैरामीटर + +**रिटर्न:** schema_matches सरणी और मेटाडेटा के साथ डिक्ट + +### `structured_query(self, question, user='trustgraph', collection='default')` + +संरचित डेटा के खिलाफ एक प्राकृतिक भाषा प्रश्न निष्पादित करें। +एनएलपी क्वेरी रूपांतरण और GraphQL निष्पादन को जोड़ता है। + +**तर्क:** + +`question`: प्राकृतिक भाषा प्रश्न +`user`: कैसेंड्रा कीस्पेस पहचानकर्ता (डिफ़ॉल्ट: "trustgraph") +`collection`: डेटा संग्रह पहचानकर्ता (डिफ़ॉल्ट: "default") + +**रिटर्न:** डेटा और वैकल्पिक त्रुटियों के साथ डिक्ट + +### `text_completion(self, system, prompt)` + +फ़्लो के एलएलएम का उपयोग करके टेक्स्ट कंप्लीशन निष्पादित करें। + +**तर्क:** + +`system`: सिस्टम प्रॉम्प्ट जो सहायक के व्यवहार को परिभाषित करता है +`prompt`: उपयोगकर्ता प्रॉम्प्ट/प्रश्न + +**रिटर्न:** स्ट्र: उत्पन्न प्रतिक्रिया पाठ + +**उदाहरण:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +पैटर्न मिलान का उपयोग करके ज्ञान ग्राफ त्रिकों को क्वेरी करें। + +यह आरडीएफ त्रिकों की खोज करता है जो दिए गए विषय, विधेय और/या +ऑब्जेक्ट पैटर्न से मेल खाते हैं। अनिश्चित पैरामीटर वाइल्डकार्ड के रूप में कार्य करते हैं। + +**तर्क:** + +`s`: विषय यूआरआई (वैकल्पिक, वाइल्डकार्ड के लिए None का उपयोग करें) +`p`: विधेय यूआरआई (वैकल्पिक, वाइल्डकार्ड के लिए None का उपयोग करें) +`o`: ऑब्जेक्ट यूआरआई या लिटरल (वैकल्पिक, वाइल्डकार्ड के लिए None का उपयोग करें) +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (वैकल्पिक) +`collection`: संग्रह पहचानकर्ता (वैकल्पिक) +`limit`: वापस करने के लिए अधिकतम परिणाम (डिफ़ॉल्ट: 10000) + +**रिटर्न:** list[Triple]: मिलान करने वाले ट्रिपल ऑब्जेक्ट की सूची + +**उठाता है:** + +`RuntimeError`: यदि s या p यूआरआई नहीं है, या o यूआरआई/लिटरल नहीं है + +**उदाहरण:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +REST API का उपयोग करके एसिंक्रोनस फ्लो प्रबंधन क्लाइंट। + +यह एसिंक/अवेट पर आधारित फ्लो प्रबंधन संचालन प्रदान करता है, जिसमें लिस्टिंग, +फ्लो शुरू करना, बंद करना और फ्लो क्लास परिभाषाओं का प्रबंधन शामिल है। यह एजेंटों, RAG और प्रश्नों जैसी फ्लो-स्कोप सेवाओं तक गैर-स्ट्रीमिंग +REST एंडपॉइंट के माध्यम से पहुंच भी प्रदान करता है। + + +ध्यान दें: स्ट्रीमिंग समर्थन के लिए, AsyncSocketClient का उपयोग करें। + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +एसिंक्रोनस फ्लो क्लाइंट को इनिशियलाइज़ करें। + +**तर्क:** + +`url`: ट्रस्टग्राफ API के लिए बेस URL +`timeout`: सेकंड में अनुरोध टाइमआउट +`token`: प्रमाणीकरण के लिए वैकल्पिक बेयरर टोकन + +### `aclose(self) -> None` + +एसिंक्रोनस क्लाइंट को बंद करें और संसाधनों को साफ़ करें। + +ध्यान दें: सफाई aiohttp सत्र संदर्भ प्रबंधकों द्वारा स्वचालित रूप से संभाली जाती है। +यह विधि अन्य एसिंक्रोनस क्लाइंट के साथ स्थिरता के लिए प्रदान की गई है। + +### `delete_class(self, class_name: str)` + +एक फ्लो क्लास परिभाषा को हटाएं। + +यह सिस्टम से एक फ्लो क्लास ब्लूप्रिंट को हटा देता है। यह चल रहे फ्लो उदाहरणों को प्रभावित नहीं करता है। + + +**तर्क:** + +`class_name`: हटाने के लिए फ्लो क्लास का नाम + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +प्रवाह परिभाषा प्राप्त करें। + +यह पूर्ण प्रवाह कॉन्फ़िगरेशन प्राप्त करता है, जिसमें इसका क्लास नाम, +विवरण और पैरामीटर शामिल हैं। + +**तर्क:** + +`id`: प्रवाह पहचानकर्ता + +**वापसी:** dict: प्रवाह परिभाषा ऑब्जेक्ट + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +प्रवाह वर्ग परिभाषा प्राप्त करें। + +यह एक प्रवाह वर्ग के लिए ब्लूप्रिंट परिभाषा प्राप्त करता है, जिसमें इसका +कॉन्फ़िगरेशन स्कीमा और सेवा बाइंडिंग शामिल हैं। + +**तर्क:** + +`class_name`: प्रवाह वर्ग का नाम + +**वापसी:** dict: प्रवाह वर्ग परिभाषा ऑब्जेक्ट + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +एक एसिंक्रोनस फ्लो इंस्टेंस क्लाइंट प्राप्त करें। + +यह एक विशिष्ट फ्लो की सेवाओं के साथ इंटरैक्ट करने के लिए एक क्लाइंट लौटाता है +(एजेंट, आरएजी, प्रश्न, एम्बेडिंग, आदि)। + +**तर्क:** + +`flow_id`: प्रवाह पहचानकर्ता + +**वापसी:** AsyncFlowInstance: प्रवाह-विशिष्ट कार्यों के लिए क्लाइंट + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +सभी फ्लो पहचानकर्ताओं की सूची बनाएं। + +सिस्टम में वर्तमान में तैनात सभी फ्लो के आईडी प्राप्त करता है। + +**रिटर्न:** list[str]: फ्लो पहचानकर्ताओं की सूची + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +सभी फ्लो क्लास नामों की सूची बनाएं। + +सिस्टम में उपलब्ध सभी फ्लो क्लास (ब्लूप्रिंट) के नामों को प्राप्त करता है। + +**रिटर्न:** list[str]: फ्लो क्लास नामों की सूची + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +एक फ्लो क्लास परिभाषा बनाएं या अपडेट करें। + +यह एक फ्लो क्लास ब्लूप्रिंट संग्रहीत करता है जिसका उपयोग फ्लो को इंस्टेंटिएट करने के लिए किया जा सकता है। + +**तर्क:** + +`class_name`: फ्लो क्लास का नाम +`definition`: फ्लो क्लास परिभाषा ऑब्जेक्ट + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +गेटवे एपीआई को एसिंक्रोनस एचटीटीपी पोस्ट अनुरोध भेजें। + +ट्रस्टग्राफ एपीआई को प्रमाणित अनुरोध भेजने के लिए आंतरिक विधि। + +**तर्क:** + +`path`: एपीआई एंडपॉइंट पथ (बेस यूआरएल के सापेक्ष) +`request_data`: अनुरोध पेलोड डिक्शनरी + +**रिटर्न:** डिक्ट: एपीआई से प्रतिक्रिया ऑब्जेक्ट + +**अपवाद:** + +`ProtocolException`: यदि HTTP स्थिति 200 नहीं है या प्रतिक्रिया मान्य JSON नहीं है +`ApplicationException`: यदि API एक त्रुटि प्रतिक्रिया देता है + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +एक नया फ्लो इंस्टेंस शुरू करें। + +निर्दिष्ट मापदंडों के साथ एक फ्लो क्लास परिभाषा से एक फ्लो बनाता है और शुरू करता है। + + +**तर्क:** + +`class_name`: फ्लो क्लास का नाम जिसे इंस्टेंट किया जाना है +`id`: नए फ्लो इंस्टेंस के लिए पहचानकर्ता +`description`: फ्लो का मानव-पठनीय विवरण +`parameters`: फ्लो के लिए वैकल्पिक कॉन्फ़िगरेशन पैरामीटर + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +किसी चल रही प्रक्रिया को रोकें। + +यह एक प्रक्रिया के उदाहरण को रोकता है और उसे हटा देता है, जिससे उसके संसाधनों को मुक्त किया जा सकता है। + +**तर्क:** + +`id`: रोकने के लिए प्रक्रिया की पहचानकर्ता। + +**उदाहरण:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +एसिंक्रोनस फ्लो इंस्टेंस क्लाइंट। + +यह एजेंटों, +आरएजी प्रश्नों, एम्बेडिंग और ग्राफ प्रश्नों सहित फ्लो-स्कोप सेवाओं तक एसिंक्रोनस/अवेट एक्सेस प्रदान करता है। सभी ऑपरेशन पूर्ण +प्रतिक्रियाएं (गैर-स्ट्रीमिंग) लौटाते हैं। + +ध्यान दें: स्ट्रीमिंग समर्थन के लिए, AsyncSocketFlowInstance का उपयोग करें। + +### विधियाँ + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +एसिंक्रोनस फ्लो इंस्टेंस को इनिशियलाइज़ करें। + +**तर्क:** + +`flow`: पैरेंट AsyncFlow क्लाइंट +`flow_id`: फ्लो पहचानकर्ता + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +एक एजेंट ऑपरेशन निष्पादित करें (गैर-स्ट्रीमिंग)। + +यह एक प्रश्न का उत्तर देने के लिए एक एजेंट चलाता है, जिसमें वैकल्पिक वार्तालाप स्थिति और +इतिहास शामिल है। यह एजेंट द्वारा प्रसंस्करण पूरा करने के बाद पूरी प्रतिक्रिया लौटाता है। + + +ध्यान दें: यह विधि स्ट्रीमिंग का समर्थन नहीं करती है। वास्तविक समय में एजेंट के विचारों और +टिप्पणियों के लिए, AsyncSocketFlowInstance.agent() का उपयोग करें। + +**तर्क:** + +`question`: उपयोगकर्ता का प्रश्न या निर्देश +`user`: उपयोगकर्ता पहचानकर्ता +`state`: वार्तालाप संदर्भ के लिए वैकल्पिक स्थिति शब्दकोश +`group`: सत्र प्रबंधन के लिए वैकल्पिक समूह पहचानकर्ता +`history`: वैकल्पिक वार्तालाप इतिहास सूची +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर + +**रिटर्न:** dict: उत्तर और मेटाडेटा सहित एजेंट की पूरी प्रतिक्रिया + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +दस्तावेज़-आधारित आरएजी क्वेरी (गैर-स्ट्रीमिंग) निष्पादित करें। + +दस्तावेज़ एम्बेडिंग का उपयोग करके पुनर्प्राप्ति-संवर्धित पीढ़ी करता है। +प्रासंगिक दस्तावेज़ अंशों को सिमेंटिक खोज के माध्यम से पुनर्प्राप्त करता है, फिर पुनर्प्राप्त दस्तावेज़ों के आधार पर +एक प्रतिक्रिया उत्पन्न करता है। पूर्ण प्रतिक्रिया लौटाता है। + +ध्यान दें: यह विधि स्ट्रीमिंग का समर्थन नहीं करती है। स्ट्रीमिंग आरएजी प्रतिक्रियाओं के लिए, +AsyncSocketFlowInstance.document_rag() का उपयोग करें। + +**तर्क:** + +`query`: उपयोगकर्ता क्वेरी टेक्स्ट +`user`: उपयोगकर्ता पहचानकर्ता +`collection`: दस्तावेज़ युक्त संग्रह पहचानकर्ता +`doc_limit`: पुनर्प्राप्त किए जाने वाले दस्तावेज़ अंशों की अधिकतम संख्या (डिफ़ॉल्ट: 10) +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर + +**रिटर्न:** str: दस्तावेज़ डेटा के आधार पर उत्पन्न पूर्ण प्रतिक्रिया + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +इनपुट टेक्स्ट के लिए एम्बेडिंग उत्पन्न करें। + +टेक्स्ट को संख्यात्मक वेक्टर प्रतिनिधित्व में परिवर्तित करता है, जो कि फ्लो के +कॉन्फ़िगर किए गए एम्बेडिंग मॉडल का उपयोग करके किया जाता है। सिमेंटिक खोज और समानता +तुलना के लिए उपयोगी। + +**तर्क:** + +`texts`: एम्बेड करने के लिए इनपुट टेक्स्ट की सूची। +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर। + +**रिटर्न:** dict: एम्बेडिंग वेक्टर युक्त प्रतिक्रिया। + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +सिमेंटिक इकाई खोज के लिए क्वेरी ग्राफ एम्बेडिंग। + +यह इनपुट टेक्स्ट के लिए सबसे प्रासंगिक इकाइयों को खोजने के लिए ग्राफ इकाई एम्बेडिंग पर सिमेंटिक खोज करता है। समानता के आधार पर रैंक की गई इकाइयों को लौटाता है। + + +**तर्क:** + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट। +`user`: उपयोगकर्ता पहचानकर्ता। +`collection`: ग्राफ एम्बेडिंग युक्त संग्रह पहचानकर्ता। +`limit`: लौटाने के लिए अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10)। +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर। + +**रिटर्न:** dict: रैंक किए गए इकाई मिलानों के साथ प्रतिक्रिया, जिसमें समानता स्कोर शामिल हैं। + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +ग्राफ-आधारित आरएजी क्वेरी (गैर-स्ट्रीमिंग) निष्पादित करें। + +यह ज्ञान ग्राफ डेटा का उपयोग करके पुनर्प्राप्ति-संवर्धित पीढ़ी करता है। +यह प्रासंगिक संस्थाओं और उनके संबंधों की पहचान करता है, और फिर ग्राफ संरचना पर आधारित एक +प्रतिक्रिया उत्पन्न करता है। यह पूर्ण प्रतिक्रिया लौटाता है। + +ध्यान दें: यह विधि स्ट्रीमिंग का समर्थन नहीं करती है। स्ट्रीमिंग आरएजी प्रतिक्रियाओं के लिए, +AsyncSocketFlowInstance.graph_rag() का उपयोग करें। + +**तर्क:** + +`query`: उपयोगकर्ता क्वेरी टेक्स्ट +`user`: उपयोगकर्ता पहचानकर्ता +`collection`: ज्ञान ग्राफ युक्त संग्रह पहचानकर्ता +`max_subgraph_size`: प्रति सबग्राफ अधिकतम त्रिकों की संख्या (डिफ़ॉल्ट: 1000) +`max_subgraph_count`: पुनर्प्राप्त किए जाने वाले अधिकतम सबग्राफ की संख्या (डिफ़ॉल्ट: 5) +`max_entity_distance`: इकाई विस्तार के लिए अधिकतम ग्राफ दूरी (डिफ़ॉल्ट: 3) +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर + +**रिटर्न:** स्ट्रिंग: ग्राफ डेटा पर आधारित पूर्ण उत्पन्न प्रतिक्रिया + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +किसी फ्लो-स्कोप सेवा को अनुरोध भेजें। + +इस फ्लो इंस्टेंस के भीतर सेवाओं को कॉल करने के लिए आंतरिक विधि। + +**तर्क:** + +`service`: सेवा का नाम (उदाहरण के लिए, "एजेंट", "ग्राफ-आरएजी", "ट्रिपल्स") +`request_data`: सेवा अनुरोध पेलोड + +**रिटर्न:** डिक्ट: सेवा प्रतिक्रिया ऑब्जेक्ट + +**अपवाद:** + +`ProtocolException`: यदि अनुरोध विफल हो जाता है या प्रतिक्रिया अमान्य है +`ApplicationException`: यदि सेवा कोई त्रुटि लौटाती है + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +संरचित डेटा पर सिमेंटिक खोज के लिए क्वेरी रो एम्बेडिंग। + +पंक्तियों के रो इंडेक्स एम्बेडिंग पर सिमेंटिक खोज करता है ताकि उन पंक्तियों को खोजा जा सके जिनके +अनुक्रमित फ़ील्ड मान इनपुट टेक्स्ट के सबसे समान हैं। संरचित डेटा पर अस्पष्ट/सिमेंटिक मिलान को सक्षम करता है। + +**तर्क:** + + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट। +`schema_name`: खोज के लिए स्कीमा नाम। +`user`: उपयोगकर्ता पहचानकर्ता (डिफ़ॉल्ट: "trustgraph")। +`collection`: संग्रह पहचानकर्ता (डिफ़ॉल्ट: "default")। +`index_name`: वैकल्पिक इंडेक्स नाम जिसका उपयोग खोज को विशिष्ट इंडेक्स तक सीमित करने के लिए किया जा सकता है। +`limit`: वापस करने के लिए अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10)। +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर। + +**रिटर्न:** dict: मिलान वाले उत्तर जिसमें index_name, index_value, text और score शामिल हैं। + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +संग्रहीत पंक्तियों पर एक GraphQL क्वेरी निष्पादित करें। + +यह संरचित डेटा पंक्तियों को GraphQL सिंटैक्स का उपयोग करके क्वेरी करता है। यह चर और नामित ऑपरेशनों के साथ जटिल +क्वेरी का समर्थन करता है। + +**तर्क:** + +`query`: GraphQL क्वेरी स्ट्रिंग +`user`: उपयोगकर्ता पहचानकर्ता +`collection`: पंक्तियों वाले संग्रह पहचानकर्ता +`variables`: वैकल्पिक GraphQL क्वेरी चर +`operation_name`: मल्टी-ऑपरेशन क्वेरी के लिए वैकल्पिक ऑपरेशन नाम +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर + +**रिटर्न:** dict: डेटा और/या त्रुटियों के साथ GraphQL प्रतिक्रिया + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +पाठ पूर्णता उत्पन्न करें (गैर-स्ट्रीमिंग)। + +यह विधि, एक सिस्टम प्रॉम्प्ट और उपयोगकर्ता प्रॉम्प्ट के आधार पर, एक एलएलएम से पाठ प्रतिक्रिया उत्पन्न करती है। +यह पूर्ण प्रतिक्रिया पाठ लौटाता है। + +ध्यान दें: यह विधि स्ट्रीमिंग का समर्थन नहीं करती है। स्ट्रीमिंग पाठ पीढ़ी के लिए, +AsyncSocketFlowInstance.text_completion() का उपयोग करें। + +**तर्क:** + +`system`: सिस्टम प्रॉम्प्ट जो एलएलएम के व्यवहार को परिभाषित करता है। +`prompt`: उपयोगकर्ता प्रॉम्प्ट या प्रश्न। +`**kwargs`: अतिरिक्त, सेवा-विशिष्ट पैरामीटर। + +**रिटर्न:** str: पूर्ण उत्पन्न पाठ प्रतिक्रिया। + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +पैटर्न मिलान का उपयोग करके RDF त्रिगुणों की खोज करें। + +यह निर्दिष्ट विषय, विधेय और/या +ऑब्जेक्ट पैटर्न से मेल खाने वाले त्रिगुणों की खोज करता है। पैटर्न किसी भी मान से मेल खाने के लिए 'None' का उपयोग करते हैं। + +**तर्क:** + +`s`: विषय पैटर्न (किसी भी मान से मेल खाने के लिए 'None') +`p`: विधेय पैटर्न (किसी भी मान से मेल खाने के लिए 'None') +`o`: ऑब्जेक्ट पैटर्न (किसी भी मान से मेल खाने के लिए 'None') +`user`: उपयोगकर्ता पहचानकर्ता (सभी उपयोगकर्ताओं के लिए 'None') +`collection`: संग्रह पहचानकर्ता (सभी संग्रहों के लिए 'None') +`limit`: लौटाने के लिए त्रिगुणों की अधिकतम संख्या (डिफ़ॉल्ट: 100) +`**kwargs`: अतिरिक्त सेवा-विशिष्ट पैरामीटर + +**वापसी:** dict: मिलान करने वाले त्रिगुणों वाली प्रतिक्रिया + +**उदाहरण:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +स्ट्रीमिंग कार्यों के लिए सिंक्रोनस वेबसॉकेट क्लाइंट। + +यह वेबसॉकेट-आधारित ट्रस्टग्राफ सेवाओं के लिए एक सिंक्रोनस इंटरफ़ेस प्रदान करता है, +जो उपयोग में आसानी के लिए सिंक्रोनस जनरेटर के साथ एसिंक्रोनस वेबसॉकेट लाइब्रेरी को रैप करता है। +यह एजेंटों, आरएजी प्रश्नों और टेक्स्ट पूर्णता से स्ट्रीमिंग प्रतिक्रियाओं का समर्थन करता है। + +ध्यान दें: यह एसिंक्रोनस वेबसॉकेट ऑपरेशनों के चारों ओर एक सिंक्रोनस रैपर है। +वास्तविक एसिंक्रोनस समर्थन के लिए, AsyncSocketClient का उपयोग करें। + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +सिंक्रोनस वेबसॉकेट क्लाइंट को इनिशियलाइज़ करें। + +**तर्क:** + +`url`: ट्रस्टग्राफ एपीआई के लिए बेस यूआरएल (HTTP/HTTPS को WS/WSS में परिवर्तित किया जाएगा) +`timeout`: सेकंड में वेबसॉकेट टाइमआउट +`token`: प्रमाणीकरण के लिए वैकल्पिक बेयरर टोकन + +### `close(self) -> None` + +वेबसॉकेट कनेक्शन बंद करें। + +ध्यान दें: एसिंक्रोनस कोड में संदर्भ प्रबंधकों द्वारा सफाई स्वचालित रूप से संभाली जाती है। + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +वेबसॉकेट स्ट्रीमिंग ऑपरेशनों के लिए एक फ्लो इंस्टेंस प्राप्त करें। + +**तर्क:** + +`flow_id`: फ्लो पहचानकर्ता + +**रिटर्न:** SocketFlowInstance: स्ट्रीमिंग विधियों वाला फ्लो इंस्टेंस + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +सिंक्रोनस वेबसॉकेट फ्लो इंस्टेंस, स्ट्रीमिंग कार्यों के लिए। + +यह REST फ्लोइंस्टेंस के समान इंटरफ़ेस प्रदान करता है, लेकिन वास्तविक समय प्रतिक्रियाओं के लिए वेबसॉकेट-आधारित +स्ट्रीमिंग समर्थन के साथ। सभी विधियाँ एक वैकल्पिक +`streaming` पैरामीटर का समर्थन करती हैं, जो वृद्धिशील परिणाम वितरण को सक्षम करता है। + +### विधियाँ + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +सॉकेट फ्लो इंस्टेंस को आरंभ करें। + +**तर्क:** + +`client`: पैरेंट सॉकेटक्लाइंट +`flow_id`: फ्लो पहचानकर्ता + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +एक एजेंट ऑपरेशन को स्ट्रीमिंग समर्थन के साथ निष्पादित करें। + +एजेंट टूल का उपयोग करके बहु-चरणीय तर्क कर सकते हैं। यह विधि हमेशा +स्ट्रीमिंग चंक्स (विचार, अवलोकन, उत्तर) लौटाती है, भले ही +streaming=False हो, ताकि एजेंट की तर्क प्रक्रिया दिखाई जा सके। + +**तर्क:** + +`question`: उपयोगकर्ता का प्रश्न या निर्देश +`user`: उपयोगकर्ता पहचानकर्ता +`state`: स्टेटफुल वार्तालापों के लिए वैकल्पिक स्टेट डिक्शनरी +`group`: मल्टी-यूजर संदर्भों के लिए वैकल्पिक समूह पहचानकर्ता +`history`: वैकल्पिक रूप से संदेशों की सूची के रूप में वार्तालाप इतिहास +`streaming`: स्ट्रीमिंग मोड सक्षम करें (डिफ़ॉल्ट: False) +`**kwargs`: एजेंट सेवा को पास किए गए अतिरिक्त पैरामीटर + +**रिटर्न:** Iterator[StreamingChunk]: एजेंट के विचारों, अवलोकनों और उत्तरों का स्ट्रीम + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +स्पष्टीकरण समर्थन के साथ एक एजेंट ऑपरेशन निष्पादित करें। + +यह सामग्री खंडों (AgentThought, AgentObservation, AgentAnswer) +और प्रामाणिकता घटनाओं (ProvenanceEvent) दोनों को स्ट्रीम करता है। प्रामाणिकता घटनाओं में URI होते हैं +जिन्हें विस्तृत जानकारी प्राप्त करने के लिए ExplainabilityClient का उपयोग करके प्राप्त किया जा सकता है +एजेंट के तर्क प्रक्रिया के बारे में। + +एजेंट ट्रेस में शामिल हैं: +सत्र: प्रारंभिक प्रश्न और सत्र मेटाडेटा +पुनरावृत्तियाँ: प्रत्येक विचार/क्रिया/अवलोकन चक्र +निष्कर्ष: अंतिम उत्तर + +**तर्क:** + +`question`: उपयोगकर्ता का प्रश्न या निर्देश +`user`: उपयोगकर्ता पहचानकर्ता +`collection`: प्रामाणिकता भंडारण के लिए संग्रह पहचानकर्ता +`state`: राज्यपूर्ण वार्ता के लिए वैकल्पिक राज्य शब्दकोश +`group`: बहु-उपयोगकर्ता संदर्भों के लिए वैकल्पिक समूह पहचानकर्ता +`history`: संदेशों की सूची के रूप में वैकल्पिक वार्ता इतिहास +`**kwargs`: एजेंट सेवा को अतिरिक्त पैरामीटर +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: एजेंट खंड और प्रामाणिकता घटनाएँ + +**उदाहरण:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +सिमेंटिक समानता का उपयोग करके दस्तावेज़ के टुकड़ों को क्वेरी करें। + +**तर्क:** + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`limit`: अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर + +**रिटर्न:** डिक्ट: मिलान करने वाले दस्तावेज़ टुकड़ों के chunk_ids के साथ क्वेरी परिणाम + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +दस्तावेज़-आधारित आरएजी क्वेरी को वैकल्पिक स्ट्रीमिंग के साथ निष्पादित करें। + +यह प्रासंगिक दस्तावेज़ टुकड़ों को खोजने के लिए वेक्टर एम्बेडिंग का उपयोग करता है, फिर एक एलएलएम का उपयोग करके +प्रतिक्रिया उत्पन्न करता है। स्ट्रीमिंग मोड क्रमिक रूप से परिणाम प्रदान करता है। + +**तर्क:** + +`query`: प्राकृतिक भाषा क्वेरी +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`doc_limit`: पुनर्प्राप्त किए जाने वाले अधिकतम दस्तावेज़ टुकड़ों की संख्या (डिफ़ॉल्ट: 10) +`streaming`: स्ट्रीमिंग मोड सक्षम करें (डिफ़ॉल्ट: False) +`**kwargs`: सेवा को पारित अतिरिक्त पैरामीटर + +**रिटर्न:** Union[str, Iterator[str]]: पूर्ण प्रतिक्रिया या पाठ टुकड़ों की धारा + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +दस्तावेज़-आधारित आरएजी क्वेरी को व्याख्यात्मकता समर्थन के साथ निष्पादित करें। + +यह सामग्री के टुकड़ों (RAGChunk) और उत्पत्ति घटनाओं (ProvenanceEvent) दोनों को स्ट्रीम करता है। +उत्पत्ति घटनाओं में यूआरआई होते हैं जिन्हें ExplainabilityClient का उपयोग करके प्राप्त किया जा सकता है +ताकि प्रतिक्रिया कैसे उत्पन्न हुई, इसके बारे में विस्तृत जानकारी प्राप्त की जा सके। + +दस्तावेज़ आरएजी ट्रेस में निम्नलिखित शामिल हैं: +प्रश्न: उपयोगकर्ता की क्वेरी +अन्वेषण: दस्तावेज़ भंडार से प्राप्त किए गए टुकड़े (chunk_count) +संश्लेषण: उत्पन्न उत्तर + +**तर्क:** + +`query`: प्राकृतिक भाषा क्वेरी +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`doc_limit`: पुनर्प्राप्त करने के लिए अधिकतम दस्तावेज़ टुकड़े (डिफ़ॉल्ट: 10) +`**kwargs`: सेवा को पारित अतिरिक्त पैरामीटर +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: सामग्री के टुकड़े और उत्पत्ति घटनाएं + +**उदाहरण:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +एक या अधिक ग्रंथों के लिए वेक्टर एम्बेडिंग उत्पन्न करें। + +**तर्क:** + +`texts`: एम्बेड करने के लिए इनपुट ग्रंथों की सूची +`**kwargs`: सेवा को पास किए गए अतिरिक्त पैरामीटर + +**रिटर्न:** dict: वैक्टर युक्त प्रतिक्रिया (प्रत्येक इनपुट टेक्स्ट के लिए एक सेट) + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +सिमेंटिक समानता का उपयोग करके ज्ञान ग्राफ संस्थाओं को क्वेरी करें। + +**तर्क:** + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`limit`: अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर + +**रिटर्न:** dict: समान संस्थाओं के साथ क्वेरी परिणाम + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +ग्राफ-आधारित आरएजी क्वेरी को वैकल्पिक स्ट्रीमिंग के साथ निष्पादित करें। + +यह प्रासंगिक संदर्भ खोजने के लिए ज्ञान ग्राफ संरचना का उपयोग करता है, और फिर +एक एलएलएम का उपयोग करके प्रतिक्रिया उत्पन्न करता है। स्ट्रीमिंग मोड क्रमिक रूप से परिणाम प्रदान करता है। + +**तर्क:** + +`query`: प्राकृतिक भाषा क्वेरी +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`max_subgraph_size`: सबग्राफ में अधिकतम कुल त्रिगुण (डिफ़ॉल्ट: 1000) +`max_subgraph_count`: उपग्राफ की अधिकतम संख्या (डिफ़ॉल्ट: 5) +`max_entity_distance`: अधिकतम ट्रैवर्सल गहराई (डिफ़ॉल्ट: 3) +`streaming`: स्ट्रीमिंग मोड सक्षम करें (डिफ़ॉल्ट: False) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर जो भेजे जाते हैं + +**रिटर्न:** यूनियन[स्ट्रिंग, इटरेटर[स्ट्रिंग]]: पूर्ण प्रतिक्रिया या टेक्स्ट चंक्स की स्ट्रीम + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +स्पष्टीकरण समर्थन के साथ ग्राफ-आधारित आरएजी क्वेरी निष्पादित करें। + +यह सामग्री खंडों (RAGChunk) और उत्पत्ति घटनाओं (ProvenanceEvent) दोनों को स्ट्रीम करता है। +उत्पत्ति घटनाओं में यूआरआई होते हैं जिन्हें ExplainabilityClient का उपयोग करके प्राप्त किया जा सकता है +ताकि प्रतिक्रिया कैसे उत्पन्न हुई, इसके बारे में विस्तृत जानकारी प्राप्त की जा सके। + +**तर्क:** + +`query`: प्राकृतिक भाषा क्वेरी +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`max_subgraph_size`: सबग्राफ में अधिकतम कुल त्रिगुण (डिफ़ॉल्ट: 1000) +`max_subgraph_count`: उपग्राफों की अधिकतम संख्या (डिफ़ॉल्ट: 5) +`max_entity_distance`: अधिकतम ट्रैवर्सल गहराई (डिफ़ॉल्ट: 3) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: सामग्री खंड और उत्पत्ति घटनाएं + +**उदाहरण:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +मॉडल कॉन्टेक्स्ट प्रोटोकॉल (MCP) टूल को निष्पादित करें। + +**तर्क:** + +`name`: टूल का नाम/पहचानकर्ता +`parameters`: टूल पैरामीटर डिक्शनरी +`**kwargs`: सेवा को पास किए गए अतिरिक्त पैरामीटर + +**रिटर्न:** डिक्ट: टूल निष्पादन परिणाम + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +एक वैकल्पिक स्ट्रीमिंग विकल्प के साथ एक प्रॉम्प्ट टेम्पलेट निष्पादित करें। + +**तर्क:** + +`id`: प्रॉम्प्ट टेम्पलेट पहचानकर्ता +`variables`: चर नाम से मान मैपिंग का शब्दकोश +`streaming`: स्ट्रीमिंग मोड सक्षम करें (डिफ़ॉल्ट: False) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर + +**रिटर्न:** Union[str, Iterator[str]]: पूर्ण प्रतिक्रिया या टेक्स्ट चंक्स की धारा + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +अनुक्रमित फ़ील्ड पर सिमेंटिक समानता का उपयोग करके पंक्ति डेटा क्वेरी करें। + +उन पंक्तियों को खोजें जिनके अनुक्रमित फ़ील्ड मान इनपुट टेक्स्ट के सिमेंटिक रूप से समान हैं, +वेक्टर एम्बेडिंग का उपयोग करके। यह संरचित डेटा पर अस्पष्ट/सिमेंटिक मिलान को सक्षम बनाता है। + + +**तर्क:** + +`text`: सिमेंटिक खोज के लिए क्वेरी टेक्स्ट +`schema_name`: खोज के लिए स्कीमा का नाम +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (डिफ़ॉल्ट: "trustgraph") +`collection`: संग्रह पहचानकर्ता (डिफ़ॉल्ट: "default") +`index_name`: वैकल्पिक इंडेक्स नाम जिससे खोज को विशिष्ट इंडेक्स तक सीमित किया जा सके +`limit`: अधिकतम परिणामों की संख्या (डिफ़ॉल्ट: 10) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर जो पास किए जाते हैं + +**रिटर्न:** dict: मिलान वाले क्वेरी परिणाम जिनमें index_name, index_value, text और score शामिल हैं + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +संरचित पंक्तियों के विरुद्ध एक GraphQL क्वेरी निष्पादित करें। + +**तर्क:** + +`query`: GraphQL क्वेरी स्ट्रिंग +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`variables`: वैकल्पिक क्वेरी चर शब्दकोश +`operation_name`: मल्टी-ऑपरेशन दस्तावेज़ों के लिए वैकल्पिक ऑपरेशन नाम +`**kwargs`: सेवा को पारित अतिरिक्त पैरामीटर + +**रिटर्न:** dict: डेटा, त्रुटियों और/या एक्सटेंशन के साथ GraphQL प्रतिक्रिया + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +वैकल्पिक स्ट्रीमिंग के साथ टेक्स्ट पूर्णता निष्पादित करें। + +**तर्क:** + +`system`: सिस्टम प्रॉम्प्ट जो सहायक के व्यवहार को परिभाषित करता है। +`prompt`: उपयोगकर्ता प्रॉम्प्ट/प्रश्न। +`streaming`: स्ट्रीमिंग मोड सक्षम करें (डिफ़ॉल्ट: False)। +`**kwargs`: सेवा को पारित अतिरिक्त पैरामीटर। + +**रिटर्न:** Union[str, Iterator[str]]: पूर्ण प्रतिक्रिया या टेक्स्ट टुकड़ों की धारा। + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +पैटर्न मिलान का उपयोग करके ज्ञान ग्राफ त्रिकों को क्वेरी करें। + +**तर्क:** + +`s`: विषय फ़िल्टर - URI स्ट्रिंग, टर्म डिक्शनरी, या वाइल्डकार्ड के लिए None +`p`: विधेय फ़िल्टर - URI स्ट्रिंग, टर्म डिक्शनरी, या वाइल्डकार्ड के लिए None +`o`: वस्तु फ़िल्टर - URI/लिटरल स्ट्रिंग, टर्म डिक्शनरी, या वाइल्डकार्ड के लिए None +`g`: नामित ग्राफ फ़िल्टर - URI स्ट्रिंग या सभी ग्राफों के लिए None +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (वैकल्पिक) +`collection`: संग्रह पहचानकर्ता (वैकल्पिक) +`limit`: वापस करने के लिए अधिकतम परिणाम (डिफ़ॉल्ट: 100) +`**kwargs`: सेवा को अतिरिक्त पैरामीटर + +**वापसी:** List[Dict]: वायर प्रारूप में मिलान किए गए त्रिकों की सूची + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +स्ट्रीमिंग बैचों के साथ नॉलेज ग्राफ ट्रिपल क्वेरी करें। + +जैसे ही ट्रिपल आते हैं, वे बैचों में उपलब्ध होते हैं, जिससे पहले परिणाम प्राप्त करने का समय कम होता है +और बड़े परिणाम सेट के लिए मेमोरी ओवरहेड कम होता है। + +**तर्क:** + +`s`: विषय फ़िल्टर - URI स्ट्रिंग, टर्म डिक्ट, या वाइल्डकार्ड के लिए None +`p`: विधेय फ़िल्टर - URI स्ट्रिंग, टर्म डिक्ट, या वाइल्डकार्ड के लिए None +`o`: वस्तु फ़िल्टर - URI/लिटरल स्ट्रिंग, टर्म डिक्ट, या वाइल्डकार्ड के लिए None +`g`: नामित ग्राफ फ़िल्टर - URI स्ट्रिंग या सभी ग्राफ के लिए None +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता (वैकल्पिक) +`collection`: संग्रह पहचानकर्ता (वैकल्पिक) +`limit`: वापस करने के लिए अधिकतम परिणाम (डिफ़ॉल्ट: 100) +`batch_size`: प्रति बैच ट्रिपल (डिफ़ॉल्ट: 20) +`**kwargs`: सेवा को पास किए गए अतिरिक्त पैरामीटर +`Yields`: +`List[Dict]`: वायर प्रारूप में ट्रिपल के बैच + +**उदाहरण:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +एसिंक्रोनस वेबसॉकेट क्लाइंट + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None)` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + +### `aclose(self)` + +वेबसॉकेट कनेक्शन बंद करें + +### `flow(self, flow_id: str)` + +वेबसॉकेट संचालन के लिए एसिंक्रोनस फ्लो इंस्टेंस प्राप्त करें + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +एसिंक्रोनस वेबसॉकेट फ्लो इंस्टेंस + +### विधियाँ + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +वैकल्पिक स्ट्रीमिंग के साथ एजेंट + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +वैकल्पिक स्ट्रीमिंग के साथ RAG दस्तावेज़ + +### `embeddings(self, texts: list, **kwargs)` + +टेक्स्ट एम्बेडिंग उत्पन्न करें + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +सिमेंटिक खोज के लिए ग्राफ एम्बेडिंग क्वेरी करें + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +वैकल्पिक स्ट्रीमिंग के साथ ग्राफ RAG + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +MCP टूल निष्पादित करें + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +वैकल्पिक स्ट्रीमिंग के साथ प्रॉम्प्ट निष्पादित करें + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +संरचित डेटा पर सिमेंटिक खोज के लिए पंक्ति एम्बेडिंग क्वेरी करें + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +संरचित पंक्तियों के खिलाफ GraphQL क्वेरी + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +वैकल्पिक स्ट्रीमिंग के साथ टेक्स्ट पूर्णता + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +ट्रिपल पैटर्न क्वेरी + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +एक मान से वायर-फॉर्मेट टर्म डिक्ट बनाएं। + +ऑटो-डिटेक्शन नियम (जब term_type None है): + पहले से ही 't' कुंजी वाला डिक्ट -> यथावत लौटाएं (पहले से ही एक टर्म) + http://, https://, urn: से शुरू होता है -> IRI + <> (जैसे, ) में संलग्न -> IRI (कोण कोष्ठक हटा दिए गए) + कुछ भी और -> शाब्दिक + +**तर्क:** + +`value`: टर्म मान (स्ट्रिंग, डिक्ट या None) +`term_type`: 'iri', 'literal' या ऑटो-डिटेक्शन के लिए None में से एक +`datatype`: शाब्दिक ऑब्जेक्ट के लिए डेटाटाइप (जैसे, xsd:integer) +`language`: शाब्दिक ऑब्जेक्ट के लिए भाषा टैग (जैसे, en) + +**रिटर्न:** डिक्ट: वायर-फॉर्मेट टर्म डिक्ट, या यदि मान None है तो None + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +आयात/निर्यात के लिए सिंक्रोनस बल्क ऑपरेशंस क्लाइंट। + +बड़े डेटासेट के लिए कुशल बल्क डेटा ट्रांसफर वेबसॉकेट के माध्यम से प्रदान करता है। +उपयोग में आसानी के लिए सिंक्रोनस जनरेटर के साथ एसिंक्रोनस वेबसॉकेट ऑपरेशंस को रैप करता है। + +ध्यान दें: वास्तविक एसिंक्रोनस समर्थन के लिए, AsyncBulkClient का उपयोग करें। + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +सिंक्रोनस बल्क क्लाइंट को इनिशियलाइज़ करें। + +**तर्क:** + +`url`: ट्रस्टग्राफ एपीआई के लिए बेस यूआरएल (HTTP/HTTPS को WS/WSS में परिवर्तित किया जाएगा) +`timeout`: सेकंड में वेबसॉकेट टाइमआउट +`token`: प्रमाणीकरण के लिए वैकल्पिक बेयरर टोकन + +### `close(self) -> None` + +कनेक्शन बंद करें + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +एक फ्लो से बल्क एक्सपोर्ट डॉक्यूमेंट एम्बेडिंग। + +वेबसॉकेट स्ट्रीमिंग के माध्यम से सभी डॉक्यूमेंट चंक एम्बेडिंग को कुशलतापूर्वक डाउनलोड करता है। + +**तर्क:** + +`flow`: फ्लो आइडेंटिफायर +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**रिटर्न:** Iterator[Dict[str, Any]]: एम्बेडिंग डिक्शनरी का स्ट्रीम + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +किसी फ्लो से बल्क एक्सपोर्ट एंटिटी कॉन्टेक्स्ट। + +वेबसॉकेट स्ट्रीमिंग के माध्यम से सभी एंटिटी कॉन्टेक्स्ट जानकारी को कुशलतापूर्वक डाउनलोड करता है। + +**तर्क:** + +`flow`: फ्लो आइडेंटिफायर +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**रिटर्न:** Iterator[Dict[str, Any]]: कॉन्टेक्स्ट डिक्शनरी का स्ट्रीम + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +एक फ्लो से ग्राफ एम्बेडिंग का बल्क एक्सपोर्ट। + +वेबसॉकेट स्ट्रीमिंग के माध्यम से सभी ग्राफ एंटिटी एम्बेडिंग को कुशलतापूर्वक डाउनलोड करता है। + +**तर्क:** + +`flow`: फ्लो आइडेंटिफायर +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**रिटर्न:** Iterator[Dict[str, Any]]: एम्बेडिंग डिक्शनरी का स्ट्रीम + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +एक प्रवाह से RDF त्रिगुणों का बल्क निर्यात करें। + +सभी त्रिगुणों को कुशलतापूर्वक WebSocket स्ट्रीमिंग के माध्यम से डाउनलोड करता है। + +**तर्क:** + +`flow`: प्रवाह पहचानकर्ता +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**रिटर्न:** Iterator[Triple]: ट्रिपल ऑब्जेक्ट्स की स्ट्रीम + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +एक फ्लो में दस्तावेज़ एम्बेडिंग को बल्क में इम्पोर्ट करें। + +दस्तावेज़ RAG प्रश्नों में उपयोग के लिए, वेबसॉकेट स्ट्रीमिंग के माध्यम से कुशलतापूर्वक दस्तावेज़ चंक एम्बेडिंग अपलोड करता है। + + +**तर्क:** + +`flow`: फ्लो पहचानकर्ता +`embeddings`: एम्बेडिंग डिक्शनरी उत्पन्न करने वाला इटरेटर +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +एक फ्लो में एंटिटी कॉन्टेक्स्ट को बल्क में इम्पोर्ट करें। + +वेबसॉकेट स्ट्रीमिंग के माध्यम से एंटिटी कॉन्टेक्स्ट जानकारी को कुशलतापूर्वक अपलोड करता है। +एंटिटी कॉन्टेक्स्ट, ग्राफ एंटिटीज के बारे में अतिरिक्त पाठ्य संदर्भ प्रदान करते हैं +बेहतर RAG प्रदर्शन के लिए। + +**तर्क:** + +`flow`: फ्लो आइडेंटिफायर +`contexts`: कॉन्टेक्स्ट डिक्शनरी उत्पन्न करने वाला इटरेटर +`metadata`: आईडी, मेटाडेटा, उपयोगकर्ता, संग्रह के साथ मेटाडेटा डिक्ट +`batch_size`: बैच प्रति कॉन्टेक्स्ट की संख्या (डिफ़ॉल्ट 100) +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +एक फ्लो में ग्राफ एम्बेडिंग को बल्क में इम्पोर्ट करें। + +वेबसॉकेट स्ट्रीमिंग के माध्यम से ग्राफ एंटिटी एम्बेडिंग को कुशलतापूर्वक अपलोड करता है। + +**तर्क:** + +`flow`: फ्लो पहचानकर्ता +`embeddings`: एम्बेडिंग डिक्शनरी उत्पन्न करने वाला इटरेटर +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +एक फ्लो में संरचित पंक्तियों को बल्क में आयात करें। + +कुशलतापूर्वक संरचित डेटा पंक्तियों को WebSocket स्ट्रीमिंग के माध्यम से अपलोड करता है +जिसका उपयोग GraphQL प्रश्नों में किया जाता है। + +**तर्क:** + +`flow`: फ्लो पहचानकर्ता +`rows`: पंक्ति शब्दकोशों को उत्पन्न करने वाला इटरेटर +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**उदाहरण:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +एक फ्लो में RDF ट्रिपल का बल्क इम्पोर्ट करें। + +वेबसॉकेट स्ट्रीमिंग के माध्यम से बड़ी संख्या में ट्रिपल को कुशलतापूर्वक अपलोड करता है। + +**तर्क:** + +`flow`: फ्लो आइडेंटिफायर +`triples`: ट्रिपल ऑब्जेक्ट्स उत्पन्न करने वाला इटरेटर +`metadata`: आईडी, मेटाडेटा, यूजर, कलेक्शन के साथ मेटाडेटा डिक्ट +`batch_size`: प्रति बैच ट्रिपल की संख्या (डिफ़ॉल्ट 100) +`**kwargs`: अतिरिक्त पैरामीटर (भविष्य के उपयोग के लिए आरक्षित) + +**उदाहरण:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +एसिंक्रोनस बल्क ऑपरेशंस क्लाइंट + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +स्वयं को इनिशियलाइज़ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + +### `aclose(self) -> None` + +कनेक्शन बंद करें + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +वेबसॉकेट के माध्यम से दस्तावेज़ एम्बेडिंग का बल्क एक्सपोर्ट + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +वेबसॉकेट के माध्यम से एंटिटी कॉन्टेक्स्ट का बल्क एक्सपोर्ट + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +वेबसॉकेट के माध्यम से ग्राफ एम्बेडिंग का बल्क एक्सपोर्ट + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +वेबसॉकेट के माध्यम से ट्रिपल्स का बल्क एक्सपोर्ट + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +वेबसॉकेट के माध्यम से दस्तावेज़ एम्बेडिंग का बल्क इम्पोर्ट + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +वेबसॉकेट के माध्यम से एंटिटी कॉन्टेक्स्ट का बल्क इम्पोर्ट + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +वेबसॉकेट के माध्यम से ग्राफ एम्बेडिंग का बल्क इम्पोर्ट + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +वेबसॉकेट के माध्यम से पंक्तियों का बल्क इम्पोर्ट + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +वेबसॉकेट के माध्यम से ट्रिपल्स का बल्क इम्पोर्ट + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +सिंक्रोनस मेट्रिक्स क्लाइंट + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + +### `get(self) -> str` + +प्रोमेथियस मेट्रिक्स को टेक्स्ट के रूप में प्राप्त करें + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +एसिंक्रोनस मेट्रिक्स क्लाइंट + +### विधियाँ + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + +### `aclose(self) -> None` + +कनेक्शन बंद करें + +### `get(self) -> str` + +प्रोमेथियस मेट्रिक्स को टेक्स्ट के रूप में प्राप्त करें + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +स्पष्टीकरण संस्थाओं को लाने के लिए क्लाइंट, जिसमें अंततः स्थिरता प्रबंधन शामिल है। + +यह शांत अवस्था का पता लगाने का उपयोग करता है: प्राप्त करें, प्रतीक्षा करें, फिर से प्राप्त करें, तुलना करें। +यदि परिणाम समान हैं, तो डेटा स्थिर है। + +### विधियाँ + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +स्पष्टीकरण क्लाइंट को आरंभ करें। + +**तर्क:** + +`flow_instance`: त्रिकों को क्वेरी करने के लिए एक SocketFlowInstance +`retry_delay`: पुन: प्रयास के बीच का विलंब (डिफ़ॉल्ट: 0.2) +`max_retries`: अधिकतम पुन: प्रयास (डिफ़ॉल्ट: 10) + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +पता करें कि क्या सत्र GraphRAG या Agent प्रकार का है। + +**तर्क:** + +`session_uri`: सत्र/प्रश्न URI +`graph`: नामित ग्राफ +`user`: उपयोगकर्ता/keyspace पहचानकर्ता +`collection`: संग्रह पहचानकर्ता + +**रिटर्न:** "graphrag" या "agent" + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +एक सत्र URI से शुरू होने वाला संपूर्ण Agent ट्रेस प्राप्त करें। + +यह उत्पत्ति श्रृंखला का अनुसरण करता है: प्रश्न -> विश्लेषण (s) -> निष्कर्ष + +**तर्क:** + +`session_uri`: एजेंट सत्र/प्रश्न URI +`graph`: नामित ग्राफ (डिफ़ॉल्ट: urn:graph:retrieval) +`user`: उपयोगकर्ता/keyspace पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`api`: लाइब्रेरियन एक्सेस के लिए TrustGraph Api उदाहरण (वैकल्पिक) +`max_content`: निष्कर्ष के लिए अधिकतम सामग्री लंबाई + +**रिटर्न:** प्रश्न, पुनरावृत्तियों (विश्लेषण सूची), निष्कर्ष संस्थाओं के साथ डिक्ट + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +एक प्रश्न URI से शुरू होने वाला संपूर्ण DocumentRAG ट्रेस प्राप्त करें। + +यह उत्पत्ति श्रृंखला का अनुसरण करता है: + प्रश्न -> ग्राउंडिंग -> अन्वेषण -> संश्लेषण + +**तर्क:** + +`question_uri`: प्रश्न इकाई URI +`graph`: नामित ग्राफ (डिफ़ॉल्ट: urn:graph:retrieval) +`user`: उपयोगकर्ता/keyspace पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`api`: लाइब्रेरियन एक्सेस के लिए TrustGraph Api उदाहरण (वैकल्पिक) +`max_content`: संश्लेषण के लिए अधिकतम सामग्री लंबाई + +**रिटर्न:** प्रश्न, ग्राउंडिंग, अन्वेषण, संश्लेषण संस्थाओं के साथ डिक्ट + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +दस्तावेज़ URI द्वारा लाइब्रेरियन से सामग्री प्राप्त करें। + +**तर्क:** + +`document_uri`: लाइब्रेरियन में दस्तावेज़ URI +`api`: लाइब्रेरियन एक्सेस के लिए TrustGraph Api उदाहरण +`user`: लाइब्रेरियन के लिए उपयोगकर्ता पहचानकर्ता +`max_content`: वापस करने के लिए अधिकतम सामग्री लंबाई + +**रिटर्न:** स्ट्रिंग के रूप में दस्तावेज़ सामग्री + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +एक एज सिलेक्शन एंटिटी प्राप्त करें (जो फोकस द्वारा उपयोग किया जाता है)। + +**तर्क:** + +`uri`: एज सिलेक्शन URI +`graph`: क्वेरी करने के लिए नामित ग्राफ +`user`: उपयोगकर्ता/keyspace पहचानकर्ता +`collection`: संग्रह पहचानकर्ता + +**रिटर्न:** एज सिलेक्शन या यदि नहीं मिला तो None + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +URI के माध्यम से एक व्याख्यात्मकता इकाई प्राप्त करें और संभावित स्थिरता प्रबंधन के साथ। + +शांत अवस्था का पता लगाने का उपयोग करता है: +1. URI के लिए ट्रिपल प्राप्त करें +2. यदि शून्य परिणाम हैं, तो पुनः प्रयास करें +3. यदि गैर-शून्य परिणाम हैं, तो प्रतीक्षा करें और फिर से प्राप्त करें +4. यदि समान परिणाम हैं, तो डेटा स्थिर है - पार्स करें और वापस करें +5. यदि अलग-अलग परिणाम हैं, तो डेटा अभी भी लिखा जा रहा है - पुनः प्रयास करें + +**तर्क:** + +`uri`: प्राप्त करने के लिए इकाई URI +`graph`: क्वेरी करने के लिए नामित ग्राफ (जैसे, "urn:graph:retrieval") +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता + +**वापसी:** ExplainEntity उपवर्ग या यदि नहीं मिला तो None + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +एक फोकस इकाई और उसके सभी किनारे चयन प्राप्त करें। + +**तर्क:** + +`uri`: फोकस इकाई URI +`graph`: क्वेरी करने के लिए नामित ग्राफ +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता + +**वापसी:** भरे हुए edge_selections के साथ Focus, या None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +एक प्रश्न URI से शुरू होकर संपूर्ण GraphRAG ट्रेस प्राप्त करें। + +उत्पत्ति श्रृंखला का पालन करें: प्रश्न -> ग्राउंडिंग -> अन्वेषण -> फोकस -> संश्लेषण + +**तर्क:** + +`question_uri`: प्रश्न इकाई URI +`graph`: नामित ग्राफ (डिफ़ॉल्ट: urn:graph:retrieval) +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`api`: लाइब्रेरियन एक्सेस के लिए ट्रस्टग्राफ एपीआई उदाहरण (वैकल्पिक) +`max_content`: संश्लेषण के लिए अधिकतम सामग्री लंबाई + +**वापसी:** प्रश्न, ग्राउंडिंग, अन्वेषण, फोकस, संश्लेषण संस्थाओं के साथ डिक्ट + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +एक संग्रह में सभी व्याख्यात्मकता सत्र (प्रश्न) सूचीबद्ध करें। + +**तर्क:** + +`graph`: नामित ग्राफ (डिफ़ॉल्ट: urn:graph:retrieval) +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता +`limit`: वापस करने के लिए सत्रों की अधिकतम संख्या + +**वापसी:** टाइमस्टैम्प द्वारा क्रमबद्ध प्रश्न संस्थाओं की सूची (नवीनतम पहले) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +एक किनारे ट्रिपल के सभी घटकों के लिए लेबल हल करें। + +**तर्क:** + +`edge`: "s", "p", "o" कुंजियों वाला डिक्ट +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता + +**वापसी:** (s_label, p_label, o_label) का टपल + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +कैशिंग के साथ एक URI के लिए rdfs:label हल करें। + +**तर्क:** + +`uri`: URI जिसके लिए लेबल प्राप्त करना है +`user`: उपयोगकर्ता/कीस्पेस पहचानकर्ता +`collection`: संग्रह पहचानकर्ता + +**वापसी:** यदि पाया जाता है तो लेबल, अन्यथा URI स्वयं + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +व्याख्यात्मक संस्थाओं के लिए आधार वर्ग। + +**फ़ील्ड:** + +`uri`: +`entity_type`: + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +प्रश्न इकाई - उपयोगकर्ता का वह प्रश्न जिसने सत्र शुरू किया। + +**फ़ील्ड:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +अन्वेषण इकाई - ज्ञान भंडार से प्राप्त किनारे/खंड। + +**फ़ील्ड:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +मुख्य इकाई - एलएलएम तर्क के साथ चयनित किनारे (केवल GraphRAG)। + +**फ़ील्ड:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +संश्लेषण इकाई - अंतिम उत्तर। + +**फ़ील्ड:** + +`uri`: +`entity_type`: +`document`: + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +विश्लेषण इकाई - एक विचार/कार्य/अवलोकन चक्र (केवल एजेंट)। + +**फ़ील्ड:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +निष्कर्ष इकाई - अंतिम उत्तर (केवल एजेंट)। + +**फ़ील्ड:** + +`uri`: +`entity_type`: +`document`: + +### विधियाँ + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +ग्राफआरएजी फोकस चरण से तर्क के साथ एक चयनित किनारा। + +**फ़ील्ड:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### विधियाँ + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +वायर-फॉर्मेट ट्रिपल को (s, p, o) टुपल्स में बदलें। + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +एक वायर-फॉर्मेट टर्म डिक्ट से मान निकालें। + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +आरडीएफ ट्रिपल जो एक ज्ञान ग्राफ कथन का प्रतिनिधित्व करता है। + +**फ़ील्ड:** + +`s`: +`p`: +`o`: + +### विधियाँ + +### `__init__(self, s: str, p: str, o: str) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +दिए गए ऑब्जेक्ट से एक नया स्ट्रिंग ऑब्जेक्ट बनाएं। यदि एन्कोडिंग या +त्रुटियां निर्दिष्ट हैं, तो ऑब्जेक्ट में एक डेटा बफर होना चाहिए +जिसे दिए गए एन्कोडिंग और त्रुटि हैंडलर का उपयोग करके डिकोड किया जाएगा। +अन्यथा, यह ऑब्जेक्ट.__str__() (यदि परिभाषित है) का परिणाम लौटाता है +या repr(object)। +एन्कोडिंग डिफ़ॉल्ट रूप से 'utf-8' है। +त्रुटियां डिफ़ॉल्ट रूप से 'strict' हैं। + +### विधियाँ + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +दिए गए ऑब्जेक्ट से एक नया स्ट्रिंग ऑब्जेक्ट बनाएं। यदि एन्कोडिंग या +त्रुटियां निर्दिष्ट हैं, तो ऑब्जेक्ट में एक डेटा बफर होना चाहिए +जिसे दिए गए एन्कोडिंग और त्रुटि हैंडलर का उपयोग करके डिकोड किया जाएगा। +अन्यथा, यह ऑब्जेक्ट.__str__() (यदि परिभाषित है) का परिणाम लौटाता है +या repr(object)। +एन्कोडिंग डिफ़ॉल्ट रूप से 'utf-8' है। +त्रुटियां डिफ़ॉल्ट रूप से 'strict' हैं। + +### विधियाँ + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +कॉन्फ़िगरेशन कुंजी पहचानकर्ता। + +**फ़ील्ड:** + +`type`: +`key`: + +### विधियाँ + +### `__init__(self, type: str, key: str) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +कॉन्फ़िगरेशन कुंजी-मान जोड़ी। + +**फ़ील्ड:** + +`type`: +`key`: +`value`: + +### विधियाँ + +### `__init__(self, type: str, key: str, value: str) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +पुस्तकालय में एक दस्तावेज़ के लिए मेटाडेटा। + +**विशेषताएं:** + +`parent_id: Parent document ID for child documents (empty for top`: स्तर (docs) + +**फ़ील्ड:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### विधियाँ + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +एक सक्रिय दस्तावेज़ प्रसंस्करण कार्य के लिए मेटाडेटा। + +**फ़ील्ड:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### विधियाँ + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +डेटा संग्रह के लिए मेटाडेटा। + +संग्रह दस्तावेज़ों और +ज्ञान ग्राफ डेटा के लिए तार्किक समूहीकरण और अलगाव प्रदान करते हैं। + +**विशेषताएं:** + +`name: Human`: पढ़ने योग्य संग्रह नाम + +**फ़ील्ड:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### विधियाँ + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +स्ट्रीमिंग प्रतिक्रिया खंडों के लिए आधार वर्ग। + +वेबसॉकेट-आधारित स्ट्रीमिंग कार्यों के लिए उपयोग किया जाता है, जहाँ प्रतिक्रियाएँ उत्पन्न होने पर क्रमिक रूप से भेजी जाती हैं। + + +**फ़ील्ड:** + +`content`: +`end_of_message`: + +### विधियाँ + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +एजेंट की तर्क/विचार प्रक्रिया का खंड। + +यह एजेंट के निष्पादन के दौरान आंतरिक तर्क या योजना चरणों का प्रतिनिधित्व करता है। +ये खंड दर्शाते हैं कि एजेंट समस्या के बारे में कैसे सोच रहा है। + +**फ़ील्ड:** + +`content`: +`end_of_message`: +`chunk_type`: + +### विधियाँ + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +एजेंट टूल निष्पादन अवलोकन खंड। + +यह किसी टूल या क्रिया को निष्पादित करने के परिणाम या अवलोकन को दर्शाता है। +ये खंड दिखाते हैं कि एजेंट ने टूल का उपयोग करके क्या सीखा। + +**फ़ील्ड:** + +`content`: +`end_of_message`: +`chunk_type`: + +### विधियाँ + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +एजेंट का अंतिम उत्तर खंड। + +यह एजेंट की अंतिम प्रतिक्रिया का प्रतिनिधित्व करता है जो उपयोगकर्ता के प्रश्न का उत्तर देने के लिए +अपनी तर्क क्षमता और टूल उपयोग को पूरा करने के बाद देता है। + +**विशेषताएं:** + +`chunk_type: Always "final`: उत्तर" + +**फ़ील्ड:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### विधियाँ + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +आरएजी (रीट्रिवल-ऑगमेंटेड जनरेशन) स्ट्रीमिंग चंक। + +ग्राफ आरएजी, दस्तावेज़ आरएजी, टेक्स्ट कंप्लीशन, +और अन्य जेनरेटिव सेवाओं से प्रतिक्रियाओं को स्ट्रीम करने के लिए उपयोग किया जाता है। + +**फ़ील्ड:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### मेथड + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +स्वयं को इनिशियलाइज़ करें। सटीक सिग्नेचर के लिए help(type(self)) देखें। + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +व्याख्यात्मकता के लिए उत्पत्ति घटना। + +जब व्याख्यात्मक मोड सक्षम होता है तो GraphRAG प्रश्नों के दौरान उत्सर्जित। +प्रत्येक घटना एक उत्पत्ति नोड का प्रतिनिधित्व करती है जो प्रश्न प्रसंस्करण के दौरान बनाई जाती है। + +**फ़ील्ड:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### विधियाँ + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +स्वयं को आरंभ करें। सटीक हस्ताक्षर के लिए help(type(self)) देखें। + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +जब वेबसॉकेट प्रोटोकॉल त्रुटियां होती हैं, तो यह त्रुटि उत्पन्न होती है। + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +सभी ट्रस्टग्राफ सेवा त्रुटियों के लिए आधार वर्ग। + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +एजेंट सेवा त्रुटि + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +कॉन्फ़िगरेशन सेवा त्रुटि + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +दस्तावेज़ पुनर्प्राप्ति त्रुटि। + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +प्रवाह प्रबंधन त्रुटि + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +एपीआई गेटवे त्रुटि + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +ग्राफ आरएजी पुनर्प्राप्ति त्रुटि + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +एलएलएम सेवा त्रुटि + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +डेटा लोड करने में त्रुटि + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +खोज/खोज त्रुटि + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +एनएलपी क्वेरी सेवा त्रुटि + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +पंक्तियों के क्वेरी सेवा त्रुटि + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +अनुरोध प्रसंस्करण त्रुटि + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +संरचित क्वेरी सेवा त्रुटि + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +अप्रत्याशित/अज्ञात त्रुटि + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +सभी ट्रस्टग्राफ सेवा त्रुटियों के लिए आधार वर्ग। + + +-- diff --git a/docs/python-api.md b/docs/python-api.md index 80773184..5b53f862 100644 --- a/docs/python-api.md +++ b/docs/python-api.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "TrustGraph Python API Reference" +nav_order: 5 +--- + # TrustGraph Python API Reference ## Installation @@ -3569,4 +3575,3 @@ Base class for all TrustGraph service errors --- - diff --git a/docs/python-api.pt.md b/docs/python-api.pt.md new file mode 100644 index 00000000..6d8956dd --- /dev/null +++ b/docs/python-api.pt.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "Referência da API Python do TrustGraph" +parent: "Portuguese (Beta)" +--- + +# Referência da API Python do TrustGraph + +> **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. + +## Instalação + +```bash +pip install trustgraph +``` + +## Início Rápido + +Todas as classes e tipos são importados do pacote `trustgraph.api`: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## Tabela de Conteúdo + +### Núcleo + +[Api](#api) + +### Clientes de Fluxo + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### Clientes WebSocket + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### Operações em Massa + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### Métricas + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### Tipos de Dados + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### Exceções + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +Cliente principal da API TrustGraph para operações síncronas e assíncronas. + +Esta classe fornece acesso a todos os serviços do TrustGraph, incluindo gerenciamento de fluxo, +operações de grafo de conhecimento, processamento de documentos, consultas RAG e muito mais. Ele suporta +tanto padrões de comunicação baseados em REST quanto baseados em WebSocket. + +O cliente pode ser usado como um gerenciador de contexto para limpeza automática de recursos: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### Métodos + +### `__aenter__(self)` + +Entre no gerenciador de contexto assíncrono. + +### `__aexit__(self, *args)` + +Saia do gerenciador de contexto assíncrono e feche as conexões. + +### `__enter__(self)` + +Entre no gerenciador de contexto síncrono. + +### `__exit__(self, *args)` + +Saia do gerenciador de contexto síncrono e feche as conexões. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +Inicialize o cliente da API TrustGraph. + +**Argumentos:** + +`url`: URL base para a API TrustGraph (padrão: "http://localhost:8088/"") +`timeout`: Tempo limite de solicitação em segundos (padrão: 60) +`token`: Token de autorização opcional para autenticação + +**Exemplo:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +Fechar todas as conexões de cliente assíncronas. + +Este método fecha as conexões assíncronas WebSocket, de operação em lote e de fluxo. +Ele é chamado automaticamente ao sair de um gerenciador de contexto assíncrono. + +**Exemplo:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +Obtenha um cliente para operações em lote assíncronas. + +Fornece operações de importação/exportação em lote com estilo async/await via WebSocket +para o tratamento eficiente de grandes conjuntos de dados. + +**Retorna:** AsyncBulkClient: Cliente para operações em lote assíncronas. + +**Exemplo:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +Obtenha um cliente de fluxo baseado em REST assíncrono. + +Fornece acesso com estilo async/await às operações de fluxo. Isso é preferível +para aplicativos e frameworks Python assíncronos (FastAPI, aiohttp, etc.). + +**Retorna:** AsyncFlow: Cliente de fluxo assíncrono + +**Exemplo:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +Obtenha um cliente de métricas assíncrono. + +Fornece acesso com estilo async/await às métricas do Prometheus. + +**Retorna:** AsyncMetrics: Cliente de métricas assíncrono + +**Exemplo:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +Obtenha um cliente WebSocket assíncrono para operações de streaming. + +Fornece acesso WebSocket no estilo async/await com suporte a streaming. +Este é o método preferido para streaming assíncrono em Python. + +**Retorna:** AsyncSocketClient: Cliente WebSocket assíncrono + +**Exemplo:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +Obtenha um cliente de operações em lote síncronas para importação/exportação. + +As operações em lote permitem a transferência eficiente de grandes conjuntos de dados via conexões WebSocket, +incluindo triplas, embeddings, contextos de entidades e objetos. + +**Retorna:** BulkClient: Cliente de operações em lote síncronas. + +**Exemplo:** + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +Fechar todas as conexões de cliente síncronas. + +Este método fecha as conexões WebSocket e de operações em lote. +Ele é chamado automaticamente quando sai de um gerenciador de contexto. + +**Exemplo:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +Obtenha um cliente de Coleção para gerenciar coleções de dados. + +As Coleções organizam documentos e dados de grafos de conhecimento em +agrupamentos lógicos para isolamento e controle de acesso. + +**Retorna:** Coleção: Cliente de gerenciamento de Coleção + +**Exemplo:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +Obtenha um cliente de Config para gerenciar as configurações. + +**Retorna:** Config: Cliente de gerenciamento de configuração + +**Exemplo:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +Obtenha um cliente Flow para gerenciar e interagir com fluxos. + +Os fluxos são as unidades de execução primárias no TrustGraph, fornecendo acesso a +serviços como agentes, consultas RAG, embeddings e processamento de documentos. + +**Retorna:** Flow: Cliente de gerenciamento de fluxos + +**Exemplo:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +Obtenha um cliente Knowledge para gerenciar os núcleos do grafo de conhecimento. + +**Retorna:** Knowledge: Cliente de gerenciamento de grafo de conhecimento + +**Exemplo:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +Obtenha um cliente da Biblioteca para gerenciamento de documentos. + +A biblioteca fornece armazenamento de documentos, gerenciamento de metadados e +coordenação do fluxo de trabalho de processamento. + +**Retorna:** Biblioteca: Cliente de gerenciamento de biblioteca de documentos + +**Exemplo:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +Obtém um cliente de métricas síncronas para monitoramento. + +Recupera métricas formatadas em Prometheus do serviço TrustGraph +para monitoramento e observabilidade. + +**Retorna:** Métricas: Cliente de métricas síncronas + +**Exemplo:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +Faça uma requisição de API REST de baixo nível. + +Este método é principalmente para uso interno, mas pode ser usado para acesso direto +à API quando necessário. + +**Argumentos:** + +`path`: Caminho do endpoint da API (relativo à URL base) +`request`: Payload da requisição como um dicionário + +**Retorna:** dict: Objeto de resposta + +**Levanta:** + +`ProtocolException`: Se o status da resposta não for 200 ou a resposta não for JSON +`ApplicationException`: Se a resposta contiver um erro + +**Exemplo:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +Obtenha um cliente WebSocket síncrono para operações de streaming. + +As conexões WebSocket fornecem suporte de streaming para respostas em tempo real +de agentes, consultas RAG e preenchimentos de texto. Este método retorna um +wrapper síncrono em torno do protocolo WebSocket. + +**Retorna:** SocketClient: Cliente WebSocket síncrono + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +Cliente de gerenciamento de fluxo para operações de blueprint e instância de fluxo. + +Esta classe fornece métodos para gerenciar blueprints de fluxo (modelos) e +instâncias de fluxo (fluxos em execução). Blueprints definem a estrutura e +os parâmetros dos fluxos, enquanto as instâncias representam fluxos ativos que podem +executar serviços. + +### Métodos + +### `__init__(self, api)` + +Inicializar o cliente de fluxo. + +**Argumentos:** + +`api`: Instância pai da API para fazer requisições + +### `delete_blueprint(self, blueprint_name)` + +Excluir um blueprint de fluxo. + +**Argumentos:** + +`blueprint_name`: Nome do blueprint a ser excluído + +**Exemplo:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +Obtenha a definição de uma instância de fluxo em execução. + +**Argumentos:** + +`id`: ID da instância de fluxo + +**Retorna:** dict: Definição da instância de fluxo + +**Exemplo:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +Obtenha uma definição de blueprint de fluxo por nome. + +**Argumentos:** + +`blueprint_name`: Nome do blueprint a ser recuperado + +**Retorna:** dict: Definição do blueprint como um dicionário + +**Exemplo:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +Obtenha uma instância de FlowInstance para executar operações em um fluxo específico. + +**Argumentos:** + +`id`: Identificador do fluxo (padrão: "default") + +**Retorna:** FlowInstance: Instância do fluxo para operações de serviço + +**Exemplo:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +Listar todas as instâncias de fluxo ativas. + +**Retorna:** list[str]: Lista de IDs de instâncias de fluxo + +**Exemplo:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +Listar todos os diagramas de fluxo disponíveis. + +**Retorna:** list[str]: Lista de nomes de diagramas. + +**Exemplo:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +Criar ou atualizar um modelo de fluxo. + +**Argumentos:** + +`blueprint_name`: Nome para o modelo +`definition`: Dicionário de definição do modelo + +**Exemplo:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +Faça uma solicitação de API com escopo de fluxo. + +**Argumentos:** + +`path`: Sufixo de caminho opcional para os endpoints de fluxo. +`request`: Dicionário de carga útil da solicitação. + +**Retorna:** dict: Objeto de resposta. + +**Levanta:** + +`RuntimeError`: Se o parâmetro da solicitação não for especificado. + +### `start(self, blueprint_name, id, description, parameters=None)` + +Inicie uma nova instância de fluxo a partir de um modelo. + +**Argumentos:** + +`blueprint_name`: Nome do modelo a ser instanciado. +`id`: Identificador exclusivo para a instância do fluxo. +`description`: Descrição legível por humanos. +`parameters`: Dicionário de parâmetros opcionais. + +**Exemplo:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +Interromper uma instância de fluxo em execução. + +**Argumentos:** + +`id`: ID da instância de fluxo a ser interrompida + +**Exemplo:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +Cliente de instância de fluxo para executar serviços em um fluxo específico. + +Esta classe fornece acesso a todos os serviços do TrustGraph, incluindo: +Preenchimento de texto e incorporações +Operações de agente com gerenciamento de estado +Consultas RAG de grafos e documentos +Operações de grafo de conhecimento (triplas, objetos) +Carregamento e processamento de documentos +Conversão de linguagem natural para consulta GraphQL +Análise de dados estruturados e detecção de esquema +Execução de ferramentas MCP +Modelagem de prompts + +Os serviços são acessados através de uma instância de fluxo em execução, identificada por um ID. + +### Métodos + +### `__init__(self, api, id)` + +Inicializa FlowInstance. + +**Argumentos:** + +`api`: Cliente Flow pai +`id`: Identificador da instância de fluxo + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +Executa uma operação de agente com capacidades de raciocínio e uso de ferramentas. + +Os agentes podem realizar raciocínio em várias etapas, usar ferramentas e manter o estado da conversa +em várias interações. Esta é uma versão síncrona não transmitida. + +**Argumentos:** + +`question`: Pergunta ou instrução do usuário +`user`: Identificador do usuário (padrão: "trustgraph") +`state`: Dicionário de estado opcional para conversas com estado +`group`: Identificador de grupo opcional para contextos multiusuário +`history`: Histórico de conversa opcional como uma lista de dicionários de mensagens + +**Retorna:** str: Resposta final do agente + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +Detectar o tipo de dado de uma amostra de dados estruturados. + +**Argumentos:** + +`sample`: Amostra de dados a ser analisada (conteúdo em string) + +**Retorna:** Dicionário com detected_type, confidence e metadados opcionais. + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +Realizar diagnóstico de dados combinado: detectar tipo e gerar descritor. + +**Argumentos:** + +`sample`: Amostra de dados a ser analisada (conteúdo em string) +`schema_name`: Nome de esquema de destino opcional para geração de descritor. +`options`: Parâmetros opcionais (por exemplo, delimitador para CSV). + +**Retorna:** Dicionário com detected_type, confidence, descriptor e metadados. + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +Consultar trechos de documentos usando similaridade semântica. + +Encontra trechos de documentos cujo conteúdo é semanticamente similar ao +texto de entrada, usando embeddings vetoriais. + +**Argumentos:** + +`text`: Texto de consulta para busca semântica. +`user`: Identificador de usuário/espaço de chaves. +`collection`: Identificador de coleção. +`limit`: Número máximo de resultados (padrão: 10). + +**Retorna:** Dicionário: Resultados da consulta com trechos contendo chunk_id e score. + +**Exemplo:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +Execute uma consulta de Geração Aumentada por Recuperação (RAG) baseada em documentos. + +O RAG baseado em documentos usa incorporações vetoriais para encontrar trechos de documentos relevantes, +e então gera uma resposta usando um LLM, utilizando esses trechos como contexto. + +**Argumentos:** + +`query`: Consulta em linguagem natural +`user`: Identificador de usuário/espaço de chaves (padrão: "trustgraph") +`collection`: Identificador de coleção (padrão: "default") +`doc_limit`: Número máximo de trechos de documentos a serem recuperados (padrão: 10) + +**Retorna:** str: Resposta gerada incorporando o contexto do documento + +**Exemplo:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +Gere incorporações vetoriais para um ou mais textos. + +Converte textos em representações vetoriais densas adequadas para busca semântica e +comparação de similaridade. + +**Argumentos:** + +`texts`: Lista de textos de entrada a serem incorporados + +**Retorna:** list[list[list[float]]]: Incorporações vetoriais, um conjunto por texto de entrada + +**Exemplo:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +Gerar um descritor para mapeamento de dados estruturados para um esquema específico. + +**Argumentos:** + +`sample`: Amostra de dados a ser analisada (conteúdo de string) +`data_type`: Tipo de dados (csv, json, xml) +`schema_name`: Nome do esquema de destino para a geração do descritor +`options`: Parâmetros opcionais (por exemplo, delimitador para CSV) + +**Retorna:** dicionário com o descritor e metadados + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +Consultar entidades de grafo de conhecimento usando similaridade semântica. + +Encontra entidades no grafo de conhecimento cujas descrições são semanticamente +similares ao texto de entrada, usando incorporações vetoriais. + +**Argumentos:** + +`text`: Texto de consulta para pesquisa semântica +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`limit`: Número máximo de resultados (padrão: 10) + +**Retorna:** dicionário: Resultados da consulta com entidades similares + +**Exemplo:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +Execute consulta de Geração Aumentada por Recuperação (RAG) baseada em grafo. + +O Graph RAG utiliza a estrutura do grafo de conhecimento para encontrar o contexto relevante, +percorrendo as relações entre entidades, e então gera uma resposta usando um LLM. + +**Argumentos:** + +`query`: Consulta em linguagem natural +`user`: Identificador de usuário/espaço de chaves (padrão: "trustgraph") +`collection`: Identificador de coleção (padrão: "default") +`entity_limit`: Número máximo de entidades a recuperar (padrão: 50) +`triple_limit`: Número máximo de triplas por entidade (padrão: 30) +`max_subgraph_size`: Número máximo total de triplas no subgrafo (padrão: 150) +`max_path_length`: Profundidade máxima de travessia (padrão: 2) + +**Retorna:** str: Resposta gerada incorporando o contexto do grafo + +**Exemplo:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +Carregar um documento binário para processamento. + +Envia um documento (PDF, DOCX, imagens, etc.) para extração e +processamento através do pipeline de documentos do fluxo. + +**Argumentos:** + +`document`: Conteúdo do documento como bytes +`id`: Identificador de documento opcional (gerado automaticamente se for None) +`metadata`: Metadados opcionais (lista de Triplas ou objeto com método emit) +`user`: Identificador de usuário/espaço de chaves (opcional) +`collection`: Identificador de coleção (opcional) + +**Retorna:** dict: Resposta de processamento + +**Levanta:** + +`RuntimeError`: Se metadados forem fornecidos sem id + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +Carrega o conteúdo de texto para processamento. + +Carrega o conteúdo de texto para extração e processamento através do pipeline de texto do fluxo. + + +**Argumentos:** + +`text`: Conteúdo de texto como bytes +`id`: Identificador de documento opcional (gerado automaticamente se for None) +`metadata`: Metadados opcionais (lista de Triplas ou objeto com método emit) +`charset`: Codificação de caracteres (padrão: "utf-8") +`user`: Identificador de usuário/espaço de chaves (opcional) +`collection`: Identificador de coleção (opcional) + +**Retorna:** dict: Resposta de processamento + +**Levanta:** + +`RuntimeError`: Se metadados forem fornecidos sem id + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +Execute uma ferramenta de Protocolo de Contexto de Modelo (MCP). + +As ferramentas MCP fornecem funcionalidade extensível para agentes e fluxos de trabalho, +permitindo a integração com sistemas e serviços externos. + +**Argumentos:** + +`name`: Nome/identificador da ferramenta +`parameters`: Dicionário de parâmetros da ferramenta (padrão: {}) + +**Retorna:** str ou dict: Resultado da execução da ferramenta + +**Levanta:** + +`ProtocolException`: Se o formato da resposta for inválido + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +Converter uma pergunta em linguagem natural em uma consulta GraphQL. + +**Argumentos:** + +`question`: Pergunta em linguagem natural +`max_results`: Número máximo de resultados a retornar (padrão: 100) + +**Retorna:** dicionário com graphql_query, variáveis, schemas detectados, confiança + +### `prompt(self, id, variables)` + +Executar um modelo de prompt com substituição de variáveis. + +Modelos de prompt permitem padrões de prompt reutilizáveis com variáveis dinâmicas. +de substituição, úteis para engenharia de prompt consistente. + +**Argumentos:** + +`id`: Identificador do modelo de prompt. +`variables`: Dicionário de mapeamentos de nomes de variáveis para valores. + +**Retorna:** str ou dict: Resultado do prompt renderizado (texto ou objeto estruturado). + +**Levanta:** + +`ProtocolException`: Se o formato da resposta for inválido. + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +Faça uma solicitação de serviço nesta instância de fluxo. + +**Argumentos:** + +`path`: Caminho do serviço (por exemplo, "service/text-completion") +`request`: Dicionário de carga útil da solicitação + +**Retorna:** dict: Resposta do serviço + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +Consulta dados de linha usando similaridade semântica em campos indexados. + +Encontra linhas cujos valores de campos indexados são semanticamente semelhantes ao +texto de entrada, usando incorporações vetoriais. Isso permite a correspondência aproximada/semântica +em dados estruturados. + +**Argumentos:** + +`text`: Texto de consulta para pesquisa semântica +`schema_name`: Nome do esquema para pesquisar +`user`: Identificador de usuário/espaço de chaves (padrão: "trustgraph") +`collection`: Identificador de coleção (padrão: "default") +`index_name`: Nome de índice opcional para filtrar a pesquisa para um índice específico +`limit`: Número máximo de resultados (padrão: 10) + +**Retorna:** dict: Resultados da consulta com correspondências contendo index_name, index_value, text e score + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +Execute uma consulta GraphQL contra linhas estruturadas no grafo de conhecimento. + +Consulta dados estruturados usando a sintaxe GraphQL, permitindo consultas complexas +com filtragem, agregação e travessia de relacionamentos. + +**Argumentos:** + +`query`: String de consulta GraphQL +`user`: Identificador de usuário/espaço de chaves (padrão: "trustgraph") +`collection`: Identificador de coleção (padrão: "default") +`variables`: Dicionário opcional de variáveis de consulta +`operation_name`: Nome de operação opcional para documentos com várias operações + +**Retorna:** dict: Resposta GraphQL com os campos 'data', 'errors' e/ou 'extensions' + +**Levanta:** + +`ProtocolException`: Se ocorrer um erro de nível do sistema + +**Exemplo:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +Selecione os esquemas correspondentes para uma amostra de dados usando análise de prompt. + +**Argumentos:** + +`sample`: Amostra de dados a ser analisada (conteúdo de string) +`options`: Parâmetros opcionais + +**Retorna:** dicionário com array schema_matches e metadados + +### `structured_query(self, question, user='trustgraph', collection='default')` + +Execute uma pergunta em linguagem natural contra dados estruturados. +Combina a conversão de consulta NLP e a execução GraphQL. + +**Argumentos:** + +`question`: Pergunta em linguagem natural +`user`: Identificador de keyspace do Cassandra (padrão: "trustgraph") +`collection`: Identificador da coleção de dados (padrão: "default") + +**Retorna:** dicionário com dados e erros opcionais + +### `text_completion(self, system, prompt)` + +Execute a conclusão de texto usando o LLM do fluxo. + +**Argumentos:** + +`system`: Prompt do sistema que define o comportamento do assistente +`prompt`: Prompt/pergunta do usuário + +**Retorna:** str: Texto de resposta gerado + +**Exemplo:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +Consultar triplas de grafos de conhecimento usando correspondência de padrões. + +Procura triplas RDF que correspondam aos padrões de sujeito, predicado e/ou +objeto fornecidos. Parâmetros não especificados atuam como curingas. + +**Argumentos:** + +`s`: URI do sujeito (opcional, use None para curinga) +`p`: URI do predicado (opcional, use None para curinga) +`o`: URI do objeto ou Literal (opcional, use None para curinga) +`user`: Identificador de usuário/espaço de chaves (opcional) +`collection`: Identificador de coleção (opcional) +`limit`: Número máximo de resultados a retornar (padrão: 10000) + +**Retorna:** list[Triple]: Lista de objetos Triple correspondentes + +**Levanta:** + +`RuntimeError`: Se s ou p não forem um Uri, ou o não for um Uri/Literal + +**Exemplo:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +Cliente de gerenciamento de fluxo assíncrono usando a API REST. + +Fornece operações de gerenciamento de fluxo baseadas em async/await, incluindo listagem, +início, parada de fluxos e gerenciamento de definições de classes de fluxo. Também fornece +acesso a serviços de escopo de fluxo, como agentes, RAG e consultas, por meio de +endpoints REST não baseados em streaming. + +Nota: Para suporte a streaming, use AsyncSocketClient em vez disso. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializa o cliente de fluxo assíncrono. + +**Argumentos:** + +`url`: URL base para a API TrustGraph +`timeout`: Tempo limite de solicitação em segundos +`token`: Token de autorização opcional para autenticação + +### `aclose(self) -> None` + +Fecha o cliente assíncrono e libera recursos. + +Nota: A limpeza é tratada automaticamente pelos gerenciadores de contexto de sessão aiohttp. +Este método é fornecido para consistência com outros clientes assíncronos. + +### `delete_class(self, class_name: str)` + +Exclui uma definição de classe de fluxo. + +Remove um modelo de classe de fluxo do sistema. Não afeta +instâncias de fluxo em execução. + +**Argumentos:** + +`class_name`: Nome da classe de fluxo a ser excluída + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +Obter a definição do fluxo. + +Recupera a configuração completa do fluxo, incluindo seu nome de classe, +descrição e parâmetros. + +**Argumentos:** + +`id`: Identificador do fluxo + +**Retorna:** dict: Objeto de definição do fluxo + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +Obter a definição da classe de fluxo. + +Recupera a definição do blueprint para uma classe de fluxo, incluindo seu +esquema de configuração e associações de serviço. + +**Argumentos:** + +`class_name`: Nome da classe de fluxo + +**Retorna:** dict: Objeto de definição da classe de fluxo + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +Obtenha uma instância de cliente de fluxo assíncrono. + +Retorna um cliente para interagir com os serviços de um fluxo específico +(agente, RAG, consultas, embeddings, etc.). + +**Argumentos:** + +`flow_id`: Identificador do fluxo + +**Retorna:** AsyncFlowInstance: Cliente para operações específicas do fluxo + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +Liste todos os identificadores de fluxo. + +Recupera os IDs de todos os fluxos atualmente implementados no sistema. + +**Retorna:** list[str]: Lista de identificadores de fluxo + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +Listar todos os nomes das classes de fluxo. + +Recupera os nomes de todas as classes de fluxo (modelos) disponíveis no sistema. + +**Retorna:** list[str]: Lista de nomes das classes de fluxo. + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +Criar ou atualizar uma definição de classe de fluxo. + +Armazena um modelo de classe de fluxo que pode ser usado para instanciar fluxos. + +**Argumentos:** + +`class_name`: Nome da classe de fluxo +`definition`: Objeto de definição da classe de fluxo + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Faça uma requisição HTTP POST assíncrona para a API Gateway. + +Método interno para fazer requisições autenticadas para a API TrustGraph. + +**Argumentos:** + +`path`: Caminho do endpoint da API (relativo à URL base) +`request_data`: Dicionário de carga útil da requisição + +**Retorna:** dict: Objeto de resposta da API + +**Levanta:** + +`ProtocolException`: Se o status HTTP não for 200 ou a resposta não for um JSON válido +`ApplicationException`: Se a API retornar uma resposta de erro + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +Inicia uma nova instância de fluxo. + +Cria e inicia um fluxo a partir de uma definição de classe de fluxo com os +parâmetros especificados. + +**Argumentos:** + +`class_name`: Nome da classe de fluxo a ser instanciada +`id`: Identificador para a nova instância de fluxo +`description`: Descrição legível por humanos do fluxo +`parameters`: Parâmetros de configuração opcionais para o fluxo + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +Interromper um fluxo em execução. + +Interrompe e remove uma instância de fluxo, liberando seus recursos. + +**Argumentos:** + +`id`: Identificador do fluxo a ser interrompido + +**Exemplo:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +Cliente de instância de fluxo assíncrono. + +Fornece acesso async/await a serviços com escopo de fluxo, incluindo agentes, +Consultas RAG, embeddings e consultas de grafo. Todas as operações retornam respostas completas (não em streaming). + + +Nota: Para suporte a streaming, use AsyncSocketFlowInstance. + +### Métodos + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +Inicializa a instância de fluxo assíncrono. + +**Argumentos:** + +`flow`: Cliente AsyncFlow pai +`flow_id`: Identificador do fluxo + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +Execute uma operação de agente (não em streaming). + +Executa um agente para responder a uma pergunta, com estado de conversa opcional e +histórico. Retorna a resposta completa após o agente ter terminado de +processar. + +Nota: Este método não suporta streaming. Para pensamentos e observações do agente em tempo real, use AsyncSocketFlowInstance.agent() em vez disso. + + +**Argumentos:** + +`question`: Pergunta ou instrução do usuário +`user`: Identificador do usuário +`state`: Dicionário de estado opcional para o contexto da conversa +`group`: Identificador de grupo opcional para o gerenciamento de sessões +`history`: Lista de histórico de conversa opcional +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** dict: Resposta completa do agente, incluindo a resposta e metadados + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +Execute consulta RAG baseada em documentos (não em streaming). + +Realiza a Geração Aumentada por Recuperação usando incorporações de documentos. +Recupera trechos de documentos relevantes por meio de busca semântica e, em seguida, gera +uma resposta fundamentada nos documentos recuperados. Retorna a resposta completa. + +Nota: Este método não suporta streaming. Para respostas RAG em streaming, +use AsyncSocketFlowInstance.document_rag() em vez disso. + +**Argumentos:** + +`query`: Texto da consulta do usuário +`user`: Identificador do usuário +`collection`: Identificador da coleção contendo os documentos +`doc_limit`: Número máximo de trechos de documentos a serem recuperados (padrão: 10) +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** str: Resposta completa gerada com base nos dados do documento + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +Gere incorporações para textos de entrada. + +Converte textos em representações vetoriais numéricas usando o modelo de incorporação configurado do fluxo. Útil para pesquisa semântica e comparações de similaridade. + + + +**Argumentos:** + +`texts`: Lista de textos de entrada a serem incorporados +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** dict: Resposta contendo vetores de incorporação + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +Consulta incorporações de grafos para busca semântica de entidades. + +Realiza uma busca semântica sobre as incorporações de entidades do grafo para encontrar entidades +mais relevantes para o texto de entrada. Retorna entidades classificadas por similaridade. + +**Argumentos:** + +`text`: Texto de consulta para a busca semântica +`user`: Identificador do usuário +`collection`: Identificador da coleção contendo as incorporações do grafo +`limit`: Número máximo de resultados a serem retornados (padrão: 10) +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** dict: Resposta contendo correspondências de entidades classificadas com pontuações de similaridade + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +Execute consulta RAG baseada em grafo (não em streaming). + +Realiza a geração aumentada por recuperação usando dados de grafo de conhecimento. +Identifica entidades relevantes e seus relacionamentos, e então gera uma +resposta fundamentada na estrutura do grafo. Retorna a resposta completa. + +Nota: Este método não suporta streaming. Para respostas RAG em streaming, +use AsyncSocketFlowInstance.graph_rag() em vez disso. + +**Argumentos:** + +`query`: Texto da consulta do usuário +`user`: Identificador do usuário +`collection`: Identificador da coleção contendo o grafo de conhecimento +`max_subgraph_size`: Número máximo de triplas por subgrafo (padrão: 1000) +`max_subgraph_count`: Número máximo de subgrafos a serem recuperados (padrão: 5) +`max_entity_distance`: Distância máxima do grafo para expansão de entidades (padrão: 3) +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** str: Resposta completa gerada com base nos dados do grafo + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Faça uma requisição para um serviço com escopo de fluxo. + +Método interno para chamar serviços dentro desta instância de fluxo. + +**Argumentos:** + +`service`: Nome do serviço (por exemplo, "agent", "graph-rag", "triples") +`request_data`: Payload da requisição do serviço + +**Retorna:** dict: Objeto de resposta do serviço + +**Lança:** + +`ProtocolException`: Se a requisição falhar ou a resposta for inválida +`ApplicationException`: Se o serviço retornar um erro + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +Consulta as incorporações de linhas para pesquisa semântica em dados estruturados. + +Realiza uma pesquisa semântica sobre as incorporações do índice de linhas para encontrar linhas cujos +valores de campo indexados são mais semelhantes ao texto de entrada. Permite +correspondência fuzzy/semântica em dados estruturados. + +**Argumentos:** + +`text`: Texto da consulta para pesquisa semântica +`schema_name`: Nome do esquema para pesquisar +`user`: Identificador do usuário (padrão: "trustgraph") +`collection`: Identificador da coleção (padrão: "default") +`index_name`: Nome de índice opcional para filtrar a pesquisa para um índice específico +`limit`: Número máximo de resultados a serem retornados (padrão: 10) +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** dict: Resposta contendo correspondências com index_name, index_value, text e score + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +Execute uma consulta GraphQL em linhas armazenadas. + +Consulta linhas de dados estruturados usando a sintaxe GraphQL. Suporta consultas complexas +com variáveis e operações nomeadas. + +**Argumentos:** + +`query`: String da consulta GraphQL +`user`: Identificador do usuário +`collection`: Identificador da coleção contendo as linhas +`variables`: Variáveis de consulta GraphQL opcionais +`operation_name`: Nome da operação opcional para consultas com múltiplas operações +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** dict: Resposta GraphQL com dados e/ou erros + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +Gerar conclusão de texto (não em fluxo). + +Gera uma resposta de texto a partir de um LLM, dado um prompt do sistema e um prompt do usuário. +Retorna o texto da resposta completo. + +Nota: Este método não suporta streaming. Para geração de texto em fluxo, +use AsyncSocketFlowInstance.text_completion() em vez disso. + +**Argumentos:** + +`system`: Prompt do sistema que define o comportamento do LLM. +`prompt`: Prompt ou pergunta do usuário. +`**kwargs`: Parâmetros adicionais específicos do serviço. + +**Retorna:** str: Resposta de texto gerada completa. + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +Consulta triplas RDF usando correspondência de padrões. + +Procura triplas que correspondam aos padrões especificados de sujeito, predicado e/ou +objeto. Os padrões usam "None" como um caractere curinga para corresponder a qualquer valor. + +**Argumentos:** + +`s`: Padrão do sujeito (None para caractere curinga) +`p`: Padrão do predicado (None para caractere curinga) +`o`: Padrão do objeto (None para caractere curinga) +`user`: Identificador do usuário (None para todos os usuários) +`collection`: Identificador da coleção (None para todas as coleções) +`limit`: Número máximo de triplas a retornar (padrão: 100) +`**kwargs`: Parâmetros adicionais específicos do serviço + +**Retorna:** dict: Resposta contendo as triplas correspondentes + +**Exemplo:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +Cliente WebSocket síncrono para operações de streaming. + +Fornece uma interface síncrona para serviços TrustGraph baseados em WebSocket, +envolvendo a biblioteca de WebSockets assíncrona com geradores síncronos para facilitar o uso. +Suporta respostas de streaming de agentes, consultas RAG e preenchimentos de texto. + +Nota: Este é um wrapper síncrono em torno de operações de WebSocket assíncronas. Para +suporte assíncrono real, use AsyncSocketClient em vez disso. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializa o cliente WebSocket síncrono. + +**Argumentos:** + +`url`: URL base para a API TrustGraph (HTTP/HTTPS serão convertidos para WS/WSS) +`timeout`: Tempo limite do WebSocket em segundos +`token`: Token de autorização opcional para autenticação + +### `close(self) -> None` + +Fecha as conexões WebSocket. + +Nota: A limpeza é tratada automaticamente pelos gerenciadores de contexto em código assíncrono. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +Obtém uma instância de fluxo para operações de streaming de WebSocket. + +**Argumentos:** + +`flow_id`: Identificador do fluxo + +**Retorna:** SocketFlowInstance: Instância de fluxo com métodos de streaming + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +Fluxo de WebSocket síncrono para operações de streaming. + +Fornece a mesma interface que o FlowInstance REST, mas com suporte a streaming baseado em WebSocket +para respostas em tempo real. Todos os métodos suportam um parâmetro opcional +`streaming` para habilitar a entrega incremental de resultados. + +### Métodos + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +Inicializa a instância do fluxo de socket. + +**Argumentos:** + +`client`: SocketClient pai +`flow_id`: Identificador do fluxo + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +Executa uma operação de agente com suporte a streaming. + +Os agentes podem realizar raciocínios de várias etapas com o uso de ferramentas. Este método sempre +retorna fragmentos de streaming (pensamentos, observações, respostas), mesmo quando +streaming=False, para mostrar o processo de raciocínio do agente. + +**Argumentos:** + +`question`: Pergunta ou instrução do usuário +`user`: Identificador do usuário +`state`: Dicionário de estado opcional para conversas com estado +`group`: Identificador de grupo opcional para contextos multiusuário +`history`: Histórico de conversas opcional como uma lista de dicionários de mensagens +`streaming`: Habilita o modo de streaming (padrão: Falso) +`**kwargs`: Parâmetros adicionais passados para o serviço do agente + +**Retorna:** Iterator[StreamingChunk]: Fluxo de pensamentos, observações e respostas do agente + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +Execute uma operação de agente com suporte para explicabilidade. + +Transmite tanto os fragmentos de conteúdo (AgentThought, AgentObservation, AgentAnswer) +quanto os eventos de rastreabilidade (ProvenanceEvent). Os eventos de rastreabilidade contêm URIs +que podem ser acessados usando o ExplainabilityClient para obter informações detalhadas +sobre o processo de raciocínio do agente. + +O rastreamento do agente consiste em: +Sessão: A pergunta inicial e os metadados da sessão +Iterações: Cada ciclo de pensamento/ação/observação +Conclusão: A resposta final + +**Argumentos:** + +`question`: Pergunta ou instrução do usuário +`user`: Identificador do usuário +`collection`: Identificador de coleção para armazenamento de rastreabilidade +`state`: Dicionário de estado opcional para conversas com estado +`group`: Identificador de grupo opcional para contextos multiusuário +`history`: Histórico de conversas opcional como uma lista de dicionários de mensagens +`**kwargs`: Parâmetros adicionais passados para o serviço do agente +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: Fragmentos do agente e eventos de rastreabilidade + +**Exemplo:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Consultar trechos de documentos usando similaridade semântica. + +**Argumentos:** + +`text`: Texto da consulta para busca semântica +`user`: Identificador do usuário/espaço de chaves +`collection`: Identificador da coleção +`limit`: Número máximo de resultados (padrão: 10) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** dict: Resultados da consulta com os IDs dos trechos dos documentos correspondentes + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Execute uma consulta RAG baseada em documentos com streaming opcional. + +Utiliza incorporações vetoriais para encontrar trechos de documentos relevantes e, em seguida, gera +uma resposta usando um LLM. O modo de streaming entrega resultados incrementalmente. + +**Argumentos:** + +`query`: Consulta em linguagem natural +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`doc_limit`: Número máximo de trechos de documentos a serem recuperados (padrão: 10) +`streaming`: Habilitar o modo de streaming (padrão: Falso) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** Union[str, Iterator[str]]: Resposta completa ou fluxo de trechos de texto + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Execute uma consulta RAG baseada em documentos com suporte para explicabilidade. + +Transmite tanto os fragmentos de conteúdo (RAGChunk) quanto os eventos de rastreabilidade (ProvenanceEvent). +Os eventos de rastreabilidade contêm URIs que podem ser recuperados usando o ExplainabilityClient +para obter informações detalhadas sobre como a resposta foi gerada. + +O rastreamento RAG do documento consiste em: +Pergunta: A consulta do usuário +Exploração: Fragmentos recuperados do armazenamento de documentos (chunk_count) +Síntese: A resposta gerada + +**Argumentos:** + +`query`: Consulta em linguagem natural +`user`: Identificador do usuário/espaço de chaves +`collection`: Identificador da coleção +`doc_limit`: Número máximo de fragmentos de documento a serem recuperados (padrão: 10) +`**kwargs`: Parâmetros adicionais passados para o serviço +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Fragmentos de conteúdo e eventos de rastreabilidade + +**Exemplo:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +Gerar incorporações vetoriais para um ou mais textos. + +**Argumentos:** + +`texts`: Lista de textos de entrada a serem incorporados +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** dict: Resposta contendo vetores (um conjunto por texto de entrada) + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Consultar entidades de grafo de conhecimento usando similaridade semântica. + +**Argumentos:** + +`text`: Texto da consulta para busca semântica +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`limit`: Número máximo de resultados (padrão: 10) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** dict: Resultados da consulta com entidades similares + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Execute consulta RAG baseada em grafo com streaming opcional. + +Utiliza a estrutura do grafo de conhecimento para encontrar o contexto relevante e, em seguida, gera +uma resposta usando um LLM. O modo de streaming entrega os resultados incrementalmente. + +**Argumentos:** + +`query`: Consulta em linguagem natural +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`max_subgraph_size`: Número máximo total de triplas no subgrafo (padrão: 1000) +`max_subgraph_count`: Número máximo de subgrafos (padrão: 5) +`max_entity_distance`: Profundidade máxima de travessia (padrão: 3) +`streaming`: Habilitar o modo de streaming (padrão: Falso) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** Union[str, Iterator[str]]: Resposta completa ou fluxo de fragmentos de texto + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Execute consulta RAG baseada em grafo com suporte para explicabilidade. + +Transmite tanto os fragmentos de conteúdo (RAGChunk) quanto os eventos de rastreabilidade (ProvenanceEvent). +Os eventos de rastreabilidade contêm URIs que podem ser recuperados usando ExplainabilityClient +para obter informações detalhadas sobre como a resposta foi gerada. + +**Argumentos:** + +`query`: Consulta em linguagem natural +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`max_subgraph_size`: Número máximo total de triplas no subgrafo (padrão: 1000) +`max_subgraph_count`: Número máximo de subgrafos (padrão: 5) +`max_entity_distance`: Profundidade máxima de travessia (padrão: 3) +`**kwargs`: Parâmetros adicionais passados para o serviço +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Fragmentos de conteúdo e eventos de rastreabilidade + +**Exemplo:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +Execute uma ferramenta de Protocolo de Contexto de Modelo (MCP). + +**Argumentos:** + +`name`: Nome/identificador da ferramenta +`parameters`: Dicionário de parâmetros da ferramenta +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** dict: Resultado da execução da ferramenta + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Execute um modelo de prompt com streaming opcional. + +**Argumentos:** + +`id`: Identificador do modelo de prompt +`variables`: Dicionário de mapeamentos de nome de variável para valor +`streaming`: Habilitar o modo de streaming (padrão: Falso) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** Union[str, Iterator[str]]: Resposta completa ou fluxo de fragmentos de texto + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Consulta dados de linhas usando similaridade semântica em campos indexados. + +Encontra linhas cujos valores de campos indexados são semanticamente similares ao +texto de entrada, usando embeddings vetoriais. Isso permite correspondência aproximada/semântica +em dados estruturados. + +**Argumentos:** + +`text`: Texto de consulta para busca semântica +`schema_name`: Nome do esquema para pesquisar +`user`: Identificador de usuário/espaço de chaves (padrão: "trustgraph") +`collection`: Identificador de coleção (padrão: "default") +`index_name`: Nome de índice opcional para filtrar a pesquisa para um índice específico +`limit`: Número máximo de resultados (padrão: 10) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** dict: Resultados da consulta com correspondências contendo index_name, index_value, text e score + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +Execute uma consulta GraphQL contra linhas estruturadas. + +**Argumentos:** + +`query`: String de consulta GraphQL +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`variables`: Dicionário opcional de variáveis de consulta +`operation_name`: Nome de operação opcional para documentos de múltiplas operações +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** dict: Resposta GraphQL com dados, erros e/ou extensões + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +Execute a conclusão de texto com streaming opcional. + +**Argumentos:** + +`system`: Prompt do sistema que define o comportamento do assistente. +`prompt`: Prompt/pergunta do usuário. +`streaming`: Habilita o modo de streaming (padrão: Falso). +`**kwargs`: Parâmetros adicionais passados para o serviço. + +**Retorna:** Union[str, Iterator[str]]: Resposta completa ou fluxo de fragmentos de texto. + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +Consultar triplas de grafos de conhecimento usando correspondência de padrões. + +**Argumentos:** + +`s`: Filtro do sujeito - String URI, dicionário de termos ou None para curinga +`p`: Filtro do predicado - String URI, dicionário de termos ou None para curinga +`o`: Filtro do objeto - String URI/literal, dicionário de termos ou None para curinga +`g`: Filtro do grafo nomeado - String URI ou None para todos os grafos +`user`: Identificador de usuário/espaço de chaves (opcional) +`collection`: Identificador de coleção (opcional) +`limit`: Número máximo de resultados a retornar (padrão: 100) +`**kwargs`: Parâmetros adicionais passados para o serviço + +**Retorna:** List[Dict]: Lista de triplas correspondentes no formato de fio + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +Consultar triplas de um grafo de conhecimento com lotes de streaming. + +Produz lotes de triplas à medida que chegam, reduzindo o tempo para o primeiro resultado +e a sobrecarga de memória para conjuntos de resultados grandes. + +**Argumentos:** + +`s`: Filtro de sujeito - String URI, dicionário de termos ou None para curinga +`p`: Filtro de predicado - String URI, dicionário de termos ou None para curinga +`o`: Filtro de objeto - String URI/literal, dicionário de termos ou None para curinga +`g`: Filtro de grafo nomeado - String URI ou None para todos os grafos +`user`: Identificador de usuário/espaço de chaves (opcional) +`collection`: Identificador de coleção (opcional) +`limit`: Número máximo de resultados a retornar (padrão: 100) +`batch_size`: Triplas por lote (padrão: 20) +`**kwargs`: Parâmetros adicionais passados para o serviço +`Yields`: +`List[Dict]`: Lotes de triplas em formato de fio + +**Exemplo:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +Cliente WebSocket assíncrono + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None)` + +Inicialize self. Consulte help(type(self)) para a assinatura correta. + +### `aclose(self)` + +Fechar conexão WebSocket + +### `flow(self, flow_id: str)` + +Obter instância de fluxo assíncrono para operações WebSocket + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +Fluxo assíncrono de WebSocket. + +### Métodos + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +Inicializa self. Consulte help(type(self)) para obter a assinatura correta. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +Agente com streaming opcional. + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +Documento RAG com streaming opcional. + +### `embeddings(self, texts: list, **kwargs)` + +Gera incorporações de texto. + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +Consulta incorporações de grafo para pesquisa semântica. + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +RAG de grafo com streaming opcional. + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +Executa a ferramenta MCP. + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +Executa o prompt com streaming opcional. + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +Consulta incorporações de linha para pesquisa semântica em dados estruturados. + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +Consulta GraphQL contra linhas estruturadas. + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +Conclusão de texto com streaming opcional. + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +Consulta de padrão triplo. + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +Cria um dicionário Term no formato de fio a partir de um valor. + +Regras de detecção automática (quando term_type é None): + Já é um dicionário com a chave 't' -> retorna como está (já é um Term) + Começa com http://, https://, urn: -> IRI + Envolvido em <> (por exemplo, ) -> IRI (colchetes angulares removidos) + Qualquer outra coisa -> literal + +**Argumentos:** + +`value`: O valor do termo (string, dicionário ou None) +`term_type`: Um dos valores 'iri', 'literal' ou None para detecção automática +`datatype`: Tipo de dados para objetos literais (por exemplo, xsd:integer) +`language`: Etiqueta de idioma para objetos literais (por exemplo, en) + +**Retorna:** dict: Dicionário Term no formato de fio, ou None se o valor for None + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +Cliente para operações em lote síncronas para importação/exportação. + +Fornece transferência eficiente de dados em lote via WebSocket para grandes conjuntos de dados. +Envolve operações assíncronas do WebSocket com geradores síncronos para facilitar o uso. + +Nota: Para suporte assíncrono real, use AsyncBulkClient em vez disso. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicializa o cliente de lote síncrono. + +**Argumentos:** + +`url`: URL base para a API TrustGraph (HTTP/HTTPS serão convertidos para WS/WSS) +`timeout`: Tempo limite do WebSocket em segundos +`token`: Token de autorização opcional para autenticação + +### `close(self) -> None` + +Fecha as conexões + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Exporta em lote os embeddings de documentos de um fluxo. + +Baixa eficientemente todos os embeddings de fragmentos de documentos via streaming WebSocket. + +**Argumentos:** + +`flow`: Identificador do fluxo +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Retorna:** Iterator[Dict[str, Any]]: Fluxo de dicionários de embedding + +**Exemplo:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Exportação em massa de contextos de entidades de um fluxo. + +Faz o download de todas as informações do contexto da entidade de forma eficiente via streaming WebSocket. + +**Argumentos:** + +`flow`: Identificador do fluxo +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Retorna:** Iterator[Dict[str, Any]]: Fluxo de dicionários de contexto + +**Exemplo:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Exportação em massa de representações gráficas (embeddings) de um fluxo. + +Faz o download de todas as representações gráficas de entidades de forma eficiente via streaming WebSocket. + +**Argumentos:** + +`flow`: Identificador do fluxo +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Retorna:** Iterator[Dict[str, Any]]: Fluxo de dicionários de representações. + +**Exemplo:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +Exportação em massa de triplas RDF de um fluxo. + +Faz o download de todas as triplas de forma eficiente via streaming WebSocket. + +**Argumentos:** + +`flow`: Identificador do fluxo +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Retorna:** Iterator[Triple]: Fluxo de objetos Triple + +**Exemplo:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em massa de embeddings de documentos em um fluxo. + +Carrega eficientemente embeddings de fragmentos de documentos via streaming WebSocket +para uso em consultas RAG de documentos. + +**Argumentos:** + +`flow`: Identificador do fluxo +`embeddings`: Iterador que retorna dicionários de embedding +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Exemplo:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Importação em massa de contextos de entidades em um fluxo. + +Carrega eficientemente informações de contexto de entidade por meio de streaming WebSocket. +Os contextos de entidade fornecem contexto textual adicional sobre as entidades do grafo +para melhorar o desempenho do RAG. + +**Argumentos:** + +`flow`: Identificador do fluxo +`contexts`: Iterador que retorna dicionários de contexto +`metadata`: Dicionário de metadados com id, metadados, usuário, coleção +`batch_size`: Número de contextos por lote (padrão: 100) +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Exemplo:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em massa de representações gráficas em um fluxo. + +Carrega de forma eficiente as representações de entidades gráficas via streaming WebSocket. + +**Argumentos:** + +`flow`: Identificador do fluxo +`embeddings`: Iterador que retorna dicionários de representações +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Exemplo:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em massa de linhas estruturadas em um fluxo. + +Carrega eficientemente linhas de dados estruturados via streaming WebSocket +para uso em consultas GraphQL. + +**Argumentos:** + +`flow`: Identificador do fluxo +`rows`: Iterador que retorna dicionários de linhas +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Exemplo:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Importação em massa de triplas RDF em um fluxo. + +Carrega eficientemente um grande número de triplas via streaming WebSocket. + +**Argumentos:** + +`flow`: Identificador do fluxo +`triples`: Iterador que retorna objetos Triple +`metadata`: Dicionário de metadados com id, metadados, usuário, coleção +`batch_size`: Número de triplas por lote (padrão 100) +`**kwargs`: Parâmetros adicionais (reservados para uso futuro) + +**Exemplo:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +Cliente para operações em lote assíncronas. + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + +### `aclose(self) -> None` + +Fechar conexões + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Exportação em lote de incorporações de documentos via WebSocket. + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Exportação em lote de contextos de entidades via WebSocket. + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Exportação em lote de incorporações de grafos via WebSocket. + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +Exportação em lote de triplas via WebSocket. + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em lote de incorporações de documentos via WebSocket. + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em lote de contextos de entidades via WebSocket. + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em lote de incorporações de grafos via WebSocket. + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Importação em lote de linhas via WebSocket. + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +Importação em lote de triplas via WebSocket. + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +Cliente de métricas síncronas + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + +### `get(self) -> str` + +Obtenha as métricas do Prometheus como texto + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +Cliente de métricas assíncronas + +### Métodos + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + +### `aclose(self) -> None` + +Fechar conexões + +### `get(self) -> str` + +Obter métricas do Prometheus como texto + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +Cliente para buscar entidades de explicabilidade com tratamento de consistência eventual. + +Utiliza detecção de quiescência: buscar, esperar, buscar novamente, comparar. +Se os resultados forem os mesmos, os dados são estáveis. + +### Métodos + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +Inicializa o cliente de explicabilidade. + +**Argumentos:** + +`flow_instance`: Uma instância de SocketFlowInstance para consultar triplas. +`retry_delay`: Atraso entre as tentativas (padrão: 0,2). +`max_retries`: Número máximo de tentativas (padrão: 10). + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +Detecta se uma sessão é do tipo GraphRAG ou Agent. + +**Argumentos:** + +`session_uri`: O URI da sessão/pergunta. +`graph`: Grafo nomeado. +`user`: Identificador de usuário/espaço de chaves. +`collection`: Identificador de coleção. + +**Retorna:** "graphrag" ou "agent". + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Busca o rastreamento completo do Agent a partir de um URI de sessão. + +Segue a cadeia de rastreabilidade: Pergunta -> Análise(s) -> Conclusão. + +**Argumentos:** + +`session_uri`: O URI da sessão/pergunta do agente. +`graph`: Grafo nomeado (padrão: urn:graph:retrieval). +`user`: Identificador de usuário/espaço de chaves. +`collection`: Identificador de coleção. +`api`: Instância da API TrustGraph para acesso ao bibliotecário (opcional). +`max_content`: Comprimento máximo do conteúdo para a conclusão. + +**Retorna:** Dicionário com a pergunta, iterações (lista de Análises) e entidades de conclusão. + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Busca o rastreamento completo do DocumentRAG a partir de um URI de pergunta. + +Segue a cadeia de rastreabilidade: + Pergunta -> Fundamentação -> Exploração -> Síntese. + +**Argumentos:** + +`question_uri`: O URI da entidade de pergunta. +`graph`: Grafo nomeado (padrão: urn:graph:retrieval). +`user`: Identificador de usuário/espaço de chaves. +`collection`: Identificador de coleção. +`api`: Instância da API TrustGraph para acesso ao bibliotecário (opcional). +`max_content`: Comprimento máximo do conteúdo para a síntese. + +**Retorna:** Dicionário com a pergunta, fundamentação, exploração e entidades de síntese. + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +Busca o conteúdo do bibliotecário por URI de documento. + +**Argumentos:** + +`document_uri`: O URI do documento no bibliotecário. +`api`: Instância da API TrustGraph para acesso ao bibliotecário. +`user`: Identificador de usuário para o bibliotecário. +`max_content`: Comprimento máximo do conteúdo a ser retornado. + +**Retorna:** O conteúdo do documento como uma string. + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +Busca uma entidade de seleção de arestas (usada pelo Focus). + +**Argumentos:** + +`uri`: O URI da seleção de arestas. +`graph`: Grafo nomeado a ser consultado. +`user`: Identificador de usuário/espaço de chaves. +`collection`: Identificador de coleção. + +**Retorna:** EdgeSelection ou None se não for encontrado. + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +Buscar uma entidade de explicabilidade por URI com tratamento de consistência eventual. + +Usa detecção de quiescência: +1. Buscar triplas para o URI +2. Se não houver resultados, tentar novamente +3. Se houver resultados, esperar e buscar novamente +4. Se os resultados forem os mesmos, os dados são estáveis - analisar e retornar +5. Se os resultados forem diferentes, os dados ainda estão sendo gravados - tentar novamente + +**Argumentos:** + +`uri`: O URI da entidade a ser buscada +`graph`: Grafo nomeado a ser consultado (por exemplo, "urn:graph:retrieval") +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção + +**Retorna:** Subclasse ExplainEntity ou None se não for encontrada + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +Buscar uma entidade Focus e todas as suas seleções de arestas. + +**Argumentos:** + +`uri`: O URI da entidade Focus +`graph`: Grafo nomeado a ser consultado +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção + +**Retorna:** Focus com edge_selections preenchidos, ou None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Buscar o rastreamento completo do GraphRAG a partir de um URI de pergunta. + +Segue a cadeia de rastreabilidade: Pergunta -> Grounding -> Exploração -> Focus -> Síntese + +**Argumentos:** + +`question_uri`: O URI da entidade de pergunta +`graph`: Grafo nomeado (padrão: urn:graph:retrieval) +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`api`: Instância da API TrustGraph para acesso de bibliotecário (opcional) +`max_content`: Comprimento máximo do conteúdo para síntese + +**Retorna:** Dicionário com as entidades de pergunta, grounding, exploração, focus e síntese + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +Listar todas as sessões de explicabilidade (perguntas) em uma coleção. + +**Argumentos:** + +`graph`: Grafo nomeado (padrão: urn:graph:retrieval) +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção +`limit`: Número máximo de sessões a serem retornadas + +**Retorna:** Lista de entidades de Pergunta ordenadas por timestamp (mais recentes primeiro) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +Resolver rótulos para todos os componentes de uma tripla de aresta. + +**Argumentos:** + +`edge`: Dicionário com chaves "s", "p" e "o" +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção + +**Retorna:** Tupla de (s_label, p_label, o_label) + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +Resolver rdfs:label para um URI, com cache. + +**Argumentos:** + +`uri`: O URI para o qual obter o rótulo +`user`: Identificador de usuário/espaço de chaves +`collection`: Identificador de coleção + +**Retorna:** O rótulo se encontrado, caso contrário, o próprio URI + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +Classe base para entidades de explicabilidade. + +**Campos:** + +`uri`: +`entity_type`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para a assinatura correta. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +Entidade de pergunta - a consulta do usuário que iniciou a sessão. + +**Campos:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +Entidade de exploração - arestas/pedaços recuperados do repositório de conhecimento. + +**Campos:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +Entidade de foco - arestas selecionadas com raciocínio LLM (apenas GraphRAG). + +**Campos:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +Entidade de síntese - a resposta final. + +**Campos:** + +`uri`: +`entity_type`: +`document`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para a assinatura correta. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +Entidade de análise - um ciclo de pensar/agir/observar (apenas para o Agente). + +**Campos:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +Conclusão da entidade - resposta final (Agente apenas). + +**Campos:** + +`uri`: +`entity_type`: +`document`: + +### Métodos + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +Uma aresta selecionada com raciocínio da etapa GraphRAG Focus. + +**Campos:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### Métodos + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +Converta triplas no formato de fio em tuplas (s, p, o). + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +Extraia o valor de um dicionário Term no formato de fio. + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +Tripla RDF que representa uma declaração de um grafo de conhecimento. + +**Campos:** + +`s`: +`p`: +`o`: + +### Métodos + +### `__init__(self, s: str, p: str, o: str) -> None` + +Inicializa self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Crie um novo objeto string a partir do objeto fornecido. Se encoding ou +errors forem especificados, então o objeto deve expor um buffer de dados +que será decodificado usando a codificação e o manipulador de erros fornecidos. +Caso contrário, retorna o resultado de object.__str__() (se definido) +ou repr(object). +encoding tem como padrão 'utf-8'. +errors tem como padrão 'strict'. + +### Métodos + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Crie um novo objeto string a partir do objeto fornecido. Se encoding ou +errors forem especificados, então o objeto deve expor um buffer de dados +que será decodificado usando a codificação e o manipulador de erros fornecidos. +Caso contrário, retorna o resultado de object.__str__() (se definido) +ou repr(object). +encoding tem como padrão 'utf-8'. +errors tem como padrão 'strict'. + +### Métodos + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +Identificador da chave de configuração. + +**Campos:** + +`type`: +`key`: + +### Métodos + +### `__init__(self, type: str, key: str) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +Par de chave-valor de configuração. + +**Campos:** + +`type`: +`key`: +`value`: + +### Métodos + +### `__init__(self, type: str, key: str, value: str) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +Metadados para um documento na biblioteca. + +**Atributos:** + +`parent_id: Parent document ID for child documents (empty for top`: level docs) + +**Campos:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### Métodos + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +Metadados para um processo de documento ativo. + +**Campos:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### Métodos + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +Metadados para uma coleção de dados. + +As coleções fornecem agrupamento lógico e isolamento para documentos e +dados de grafo de conhecimento. + +**Atributos:** + +`name: Human`: nome da coleção legível + +**Campos:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### Métodos + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +Classe base para fragmentos de resposta de streaming. + +Usado para operações de streaming baseadas em WebSocket, onde as respostas são entregues +incrementalmente à medida que são geradas. + +**Campos:** + +`content`: +`end_of_message`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +Inicializa self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +Trecho de raciocínio/processo de pensamento do agente. + +Representa o raciocínio interno ou as etapas de planejamento do agente durante a execução. +Esses trechos mostram como o agente está pensando sobre o problema. + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +Trecho de observação da execução da ferramenta do agente. + +Representa o resultado ou a observação da execução de uma ferramenta ou ação. +Esses trechos mostram o que o agente aprendeu ao usar ferramentas. + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +Trecho da resposta final do agente. + +Representa a resposta final do agente ao pedido do usuário após concluir +seu raciocínio e uso de ferramentas. + +**Atributos:** + +`chunk_type: Always "final`: answer" + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +RAG (Geração Aumentada por Recuperação) em blocos de fluxo. + +Usado para transmitir respostas de RAG de grafos, RAG de documentos, preenchimento de texto, +e outros serviços generativos. + +**Campos:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### Métodos + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +Inicializa self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +Evento de rastreabilidade para explicabilidade. + +Emitido durante as consultas GraphRAG quando o modo de explicabilidade está habilitado. +Cada evento representa um nó de rastreabilidade criado durante o processamento da consulta. + +**Campos:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### Métodos + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +Inicialize self. Consulte help(type(self)) para obter a assinatura correta. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +Disparado quando ocorrem erros no protocolo WebSocket. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +Classe base para todos os erros do serviço TrustGraph. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +Erro no serviço do agente + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +Erro no serviço de configuração. + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +Erro de recuperação de documentos RAG. + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +Erro de gerenciamento de fluxo + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +Erro no API Gateway + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +Erro de recuperação do Graph RAG. + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +Erro no serviço de LLM. + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +Erro ao carregar dados + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +Erro de pesquisa/busca + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +Erro no serviço de consulta de processamento de linguagem natural. + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +Erro no serviço de consulta de linhas. + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +Erro no processamento da requisição. + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +Erro no serviço de consulta estruturada. + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +Erro inesperado/desconhecido + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +Classe base para todos os erros do serviço TrustGraph. + + +-- diff --git a/docs/python-api.ru.md b/docs/python-api.ru.md new file mode 100644 index 00000000..38be9dbf --- /dev/null +++ b/docs/python-api.ru.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "Справочник API TrustGraph на Python" +parent: "Russian (Beta)" +--- + +# Справочник API TrustGraph на Python + +> **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. + +## Установка + +```bash +pip install trustgraph +``` + +## Быстрый старт + +Все классы и типы импортируются из пакета `trustgraph.api`: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## Оглавление + +### Основное + +[Api](#api) + +### Клиенты потоков + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### Клиенты WebSocket + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### Операции пакетной обработки + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### Метрики + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### Типы данных + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### Исключения + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +Основной клиент API TrustGraph для синхронных и асинхронных операций. + +Этот класс предоставляет доступ ко всем сервисам TrustGraph, включая управление потоками, +операции с графом знаний, обработку документов, запросы RAG и многое другое. Он поддерживает +как коммуникационные модели на основе REST, так и на основе WebSocket. + +Клиент может использоваться как менеджер контекста для автоматической очистки ресурсов: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### Методы + +### `__aenter__(self)` + +Войдите в асинхронный контекстный менеджер. + +### `__aexit__(self, *args)` + +Выйдите из асинхронного контекстного менеджера и закройте соединения. + +### `__enter__(self)` + +Войдите в синхронный контекстный менеджер. + +### `__exit__(self, *args)` + +Выйдите из синхронного контекстного менеджера и закройте соединения. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +Инициализируйте клиент API TrustGraph. + +**Аргументы:** + +`url`: Базовый URL для API TrustGraph (по умолчанию: "http://localhost:8088/"") +`timeout`: Время ожидания запроса в секундах (по умолчанию: 60) +`token`: Необязательный токен для аутентификации + +**Пример:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +Закройте все асинхронные клиентские соединения. + +Этот метод закрывает асинхронные WebSocket-соединения, пакетные операции и потоковые соединения. +Он автоматически вызывается при выходе из асинхронного контекстного менеджера. + +**Пример:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +Получите клиент для асинхронных пакетных операций. + +Предоставляет пакетные операции импорта/экспорта в стиле async/await через WebSocket +для эффективной обработки больших наборов данных. + +**Возвращает:** AsyncBulkClient: Асинхронный клиент для пакетных операций. + +**Пример:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +Получите асинхронный клиент потоковой передачи на основе REST. + +Предоставляет доступ к операциям потоковой передачи в стиле async/await. Это предпочтительно +для асинхронных приложений и фреймворков Python (FastAPI, aiohttp и т.д.). + +**Возвращает:** AsyncFlow: Асинхронный клиент потоковой передачи + +**Пример:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +Получите асинхронного клиента для сбора метрик. + +Предоставляет доступ к метрикам Prometheus в стиле async/await. + +**Возвращает:** AsyncMetrics: Асинхронный клиент для сбора метрик. + +**Пример:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +Получите асинхронный WebSocket-клиент для операций потоковой передачи. + +Предоставляет доступ к WebSocket в стиле async/await с поддержкой потоковой передачи. +Это предпочтительный метод для асинхронной потоковой передачи в Python. + +**Возвращает:** AsyncSocketClient: Асинхронный WebSocket-клиент + +**Пример:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +Получите клиент для синхронных пакетных операций импорта/экспорта. + +Пакетные операции позволяют эффективно передавать большие наборы данных через соединения WebSocket, +включая тройки, вложения, контексты сущностей и объекты. + +**Возвращает:** BulkClient: Клиент для синхронных пакетных операций. + +**Пример:** + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +Закройте все синхронные клиентские соединения. + +Этот метод закрывает соединения WebSocket и пакетных операций. +Он автоматически вызывается при выходе из контекстного менеджера. + +**Пример:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +Получите клиент Collection для управления наборами данных. + +Коллекции организуют документы и данные графа знаний в +логические группы для изоляции и контроля доступа. + +**Возвращает:** Collection: Клиент для управления коллекциями. + +**Пример:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +Получите клиент Config для управления настройками конфигурации. + +**Возвращает:** Config: Клиент для управления конфигурацией. + +**Пример:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +Получите клиент Flow для управления и взаимодействия с потоками. + +Потоки являются основными единицами выполнения в TrustGraph, предоставляя доступ к +сервисам, таким как агенты, запросы RAG, встраивания и обработка документов. + +**Возвращает:** Flow: Клиент для управления потоками. + +**Пример:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +Получите клиент Knowledge для управления ядрами графов знаний. + +**Возвращает:** Клиент Knowledge для управления графами знаний. + +**Пример:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +Получите клиент библиотеки для управления документами. + +Библиотека предоставляет хранение документов, управление метаданными и +координацию рабочих процессов. + +**Возвращает:** Library: Клиент для управления библиотекой документов + +**Пример:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +Получите синхронный клиент для сбора метрик для мониторинга. + +Получает метрики в формате Prometheus из сервиса TrustGraph +для мониторинга и обеспечения наблюдаемости. + +**Возвращает:** Метрики: Синхронный клиент для сбора метрик. + +**Пример:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +Выполнить запрос REST API на низком уровне. + +Этот метод предназначен в основном для внутреннего использования, но может использоваться для прямого +доступа к API, когда это необходимо. + +**Аргументы:** + +`path`: Путь к API (относительно базового URL) +`request`: Текстовые данные запроса в виде словаря + +**Возвращает:** dict: Объект ответа + +**Вызывает исключения:** + +`ProtocolException`: Если код состояния ответа не равен 200 или ответ не является JSON +`ApplicationException`: Если ответ содержит ошибку + +**Пример:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +Получите синхронного клиента WebSocket для операций потоковой передачи. + +Соединения WebSocket обеспечивают поддержку потоковой передачи для ответов в режиме реального времени +от агентов, запросов RAG и завершения текста. Этот метод возвращает +синхронную обертку вокруг протокола WebSocket. + +**Возвращает:** SocketClient: Синхронный клиент WebSocket + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +Клиент для управления потоками, предназначенный для операций с шаблонами и экземплярами потоков. + +Этот класс предоставляет методы для управления шаблонами потоков и +экземплярами потоков (запущенными потоками). Шаблоны определяют структуру и +параметры потоков, в то время как экземпляры представляют активные потоки, которые могут +выполнять сервисы. + +### Методы + +### `__init__(self, api)` + +Инициализация клиента потоков. + +**Аргументы:** + +`api`: Родительский экземпляр API для выполнения запросов. + +### `delete_blueprint(self, blueprint_name)` + +Удаление шаблона потока. + +**Аргументы:** + +`blueprint_name`: Имя шаблона, который необходимо удалить. + +**Пример:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +Получить определение экземпляра активного процесса. + +**Аргументы:** + +`id`: Идентификатор экземпляра процесса + +**Возвращает:** dict: Определение экземпляра процесса + +**Пример:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +Получить определение схемы по имени. + +**Аргументы:** + +`blueprint_name`: Имя схемы, которую необходимо получить. + +**Возвращает:** dict: Определение схемы в виде словаря. + +**Пример:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +Получение объекта FlowInstance для выполнения операций над определенным потоком. + +**Аргументы:** + +`id`: Идентификатор потока (по умолчанию: "default") + +**Возвращает:** FlowInstance: Объект Flow для операций сервиса. + +**Пример:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +Перечислить все активные экземпляры потоков. + +**Возвращает:** list[str]: Список идентификаторов экземпляров потоков. + +**Пример:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +Перечислить все доступные шаблоны потоков. + +**Возвращает:** list[str]: Список имен шаблонов. + +**Пример:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +Создать или обновить шаблон потока. + +**Аргументы:** + +`blueprint_name`: Имя для шаблона +`definition`: Словарь определения шаблона + +**Пример:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +Отправьте API-запрос в рамках одного потока. + +**Аргументы:** + +`path`: Необязательный суффикс пути для конечных точек потока. +`request`: Словарь, содержащий полезную нагрузку запроса. + +**Возвращает:** dict: Объект ответа. + +**Вызывает исключение:** + +`RuntimeError`: Если параметр запроса не указан. + +### `start(self, blueprint_name, id, description, parameters=None)` + +Запустите новый экземпляр потока из шаблона. + +**Аргументы:** + +`blueprint_name`: Имя шаблона для создания экземпляра. +`id`: Уникальный идентификатор экземпляра потока. +`description`: Описание, понятное человеку. +`parameters`: Необязательный словарь параметров. + +**Пример:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +Остановить запущенный экземпляр потока. + +**Аргументы:** + +`id`: Идентификатор экземпляра потока, который необходимо остановить. + +**Пример:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +Клиент экземпляра потока для выполнения сервисов в определенном потоке. + +Этот класс предоставляет доступ ко всем сервисам TrustGraph, включая: +Завершение текста и создание векторных представлений +Операции агентов с управлением состоянием +Запросы RAG к графам и документам +Операции с графами знаний (тройки, объекты) +Загрузка и обработка документов +Преобразование естественного языка в запрос GraphQL +Анализ структурированных данных и обнаружение схемы +Выполнение инструмента MCP +Шаблонизация запросов + +Сервисы доступны через работающий экземпляр потока, идентифицированный по ID. + +### Методы + +### `__init__(self, api, id)` + +Инициализация FlowInstance. + +**Аргументы:** + +`api`: Родительский клиент потока +`id`: Идентификатор экземпляра потока + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +Выполнение операции агента с возможностями рассуждения и использования инструментов. + +Агенты могут выполнять многоступенчатое рассуждение, использовать инструменты и поддерживать +состояние разговора в течение взаимодействий. Это синхронная версия без потоковой передачи. + +**Аргументы:** + +`question`: Вопрос или инструкция пользователя +`user`: Идентификатор пользователя (по умолчанию: "trustgraph") +`state`: Необязательный словарь состояния для разговоров с состоянием +`group`: Необязательный идентификатор группы для многопользовательских контекстов +`history`: Необязательная история разговора в виде списка словарей сообщений + +**Возвращает:** str: Окончательный ответ агента + +**Пример:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +Определить тип данных для образца структурированных данных. + +**Аргументы:** + +`sample`: Образец данных для анализа (текстовое содержимое) + +**Возвращает:** словарь с информацией о типе, уверенности и необязательных метаданных. + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +Выполнить комплексную диагностику данных: определить тип и сгенерировать описание. + +**Аргументы:** + +`sample`: Образец данных для анализа (текстовое содержимое) +`schema_name`: Необязательное имя целевой схемы для генерации описания. +`options`: Необязательные параметры (например, разделитель для CSV). + +**Возвращает:** словарь с информацией о типе, уверенности, описании и метаданных. + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +Запрос фрагментов документов с использованием семантического сходства. + +Находит фрагменты документов, содержимое которых семантически похоже на +входной текст, используя векторные представления. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска. +`user`: Идентификатор пользователя/пространства. +`collection`: Идентификатор коллекции. +`limit`: Максимальное количество результатов (по умолчанию: 10). + +**Возвращает:** словарь: Результаты запроса с фрагментами, содержащими chunk_id и score. + +**Пример:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +Выполнение запроса Retrieval-Augmented Generation (RAG), основанного на документах. + +RAG на основе документов использует векторные представления для поиска соответствующих фрагментов документов, +а затем генерирует ответ с использованием LLM, используя эти фрагменты в качестве контекста. + +**Аргументы:** + +`query`: Запрос на естественном языке +`user`: Идентификатор пользователя/пространства (по умолчанию: "trustgraph") +`collection`: Идентификатор коллекции (по умолчанию: "default") +`doc_limit`: Максимальное количество фрагментов документов для извлечения (по умолчанию: 10) + +**Возвращает:** str: Сгенерированный ответ, включающий контекст документа + +**Пример:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +Генерирует векторные представления для одного или нескольких текстов. + +Преобразует тексты в плотные векторные представления, подходящие для семантического +поиска и сравнения схожести. + +**Аргументы:** + +`texts`: Список входных текстов для создания векторных представлений. + +**Возвращает:** list[list[list[float]]]: Векторные представления, один набор для каждого входного текста. + +**Пример:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +Создать описание для сопоставления структурированных данных с определенной схемой. + +**Аргументы:** + +`sample`: Пример данных для анализа (текстовое содержимое) +`data_type`: Тип данных (csv, json, xml) +`schema_name`: Имя целевой схемы для создания описания +`options`: Необязательные параметры (например, разделитель для CSV) + +**Возвращает:** словарь с описанием и метаданными + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +Запрос сущностей графа знаний с использованием семантического сходства. + +Находит сущности в графе знаний, описания которых семантически +схожи с входным текстом, используя векторные представления. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`user`: Идентификатор пользователя/пространства ключей +`collection`: Идентификатор коллекции +`limit`: Максимальное количество результатов (по умолчанию: 10) + +**Возвращает:** словарь: Результаты запроса с похожими сущностями + +**Пример:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +Выполнение запроса на основе графов для генерации ответов с использованием извлеченной информации (RAG). + +Graph RAG использует структуру графа знаний для поиска релевантного контекста путем +обхода связей между сущностями, а затем генерирует ответ с использованием большой языковой модели (LLM). + +**Аргументы:** + +`query`: Запрос на естественном языке +`user`: Идентификатор пользователя/пространства (по умолчанию: "trustgraph") +`collection`: Идентификатор коллекции (по умолчанию: "default") +`entity_limit`: Максимальное количество сущностей для извлечения (по умолчанию: 50) +`triple_limit`: Максимальное количество троек на сущность (по умолчанию: 30) +`max_subgraph_size`: Максимальное общее количество троек в подграфе (по умолчанию: 150) +`max_path_length`: Максимальная глубина обхода (по умолчанию: 2) + +**Возвращает:** str: Сгенерированный ответ, включающий контекст графа + +**Пример:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +Загрузка двоичного документа для обработки. + +Загрузка документа (PDF, DOCX, изображений и т.д.) для извлечения и +обработки через конвейер документов. + +**Аргументы:** + +`document`: Содержимое документа в виде байтов +`id`: Необязательный идентификатор документа (генерируется автоматически, если None) +`metadata`: Необязательные метаданные (список троек или объект с методом emit) +`user`: Идентификатор пользователя/пространства ключей (необязательно) +`collection`: Идентификатор коллекции (необязательно) + +**Возвращает:** dict: Ответ обработки + +**Вызывает исключения:** + +`RuntimeError`: Если предоставлены метаданные без идентификатора + +**Пример:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +Загрузка текстового контента для обработки. + +Загрузка текстового контента для извлечения и обработки через конвейер текста. + + +**Аргументы:** + +`text`: Текстовый контент в виде байтов +`id`: Необязательный идентификатор документа (генерируется автоматически, если None) +`metadata`: Необязательные метаданные (список троек или объект с методом emit) +`charset`: Кодировка символов (по умолчанию: "utf-8") +`user`: Идентификатор пользователя/пространства ключей (необязательно) +`collection`: Идентификатор коллекции (необязательно) + +**Возвращает:** dict: Ответ обработки + +**Вызывает исключения:** + +`RuntimeError`: Если предоставлены метаданные без идентификатора + +**Пример:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +Выполнить инструмент протокола контекста модели (Model Context Protocol, MCP). + +Инструменты MCP предоставляют расширяемую функциональность для агентов и рабочих процессов, +позволяя интеграцию с внешними системами и сервисами. + +**Аргументы:** + +`name`: Имя/идентификатор инструмента +`parameters`: Словарь параметров инструмента (по умолчанию: {}) + +**Возвращает:** str или dict: Результат выполнения инструмента + +**Вызывает исключение:** + +`ProtocolException`: Если формат ответа недействителен + +**Пример:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +Преобразование вопроса на естественном языке в запрос GraphQL. + +**Аргументы:** + +`question`: Вопрос на естественном языке +`max_results`: Максимальное количество возвращаемых результатов (по умолчанию: 100) + +**Возвращает:** словарь с полями graphql_query, variables, detected_schemas, confidence + +### `prompt(self, id, variables)` + +Выполнение шаблона запроса с подстановкой переменных. + +Шаблоны запросов позволяют использовать многократно шаблоны запросов с динамическими переменными. +Это полезно для обеспечения согласованности при разработке запросов. + +**Аргументы:** + +`id`: Идентификатор шаблона запроса. +`variables`: Словарь, содержащий соответствия между именами переменных и их значениями. + +**Возвращает:** str или dict: Результат отрисованного запроса (текст или структурированный объект). + +**Вызывает исключение:** + +`ProtocolException`: Если формат ответа недействителен. + +**Пример:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +Отправьте запрос на создание сервиса для этого экземпляра потока. + +**Аргументы:** + +`path`: Путь к сервису (например, "service/text-completion") +`request`: Словарь с данными запроса + +**Возвращает:** dict: Ответ сервиса + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +Запрос данных строк с использованием семантического сходства по индексированным полям. + +Находит строки, значения индексированных полей которых семантически схожи с +входным текстом, используя векторные представления. Это обеспечивает нечеткое/семантическое сопоставление +структурированных данных. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`schema_name`: Имя схемы для поиска +`user`: Идентификатор пользователя/пространства ключей (по умолчанию: "trustgraph") +`collection`: Идентификатор коллекции (по умолчанию: "default") +`index_name`: Необязательное имя индекса для фильтрации поиска по определенному индексу +`limit`: Максимальное количество результатов (по умолчанию: 10) + +**Возвращает:** dict: Результаты запроса с совпадениями, содержащими index_name, index_value, text и score + +**Пример:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +Выполнение запроса GraphQL к структурированным данным в графе знаний. + +Запросы структурированных данных с использованием синтаксиса GraphQL, что позволяет выполнять сложные запросы +с фильтрацией, агрегацией и обходом связей. + +**Аргументы:** + +`query`: Строка запроса GraphQL +`user`: Идентификатор пользователя/пространства (по умолчанию: "trustgraph") +`collection`: Идентификатор коллекции (по умолчанию: "default") +`variables`: Необязательный словарь переменных запроса +`operation_name`: Необязательное имя операции для документов с несколькими операциями + +**Возвращает:** dict: Ответ GraphQL с полями 'data', 'errors' и/или 'extensions' + +**Вызывает исключение:** + +`ProtocolException`: Если возникает системная ошибка + +**Пример:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +Выберите соответствующие схемы для образца данных, используя анализ запросов. + +**Аргументы:** + +`sample`: Образец данных для анализа (текстовое содержимое) +`options`: Необязательные параметры + +**Возвращает:** словарь с массивом schema_matches и метаданными + +### `structured_query(self, question, user='trustgraph', collection='default')` + +Выполните запрос на естественном языке к структурированным данным. +Объединяет преобразование запроса NLP и выполнение GraphQL. + +**Аргументы:** + +`question`: Запрос на естественном языке +`user`: Идентификатор пространства ключей Cassandra (по умолчанию: "trustgraph") +`collection`: Идентификатор набора данных (по умолчанию: "default") + +**Возвращает:** словарь с данными и, возможно, ошибками + +### `text_completion(self, system, prompt)` + +Выполните текстовое завершение с использованием LLM потока. + +**Аргументы:** + +`system`: Системная подсказка, определяющая поведение помощника +`prompt`: Подсказка/вопрос пользователя + +**Возвращает:** str: Сгенерированный текст ответа + +**Пример:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +Запрос троек знаний графа с использованием сопоставления с образцом. + +Поиск троек RDF, соответствующих заданным шаблонам субъекта, предиката и/или +объекта. Неуказанные параметры действуют как подстановочные знаки. + +**Аргументы:** + +`s`: URI субъекта (необязательно, используйте None для подстановочного знака) +`p`: URI предиката (необязательно, используйте None для подстановочного знака) +`o`: URI объекта или литерала (необязательно, используйте None для подстановочного знака) +`user`: Идентификатор пользователя/пространства ключей (необязательно) +`collection`: Идентификатор коллекции (необязательно) +`limit`: Максимальное количество возвращаемых результатов (по умолчанию: 10000) + +**Возвращает:** list[Triple]: Список объектов Triple, соответствующих условиям. + +**Вызывает исключение:** + +`RuntimeError`: Если s или p не являются Uri, или o не является Uri/Literal + +**Пример:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +Клиент для управления асинхронными процессами с использованием REST API. + +Предоставляет операции управления процессами на основе async/await, включая перечисление, +запуск, остановку процессов и управление определениями классов процессов. Также предоставляет +доступ к сервисам, связанным с процессами, таким как агенты, RAG и запросы, через REST-интерфейсы без потоковой передачи. + + +Обратите внимание: для поддержки потоковой передачи используйте AsyncSocketClient. + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Инициализация асинхронного клиента для управления процессами. + +**Аргументы:** + +`url`: Базовый URL для API TrustGraph. +`timeout`: Время ожидания запроса в секундах. +`token`: Необязательный токен для аутентификации. + +### `aclose(self) -> None` + +Закрытие асинхронного клиента и освобождение ресурсов. + +Обратите внимание: очистка выполняется автоматически менеджерами контекста сессии aiohttp. +Этот метод предоставляется для обеспечения согласованности с другими асинхронными клиентами. + +### `delete_class(self, class_name: str)` + +Удаление определения класса процесса. + +Удаляет шаблон класса процесса из системы. Не влияет на +работающие экземпляры процессов. + +**Аргументы:** + +`class_name`: Имя класса процесса для удаления. + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +Получение определения потока. + +Получает полную конфигурацию потока, включая его имя класса, +описание и параметры. + +**Аргументы:** + +`id`: Идентификатор потока + +**Возвращает:** dict: Объект определения потока + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +Получение определения класса потока. + +Получает определение шаблона для класса потока, включая его +схему конфигурации и привязки к сервисам. + +**Аргументы:** + +`class_name`: Имя класса потока + +**Возвращает:** dict: Объект определения класса потока + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +Получение экземпляра клиента асинхронного потока. + +Возвращает клиент для взаимодействия со службами конкретного потока (агент, RAG, запросы, встраивания и т.д.). + + +**Аргументы:** + +`flow_id`: Идентификатор потока + +**Возвращает:** AsyncFlowInstance: Клиент для операций, специфичных для потока + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +Перечислить все идентификаторы потоков. + +Получает идентификаторы всех потоков, которые в настоящее время развернуты в системе. + +**Возвращает:** list[str]: Список идентификаторов потоков + +**Пример:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +Перечислите все имена классов потоков. + +Получает имена всех классов потоков (шаблонов), доступных в системе. + +**Возвращает:** list[str]: Список имен классов потоков. + +**Пример:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +Создать или обновить определение класса потока. + +Хранит шаблон класса потока, который можно использовать для создания экземпляров потоков. + +**Аргументы:** + +`class_name`: Имя класса потока +`definition`: Объект определения класса потока + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Выполнить асинхронный HTTP POST-запрос к API шлюза. + +Внутренний метод для выполнения аутентифицированных запросов к API TrustGraph. + +**Аргументы:** + +`path`: Путь к API (относительно базового URL) +`request_data`: Словарь с данными запроса + +**Возвращает:** dict: Объект ответа от API + +**Вызывает исключения:** + +`ProtocolException`: Если HTTP-статус не 200 или ответ не является допустимым JSON +`ApplicationException`: Если API возвращает ответ об ошибке + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +Запустить новый экземпляр потока. + +Создает и запускает поток из определения класса потока с указанными +параметрами. + +**Аргументы:** + +`class_name`: Имя класса потока для создания экземпляра +`id`: Идентификатор нового экземпляра потока +`description`: Человекочитаемое описание потока +`parameters`: Необязательные параметры конфигурации для потока + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +Остановить выполняющийся процесс. + +Останавливает и удаляет экземпляр процесса, освобождая его ресурсы. + +**Аргументы:** + +`id`: Идентификатор процесса, который необходимо остановить. + +**Пример:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +Клиент экземпляра асинхронного потока. + +Предоставляет доступ с использованием async/await к сервисам, связанным с потоком, включая агентов, +запросы RAG, эмбеддинги и запросы к графу. Все операции возвращают полные +ответы (без потоковой передачи). + +Обратите внимание: для поддержки потоковой передачи используйте AsyncSocketFlowInstance. + +### Методы + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +Инициализация асинхронного экземпляра потока. + +**Аргументы:** + +`flow`: Родительский клиент AsyncFlow +`flow_id`: Идентификатор потока + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +Выполнение операции агента (без потоковой передачи). + +Запускает агента для ответа на вопрос, с необязательным состоянием разговора и +историей. Возвращает полный ответ после завершения обработки агентом. + + +Обратите внимание: этот метод не поддерживает потоковую передачу. Для получения мыслей и наблюдений агента в режиме реального времени используйте AsyncSocketFlowInstance.agent(). + + +**Аргументы:** + +`question`: Вопрос или инструкция пользователя +`user`: Идентификатор пользователя +`state`: Необязательный словарь состояния для контекста разговора +`group`: Необязательный идентификатор группы для управления сеансом +`history`: Необязательный список истории разговоров +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** dict: Полный ответ агента, включая ответ и метаданные + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +Выполнение запроса RAG на основе документов (без потоковой передачи). + +Выполняет генерацию с использованием информации, полученной из документов. +Извлекает соответствующие фрагменты документов с помощью семантического поиска, а затем генерирует +ответ, основанный на извлеченных документах. Возвращает полный ответ. + +Обратите внимание: этот метод не поддерживает потоковую передачу. Для получения потоковых ответов RAG используйте AsyncSocketFlowInstance.document_rag(). + + +**Аргументы:** + +`query`: Текст запроса пользователя +`user`: Идентификатор пользователя +`collection`: Идентификатор коллекции, содержащей документы +`doc_limit`: Максимальное количество фрагментов документов для извлечения (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** str: Полный сгенерированный ответ, основанный на данных документов + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +Генерирует векторные представления для входных текстов. + +Преобразует тексты в числовые векторные представления, используя +настроенную модель для создания векторных представлений. Полезно для семантического поиска и +сравнения схожести. + +**Аргументы:** + +`texts`: Список входных текстов для создания векторных представлений. +`**kwargs`: Дополнительные параметры, специфичные для сервиса. + +**Возвращает:** dict: Ответ, содержащий векторные представления. + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +Выполняет поиск векторных представлений графов для семантического поиска сущностей. + +Выполняет семантический поиск по векторным представлениям сущностей графа для поиска сущностей, +наиболее релевантных входному тексту. Возвращает сущности, отсортированные по степени схожести. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`user`: Идентификатор пользователя +`collection`: Идентификатор коллекции, содержащей векторные представления графа +`limit`: Максимальное количество возвращаемых результатов (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** dict: Ответ, содержащий отсортированные совпадения сущностей с оценками схожести + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +Выполнение запроса RAG на основе графа (без потоковой передачи). + +Выполняет генерацию с использованием информации, полученной из графа знаний. +Определяет соответствующие сущности и их взаимосвязи, а затем генерирует +ответ, основанный на структуре графа. Возвращает полный ответ. + +Обратите внимание: этот метод не поддерживает потоковую передачу. Для получения потоковых ответов RAG используйте AsyncSocketFlowInstance.graph_rag(). + + +**Аргументы:** + +`query`: Текст запроса пользователя +`user`: Идентификатор пользователя +`collection`: Идентификатор коллекции, содержащей граф знаний +`max_subgraph_size`: Максимальное количество троек на подграфе (по умолчанию: 1000) +`max_subgraph_count`: Максимальное количество подграфов для извлечения (по умолчанию: 5) +`max_entity_distance`: Максимальное расстояние графа для расширения сущностей (по умолчанию: 3) +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** str: Полный сгенерированный ответ, основанный на данных графа + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Отправка запроса к сервису, доступному в рамках текущего потока. + +Внутренний метод для вызова сервисов в пределах текущего экземпляра потока. + +**Аргументы:** + +`service`: Имя сервиса (например, "agent", "graph-rag", "triples") +`request_data`: Тело запроса к сервису + +**Возвращает:** dict: Объект ответа от сервиса + +**Вызывает исключения:** + +`ProtocolException`: Если запрос не удался или ответ недействителен +`ApplicationException`: Если сервис вернул ошибку + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +Запрос векторных представлений строк для семантического поиска в структурированных данных. + +Выполняет семантический поиск по векторным представлениям индексов строк для поиска строк, чьи +значения индексированных полей наиболее близки к входному тексту. Обеспечивает +нечеткое/семантическое сопоставление в структурированных данных. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`schema_name`: Имя схемы для поиска +`user`: Идентификатор пользователя (по умолчанию: "trustgraph") +`collection`: Идентификатор коллекции (по умолчанию: "default") +`index_name`: Необязательное имя индекса для фильтрации поиска по конкретному индексу +`limit`: Максимальное количество возвращаемых результатов (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** dict: Ответ, содержащий совпадения с index_name, index_value, text и score + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +Выполнение запроса GraphQL к сохраненным строкам. + +Запросы структурированные данные строк, используя синтаксис GraphQL. Поддерживает сложные +запросы с переменными и именованными операциями. + +**Аргументы:** + +`query`: Строка запроса GraphQL +`user`: Идентификатор пользователя +`collection`: Идентификатор коллекции, содержащей строки +`variables`: Необязательные переменные запроса GraphQL +`operation_name`: Необязательное имя операции для запросов с несколькими операциями +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** dict: Ответ GraphQL с данными и/или ошибками + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +Генерирует текстовое завершение (не в режиме потоковой передачи). + +Генерирует текстовый ответ от LLM на основе системной подсказки и пользовательской подсказки. +Возвращает полный текст ответа. + +Обратите внимание: этот метод не поддерживает потоковую передачу. Для генерации текста в режиме потоковой передачи используйте AsyncSocketFlowInstance.text_completion(). + + +**Аргументы:** + +`system`: Системная подсказка, определяющая поведение LLM. +`prompt`: Пользовательская подсказка или вопрос. +`**kwargs`: Дополнительные параметры, специфичные для сервиса. + +**Возвращает:** str: Полный сгенерированный текст ответа. + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +Запрос RDF-тройств с использованием сопоставления с образцом. + +Поиск тройств, соответствующих указанным шаблонам субъекта, предиката и/или +объекта. Шаблоны используют "None" в качестве подстановочного знака для сопоставления с любым значением. + +**Аргументы:** + +`s`: Шаблон субъекта (None для подстановочного знака) +`p`: Шаблон предиката (None для подстановочного знака) +`o`: Шаблон объекта (None для подстановочного знака) +`user`: Идентификатор пользователя (None для всех пользователей) +`collection`: Идентификатор коллекции (None для всех коллекций) +`limit`: Максимальное количество тройств для возврата (по умолчанию: 100) +`**kwargs`: Дополнительные параметры, специфичные для сервиса + +**Возвращает:** dict: Ответ, содержащий соответствующие тройства + +**Пример:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +Синхронный WebSocket-клиент для потоковых операций. + +Предоставляет синхронный интерфейс для сервисов TrustGraph, основанных на WebSocket, +обертывая асинхронную библиотеку websockets с использованием синхронных генераторов для удобства использования. +Поддерживает потоковые ответы от агентов, запросы RAG и текстовые подсказки. + +Обратите внимание: это синхронная обертка вокруг асинхронных операций WebSocket. Для +полной асинхронной поддержки используйте AsyncSocketClient. + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Инициализация синхронного WebSocket-клиента. + +**Аргументы:** + +`url`: Базовый URL для API TrustGraph (HTTP/HTTPS будет преобразован в WS/WSS) +`timeout`: Время ожидания WebSocket в секундах +`token`: Необязательный токен для аутентификации + +### `close(self) -> None` + +Закрытие WebSocket-соединений. + +Обратите внимание: очистка выполняется автоматически с помощью менеджеров контекста в асинхронном коде. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +Получение экземпляра потока для потоковых операций WebSocket. + +**Аргументы:** + +`flow_id`: Идентификатор потока + +**Возвращает:** SocketFlowInstance: Экземпляр потока с методами потоковой передачи + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +Экземпляр потока WebSocket для операций потоковой передачи. + +Предоставляет тот же интерфейс, что и FlowInstance REST, но с поддержкой потоковой передачи на основе WebSocket +для получения ответов в реальном времени. Все методы поддерживают необязательный +параметр `streaming` для включения постепенной доставки результатов. + +### Методы + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +Инициализация экземпляра потока сокета. + +**Аргументы:** + +`client`: Родительский SocketClient +`flow_id`: Идентификатор потока + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +Выполнение операции агента с поддержкой потоковой передачи. + +Агенты могут выполнять многоэтапные рассуждения с использованием инструментов. Этот метод всегда +возвращает потоковые фрагменты (мысли, наблюдения, ответы), даже когда +streaming=False, чтобы показать процесс рассуждений агента. + +**Аргументы:** + +`question`: Вопрос или инструкция пользователя +`user`: Идентификатор пользователя +`state`: Необязательный словарь состояния для разговоров с состоянием +`group`: Необязательный идентификатор группы для многопользовательских контекстов +`history`: Необязательная история разговоров в виде списка словарей сообщений +`streaming`: Включить режим потоковой передачи (по умолчанию: False) +`**kwargs`: Дополнительные параметры, передаваемые службе агента + +**Возвращает:** Iterator[StreamingChunk]: Поток мыслей, наблюдений и ответов агента + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +Выполнение операции агента с поддержкой объяснимости. + +Передает как фрагменты контента (AgentThought, AgentObservation, AgentAnswer), +так и события, связанные с происхождением (ProvenanceEvent). События, связанные с происхождением, содержат URI, +которые можно получить с помощью ExplainabilityClient для получения подробной информации +о процессе рассуждений агента. + +Трассировка агента состоит из: +Сессия: Исходный вопрос и метаданные сессии. +Итерации: Каждый цикл мыслей/действий/наблюдений. +Заключение: Окончательный ответ. + +**Аргументы:** + +`question`: Вопрос или инструкция пользователя. +`user`: Идентификатор пользователя. +`collection`: Идентификатор коллекции для хранения данных о происхождении. +`state`: Необязательный словарь состояния для разговоров с сохранением состояния. +`group`: Необязательный идентификатор группы для многопользовательских контекстов. +`history`: Необязательная история разговоров в виде списка словарей сообщений. +`**kwargs`: Дополнительные параметры, передаваемые службе агента. +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: Фрагменты агента и события, связанные с происхождением. + +**Пример:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Запрос фрагментов документов с использованием семантического сходства. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`user`: Идентификатор пользователя/пространства ключей +`collection`: Идентификатор коллекции +`limit`: Максимальное количество результатов (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, передаваемые сервису + +**Возвращает:** dict: Результаты запроса с идентификаторами фрагментов соответствующих фрагментов документов + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Выполнение запроса RAG на основе документов с возможностью опциональной потоковой передачи. + +Использует векторные представления для поиска релевантных фрагментов документов, а затем генерирует +ответ с использованием LLM. Режим потоковой передачи предоставляет результаты постепенно. + +**Аргументы:** + +`query`: Запрос на естественном языке +`user`: Идентификатор пользователя/пространства +`collection`: Идентификатор коллекции +`doc_limit`: Максимальное количество фрагментов документов для извлечения (по умолчанию: 10) +`streaming`: Включить режим потоковой передачи (по умолчанию: False) +`**kwargs`: Дополнительные параметры, передаваемые службе + +**Возвращает:** Union[str, Iterator[str]]: Полный ответ или поток текстовых фрагментов + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Выполнение запроса RAG на основе документов с поддержкой объяснимости. + +Передает как фрагменты контента (RAGChunk), так и события, связанные с происхождением (ProvenanceEvent). +События, связанные с происхождением, содержат URI, которые можно получить с помощью ExplainabilityClient, +чтобы получить подробную информацию о том, как был сгенерирован ответ. + +Трассировка RAG для документа состоит из: +Вопрос: Запрос пользователя +Исследование: Фрагменты, извлеченные из хранилища документов (chunk_count) +Синтез: Сгенерированный ответ + +**Аргументы:** + +`query`: Запрос на естественном языке +`user`: Идентификатор пользователя/пространства ключей +`collection`: Идентификатор коллекции +`doc_limit`: Максимальное количество фрагментов документов для извлечения (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, передаваемые службе +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Фрагменты контента и события, связанные с происхождением + +**Пример:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +Создание векторных представлений для одного или нескольких текстов. + +**Аргументы:** + +`texts`: Список входных текстов для создания векторных представлений. +`**kwargs`: Дополнительные параметры, передаваемые сервису. + +**Возвращает:** dict: Ответ, содержащий векторы (один набор для каждого входного текста). + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Запрос сущностей графа знаний с использованием семантического сходства. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`user`: Идентификатор пользователя/пространства +`collection`: Идентификатор коллекции +`limit`: Максимальное количество результатов (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, передаваемые сервису + +**Возвращает:** dict: Результаты запроса с похожими сущностями + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Выполнение запроса RAG на основе графа с возможностью потоковой передачи. + +Использует структуру графа знаний для поиска релевантного контекста, а затем генерирует +ответ с использованием LLM. Режим потоковой передачи предоставляет результаты постепенно. + +**Аргументы:** + +`query`: Запрос на естественном языке +`user`: Идентификатор пользователя/пространства +`collection`: Идентификатор коллекции +`max_subgraph_size`: Максимальное общее количество троек в подграфе (по умолчанию: 1000) +`max_subgraph_count`: Максимальное количество подграфов (по умолчанию: 5) +`max_entity_distance`: Максимальная глубина обхода (по умолчанию: 3) +`streaming`: Включить режим потоковой передачи (по умолчанию: False) +`**kwargs`: Дополнительные параметры, передаваемые службе + +**Возвращает:** Union[str, Iterator[str]]: Полный ответ или поток текстовых фрагментов + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Выполнение запроса RAG на основе графов с поддержкой объяснимости. + +Передает как фрагменты контента (RAGChunk), так и события, связанные с происхождением (ProvenanceEvent). +События, связанные с происхождением, содержат URI, которые можно получить с помощью ExplainabilityClient, +чтобы получить подробную информацию о том, как был сгенерирован ответ. + +**Аргументы:** + +`query`: Запрос на естественном языке +`user`: Идентификатор пользователя/пространства +`collection`: Идентификатор коллекции +`max_subgraph_size`: Максимальное общее количество троек в подграфе (по умолчанию: 1000) +`max_subgraph_count`: Максимальное количество подграфов (по умолчанию: 5) +`max_entity_distance`: Максимальная глубина обхода (по умолчанию: 3) +`**kwargs`: Дополнительные параметры, передаваемые службе +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Фрагменты контента и события, связанные с происхождением + +**Пример:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +Запустить инструмент протокола контекста модели (MCP). + +**Аргументы:** + +`name`: Имя/идентификатор инструмента +`parameters`: Словарь параметров инструмента +`**kwargs`: Дополнительные параметры, передаваемые сервису + +**Возвращает:** dict: Результат выполнения инструмента + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Выполнение шаблона запроса с возможностью потоковой передачи. + +**Аргументы:** + +`id`: Идентификатор шаблона запроса +`variables`: Словарь, содержащий соответствия между именами переменных и их значениями +`streaming`: Включить режим потоковой передачи (по умолчанию: False) +`**kwargs`: Дополнительные параметры, передаваемые службе + +**Возвращает:** Union[str, Iterator[str]]: Полный ответ или поток текстовых фрагментов + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Запрос данных строк с использованием семантического сходства по индексированным полям. + +Находит строки, значения индексированных полей которых семантически схожи с +входным текстом, используя векторные представления. Это обеспечивает нечеткое/семантическое сопоставление +структурированных данных. + +**Аргументы:** + +`text`: Текст запроса для семантического поиска +`schema_name`: Имя схемы для поиска +`user`: Идентификатор пользователя/пространства ключей (по умолчанию: "trustgraph") +`collection`: Идентификатор коллекции (по умолчанию: "default") +`index_name`: Необязательное имя индекса для фильтрации поиска по определенному индексу +`limit`: Максимальное количество результатов (по умолчанию: 10) +`**kwargs`: Дополнительные параметры, передаваемые службе + +**Возвращает:** dict: Результаты запроса, содержащие соответствия, включая index_name, index_value, text и score + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +Выполнение запроса GraphQL к структурированным строкам. + +**Аргументы:** + +`query`: Строка запроса GraphQL +`user`: Идентификатор пользователя/пространства ключей +`collection`: Идентификатор коллекции +`variables`: Необязательный словарь переменных запроса +`operation_name`: Необязательное имя операции для документов с несколькими операциями +`**kwargs`: Дополнительные параметры, передаваемые службе + +**Возвращает:** dict: Ответ GraphQL с данными, ошибками и/или расширениями + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +Выполнить завершение текста с возможностью потоковой передачи. + +**Аргументы:** + +`system`: Системная подсказка, определяющая поведение ассистента. +`prompt`: Подсказка/вопрос пользователя. +`streaming`: Включить режим потоковой передачи (по умолчанию: False). +`**kwargs`: Дополнительные параметры, передаваемые сервису. + +**Возвращает:** Union[str, Iterator[str]]: Полный ответ или поток текстовых фрагментов. + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +Запрос троек графа знаний с использованием сопоставления с образцом. + +**Аргументы:** + +`s`: Фильтр по субъекту - строка URI, словарь терминов или None для подстановки +`p`: Фильтр по предикату - строка URI, словарь терминов или None для подстановки +`o`: Фильтр по объекту - строка URI/литерала, словарь терминов или None для подстановки +`g`: Фильтр по именованному графу - строка URI или None для всех графов +`user`: Идентификатор пользователя/пространства ключей (необязательно) +`collection`: Идентификатор коллекции (необязательно) +`limit`: Максимальное количество возвращаемых результатов (по умолчанию: 100) +`**kwargs`: Дополнительные параметры, передаваемые сервису + +**Возвращает:** List[Dict]: Список соответствующих троек в формате передачи данных + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +Запрос троек знаний с использованием потоковых пакетов. + +Возвращает пакеты троек по мере их поступления, что сокращает время получения первого результата +и объем используемой памяти для больших наборов результатов. + +**Аргументы:** + +`s`: Фильтр по субъекту - URI строка, словарь терминов или None для подстановки +`p`: Фильтр по предикату - URI строка, словарь терминов или None для подстановки +`o`: Фильтр по объекту - URI/строка литерала, словарь терминов или None для подстановки +`g`: Фильтр по именованному графу - URI строка или None для всех графов +`user`: Идентификатор пользователя/пространства ключей (необязательно) +`collection`: Идентификатор коллекции (необязательно) +`limit`: Максимальное количество возвращаемых результатов (по умолчанию: 100) +`batch_size`: Количество троек в пакете (по умолчанию: 20) +`**kwargs`: Дополнительные параметры, передаваемые сервису +`Yields`: +`List[Dict]`: Пакеты троек в формате передачи данных + +**Пример:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +Асинхронный WebSocket клиент + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None)` + +Инициализация объекта `self`. См. `help(type(self))` для получения точного определения. + +### `aclose(self)` + +Закрытие WebSocket соединения + +### `flow(self, flow_id: str)` + +Получение асинхронной реализации для операций с WebSocket + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +Экземпляр асинхронного потока WebSocket. + +### Методы + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +Инициализация объекта `self`. См. `help(type(self))` для получения точного определения. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +Агент с опциональной потоковой передачей. + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +Документирование RAG с опциональной потоковой передачей. + +### `embeddings(self, texts: list, **kwargs)` + +Генерация текстовых векторных представлений. + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +Запрос векторных представлений графа для семантического поиска. + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +Граф RAG с опциональной потоковой передачей. + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +Выполнение инструмента MCP. + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +Выполнение запроса с опциональной потоковой передачей. + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +Запрос векторных представлений строк для семантического поиска структурированных данных. + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +Запрос GraphQL для структурированных строк. + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +Автозаполнение текста с опциональной потоковой передачей. + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +Запрос шаблона триплетов. + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +Создание словаря Term в формате двоичных данных из значения. + +Правила автоматического определения (когда `term_type` равен None): + Уже является словарем с ключом 't' -> возвращается как есть (уже является Term). + Начинается с http://, https://, urn: -> IRI. + Ограничено символами < (например, ) -> IRI (символы угловых скобок удаляются). + Все остальное -> литерал. + +**Аргументы:** + +`value`: Значение Term (строка, словарь или None). +`term_type`: Один из вариантов: 'iri', 'literal' или None для автоматического определения. +`datatype`: Тип данных для литеральных объектов (например, xsd:integer). +`language`: Языковой тег для литеральных объектов (например, en). + +**Возвращает:** dict: Словарь Term в формате двоичных данных или None, если значение равно None. + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +Клиент для синхронных массовых операций импорта/экспорта. + +Обеспечивает эффективную массовую передачу данных через WebSocket для больших наборов данных. +Оборачивает асинхронные операции WebSocket в синхронные генераторы для удобства использования. + +Примечание: Для полной поддержки асинхронности используйте AsyncBulkClient. + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Инициализация синхронного клиента для массовых операций. + +**Аргументы:** + +`url`: Базовый URL для API TrustGraph (HTTP/HTTPS будут преобразованы в WS/WSS) +`timeout`: Время ожидания WebSocket в секундах +`token`: Необязательный токен для аутентификации + +### `close(self) -> None` + +Закрытие соединений + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Массовый экспорт векторных представлений документов из потока. + +Эффективно загружает все векторные представления фрагментов документов через потоковую передачу WebSocket. + +**Аргументы:** + +`flow`: Идентификатор потока +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Возвращает:** Iterator[Dict[str, Any]]: Поток словарей векторных представлений + +**Пример:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Массовый экспорт контекстов сущностей из потока. + +Эффективно загружает всю информацию о контексте сущностей через потоковую передачу WebSocket. + +**Аргументы:** + +`flow`: Идентификатор потока +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Возвращает:** Iterator[Dict[str, Any]]: Поток словарей контекста + +**Пример:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Массовый экспорт векторных представлений графов из потока. + +Эффективно загружает все векторные представления сущностей графа через потоковую передачу WebSocket. + +**Аргументы:** + +`flow`: Идентификатор потока +`**kwargs`: Дополнительные параметры (зарезервировано для будущих версий) + +**Возвращает:** Iterator[Dict[str, Any]]: Поток словарей векторных представлений + +**Пример:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +Массовый экспорт RDF-тройств из потока. + +Эффективно загружает все тройства через потоковую передачу WebSocket. + +**Аргументы:** + +`flow`: Идентификатор потока +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Возвращает:** Iterator[Triple]: Поток объектов Triple + +**Пример:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Импорт большого количества векторных представлений документов в поток. + +Эффективная загрузка векторных представлений фрагментов документов через потоковую передачу WebSocket +для использования в запросах RAG (Retrieval-Augmented Generation) к документам. + +**Аргументы:** + +`flow`: Идентификатор потока +`embeddings`: Итератор, возвращающий словари векторных представлений +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Пример:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Импорт большого количества сущностей в контекст потока. + +Эффективная загрузка информации о контексте сущностей через потоковую передачу WebSocket. +Контексты сущностей предоставляют дополнительный текстовый контекст о сущностях графа +для повышения производительности RAG. + +**Аргументы:** + +`flow`: Идентификатор потока +`contexts`: Итератор, возвращающий словари контекста +`metadata`: Словарь метаданных с id, метаданными, пользователем, коллекцией +`batch_size`: Количество контекстов в пакете (по умолчанию 100) +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Пример:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Импорт графовых представлений в поток. + +Эффективная загрузка представлений графовых сущностей через потоковую передачу WebSocket. + +**Аргументы:** + +`flow`: Идентификатор потока +`embeddings`: Итератор, возвращающий словари представлений +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Пример:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Импорт структурированных строк в поток. + +Эффективная загрузка структурированных данных в виде строк через потоковую передачу WebSocket +для использования в запросах GraphQL. + +**Аргументы:** + +`flow`: Идентификатор потока +`rows`: Итератор, возвращающий словари строк +`**kwargs`: Дополнительные параметры (зарезервированы для будущего использования) + +**Пример:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Импорт большого количества RDF-тройств в поток. + +Эффективно загружает большое количество тройств через потоковую передачу WebSocket. + +**Аргументы:** + +`flow`: Идентификатор потока +`triples`: Итератор, возвращающий объекты Triple +`metadata`: Словарь метаданных с id, метаданными, пользователем, коллекцией +`batch_size`: Количество тройств в пакете (по умолчанию 100) +`**kwargs`: Дополнительные параметры (зарезервировано для будущего использования) + +**Пример:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +Клиент для асинхронных пакетных операций. + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Инициализация объекта `self`. См. `help(type(self))` для получения точного определения. + +### `aclose(self) -> None` + +Закрытие соединений. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Пакетный экспорт векторных представлений документов через WebSocket. + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Пакетный экспорт контекстов сущностей через WebSocket. + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Пакетный экспорт векторных представлений графа через WebSocket. + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +Пакетный экспорт троек через WebSocket. + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Пакетный импорт векторных представлений документов через WebSocket. + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Пакетный импорт контекстов сущностей через WebSocket. + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Пакетный импорт векторных представлений графа через WebSocket. + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Пакетный импорт строк через WebSocket. + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +Пакетный импорт троек через WebSocket. + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +Клиент для синхронных метрик + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + +### `get(self) -> str` + +Получение метрик Prometheus в виде текста + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +Асинхронный клиент для работы с метриками. + +### Методы + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Инициализация объекта. См. help(type(self)) для получения точного определения. + +### `aclose(self) -> None` + +Закрытие соединений. + +### `get(self) -> str` + +Получение метрик Prometheus в текстовом формате. + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +Клиент для получения сущностей объяснимости с обеспечением конечной согласованности. + +Использует обнаружение состояния покоя: получение, ожидание, повторное получение, сравнение. +Если результаты одинаковы, данные стабильны. + +### Методы + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +Инициализация клиента объяснимости. + +**Аргументы:** + +`flow_instance`: Экземпляр SocketFlowInstance для запроса троек. +`retry_delay`: Задержка между повторными попытками в секундах (по умолчанию: 0.2). +`max_retries`: Максимальное количество повторных попыток (по умолчанию: 10). + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +Определяет, является ли сессия типом GraphRAG или Agent. + +**Аргументы:** + +`session_uri`: URI сессии/вопроса. +`graph`: Именованный граф. +`user`: Идентификатор пользователя/пространства ключей. +`collection`: Идентификатор коллекции. + +**Возвращает:** "graphrag" или "agent". + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Получает полный трассировочный файл Agent, начиная с URI сессии. + +Отслеживает цепочку происхождения: Вопрос -> Анализ(ы) -> Вывод. + +**Аргументы:** + +`session_uri`: URI сессии/вопроса Agent. +`graph`: Именованный граф (по умолчанию: urn:graph:retrieval). +`user`: Идентификатор пользователя/пространства ключей. +`collection`: Идентификатор коллекции. +`api`: Экземпляр TrustGraph Api для доступа к библиотекарю (необязательно). +`max_content`: Максимальная длина содержимого для вывода. + +**Возвращает:** Словарь с вопросом, итерациями (список Анализов), сущностями вывода. + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Получает полный трассировочный файл DocumentRAG, начиная с URI вопроса. + +Отслеживает цепочку происхождения: + Вопрос -> Базирование -> Исследование -> Синтез. + +**Аргументы:** + +`question_uri`: URI сущности вопроса. +`graph`: Именованный граф (по умолчанию: urn:graph:retrieval). +`user`: Идентификатор пользователя/пространства ключей. +`collection`: Идентификатор коллекции. +`api`: Экземпляр TrustGraph Api для доступа к библиотекарю (необязательно). +`max_content`: Максимальная длина содержимого для синтеза. + +**Возвращает:** Словарь с вопросом, базированием, исследованием, сущностями синтеза. + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +Получает содержимое из библиотеки по URI документа. + +**Аргументы:** + +`document_uri`: URI документа в библиотеке. +`api`: Экземпляр TrustGraph Api для доступа к библиотеке. +`user`: Идентификатор пользователя для библиотеки. +`max_content`: Максимальная длина содержимого для возврата. + +**Возвращает:** Содержимое документа в виде строки. + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +Получает сущность выбора ребра (используется Focus). + +**Аргументы:** + +`uri`: URI выбора ребра. +`graph`: Именованный граф для запроса. +`user`: Идентификатор пользователя/пространства ключей. +`collection`: Идентификатор коллекции. + +**Возвращает:** EdgeSelection или None, если не найдено. + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +Получение сущности объяснимости по URI с обработкой обеспечения согласованности. + +Использует обнаружение состояния покоя: +1. Получение троек для URI +2. Если результатов нет, повторить попытку +3. Если результатов больше нуля, подождать и получить снова +4. Если результаты совпадают, данные стабильны - разобрать и вернуть +5. Если результаты отличаются, данные все еще записываются - повторить попытку + +**Аргументы:** + +`uri`: URI сущности для получения +`graph`: Именованный граф для запроса (например, "urn:graph:retrieval") +`user`: Идентификатор пользователя/пространства имен +`collection`: Идентификатор коллекции + +**Возвращает:** Подкласс ExplainEntity или None, если не найдено + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +Получение сущности Focus и всех ее выбранных ребер. + +**Аргументы:** + +`uri`: URI сущности Focus +`graph`: Именованный граф для запроса +`user`: Идентификатор пользователя/пространства имен +`collection`: Идентификатор коллекции + +**Возвращает:** Focus с заполненными edge_selections или None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Получение полной трассировки GraphRAG, начиная с URI вопроса. + +Отслеживает цепочку происхождения: Вопрос -> Основание -> Исследование -> Focus -> Синтез + +**Аргументы:** + +`question_uri`: URI сущности вопроса +`graph`: Именованный граф (по умолчанию: urn:graph:retrieval) +`user`: Идентификатор пользователя/пространства имен +`collection`: Идентификатор коллекции +`api`: Экземпляр TrustGraph Api для доступа к библиотеке (необязательно) +`max_content`: Максимальная длина содержимого для синтеза + +**Возвращает:** Словарь с сущностями вопроса, основания, исследования, Focus и синтеза + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +Перечисление всех сессий объяснимости (вопросов) в коллекции. + +**Аргументы:** + +`graph`: Именованный граф (по умолчанию: urn:graph:retrieval) +`user`: Идентификатор пользователя/пространства имен +`collection`: Идентификатор коллекции +`limit`: Максимальное количество сессий для возврата + +**Возвращает:** Список сущностей Question, отсортированный по времени (самые новые в начале) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +Разрешение меток для всех компонентов тройки ребра. + +**Аргументы:** + +`edge`: Словарь с ключами "s", "p", "o" +`user`: Идентификатор пользователя/пространства имен +`collection`: Идентификатор коллекции + +**Возвращает:** Кортеж (s_label, p_label, o_label) + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +Разрешение rdfs:label для URI с использованием кэширования. + +**Аргументы:** + +`uri`: URI, для которого необходимо получить метку +`user`: Идентификатор пользователя/пространства имен +`collection`: Идентификатор коллекции + +**Возвращает:** Метка, если найдена, в противном случае сам URI + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +Базовый класс для сущностей, обеспечивающих понятность. + +**Поля:** + +`uri`: +`entity_type`: + +### Методы + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +Инициализация объекта self. См. help(type(self)) для получения точного определения. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +Вопрос (Question entity) - запрос пользователя, который инициировал сессию. + +**Поля (Fields):** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### Методы (Methods) + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +Объект исследования - ребра/фрагменты, извлеченные из хранилища знаний. + +**Поля:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### Методы + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +Объект фокусировки - выбранные ребра с использованием логического вывода на основе больших языковых моделей (только для GraphRAG). + +**Поля:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### Методы + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +Синтетическая сущность - окончательный ответ. + +**Поля:** + +`uri`: +`entity_type`: +`document`: + +### Методы + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +Аналитическая сущность - один цикл мышления/действия/наблюдения (только для Агента). + +**Поля:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### Методы + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +Заключительная сущность - окончательный ответ (только для агента). + +**Поля:** + +`uri`: +`entity_type`: +`document`: + +### Методы + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +Выбранный ребро с обоснованием из шага GraphRAG Focus. + +**Поля:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### Методы + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +Преобразование троек в формате "wire" в кортежи (s, p, o). + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +Извлечение значения из словаря Term в формате "wire". + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +Тройка RDF, представляющая утверждение графа знаний. + +**Поля:** + +`s`: +`p`: +`o`: + +### Методы + +### `__init__(self, s: str, p: str, o: str) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Создает новый строковый объект из заданного объекта. Если указаны параметры encoding или +errors, то объект должен предоставлять буфер данных, который будет декодирован с использованием указанной кодировки и обработчика ошибок. +В противном случае возвращается результат object.__str__() (если определен) +или repr(object). +encoding по умолчанию - 'utf-8'. +errors по умолчанию - 'strict'. + + +### Методы + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Создает новый строковый объект из заданного объекта. Если указаны параметры encoding или +errors, то объект должен предоставлять буфер данных, который будет декодирован с использованием указанной кодировки и обработчика ошибок. +В противном случае возвращается результат object.__str__() (если определен) +или repr(object). +encoding по умолчанию - 'utf-8'. +errors по умолчанию - 'strict'. + + +### Методы + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +Идентификатор конфигурационного ключа. + +**Поля:** + +`type`: +`key`: + +### Методы + +### `__init__(self, type: str, key: str) -> None` + +Инициализация объекта self. См. help(type(self)) для получения точного определения. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +Пара ключ-значение конфигурации. + +**Поля:** + +`type`: +`key`: +`value`: + +### Методы + +### `__init__(self, type: str, key: str, value: str) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +Метаданные для документа в библиотеке. + +**Атрибуты:** + +`parent_id: Parent document ID for child documents (empty for top`: level docs) + +**Поля:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### Методы + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +Метаданные для активной задачи обработки документа. + +**Поля:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### Методы + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +Метаданные для набора данных. + +Коллекции обеспечивают логическую группировку и изоляцию для документов и +данных графа знаний. + +**Атрибуты:** + +`name: Human`: читаемое имя коллекции + +**Поля:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### Методы + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +Базовый класс для потоковой передачи фрагментов ответа. + +Используется для операций потоковой передачи на основе WebSocket, когда ответы доставляются +постепенно по мере их генерации. + +**Поля:** + +`content`: +`end_of_message`: + +### Методы + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +Инициализация объекта self. См. help(type(self)) для получения точного определения. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +Обоснование/процесс мышления агента. + +Представляет собой внутренние этапы рассуждений или планирования агента во время выполнения. +Эти фрагменты показывают, как агент мыслит о проблеме. + +**Поля:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Методы + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +Инициализация self. См. help(type(self)) для получения точного определения. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +Фрагмент наблюдения за выполнением инструмента агента. + +Представляет собой результат или наблюдение, полученное в результате выполнения инструмента или действия. +Эти фрагменты показывают, что агент узнал, используя инструменты. + +**Поля:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Методы + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +Инициализация self. См. help(type(self)) для получения точной сигнатуры. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +Заключительный фрагмент ответа агента. + +Представляет собой окончательный ответ агента пользователю на его запрос после завершения +процесса рассуждений и использования инструментов. + +**Атрибуты:** + +`chunk_type: Always "final`: answer" + +**Поля:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### Методы + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +Инициализация self. См. help(type(self)) для получения точной сигнатуры. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +Поток данных RAG (Retrieval-Augmented Generation). + +Используется для потоковой передачи ответов от графовых систем RAG, систем RAG на основе документов, для завершения текста, +и других генеративных сервисов. + +**Поля:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### Методы + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +Инициализация объекта self. См. help(type(self)) для получения точного определения. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +Событие, связанное с происхождением, для обеспечения понятности. + +Генерируется во время запросов GraphRAG, когда включен режим объяснения. +Каждое событие представляет узел происхождения, созданный во время обработки запроса. + +**Поля:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### Методы + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +Инициализация self. См. help(type(self)) для получения точной сигнатуры. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +Возникает при возникновении ошибок протокола WebSocket. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +Базовый класс для всех ошибок сервиса TrustGraph. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +Ошибка сервиса агента + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +Ошибка сервиса конфигурации + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +Ошибка извлечения документов RAG. + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +Ошибка управления потоком + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +Ошибка API Gateway + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +Ошибка извлечения данных из графа RAG. + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +Ошибка сервиса LLM + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +Ошибка загрузки данных + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +Ошибка поиска/просмотра. + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +Ошибка сервиса обработки запросов на естественном языке. + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +Ошибка сервиса запросов данных. + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +Ошибка обработки запроса + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +Ошибка сервиса структурированных запросов. + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +Неожиданная/неизвестная ошибка + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +Базовый класс для всех ошибок сервиса TrustGraph. + + +-- diff --git a/docs/python-api.sw.md b/docs/python-api.sw.md new file mode 100644 index 00000000..3790adcf --- /dev/null +++ b/docs/python-api.sw.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "Marejeleo ya API ya Python ya TrustGraph" +parent: "Swahili (Beta)" +--- + +# Marejeleo ya API ya Python ya TrustGraph + +> **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. + +## Ufungaji + +```bash +pip install trustgraph +``` + +## Kuanza Haraka + +Madarasa na aina zote zinaingizwa kutoka kwenye kifurushi cha `trustgraph.api`: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## Jina la Yaliyomo + +### Msingi + +[Api](#api) + +### Wateja wa Flow + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### Wateja wa WebSocket + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### Operesheni za Kiasi + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### Vipimo + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### Aina za Data + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### Vizuizi + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +Mteja mkuu wa API ya TrustGraph kwa operesheni za synchronous na asynchronous. + +Darasa hili hutoa ufikiaji kwa huduma zote za TrustGraph, pamoja na usimamizi wa mtiririko, +operesheni za grafu ya maarifa, usindikaji wa hati, maswali ya RAG, na zaidi. Inasaidia +mifumo ya mawasiliano ya msingi wa REST na WebSocket. + +Mteja unaweza kutumika kama meneja wa muktadha kwa usafi wa kiotomatiki wa rasilimali: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### Mbinu + +### `__aenter__(self)` + +Ingia katika meneja wa muktadha wa asinkroni. + +### `__aexit__(self, *args)` + +Ondoka katika meneja wa muktadha wa asinkroni na ufungue miunganisho. + +### `__enter__(self)` + +Ingia katika meneja wa muktadha wa sinkroni. + +### `__exit__(self, *args)` + +Ondoka katika meneja wa muktadha wa sinkroni na ufungue miunganisho. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +Anzisha mteja wa API ya TrustGraph. + +**Vigezo:** + +`url`: URL ya msingi kwa API ya TrustGraph (kiwango chachilia: "http://localhost:8088/"") +`timeout`: Muda wa kikao wa ombi katika sekunde (kiwango chachilia: 60) +`token`: Tokeni ya kuhudhuria ya hiari kwa uthibitishaji + +**Mfano:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +Funga miunganisho yote ya mteja isiyo ya kawaida. + +Njia hii inafunga miunganisho ya WebSocket isiyo ya kawaida, operesheni kubwa, na miunganisho ya mtiririko. +Inaitwa kiotomatiki wakati wa kutoka katika meneja wa muktadha usio wa kawaida. + +**Mfano:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +Pata mteja wa operesheni za wingi zisizo za moja kwa moja. + +Hutoa operesheni za uagizaji/uangamizi za wingi kwa mtindo wa async/await kupitia WebSocket +kwa ajili ya usimamizi bora wa data kubwa. + +**Inarudisha:** AsyncBulkClient: Mteja wa operesheni za wingi zisizo za moja kwa moja. + +**Mfano:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +Pata mteja wa mtiririko (flow) unaotumia REST na unaoweza kufanya kazi bila kusubiri. + +Hutoa ufikiaji wa operesheni za mtiririko kwa mtindo wa async/await. Hii inapendelewa +kwa programu na mifumo ya Python inayotumia async (FastAPI, aiohttp, n.k.). + +**Inarudisha:** AsyncFlow: Mteja wa mtiririko (flow) usiofanya kazi bila kusubiri. + +**Mfano:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +Pata mteja wa metriki zisizo za moja kwa moja. + +Hutoa ufikiaji wa mtindo wa async/await kwa metriki za Prometheus. + +**Inarudisha:** AsyncMetrics: Mteja wa metriki zisizo za moja kwa moja. + +**Mfano:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +Pata mteja wa WebSocket usio na utaratibu kwa operesheni za utiririshaji. + +Hutoa ufikiaji wa WebSocket wa aina ya async/await pamoja na usaidizi wa utiririshaji. +Hii ndiyo njia inayopendekezwa kwa utiririshaji usio na utaratibu katika Python. + +**Inarudisha:** AsyncSocketClient: Mteja wa WebSocket usio na utaratibu. + +**Mfano:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +Pata mteja wa shughuli za wingi za moja kwa moja kwa ajili ya uagizaji/utoaji. + +Shughuli za wingi huruhusu uhamishaji wa ufanisi wa data kubwa kupitia muunganisho wa WebSocket, +ikiwa ni pamoja na vitu vitatu, maandamano, muktadha wa vitu, na vitu. + +**Inarudisha:** BulkClient: Mteja wa shughuli za wingi za moja kwa moja. + +**Mfano:** + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +Funga miunganisho yote ya mteja ya wakati huo. + +Njia hii inafunga miunganisho ya WebSocket na miunganisho ya operesheni kubwa. +Inaitwa kiotomatiki wakati wa kutoka katika meneja wa muktadha. + +**Mfano:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +Pata mteja wa Collection kwa ajili ya kusimamia makusanyo ya data. + +Makusanyo huandaa hati na data ya mfumo wa maarifa katika +vikundi vya mantiki kwa ajili ya kutenganisha na udhibiti wa ufikiaji. + +**Inarudisha:** Collection: Mteja wa usimamizi wa Collection + +**Mfano:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +Pata mteja wa Config kwa ajili ya kusimamia mipangilio. + +**Inarudisha:** Config: Mteja wa usimamizi wa mipangilio. + +**Mfano:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +Pata programu (client) ya Flow kwa ajili ya kusimamia na kuingiliana na michakato. + +Michakato (Flows) ni vitengo vikuu vya utekelezaji katika TrustGraph, ikitoa ufikiaji kwa +huduma kama vile wakala, maswali ya RAG, maandamano, na usindikaji wa nyaraka. + +**Inarudisha:** Flow: Programu ya usimamizi wa Flow. + +**Mfano:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +Pata mteja wa Knowledge kwa ajili ya kusimamia msingi wa grafu ya maarifa. + +**Inarudisha:** Mteja wa usimamizi wa grafu ya maarifa: Knowledge + +**Mfano:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +Pata mteja wa Maktaba kwa usimamizi wa nyaraka. + +Maktaba hutoa uhifadhi wa nyaraka, usimamizi wa metadata, na +uratibu wa mtiririko wa kazi. + +**Inarudisha:** Library: Mteja wa usimamizi wa maktaba ya nyaraka. + +**Mfano:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +Pata mteja wa metriki wa moja kwa moja kwa ajili ya ufuatiliaji. + +Hupata metriki zilizofunganishwa kwa muundo wa Prometheus kutoka kwa huduma ya TrustGraph +kwa ajili ya ufuatiliaji na uwezeshaji. + +**Inarudisha:** Metri: Mteja wa metriki wa moja kwa moja + +**Mfano:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +Fanya ombi la API ya REST ya kiwango cha chini. + +Njia hii hutumika hasa kwa matumizi ya ndani, lakini inaweza kutumika kwa ufikiaji wa moja kwa moja +wa API wakati inahitajika. + +**Vigezo:** + +`path`: Njia ya mwisho ya API (kulingana na URL ya msingi) +`request`: Takwimu ya ombi kama kamusi + +**Inarudisha:** dict: Kijisimu cha majibu + +**Inatirisha:** + +`ProtocolException`: Ikiwa hali ya majibu si 200 au majibu hayana umbizo la JSON +`ApplicationException`: Ikiwa majibu yana kosa + +**Mfano:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +Pata mteja wa WebSocket wa aina ya moja kwa shughuli za utiririshaji. + +Miunganisho ya WebSocket hutoa utiifu wa data kwa majibu ya muda halisi +kutoka kwa wakala, maswali ya RAG, na kukamilisha maandishi. Njia hii inarudisha +kifungashio cha aina ya moja kilichozunguka itifaki ya WebSocket. + +**Inarudisha:** SocketClient: Mteja wa WebSocket wa aina ya moja. + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +Mteja wa usimamizi wa mtiririko kwa operesheni za muundo na mfano wa mtiririko. + +Darasa hili hutoa mbinu za kusimamia muundo wa mtiririko (vipengele) na +mifano ya mtiririko (mitiririko inayoendelea). Vipengele vinafafanua muundo na +vigezo vya mitiririko, wakati mifano inawakilisha mitiririko inayofanya kazi ambayo +inaweza kutekeleza huduma. + +### Mbinu + +### `__init__(self, api)` + +Anzisha mteja wa mtiririko. + +**Majadiliano:** + +`api`: Eneo la awali la Api kwa kutuma ombi. + +### `delete_blueprint(self, blueprint_name)` + +Futa muundo wa mtiririko. + +**Majadiliano:** + +`blueprint_name`: Jina la muundo kufutwa. + +**Mfano:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +Pata ufafanuzi wa mfano unaoendelea. + +**Vigezo:** + +`id`: Kitambulisho cha mfano. + +**Inarudisha:** dict: Ufafanuzi wa mfano. + +**Mfano:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +Pata ufafanuzi wa mpango (blueprint) kwa jina. + +**Vigezo:** + +`blueprint_name`: Jina la mpango (blueprint) ambao unataka kupata + +**Inarudisha:** dict: Ufafanuzi wa mpango (blueprint) kama kamusi. + +**Mfano:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +Pata FlowInstance ili kutekeleza shughuli kwenye mtiririko maalum. + +**Vigezo:** + +`id`: Kitambulisho cha mtiririko (cha kawaida: "default") + +**Inarudisha:** FlowInstance: Mtiririko wa huduma kwa shughuli. + +**Mfano:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +Orodha ya matukio yote yanayoendelea. + +**Inarudisha:** list[str]: Orodha ya kitambulisho cha matukio. + +**Mfano:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +Orodha ya mipango yote ya mtiririko inayopatikana. + +**Inarudisha:** list[str]: Orodha ya majina ya mipango + +**Mfano:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +Kuunda au kusasisha mpango wa mtiririko. + +**Vigezo:** + +`blueprint_name`: Jina la mpango +`definition`: Kamusi ya ufafanuzi wa mpango + +**Mfano:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +Fanya ombi la API katika eneo maalum. + +**Vigezo:** + +`path`: Ongeza ya hiari kwa njia za mwisho za eneo. +`request`: Kamusi ya data ya ombi. + +**Inarudisha:** dict: Kitu kinachojibu. + +**Inayotokea:** + +`RuntimeError`: Ikiwa parameter ya ombi haijatolewa. + +### `start(self, blueprint_name, id, description, parameters=None)` + +Anza eneo jipya kutoka kwa mpango. + +**Vigezo:** + +`blueprint_name`: Jina la mpango ambao utaanzishwa. +`id`: Kitambulisho cha kipekee kwa eneo. +`description`: Maelezo ambayo yanaweza kueleweka. +`parameters`: Vigezo vya hiari. + +**Mfano:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +Kusimamisha mfumo unaoendelea. + +**Vigezo:** + +`id`: Kitambulisho cha mfumo unaoendelea ili kusimamishwa. + +**Mfano:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +Mteja wa mfumo (flow) kwa kutekeleza huduma kwenye mfumo maalum. + +Darasa hili hutoa ufikiaji kwa huduma zote za TrustGraph, pamoja na: +Kukamilisha maandishi na uwekaji wa data (embeddings) +Utendaji wa wakala (agent) pamoja na usimamizi wa hali (state) +Ufuatiliaji wa maswali (queries) ya RAG kwa grafu na nyaraka +Utendaji wa grafu ya maarifa (triples, vitu) +Kupakua na kuchakata nyaraka +Ubadilishaji wa lugha ya asili kuwa swali la GraphQL +Uchambuzi wa data iliyopangwa na utambuzi wa muundo (schema) +Utendaji wa zana ya MCP +Ubunifu wa kigezo cha swali (prompt templating) + +Huduma zinapatikana kupitia mfumo unaoendelea (flow instance) unaotambulika na kitambulisho (ID). + +### Mbinu (Methods) + +### `__init__(self, api, id)` + +Anzisha FlowInstance. + +**Majadilisho:** + +`api`: Mteja wa mfumo (flow) wa juu. +`id`: Kitambulisho cha mfumo unaoendelea (flow instance). + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +Tekeleza utendaji wa wakala (agent) pamoja na uwezo wa kufikiri na kutumia zana. + +Wakala wanaweza kufanya utafakari wa hatua nyingi, kutumia zana, na kudumisha mazungumzo +hali katika mwingiliano. Hii ni toleo la moja kwa moja (synchronous) lisilo na utiririshaji (non-streaming). + +**Majadilisho:** + +`question`: Swali au maagizo ya mtumiaji. +`user`: Kitambulisho cha mtumiaji (default: "trustgraph") +`state`: Kamusi ya hali (state) ya hiari kwa mazungumzo yenye hali. +`group`: Kitambulisho cha kikundi cha hiari kwa muktadha wa watumiaji wengi. +`history`: Historia ya mazungumzo ya hiari kama orodha ya maneno ya kamusi. + +**Inarudisha:** string: Jibu la mwisho la wakala. + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +Gundua aina ya data ya sampuli ya data iliyohifadhiwa. + +**Vigezo:** + +`sample`: Sampuli ya data kuchanganua (yaliyomo katika maandishi) + +**Inarudisha:** kamusi yenye aina_iliyogunduliwa, uaminifu, na metadata ya hiari + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +Fanya uchunguzi wa pamoja wa data: gundua aina na uundue maelezo. + +**Vigezo:** + +`sample`: Sampuli ya data kuchanganua (yaliyomo katika maandishi) +`schema_name`: Jina la schema ya lengo la hiari kwa uundaji wa maelezo +`options`: Vigezo vya hiari (k.m., kigawanyo kwa CSV) + +**Inarudisha:** kamusi yenye aina_iliyogunduliwa, uaminifu, maelezo, na metadata + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +Tafuta vipande vya hati kwa kutumia utofauti wa maana. + +Inapata vipande vya hati ambavyo yaliyomo katika vipande hivyo yanafanana kwa maana na +maandishi ya ingizo, kwa kutumia uelekezo wa vector. + +**Vigezo:** + +`text`: Maandishi ya swali kwa utafutaji wa maana +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`limit`: Nambari ya juu ya matokeo (ya kawaida: 10) + +**Inarudisha:** kamusi: Matokeo ya swali yenye vipande vyenye kitambulisho cha kipande na alama + +**Mfano:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +Tekeleza swali la Uzalishaji Ulioboreshwa na Utafiti (RAG) linalotegemea nyaraka. + +RAG ya nyaraka hutumia ufashilia wa vector ili kupata vipande muhimu vya nyaraka, +kisha huunda jibu kwa kutumia LLM (Large Language Model) kwa kutumia vipande hivyo kama muktadha. + +**Vigezo:** + +`query`: Swali katika lugha ya asili +`user`: Kitambulisho cha mtumiaji/nafasi (cha kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko (cha kawaida: "default") +`doc_limit`: Vipande vingi vya nyaraka ambavyo vitapatikana (cha kawaida: 10) + +**Inarudisha:** string: Jibu lililoundwa ambalo linajumuisha muktadha wa nyaraka + +**Mfano:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +Toa ufafanuzi wa vector kwa maandishi moja au zaidi. + +Hubadilisha maandishi kuwa uwakilishi wa vector mnono unaofaa kwa utafutaji wa maana +na kulinganisha sawa. + +**Vigezo:** + +`texts`: Orodha ya maandishi ya pembeni ambayo yanahitajika kufafanuliwa + +**Inarudisha:** list[list[list[float]]]: Ufafanuzi wa vector, seti moja kwa kila maandishi ya pembeni + +**Mfano:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +Tengeneza maelezo kwa ajili ya uhusiano wa data iliyopangwa na mpango maalum. + +**Vigezo:** + +`sample`: Sampuli ya data ya kuchambua (maudhui ya maandishi) +`data_type`: Aina ya data (csv, json, xml) +`schema_name`: Jina la mpango unaolengwa kwa ajili ya utengenezaji wa maelezo +`options`: Vigezo vya hiari (k.m., kigawanyo kwa CSV) + +**Inarudisha:** kamusi yenye maelezo na metadata + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +Tafuta vitu vya grafu ya maarifa kwa kutumia ufanano wa maana. + +Inatafuta vitu katika grafu ya maarifa ambavyo maelezo yake yanafanana +na maandishi yaingizwavyo, kwa kutumia uelekezo wa vector. + +**Vigezo:** + +`text`: Maandishi ya swali kwa ajili ya utafutaji wa maana +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`limit`: Nambari ya juu ya matokeo (ya kawaida: 10) + +**Inarudisha:** kamusi: Matokeo ya swali na vitu vinavyofanana + +**Mfano:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +Tekeleza swali la Uzalishaji Ulioboreshwa na Utafutaji (RAG) unaotegemea grafu. + +RAG ya grafu hutumia muundo wa grafu ya maarifa ili kupata muktadha unaohusiana kwa +kutumia uhusiano wa vitu, kisha huunda jibu kwa kutumia LLM. + +**Vigezo:** + +`query`: Swali la lugha ya asili +`user`: Kitambulisho cha mtumiaji/nafasi (cha kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko (cha kawaida: "default") +`entity_limit`: Vitu vingi zaidi ya kuchuja (cha kawaida: 50) +`triple_limit`: Triples nyingi zaidi kwa kila kitu (cha kawaida: 30) +`max_subgraph_size`: Triples jumla nyingi zaidi katika subgraph (cha kawaida: 150) +`max_path_length`: Kina cha juu zaidi cha utafutaji (cha kawaida: 2) + +**Inarudisha:** string: Jibu lililoundwa ambalo linajumuisha muktadha wa grafu + +**Mfano:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +Pakia hati ya binary ili kuendelea na usindikaji. + +Hupakia hati (PDF, DOCX, picha, n.k.) ili kuchukua maelezo na +kuendelea na usindikaji kupitia mchakato wa hati. + +**Vigezo:** + +`document`: Yaliyomo katika hati kama bytes +`id`: Kitambulisho cha hati cha hiari (kinatengenezwa kiotomatiki ikiwa hakipo) +`metadata`: Meta-data ya hiari (orodha ya Triples au kitu na njia ya emit) +`user`: Kitambulisho cha mtumiaji/nafasi (cha hiari) +`collection`: Kitambulisho cha mkusanyiko (cha hiari) + +**Inarudisha:** dict: Jibu la usindikaji + +**Inatirisha:** + +`RuntimeError`: Ikiwa meta-data imetolewa bila kitambulisho + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +Pakia maudhui ya maandishi kwa ajili ya uchakataji. + +Hupakia maudhui ya maandishi kwa ajili ya uondoaji na uchakataji kupitia njia ya maandishi ya mtiririko. + + +**Vigezo:** + +`text`: Maudhui ya maandishi kama bytes +`id`: Kitambulisho cha hati cha hiari (kinaundwa kiotomatiki ikiwa hakipo) +`metadata`: Meta data ya hiari (orodha ya Triples au kitu na njia ya emit) +`charset`: Ufuatiliaji wa herufi (kiasi: "utf-8") +`user`: Kitambulisho cha mtumiaji/nafasi (cha hiari) +`collection`: Kitambulisho cha mkusanyiko (cha hiari) + +**Inarudisha:** dict: Jibu la uchakataji + +**Inayotokea:** + +`RuntimeError`: Ikiwa meta data imetolewa bila kitambulisho + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +Fanya kazi na zana ya Itifaki ya Mfumo (MCP). + +Zana za MCP hutoa utendakazi unaoweza kupanuliwa kwa wakala na michakato, +kuruhusu ujumuishaji na mifumo na huduma za nje. + +**Vigezo:** + +`name`: Jina/kitambulisho cha zana +`parameters`: Kamusi ya vigezo vya zana (ya kawaida: {}) + +**Inarudisha:** string au kamusi: Matokeo ya utekelezaji wa zana + +**Inatirisha:** + +`ProtocolException`: Ikiwa muundo wa majibu hauna uhakika + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +Badilisha swali la lugha ya asili kuwa ombi la GraphQL. + +**Vigezo:** + +`question`: Swali la lugha ya asili +`max_results`: Nambari ya juu ya matokeo yanayorudishwa (ya kawaida: 100) + +**Inarudisha:** kamusi yenye graphql_query, variables, detected_schemas, uaminifu + +### `prompt(self, id, variables)` + +Tekeleza kiolezo cha ombi kwa kubadilisha vigezo. + +Kiolezo cha ombi huruhusu muundo wa ombi unaoweza kutumika tena na kubadilisha vigezo, +muhimu kwa uhandisi wa ombi unaoendana. + +**Vigezo:** + +`id`: Kitambulisho cha kiolezo cha ombi +`variables`: Kamusi ya ulinganisho wa jina la kigezo hadi thamani + +**Inarudisha:** string au kamusi: Matokeo ya ombi yaliyobadilishwa (maandishi au kitu kilicho na muundo) + +**Inatirisha:** + +`ProtocolException`: Ikiwa muundo wa jibu sio sahihi + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +Toa ombi la huduma katika toleo hili la mtiririko. + +**Vigezo:** + +`path`: Njia ya huduma (k.m., "service/text-completion") +`request`: Kamusi ya data ya ombi + +**Inarudisha:** dict: Jibu la huduma + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +Tafuta data ya mstari kwa kutumia ufanano wa maana kwenye sehemu zilizofichwa. + +Inatafuta mistari ambayo maadili ya sehemu zilizofichwa yanafanana kwa maana na +maandishi ya ingizo, kwa kutumia uelekezo wa vector. Hii inaruhusu utafutaji wa "fuzzy"/maana +kwenye data iliyopangwa. + +**Vigezo:** + +`text`: Maandishi ya swali kwa utafutaji wa maana +`schema_name`: Jina la mpango wa kutafuta ndani +`user`: Kitambulisho cha mtumiaji/nafasi (cha kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko (cha kawaida: "default") +`index_name`: Jina la fahirisi la hiari ili kuchuja utafutaji kwa fahirisi maalum +`limit`: Idadi ya juu ya matokeo (cha kawaida: 10) + +**Inarudisha:** dict: Matokeo ya utafutaji ambayo yana mechi, na yana index_name, index_value, text, na score + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +Tekeleza swali la GraphQL dhidi ya safu zilizopangwa katika grafu ya maarifa. + +Maswali hutumia data iliyopangwa kwa lugha ya GraphQL, na kuruhusu maswali magumu +yenye kuchujwa, ukusanyaji, na uhusiano. + +**Vigezo:** + +`query`: Mnyororo wa swali la GraphQL +`user`: Kitambulisho cha mtumiaji/nafasi (cha kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko (cha kawaida: "default") +`variables`: Kamusi ya vigezo vya swali ya hiari +`operation_name`: Jina la operesheni ya hiari kwa hati za operesheni nyingi + +**Inarudisha:** dict: Jibu la GraphQL na sehemu za 'data', 'errors', na/au 'extensions' + +**Inatirisha:** + +`ProtocolException`: Ikiwa hitilafu ya kiwango cha mfumo hutokea + +**Mfano:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +Chagua schemas zinazolingana kwa sampuli ya data kwa kutumia uchambuzi wa swali. + +**Vigezo:** + +`sample`: Sampuli ya data ya kuchambua (maudhui ya maandishi) +`options`: Vigezo vya hiari + +**Inarudisha:** kamusi yenye safu ya schema_matches na metadata + +### `structured_query(self, question, user='trustgraph', collection='default')` + +Tekeleza swali la lugha ya asili dhidi ya data iliyopangwa. +Inachanganya ubadilishaji wa swali la NLP na utekelezaji wa GraphQL. + +**Vigezo:** + +`question`: Swali la lugha ya asili +`user`: Kitambulisho cha nafasi ya Cassandra (cha kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko wa data (cha kawaida: "default") + +**Inarudisha:** kamusi yenye data na makosa yanayohitajika + +### `text_completion(self, system, prompt)` + +Tekeleza kukamilisha maandishi kwa kutumia LLM ya mtiririko. + +**Vigezo:** + +`system`: Swali la mfumo linalobainisha tabia ya msaidizi +`prompt`: Swali/swali la mtumiaji + +**Inarudisha:** maandishi: Jibu lililoundwa + +**Mfano:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +Tafuta ujuzi wa grapu kwa kutumia utangamano. + +Inatafuta triplet za RDF zinazofanana na mada, tabia, na/au +mifumo ya kitu. Vigezo visivyotajwa hufanya kama vichwa vya habari. + +**Vigezo:** + +`s`: URI ya mada (hiari, tumia None kwa kichwa cha habari) +`p`: URI ya tabia (hiari, tumia None kwa kichwa cha habari) +`o`: URI ya kitu au Literal (hiari, tumia None kwa kichwa cha habari) +`user`: Kitambulisho cha mtumiaji/nafasi (hiari) +`collection`: Kitambulisho cha mkusanyiko (hiari) +`limit`: Matokeo ya juu ya kurejesha (ya kawaida: 10000) + +**Inarejea:** list[Triple]: Orodha ya vitu vinavyolingana vya Triple + +**Inatiruka:** + +`RuntimeError`: Ikiwa s au p si Uri, au o si Uri/Literal + +**Mfano:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +Mteja wa usimamizi wa mtiririko usio na usawisi, unaotumia API ya REST. + +Hutoa operesheni za usimamizi wa mtiririko kulingana na async/await, ikiwa ni pamoja na kuorodhesha, +kuanzisha, kusimamisha mitiririko, na kusimamia ufafanuzi wa darasa la mtiririko. Pia hutoa +ufikiaji wa huduma za mtiririko kama vile wakala, RAG, na maswali kupitia sehemu za mwisho za REST ambazo hazitumii utiririshaji. + + +Kumbuka: Kwa usaidizi wa utiririshaji, tumia AsyncSocketClient badala yake. + +### Mbinu + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Anzisha mteja wa mtiririko usio na usawisi. + +**Majadiliano:** + +`url`: URL ya msingi ya API ya TrustGraph +`timeout`: Muda wa kuchelewa wa ombi kwa sekunde +`token`: Tokeni ya kuhifadhiwa ya hiari kwa uthibitishaji + +### `aclose(self) -> None` + +Funga mteja usio na usawisi na safisha rasilimali. + +Kumbuka: Usafishaji unashughulikiwa kiotomatiki na meneja wa muktadha wa kikao cha aiohttp. +Mbinu hii hutolewa kwa utangamano na wateja wengine wasio na usawisi. + +### `delete_class(self, class_name: str)` + +Futa ufafanuzi wa darasa la mtiririko. + +Huondoa mpango wa darasa la mtiririko kutoka kwenye mfumo. Haathiri +mifano ya mtiririko inayoruka. + +**Majadiliano:** + +`class_name`: Jina la darasa la mtiririko kufutwa + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +Pata ufafanuzi wa mtiririko. + +Hupata usanidi kamili wa mtiririko, pamoja na jina lake la darasa, +maelezo, na vigezo. + +**Vigezo:** + +`id`: Kitambulisho cha mtiririko + +**Inarudisha:** dict: Kitu cha ufafanuzi wa mtiririko + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +Pata ufafanuzi wa darasa la mtiririko. + +Inapata ufafanuzi wa mpango wa darasa la mtiririko, pamoja na +mpango wake wa usanidi na viunganisho vya huduma. + +**Vigezo:** + +`class_name`: Jina la darasa la mtiririko + +**Inarudisha:** dict: Kitu kinachowakilisha ufafanuzi wa darasa la mtiririko + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +Pata mteja wa mtiririko wa async. + +Inarudisha mteja kwa ajili ya kuingiliana na huduma za mtiririko maalum +(wakala, RAG, maswali, ufumbuzi, n.k.). + +**Majadiliano:** + +`flow_id`: Kitambulisho cha mtiririko + +**Inarudisha:** AsyncFlowInstance: Mteja kwa operesheni maalum za mtiririko + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +Orodha ya kitambulisho cha kila mtiririko. + +Inapata kitambulisho cha kila mtiririko unaoendeshwa kwa sasa katika mfumo. + +**Inarudisha:** list[str]: Orodha ya kitambulisho cha mtiririko + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +Orodha ya majina yote ya darasa la mtiririko. + +Inapata majina ya madarasa yote ya mtiririko (mipango) yanayopatikana katika mfumo. + +**Inarudisha:** list[str]: Orodha ya majina ya darasa la mtiririko. + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +Kuunda au kusasisha ufafanuzi wa darasa la mtiririko. + +Hifadhi mfumo wa darasa la mtiririko ambao unaweza kutumika kuunda mitiririko. + +**Vigezo:** + +`class_name`: Jina la darasa la mtiririko +`definition`: Kifaa cha ufafanuzi cha darasa la mtiririko + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Fanya ombi la HTTP POST lisilo na usumbufu kwa API ya Gateway. + +Njia ya ndani ya kutuma ombi lililo na uthibitisho kwa API ya TrustGraph. + +**Vigezo:** + +`path`: Njia ya mwisho ya API (kulinganisha na URL ya msingi) +`request_data`: Kamusi ya data inayotumwa kwenye ombi + +**Inarudisha:** dict: Kielelezo cha majibu kutoka kwa API + +**Inayotokea:** + +`ProtocolException`: Ikiwa hali ya HTTP si 200 au majibu hayana umbizo sahihi la JSON +`ApplicationException`: Ikiwa API inarudisha jibu la kosa + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +Anzisha mfumo mpya wa utekelezaji. + +Huunda na kuanzisha mfumo kutoka kwa ufafanuzi wa darasa la mfumo pamoja na +vigezo vilivyoelezwa. + +**Vigezo:** + +`class_name`: Jina la darasa la mfumo linalotumiwa +`id`: Kitambulisho cha mfumo mpya +`description`: Maelezo yanayoweza kusomwa na binadamu ya mfumo +`parameters`: Vigezo vya ziada vya usanidi vya mfumo + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +Kusimamisha mtiririko unaoendelea. + +Inasimamisha na kuondoa mfano wa mtiririko, na kutoa rasilimali zake. + +**Vigezo:** + +`id`: Kitambulisho cha mtiririko ili kusimamishwa + +**Mfano:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +Mteja wa mfumo wa kazi usiofanyika kwa wakati mmoja. + +Hutoa ufikiaji wa async/await kwa huduma za mfumo wa kazi, ikiwa ni pamoja na wakala, +Maswali ya RAG, maandamano, na maswali ya grafu. Operesheni zote hurudisha +majibu kamili (ya moja kwa moja). + +Kumbuka: Kwa usaidizi wa utiririshaji, tumia AsyncSocketFlowInstance. + +### Mbinu + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +Anzisha mfumo wa kazi usiofanyika kwa wakati mmoja. + +**Majadiliano:** + +`flow`: Mteja wa AsyncFlow mkuu +`flow_id`: Kitambulisho cha mfumo wa kazi + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +Fanya operesheni ya wakala (ya moja kwa moja). + +Huendesha wakala kujibu swali, pamoja na hali ya mazungumzo na +historia. Inarudisha jibu kamili baada ya wakala kumaliza +kuchakata. + +Kumbuka: Njia hii haitumii utiririshaji. Kwa mawazo na matokeo ya wakala +ya wakati halisi, tumia AsyncSocketFlowInstance.agent() badala yake. + +**Majadiliano:** + +`question`: Suali au maagizo ya mtumiaji +`user`: Kitambulisho cha mtumiaji +`state`: Kamusi ya hali ya hiari kwa muktadha wa mazungumzo +`group`: Kitambulisho cha kikundi cha hiari kwa usimamizi wa kikao +`history`: Orodha ya historia ya mazungumzo ya hiari +`**kwargs`: Vigezo vya ziada maalum kwa huduma + +**Inarudisha:** dict: Jibu kamili la wakala ikiwa ni pamoja na jibu na metadata + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +Fanya swali la RAG (Retrieval-Augmented Generation) linalotegemea hati (si mtiririko). + +Hufanya Uundaji Ulioboreshwa kwa Upatanishaji kwa kutumia ufichuo wa hati. +Hupata vipande muhimu vya hati kupitia utafutaji wa maana, kisha huunda +jibu linalotegemea hati zilizopatikana. Inarudisha jibu kamili. + +Kumbuka: Njia hii haitumii mtiririko. Kwa majibu ya RAG yanayotumia mtiririko, +tumia AsyncSocketFlowInstance.document_rag() badala yake. + +**Vigezo:** + +`query`: Nakala ya swali la mtumiaji +`user`: Kitambulisho cha mtumiaji +`collection`: Kitambulisho cha mkusanyiko unao na hati +`doc_limit`: Nambari ya juu ya vipande vya hati ambavyo vinaweza kupatikana (kiwango chachilia: 10) +`**kwargs`: Vigezo vya ziada vinavyohusiana na huduma + +**Inarudisha:** str: Jibu kamili lililoundwa na linalotegemea data ya hati + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +Toa maelezo kwa maandishi ya pembejeo. + +Hubadilisha maandishi kuwa uwakilishi wa nambari za vector kwa kutumia +mfumo wa embedding uliopangwa wa mtiririko. Ni muhimu kwa utafutaji wa maana na +ulinganisho wa alama. + +**Vigezo:** + +`texts`: Orodha ya maandishi ya pembejeo ambayo yanahitajika kuwekwa maelezo. +`**kwargs`: Vigezo vya ziada maalum kwa huduma. + +**Inarudisha:** dict: Jibu lenye vector za maelezo. + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +Tafuta ujumuishi wa grafu kwa ajili ya utafutaji wa vitu vya maana. + +Hufanya utafutaji wa maana kwenye ujumuishi wa vitu vya grafu ili kupata vitu +ambavyo ni muhimu zaidi kwa maandishi yaliyopo. Inarudisha vitu vilivyopangwa kwa umuhimu. + +**Vigezo:** + +`text`: Maandishi ya swali kwa utafutaji wa maana +`user`: Kitambulisho cha mtumiaji +`collection`: Kitambulisho cha mkusanyiko unao na ujumuishi wa grafu +`limit`: Nambari ya juu ya matokeo yanayorudishwa (ya kawaida: 10) +`**kwargs`: Vigezo vya ziada maalum kwa huduma + +**Inarudisha:** dict: Jibu linalo na vitu vinavyolingana vilivyopangwa pamoja na alama za umuhimu + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +Tekeleza swali la RAG linalotegemea grafu (lisilo na utiririshaji). + +Hufanya Uundaji Ulioboreshwa na Upatanishaji kwa kutumia data ya grafu ya maarifa. +Hutambua vitu muhimu na uhusiano wao, kisha huunda +jibu ambalo limekithiri katika muundo wa grafu. Inarudisha jibu kamili. + +Kumbuka: Njia hii haitumii utiririshaji. Kwa majibu ya RAG yanayotumia utiririshaji, +tumia AsyncSocketFlowInstance.graph_rag() badala yake. + +**Vigezo:** + +`query`: Nakala ya swali la mtumiaji +`user`: Kitambulisho cha mtumiaji +`collection`: Kitambulisho cha mkusanyiko unao na grafu ya maarifa +`max_subgraph_size`: Nambari ya juu ya triplet kwa kila subgrafu (ya kawaida: 1000) +`max_subgraph_count`: Nambari ya juu ya subgrafu za kuchukuliwa (ya kawaida: 5) +`max_entity_distance`: Umbali wa juu wa grafu kwa upanuzi wa vitu (ya kawaida: 3) +`**kwargs`: Vigezo vya ziada vya huduma maalum + +**Inarudisha:** string: Jibu kamili lililoundwa ambalo limekithiri katika data ya grafu + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Tafadhali omba huduma iliyo ndani ya eneo la mtiririko. + +Njia ya ndani ya kuita huduma ndani ya mfano huu wa mtiririko. + +**Vigezo:** + +`service`: Jina la huduma (k.m., "agent", "graph-rag", "triples") +`request_data`: Takwimu ya ombi la huduma + +**Inarudisha:** dict: Kielelezo cha jibu la huduma + +**Inatirisha:** + +`ProtocolException`: Ikiwa ombi halikubaliwi au jibu ni batili +`ApplicationException`: Ikiwa huduma inarudisha kosa + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +Tafuta ujumbe wa mistari ili kutafuta maana katika data iliyopangwa. + +Hufanya utafutaji wa maana kwenye ujumbe wa mistari ili kupata mistari ambayo +maadili ya sehemu iliyopangwa ni sawa zaidi na maandishi ya ingizo. Inaruhusu +utangamano/ufanisi wa maana katika data iliyopangwa. + +**Vigezo:** + +`text`: Maandishi ya swali kwa utafutaji wa maana +`schema_name`: Jina la mpango wa kutafuta ndani +`user`: Kitambulisho cha mtumiaji (kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko (kawaida: "default") +`index_name`: Jina la faharasa la hiari ili kuchuja utafutaji kwa faharasa maalum +`limit`: Nambari ya juu ya matokeo ya kurejesha (kawaida: 10) +`**kwargs`: Vigezo vya ziada vya huduma + +**Inarudisha:** dict: Jibu linalo na mechi pamoja na index_name, index_value, text, na score + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +Tekeleza swali la GraphQL kwenye mistari iliyohifadhiwa. + +Maswali hutumia mistari iliyo na muundo kwa kutumia sintaksia ya GraphQL. Inasaidia +maswali magumu yenye vigezo na operesheni zilizo na majina. + +**Vigezo:** + +`query`: Mnyororo wa swali la GraphQL +`user`: Kitambulisho cha mtumiaji +`collection`: Kitambulisho cha mkusanyiko unao na mistari +`variables`: Vigezo vya swali la GraphQL vya hiari +`operation_name`: Jina la operesheni la hiari kwa maswali mengi +`**kwargs`: Vigezo vya ziada vya mahitaji ya huduma + +**Inarudisha:** dict: Jibu la GraphQL lenye data na/au makosa + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +Toa maandishi yaliyokamilika (hayajazalishwa kwa utiririshaji). + +Huunda jibu la maandishi kutoka kwa mfumo wa LLM (Large Language Model) kwa kutumia maagizo ya mfumo na maagizo ya mtumiaji. +Inarudisha maandishi kamili ya jibu. + +Kumbuka: Njia hii haitumii utiririshaji. Kwa utiririshaji wa maandishi, +tumia AsyncSocketFlowInstance.text_completion() badala yake. + +**Vigezo:** + +`system`: Maagizo ya mfumo ambayo yanaeleza tabia ya mfumo wa LLM. +`prompt`: Maagizo ya mtumiaji au swali. +`**kwargs`: Vigezo vya ziada ambavyo ni mahususi kwa huduma. + +**Inarudisha:** str: Jibu kamili la maandishi lililozalishwa. + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +Tafuta maneno matatu ya RDF kwa kutumia utambuzi wa muundo. + +Inatafuta maneno matatu yanayolingana na mada, sifa, na/au +mifumo ya kitu. Mifumo hutumia "Hakuna" kama ishara ya kujielekeza ili kuangalia thamani yoyote. + +**Vigezo:** + +`s`: Mfumo wa mada (Hakuna kwa kujielekeza) +`p`: Mfumo wa sifa (Hakuna kwa kujielekeza) +`o`: Mfumo wa kitu (Hakuna kwa kujielekeza) +`user`: Kitambulisho cha mtumiaji (Hakuna kwa watumiaji wote) +`collection`: Kitambulisho cha mkusanyiko (Hakuna kwa mkusanyiko wote) +`limit`: Nambari ya juu ya maneno matatu ya kurejesha (ya kawaida: 100) +`**kwargs`: Vigezo vya ziada maalum kwa huduma + +**Inarejea:** dict: Jibu lenye maneno matatu yanayolingana + +**Mfano:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +Mteja wa WebSocket wa wakati mmoja kwa operesheni za utiririshaji. + +Hutoa kiolesura cha wakati mmoja kwa huduma za TrustGraph zinazotegemea WebSocket, +ikibadilisha maktabu ya websockets ya asinkroni na jenereta za wakati mmoja ili iwe rahisi kutumia. +Inasaidia majibu ya utiririshaji kutoka kwa wakala, maswali ya RAG, na kukamilisha maandishi. + +Kumbuka: Hii ni kifungashio cha wakati mmoja kilichoanzishwa kwenye operesheni za WebSocket za asinkroni. Kwa +usaidizi wa kweli wa asinkroni, tumia AsyncSocketClient badala yake. + +### Mbinu + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Anzisha mteja wa WebSocket wa wakati mmoja. + +**Majadiliano:** + +`url`: URL ya msingi kwa API ya TrustGraph (HTTP/HTTPS itabadilishwa kuwa WS/WSS) +`timeout`: Muda wa kimya wa WebSocket kwa sekunde +`token`: Tokeni ya kuhifadhia ya hiari kwa uthibitishaji + +### `close(self) -> None` + +Funga miunganisho ya WebSocket. + +Kumbuka: Usafi unashughulikiwa kiotomatiki na wasimamizi wa muktadha katika msimbo wa asinkroni. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +Pata mfano wa mtiririko kwa operesheni za utiririshaji wa WebSocket. + +**Majadiliano:** + +`flow_id`: Kitambulisho cha mtiririko + +**Inarudisha:** SocketFlowInstance: Mfano wa mtiririko na mbinu za utiririshaji + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +Mfumo wa mawasiliano ya WebSocket wa wakati mmoja kwa operesheni za utiririshaji. + +Hutoa kiolesura sawa na FlowInstance ya REST lakini na msaada wa utiririshaji wa WebSocket +kwa majibu ya wakati halisi. Mbinu zote zinaunga mkono parameter ya hiari +`streaming` ili kuwezesha utoaji wa matokeo kwa hatua. + +### Mbinu + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +Anzisha mfumo wa utiririshaji wa soketi. + +**Majadiliano:** + +`client`: Soketi ya Msimamizi +`flow_id`: Kitambulisho cha mtiririko + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +Fanya operesheni ya wakala na msaada wa utiririshaji. + +Wakala wanaweza kufanya utaratibu wa hatua kadhaa kwa kutumia zana. Mbinu hii daima +hurudisha vipande vya utiririshaji (mawazo, uchunguzi, majibu) hata wakati +streaming=False, ili kuonyesha mchakato wa utafakari wa wakala. + +**Majadiliano:** + +`question`: Swali au maagizo ya mtumiaji +`user`: Kitambulisho cha mtumiaji +`state`: Kamusi ya hiari ya hali kwa mazungumzo ya hali +`group`: Kitambulisho cha hiari cha kikundi kwa muktadha wa watumiaji wengi +`history`: Historia ya hiari ya mazungumzo kama orodha ya maneno +`streaming`: Washa hali ya utiririshaji (kiasi: False) +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma ya wakala + +**Hurejesha:** Iterator[StreamingChunk]: Mto wa mawazo, uchunguzi, na majibu ya wakala + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +Fanya operesheni ya wakala pamoja na ufuatiliaji wa uelewaji. + +Hutuma vipande vya maudhui (AgentThought, AgentObservation, AgentAnswer) +na matukio ya asili (ProvenanceEvent). Matukio ya asili yana anwani za mtandao (URIs) +ambazo zinaweza kupatikana kwa kutumia ExplainabilityClient ili kupata maelezo +kuhusu mchakato wa utafakari wa wakala. + +Ufuatiliaji wa wakala una vipengele vifuatavyo: +Kipindi: Swali la awali na metadata ya kipindi +Mzunguko: Kila mzunguko wa mawazo/tendo/uchunguzi +Hitimisho: Jibu la mwisho + +**Vigezo:** + +`question`: Swali au maagizo ya mtumiaji +`user`: Kitambulisho cha mtumiaji +`collection`: Kitambulisho cha mkusanyiko kwa uhifadhi wa asili +`state`: Kamusi ya hali inayobadilika (optional) kwa mazungumzo yanayoendelea +`group`: Kitambulisho cha kikundi (optional) kwa mazingira ya watumiaji wengi +`history`: Historia ya mazungumzo (optional) kama orodha ya maneno +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma ya wakala +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: Vipande vya wakala na matukio ya asili + +**Mfano:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Tafuta vipande vya hati kwa kutumia utambulisho wa maana. + +**Vigezo:** + +`text`: Nakala ya swali kwa utafutaji wa maana +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`limit`: Nambari ya juu ya matokeo (ya kawaida: 10) +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma + +**Inarudisha:** dict: Matokeo ya swali na kitambulisho cha vipande vya hati vinavyolingana + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Fanya swali la RAG (Retrieval-Augmented Generation) linalotegemea hati, na uwezekano wa kutumia utiririshaji. + +Hutumia ufashiliaji wa vector ili kupata vipande muhimu vya hati, kisha huunda +jibu kwa kutumia LLM (Large Language Model). Njia ya utiririshaji huwasilisha matokeo hatua kwa hatua. + +**Vigezo:** + +`query`: Swali la lugha ya asili +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`doc_limit`: Idadi ya juu ya vipande vya hati ambavyo vinaweza kupatikana (kiwango chachilia: 10) +`streaming`: Washa hali ya utiririshaji (kiwango chachilia: False) +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma + +**Hurejesha:** Union[str, Iterator[str]]: Jibu kamili au mkondo wa vipande vya maandishi + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Fanya swali la RAG (Retrieval-Augmented Generation) linalotegemea hati na linalo na uwezo wa kueleza. + +Hutuma vipande vya maudhui (RAGChunk) na matukio ya asili (ProvenanceEvent). +Matukio ya asili yana anwani za mtandao (URIs) ambazo zinaweza kupatikana kwa kutumia ExplainabilityClient +ili kupata maelezo ya kina kuhusu jinsi jibu lilivyoundwa. + +Mfuatiliaji wa RAG wa hati una vipengele vifuatavyo: +Swali: Swali la mtumiaji +Uchunguzi: Vipande vilivyopatikana kutoka kwenye hifadhi ya hati (idadi ya vipande) +Muundo: Jibu lililoundwa + +**Vigezo:** + +`query`: Swali kwa lugha ya asili +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`doc_limit`: Vipande vingi vya hati ambavyo vinaweza kupatikana (kiwango chachilia: 10) +`**kwargs`: Vigezo vya ziada ambavyo vinatumiwa kwa huduma +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Vipande vya maudhui na matukio ya asili + +**Mfano:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +Toa ufafanuzi wa maandishi kwa ajili ya maandishi moja au zaidi. + +**Vigezo:** + +`texts`: Orodha ya maandishi ya pembeni ambayo yatatumika kuunda ufafanuzi. +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma. + +**Inarudisha:** dict: Jibu ambalo lina ufafanuzi (kundi moja kwa kila maandishi ya pembeni). + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Tafuta vitu vya grafu ya maarifa kwa kutumia utambulisho wa maana. + +**Vigezo:** + +`text`: Nakala ya swali kwa utafutaji wa maana +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`limit`: Nambari ya juu ya matokeo (ya kawaida: 10) +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma + +**Inarudisha:** dict: Matokeo ya swali na vitu vinavyofanana + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Tekeleza swali la RAG linalotegemea grafu pamoja na utiririshaji wa hiari. + +Hutumia muundo wa grafu ya maarifa ili kupata muktadha unaohusika, kisha huunda +jibu kwa kutumia LLM. Njia ya utiririshaji huwasilisha matokeo hatua kwa hatua. + +**Vigezo:** + +`query`: Swali la lugha ya asili +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`max_subgraph_size`: Idadi ya juu ya triplet katika subgrafu (ya kawaida: 1000) +`max_subgraph_count`: Idadi ya juu ya subgrafu (ya kawaida: 5) +`max_entity_distance`: Kina cha juu cha utafutaji (ya kawaida: 3) +`streaming`: Washa hali ya utiririshaji (ya kawaida: False) +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma + +**Hurejesha:** Union[str, Iterator[str]]: Jibu kamili au mkondo wa vipande vya maandishi + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Tekeleza swali la RAG linalotegemea grafu pamoja na utumiaji wa uelewaji. + +Hutiririsha vipande vya maudhui (RAGChunk) na matukio ya asili (ProvenanceEvent). +Matukio ya asili yana URI ambazo zinaweza kupatikana kwa kutumia ExplainabilityClient +ili kupata maelezo ya kina kuhusu jinsi jibu lilivyoundwa. + +**Vigezo:** + +`query`: Swali la lugha ya asili +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`max_subgraph_size`: Idadi ya juu ya triplet katika subgrafu (ya kawaida: 1000) +`max_subgraph_count`: Idadi ya juu ya subgrafu (ya kawaida: 5) +`max_entity_distance`: Kina cha juu cha utafutaji (ya kawaida: 3) +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: Vipande vya maudhui na matukio ya asili + +**Mfano:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +Fanya kazi ya zana ya Itifaki ya Mfumo (MCP). + +**Vigezo:** + +`name`: Jina/kitambulisho cha zana +`parameters`: Kamusi ya vigezo vya zana +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma + +**Inarudisha:** dict: Matokeo ya utekelezaji wa zana + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Tekeleza mfumo wa kielelezo cha ombi pamoja na utiririshaji wa hiari. + +**Vigezo:** + +`id`: Kitambulisho cha kielelezo cha ombi +`variables`: Kamusi ya uhusiano kati ya jina la vigezo na maadili +`streaming`: Washa hali ya utiririshaji (kiwango chake: Feleke) +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma + +**Inarudisha:** Union[str, Iterator[str]]: Jibu kamili au mkondo wa vipande vya maandishi + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Tafuta data ya safu kwa kutumia utofauti wa maana kwenye sehemu zilizofichwa. + +Inatafuta safu ambazo maadili ya sehemu zilizofichwa zinafanana kwa maana na +maandishi ya ingizo, kwa kutumia uelekezo wa vector. Hii inaruhusu utafutaji wa "fuzzy"/maana +kwenye data iliyopangwa. + +**Vigezo:** + +`text`: Maandishi ya swali kwa utafutaji wa maana +`schema_name`: Jina la schema ili kutafuta ndani +`user`: Kitambulisho cha mtumiaji/keyspace (cha kawaida: "trustgraph") +`collection`: Kitambulisho cha mkusanyiko (cha kawaida: "default") +`index_name`: Jina la index la hiari ili kuchuja utafutaji kwa index maalum +`limit`: Nambari ya juu ya matokeo (cha kawaida: 10) +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma + +**Inarudisha:** dict: Matokeo ya swali ambayo yana mechi zinazojumuisha index_name, index_value, text, na score + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +Tekeleza swali la GraphQL dhidi ya mistari iliyopangwa. + +**Vigezo:** + +`query`: Mnyororo wa swali la GraphQL +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`variables`: Kamusi ya vigezo vya swali ya hiari +`operation_name`: Jina la operesheni ya hiari kwa hati za operesheni nyingi +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma + +**Inarudisha:** dict: Jibu la GraphQL lenye data, makosa, na/au nyongeza + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +Tekeleza kukamilisha maandishi kwa kutumia utiririshaji wa hiari. + +**Vigezo:** + +`system`: Maelezo ya mfumo ambayo yanaelezea tabia ya msaidizi. +`prompt`: Maelezo ya mtumiaji/swali. +`streaming`: Washa hali ya utiririshaji (kiwango chachilia: False). +`**kwargs`: Vigezo vya ziada ambavyo hutumwa kwa huduma. + +**Inarudisha:** Union[str, Iterator[str]]: Jibu kamili au mkondo wa vipande vya maandishi. + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +Tafuta tripli za grafu ya maarifa kwa kutumia utambuzi wa muundo. + +**Vigezo:** + +`s`: Kichujio cha somo - Msururu wa URI, kamusi ya neno, au None kwa kichujio cha kila kitu. +`p`: Kichujio cha tabia - Msururu wa URI, kamusi ya neno, au None kwa kichujio cha kila kitu. +`o`: Kichujio cha kitu - Msururu wa URI/lita, kamusi ya neno, au None kwa kichujio cha kila kitu. +`g`: Kichujio cha grafu iliyojulikana - Msururu wa URI au None kwa grafu zote. +`user`: Kitambulisho cha mtumiaji/nafasi (hiari). +`collection`: Kitambulisho cha mkusanyiko (hiari). +`limit`: Matokeo ya kiwango cha juu ya kurudishwa (kiwango chachilia: 100). +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma. + +**Inarudisha:** Orodha[Dict]: Orodha ya tripli zinazolingana katika muundo wa msingi. + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +Tafuta tripla za grafu ya maarifa kwa kutumia mikondo ya data. + +Hutoa mikondo ya tripla kadri zinavyofika, na hivyo kupunguza muda wa kupata matokeo ya kwanza +na matumizi ya kumbukumbu kwa matokeo makubwa. + +**Vigezo:** + +`s`: Kichujio cha mada - Msururu wa URI, kamusi ya neno, au None kwa kichujio cha wote. +`p`: Kichujio cha sifa - Msururu wa URI, kamusi ya neno, au None kwa kichujio cha wote. +`o`: Kichujio cha kitu - Msururu wa URI/lita, kamusi ya neno, au None kwa kichujio cha wote. +`g`: Kichujio cha grafu iliyojulikana - Msururu wa URI au None kwa grafu zote. +`user`: Kitambulisho cha mtumiaji/nafasi (hiari). +`collection`: Kitambulisho cha mkusanyiko (hiari). +`limit`: Matokeo mengi ya kurejesha (ya kawaida: 100). +`batch_size`: Tripla kwa kila kikundi (ya kawaida: 20). +`**kwargs`: Vigezo vya ziada vilivyopitishwa kwa huduma. +`Yields`: +`List[Dict]`: Mikundi ya tripla katika umbizo la mawasiliano. + +**Mfano:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +Mteja wa WebSocket asinkroni. + +### Mbinu + +### `__init__(self, url: str, timeout: int, token: str | None)` + +Anzisha `self`. Angalia `help(type(self))` kwa maelezo sahihi ya muundo. + +### `aclose(self)` + +Funga muunganisho wa WebSocket. + +### `flow(self, flow_id: str)` + +Pata mfumo wa kazi asinkroni kwa operesheni za WebSocket. + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +Mfumo wa mtiririko wa WebSocket usiohusisha wakati. + +### Mbinu + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +Anzisha `self`. Angalia `help(type(self))` kwa maelezo sahihi ya jinsi ya kutumia. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +Wakala na utiririshaji wa hiari. + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +Andika RAG (Retrieval-Augmented Generation) na utiririshaji wa hiari. + +### `embeddings(self, texts: list, **kwargs)` + +Tengeneza ufichishaji wa maandishi. + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +Tafuta ufichishaji wa grafu kwa utafutaji wa maana. + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +Grafu RAG na utiririshaji wa hiari. + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +Endesha zana ya MCP. + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +Endesha ombi na utiririshaji wa hiari. + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +Tafuta ufichishaji wa mistari kwa utafutaji wa maana kwenye data iliyopangwa. + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +Ombi la GraphQL dhidi ya mistari iliyopangwa. + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +Kukamilisha maandishi na utiririshaji wa hiari. + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +Uchunguzi wa muundo wa tatu. + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +Jenga kamusi ya Term ya muundo kutoka kwa thamani. + +Kanuni za utambuzi wa kiotomatiki (wakati `term_type` ni `None`): + Tayari ni kamusi yenye ufunguo 't' -> irudishe kama ilivyo (tayari ni Term) + Inaanzia na http://, https://, urn: -> IRI + Imezungushwa ndani ya <> (e.g., ) -> IRI (brashi za pembe zimeondolewa) + Kila kitu kingine -> literal + +**Majadiliano:** + +`value`: Thamani ya Term (mfululizo, kamusi, au `None`) +`term_type`: Moja kati ya 'iri', 'literal', au `None` kwa utambuzi wa kiotomatiki +`datatype`: Aina ya data kwa vitu vya literal (e.g., xsd:integer) +`language`: Lango la lugha kwa vitu vya literal (e.g., en) + +**Inarudisha:** kamusi: Kamusi ya Term ya muundo, au `None` ikiwa thamani ni `None` + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +Mteja wa operesheni za wingi za wakati mmoja kwa uagizaji/utoaji. + +Hutoa uhamishaji wa data wa wingi unaofaa kupitia WebSocket kwa data kubwa. +Huweka operesheni za WebSocket za asinkroni na jenereta za wakati mmoja ili kupunguza ugumu. + +Kumbuka: Kwa usaidizi halisi wa asinkroni, tumia AsyncBulkClient badala yake. + +### Mbinu + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Anzisha mteja wa wingi wa wakati mmoja. + +**Majadilisho:** + +`url`: URL ya msingi kwa API ya TrustGraph (HTTP/HTTPS itabadilishwa kuwa WS/WSS) +`timeout`: Muda wa timeout wa WebSocket kwa sekunde +`token`: Tokeni ya kuhifadhiwa ya hiari kwa uthibitishaji + +### `close(self) -> None` + +Funga miunganisho + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Toa nakala za uainishaji kutoka kwa mtiririko. + +Inapakua kwa ufanisi uainishaji wote wa vipande vya nyaraka kupitia utiririshaji wa WebSocket. + +**Majadilisho:** + +`flow`: Kitambulisho cha mtiririko +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye) + +**Inarudisha:** Iterator[Dict[str, Any]]: Msururu wa kamusi za uainishaji + +**Mfano:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Uhamisho wa wingi wa muktadha wa vitu kutoka kwa mtiririko. + +Inapakua habari yote ya muktadha wa vitu kwa ufanisi kupitia utiririshaji wa WebSocket. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye) + +**Inarudisha:** Iterator[Dict[str, Any]]: Msururu wa kamusi za muktadha + +**Mfano:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Uhamisho wa wingi wa maandamano ya grafu kutoka kwa mtiririko. + +Inapakua kwa ufanisi maandamano yote ya vitu vya grafu kupitia utiririshaji wa WebSocket. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye) + +**Inarudisha:** Iterator[Dict[str, Any]]: Mto wa kamusi za maandamano + +**Mfano:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +Uhamisho wa wingi wa data ya RDF kutoka kwa mtiririko. + +Inapakua data yote kwa ufanisi kupitia utiririshaji wa WebSocket. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko. +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye). + +**Inarudisha:** Iterator[Triple]: Mto wa vitu vya Triple. + +**Mfano:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Kuleta kwa wingi maandishi ya kuingizwa katika mtiririko. + +Huainisha kwa ufanisi maandishi ya vipande vya maandishi kupitia utiririshaji wa WebSocket +kwa matumizi katika maswali ya RAG ya maandishi. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`embeddings`: Mfumo unaotoa kamusi za kuingizwa +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye) + +**Mfano:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Kuleta kwa wingi maelezo ya vitu ndani ya mtiririko. + +Huwezesha kupakia taarifa za maelezo ya vitu kupitia utiririshaji wa WebSocket. +Maelezo ya vitu hutoa maelezo ya ziada ya maandishi kuhusu vitu vya chati +ili kuboresha utendaji wa RAG. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`contexts`: Iteratili inayotoa kamusi za maelezo +`metadata`: Kamusi ya metadata yenye id, metadata, mtumiaji, mkusanyiko +`batch_size`: Idadi ya maelezo kwa kila kundi (ya kawaida 100) +`**kwargs`: Vigezo vya ziada (vimehifadhiwa kwa matumizi ya baadaye) + +**Mfano:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Kuleta kwa wingi michoro ya pembejeo katika mtiririko. + +Huainisha kwa ufanisi pembejeo za michoro kupitia utiririshaji wa WebSocket. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`embeddings`: Mfuatiliao unaotoa kamusi za pembejeo +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye) + +**Mfano:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Kuingiza kwa wingi mistari iliyoandaliwa katika mtiririko. + +Inapakia data iliyoandaliwa kwa ufanisi kupitia utiririshaji wa WebSocket +kwa ajili ya matumizi katika maswali ya GraphQL. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`rows`: Mfuatiliazo unaotoa kamusi za mistari +`**kwargs`: Vigezo vya ziada (hifadhiwa kwa matumizi ya baadaye) + +**Mfano:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Uingizaji wa jumla wa triplet za RDF katika mtiririko. + +Huainisha triplet nyingi kwa ufanisi kupitia utiririshaji wa WebSocket. + +**Vigezo:** + +`flow`: Kitambulisho cha mtiririko +`triples`: Itereta inayotoa vitu vya Triple +`metadata`: Kamusi ya metadata yenye id, metadata, mtumiaji, mkusanyiko +`batch_size`: Idadi ya triplet kwa kila kundi (ya kawaida 100) +`**kwargs`: Vigezo vya ziada (vimehifadhiwa kwa matumizi ya baadaye) + +**Mfano:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +Mteja wa operesheni za wingi zisizo za wakati. + +### Mbinu + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Anzisha `self`. Angalia `help(type(self))` kwa maelezo sahihi ya muundo. + +### `aclose(self) -> None` + +Funga miunganisho. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Uhamisho wa wingi wa maandishi ya nyaraka kupitia WebSocket. + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Uhamisho wa wingi wa muktadha wa vitu kupitia WebSocket. + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +Uhamisho wa wingi wa maandishi ya chati kupitia WebSocket. + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +Uhamisho wa wingi wa triplet kupitia WebSocket. + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Uingizaji wa wingi wa maandishi ya nyaraka kupitia WebSocket. + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Uingizaji wa wingi wa muktadha wa vitu kupitia WebSocket. + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Uingizaji wa wingi wa maandishi ya chati kupitia WebSocket. + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +Uingizaji wa wingi wa mistari kupitia WebSocket. + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +Uingizaji wa wingi wa triplet kupitia WebSocket. + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +Mteja wa metriki za wakati mmoja. + +### Mbinu + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Anzisha `self`. Angalia `help(type(self))` kwa maelezo sahihi ya muundo. + +### `get(self) -> str` + +Pata metriki za Prometheus kama maandishi. + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +Mteja wa metriki zisizo za wakati (asynchronous). + +### Mbinu (Methods) + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Anzisha (Initialize) `self`. Angalia `help(type(self))` kwa maelezo sahihi ya muundo. + +### `aclose(self) -> None` + +Funga miunganisho (Close connections). + +### `get(self) -> str` + +Pata metriki za Prometheus kama maandishi (Get Prometheus metrics as text). + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +Mteja wa kupata vitu vya uhalisia kwa utaratibu wa utangamano wa mwisho. + +Hutumia utambuzi wa utulivu: pata, subiri, pata tena, linganisha. +Ikiwa matokeo ni sawa, data ni thabiti. + +### Mbinu + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +Anzisha mteja wa uhalisia. + +**Majadiliano:** + +`flow_instance`: Toleo la SocketFlowInstance kwa kuuliza vitatu. +`retry_delay`: Kuchelewesha kati ya majaribio katika sekunde (kiwango chote: 0.2). +`max_retries`: Jaribio la juu zaidi (kiwango chote: 10). + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +Thibitisha ikiwa kikao ni cha aina ya GraphRAG au Agent. + +**Vigezo:** + +`session_uri`: URI ya kipindi/swali +`graph`: Grafu iliyopewa jina +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko + +**Inarudisha:** "graphrag" au "agent" + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Pata faili kamili ya "Agent" kuanzia URI ya kipindi. + +Fuata mnyororo wa asili: Swali -> Uchambuzi(s) -> Hitimisho + +**Vigezo:** + +`session_uri`: URI ya kipindi cha "agent"/swali +`graph`: Grafu iliyopewa jina (ya kawaida: urn:graph:retrieval) +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`api`: Ena ya TrustGraph API kwa ufikiaji wa "librarian" (hiari) +`max_content`: Urefu wa juu wa maudhui kwa hitimisho + +**Inarudi:** Kamusi yenye swali, mara (Orodha ya uchambuzi), na vitu vya hitimisho. + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Kuchukua faili kamili ya "DocumentRAG" kuanzia URI ya swali. + +Kufuata mnyororo wa asili: + Swali -> Msingi -> Uchunguzi -> Muunganisho + +**Majadiliano:** + +`question_uri`: URI ya swali. +`graph`: Grafu iliyoitwa (ya kawaida: urn:graph:retrieval). +`user`: Kitambulisho cha mtumiaji/nafasi. +`collection`: Kitambulisho cha mkusanyiko. +`api`: Eneo la TrustGraph API kwa ufikiaji wa "librarian" (hiari). +`max_content`: Urefu wa juu wa yaliyomo kwa muunganisho. + +**Inarudi:** Kamusi yenye swali, msingi, uchunguzi, na vitu vya muunganisho. + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +Kuchukua yaliyomo kutoka kwa "librarian" kwa URI ya hati. + +**Majadiliano:** + +`document_uri`: URI ya hati katika "librarian". +`api`: Eneo la TrustGraph API kwa ufikiaji wa "librarian". +`user`: Kitambulisho cha mtumiaji kwa "librarian". +`max_content`: Urefu wa juu wa yaliyomo yanayorudishwa. + +**Inarudi:** Yaliyomo ya hati kama mfululizo. + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +Kuchukua kitambulisho cha uchaguzi wa "edge" (kinachotumika na Focus). + +**Majadiliano:** + +`uri`: URI ya uchaguzi wa "edge". +`graph`: Grafu iliyoitwa ya kuchunguza. +`user`: Kitambulisho cha mtumiaji/nafasi. +`collection`: Kitambulisho cha mkusanyiko. + +**Inarudi:** EdgeSelection au None ikiwa haipatikani. + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +Kuchukua na kueleza kitu (entity) kwa kutumia URI, na kusimamia utaratibu wa uthabiti. + +Hutumia utambuzi wa utulivu: +1. Kuchukua data (triples) kwa URI +2. Ikiwa hakuna matokeo, jaribu tena +3. Ikiwa kuna matokeo, subiri na chukua tena +4. Ikiwa matokeo ni sawa, data imetulia - changanua na urudishe +5. Ikiwa matokeo ni tofauti, data bado inaanzishwa - jaribu tena + +**Vigezo:** + +`uri`: URI ya kitu (entity) kinachohitajika +`graph`: Picha (graph) inayotumika kwa utafutaji (e.g., "urn:graph:retrieval") +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko + +**Inarudisha:** Kifaa cha aina ya ExplainEntity au None ikiwa haipatikani + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +Kuchukua kitu (entity) cha "Focus" na uteuzi wake wote wa "edge". + +**Vigezo:** + +`uri`: URI ya kitu (entity) cha "Focus" +`graph`: Picha (graph) inayotumika kwa utafutaji +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko + +**Inarudisha:** "Focus" iliyo na "edge_selections" zilizojazwa, au None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Kuchukua "GraphRAG" kamili kuanzia URI ya swali. + +Ifuatilia mnyororo wa asili: Swali -> Uthabiti -> Uchunguzi -> Focus -> Muhtasari + +**Vigezo:** + +`question_uri`: URI ya swali +`graph`: Picha (default: urn:graph:retrieval) +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`api`: Ena ya TrustGraph API kwa ufikiaji wa "librarian" (hiari) +`max_content`: Urefu wa juu wa yaliyomo kwa ajili ya muhtasari + +**Inarudisha:** Kamusi yenye vitu vya swali, msingi, uchunguzi, lengo, na muhtasari. + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +Orodha ya vipindi vyote vya kufafanua (maswali) katika mkusanyiko. + +**Majadiliano:** + +`graph`: Picha iliyopewa jina (ya kawaida: urn:graph:retrieval) +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko +`limit`: Nambari ya juu ya vipindi kurudishwa + +**Inarudisha:** Orodha ya vitu vya Swali vilivyopangwa kwa wakati (vya hivi karibuni kwanza) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +Tatua lebo kwa vipengele vyote vya triplet ya ukingo. + +**Majadiliano:** + +`edge`: Kamusi yenye funguo za "s", "p", na "o" +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko + +**Inarudisha:** Jozi ya (s_label, p_label, o_label) + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +Tatua rdfs:label kwa URI, pamoja na kuhifadhi. + +**Majadiliano:** + +`uri`: URI ambayo lebo inapaswa kupatikana +`user`: Kitambulisho cha mtumiaji/nafasi +`collection`: Kitambulisho cha mkusanyiko + +**Inarudisha:** Lebo ikiwa imepatikana, vinginevyo URI yenyewe. + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +Darasa la msingi kwa vitu vya uelewaji. + +**Vipengele:** + +`uri`: +`entity_type`: + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +Swali la mtumiaji - swali la mtumiaji ambalo lilianzisha kipindi. + +**Vifaa:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +Kitengo cha utafiti - pembejeo/sehemu zilizopatikana kutoka kwenye hifadhi ya maarifa. + +**Vifaa:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +Mfumo wa msingi - pembe zilizochaguliwa pamoja na utaratibu wa akili wa LLM (GraphRAG pekee). + +**Sehemu:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +Kitengo cha muhtasari - jibu la mwisho. + +**Sehemu:** + +`uri`: +`entity_type`: +`document`: + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +Kitengo cha uchambuzi - mzunguko mmoja wa kufikiria/kutenda/kuchunguza (Kwa wakala pekee). + +**Vyunzo:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +Hitimisho la kitengo - jibu la mwisho (Kwa wakala pekee). + +**Sehemu:** + +`uri`: +`entity_type`: +`document`: + +### Mbinu + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +Kichwa kilichochaguliwa pamoja na hoja kutoka hatua ya GraphRAG Focus. + +**Sehemu:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### Mbinu + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +Badilisha triplet katika umbizo la waya kuwa tuples za (s, p, o). + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +Toa thamani kutoka kwenye kamusi ya Term katika umbizo la waya. + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +Mfumo wa data wa RDF unaoonyesha sentensi ya grafu ya maarifa. + +**Sehemu:** + +`s`: +`p`: +`o`: + +### Mbinu + +### `__init__(self, s: str, p: str, o: str) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Unda mnyororo mpya kutoka kwa kitu kilichopewa. Ikiwa encoding au +errors imebainishwa, basi kitu lazima kiwe na buffer ya data +ambayo itafichuliwa kwa kutumia encoding iliyopewa na kidhibiti cha makosa. +Vinginevyo, hurudia matokeo ya kitu.__str__() (ikiwa imefafanuliwa) +au repr(kitu). +encoding huwezeshwa kuwa 'utf-8'. +errors huwezeshwa kuwa 'strict'. + +### Mbinu + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +Unda mnyororo mpya kutoka kwa kitu kilichopewa. Ikiwa encoding au +errors imebainishwa, basi kitu lazima kiwe na buffer ya data +ambayo itafichuliwa kwa kutumia usimbaji (encoding) na kidhibiti cha makosa (error handler) uliobainishwa. +Vinginevyo, hurudia matokeo ya kitu.__str__() (ikiwa imefafanuliwa) +au repr(object). +usimbaji (encoding) huanguka kwa 'utf-8'. +makosa (errors) huanguka kwa 'strict'. + +### Mbinu + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +Kitambulisho cha ufunguo wa usanidi. + +**Sehemu:** + +`type`: +`key`: + +### Mbinu + +### `__init__(self, type: str, key: str) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +Jozi ya ufunguo na thamani ya usanidi. + +**Sehemu:** + +`type`: +`key`: +`value`: + +### Mbinu + +### `__init__(self, type: str, key: str, value: str) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +Meta data kwa hati katika maktaba. + +**Sifa:** + +`parent_id: Parent document ID for child documents (empty for top`: ngazi ya hati + +**Nafasi:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### Mbinu + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +Meta data kwa kazi ya usindikaji hati inayofanya kazi. + +**Vyunzo:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### Mbinu + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +Meta data kwa mkusanyiko wa data. + +Mikusanyiko hutoa uainishaji na kutenganisha kwa mantiki kwa hati na +data ya mfumo wa maarifa. + +**Sifa:** + +`name: Human`: jina la mkusanyiko linalosoma + +**Nafasi:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### Mbinu + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +Anzisha self. Angalia help(type(self)) kwa saini sahihi. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +Darasa la msingi kwa ajili ya vipande vya majibu yanayotumwa. + +Hutumika kwa operesheni za utiririshaji zinazotegemea WebSocket ambapo majibu hutolewa +hatua kwa hatua yanapozalishwa. + +**Vipengele:** + +`content`: +`end_of_message`: + +### Njia + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +Sehemu ya hoja au mchakato wa kufikiri wa wakala. + +Inawakilisha hoja au hatua za upangaji za ndani za wakala wakati wa utekelezaji. +Sehemu hizi zinaonyesha jinsi wakala anavyofikiri kuhusu tatizo. + +**Vifaa:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Mbinu + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +Sehemu ya matokeo au uchunguzi wa matumizi ya zana. + +Inawakilisha matokeo au uchunguzi kutoka kwa matumizi ya zana au kitendo. +Sehemu hizi zinaonyesha kile ambacho wakala alijifunza kutokana na matumizi ya zana. + +**Vifaa:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Mbinu + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +Sehemu ya jibu la mwisho la wakala. + +Inawakilisha jibu la mwisho la wakala kwa swali la mtumiaji baada ya kukamilisha +utaratibu wake na matumizi ya zana. + +**Sifa:** + +`chunk_type: Always "final`: jibu" + +**Nafasi:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### Mbinu + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +Sehemu inayotumika kwa utiririshaji ya RAG (Uundaji Ulioboreshwa na Urekebishaji). + +Inatumika kwa utiririshaji wa majibu kutoka kwa RAG ya grafu, RAG ya hati, kukamilisha maandishi, +na huduma zingine za uundaji. + +**Vipengele:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### Mbinu + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +Anzisha self. Angalia help(type(self)) kwa maelezo sahihi ya muundo. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +Tukio la asili kwa ajili ya uelewaji. + +Hutolewa wakati wa maswali ya GraphRAG wakati hali ya uelewaji imeanzishwa. +Kila tukio linawakilisha nodi ya asili iliyoundwa wakati wa uchakataji wa swali. + +**Vifaa:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### Mbinu + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +Anzisha self. Angalia help(type(self)) kwa ajili ya saini sahihi. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +Inayotokea wakati wa hitilafu za itifaki ya WebSocket. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +Darasa la msingi kwa makosa yote ya huduma ya TrustGraph. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +Kosa la huduma ya wakala. + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +Kosa la huduma ya usanidi. + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +Kosa la upokeaji wa hati kutoka kwa mfumo. + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +Kosa la usimamizi wa mtiririko + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +Kosa la API Gateway + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +Kosa la urejesho la mfumo wa RAG. + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +Kosa la huduma ya LLM. + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +Kosa la kupakia data. + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +Kosa la utafutaji/tazama. + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +Kosa la huduma ya utafutaji kwa lugha. + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +Kosa la huduma ya utafutaji wa data. + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +Kosa katika usindikaji wa ombi. + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +Kosa la huduma ya maswali iliyopangwa. + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +Kosa lisilotarajiwa/lisilojulikana. + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +Darasa la msingi kwa makosa yote ya huduma ya TrustGraph. + + +-- diff --git a/docs/python-api.tr.md b/docs/python-api.tr.md new file mode 100644 index 00000000..4a55586d --- /dev/null +++ b/docs/python-api.tr.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "TrustGraph Python API Referansı" +parent: "Turkish (Beta)" +--- + +# TrustGraph Python API Referansı + +> **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. + +## Kurulum + +```bash +pip install trustgraph +``` + +## Hızlı Başlangıç + +Tüm sınıflar ve tipler, `trustgraph.api` paketinden içe aktarılmıştır: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## İçindekiler + +### Çekirdek + +[Api](#api) + +### Akış İstemcileri + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### WebSocket İstemcileri + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### Toplu İşlemler + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### Metrikler + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### Veri Tipleri + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### İstisnalar + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +Senkron ve asenkron işlemler için ana TrustGraph API istemcisi. + +Bu sınıf, akış yönetimi, +bilgi grafiği işlemleri, belge işleme, RAG sorguları ve daha fazlası dahil olmak üzere tüm TrustGraph hizmetlerine erişim sağlar. Hem REST tabanlı hem de WebSocket tabanlı iletişim modellerini destekler. + + +İstemci, otomatik kaynak temizliği için bir bağlam yöneticisi olarak kullanılabilir: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### Yöntemler + +### `__aenter__(self)` + +Asenkron bağlam yöneticisine girin. + +### `__aexit__(self, *args)` + +Asenkron bağlam yöneticisinden çıkın ve bağlantıları kapatın. + +### `__enter__(self)` + +Senkron bağlam yöneticisine girin. + +### `__exit__(self, *args)` + +Senkron bağlam yöneticisinden çıkın ve bağlantıları kapatın. + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +TrustGraph API istemciyi başlatın. + +**Argümanlar:** + +`url`: TrustGraph API'si için temel URL (varsayılan: "http://localhost:8088/"") +`timeout`: İstek zaman aşımı süresi (saniye cinsinden) (varsayılan: 60) +`token`: İsteğe bağlı doğrulama için taşıyıcı belirteci + +**Örnek:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +Tüm asenkron istemci bağlantılarını kapatın. + +Bu yöntem, asenkron WebSocket, toplu işlem ve akış bağlantılarını kapatır. +Bu, asenkron bir bağlam yöneticisinden çıkıldığında otomatik olarak çağrılır. + +**Örnek:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +Asenkron toplu işlemler istemcisi alın. + +WebSocket üzerinden asenkron/bekleme tarzı toplu içe/dışa aktarma işlemleri sağlar, +böylece büyük veri kümelerinin verimli bir şekilde işlenmesini sağlar. + +**Döndürür:** AsyncBulkClient: Asenkron toplu işlemler istemcisi + +**Örnek:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +Asenkron, REST tabanlı bir akış istemcisi alın. + +Akış işlemlerine, async/await stili erişim sağlar. Bu, asenkron Python uygulamaları ve çerçeveleri (FastAPI, aiohttp, vb.) için tercih edilir. + + +**Döndürür:** AsyncFlow: Asenkron akış istemcisi + +**Örnek:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +Asenkron bir metrik istemcisi alın. + +Prometheus metriklerine, async/await tarzında erişim sağlar. + +**Döndürür:** AsyncMetrics: Asenkron metrik istemcisi + +**Örnek:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +Akış işlemleri için asenkron bir WebSocket istemcisi alın. + +Akış desteği ile asenkron/bekleme tarzı WebSocket erişimi sağlar. +Bu, Python'da asenkron akış için tercih edilen yöntemdir. + +**Döndürür:** AsyncSocketClient: Asenkron WebSocket istemcisi + +**Örnek:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +İçe/dışa aktarım için senkron toplu işlemler istemcisi alın. + +Toplu işlemler, üçlüler, gömülü veriler, varlık bağlamları ve nesneler dahil olmak üzere büyük veri kümelerinin WebSocket bağlantıları aracılığıyla verimli bir şekilde aktarılmasını sağlar. + +**Döndürür:** BulkClient: Senkron toplu işlemler istemcisi + +**Örnek:** + + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +Tüm senkronize istemci bağlantılarını kapatın. + +Bu yöntem, WebSocket ve toplu işlem bağlantılarını kapatır. +Bir bağlam yöneticisinden çıkılırken otomatik olarak çağrılır. + +**Örnek:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +Veri koleksiyonlarını yönetmek için bir Collection istemcisi alın. + +Koleksiyonlar, belgeleri ve bilgi grafiği verilerini, +izolasyon ve erişim kontrolü için mantıksal gruplara ayırır. + +**Döndürür:** Collection: Koleksiyon yönetimi istemcisi + +**Örnek:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +Yapılandırma ayarlarını yönetmek için bir Config istemcisi alın. + +**Döndürür:** Config: Yapılandırma yönetimi istemcisi + +**Örnek:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +Akışları yönetmek ve etkileşim kurmak için bir Flow istemcisi edinin. + +Akışlar, TrustGraph'ta birincil yürütme birimleridir ve ajanlar, RAG sorguları, gömme ve belge işleme gibi +hizmetlere erişim sağlar. + +**Döndürür:** Flow: Akış yönetimi istemcisi + +**Örnek:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +Bilgi grafiği çekirdeklerini yönetmek için bir Knowledge istemcisi edinin. + +**Döndürür:** Knowledge: Bilgi grafiği yönetimi istemcisi + +**Örnek:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +Belge yönetimi için bir Kütüphane istemcisi edinin. + +Bu kütüphane, belge depolama, meta veri yönetimi ve +iş akışı koordinasyonu sağlar. + +**Döndürür:** Library: Belge kütüphanesi yönetimi istemcisi + +**Örnek:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +İzleme için senkron bir ölçüm istemcisi alın. + +İzleme ve gözlemlenebilirlik için TrustGraph hizmetinden Prometheus formatında ölçümleri alır. + +**Döndürür:** Ölçümler: Senkron ölçüm istemcisi + + +**Örnek:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +Düşük seviyeli bir REST API isteği yapın. + +Bu yöntem öncelikle dahili kullanım içindir, ancak gerektiğinde doğrudan +API erişimi için kullanılabilir. + +**Argümanlar:** + +`path`: API uç noktası yolu (temel URL'ye göre) +`request`: İstek yükü, bir sözlük olarak + +**Döndürür:** dict: Yanıt nesnesi + +**Hatalar:** + +`ProtocolException`: Yanıt durum kodu 200 değilse veya yanıt JSON değilse +`ApplicationException`: Yanıt bir hata içeriyorsa + +**Örnek:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +Akış işlemleri için senkron bir WebSocket istemcisi alın. + +WebSocket bağlantıları, gerçek zamanlı yanıtlar için akış desteği sağlar +ajanlardan, RAG sorgularından ve metin tamamlama işlemlerinden. Bu yöntem, WebSocket protokolünün +senkron bir sarmalayıcısını döndürür. + +**Döndürür:** SocketClient: Senkron WebSocket istemcisi + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +Blueprint ve akış örneği işlemlerini gerçekleştirmek için kullanılan akış yönetimi istemcisi. + +Bu sınıf, akış blueprint'larını (şablonları) ve +akış örneklerini (çalışan akışları) yönetmek için yöntemler sağlar. Blueprint'ler, akışların yapısını ve +parametrelerini tanımlarken, örnekler, hizmetleri çalıştırabilen aktif akışları temsil eder. + + +### Yöntemler + +### `__init__(self, api)` + +Akış istemcisini başlat. + +**Argümanlar:** + +`api`: İstekler göndermek için kullanılan üst düzey Api örneği. + +### `delete_blueprint(self, blueprint_name)` + +Bir akış blueprint'ini sil. + +**Argümanlar:** + +`blueprint_name`: Silinecek blueprint'in adı. + +**Örnek:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +Çalışan bir akış örneğinin tanımını alın. + +**Argümanlar:** + +`id`: Akış örneği kimliği + +**Döndürür:** dict: Akış örneği tanımı + +**Örnek:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +Bir akış şema tanımını ada göre alın. + +**Argümanlar:** + +`blueprint_name`: Alınacak şemanın adı + +**Döndürür:** dict: Şema tanımı bir sözlük olarak + +**Örnek:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +Belirli bir akış üzerinde işlemler yürütmek için bir FlowInstance alın. + +**Argümanlar:** + +`id`: Akış tanımlayıcısı (varsayılan: "default") + +**Döndürür:** FlowInstance: Servis işlemleri için akış örneği + +**Örnek:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +Tüm aktif akış örneklerini listele. + +**Döndürür:** list[str]: Akış örnekleri kimliklerinin listesi + +**Örnek:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +Mevcut tüm akış şemalarını listele. + +**Döndürür:** list[str]: Şema adlarının listesi + +**Örnek:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +Bir akış şemasını oluştur veya güncelle. + +**Argümanlar:** + +`blueprint_name`: Şema için isim +`definition`: Şema tanım sözlüğü + +**Örnek:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +Akış kapsamlı bir API isteği yapın. + +**Argümanlar:** + +`path`: Akış uç noktaları için isteğe bağlı yol soneki +`request`: İstek yükü sözlüğü + +**Döndürür:** dict: Yanıt nesnesi + +**Hatalar:** + +`RuntimeError`: İstek parametresi belirtilmediyse + +### `start(self, blueprint_name, id, description, parameters=None)` + +Bir şablondan yeni bir akış örneği başlatın. + +**Argümanlar:** + +`blueprint_name`: Oluşturulacak şablonun adı +`id`: Akış örneği için benzersiz tanımlayıcı +`description`: İnsan tarafından okunabilir açıklama +`parameters`: İsteğe bağlı parametreler sözlüğü + +**Örnek:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +Çalışan bir akış örneğini durdurun. + +**Argümanlar:** + +`id`: Durdurulacak akış örneği kimliği + +**Örnek:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +Belirli bir akış üzerinde hizmetleri çalıştırmak için kullanılan akış örneği istemcisi. + +Bu sınıf, aşağıdaki TrustGraph hizmetlerine erişim sağlar: +Metin tamamlama ve gömme +Durum yönetimi ile birlikte aracı işlemleri +Grafik ve belge RAG sorguları +Bilgi grafiği işlemleri (üçlüler, nesneler) +Belge yükleme ve işleme +Doğal dili GraphQL sorgusuna dönüştürme +Yapılandırılmış veri analizi ve şema algılama +MCP aracı yürütme +İstek şablonlama + +Hizmetler, ID ile tanımlanan çalışan bir akış örneği aracılığıyla erişilir. + +### Yöntemler + +### `__init__(self, api, id)` + +FlowInstance'ı başlat. + +**Argümanlar:** + +`api`: Üst akış istemcisi +`id`: Akış örneği tanımlayıcısı + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +Akıl yürütme ve araç kullanma yetenekleriyle bir aracı işlemi yürüt. + +Aracıların çok adımlı akıl yürütme yapabilmesi, araçları kullanabilmesi ve etkileşimler arasında konuşma +durumunu koruyabilmesi mümkündür. Bu, senkron, akışsız bir versiyondur. + +**Argümanlar:** + +`question`: Kullanıcı sorusu veya talimatı +`user`: Kullanıcı tanımlayıcısı (varsayılan: "trustgraph") +`state`: Durumlu konuşmalar için isteğe bağlı durum sözlüğü +`group`: Çok kullanıcılı bağlamlar için isteğe bağlı grup tanımlayıcısı +`history`: İsteğe bağlı olarak mesaj sözlükleri listesi olarak konuşma geçmişi + +**Döndürür:** str: Aracının son cevabı + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +Yapılandırılmış bir veri örneğinin veri türünü tespit edin. + +**Argümanlar:** + +`sample`: Analiz edilecek veri örneği (metin içeriği) + +**Döndürür:** tespit_türü, güven ve isteğe bağlı meta verileri içeren bir sözlük. + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +Birleşik veri tanılama işlemini gerçekleştirin: türü tespit edin ve tanımlayıcı oluşturun. + +**Argümanlar:** + +`sample`: Analiz edilecek veri örneği (metin içeriği) +`schema_name`: İsteğe bağlı, tanımlayıcı oluşturmak için hedef şema adı +`options`: İsteğe bağlı parametreler (örneğin, CSV için ayraç) + +**Döndürür:** tespit_türü, güven, tanımlayıcı ve meta verileri içeren bir sözlük. + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +Anlamsal benzerlik kullanarak belge parçalarına sorgu yapın. + +Vektör gömüler kullanarak, içeriği giriş metnine anlamsal olarak benzeyen belge parçalarını bulur. + + +**Argümanlar:** + +`text`: Anlamsal arama için sorgu metni +`user`: Kullanıcı/keyspace tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`limit`: Maksimum sonuç sayısı (varsayılan: 10) + +**Döndürür:** dict: Parçaları içeren sonuçlar, chunk_id ve puan ile birlikte. + +**Örnek:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +Belge tabanlı Geliştirilmiş Bilgi Alma (RAG) sorgusunu çalıştırın. + +Belge RAG, ilgili belge parçalarını bulmak için vektör gömülerini kullanır, +ardından bu parçaları bağlam olarak kullanarak bir LLM ile bir yanıt oluşturur. + +**Argümanlar:** + +`query`: Doğal dil sorgusu +`user`: Kullanıcı/keyspace tanımlayıcısı (varsayılan: "trustgraph") +`collection`: Koleksiyon tanımlayıcısı (varsayılan: "default") +`doc_limit`: Alınacak maksimum belge parçası sayısı (varsayılan: 10) + +**Döndürür:** str: Belge bağlamını içeren oluşturulan yanıt + +**Örnek:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +Bir veya daha fazla metin için vektör gömme işlemleri gerçekleştirin. + +Metinleri, semantik +arama ve benzerlik karşılaştırması için uygun olan yoğun vektör gösterimlerine dönüştürür. + +**Argümanlar:** + +`texts`: Gömülecek giriş metinlerinin listesi + +**Döndürür:** list[list[list[float]]]: Vektör gömmeleri, her giriş metni için bir set. + +**Örnek:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +Belirli bir şemaya yapılandırılmış veri eşlemesi için bir tanımlayıcı oluşturun. + +**Argümanlar:** + +`sample`: Analiz edilecek veri örneği (metin içeriği) +`data_type`: Veri türü (csv, json, xml) +`schema_name`: Tanımlayıcı oluşturmak için hedef şema adı +`options`: İsteğe bağlı parametreler (örneğin, CSV için ayraç) + +**Döndürür:** tanımlayıcı ve meta verileri içeren sözlük + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +Anlamsal benzerlik kullanarak bilgi grafiği varlıklarını sorgulayın. + +Vektör gömüler kullanarak, giriş metnine anlamsal olarak +benzer açıklamaları olan bilgi grafiğindeki varlıkları bulur. + +**Argümanlar:** + +`text`: Anlamsal arama için sorgu metni +`user`: Kullanıcı/keyspace tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`limit`: Maksimum sonuç sayısı (varsayılan: 10) + +**Döndürür:** dict: Benzer varlıklarla birlikte sorgu sonuçları + +**Örnek:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +Grafik tabanlı, Bilgiyle Zenginleştirilmiş Üretim (RAG) sorgusunu çalıştırın. + +Grafik RAG, ilgili bağlamı bulmak için bilgi grafiği yapısını kullanarak, varlık ilişkilerini +izleyerek ve ardından bir LLM kullanarak bir yanıt oluşturur. + +**Argümanlar:** + +`query`: Doğal dil sorgusu +`user`: Kullanıcı/veri kümesi tanımlayıcısı (varsayılan: "trustgraph") +`collection`: Koleksiyon tanımlayıcısı (varsayılan: "default") +`entity_limit`: Alınacak maksimum varlık sayısı (varsayılan: 50) +`triple_limit`: Her varlık için maksimum üçlü sayısı (varsayılan: 30) +`max_subgraph_size`: Alt grafik içindeki maksimum toplam üçlü sayısı (varsayılan: 150) +`max_path_length`: Maksimum gezinme derinliği (varsayılan: 2) + +**Döndürür:** str: Grafik bağlamını içeren oluşturulmuş yanıt + +**Örnek:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +Bir belgeyi işleme için yükleyin. + +Bir belgeyi (PDF, DOCX, resimler, vb.) çıkarma ve +iş akışının belge işleme hattı aracılığıyla işlenmesi için yükleyin. + +**Argümanlar:** + +`document`: Belge içeriği (bayt olarak) +`id`: İsteğe bağlı belge tanımlayıcısı (None ise otomatik olarak oluşturulur) +`metadata`: İsteğe bağlı meta veri (Üçlüler listesi veya emit yöntemine sahip nesne) +`user`: Kullanıcı/veri alanı tanımlayıcısı (isteğe bağlı) +`collection`: Koleksiyon tanımlayıcısı (isteğe bağlı) + +**Döndürür:** dict: İşleme yanıtı + +**Hatalar:** + +`RuntimeError`: Meta veri sağlanırsa ancak kimlik belirtilmezse + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +İşlenmek üzere metin içeriğini yükleyin. + +Metin içeriğini, akışın metin işleme hattı aracılığıyla çıkarma ve işleme için yükler. + + +**Argümanlar:** + +`text`: Metin içeriği (bayt olarak) +`id`: İsteğe bağlı belge tanımlayıcısı (None ise otomatik olarak oluşturulur) +`metadata`: İsteğe bağlı meta veri (Üçlüler listesi veya emit yöntemine sahip nesne) +`charset`: Karakter kodlaması (varsayılan: "utf-8") +`user`: Kullanıcı/keyspace tanımlayıcısı (isteğe bağlı) +`collection`: Koleksiyon tanımlayıcısı (isteğe bağlı) + +**Döndürür:** dict: İşleme yanıtı + +**Hatalar:** + +`RuntimeError`: Meta veri sağlanmış ancak id belirtilmemişse + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +Bir Model Bağlam Protokolü (MCP) aracını çalıştırın. + +MCP araçları, ajanlar ve iş akışları için genişletilebilir işlevsellik sağlar, +ve harici sistemler ve hizmetlerle entegrasyon imkanı sunar. + +**Argümanlar:** + +`name`: Araç adı/tanımlayıcı +`parameters`: Araç parametreleri sözlüğü (varsayılan: {}) + +**Döndürür:** str veya dict: Aracın çalıştırma sonucu + +**Hatalar:** + +`ProtocolException`: Yanıt formatı geçersizse + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +Doğal bir dil sorusunu GraphQL sorgusuna dönüştürün. + +**Argümanlar:** + +`question`: Doğal dil sorusu +`max_results`: Döndürülecek maksimum sonuç sayısı (varsayılan: 100) + +**Döndürür:** graphql_query, variables, detected_schemas, confidence alanlarını içeren bir sözlük. + +### `prompt(self, id, variables)` + +Değişken yerleştirmesiyle bir istem şablonunu çalıştırın. + +İstek şablonları, dinamik değişkenlerle yeniden kullanılabilir istek kalıplarına olanak tanır ve tutarlı istek mühendisliği için kullanışlıdır. + + +**Argümanlar:** + +`id`: İstek şablonu tanımlayıcısı +`variables`: Değişken adı ile değer eşlemelerinin sözlüğü + +**Döndürür:** str veya dict: Oluşturulmuş istek sonucu (metin veya yapılandırılmış nesne) + +**Hatalar:** + +`ProtocolException`: Yanıt formatı geçersizse + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +Bu işlem örneği üzerinden bir hizmet isteği oluşturun. + +**Parametreler:** + +`path`: Hizmet yolu (örneğin, "service/text-completion") +`request`: İstek yükü sözlüğü + +**Dönüş:** dict: Hizmet yanıtı + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +İndekslenmiş alanlar üzerinde semantik benzerlik kullanarak satır verilerini sorgulayın. + +İndeksli alan değerlerinin, vektör gömüler kullanılarak, giriş metnine anlamsal olarak benzer olduğu satırları bulur. Bu, yapılandırılmış veriler üzerinde bulanık/anlamsal eşleşme sağlar. + +**Argümanlar:** + + + +`text`: Anlamsal arama için sorgu metni +`schema_name`: İçinde arama yapılacak şema adı +`user`: Kullanıcı/veri tabanı tanımlayıcısı (varsayılan: "trustgraph") +`collection`: Koleksiyon tanımlayıcısı (varsayılan: "default") +`index_name`: Aramayı belirli bir indekse sınırlamak için isteğe bağlı indeks adı +`limit`: Maksimum sonuç sayısı (varsayılan: 10) + +**Döndürür:** dict: Eşleşmeleri içeren, index_name, index_value, text ve score alanlarını içeren sorgu sonuçları + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +Bilgi grafiğindeki yapılandırılmış satırlara karşı bir GraphQL sorgusu çalıştırın. + +GraphQL sözdizimini kullanarak yapılandırılmış verileri sorgular, bu sayede filtreleme, toplama ve ilişki taraması gibi karmaşık sorgular +mümkün hale gelir. + +**Parametreler:** + +`query`: GraphQL sorgu dizesi +`user`: Kullanıcı/veri alanı tanımlayıcısı (varsayılan: "trustgraph") +`collection`: Koleksiyon tanımlayıcısı (varsayılan: "default") +`variables`: İsteğe bağlı sorgu değişkenleri sözlüğü +`operation_name`: Çoklu işlem belgeleri için isteğe bağlı işlem adı + +**Döndürür:** dict: 'data', 'errors' ve/veya 'extensions' alanlarına sahip GraphQL yanıtı + +**Hatalar:** + +`ProtocolException`: Sistem düzeyinde bir hata oluşursa + +**Örnek:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +Bir veri örneği için, istem analizi kullanarak eşleşen şemaları seçin. + +**Argümanlar:** + +`sample`: Analiz edilecek veri örneği (metin içeriği) +`options`: İsteğe bağlı parametreler + +**Döndürür:** schema_matches dizisi ve meta veriler içeren bir sözlük. + +### `structured_query(self, question, user='trustgraph', collection='default')` + +Yapılandırılmış verilere karşı doğal dil sorgusu yürütün. +NLP sorgu dönüşümü ve GraphQL yürütmeyi birleştirir. + +**Argümanlar:** + +`question`: Doğal dil sorgusu +`user`: Cassandra keyspace tanımlayıcısı (varsayılan: "trustgraph") +`collection`: Veri koleksiyonu tanımlayıcısı (varsayılan: "default") + +**Döndürür:** veri ve isteğe bağlı hataları içeren bir sözlük. + +### `text_completion(self, system, prompt)` + +İş akışının LLM'sini kullanarak metin tamamlama işlemini yürütün. + +**Argümanlar:** + +`system`: Yardımcının davranışını tanımlayan sistem istemi +`prompt`: Kullanıcı istemi/sorusu + +**Döndürür:** str: Oluşturulan yanıt metni + +**Örnek:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +Desen eşleştirme kullanarak bilgi grafiği üçlülerini sorgulayın. + +Belirtilen konu, yüklem ve/veya +nesne desenlerine uyan RDF üçlülerini arar. Belirtilmemiş parametreler, joker karakter olarak işlev görür. + +**Argümanlar:** + +`s`: Konu URI'si (isteğe bağlı, joker karakter için None kullanın) +`p`: Yüklem URI'si (isteğe bağlı, joker karakter için None kullanın) +`o`: Nesne URI'si veya Literal (isteğe bağlı, joker karakter için None kullanın) +`user`: Kullanıcı/veri tabanı tanımlayıcısı (isteğe bağlı) +`collection`: Koleksiyon tanımlayıcısı (isteğe bağlı) +`limit`: Döndürülecek maksimum sonuç sayısı (varsayılan: 10000) + +**Döndürür:** list[Triple]: Eşleşen Triple nesnelerinin listesi + +**Hatalar:** + +`RuntimeError`: s veya p bir Uri değilse veya o bir Uri/Literal değilse + +**Örnek:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +REST API'sini kullanan asenkron akış yönetimi istemcisi. + +Listeleme, +akışları başlatma, durdurma ve akış sınıf tanımlarını yönetme gibi, async/await tabanlı akış yönetimi işlemleri sağlar. Ayrıca, ajanlar, RAG ve sorgular gibi akış kapsamlı hizmetlere, akış olmayan REST uç noktaları aracılığıyla erişim sağlar. + +Not: Akış desteği için, AsyncSocketClient'ı kullanın. + +### Yöntemler + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Asenkron akış istemciyi başlat. + +**Argümanlar:** + +`url`: TrustGraph API'si için temel URL +`timeout`: İstek zaman aşımı (saniye cinsinden) +`token`: Kimlik doğrulama için isteğe bağlı taşıyıcı belirteci + +### `aclose(self) -> None` + +Asenkron istemciyi kapatın ve kaynakları temizleyin. + +Not: Temizleme, aiohttp oturum bağlam yöneticileri tarafından otomatik olarak yapılır. +Bu yöntem, diğer asenkron istemcilerle tutarlılık sağlamak için sağlanmıştır. + +### `delete_class(self, class_name: str)` + +Bir akış sınıf tanımını silin. + +Sistemden bir akış sınıf şablonunu kaldırır. Çalışan akış örneklerini etkilemez. + + +**Argümanlar:** + +`class_name`: Silinecek akış sınıf adı + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +Akış tanımını al. + +Sınıf adı, +açıklaması ve parametreleri dahil olmak üzere eksiksiz akış yapılandırmasını alır. + +**Argümanlar:** + +`id`: Akış tanımlayıcısı + +**Döndürür:** dict: Akış tanımı nesnesi + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +Akış sınıfı tanımını alın. + +Bir akış sınıfının, yapılandırma şeması ve hizmet bağlamaları dahil olmak üzere, temel tasarım tanımını alır. + + +**Parametreler:** + +`class_name`: Akış sınıfı adı + +**Döndürür:** dict: Akış sınıfı tanım nesnesi + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +Asenkron akış örneği istemciyi alın. + +Belirli bir akışın hizmetleriyle etkileşim kurmak için bir istemci döndürür +(ajan, RAG, sorgular, gömme vb.). + +**Argümanlar:** + +`flow_id`: Akış tanımlayıcısı + +**Döndürür:** AsyncFlowInstance: Akışa özel işlemler için istemci + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +Tüm akış tanımlayıcılarını listele. + +Sistemde şu anda dağıtılmış olan tüm akışların kimliklerini alır. + +**Döndürür:** list[str]: Akış tanımlayıcılarının listesi + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +Tüm akış sınıfı adlarını listele. + +Sistemdeki mevcut tüm akış sınıfı (şablon) adlarını alır. + +**Döndürür:** list[str]: Akış sınıfı adlarının listesi + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +Bir akış sınıf tanımını oluşturun veya güncelleyin. + +Akışları örneklemek için kullanılabilecek bir akış sınıf şablonunu saklar. + +**Argümanlar:** + +`class_name`: Akış sınıf adı +`definition`: Akış sınıf tanımı nesnesi + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Gateway API'sine asenkron HTTP POST isteği gönderin. + +TrustGraph API'sine kimlik doğrulaması yapılmış istekler göndermek için kullanılan iç metot. + +**Argümanlar:** + +`path`: API uç noktası yolu (temel URL'ye göre) +`request_data`: İstek yükü sözlüğü + +**Döndürür:** dict: API'den gelen yanıt nesnesi + +**Hatalar:** + +`ProtocolException`: HTTP durum kodu 200 değilse veya yanıt geçerli bir JSON değilse +`ApplicationException`: API bir hata yanıtı döndürürse + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +Yeni bir akış örneği başlatın. + +Belirtilen parametrelerle, bir akış sınıf tanımından bir akış oluşturur ve başlatır. + + +**Argümanlar:** + +`class_name`: Oluşturulacak akış sınıfının adı +`id`: Yeni akış örneği için tanımlayıcı +`description`: Akışın insan tarafından okunabilir açıklaması +`parameters`: Akış için isteğe bağlı yapılandırma parametreleri + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +Çalışan bir akışı durdur. + +Bir akış örneğini durdurur ve kaldırır, böylece kaynakları serbest bırakılır. + +**Argümanlar:** + +`id`: Durdurulacak akış tanımlayıcısı + +**Örnek:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +Asenkron akış örneği istemcisi. + +Ajanlar, +RAG sorguları, gömülme işlemleri ve grafik sorguları dahil olmak üzere akış kapsamındaki hizmetlere asenkron/bekleme erişimi sağlar. Tüm işlemler, eksiksiz +yanıtları (akışsız) döndürür. + +Not: Akış desteği için, AsyncSocketFlowInstance'ı kullanın. + +### Yöntemler + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +Asenkron akış örneğini başlatır. + +**Argümanlar:** + +`flow`: Üst düzey AsyncFlow istemcisi +`flow_id`: Akış tanımlayıcısı + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +Bir ajan işlemini (akışsız) yürütür. + +Bir soruyu yanıtlamak için bir ajan çalıştırır, isteğe bağlı konuşma durumu ve +geçmişi ile. Ajan işleme işlemini tamamladıktan sonra eksiksiz yanıtı döndürür. + + +Not: Bu yöntem akışı desteklemez. Gerçek zamanlı ajan düşünceleri ve +gözlemler için, AsyncSocketFlowInstance.agent() yöntemini kullanın. + +**Argümanlar:** + +`question`: Kullanıcı sorusu veya talimatı +`user`: Kullanıcı tanımlayıcısı +`state`: İsteğe bağlı, konuşma bağlamı için durum sözlüğü +`group`: İsteğe bağlı, oturum yönetimi için grup tanımlayıcısı +`history`: İsteğe bağlı, konuşma geçmişi listesi +`**kwargs`: Ek, hizmete özgü parametreler + +**Döndürür:** dict: Cevap ve meta verileri içeren eksiksiz ajan yanıtı + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +Belge tabanlı RAG sorgusunu (akışsız) çalıştırın. + +Belge gömüler kullanarak, bilgi artırılmış metin oluşturma işlemini gerçekleştirir. +Anlamsal arama yoluyla ilgili belge parçalarını alır ve ardından alınan belgelerle +ilişkili bir yanıt oluşturur. Tam yanıtı döndürür. + +Not: Bu yöntem akışı desteklemez. Akışlı RAG yanıtları için, +bunun yerine AsyncSocketFlowInstance.document_rag() yöntemini kullanın. + +**Argümanlar:** + +`query`: Kullanıcı sorgusu metni +`user`: Kullanıcı kimliği +`collection`: Belgeleri içeren koleksiyon kimliği +`doc_limit`: Alınacak maksimum belge parçası sayısı (varsayılan: 10) +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** str: Belge verilerine dayalı olarak oluşturulan tam yanıt + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +Girdi metinleri için gömme (embedding) oluşturur. + +Metinleri, akışın yapılandırılmış gömme modelini kullanarak sayısal vektör gösterimlerine dönüştürür. Anlamsal arama ve benzerlik +karşılaştırmaları için kullanışlıdır. + + +**Argümanlar:** + +`texts`: Gömülecek girdi metinlerinin listesi +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** dict: Gömme vektörlerini içeren yanıt + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +Anlamsal varlık araması için grafik gömme verilerini sorgular. + +Varlıkların anlamsal olarak aranmasını, grafik varlık gömmeleri üzerinde gerçekleştirerek, giriş metnine en uygun varlıkları bulur. Benzerliğe göre sıralanmış varlıkları döndürür. + + +**Argümanlar:** + +`text`: Anlamsal arama için sorgu metni +`user`: Kullanıcı kimliği +`collection`: Grafik gömmelerini içeren koleksiyon kimliği +`limit`: Döndürülecek maksimum sonuç sayısı (varsayılan: 10) +`**kwargs`: Ek hizmete özel parametreler + +**Döndürür:** dict: Sıralanmış varlık eşleşmelerini ve benzerlik puanlarını içeren yanıt + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +Grafik tabanlı RAG sorgusunu (akışsız) çalıştırın. + +Bilgi grafi veri kullanarak, bilgiyle zenginleştirilmiş metin üretimi gerçekleştirir. +İlgili varlıkları ve bunların ilişkilerini belirler, ardından grafiğin yapısına dayalı olarak bir +yanıt oluşturur. Tam yanıtı döndürür. + +Not: Bu yöntem akışı desteklemez. Akışlı RAG yanıtları için, bunun yerine AsyncSocketFlowInstance.graph_rag() kullanın. + + +**Argümanlar:** + +`query`: Kullanıcı sorgusu metni +`user`: Kullanıcı kimliği +`collection`: Bilgi grafiğini içeren koleksiyon kimliği +`max_subgraph_size`: Her alt grafik için maksimum üçlü sayısı (varsayılan: 1000) +`max_subgraph_count`: Alınacak maksimum alt grafik sayısı (varsayılan: 5) +`max_entity_distance`: Varlık genişletmesi için maksimum grafik mesafesi (varsayılan: 3) +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** str: Grafik verilerine dayalı olarak oluşturulan tam yanıt + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +Bir akış kapsamındaki bir hizmete istek gönderin. + +Bu akış örneği içindeki hizmetleri çağırmak için kullanılan iç metot. + +**Argümanlar:** + +`service`: Hizmet adı (örneğin, "agent", "graph-rag", "triples") +`request_data`: Hizmet isteği yükü + +**Döndürür:** dict: Hizmet yanıt nesnesi + +**Hatalar:** + +`ProtocolException`: İstek başarısız olursa veya yanıt geçersizse +`ApplicationException`: Hizmet bir hata döndürürse + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +Yapılandırılmış veriler üzerinde semantik arama için satır gömme vektörlerini sorgular. + +Satır indeks gömme vektörleri üzerinde semantik arama gerçekleştirir ve giriş metnine en benzer indeksli alan değerlerine sahip satırları bulur. Yapılandırılmış veriler üzerinde bulanık/semantik eşleşme sağlar. + + +**Argümanlar:** + + +`text`: Semantik arama için sorgu metni +`schema_name`: Arama yapılacak şema adı +`user`: Kullanıcı kimliği (varsayılan: "trustgraph") +`collection`: Koleksiyon kimliği (varsayılan: "default") +`index_name`: Aramayı belirli bir indekse sınırlamak için isteğe bağlı indeks adı +`limit`: Döndürülecek maksimum sonuç sayısı (varsayılan: 10) +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** dict: index_name, index_value, text ve score ile eşleşmeleri içeren yanıt + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +Saklanan satırları kullanarak bir GraphQL sorgusu çalıştırın. + +GraphQL sözdizimini kullanarak yapılandırılmış veri satırlarını sorgular. Değişkenler ve adlandırılmış işlemler içeren karmaşık +sorguları destekler. + +**Argümanlar:** + +`query`: GraphQL sorgu dizesi +`user`: Kullanıcı tanımlayıcısı +`collection`: Satırları içeren koleksiyon tanımlayıcısı +`variables`: İsteğe bağlı GraphQL sorgu değişkenleri +`operation_name`: Çoklu işlem sorguları için isteğe bağlı işlem adı +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** dict: Veri ve/veya hataları içeren GraphQL yanıtı + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +Metin tamamlama oluşturun (akış olmadan). + +Bir sistem istemi ve kullanıcı istemi verildiğinde, bir LLM'den metin yanıtı oluşturur. +Tam yanıt metnini döndürür. + +Not: Bu yöntem akışı desteklemez. Akışlı metin oluşturma için, +bunun yerine AsyncSocketFlowInstance.text_completion() yöntemini kullanın. + +**Argümanlar:** + +`system`: LLM'nin davranışını tanımlayan sistem istemi +`prompt`: Kullanıcı istemi veya sorusu +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** str: Tam oluşturulmuş metin yanıtı + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +Desen eşleştirme kullanarak RDF üçlülerini sorgulayın. + +Belirtilen konu, yüklem ve/veya +nesne desenlerine uyan üçlüleri arar. Desenler, herhangi bir değeri eşleştirmek için "None" değerini joker karakter olarak kullanır. + +**Argümanlar:** + +`s`: Konu deseni (joker karakter için "None") +`p`: Yüklem deseni (joker karakter için "None") +`o`: Nesne deseni (joker karakter için "None") +`user`: Kullanıcı kimliği (tüm kullanıcılar için "None") +`collection`: Koleksiyon kimliği (tüm koleksiyonlar için "None") +`limit`: Döndürülecek maksimum üçlü sayısı (varsayılan: 100) +`**kwargs`: Ek hizmete özgü parametreler + +**Döndürür:** dict: Eşleşen üçlüleri içeren yanıt + +**Örnek:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +Akış işlemleri için senkron WebSocket istemcisi. + +WebSocket tabanlı TrustGraph hizmetlerine senkron bir arayüz sağlar, +kullanımı kolaylaştırmak için senkron oluşturucularla asenkron WebSocket kütüphanesini sarar. +Ajanlardan gelen akış yanıtlarını, RAG sorgularını ve metin tamamlama işlemlerini destekler. + +Not: Bu, asenkron WebSocket işlemlerinin etrafında oluşturulmuş bir senkron katmandır. +Gerçek asenkron destek için AsyncSocketClient'ı kullanın. + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Senkron WebSocket istemcisini başlatın. + +**Argümanlar:** + +`url`: TrustGraph API'si için temel URL (HTTP/HTTPS, WS/WSS'ye dönüştürülecektir) +`timeout`: Saniyeler cinsinden WebSocket zaman aşımı +`token`: İsteğe bağlı kimlik doğrulama için taşıyıcı belirteci + +### `close(self) -> None` + +WebSocket bağlantılarını kapatın. + +Not: Temizleme, asenkron kodda bağlam yöneticileri tarafından otomatik olarak yapılır. + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +WebSocket akış işlemleri için bir akış örneği alın. + +**Argümanlar:** + +`flow_id`: Akış tanımlayıcısı + +**Döndürür:** SocketFlowInstance: Akış yöntemleri içeren akış örneği + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +Akış işlemleri için senkron WebSocket akışı örneği. + +REST FlowInstance ile aynı arayüzü sağlar, ancak gerçek zamanlı yanıtlar için WebSocket tabanlı +akış desteği sunar. Tüm yöntemler, kademeli sonuç teslimini etkinleştirmek için isteğe bağlı +`streaming` parametresini destekler. + +### Yöntemler + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +Soket akışı örneğini başlatır. + +**Argümanlar:** + +`client`: Üst SoketClient +`flow_id`: Akış tanımlayıcısı + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +Akış desteği ile bir ajan işlemi gerçekleştirin. + +Ajanlar, araç kullanımıyla çok aşamalı akıl yürütme yapabilir. Bu yöntem, streaming=False olsa bile, her zaman +akış parçaları (düşünceler, gözlemler, cevaplar) döndürür, böylece ajanın akıl yürütme süreci gösterilir. + + +**Argümanlar:** + +`question`: Kullanıcı sorusu veya talimatı +`user`: Kullanıcı kimliği +`state`: Durumlu konuşmalar için isteğe bağlı durum sözlüğü +`group`: Çok kullanıcılı bağlamlar için isteğe bağlı grup kimliği +`history`: İsteğe bağlı olarak mesaj sözlüklerinin listesi olarak konuşma geçmişi +`streaming`: Akış modunu etkinleştir (varsayılan: False) +`**kwargs`: Ajan hizmetine iletilen ek parametreler + +**Döndürür:** Iterator[StreamingChunk]: Ajanın düşüncelerinin, gözlemlerinin ve cevaplarının akışı + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +Açıklanabilirlik desteğiyle bir ajan işlemini yürütün. + +Hem içerik parçalarını (AgentThought, AgentObservation, AgentAnswer) +ve kaynak olaylarını (ProvenanceEvent) akışa aktarır. Kaynak olayları, ayrıntılı bilgi +almak için ExplainabilityClient kullanılarak alınabilen URI'ler içerir +ve ajanın akıl yürütme süreci hakkında. + +Ajan izi şunlardan oluşur: +Oturum: Başlangıç sorusu ve oturum meta verileri +Yinelemeler: Her düşünce/eylem/gözlem döngüsü +Sonuç: Nihai cevap + +**Argümanlar:** + +`question`: Kullanıcı sorusu veya talimatı +`user`: Kullanıcı tanımlayıcısı +`collection`: Kaynak depolama için koleksiyon tanımlayıcısı +`state`: Durumlu konuşmalar için isteğe bağlı durum sözlüğü +`group`: Çoklu kullanıcı bağlamları için isteğe bağlı grup tanımlayıcısı +`history`: İsteğe bağlı olarak mesaj sözlüklerinin listesi olarak konuşma geçmişi +`**kwargs`: Ajan hizmetine iletilen ek parametreler +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`: Ajan parçaları ve kaynak olayları + +**Örnek:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Anlamlı benzerlik kullanarak belge parçalarını sorgulayın. + +**Argümanlar:** + +`text`: Anlamlı arama için sorgu metni +`user`: Kullanıcı/veri kümesi tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`limit`: Maksimum sonuç sayısı (varsayılan: 10) +`**kwargs`: Hizmete iletilen ek parametreler + +**Dönüş:** dict: Eşleşen belge parçalarının chunk_id'leri ile birlikte sorgu sonuçları + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +Belge tabanlı RAG sorgusunu, isteğe bağlı olarak akış modunda çalıştırın. + +İlgili belge parçalarını bulmak için vektör gömülmelerini kullanır, ardından bir LLM kullanarak +bir yanıt oluşturur. Akış modu, sonuçları kademeli olarak sunar. + +**Argümanlar:** + +`query`: Doğal dil sorgusu +`user`: Kullanıcı/veri kümesi tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`doc_limit`: Alınacak maksimum belge parçası sayısı (varsayılan: 10) +`streaming`: Akış modunu etkinleştir (varsayılan: False) +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** Union[str, Iterator[str]]: Tam yanıt veya metin parçalarının akışı + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Açıklanabilirlik desteğiyle belge tabanlı RAG sorgusunu çalıştırın. + +Hem içerik parçalarını (RAGChunk) hem de kaynak olaylarını (ProvenanceEvent) akışa aktarır. +Kaynak olayları, yanıtın nasıl oluşturulduğuna dair ayrıntılı bilgi almak için ExplainabilityClient kullanılarak alınabilen URI'ler içerir. + + +Belge RAG izi şunlardan oluşur: +Soru: Kullanıcının sorgusu +Keşif: Belge deposundan alınan parçalar (parça_sayısı) +Sentez: Oluşturulan yanıt + +**Argümanlar:** + +`query`: Doğal dil sorgusu +`user`: Kullanıcı/keyspace tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`doc_limit`: Alınacak maksimum belge parçası sayısı (varsayılan: 10) +`**kwargs`: Hizmete iletilen ek parametreler +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: İçerik parçaları ve kaynak olayları + +**Örnek:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +Bir veya daha fazla metin için vektör gömme işlemleri gerçekleştirin. + +**Argümanlar:** + +`texts`: Gömülecek giriş metinlerinin listesi +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** dict: Vektörleri içeren (her giriş metni için bir set) yanıt + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +Anlamsal benzerlik kullanarak bilgi grafiği varlıklarını sorgulayın. + +**Argümanlar:** + +`text`: Anlamsal arama için sorgu metni +`user`: Kullanıcı/veri kümesi tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`limit`: Maksimum sonuç sayısı (varsayılan: 10) +`**kwargs`: Hizmete iletilen ek parametreler + +**Dönüş:** dict: Benzer varlıklarla birlikte sorgu sonuçları + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +İsteğe bağlı akışla, grafik tabanlı RAG sorgusunu çalıştırın. + +İlgili bağlamı bulmak için bilgi grafiği yapısını kullanır, ardından +bir LLM kullanarak bir yanıt oluşturur. Akış modu, sonuçları kademeli olarak sunar. + +**Argümanlar:** + +`query`: Doğal dil sorgusu +`user`: Kullanıcı/veri kümesi tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`max_subgraph_size`: Alt grafikteki maksimum toplam üçlü sayısı (varsayılan: 1000) +`max_subgraph_count`: Maksimum alt grafik sayısı (varsayılan: 5) +`max_entity_distance`: Maksimum gezinme derinliği (varsayılan: 3) +`streaming`: Akış modunu etkinleştir (varsayılan: False) +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** Union[str, Iterator[str]]: Tam yanıt veya metin parçalarının akışı + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +Açıklanabilirlik desteğiyle grafik tabanlı RAG sorgusunu çalıştırın. + +Hem içerik parçalarını (RAGChunk) hem de kaynak olaylarını (ProvenanceEvent) iletir. +Kaynak olayları, yanıtın nasıl oluşturulduğuna dair ayrıntılı bilgi almak için ExplainabilityClient kullanılarak alınabilen URI'ler içerir. + + +**Argümanlar:** + +`query`: Doğal dil sorgusu +`user`: Kullanıcı/keyspace tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`max_subgraph_size`: Alt grafik içindeki maksimum toplam üçlü sayısı (varsayılan: 1000) +`max_subgraph_count`: Maksimum alt grafik sayısı (varsayılan: 5) +`max_entity_distance`: Maksimum gezinme derinliği (varsayılan: 3) +`**kwargs`: Hizmete iletilen ek parametreler +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: İçerik parçaları ve kaynak olayları + +**Örnek:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +Bir Model Bağlam Protokolü (MCP) aracını çalıştırın. + +**Argümanlar:** + +`name`: Araç adı/tanımlayıcı +`parameters`: Araç parametreleri sözlüğü +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** dict: Aracın çalıştırma sonucu + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +İsteğe bağlı akışla bir istem şablonunu yürütün. + +**Argümanlar:** + +`id`: İstem şablonu tanımlayıcısı +`variables`: Değişken adı ile değer eşlemelerinin sözlüğü +`streaming`: Akış modunu etkinleştir (varsayılan: False) +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** Union[str, Iterator[str]]: Tam yanıt veya metin parçacıklarının akışı + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +İndekslenmiş alanlar üzerinde semantik benzerlik kullanarak sorgu satır verilerini alın. + +Giriş metnine semantik olarak benzer olan, indekslenmiş alan değerlerine sahip satırları bulur, vektör gömme teknikleri kullanılarak. Bu, yapılandırılmış veriler üzerinde bulanık/semantik eşleşme +sağlar. + + +**Argümanlar:** + +`text`: Anlamsal arama için sorgu metni +`schema_name`: İçinde arama yapılacak şema adı +`user`: Kullanıcı/veri tabanı tanımlayıcısı (varsayılan: "trustgraph") +`collection`: Koleksiyon tanımlayıcısı (varsayılan: "default") +`index_name`: Aramayı belirli bir indekse sınırlamak için isteğe bağlı indeks adı +`limit`: Maksimum sonuç sayısı (varsayılan: 10) +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** dict: Eşleşmeleri içeren, index_name, index_value, text ve score alanlarını içeren sorgu sonuçları + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +Yapılandırılmış satırlara karşı bir GraphQL sorgusu çalıştırın. + +**Argümanlar:** + +`query`: GraphQL sorgu dizesi +`user`: Kullanıcı/keyspace tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`variables`: İsteğe bağlı sorgu değişkenleri sözlüğü +`operation_name`: Çoklu işlem belgeleri için isteğe bağlı işlem adı +`**kwargs`: Hizmete iletilen ek parametreler + +**Döndürür:** dict: Veri, hatalar ve/veya uzantılar içeren GraphQL yanıtı + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +İsteğe bağlı akışla metin tamamlama işlemini gerçekleştirin. + +**Argümanlar:** + +`system`: Asistanın davranışını tanımlayan sistem istemi +`prompt`: Kullanıcı istemi/sorusu +`streaming`: Akış modunu etkinleştir (varsayılan: False) +`**kwargs`: Hizmete iletilen ek parametreler + +**Dönüş:** Union[str, Iterator[str]]: Tamamlanmış yanıt veya metin parçalarının akışı + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +Desen eşleştirme kullanarak bilgi grafiği üçlülerini sorgulayın. + +**Argümanlar:** + +`s`: Konu filtresi - URI dizesi, Terim sözlüğü veya joker karakter için None +`p`: Özne filtresi - URI dizesi, Terim sözlüğü veya joker karakter için None +`o`: Nesne filtresi - URI/literal dizesi, Terim sözlüğü veya joker karakter için None +`g`: Adlandırılmış grafik filtresi - URI dizesi veya tüm grafikler için None +`user`: Kullanıcı/uzay kimlik tanımlayıcısı (isteğe bağlı) +`collection`: Koleksiyon kimlik tanımlayıcısı (isteğe bağlı) +`limit`: Döndürülecek maksimum sonuç sayısı (varsayılan: 100) +`**kwargs`: Hizmete geçirilecek ek parametreler + +**Döndürür:** List[Dict]: Tel formatındaki eşleşen üçlülerin listesi + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +Akışlı toplu işlemlerle bilgi grafiği üçlülerini sorgulayın. + +Üçlüleri geldikleri gibi toplu olarak döndürür, böylece ilk sonuç alma süresini ve büyük sonuç kümeleri için bellek yükünü azaltır. + + +**Parametreler:** + +`s`: Konu filtresi - URI dizesi, Terim sözlüğü veya joker karakter için None +`p`: Özne filtresi - URI dizesi, Terim sözlüğü veya joker karakter için None +`o`: Nesne filtresi - URI/literal dizesi, Terim sözlüğü veya joker karakter için None +`g`: Adlandırılmış grafik filtresi - URI dizesi veya tüm grafikler için None +`user`: Kullanıcı/keyspace tanımlayıcısı (isteğe bağlı) +`collection`: Koleksiyon tanımlayıcısı (isteğe bağlı) +`limit`: Döndürülecek maksimum sonuç sayısı (varsayılan: 100) +`batch_size`: Toplu işlemdeki üçlü sayısı (varsayılan: 20) +`**kwargs`: Hizmete geçirilecek ek parametreler +`Yields`: +`List[Dict]`: Tel formatındaki üçlü topları + +**Örnek:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +Asenkron WebSocket istemcisi + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None)` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + +### `aclose(self)` + +WebSocket bağlantısını kapat + +### `flow(self, flow_id: str)` + +WebSocket işlemleri için asenkron akış örneğini al + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +Asenkron WebSocket akışı örneği + +### Yöntemler + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +İsteğe bağlı akışa sahip ajan + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +İsteğe bağlı akışa sahip RAG dokümanı + +### `embeddings(self, texts: list, **kwargs)` + +Metin gömülmelerini oluştur + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +Anlamsal arama için grafik gömülmelerini sorgula + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +İsteğe bağlı akışa sahip grafik RAG + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +MCP aracını çalıştır + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +İsteğe bağlı akışa sahip istemi çalıştır + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +Yapılandırılmış veriler üzerinde anlamsal arama için satır gömülmelerini sorgula + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +Yapılandırılmış satırlara karşı GraphQL sorgusu + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +İsteğe bağlı akışa sahip metin tamamlama + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +Üçlü desen sorgusu + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +Bir değerden tel formatlı Term sözlüğünü oluştur. + +Otomatik algılama kuralları (term_type None olduğunda): + Zaten 't' anahtarına sahip bir sözlük -> olduğu gibi döndür (zaten bir Term) + http://, https://, urn: ile başlıyorsa -> IRI + <> (örneğin, ) içinde ise -> IRI (köşeli parantezler kaldırılır) + Başka bir şey -> literal + +**Argümanlar:** + +`value`: Term değeri (string, sözlük veya None) +`term_type`: 'iri', 'literal' veya otomatik algılama için +`datatype`: Literal nesneler için veri türü (örneğin, xsd:integer) +`language`: Literal nesneler için dil etiketi (örneğin, en) + +**Döndürür:** sözlük: Tel formatlı Term sözlüğü veya değer None ise None + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +İçe/dışa aktarım için senkron toplu işlemler istemcisi. + +Büyük veri kümeleri için WebSocket üzerinden verimli toplu veri aktarımı sağlar. +Kullanım kolaylığı için asenkron WebSocket işlemlerini senkron oluşturucularla birleştirir. + +Not: Gerçek asenkron destek için, AsyncBulkClient'ı kullanın. + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Senkron toplu istemciyi başlatır. + +**Argümanlar:** + +`url`: TrustGraph API'si için temel URL (HTTP/HTTPS, WS/WSS'ye dönüştürülecektir). +`timeout`: WebSocket zaman aşımı (saniye cinsinden). +`token`: İsteğe bağlı, kimlik doğrulama için taşıyıcı belirteci. + +### `close(self) -> None` + +Bağlantıları kapatır. + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Bir akıştan toplu belge gömme çıktılarını dışa aktarır. + +Tüm belge parçası gömmelerini WebSocket akışı üzerinden verimli bir şekilde indirir. + +**Argümanlar:** + +`flow`: Akış tanımlayıcısı. +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır). + +**Döndürür:** Iterator[Dict[str, Any]]: Gömme sözlüklerinin akışı. + +**Örnek:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Bir akıştan toplu olarak varlık bağlamlarını dışa aktarın. + +Tüm varlık bağlamı bilgilerini WebSocket akışı aracılığıyla verimli bir şekilde indirir. + +**Argümanlar:** + +`flow`: Akış tanımlayıcısı +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Döndürür:** Iterator[Dict[str, Any]]: Bağlam sözlüklerinin akışı + +**Örnek:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +Bir akıştan toplu grafik gömme verilerini dışa aktarın. + +Tüm grafik varlık gömme verilerini WebSocket üzerinden verimli bir şekilde indirir. + +**Parametreler:** + +`flow`: Akış tanımlayıcısı +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Döndürür:** Iterator[Dict[str, Any]]: Gömme sözlüklerinin akışı + +**Örnek:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +Bir akıştan RDF üçlülerini toplu olarak dışa aktarın. + +Tüm üçlüleri WebSocket akışı aracılığıyla verimli bir şekilde indirir. + +**Argümanlar:** + +`flow`: Akış tanımlayıcısı +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Döndürür:** Iterator[Triple]: Triple nesnelerinin akışı + +**Örnek:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Bir akışa belge gömme verilerini toplu olarak aktarın. + +Belge parçası gömme verilerini, belge RAG sorgularında kullanılmak üzere, WebSocket akışı aracılığıyla verimli bir şekilde yükler. + + +**Argümanlar:** + +`flow`: Akış tanımlayıcısı +`embeddings`: Gömme sözlükleri üreten yineleyici +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Örnek:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Bir akışa toplu olarak varlık bağlamlarını aktarın. + +Varlık bağlamı bilgilerini WebSocket akışı aracılığıyla verimli bir şekilde yükler. +Varlık bağlamları, grafik varlıkları hakkında ek metinsel bağlam sağlar +ve geliştirilmiş RAG performansı için kullanılır. + +**Argümanlar:** + +`flow`: Akış tanımlayıcısı +`contexts`: Bağlam sözlükleri üreten yineleyici +`metadata`: id, metadata, kullanıcı, koleksiyon içeren meta veri sözlüğü +`batch_size`: Toplu iş başına bağlam sayısı (varsayılan 100) +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Örnek:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Bir akışa toplu olarak grafik gömme verilerini aktarın. + +Grafik varlık gömme verilerini WebSocket üzerinden verimli bir şekilde yükleyin. + +**Parametreler:** + +`flow`: Akış tanımlayıcısı +`embeddings`: Gömme sözlükleri üreten yineleyici +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Örnek:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +Bir akışa yapılandırılmış satırları toplu olarak aktarın. + +Yapılandırılmış veri satırlarını, GraphQL sorgularında kullanılmak üzere WebSocket akışı aracılığıyla verimli bir şekilde yükleyin. + + +**Argümanlar:** + +`flow`: Akış tanımlayıcısı +`rows`: Satır sözlükleri üreten yineleyici +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Örnek:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +Bir akışa RDF üçlülerini toplu olarak aktarın. + +Büyük miktarlarda üçlü verisini WebSocket akışı aracılığıyla verimli bir şekilde yükler. + +**Parametreler:** + +`flow`: Akış tanımlayıcısı +`triples`: Triple nesneleri üreten yineleyici +`metadata`: id, metadata, kullanıcı, koleksiyon içeren meta veri sözlüğü +`batch_size`: Her topluluktaki üçlü sayısı (varsayılan 100) +`**kwargs`: Ek parametreler (gelecekteki kullanım için ayrılmıştır) + +**Örnek:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +Asenkron toplu işlemler istemcisi + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + +### `aclose(self) -> None` + +Bağlantıları kapat + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +WebSocket üzerinden belge gömme verilerini toplu olarak dışa aktar + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +WebSocket üzerinden varlık bağlamlarını toplu olarak dışa aktar + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +WebSocket üzerinden grafik gömme verilerini toplu olarak dışa aktar + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +WebSocket üzerinden üçlüleri toplu olarak dışa aktar + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +WebSocket üzerinden belge gömme verilerini toplu olarak içe aktar + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +WebSocket üzerinden varlık bağlamlarını toplu olarak içe aktar + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +WebSocket üzerinden grafik gömme verilerini toplu olarak içe aktar + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +WebSocket üzerinden satırları toplu olarak içe aktar + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +WebSocket üzerinden üçlüleri toplu olarak içe aktar + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +Senkron ölçüm istemcisi + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + +### `get(self) -> str` + +Prometheus ölçümlerini metin olarak al + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +Asenkron metrik istemcisi + +### Yöntemler + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + +### `aclose(self) -> None` + +Bağlantıları kapat + +### `get(self) -> str` + +Prometheus metriklerini metin olarak al + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +Açıklanabilirlik varlıklarını, nihai tutarlılık işleme ile getirmek için kullanılan istemci. + +Aşağıdaki dinlenme algılama yöntemini kullanır: getirme, bekleme, tekrar getirme, karşılaştırma. +Sonuçlar aynıysa, veri kararlıdır. + +### Yöntemler + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +Açıklanabilirlik istemcisini başlat. + +**Argümanlar:** + +`flow_instance`: Üçlüleri sorgulamak için bir SocketFlowInstance. +`retry_delay`: Tekrar denemeler arasındaki gecikme (varsayılan: 0.2). +`max_retries`: Maksimum tekrar deneme sayısı (varsayılan: 10). + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +Bir oturumun GraphRAG veya Agent türünde olup olmadığını tespit edin. + +**Argümanlar:** + +`session_uri`: Oturum/soru URI'si. +`graph`: Adlandırılmış grafik. +`user`: Kullanıcı/keyspace tanımlayıcısı. +`collection`: Koleksiyon tanımlayıcısı. + +**Döndürür:** "graphrag" veya "agent". + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Bir oturum URI'sinden başlayarak, tamamlanmış Agent izini alın. + +Aşağıdaki köken zincirini izleyin: Soru -> Analiz(ler) -> Sonuç. + +**Argümanlar:** + +`session_uri`: Agent oturum/soru URI'si. +`graph`: Adlandırılmış grafik (varsayılan: urn:graph:retrieval). +`user`: Kullanıcı/keyspace tanımlayıcısı. +`collection`: Koleksiyon tanımlayıcısı. +`api`: Kütüphaneci erişimi için TrustGraph Api örneği (isteğe bağlı). +`max_content`: Sonuç için maksimum içerik uzunluğu. + +**Döndürür:** Soru, yinelemeler (Analiz listesi), sonuç varlıkları ile birlikte bir Sözlük. + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Bir soru URI'sinden başlayarak, tamamlanmış DocumentRAG izini alın. + +Aşağıdaki köken zincirini izleyin: + Soru -> Yerleştirme -> Keşif -> Sentez. + +**Argümanlar:** + +`question_uri`: Soru varlık URI'si. +`graph`: Adlandırılmış grafik (varsayılan: urn:graph:retrieval). +`user`: Kullanıcı/keyspace tanımlayıcısı. +`collection`: Koleksiyon tanımlayıcısı. +`api`: Kütüphaneci erişimi için TrustGraph Api örneği (isteğe bağlı). +`max_content`: Sentez için maksimum içerik uzunluğu. + +**Döndürür:** Soru, yerleştirme, keşif, sentez varlıkları ile birlikte bir Sözlük. + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +Bir belge URI'si tarafından kütüphaneciden içerik alın. + +**Argümanlar:** + +`document_uri`: Kütüphanecideki belge URI'si. +`api`: Kütüphaneci erişimi için TrustGraph Api örneği. +`user`: Kütüphaneci için kullanıcı tanımlayıcısı. +`max_content`: Döndürülecek maksimum içerik uzunluğu. + +**Döndürür:** Belge içeriğini bir dize olarak. + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +Bir kenar seçimi varlığı alın (Focus tarafından kullanılır). + +**Argümanlar:** + +`uri`: Kenar seçimi URI'si. +`graph`: Sorgulanacak adlandırılmış grafik. +`user`: Kullanıcı/keyspace tanımlayıcısı. +`collection`: Koleksiyon tanımlayıcısı. + +**Döndürür:** EdgeSelection veya bulunamazsa None. + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +Bir URI'yi, olası tutarlılık yönetimi ile bir açıklanabilirlik varlığı olarak alın. + +Aşağıdaki durgunluk tespitini kullanır: +1. URI için üçlüleri alın +2. Sıfır sonuç varsa, tekrar deneyin +3. Sıfır olmayan sonuçlar varsa, bekleyin ve tekrar alın +4. Aynı sonuçlar varsa, veri kararlıdır - ayrıştırın ve döndürün +5. Farklı sonuçlar varsa, veri hala yazılıyor - tekrar deneyin + +**Argümanlar:** + +`uri`: Alınacak varlık URI'si +`graph`: Sorgulanacak adlandırılmış grafik (örneğin, "urn:graph:retrieval") +`user`: Kullanıcı/anahtar alanı tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı + +**Döndürür:** Açıklanabilir Varlık alt sınıfı veya bulunamazsa None + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +Bir Focus varlığını ve tüm kenar seçimlerini alın. + +**Argümanlar:** + +`uri`: Focus varlık URI'si +`graph`: Sorgulanacak adlandırılmış grafik +`user`: Kullanıcı/anahtar alanı tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı + +**Döndürür:** Doldurulmuş kenar_seçimleri ile Focus veya bulunamazsa None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +Bir soru URI'sinden başlayarak, tamamlanmış GraphRAG izini alın. + +Aşağıdaki köken zincirini izler: Soru -> Yerleştirme -> Keşif -> Focus -> Sentez + +**Argümanlar:** + +`question_uri`: Soru varlık URI'si +`graph`: Adlandırılmış grafik (varsayılan: urn:graph:retrieval) +`user`: Kullanıcı/anahtar alanı tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`api`: Kütüphaneci erişimi için TrustGraph Api örneği (isteğe bağlı) +`max_content`: Sentez için maksimum içerik uzunluğu + +**Döndürür:** Soru, yerleştirme, keşif, focus, sentez varlıkları ile Sözlük + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +Bir koleksiyondaki tüm açıklanabilirlik oturumlarını (soruları) listeleyin. + +**Argümanlar:** + +`graph`: Adlandırılmış grafik (varsayılan: urn:graph:retrieval) +`user`: Kullanıcı/anahtar alanı tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı +`limit`: Döndürülecek maksimum oturum sayısı + +**Döndürür:** Zaman damgasına göre sıralanmış (en yeni ilk) Soru varlıkları listesi + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +Bir kenar üçlüsünün tüm bileşenleri için etiketleri çözün. + +**Argümanlar:** + +`edge`: "s", "p", "o" anahtarlarına sahip Sözlük +`user`: Kullanıcı/anahtar alanı tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı + +**Döndürür:** (s_etiketi, p_etiketi, o_etiketi) tuple'ı + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +Bir URI için rdfs:label'i, önbellekleme ile çözün. + +**Argümanlar:** + +`uri`: Etiketi alınacak URI +`user`: Kullanıcı/anahtar alanı tanımlayıcısı +`collection`: Koleksiyon tanımlayıcısı + +**Döndürür:** Bulunursa etiketi, aksi takdirde URI'yi kendisi + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +Açıklanabilirlik varlıkları için temel sınıf. + +**Alanlar:** + +`uri`: +`entity_type`: + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +Kendini başlatır. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +Soru varlığı - oturumu başlatan kullanıcının sorgusu. + +**Alanlar:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +Keşif varlığı - bilgi deposundan alınan kenarlar/parçalar. + +**Alanlar:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +Odak varlığı - LLM akıl yürütmesiyle seçilen kenarlar (yalnızca GraphRAG). + +**Alanlar:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +Sentez varlığı - nihai cevap. + +**Alanlar:** + +`uri`: +`entity_type`: +`document`: + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +Analiz varlığı - bir düşünme/eylem/gözlem döngüsü (Sadece Ajan). + +**Alanlar:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +Sonuç varlığı - kesin cevap (Sadece Ajan). + +**Alanlar:** + +`uri`: +`entity_type`: +`document`: + +### Yöntemler + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +GraphRAG Odak adımı tarafından sağlanan bir mantıkla seçilen bir kenar. + +**Alanlar:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### Yöntemler + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +Kablolu üçlüleri (s, p, o) demetlerine dönüştürün. + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +Bir kablolu Term sözlüğünden değer çıkarın. + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +Bilgi grafiği ifadesini temsil eden RDF üçlüsü. + +**Alanlar:** + +`s`: +`p`: +`o`: + +### Yöntemler + +### `__init__(self, s: str, p: str, o: str) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(nesne='') -> str +str(bayt_veya_tampon[, kodlama[, hatalar]]) -> str + +Verilen nesneden yeni bir dize nesnesi oluşturur. Eğer kodlama veya +hatalar belirtildiyse, nesne, belirtilen kodlama ve hata işleyicisi kullanılarak +çözümlenecek bir veri tamponu içermelidir. +Aksi takdirde, object.__str__()'nin sonucunu (eğer tanımlıysa) +veya repr(object)'in sonucunu döndürür. +kodlama varsayılan olarak 'utf-8' değerine sahiptir. +hatalar varsayılan olarak 'strict' değerine sahiptir. + +### Metotlar + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(nesne='') -> str +str(bayt_veya_tampon[, kodlama[, hatalar]]) -> str + +Verilen nesneden yeni bir dize nesnesi oluşturur. Eğer kodlama veya +hatalar belirtildiyse, nesne, belirtilen kodlama ve hata işleyici kullanılarak +çözümlenecek bir veri tamponu içermelidir. +Aksi takdirde, nesnenin object.__str__() (eğer tanımlıysa) +veya repr(nesne) sonucunu döndürür. +kodlama varsayılan olarak 'utf-8' değerine sahiptir. +hatalar varsayılan olarak 'strict' değerine sahiptir. + +### Yöntemler + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +Yapılandırma anahtar tanımlayıcısı. + +**Alanlar:** + +`type`: +`key`: + +### Yöntemler + +### `__init__(self, type: str, key: str) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +Yapılandırma anahtar-değer çifti. + +**Alanlar:** + +`type`: +`key`: +`value`: + +### Metotlar + +### `__init__(self, type: str, key: str, value: str) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +Kütüphanedeki bir belge için meta veri. + +**Özellikler:** + +`parent_id: Parent document ID for child documents (empty for top`: level docs) + +**Alanlar:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### Yöntemler + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +Etkin bir belge işleme işi için meta veriler. + +**Alanlar:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### Yöntemler + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +Bir veri koleksiyonu için meta veri. + +Koleksiyonlar, belgeler ve +bilgi grafiği verileri için mantıksal gruplama ve izolasyon sağlar. + +**Özellikler:** + +`name: Human`: okunabilir koleksiyon adı + +**Alanlar:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### Yöntemler + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +Akış yanıtı parçacıkları için temel sınıf. + +Yanıtların üretildikleri gibi kademeli olarak iletildiği, WebSocket tabanlı akış işlemlerinde kullanılır. + + +**Alanlar:** + +`content`: +`end_of_message`: + +### Yöntemler + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +Kendini başlatır. Doğru imza için help(type(self))'e bakın. + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +Ajanın muhakeme/düşünce süreci parçası. + +Ajanın yürütme sırasında kullandığı iç muhakeme veya planlama adımlarını temsil eder. +Bu parçalar, ajanın problemi nasıl düşündüğünü gösterir. + +**Alanlar:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Yöntemler + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +Ajan aracı yürütme gözlemi parçası. + +Bir aracın veya eylemin yürütülmesinden elde edilen sonucu veya gözlemi temsil eder. +Bu parçalar, ajanın araçları kullanmaktan ne öğrendiğini gösterir. + +**Alanlar:** + +`content`: +`end_of_message`: +`chunk_type`: + +### Yöntemler + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +Ajanın son yanıt parçası. + +Kullanıcının sorgusuna, akıl yürütme ve araç kullanımını tamamladıktan sonra, ajanın verdiği son yanıtı temsil eder. + + +**Özellikler:** + +`chunk_type: Always "final`: answer" + +**Alanlar:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### Yöntemler + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +RAG (Retrieval-Augmented Generation) akışı parçası. + +Grafik RAG, belge RAG, metin tamamlama, +ve diğer üretken hizmetlerden gelen yanıtları akış için kullanılır. + +**Alanlar:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### Yöntemler + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +Kendini başlatır. Doğru imza için help(type(self))'e bakın. + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +Açıklanabilirlik için köken olayları. + +Açıklanabilir mod etkinleştirildiğinde GraphRAG sorguları sırasında yayımlanır. +Her olay, sorgu işleme sırasında oluşturulan bir köken düğümünü temsil eder. + +**Alanlar:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### Yöntemler + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +Kendini başlat. Doğru imza için help(type(self))'e bakın. + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +WebSocket protokolü hataları oluştuğunda tetiklenir. + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +Tüm TrustGraph hizmeti hataları için temel sınıf. + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +Ajan hizmeti hatası + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +Yapılandırma hizmeti hatası + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +Belge RAG (Retrieval-Augmented Generation) alma hatası + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +Akış yönetimi hatası + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +API Ağ Geçidi hatası + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +Grafik RAG geri alma hatası + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +LLM hizmeti hatası + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +Veri yükleme hatası + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +Arama/ara hata + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +NLP sorgu hizmeti hatası + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +Satır sorgu hizmeti hatası + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +İstek işleme hatası + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +Yapılandırılmış sorgu hizmeti hatası + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +Beklenmedik/bilinmeyen hata + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +Tüm TrustGraph hizmeti hataları için temel sınıf. + + +-- diff --git a/docs/python-api.zh-cn.md b/docs/python-api.zh-cn.md new file mode 100644 index 00000000..1d718502 --- /dev/null +++ b/docs/python-api.zh-cn.md @@ -0,0 +1,4078 @@ +--- +layout: default +title: "TrustGraph Python API 参考" +parent: "Chinese (Beta)" +--- + +# TrustGraph Python API 参考 + +> **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. + +## 安装 + +```bash +pip install trustgraph +``` + +## 快速开始 + +所有类和类型都从 `trustgraph.api` 包中导入: + +```python +from trustgraph.api import Api, Triple, ConfigKey + +# Create API client +api = Api(url="http://localhost:8088/") + +# Get a flow instance +flow = api.flow().id("default") + +# Execute a graph RAG query +response = flow.graph_rag( + query="What are the main topics?", + user="trustgraph", + collection="default" +) +``` + +## 目录 + +### 核心 + +[Api](#api) + +### Flow 客户端 + +[Flow](#flow) +[FlowInstance](#flowinstance) +[AsyncFlow](#asyncflow) +[AsyncFlowInstance](#asyncflowinstance) + +### WebSocket 客户端 + +[SocketClient](#socketclient) +[SocketFlowInstance](#socketflowinstance) +[AsyncSocketClient](#asyncsocketclient) +[AsyncSocketFlowInstance](#asyncsocketflowinstance) + +### 批量操作 + +[BulkClient](#bulkclient) +[AsyncBulkClient](#asyncbulkclient) + +### 指标 + +[Metrics](#metrics) +[AsyncMetrics](#asyncmetrics) + +### 数据类型 + +[Triple](#triple) +[ConfigKey](#configkey) +[ConfigValue](#configvalue) +[DocumentMetadata](#documentmetadata) +[ProcessingMetadata](#processingmetadata) +[CollectionMetadata](#collectionmetadata) +[StreamingChunk](#streamingchunk) +[AgentThought](#agentthought) +[AgentObservation](#agentobservation) +[AgentAnswer](#agentanswer) +[RAGChunk](#ragchunk) + +### 异常 + +[ProtocolException](#protocolexception) +[TrustGraphException](#trustgraphexception) +[AgentError](#agenterror) +[ConfigError](#configerror) +[DocumentRagError](#documentragerror) +[FlowError](#flowerror) +[GatewayError](#gatewayerror) +[GraphRagError](#graphragerror) +[LLMError](#llmerror) +[LoadError](#loaderror) +[LookupError](#lookuperror) +[NLPQueryError](#nlpqueryerror) +[RowsQueryError](#rowsqueryerror) +[RequestError](#requesterror) +[StructuredQueryError](#structuredqueryerror) +[UnexpectedError](#unexpectederror) +[ApplicationException](#applicationexception) + +-- + +## `Api` + +```python +from trustgraph.api import Api +``` + +主要的 TrustGraph API 客户端,用于同步和异步操作。 + +此类提供对所有 TrustGraph 服务的访问,包括流程管理、 +知识图谱操作、文档处理、RAG 查询等等。它支持 +基于 REST 和基于 WebSocket 的通信模式。 + +客户端可以作为上下文管理器使用,以进行自动资源清理: + ```python + with Api(url="http://localhost:8088/") as api: + result = api.flow().id("default").graph_rag(query="test") + ``` + +### 方法 + +### `__aenter__(self)` + +进入异步上下文管理器。 + +### `__aexit__(self, *args)` + +退出异步上下文管理器并关闭连接。 + +### `__enter__(self)` + +进入同步上下文管理器。 + +### `__exit__(self, *args)` + +退出同步上下文管理器并关闭连接。 + +### `__init__(self, url='http://localhost:8088/', timeout=60, token: str | None = None)` + +初始化 TrustGraph API 客户端。 + +**参数:** + +`url`: TrustGraph API 的基本 URL (默认值: "http://localhost:8088/"") +`timeout`: 请求超时时间,单位为秒 (默认值: 60) +`token`: 可选的用于身份验证的 bearer token + +**示例:** + +```python +# Local development +api = Api() + +# Production with authentication +api = Api( + url="https://trustgraph.example.com/", + timeout=120, + token="your-api-token" +) +``` + +### `aclose(self)` + +关闭所有异步客户端连接。 + +此方法关闭异步 WebSocket、批量操作和流连接。 +当退出异步上下文管理器时,它会自动调用。 + +**示例:** + +```python +api = Api() +async_socket = api.async_socket() +# ... use async_socket +await api.aclose() # Clean up connections + +# Or use async context manager (automatic cleanup) +async with Api() as api: + async_socket = api.async_socket() + # ... use async_socket +# Automatically closed +``` + +### `async_bulk(self)` + +获取一个异步批量操作客户端。 + +提供通过 WebSocket 进行异步/等待风格的批量导入/导出操作,以便高效处理大型数据集。 + +**返回值:** AsyncBulkClient: 异步批量操作客户端 + + +**示例:** + +```python +async_bulk = api.async_bulk() + +# Export triples asynchronously +async for triple in async_bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import with async generator +async def triple_gen(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +await async_bulk.import_triples( + flow="default", + triples=triple_gen() +) +``` + +### `async_flow(self)` + +获取一个基于异步 REST 的流程客户端。 + +提供对流程操作的 async/await 风格访问。这对于异步 Python 应用程序和框架(FastAPI、aiohttp 等)是首选。 + + +**返回值:** AsyncFlow: 异步流程客户端 + +**示例:** + +```python +async_flow = api.async_flow() + +# List flows +flow_ids = await async_flow.list() + +# Execute operations +instance = async_flow.id("default") +result = await instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `async_metrics(self)` + +获取一个异步指标客户端。 + +提供对 Prometheus 指标的 async/await 风格访问。 + +**返回值:** AsyncMetrics: 异步指标客户端 + +**示例:** + +```python +async_metrics = api.async_metrics() +prometheus_text = await async_metrics.get() +print(prometheus_text) +``` + +### `async_socket(self)` + +获取一个异步 WebSocket 客户端,用于流式操作。 + +提供异步/等待 (async/await) 风格的 WebSocket 访问,并支持流式传输。 +这是在 Python 中进行异步流式传输的首选方法。 + +**返回值:** AsyncSocketClient: 异步 WebSocket 客户端 + +**示例:** + +```python +async_socket = api.async_socket() +flow = async_socket.flow("default") + +# Stream agent responses +async for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + +### `bulk(self)` + +获取用于导入/导出的同步批量操作客户端。 + +批量操作允许通过 WebSocket 连接高效地传输大型数据集,包括三元组、嵌入、实体上下文和对象。 + +**返回值:** BulkClient: 同步批量操作客户端 + + +**示例:** + +```python +bulk = api.bulk() + +# Export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} {triple.p} {triple.o}") + +# Import triples +def triple_generator(): + yield Triple(s="subj", p="pred", o="obj") + # ... more triples + +bulk.import_triples(flow="default", triples=triple_generator()) +``` + +### `close(self)` + +关闭所有同步客户端连接。 + +此方法关闭 WebSocket 和批量操作连接。 +它在退出上下文管理器时会自动调用。 + +**示例:** + +```python +api = Api() +socket = api.socket() +# ... use socket +api.close() # Clean up connections + +# Or use context manager (automatic cleanup) +with Api() as api: + socket = api.socket() + # ... use socket +# Automatically closed +``` + +### `collection(self)` + +获取一个 Collection 客户端,用于管理数据集合。 + +集合将文档和知识图谱数据组织成 +逻辑分组,用于隔离和访问控制。 + +**返回值:** Collection: 集合管理客户端 + +**示例:** + +```python +collection = api.collection() + +# List collections +colls = collection.list_collections(user="trustgraph") + +# Update collection metadata +collection.update_collection( + user="trustgraph", + collection="default", + name="Default Collection", + description="Main data collection" +) +``` + +### `config(self)` + +获取一个 Config 客户端,用于管理配置设置。 + +**返回值:** Config: 配置管理客户端 + +**示例:** + +```python +config = api.config() + +# Get configuration values +values = config.get([ConfigKey(type="llm", key="model")]) + +# Set configuration +config.put([ConfigValue(type="llm", key="model", value="gpt-4")]) +``` + +### `flow(self)` + +获取一个 Flow 客户端,用于管理和与流程进行交互。 + +Flows 是 TrustGraph 中的主要执行单元,提供对 +诸如代理、RAG 查询、嵌入和文档处理等服务的访问。 + +**返回值:** Flow: Flow 管理客户端 + +**示例:** + +```python +flow_client = api.flow() + +# List available blueprints +blueprints = flow_client.list_blueprints() + +# Get a specific flow instance +flow_instance = flow_client.id("default") +response = flow_instance.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `knowledge(self)` + +获取一个 Knowledge 客户端,用于管理知识图谱核心。 + +**返回值:** Knowledge: 知识图谱管理客户端 + +**示例:** + +```python +knowledge = api.knowledge() + +# List available KG cores +cores = knowledge.list_kg_cores(user="trustgraph") + +# Load a KG core +knowledge.load_kg_core(id="core-123", user="trustgraph") +``` + +### `library(self)` + +获取一个用于文档管理的库客户端。 + +该库提供文档存储、元数据管理以及 +处理工作流程协调功能。 + +**返回值:** Library: 文档库管理客户端 + +**示例:** + +```python +library = api.library() + +# Add a document +library.add_document( + document=b"Document content", + id="doc-123", + metadata=[], + user="trustgraph", + title="My Document", + comments="Test document" +) + +# List documents +docs = library.get_documents(user="trustgraph") +``` + +### `metrics(self)` + +获取一个同步指标客户端,用于监控。 + +从 TrustGraph 服务获取 Prometheus 格式的指标,用于监控和可观察性。 + +**返回值:** 指标:同步指标客户端 + + +**示例:** + +```python +metrics = api.metrics() +prometheus_text = metrics.get() +print(prometheus_text) +``` + +### `request(self, path, request)` + +构造一个低级别的 REST API 请求。 + +此方法主要用于内部使用,但可以在需要时用于直接 +API 访问。 + +**参数:** + +`path`: API 端点路径(相对于基本 URL) +`request`: 请求负载,以字典形式表示 + +**返回值:** dict: 响应对象 + +**抛出异常:** + +`ProtocolException`: 如果响应状态码不是 200 或响应不是 JSON 格式 +`ApplicationException`: 如果响应包含错误 + +**示例:** + +```python +response = api.request("flow", { + "operation": "list-flows" +}) +``` + +### `socket(self)` + +获取一个同步的 WebSocket 客户端,用于流式操作。 + +WebSocket 连接提供流式支持,用于实时响应 +来自代理、RAG 查询和文本补全。此方法返回一个 +对 WebSocket 协议的同步包装器。 + +**返回值:** SocketClient: 同步 WebSocket 客户端 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent( + question="Explain quantum computing", + user="trustgraph", + streaming=True +): + if hasattr(chunk, 'content'): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `Flow` + +```python +from trustgraph.api import Flow +``` + +用于蓝图和流程实例操作的流程管理客户端。 + +此类提供用于管理流程蓝图(模板)和 +流程实例(正在运行的流程)的方法。蓝图定义了流程的结构和 +参数,而实例代表可以 +执行服务的活动流程。 + +### 方法 + +### `__init__(self, api)` + +初始化流程客户端。 + +**参数:** + +`api`: 用于发出请求的父级 API 实例。 + +### `delete_blueprint(self, blueprint_name)` + +删除一个流程蓝图。 + +**参数:** + +`blueprint_name`: 要删除的蓝图的名称。 + +**示例:** + +```python +api.flow().delete_blueprint("old-blueprint") +``` + +### `get(self, id)` + +获取正在运行的流程实例的定义。 + +**参数:** + +`id`: 流程实例 ID + +**返回值:** dict: 流程实例定义 + +**示例:** + +```python +flow_def = api.flow().get("default") +print(flow_def) +``` + +### `get_blueprint(self, blueprint_name)` + +通过名称获取流程蓝图定义。 + +**参数:** + +`blueprint_name`: 要检索的蓝图的名称 + +**返回值:** dict: 蓝图定义,以字典形式返回 + +**示例:** + +```python +blueprint = api.flow().get_blueprint("default") +print(blueprint) # Blueprint configuration +``` + +### `id(self, id='default')` + +获取一个 FlowInstance,用于在特定流程上执行操作。 + +**参数:** + +`id`: 流程标识符 (默认值: "default") + +**返回值:** FlowInstance: 用于服务操作的流程实例 + +**示例:** + +```python +flow = api.flow().id("my-flow") +response = flow.text_completion( + system="You are helpful", + prompt="Hello" +) +``` + +### `list(self)` + +列出所有活动流程实例。 + +**返回值:** list[str]: 流程实例 ID 列表 + +**示例:** + +```python +flows = api.flow().list() +print(flows) # ['default', 'flow-1', 'flow-2', ...] +``` + +### `list_blueprints(self)` + +列出所有可用的流程蓝图。 + +**返回值:** list[str]: 蓝图名称列表 + +**示例:** + +```python +blueprints = api.flow().list_blueprints() +print(blueprints) # ['default', 'custom-flow', ...] +``` + +### `put_blueprint(self, blueprint_name, definition)` + +创建或更新流程蓝图。 + +**参数:** + +`blueprint_name`: 蓝图的名称 +`definition`: 蓝图定义字典 + +**示例:** + +```python +definition = { + "services": ["text-completion", "graph-rag"], + "parameters": {"model": "gpt-4"} +} +api.flow().put_blueprint("my-blueprint", definition) +``` + +### `request(self, path=None, request=None)` + +发送一个流程范围内的 API 请求。 + +**参数:** + +`path`: 可选的流程端点路径后缀 +`request`: 请求负载字典 + +**返回值:** dict: 响应对象 + +**异常:** + +`RuntimeError`: 如果未指定请求参数 + +### `start(self, blueprint_name, id, description, parameters=None)` + +从蓝图启动一个新的流程实例。 + +**参数:** + +`blueprint_name`: 要实例化的蓝图名称 +`id`: 流程实例的唯一标识符 +`description`: 人类可读的描述 +`parameters`: 可选的参数字典 + +**示例:** + +```python +api.flow().start( + blueprint_name="default", + id="my-flow", + description="My custom flow", + parameters={"model": "gpt-4"} +) +``` + +### `stop(self, id)` + +停止正在运行的流程实例。 + +**参数:** + +`id`: 要停止的流程实例 ID + +**示例:** + +```python +api.flow().stop("my-flow") +``` + + +-- + +## `FlowInstance` + +```python +from trustgraph.api import FlowInstance +``` + +用于在特定流程上执行服务的流程实例客户端。 + +此类提供对所有 TrustGraph 服务的访问,包括: +文本补全和嵌入 +具有状态管理的代理操作 +图表和文档 RAG 查询 +知识图谱操作(三元组、对象) +文档加载和处理 +自然语言到 GraphQL 查询的转换 +结构化数据分析和模式检测 +MCP 工具执行 +提示模板 + +通过运行的流程实例访问服务,该实例由 ID 标识。 + +### 方法 + +### `__init__(self, api, id)` + +初始化 FlowInstance。 + +**参数:** + +`api`: 父级 Flow 客户端 +`id`: 流程实例标识符 + +### `agent(self, question, user='trustgraph', state=None, group=None, history=None)` + +执行具有推理和工具使用功能的代理操作。 + +代理可以执行多步骤推理、使用工具,并在交互过程中维护对话 +状态。 这是一个同步的非流版本。 + +**参数:** + +`question`: 用户问题或指令 +`user`: 用户标识符(默认为:"trustgraph") +`state`: 可选的状态字典,用于具有状态的对话 +`group`: 可选的组标识符,用于多用户上下文 +`history`: 可选的对话历史记录,以消息字典列表的形式 + +**返回值:** str: 代理的最终答案 + +**示例:** + +```python +flow = api.flow().id("default") + +# Simple question +answer = flow.agent( + question="What is the capital of France?", + user="trustgraph" +) + +# With conversation history +history = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi! How can I help?"} +] +answer = flow.agent( + question="Tell me about Paris", + user="trustgraph", + history=history +) +``` + +### `detect_type(self, sample)` + +检测结构化数据样本的数据类型。 + +**参数:** + +`sample`: 要分析的数据样本(字符串内容) + +**返回值:** 包含 detected_type、confidence 以及可选元数据的字典。 + +### `diagnose_data(self, sample, schema_name=None, options=None)` + +执行综合数据诊断:检测类型并生成描述符。 + +**参数:** + +`sample`: 要分析的数据样本(字符串内容) +`schema_name`: 可选的目标模式名称,用于生成描述符。 +`options`: 可选参数(例如,CSV 的分隔符)。 + +**返回值:** 包含 detected_type、confidence、descriptor 和元数据的字典。 + +### `document_embeddings_query(self, text, user, collection, limit=10)` + +使用语义相似度查询文档块。 + +查找内容在语义上与输入文本相似的文档块,使用向量嵌入。 + + +**参数:** + +`text`: 用于语义搜索的查询文本。 +`user`: 用户/键空间标识符。 +`collection`: 集合标识符。 +`limit`: 最大结果数量(默认为 10)。 + +**返回值:** 字典:包含 chunk_id 和 score 的查询结果。 + +**示例:** + +```python +flow = api.flow().id("default") +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "doc1/p0/c0", "score": 0.95}, ...]} +``` + +### `document_rag(self, query, user='trustgraph', collection='default', doc_limit=10)` + +执行基于文档的检索增强生成 (RAG) 查询。 + +文档 RAG 使用向量嵌入来查找相关的文档片段, +然后使用 LLM,并将这些片段作为上下文来生成响应。 + +**参数:** + +`query`: 自然语言查询 +`user`: 用户/键空间标识符 (默认值: "trustgraph") +`collection`: 集合标识符 (默认值: "default") +`doc_limit`: 要检索的最大文档片段数 (默认值: 10) + +**返回值:** str: 包含文档上下文的生成响应 + +**示例:** + +```python +flow = api.flow().id("default") +response = flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts)` + +为一个或多个文本生成向量嵌入。 + +将文本转换为适合语义 +搜索和相似度比较的密集向量表示。 + +**参数:** + +`texts`: 要嵌入的输入文本列表 + +**返回值:** list[list[list[float]]]: 向量嵌入,每个输入文本对应一个集合 + +**示例:** + +```python +flow = api.flow().id("default") +vectors = flow.embeddings(["quantum computing"]) +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `generate_descriptor(self, sample, data_type, schema_name, options=None)` + +生成用于将结构化数据映射到特定模式的描述符。 + +**参数:** + +`sample`: 用于分析的数据样本(字符串内容) +`data_type`: 数据类型(csv, json, xml) +`schema_name`: 用于生成描述符的目标模式名称 +`options`: 可选参数(例如,CSV的分隔符) + +**返回值:** 包含描述符和元数据的字典 + +### `graph_embeddings_query(self, text, user, collection, limit=10)` + +使用语义相似性查询知识图谱实体。 + +查找知识图谱中描述与输入文本在语义上 +相似的实体,使用向量嵌入。 + +**参数:** + +`text`: 用于语义搜索的查询文本 +`user`: 用户/键空间标识符 +`collection`: 集合标识符 +`limit`: 最大结果数量(默认为 10) + +**返回值:** 字典:包含相似实体的查询结果 + +**示例:** + +```python +flow = api.flow().id("default") +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +# results contains {"entities": [{"entity": {...}, "score": 0.95}, ...]} +``` + +### `graph_rag(self, query, user='trustgraph', collection='default', entity_limit=50, triple_limit=30, max_subgraph_size=150, max_path_length=2)` + +执行基于图的检索增强生成 (RAG) 查询。 + +图 RAG 使用知识图谱结构来通过 +遍历实体关系来查找相关上下文,然后使用 LLM 生成响应。 + +**参数:** + +`query`: 自然语言查询 +`user`: 用户/键空间标识符 (默认为: "trustgraph") +`collection`: 集合标识符 (默认为: "default") +`entity_limit`: 检索到的最大实体数量 (默认为: 50) +`triple_limit`: 每个实体的最大三元组数量 (默认为: 30) +`max_subgraph_size`: 子图中最大总三元组数量 (默认为: 150) +`max_path_length`: 最大遍历深度 (默认为: 2) + +**返回值:** str: 包含图上下文的生成响应 + +**示例:** + +```python +flow = api.flow().id("default") +response = flow.graph_rag( + query="Tell me about Marie Curie's discoveries", + user="trustgraph", + collection="scientists", + entity_limit=20, + max_path_length=3 +) +print(response) +``` + +### `load_document(self, document, id=None, metadata=None, user=None, collection=None)` + +加载一个二进制文档以进行处理。 + +上传一个文档(PDF、DOCX、图像等),以便从流程的文档管道中提取和 +处理。 + +**参数:** + +`document`: 文档内容,以字节形式表示 +`id`: 可选的文档标识符(如果为 None,则自动生成) +`metadata`: 可选的元数据(三元组列表或具有 emit 方法的对象) +`user`: 用户/键空间标识符(可选) +`collection`: 集合标识符(可选) + +**返回值:** dict: 处理响应 + +**引发:** + +`RuntimeError`: 如果提供了元数据,但没有提供 id + +**示例:** + +```python +flow = api.flow().id("default") + +# Load a PDF document +with open("research.pdf", "rb") as f: + result = flow.load_document( + document=f.read(), + id="research-001", + user="trustgraph", + collection="papers" + ) +``` + +### `load_text(self, text, id=None, metadata=None, charset='utf-8', user=None, collection=None)` + +加载用于处理的文本内容。 + +上传文本内容,以便通过流程的 +文本管道进行提取和处理。 + +**参数:** + +`text`: 文本内容,以字节形式 +`id`: 可选的文档标识符(如果为 None,则自动生成) +`metadata`: 可选的元数据(三元组列表或具有 emit 方法的对象) +`charset`: 字符编码(默认值:"utf-8") +`user`: 用户/键空间标识符(可选) +`collection`: 集合标识符(可选) + +**返回值:** dict: 处理响应 + +**异常:** + +`RuntimeError`: 如果提供了元数据,但没有提供 id + +**示例:** + +```python +flow = api.flow().id("default") + +# Load text content +text_content = b"This is the document content..." +result = flow.load_text( + text=text_content, + id="text-001", + charset="utf-8", + user="trustgraph", + collection="documents" +) +``` + +### `mcp_tool(self, name, parameters={})` + +执行一个模型上下文协议 (MCP) 工具。 + +MCP 工具提供可扩展的功能,用于代理和工作流程, +允许与外部系统和服务集成。 + +**参数:** + +`name`: 工具名称/标识符 +`parameters`: 工具参数字典 (默认: {}) + +**返回值:** str 或 dict: 工具执行结果 + +**异常:** + +`ProtocolException`: 如果响应格式无效 + +**示例:** + +```python +flow = api.flow().id("default") + +# Execute a tool +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `nlp_query(self, question, max_results=100)` + +将自然语言问题转换为 GraphQL 查询。 + +**参数:** + +`question`: 自然语言问题 +`max_results`: 返回的最大结果数量(默认为:100) + +**返回值:** 包含 graphql_query、variables、detected_schemas 和 confidence 的字典。 + +### `prompt(self, id, variables)` + +执行带有变量替换的提示模板。 + +提示模板允许使用可重用的提示模式,并带有动态变量。 +这种方法对于一致的提示工程非常有用。 + +**参数:** + +`id`: 提示模板标识符 +`variables`: 变量名称到值的映射字典 + +**返回值:** str 或 dict: 渲染后的提示结果(文本或结构化对象) + +**引发:** + +`ProtocolException`: 如果响应格式无效 + +**示例:** + +```python +flow = api.flow().id("default") + +# Text template +result = flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"} +) + +# Structured template +result = flow.prompt( + id="extract-entities", + variables={"text": "Marie Curie won Nobel Prizes"} +) +``` + +### `request(self, path, request)` + +在此流程实例中发起服务请求。 + +**参数:** + +`path`: 服务路径(例如,"service/text-completion") +`request`: 请求负载字典 + +**返回值:** dict: 服务响应 + +### `row_embeddings_query(self, text, schema_name, user='trustgraph', collection='default', index_name=None, limit=10)` + +使用语义相似性在索引字段上查询行数据。 + +查找索引字段值在语义上与输入文本相似的行,使用向量嵌入。这实现了对结构化数据的模糊/语义匹配。 + +**参数:** + + + +`text`: 用于语义搜索的查询文本。 +`schema_name`: 要搜索的模式名称。 +`user`: 用户/键空间标识符(默认为:"trustgraph")。 +`collection`: 集合标识符(默认为:"default")。 +`index_name`: 可选的索引名称,用于将搜索限制到特定的索引。 +`limit`: 最大结果数量(默认为:10)。 + +**返回值:** dict: 查询结果,包含 index_name、index_value、text 和 score。 + +**示例:** + +```python +flow = api.flow().id("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query, user='trustgraph', collection='default', variables=None, operation_name=None)` + +对知识图谱中的结构化行执行 GraphQL 查询。 + +使用 GraphQL 语法查询结构化数据,允许进行复杂的查询, +包括过滤、聚合和关系遍历。 + +**参数:** + +`query`: GraphQL 查询字符串 +`user`: 用户/键空间标识符(默认为:"trustgraph") +`collection`: 集合标识符(默认为:"default") +`variables`: 可选的查询变量字典 +`operation_name`: 多操作文档的可选操作名称 + +**返回值:** dict: 包含 'data'、'errors' 和/或 'extensions' 字段的 GraphQL 响应 + +**引发:** + +`ProtocolException`: 如果发生系统级错误 + +**示例:** + +```python +flow = api.flow().id("default") + +# Simple query +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) + +# Query with variables +query = ''' +query GetScientist($name: String!) { + scientists(name: $name) { + name + nobelPrizes + } +} +''' +result = flow.rows_query( + query=query, + variables={"name": "Marie Curie"} +) +``` + +### `schema_selection(self, sample, options=None)` + +使用提示分析,为数据样本选择匹配的模式。 + +**参数:** + +`sample`: 要分析的数据样本(字符串内容) +`options`: 可选参数 + +**返回值:** 包含 schema_matches 数组和元数据的字典。 + +### `structured_query(self, question, user='trustgraph', collection='default')` + +对结构化数据执行自然语言问题。 +结合 NLP 查询转换和 GraphQL 执行。 + +**参数:** + +`question`: 自然语言问题 +`user`: Cassandra keyspace 标识符(默认为:"trustgraph") +`collection`: 数据集合标识符(默认为:"default") + +**返回值:** 包含数据和可选错误的字典。 + +### `text_completion(self, system, prompt)` + +使用流程的 LLM 执行文本补全。 + +**参数:** + +`system`: 定义助手行为的系统提示。 +`prompt`: 用户提示/问题 + +**返回值:** str: 生成的响应文本 + +**示例:** + +```python +flow = api.flow().id("default") +response = flow.text_completion( + system="You are a helpful assistant", + prompt="What is quantum computing?" +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=10000)` + +使用模式匹配查询知识图谱三元组。 + +搜索与给定的主语、谓语和/或 +对象模式匹配的 RDF 三元组。 未指定的参数用作通配符。 + +**参数:** + +`s`: 主语 URI (可选,使用 None 表示通配符) +`p`: 谓语 URI (可选,使用 None 表示通配符) +`o`: 对象 URI 或字面量 (可选,使用 None 表示通配符) +`user`: 用户/键空间标识符 (可选) +`collection`: 集合标识符 (可选) +`limit`: 要返回的最大结果数 (默认:10000) + +**返回值:** list[Triple]: 匹配的三元组对象的列表 + +**引发:** + +`RuntimeError`: 如果 s 或 p 不是 Uri,或者 o 不是 Uri/Literal + +**示例:** + +```python +from trustgraph.knowledge import Uri, Literal + +flow = api.flow().id("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s=Uri("http://example.org/person/marie-curie"), + user="trustgraph", + collection="scientists" +) + +# Find all instances of a specific relationship +triples = flow.triples_query( + p=Uri("http://example.org/ontology/discovered"), + limit=100 +) +``` + + +-- + +## `AsyncFlow` + +```python +from trustgraph.api import AsyncFlow +``` + +使用 REST API 的异步流程管理客户端。 + +提供基于 async/await 的流程管理操作,包括列出、 +启动、停止流程,以及管理流程类定义。 此外,还提供对流程范围内的服务(如代理、RAG 和查询)的访问,这些服务通过非流式 +REST 接口提供。 + + +注意:对于流式支持,请使用 AsyncSocketClient。 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +初始化异步流程客户端。 + +**参数:** + +`url`:TrustGraph API 的基本 URL +`timeout`:请求超时时间(以秒为单位) +`token`:可选的用于身份验证的 bearer token + +### `aclose(self) -> None` + +关闭异步客户端并清理资源。 + +注意:清理由 aiohttp 会话上下文管理器自动处理。 +此方法是为了与其他异步客户端保持一致而提供的。 + +### `delete_class(self, class_name: str)` + +删除一个流程类定义。 + +从系统中移除一个流程类蓝图。 不会影响 +正在运行的流程实例。 + +**参数:** + +`class_name`:要删除的流程类名称 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Delete a flow class +await async_flow.delete_class("old-flow-class") +``` + +### `get(self, id: str) -> Dict[str, Any]` + +获取流程定义。 + +获取完整的流程配置,包括其类名、 +描述和参数。 + +**参数:** + +`id`: 流程标识符 + +**返回值:** dict: 流程定义对象 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Get flow definition +flow_def = await async_flow.get("default") +print(f"Flow class: {flow_def.get('class-name')}") +print(f"Description: {flow_def.get('description')}") +``` + +### `get_class(self, class_name: str) -> Dict[str, Any]` + +获取流程类定义。 + +获取流程类的蓝图定义,包括其配置模式和服务绑定。 + + +**参数:** + +`class_name`: 流程类名称 + +**返回值:** dict: 流程类定义对象 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Get flow class definition +class_def = await async_flow.get_class("default") +print(f"Services: {class_def.get('services')}") +``` + +### `id(self, flow_id: str)` + +获取一个异步流程实例客户端。 + +返回一个客户端,用于与特定流程的服务进行交互(代理、RAG、查询、嵌入等)。 + + +**参数:** + +`flow_id`: 流程标识符 + +**返回值:** AsyncFlowInstance: 用于特定流程操作的客户端 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Get flow instance +flow = async_flow.id("default") + +# Use flow services +result = await flow.graph_rag( + query="What is TrustGraph?", + user="trustgraph", + collection="default" +) +``` + +### `list(self) -> List[str]` + +列出所有流程标识符。 + +获取系统中当前部署的所有流程的ID。 + +**返回值:** list[str]: 流程标识符列表 + +**示例:** + +```python +async_flow = await api.async_flow() + +# List all flows +flows = await async_flow.list() +print(f"Available flows: {flows}") +``` + +### `list_classes(self) -> List[str]` + +列出所有流程类名称。 + +获取系统中所有可用流程类(蓝图)的名称。 + +**返回值:** list[str]: 流程类名称列表 + +**示例:** + +```python +async_flow = await api.async_flow() + +# List available flow classes +classes = await async_flow.list_classes() +print(f"Available flow classes: {classes}") +``` + +### `put_class(self, class_name: str, definition: Dict[str, Any])` + +创建或更新一个流程类定义。 + +存储一个流程类蓝图,该蓝图可用于实例化流程。 + +**参数:** + +`class_name`: 流程类名称 +`definition`: 流程类定义对象 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Create a custom flow class +class_def = { + "services": { + "agent": {"module": "agent", "config": {...}}, + "graph-rag": {"module": "graph-rag", "config": {...}} + } +} +await async_flow.put_class("custom-flow", class_def) +``` + +### `request(self, path: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +异步向网关API发送HTTP POST请求。 + +用于向TrustGraph API发送经过身份验证的请求的内部方法。 + +**参数:** + +`path`: API端点路径(相对于基本URL) +`request_data`: 请求负载字典 + +**返回值:** dict: 来自API的响应对象 + +**引发:** + +`ProtocolException`:如果 HTTP 状态码不是 200 或响应不是有效的 JSON +`ApplicationException`:如果 API 返回错误响应 + +### `start(self, class_name: str, id: str, description: str, parameters: Dict | None = None)` + +启动一个新的流程实例。 + +从指定的流程类定义创建并启动一个流程。 + + +**参数:** + +`class_name`:用于创建实例的流程类名称 +`id`:新流程实例的标识符 +`description`:流程的易于理解的描述 +`parameters`:流程的可选配置参数 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Start a flow from a class +await async_flow.start( + class_name="default", + id="my-flow", + description="Custom flow instance", + parameters={"model": "claude-3-opus"} +) +``` + +### `stop(self, id: str)` + +停止正在运行的流程。 + +停止并移除一个流程实例,释放其资源。 + +**参数:** + +`id`: 要停止的流程标识符 + +**示例:** + +```python +async_flow = await api.async_flow() + +# Stop a flow +await async_flow.stop("my-flow") +``` + + +-- + +## `AsyncFlowInstance` + +```python +from trustgraph.api import AsyncFlowInstance +``` + +异步流程实例客户端。 + +提供对流程范围内的服务的异步/等待访问,包括代理、 +RAG 查询、嵌入和图查询。所有操作返回完整的 +响应(非流式传输)。 + +注意:对于流式传输支持,请使用 AsyncSocketFlowInstance。 + +### 方法 + +### `__init__(self, flow: trustgraph.api.async_flow.AsyncFlow, flow_id: str)` + +初始化异步流程实例。 + +**参数:** + +`flow`: 父级 AsyncFlow 客户端 +`flow_id`: 流程标识符 + +### `agent(self, question: str, user: str, state: Dict | None = None, group: str | None = None, history: List | None = None, **kwargs: Any) -> Dict[str, Any]` + +执行代理操作(非流式传输)。 + +运行代理以回答问题,可以选择使用对话状态和 +历史记录。在代理完成处理后,返回完整的响应。 + + +注意:此方法不支持流式传输。对于代理的实时想法和 +观察结果,请使用 AsyncSocketFlowInstance.agent()。 + +**参数:** + +`question`: 用户问题或指令 +`user`: 用户标识符 +`state`: 可选的状态字典,用于对话上下文 +`group`: 可选的组标识符,用于会话管理 +`history`: 可选的对话历史记录列表 +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** dict: 完整的代理响应,包括答案和元数据 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute agent +result = await flow.agent( + question="What is the capital of France?", + user="trustgraph" +) +print(f"Answer: {result.get('response')}") +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> str` + +执行基于文档的 RAG 查询(非流式)。 + +使用文档嵌入进行检索增强生成。 +通过语义搜索检索相关的文档片段,然后根据检索到的文档生成 +一个完整的响应。返回完整的响应。 + +注意:此方法不支持流式传输。对于流式 RAG 响应, +请使用 AsyncSocketFlowInstance.document_rag()。 + +**参数:** + +`query`: 用户查询文本 +`user`: 用户标识符 +`collection`: 包含文档的集合标识符 +`doc_limit`: 要检索的最大文档片段数量(默认为 10) +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** str: 基于文档数据的完整生成的响应 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query documents +response = await flow.document_rag( + query="What does the documentation say about authentication?", + user="trustgraph", + collection="docs", + doc_limit=5 +) +print(response) +``` + +### `embeddings(self, texts: list, **kwargs: Any)` + +为输入文本生成嵌入向量。 + +将文本转换为数值向量表示,使用流程配置的嵌入模型。适用于语义搜索和相似度 +比较。 + + +**参数:** + +`texts`: 要嵌入的输入文本列表 +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** dict: 包含嵌入向量的响应 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate embeddings +result = await flow.embeddings(texts=["Sample text to embed"]) +vectors = result.get("vectors") +print(f"Embedding dimension: {len(vectors[0][0])}") +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any)` + +用于语义实体搜索的图嵌入查询。 + +对图实体嵌入执行语义搜索,以查找与输入文本最相关的实体。返回按相似度排序的实体。 + + +**参数:** + +`text`: 用于语义搜索的查询文本 +`user`: 用户标识符 +`collection`: 包含图嵌入的集合标识符 +`limit`: 要返回的最大结果数(默认为:10) +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** dict: 包含按相似度排序的实体匹配结果,以及相似度分数。 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find related entities +results = await flow.graph_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="tech-kb", + limit=5 +) + +for entity in results.get("entities", []): + print(f"{entity['name']}: {entity['score']}") +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> str` + +执行基于图的 RAG 查询(非流式)。 + +使用知识图谱数据执行检索增强生成。 +识别相关的实体及其关系,然后生成一个 +基于图结构的回应。返回完整的响应。 + +注意:此方法不支持流式传输。对于流式 RAG 响应, +请使用 AsyncSocketFlowInstance.graph_rag()。 + +**参数:** + +`query`: 用户查询文本 +`user`: 用户标识符 +`collection`: 包含知识图谱的集合标识符 +`max_subgraph_size`: 每个子图中最大三元组数(默认:1000) +`max_subgraph_count`: 要检索的最大子图数量(默认:5) +`max_entity_distance`: 实体扩展的最大图距离(默认:3) +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** str: 基于图数据生成的完整响应 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Query knowledge graph +response = await flow.graph_rag( + query="What are the relationships between these entities?", + user="trustgraph", + collection="medical-kb", + max_subgraph_count=3 +) +print(response) +``` + +### `request(self, service: str, request_data: Dict[str, Any]) -> Dict[str, Any]` + +向作用域为流程的服务发送请求。 + +用于在当前流程实例中调用服务的内部方法。 + +**参数:** + +`service`: 服务名称(例如,"agent", "graph-rag", "triples") +`request_data`: 服务请求负载 + +**返回值:** dict: 服务响应对象 + +**抛出异常:** + +`ProtocolException`: 如果请求失败或响应无效 +`ApplicationException`: 如果服务返回错误 + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any)` + +查询用于结构化数据语义搜索的行嵌入。 + +在行索引嵌入上执行语义搜索,以查找其索引字段值与输入文本最相似的行。 允许 +对结构化数据进行模糊/语义匹配。 + + +**参数:** + +`text`: 用于语义搜索的查询文本。 +`schema_name`: 要搜索的模式名称。 +`user`: 用户标识符(默认值:"trustgraph")。 +`collection`: 集合标识符(默认值:"default")。 +`index_name`: 可选的索引名称,用于将搜索限制到特定的索引。 +`limit`: 要返回的最大结果数量(默认值:10)。 +`**kwargs`: 额外的特定于服务的参数。 + +**返回值:** dict: 包含匹配项的响应,包含 index_name、index_value、text 和 score。 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Search for customers by name similarity +results = await flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +for match in results.get("matches", []): + print(f"{match['index_name']}: {match['index_value']} (score: {match['score']})") +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs: Any)` + +在存储的行上执行 GraphQL 查询。 + +使用 GraphQL 语法查询结构化数据行。支持使用变量和命名操作的复杂查询。 + + +**参数:** + +`query`: GraphQL 查询字符串 +`user`: 用户标识符 +`collection`: 包含行的集合标识符 +`variables`: 可选的 GraphQL 查询变量 +`operation_name`: 用于多操作查询的可选操作名称 +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** dict: 包含数据和/或错误的 GraphQL 响应 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Execute GraphQL query +query = ''' + query GetUsers($status: String!) { + users(status: $status) { + id + name + email + } + } +''' + +result = await flow.rows_query( + query=query, + user="trustgraph", + collection="users", + variables={"status": "active"} +) + +for user in result.get("data", {}).get("users", []): + print(f"{user['name']}: {user['email']}") +``` + +### `text_completion(self, system: str, prompt: str, **kwargs: Any) -> str` + +生成文本补全(非流式)。 + +根据系统提示和用户提示,从大型语言模型生成文本回复。 +返回完整的回复文本。 + +注意:此方法不支持流式传输。对于流式文本生成, +请使用 AsyncSocketFlowInstance.text_completion()。 + +**参数:** + +`system`: 定义大型语言模型行为的系统提示。 +`prompt`: 用户提示或问题。 +`**kwargs`: 额外的特定于服务的参数。 + +**返回值:** str: 完整的生成文本回复。 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Generate text +response = await flow.text_completion( + system="You are a helpful assistant.", + prompt="Explain quantum computing in simple terms." +) +print(response) +``` + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs: Any)` + +使用模式匹配查询 RDF 三元组。 + +搜索与指定的 subject(主体)、predicate(谓词)和/或 +object(对象)模式匹配的三元组。 模式使用 None 作为通配符来匹配任何值。 + +**参数:** + +`s`: Subject(主体)模式(None 表示通配符) +`p`: Predicate(谓词)模式(None 表示通配符) +`o`: Object(对象)模式(None 表示通配符) +`user`: 用户标识符(None 表示所有用户) +`collection`: Collection(集合)标识符(None 表示所有集合) +`limit`: 返回的三元组的最大数量(默认:100) +`**kwargs`: 额外的特定于服务的参数 + +**返回值:** dict: 包含匹配的三元组的响应 + +**示例:** + +```python +async_flow = await api.async_flow() +flow = async_flow.id("default") + +# Find all triples with a specific predicate +results = await flow.triples_query( + p="knows", + user="trustgraph", + collection="social", + limit=50 +) + +for triple in results.get("triples", []): + print(f"{triple['s']} knows {triple['o']}") +``` + + +-- + +## `SocketClient` + +```python +from trustgraph.api import SocketClient +``` + +同步 WebSocket 客户端,用于流式操作。 + +提供了对基于 WebSocket 的 TrustGraph 服务的同步接口, +通过使用同步生成器包装异步 WebSocket 库,以提高易用性。 +支持从代理接收流式响应、RAG 查询和文本补全。 + +注意:这是一个围绕异步 WebSocket 操作的同步包装器。对于 +真正的异步支持,请使用 AsyncSocketClient。 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +初始化同步 WebSocket 客户端。 + +**参数:** + +`url`:TrustGraph API 的基本 URL(HTTP/HTTPS 将转换为 WS/WSS) +`timeout`:WebSocket 超时时间(以秒为单位) +`token`:可选的用于身份验证的 bearer token + +### `close(self) -> None` + +关闭 WebSocket 连接。 + +注意:在异步代码中,清理由上下文管理器自动处理。 + +### `flow(self, flow_id: str) -> 'SocketFlowInstance'` + +获取用于 WebSocket 流式操作的 flow 实例。 + +**参数:** + +`flow_id`:Flow 标识符 + +**返回值:** SocketFlowInstance:具有流式方法的 Flow 实例 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent responses +for chunk in flow.agent(question="Hello", user="trustgraph", streaming=True): + print(chunk.content, end='', flush=True) +``` + + +-- + +## `SocketFlowInstance` + +```python +from trustgraph.api import SocketFlowInstance +``` + +同步 WebSocket 流程实例,用于流式操作。 + +它提供与 REST FlowInstance 相同的接口,但具有基于 WebSocket 的 +流式支持,用于实时响应。 所有方法都支持一个可选的 +`streaming` 参数,以启用增量结果交付。 + +### 方法 + +### `__init__(self, client: trustgraph.api.socket_client.SocketClient, flow_id: str) -> None` + +初始化 socket 流程实例。 + +**参数:** + +`client`: 父 SocketClient +`flow_id`: 流程标识符 + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, streaming: bool = False, **kwargs: Any) -> Dict[str, Any] | Iterator[trustgraph.api.types.StreamingChunk]` + +执行一个支持流式传输的代理操作。 + +代理可以执行涉及工具使用的多步骤推理。 即使当 +streaming=False 时,此方法也会始终 +返回流式传输的分块(想法、观察结果、答案),以显示代理的推理过程。 + +**参数:** + +`question`: 用户问题或指令 +`user`: 用户标识符 +`state`: 可选的状态字典,用于具有状态的对话 +`group`: 可选的组标识符,用于多用户环境 +`history`: 可选的对话历史记录,以消息字典列表的形式 +`streaming`: 启用流式传输模式(默认:False) +`**kwargs`: 传递给代理服务的其他参数 + +**返回值:** Iterator[StreamingChunk]: 代理的想法、观察结果和答案的流 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Stream agent reasoning +for chunk in flow.agent( + question="What is quantum computing?", + user="trustgraph", + streaming=True +): + if isinstance(chunk, AgentThought): + print(f"[Thinking] {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"[Observation] {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"[Answer] {chunk.content}") +``` + +### `agent_explain(self, question: str, user: str, collection: str, state: Dict[str, Any] | None = None, group: str | None = None, history: List[Dict[str, Any]] | None = None, **kwargs: Any) -> Iterator[trustgraph.api.types.StreamingChunk | trustgraph.api.types.ProvenanceEvent]` + +执行具有可解释性支持的代理操作。 + +同时流式传输内容块(AgentThought、AgentObservation、AgentAnswer) +和溯源事件(ProvenanceEvent)。溯源事件包含 URI, +可以使用 ExplainabilityClient 获取有关代理推理过程的详细信息。 + + +代理跟踪信息包括: +Session:初始问题和会话元数据 +Iterations:每个思考/行动/观察周期 +Conclusion:最终答案 + +**参数:** + +`question`:用户问题或指令 +`user`:用户标识符 +`collection`:用于存储溯源信息的集合标识符 +`state`:可选的状态字典,用于有状态的对话 +`group`:可选的组标识符,用于多用户上下文 +`history`:可选的对话历史记录,以消息字典列表的形式 +`**kwargs`:传递给代理服务的其他参数 +`Yields`: +`Union[StreamingChunk, ProvenanceEvent]`:代理块和溯源事件 + +**示例:** + +```python +from trustgraph.api import Api, ExplainabilityClient, ProvenanceEvent +from trustgraph.api import AgentThought, AgentObservation, AgentAnswer + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +for item in flow.agent_explain( + question="What is the capital of France?", + user="trustgraph", + collection="default" +): + if isinstance(item, AgentThought): + print(f"[Thought] {item.content}") + elif isinstance(item, AgentObservation): + print(f"[Observation] {item.content}") + elif isinstance(item, AgentAnswer): + print(f"[Answer] {item.content}") + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.explain_id) + +# Fetch session trace after completion +if provenance_ids: + trace = explain_client.fetch_agent_trace( + provenance_ids[0], # Session URI is first + graph="urn:graph:retrieval", + user="trustgraph", + collection="default" + ) +``` + +### `document_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +使用语义相似度查询文档块。 + +**参数:** + +`text`: 用于语义搜索的查询文本 +`user`: 用户/键空间标识符 +`collection`: 集合标识符 +`limit`: 最大结果数量(默认为:10) +`**kwargs`: 传递给服务的其他参数 + +**返回值:** dict: 包含匹配文档块的 chunk_ids 的查询结果 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.document_embeddings_query( + text="machine learning algorithms", + user="trustgraph", + collection="research-papers", + limit=5 +) +# results contains {"chunks": [{"chunk_id": "...", "score": 0.95}, ...]} +``` + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +执行基于文档的 RAG 查询,并可选择启用流式传输。 + +使用向量嵌入来查找相关的文档片段,然后使用 LLM 生成 +响应。流式模式逐步提供结果。 + +**参数:** + +`query`: 自然语言查询 +`user`: 用户/键空间标识符 +`collection`: 集合标识符 +`doc_limit`: 要检索的最大文档片段数(默认为:10) +`streaming`: 启用流式模式(默认为:False) +`**kwargs`: 传递给服务的其他参数 + +**返回值:** Union[str, Iterator[str]]: 完整的响应或文本片段的流 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming document RAG +for chunk in flow.document_rag( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `document_rag_explain(self, query: str, user: str, collection: str, doc_limit: int = 10, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +执行支持可解释性的基于文档的 RAG 查询。 + +同时流式传输内容块(RAGChunk)和溯源事件(ProvenanceEvent)。 +溯源事件包含 URI,可以使用 ExplainabilityClient 获取详细信息,了解响应的生成方式。 + + +文档 RAG 跟踪信息包括: +问题:用户的查询 +探索:从文档存储中检索到的块(chunk_count) +综合:生成的答案 + +**参数:** + +`query`:自然语言查询 +`user`:用户/键空间标识符 +`collection`:集合标识符 +`doc_limit`:要检索的最大文档块数(默认:10) +`**kwargs`:传递给服务的其他参数 +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`:内容块和溯源事件 + +**示例:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +for item in flow.document_rag_explain( + query="Summarize the key findings", + user="trustgraph", + collection="research-papers", + doc_limit=5 +): + if isinstance(item, RAGChunk): + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + # Fetch entity details + entity = explain_client.fetch_entity( + item.explain_id, + graph=item.explain_graph, + user="trustgraph", + collection="research-papers" + ) + print(f"Event: {entity}", file=sys.stderr) +``` + +### `embeddings(self, texts: list, **kwargs: Any) -> Dict[str, Any]` + +为一个或多个文本生成向量嵌入。 + +**参数:** + +`texts`: 要进行嵌入的输入文本列表。 +`**kwargs`: 传递给服务的其他参数。 + +**返回值:** dict: 包含向量的响应(每个输入文本对应一个向量集合)。 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.embeddings(["quantum computing"]) +vectors = result.get("vectors", []) +``` + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +使用语义相似度查询知识图谱实体。 + +**参数:** + +`text`: 用于语义搜索的查询文本 +`user`: 用户/命名空间标识符 +`collection`: 集合标识符 +`limit`: 最大结果数量(默认为:10) +`**kwargs`: 传递给服务的附加参数 + +**返回值:** dict: 包含相似实体的查询结果 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +results = flow.graph_embeddings_query( + text="physicist who discovered radioactivity", + user="trustgraph", + collection="scientists", + limit=5 +) +``` + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +执行基于图的关系检索增强生成(RAG)查询,并可选择启用流式传输。 + +使用知识图谱结构来查找相关上下文,然后使用大型语言模型(LLM)生成 +响应。流式模式逐步提供结果。 + +**参数:** + +`query`:自然语言查询 +`user`:用户/键空间标识符 +`collection`:集合标识符 +`max_subgraph_size`:子图中最大三元组数量(默认为:1000) +`max_subgraph_count`:最大子图数量(默认为:5) +`max_entity_distance`:最大遍历深度(默认为:3) +`streaming`:启用流式模式(默认为:False) +`**kwargs`:传递给服务的其他参数 + +**返回值:** Union[str, Iterator[str]]:完整的响应或文本块的流 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming graph RAG +for chunk in flow.graph_rag( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `graph_rag_explain(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, **kwargs: Any) -> Iterator[trustgraph.api.types.RAGChunk | trustgraph.api.types.ProvenanceEvent]` + +执行具有可解释性支持的基于图的 RAG 查询。 + +同时流式传输内容块(RAGChunk)和溯源事件(ProvenanceEvent)。 +溯源事件包含 URI,可以使用 ExplainabilityClient 获取详细信息,了解响应的生成方式。 + + +**参数:** + +`query`: 自然语言查询 +`user`: 用户/键空间标识符 +`collection`: 集合标识符 +`max_subgraph_size`: 子图中最大三元组数量(默认:1000) +`max_subgraph_count`: 最大子图数量(默认:5) +`max_entity_distance`: 最大遍历深度(默认:3) +`**kwargs`: 传递给服务的其他参数 +`Yields`: +`Union[RAGChunk, ProvenanceEvent]`: 内容块和溯源事件 + +**示例:** + +```python +from trustgraph.api import Api, ExplainabilityClient, RAGChunk, ProvenanceEvent + +socket = api.socket() +flow = socket.flow("default") +explain_client = ExplainabilityClient(flow) + +provenance_ids = [] +response_text = "" + +for item in flow.graph_rag_explain( + query="Tell me about Marie Curie", + user="trustgraph", + collection="scientists" +): + if isinstance(item, RAGChunk): + response_text += item.content + print(item.content, end='', flush=True) + elif isinstance(item, ProvenanceEvent): + provenance_ids.append(item.provenance_id) + +# Fetch explainability details +for prov_id in provenance_ids: + entity = explain_client.fetch_entity( + prov_id, + graph="urn:graph:retrieval", + user="trustgraph", + collection="scientists" + ) + print(f"Entity: {entity}") +``` + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]` + +执行模型上下文协议 (MCP) 工具。 + +**参数:** + +`name`: 工具名称/标识符 +`parameters`: 工具参数字典 +`**kwargs`: 传递给服务的附加参数 + +**返回值:** dict: 工具执行结果 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +result = flow.mcp_tool( + name="search-web", + parameters={"query": "latest AI news", "limit": 5} +) +``` + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs: Any) -> str | Iterator[str]` + +执行一个带有可选流式的提示模板。 + +**参数:** + +`id`: 提示模板标识符 +`variables`: 变量名到值的映射字典 +`streaming`: 启用流式模式 (默认: False) +`**kwargs`: 传递给服务的附加参数 + +**返回值:** Union[str, Iterator[str]]: 完整的响应或文本块的流 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Streaming prompt execution +for chunk in flow.prompt( + id="summarize-template", + variables={"topic": "quantum computing", "length": "brief"}, + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs: Any) -> Dict[str, Any]` + +使用语义相似性在索引字段上查询行数据。 + +查找其索引字段值在语义上与 +输入文本相似的行,使用向量嵌入。这实现了对结构化数据的模糊/语义匹配。 + + +**参数:** + +`text`: 用于语义搜索的查询文本 +`schema_name`: 要搜索的模式名称 +`user`: 用户/键空间标识符(默认为:"trustgraph") +`collection`: 集合标识符(默认为:"default") +`index_name`: 可选的索引名称,用于将搜索限制到特定索引 +`limit`: 最大结果数量(默认为:10) +`**kwargs`: 传递给服务的其他参数 + +**返回值:** dict: 查询结果,包含匹配项,其中包含 index_name、index_value、text 和 score + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Search for customers by name similarity +results = flow.row_embeddings_query( + text="John Smith", + schema_name="customers", + user="trustgraph", + collection="sales", + limit=5 +) + +# Filter to specific index +results = flow.row_embeddings_query( + text="machine learning engineer", + schema_name="employees", + index_name="job_title", + limit=10 +) +``` + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict[str, Any] | None = None, operation_name: str | None = None, **kwargs: Any) -> Dict[str, Any]` + +执行针对结构化行的 GraphQL 查询。 + +**参数:** + +`query`: GraphQL 查询字符串 +`user`: 用户/键空间标识符 +`collection`: 集合标识符 +`variables`: 可选的查询变量字典 +`operation_name`: 用于多操作文档的可选操作名称 +`**kwargs`: 传递给服务的附加参数 + +**返回值:** dict: 包含数据、错误和/或扩展的 GraphQL 响应 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +query = ''' +{ + scientists(limit: 10) { + name + field + discoveries + } +} +''' +result = flow.rows_query( + query=query, + user="trustgraph", + collection="scientists" +) +``` + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> str | Iterator[str]` + +执行带有可选流的文本补全。 + +**参数:** + +`system`: 定义助手行为的系统提示。 +`prompt`: 用户提示/问题。 +`streaming`: 启用流模式(默认:False)。 +`**kwargs`: 传递给服务的附加参数。 + +**返回值:** Union[str, Iterator[str]]: 完整的响应或文本块的流。 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Non-streaming +response = flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=False +) +print(response) + +# Streaming +for chunk in flow.text_completion( + system="You are helpful", + prompt="Explain quantum computing", + streaming=True +): + print(chunk, end='', flush=True) +``` + +### `triples_query(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, **kwargs: Any) -> List[Dict[str, Any]]` + +使用模式匹配查询知识图谱三元组。 + +**参数:** + +`s`: 主体过滤器 - URI 字符串、Term 字典,或 None 表示通配符 +`p`: 谓语过滤器 - URI 字符串、Term 字典,或 None 表示通配符 +`o`: 对象过滤器 - URI/字面量字符串、Term 字典,或 None 表示通配符 +`g`: 命名图过滤器 - URI 字符串或 None 表示所有图 +`user`: 用户/键空间标识符(可选) +`collection`: 集合标识符(可选) +`limit`: 返回的最大结果数(默认:100) +`**kwargs`: 传递给服务的其他参数 + +**返回值:** List[Dict]: 匹配的三元组列表,以原始格式返回 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +# Find all triples about a specific subject +triples = flow.triples_query( + s="http://example.org/person/marie-curie", + user="trustgraph", + collection="scientists" +) + +# Query with named graph filter +triples = flow.triples_query( + s="urn:trustgraph:session:abc123", + g="urn:graph:retrieval", + user="trustgraph", + collection="default" +) +``` + +### `triples_query_stream(self, s: str | Dict[str, Any] | None = None, p: str | Dict[str, Any] | None = None, o: str | Dict[str, Any] | None = None, g: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 100, batch_size: int = 20, **kwargs: Any) -> Iterator[List[Dict[str, Any]]]` + +使用流式批处理查询知识图谱三元组。 + +随着三元组的到达,它会产生一批批的三元组,从而减少获得第一个结果所需的时间,并降低大型结果集的内存开销。 + + +**参数:** + +`s`: 主体过滤器 - URI 字符串、Term 字典,或 None 表示通配符 +`p`: 谓语过滤器 - URI 字符串、Term 字典,或 None 表示通配符 +`o`: 对象过滤器 - URI/字面量字符串、Term 字典,或 None 表示通配符 +`g`: 命名图过滤器 - URI 字符串或 None 表示所有图 +`user`: 用户/键空间标识符(可选) +`collection`: 集合标识符(可选) +`limit`: 要返回的最大结果数(默认:100) +`batch_size`: 每批三元组数(默认:20) +`**kwargs`: 传递给服务的其他参数 +`Yields`: +`List[Dict]`: 以线格式的三元组批次 + +**示例:** + +```python +socket = api.socket() +flow = socket.flow("default") + +for batch in flow.triples_query_stream( + user="trustgraph", + collection="default" +): + for triple in batch: + print(triple["s"], triple["p"], triple["o"]) +``` + + +-- + +## `AsyncSocketClient` + +```python +from trustgraph.api import AsyncSocketClient +``` + +异步 WebSocket 客户端 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None)` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + +### `aclose(self)` + +关闭 WebSocket 连接 + +### `flow(self, flow_id: str)` + +获取用于 WebSocket 操作的异步流程实例 + + +-- + +## `AsyncSocketFlowInstance` + +```python +from trustgraph.api import AsyncSocketFlowInstance +``` + +异步 WebSocket 流实例 + +### 方法 + +### `__init__(self, client: trustgraph.api.async_socket_client.AsyncSocketClient, flow_id: str)` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + +### `agent(self, question: str, user: str, state: Dict[str, Any] | None = None, group: str | None = None, history: list | None = None, streaming: bool = False, **kwargs) -> Dict[str, Any] | AsyncIterator` + +带有可选流的 Agent + +### `document_rag(self, query: str, user: str, collection: str, doc_limit: int = 10, streaming: bool = False, **kwargs)` + +带有可选流的文档 RAG + +### `embeddings(self, texts: list, **kwargs)` + +生成文本嵌入 + +### `graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs)` + +用于语义搜索的图嵌入查询 + +### `graph_rag(self, query: str, user: str, collection: str, max_subgraph_size: int = 1000, max_subgraph_count: int = 5, max_entity_distance: int = 3, streaming: bool = False, **kwargs)` + +带有可选流的图 RAG + +### `mcp_tool(self, name: str, parameters: Dict[str, Any], **kwargs)` + +执行 MCP 工具 + +### `prompt(self, id: str, variables: Dict[str, str], streaming: bool = False, **kwargs)` + +带有可选流的提示执行 + +### `row_embeddings_query(self, text: str, schema_name: str, user: str = 'trustgraph', collection: str = 'default', index_name: str | None = None, limit: int = 10, **kwargs)` + +用于结构化数据的语义搜索的行嵌入查询 + +### `rows_query(self, query: str, user: str, collection: str, variables: Dict | None = None, operation_name: str | None = None, **kwargs)` + +对结构化行的 GraphQL 查询 + +### `text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs)` + +带有可选流的文本补全 + +### `triples_query(self, s=None, p=None, o=None, user=None, collection=None, limit=100, **kwargs)` + +三元模式查询 + + +-- + +### `build_term(value: Any, term_type: str | None = None, datatype: str | None = None, language: str | None = None) -> Dict[str, Any] | None` + +从值构建线性的 Term 字典。 + +自动检测规则(当 term_type 为 None 时): + 已经是一个带有 't' 键的字典 -> 保持原样(已经是 Term) + 以 http://, https://, urn: 开头 -> IRI + 包含在 <> 中(例如,)-> IRI(去除尖角括号) + 其他任何内容 -> 文本 + +**参数:** + +`value`: Term 值(字符串、字典或 None) +`term_type`: 'iri'、'literal' 或 None 中的一个,用于自动检测 +`datatype`: 文本对象的类型(例如,xsd:integer) +`language`: 文本对象的语言标签(例如,en) + +**返回值:** dict: 线性的 Term 字典,如果值是 None 则返回 None + + +-- + +## `BulkClient` + +```python +from trustgraph.api import BulkClient +``` + +用于导入/导出的同步批量操作客户端。 + +通过 WebSocket 提供高效的大数据集批量数据传输。 +使用同步生成器包装异步 WebSocket 操作,以提高易用性。 + +注意:要获得真正的异步支持,请使用 AsyncBulkClient。 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +初始化同步批量客户端。 + +**参数:** + +`url`:TrustGraph API 的基本 URL(HTTP/HTTPS 将转换为 WS/WSS) +`timeout`:WebSocket 超时时间(以秒为单位) +`token`:可选的用于身份验证的 bearer token + +### `close(self) -> None` + +关闭连接 + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +从流程中批量导出文档嵌入。 + +通过 WebSocket 流式传输高效下载所有文档块嵌入。 + +**参数:** + +`flow`:流程标识符 +`**kwargs`:附加参数(为未来使用保留) + +**返回值:** Iterator[Dict[str, Any]]: 嵌入字典的流 + +**示例:** + +```python +bulk = api.bulk() + +# Export and process document embeddings +for embedding in bulk.export_document_embeddings(flow="default"): + chunk_id = embedding.get("chunk_id") + vector = embedding.get("embedding") + print(f"{chunk_id}: {len(vector)} dimensions") +``` + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +从流程中批量导出实体上下文。 + +通过 WebSocket 流式传输高效下载所有实体上下文信息。 + +**参数:** + +`flow`: 流程标识符 +`**kwargs`: 附加参数(预留给未来使用) + +**返回值:** Iterator[Dict[str, Any]]: 上下文字典的流 + +**示例:** + +```python +bulk = api.bulk() + +# Export and process entity contexts +for context in bulk.export_entity_contexts(flow="default"): + entity = context.get("entity") + text = context.get("context") + print(f"{entity}: {text[:100]}...") +``` + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> Iterator[Dict[str, Any]]` + +从流程中批量导出图嵌入。 + +能够高效地通过 WebSocket 流式传输下载所有图实体嵌入。 + +**参数:** + +`flow`: 流程标识符 +`**kwargs`: 附加参数(预留给未来使用) + +**返回值:** Iterator[Dict[str, Any]]: 嵌入字典的流 + +**示例:** + +```python +bulk = api.bulk() + +# Export and process embeddings +for embedding in bulk.export_graph_embeddings(flow="default"): + entity = embedding.get("entity") + vector = embedding.get("embedding") + print(f"{entity}: {len(vector)} dimensions") +``` + +### `export_triples(self, flow: str, **kwargs: Any) -> Iterator[trustgraph.api.types.Triple]` + +从流程中批量导出 RDF 三元组。 + +能够高效地通过 WebSocket 流式传输下载所有三元组。 + +**参数:** + +`flow`: 流程标识符 +`**kwargs`: 附加参数(预留给未来使用) + +**返回值:** Iterator[Triple]: 三元组对象的流 + +**示例:** + +```python +bulk = api.bulk() + +# Export and process triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +### `import_document_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +将文档嵌入批量导入到流程中。 + +通过 WebSocket 流式传输高效地上传文档分块嵌入, +用于文档检索增强生成 (RAG) 查询。 + +**参数:** + +`flow`: 流程标识符 +`embeddings`: 产生嵌入字典的迭代器 +`**kwargs`: 附加参数(预留给未来使用) + +**示例:** + +```python +bulk = api.bulk() + +# Generate document embeddings to import +def doc_embedding_generator(): + yield {"chunk_id": "doc1/p0/c0", "embedding": [0.1, 0.2, ...]} + yield {"chunk_id": "doc1/p0/c1", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_document_embeddings( + flow="default", + embeddings=doc_embedding_generator() +) +``` + +### `import_entity_contexts(self, flow: str, contexts: Iterator[Dict[str, Any]], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +将实体上下文批量导入到流程中。 + +通过 WebSocket 流式传输高效地上传实体上下文信息。 +实体上下文为图实体提供额外的文本上下文, +以提高 RAG 的性能。 + +**参数:** + +`flow`: 流程标识符 +`contexts`: 产生上下文字典的迭代器 +`metadata`: 包含 id、元数据、用户、集合的元数据字典 +`batch_size`: 每个批次的上下文数量(默认为 100) +`**kwargs`: 附加参数(为未来使用保留) + +**示例:** + +```python +bulk = api.bulk() + +# Generate entity contexts to import +def context_generator(): + yield {"entity": {"v": "entity1", "e": True}, "context": "Description..."} + yield {"entity": {"v": "entity2", "e": True}, "context": "Description..."} + # ... more contexts + +bulk.import_entity_contexts( + flow="default", + contexts=context_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + +### `import_graph_embeddings(self, flow: str, embeddings: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +批量将图嵌入向量导入到流程中。 + +通过 WebSocket 流式传输高效地上传图实体嵌入向量。 + +**参数:** + +`flow`: 流程标识符 +`embeddings`: 产生嵌入字典的迭代器 +`**kwargs`: 附加参数(预留给未来使用) + +**示例:** + +```python +bulk = api.bulk() + +# Generate embeddings to import +def embedding_generator(): + yield {"entity": "entity1", "embedding": [0.1, 0.2, ...]} + yield {"entity": "entity2", "embedding": [0.3, 0.4, ...]} + # ... more embeddings + +bulk.import_graph_embeddings( + flow="default", + embeddings=embedding_generator() +) +``` + +### `import_rows(self, flow: str, rows: Iterator[Dict[str, Any]], **kwargs: Any) -> None` + +批量将结构化行导入到流程中。 + +通过 WebSocket 流式传输高效地上传结构化数据行, +用于 GraphQL 查询。 + +**参数:** + +`flow`: 流程标识符 +`rows`: 产生行字典的迭代器 +`**kwargs`: 附加参数(为未来使用保留) + +**示例:** + +```python +bulk = api.bulk() + +# Generate rows to import +def row_generator(): + yield {"id": "row1", "name": "Row 1", "value": 100} + yield {"id": "row2", "name": "Row 2", "value": 200} + # ... more rows + +bulk.import_rows( + flow="default", + rows=row_generator() +) +``` + +### `import_triples(self, flow: str, triples: Iterator[trustgraph.api.types.Triple], metadata: Dict[str, Any] | None = None, batch_size: int = 100, **kwargs: Any) -> None` + +批量将 RDF 三元组导入到流程中。 + +通过 WebSocket 流式传输高效地上传大量三元组。 + +**参数:** + +`flow`: 流程标识符 +`triples`: 产生 Triple 对象的迭代器 +`metadata`: 包含 id、元数据、用户、集合的元数据字典 +`batch_size`: 每个批次的元组数量(默认为 100) +`**kwargs`: 其他参数(保留用于未来使用) + +**示例:** + +```python +from trustgraph.api import Triple + +bulk = api.bulk() + +# Generate triples to import +def triple_generator(): + yield Triple(s="subj1", p="pred", o="obj1") + yield Triple(s="subj2", p="pred", o="obj2") + # ... more triples + +# Import triples +bulk.import_triples( + flow="default", + triples=triple_generator(), + metadata={"id": "doc1", "metadata": [], "user": "user1", "collection": "default"} +) +``` + + +-- + +## `AsyncBulkClient` + +```python +from trustgraph.api import AsyncBulkClient +``` + +异步批量操作客户端 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + +### `aclose(self) -> None` + +关闭连接 + +### `export_document_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +通过 WebSocket 批量导出文档嵌入 + +### `export_entity_contexts(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +通过 WebSocket 批量导出实体上下文 + +### `export_graph_embeddings(self, flow: str, **kwargs: Any) -> AsyncIterator[Dict[str, Any]]` + +通过 WebSocket 批量导出图嵌入 + +### `export_triples(self, flow: str, **kwargs: Any) -> AsyncIterator[trustgraph.api.types.Triple]` + +通过 WebSocket 批量导出三元组 + +### `import_document_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +通过 WebSocket 批量导入文档嵌入 + +### `import_entity_contexts(self, flow: str, contexts: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +通过 WebSocket 批量导入实体上下文 + +### `import_graph_embeddings(self, flow: str, embeddings: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +通过 WebSocket 批量导入图嵌入 + +### `import_rows(self, flow: str, rows: AsyncIterator[Dict[str, Any]], **kwargs: Any) -> None` + +通过 WebSocket 批量导入行 + +### `import_triples(self, flow: str, triples: AsyncIterator[trustgraph.api.types.Triple], **kwargs: Any) -> None` + +通过 WebSocket 批量导入三元组 + + +-- + +## `Metrics` + +```python +from trustgraph.api import Metrics +``` + +同步指标客户端 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + +### `get(self) -> str` + +获取 Prometheus 指标,以文本形式 + + +-- + +## `AsyncMetrics` + +```python +from trustgraph.api import AsyncMetrics +``` + +异步指标客户端 + +### 方法 + +### `__init__(self, url: str, timeout: int, token: str | None) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + +### `aclose(self) -> None` + +关闭连接 + +### `get(self) -> str` + +获取 Prometheus 指标(以文本形式) + + +-- + +## `ExplainabilityClient` + +```python +from trustgraph.api import ExplainabilityClient +``` + +客户端,用于获取可解释性实体,并处理最终一致性。 + +使用静默检测:获取、等待、再次获取、比较。 +如果结果相同,则数据稳定。 + +### 方法 + +### `__init__(self, flow_instance, retry_delay: float = 0.2, max_retries: int = 10)` + +初始化可解释性客户端。 + +**参数:** + +`flow_instance`: 用于查询三元组的 SocketFlowInstance。 +`retry_delay`: 重试之间的延迟(以秒为单位)(默认值:0.2)。 +`max_retries`: 最大重试次数(默认值:10)。 + +### `detect_session_type(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> str` + +检测会话是 GraphRAG 还是 Agent 类型。 + +**参数:** + +`session_uri`: 会话/问题的 URI。 +`graph`: 命名图。 +`user`: 用户/键空间标识符。 +`collection`: 集合标识符。 + +**返回值:** "graphrag" 或 "agent"。 + +### `fetch_agent_trace(self, session_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +从会话 URI 开始,获取完整的 Agent 跟踪。 + +遵循溯源链:问题 -> 分析(s) -> 结论。 + +**参数:** + +`session_uri`: Agent 会话/问题的 URI。 +`graph`: 命名图(默认值:urn:graph:retrieval)。 +`user`: 用户/键空间标识符。 +`collection`: 集合标识符。 +`api`: 用于图书管理员访问的 TrustGraph Api 实例(可选)。 +`max_content`: 结论的最大内容长度。 + +**返回值:** 包含问题、迭代(分析列表)和结论实体的字典。 + +### `fetch_docrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +从问题 URI 开始,获取完整的 DocumentRAG 跟踪。 + +遵循溯源链: + 问题 -> 关联 -> 探索 -> 综合。 + +**参数:** + +`question_uri`: 问题实体 URI。 +`graph`: 命名图(默认值:urn:graph:retrieval)。 +`user`: 用户/键空间标识符。 +`collection`: 集合标识符。 +`api`: 用于图书管理员访问的 TrustGraph Api 实例(可选)。 +`max_content`: 综合的最大内容长度。 + +**返回值:** 包含问题、关联、探索和综合实体的字典。 + +### `fetch_document_content(self, document_uri: str, api: Any, user: str | None = None, max_content: int = 10000) -> str` + +通过文档 URI 从图书管理员处获取内容。 + +**参数:** + +`document_uri`: 图书管理员中的文档 URI。 +`api`: 用于图书管理员访问的 TrustGraph Api 实例。 +`user`: 用于图书管理员的用户标识符。 +`max_content`: 要返回的最大内容长度。 + +**返回值:** 文档内容作为字符串。 + +### `fetch_edge_selection(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.EdgeSelection | None` + +获取边缘选择实体(由 Focus 使用)。 + +**参数:** + +`uri`: 边缘选择 URI。 +`graph`: 要查询的命名图。 +`user`: 用户/键空间标识符。 +`collection`: 集合标识符。 + +**返回值:** EdgeSelection 或如果未找到则返回 None。 + +### `fetch_entity(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.ExplainEntity | None` + +通过 URI 获取可解释性实体,并采用最终一致性处理。 + +使用静默检测: +1. 获取 URI 对应的三元组 +2. 如果结果为零,则重试 +3. 如果结果不为零,则等待并再次获取 +4. 如果结果相同,则数据稳定 - 解析并返回 +5. 如果结果不同,则数据仍在写入 - 重试 + +**参数:** + +`uri`: 要获取的实体 URI +`graph`: 查询的命名图 (例如,"urn:graph:retrieval") +`user`: 用户/密钥空间标识符 +`collection`: 集合标识符 + +**返回值:** ExplainEntity 子类,如果未找到则返回 None + +### `fetch_focus_with_edges(self, uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None) -> trustgraph.api.explainability.Focus | None` + +获取 Focus 实体及其所有边选择。 + +**参数:** + +`uri`: Focus 实体 URI +`graph`: 查询的命名图 +`user`: 用户/密钥空间标识符 +`collection`: 集合标识符 + +**返回值:** 包含填充的 edge_selections 的 Focus 对象,如果未找到则返回 None + +### `fetch_graphrag_trace(self, question_uri: str, graph: str | None = None, user: str | None = None, collection: str | None = None, api: Any = None, max_content: int = 10000) -> Dict[str, Any]` + +从问题 URI 开始,获取完整的 GraphRAG 跟踪。 + +遵循溯源链:问题 -> 关联 -> 探索 -> Focus -> 综合 + +**参数:** + +`question_uri`: 问题实体 URI +`graph`: 命名图 (默认: urn:graph:retrieval) +`user`: 用户/密钥空间标识符 +`collection`: 集合标识符 +`api`: 用于 librarian 访问的 TrustGraph Api 实例 (可选) +`max_content`: 综合的最大内容长度 + +**返回值:** 包含 question、grounding、exploration、focus、synthesis 实体的字典 + +### `list_sessions(self, graph: str | None = None, user: str | None = None, collection: str | None = None, limit: int = 50) -> List[trustgraph.api.explainability.Question]` + +列出集合中的所有可解释性会话 (问题)。 + +**参数:** + +`graph`: 命名图 (默认: urn:graph:retrieval) +`user`: 用户/密钥空间标识符 +`collection`: 集合标识符 +`limit`: 要返回的会话的最大数量 + +**返回值:** 按时间戳排序的 Question 实体列表 (最新在前) + +### `resolve_edge_labels(self, edge: Dict[str, str], user: str | None = None, collection: str | None = None) -> Tuple[str, str, str]` + +解决边三元组的所有组件的标签。 + +**参数:** + +`edge`: 包含 "s"、"p"、"o" 键的字典 +`user`: 用户/密钥空间标识符 +`collection`: 集合标识符 + +**返回值:** (s_label, p_label, o_label) 元组 + +### `resolve_label(self, uri: str, user: str | None = None, collection: str | None = None) -> str` + +使用缓存,为 URI 解析 rdfs:label。 + +**参数:** + +`uri`: 要获取标签的 URI +`user`: 用户/密钥空间标识符 +`collection`: 集合标识符 + +**返回值:** 如果找到,则返回标签,否则返回 URI 本身 + + +-- + +## `ExplainEntity` + +```python +from trustgraph.api import ExplainEntity +``` + +可解释性实体的基类。 + +**字段:** + +`uri`: +`entity_type`: + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '') -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `Question` + +```python +from trustgraph.api import Question +``` + +问题实体 - 用户启动会话的查询。 + +**字段:** + +`uri`: +`entity_type`: +`query`: +`timestamp`: +`question_type`: + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '', query: str = '', timestamp: str = '', question_type: str = '') -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `Exploration` + +```python +from trustgraph.api import Exploration +``` + +探索实体 - 从知识库中检索到的边/块。 + +**字段:** + +`uri`: +`entity_type`: +`edge_count`: +`chunk_count`: +`entities`: typing.List[str] + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '', edge_count: int = 0, chunk_count: int = 0, entities: List[str] = ) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `Focus` + +```python +from trustgraph.api import Focus +``` + +关注实体 - 使用 LLM 推理选择的边(仅限 GraphRAG)。 + +**字段:** + +`uri`: +`entity_type`: +`selected_edge_uris`: typing.List[str] +`edge_selections`: typing.List[trustgraph.api.explainability.EdgeSelection] + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '', selected_edge_uris: List[str] = , edge_selections: List[trustgraph.api.explainability.EdgeSelection] = ) -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `Synthesis` + +```python +from trustgraph.api import Synthesis +``` + +综合实体 - 最终答案。 + +**字段:** + +`uri`: +`entity_type`: +`document`: + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `Analysis` + +```python +from trustgraph.api import Analysis +``` + +分析实体 - 一个思考/行动/观察循环(仅限Agent)。 + +**字段:** + +`uri`: +`entity_type`: +`action`: +`arguments`: +`thought`: +`observation`: + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '', action: str = '', arguments: str = '', thought: str = '', observation: str = '') -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `Conclusion` + +```python +from trustgraph.api import Conclusion +``` + +结论实体 - 最终答案(仅限代理)。 + +**字段:** + +`uri`: +`entity_type`: +`document`: + +### 方法 + +### `__init__(self, uri: str, entity_type: str = '', document: str = '') -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `EdgeSelection` + +```python +from trustgraph.api import EdgeSelection +``` + +从 GraphRAG Focus 步骤中选择的边,并附带推理。 + +**字段:** + +`uri`: +`edge`: typing.Dict[str, str] | None +`reasoning`: + +### 方法 + +### `__init__(self, uri: str, edge: Dict[str, str] | None = None, reasoning: str = '') -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +### `wire_triples_to_tuples(wire_triples: List[Dict[str, Any]]) -> List[Tuple[str, str, Any]]` + +将线格式的三元组转换为 (s, p, o) 元组。 + + +-- + +### `extract_term_value(term: Dict[str, Any]) -> Any` + +从线格式的 Term 字典中提取值。 + + +-- + +## `Triple` + +```python +from trustgraph.api import Triple +``` + +RDF三元组,表示知识图谱中的一条陈述。 + +**字段:** + +`s`: +`p`: +`o`: + +### 方法 + +### `__init__(self, s: str, p: str, o: str) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `Uri` + +```python +from trustgraph.api import Uri +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +从给定的对象创建一个新的字符串对象。如果指定了 encoding 或 +errors,则该对象必须公开一个数据缓冲区,该缓冲区将使用给定的编码和错误处理程序进行解码。 +否则,返回 object.__str__() 的结果(如果已定义),或者 repr(object)。 +encoding 默认为 'utf-8'。 +errors 默认为 'strict'。 + +### 方法 + +### ⟦CODE_0⟧ + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `Literal` + +```python +from trustgraph.api import Literal +``` + +str(object='') -> str +str(bytes_or_buffer[, encoding[, errors]]) -> str + +从给定的对象创建一个新的字符串对象。如果指定了 encoding 或 +errors,则该对象必须公开一个数据缓冲区,该缓冲区将使用给定的编码和错误处理程序进行解码。 +否则,返回 object.__str__() 的结果(如果已定义),或者 repr(object)。 +encoding 默认为 'utf-8'。 +errors 默认为 'strict'。 + +### 方法 + +### ⟦CODE_0⟧ + +### `is_literal(self)` + +### `is_triple(self)` + +### `is_uri(self)` + + +-- + +## `ConfigKey` + +```python +from trustgraph.api import ConfigKey +``` + +配置键标识符。 + +**字段:** + +`type`: +`key`: + +### 方法 + +### `__init__(self, type: str, key: str) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `ConfigValue` + +```python +from trustgraph.api import ConfigValue +``` + +配置键值对。 + +**字段:** + +`type`: +`key`: +`value`: + +### 方法 + +### `__init__(self, type: str, key: str, value: str) -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `DocumentMetadata` + +```python +from trustgraph.api import DocumentMetadata +``` + +文档库中一个文档的元数据。 + +**属性:** + +`parent_id: Parent document ID for child documents (empty for top`: level docs) + +**字段:** + +`id`: +`time`: +`kind`: +`title`: +`comments`: +`metadata`: typing.List[trustgraph.api.types.Triple] +`user`: +`tags`: typing.List[str] +`parent_id`: +`document_type`: + +### 方法 + +### `__init__(self, id: str, time: datetime.datetime, kind: str, title: str, comments: str, metadata: List[trustgraph.api.types.Triple], user: str, tags: List[str], parent_id: str = '', document_type: str = 'source') -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `ProcessingMetadata` + +```python +from trustgraph.api import ProcessingMetadata +``` + +正在处理的文档的元数据。 + +**字段:** + +`id`: +`document_id`: +`time`: +`flow`: +`user`: +`collection`: +`tags`: typing.List[str] + +### 方法 + +### `__init__(self, id: str, document_id: str, time: datetime.datetime, flow: str, user: str, collection: str, tags: List[str]) -> None` + +初始化 self。有关准确签名的信息,请参阅 help(type(self))。 + + +-- + +## `CollectionMetadata` + +```python +from trustgraph.api import CollectionMetadata +``` + +数据的元数据。 + +集合提供逻辑分组和隔离,用于文档和 +知识图谱数据。 + +**属性:** + +`name: Human`: 可读的集合名称 + +**字段:** + +`user`: +`collection`: +`name`: +`description`: +`tags`: typing.List[str] + +### 方法 + +### `__init__(self, user: str, collection: str, name: str, description: str, tags: List[str]) -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `StreamingChunk` + +```python +from trustgraph.api import StreamingChunk +``` + +流式响应分块的基础类。 + +用于基于 WebSocket 的流式操作,其中响应以增量方式传递, +并在生成时交付。 + +**字段:** + +`content`: +`end_of_message`: + +### 方法 + +### `__init__(self, content: str, end_of_message: bool = False) -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `AgentThought` + +```python +from trustgraph.api import AgentThought +``` + +代理的推理/思考过程片段。 + +代表代理在执行期间的内部推理或规划步骤。 +这些片段展示了代理如何思考问题。 + +**字段:** + +`content`: +`end_of_message`: +`chunk_type`: + +### 方法 + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'thought') -> None` + +初始化 self。请参考 help(type(self)) 以获取准确的签名。 + + +-- + +## `AgentObservation` + +```python +from trustgraph.api import AgentObservation +``` + +代理工具执行观察块。 + +表示执行工具或操作的结果或观察结果。 +这些块显示了代理通过使用工具学到的内容。 + +**字段:** + +`content`: +`end_of_message`: +`chunk_type`: + +### 方法 + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'observation') -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `AgentAnswer` + +```python +from trustgraph.api import AgentAnswer +``` + +Agent final answer chunk. + +Represents the agent's final response to the user's query after completing +its reasoning and tool use. + +**Attributes:** + +`chunk_type: Always "final`: answer" + +**Fields:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_dialog`: + +### Methods + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'final-answer', end_of_dialog: bool = False) -> None` + +Initialize self. See help(type(self)) for accurate signature. + + +-- + +## `RAGChunk` + +```python +from trustgraph.api import RAGChunk +``` + +RAG(检索增强生成)流式传输块。 + +用于从图 RAG、文档 RAG、文本补全以及其他生成服务中流式传输响应。 + + +**字段:** + +`content`: +`end_of_message`: +`chunk_type`: +`end_of_stream`: +`error`: typing.Dict[str, str] | None + +### 方法 + +### `__init__(self, content: str, end_of_message: bool = False, chunk_type: str = 'rag', end_of_stream: bool = False, error: Dict[str, str] | None = None) -> None` + +初始化 self。有关准确的签名,请参阅 help(type(self))。 + + +-- + +## `ProvenanceEvent` + +```python +from trustgraph.api import ProvenanceEvent +``` + +可解释性的溯源事件。 + +在启用可解释模式时,GraphRAG 查询期间会发出。 +每个事件代表在查询处理过程中创建的溯源节点。 + +**字段:** + +`explain_id`: +`explain_graph`: +`event_type`: + +### 方法 + +### `__init__(self, explain_id: str, explain_graph: str = '', event_type: str = '') -> None` + +初始化 self。请参阅 help(type(self)) 以获取准确的签名。 + + +-- + +## `ProtocolException` + +```python +from trustgraph.api import ProtocolException +``` + +当 WebSocket 协议出现错误时触发。 + + +-- + +## `TrustGraphException` + +```python +from trustgraph.api import TrustGraphException +``` + +TrustGraph 服务所有错误的基类。 + + +-- + +## `AgentError` + +```python +from trustgraph.api import AgentError +``` + +代理服务错误 + + +-- + +## `ConfigError` + +```python +from trustgraph.api import ConfigError +``` + +配置服务错误 + + +-- + +## `DocumentRagError` + +```python +from trustgraph.api import DocumentRagError +``` + +文档检索错误 + + +-- + +## `FlowError` + +```python +from trustgraph.api import FlowError +``` + +流程管理错误 + + +-- + +## `GatewayError` + +```python +from trustgraph.api import GatewayError +``` + +API 网关错误 + + +-- + +## `GraphRagError` + +```python +from trustgraph.api import GraphRagError +``` + +图表 RAG 检索错误 + + +-- + +## `LLMError` + +```python +from trustgraph.api import LLMError +``` + +LLM 服务错误 + + +-- + +## `LoadError` + +```python +from trustgraph.api import LoadError +``` + +数据加载错误 + + +-- + +## `LookupError` + +```python +from trustgraph.api import LookupError +``` + +查找/搜索错误 + + +-- + +## `NLPQueryError` + +```python +from trustgraph.api import NLPQueryError +``` + +自然语言处理查询服务错误 + + +-- + +## `RowsQueryError` + +```python +from trustgraph.api import RowsQueryError +``` + +行查询服务错误 + + +-- + +## `RequestError` + +```python +from trustgraph.api import RequestError +``` + +请求处理错误 + + +-- + +## `StructuredQueryError` + +```python +from trustgraph.api import StructuredQueryError +``` + +结构化查询服务错误 + + +-- + +## `UnexpectedError` + +```python +from trustgraph.api import UnexpectedError +``` + +意外/未知的错误 + + +-- + +## `ApplicationException` + +```python +from trustgraph.api import ApplicationException +``` + +TrustGraph 服务所有错误的基类。 + + +-- diff --git a/docs/tech-specs/__TEMPLATE.ar.md b/docs/tech-specs/__TEMPLATE.ar.md new file mode 100644 index 00000000..65a1aa2d --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.ar.md @@ -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] + +## المراجع + +[المراجع إذا كانت قابلة للتطبيق] diff --git a/docs/tech-specs/__TEMPLATE.es.md b/docs/tech-specs/__TEMPLATE.es.md new file mode 100644 index 00000000..1ea4db1d --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.es.md @@ -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] diff --git a/docs/tech-specs/__TEMPLATE.he.md b/docs/tech-specs/__TEMPLATE.he.md new file mode 100644 index 00000000..d31a8750 --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.he.md @@ -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] + +## מקורות + +[מקורות, אם רלוונטיים] diff --git a/docs/tech-specs/__TEMPLATE.hi.md b/docs/tech-specs/__TEMPLATE.hi.md new file mode 100644 index 00000000..09332f50 --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.hi.md @@ -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] + +## संदर्भ + +[यदि लागू हो, तो संदर्भ] diff --git a/docs/tech-specs/__TEMPLATE.md b/docs/tech-specs/__TEMPLATE.md index df815f6c..b85ffaa6 100644 --- a/docs/tech-specs/__TEMPLATE.md +++ b/docs/tech-specs/__TEMPLATE.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Command-Line Loading Knowledge Technical Specification" +parent: "Tech Specs" +--- + # Command-Line Loading Knowledge Technical Specification ## Overview diff --git a/docs/tech-specs/__TEMPLATE.pt.md b/docs/tech-specs/__TEMPLATE.pt.md new file mode 100644 index 00000000..c2456c01 --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.pt.md @@ -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] diff --git a/docs/tech-specs/__TEMPLATE.ru.md b/docs/tech-specs/__TEMPLATE.ru.md new file mode 100644 index 00000000..dffd437a --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.ru.md @@ -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] + +## Ссылки + +[Ссылки, если применимо] diff --git a/docs/tech-specs/__TEMPLATE.sw.md b/docs/tech-specs/__TEMPLATE.sw.md new file mode 100644 index 00000000..4ba685ec --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.sw.md @@ -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] diff --git a/docs/tech-specs/__TEMPLATE.tr.md b/docs/tech-specs/__TEMPLATE.tr.md new file mode 100644 index 00000000..251091e9 --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.tr.md @@ -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] diff --git a/docs/tech-specs/__TEMPLATE.zh-cn.md b/docs/tech-specs/__TEMPLATE.zh-cn.md new file mode 100644 index 00000000..a0dfa2b4 --- /dev/null +++ b/docs/tech-specs/__TEMPLATE.zh-cn.md @@ -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] diff --git a/docs/tech-specs/agent-explainability.ar.md b/docs/tech-specs/agent-explainability.ar.md new file mode 100644 index 00000000..17dff903 --- /dev/null +++ b/docs/tech-specs/agent-explainability.ar.md @@ -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 الخاص به) +إرسال المصادر بشكل مستمر (إرسال البيانات أثناء العمل، وليس دفعة واحدة في النهاية) diff --git a/docs/tech-specs/agent-explainability.es.md b/docs/tech-specs/agent-explainability.es.md new file mode 100644 index 00000000..d91a0f5c --- /dev/null +++ b/docs/tech-specs/agent-explainability.es.md @@ -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) diff --git a/docs/tech-specs/agent-explainability.he.md b/docs/tech-specs/agent-explainability.he.md new file mode 100644 index 00000000..9e2aa7de --- /dev/null +++ b/docs/tech-specs/agent-explainability.he.md @@ -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 שלו) +פליטת מקורות מידע בסטרימינג (לשלוח תוך כדי פעולה, ולא במקשה בסוף) diff --git a/docs/tech-specs/agent-explainability.hi.md b/docs/tech-specs/agent-explainability.hi.md new file mode 100644 index 00000000..60f89a72 --- /dev/null +++ b/docs/tech-specs/agent-explainability.hi.md @@ -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" +``` + +## भविष्य की योजनाएं (इस पुल अनुरोध में नहीं) + +डीएजी निर्भरताएँ (जब विश्लेषण एन, पिछले कई विश्लेषणों के परिणामों का उपयोग करता है) +टूल-विशिष्ट उत्पत्ति लिंकिंग (नॉलेजक्वेरी → इसका ग्राफआरएजी ट्रेस) +स्ट्रीमिंग उत्पत्ति उत्सर्जन (जैसे-जैसे उत्पन्न होता है, अंत में बैच न करें) diff --git a/docs/tech-specs/agent-explainability.md b/docs/tech-specs/agent-explainability.md index f7900e75..add39fd7 100644 --- a/docs/tech-specs/agent-explainability.md +++ b/docs/tech-specs/agent-explainability.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Agent Explainability: Provenance Recording" +parent: "Tech Specs" +--- + # Agent Explainability: Provenance Recording ## Status diff --git a/docs/tech-specs/agent-explainability.pt.md b/docs/tech-specs/agent-explainability.pt.md new file mode 100644 index 00000000..089beda5 --- /dev/null +++ b/docs/tech-specs/agent-explainability.pt.md @@ -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) diff --git a/docs/tech-specs/agent-explainability.ru.md b/docs/tech-specs/agent-explainability.ru.md new file mode 100644 index 00000000..0332990a --- /dev/null +++ b/docs/tech-specs/agent-explainability.ru.md @@ -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) +Потоковая передача метаданных (отправлять по мере выполнения, а не пакетами в конце) diff --git a/docs/tech-specs/agent-explainability.sw.md b/docs/tech-specs/agent-explainability.sw.md new file mode 100644 index 00000000..30a03e35 --- /dev/null +++ b/docs/tech-specs/agent-explainability.sw.md @@ -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) diff --git a/docs/tech-specs/agent-explainability.tr.md b/docs/tech-specs/agent-explainability.tr.md new file mode 100644 index 00000000..1eb9a773 --- /dev/null +++ b/docs/tech-specs/agent-explainability.tr.md @@ -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) diff --git a/docs/tech-specs/agent-explainability.zh-cn.md b/docs/tech-specs/agent-explainability.zh-cn.md new file mode 100644 index 00000000..a9d61439 --- /dev/null +++ b/docs/tech-specs/agent-explainability.zh-cn.md @@ -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 跟踪) +流式溯源输出(在过程中输出,而不是在最后批量输出) diff --git a/docs/tech-specs/agent-orchestration.md b/docs/tech-specs/agent-orchestration.md index 90723368..ab1569ed 100644 --- a/docs/tech-specs/agent-orchestration.md +++ b/docs/tech-specs/agent-orchestration.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "TrustGraph Agent Orchestration — Technical Specification" +parent: "Tech Specs" +--- + # TrustGraph Agent Orchestration — Technical Specification ## Overview diff --git a/docs/tech-specs/architecture-principles.ar.md b/docs/tech-specs/architecture-principles.ar.md new file mode 100644 index 00000000..02f6c4d0 --- /dev/null +++ b/docs/tech-specs/architecture-principles.ar.md @@ -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. **التوافق التحليلي**: ربط بين نماذج الرسم البياني والأعمدة للاستعلامات الشاملة + +تحدد هذه الأسس بنية رسم بياني للمعرفة تحقق التوازن بين الدقة النظرية ومتطلبات قابلية التوسع العملية، ومحسنة للتكامل مع نماذج اللغة الكبيرة والمعالجة الموزعة. diff --git a/docs/tech-specs/architecture-principles.es.md b/docs/tech-specs/architecture-principles.es.md new file mode 100644 index 00000000..52445ebe --- /dev/null +++ b/docs/tech-specs/architecture-principles.es.md @@ -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. diff --git a/docs/tech-specs/architecture-principles.he.md b/docs/tech-specs/architecture-principles.he.md new file mode 100644 index 00000000..fc986666 --- /dev/null +++ b/docs/tech-specs/architecture-principles.he.md @@ -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) ולעיבוד מבוזר. diff --git a/docs/tech-specs/architecture-principles.hi.md b/docs/tech-specs/architecture-principles.hi.md new file mode 100644 index 00000000..6c06d725 --- /dev/null +++ b/docs/tech-specs/architecture-principles.hi.md @@ -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. **विश्लेषणात्मक अनुकूलता**: व्यापक क्वेरी के लिए ग्राफ और कॉलम प्रतिमानों को जोड़ें। + +ये फाउंडेशन एक नॉलेज ग्राफ आर्किटेक्चर स्थापित करते हैं जो सैद्धांतिक कठोरता को व्यावहारिक स्केलेबिलिटी आवश्यकताओं के साथ संतुलित करता है, जो एलएलएम एकीकरण और वितरित प्रसंस्करण के लिए अनुकूलित है। diff --git a/docs/tech-specs/architecture-principles.md b/docs/tech-specs/architecture-principles.md index 319859ce..b09003ed 100644 --- a/docs/tech-specs/architecture-principles.md +++ b/docs/tech-specs/architecture-principles.md @@ -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. - diff --git a/docs/tech-specs/architecture-principles.pt.md b/docs/tech-specs/architecture-principles.pt.md new file mode 100644 index 00000000..874f6b4f --- /dev/null +++ b/docs/tech-specs/architecture-principles.pt.md @@ -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. diff --git a/docs/tech-specs/architecture-principles.ru.md b/docs/tech-specs/architecture-principles.ru.md new file mode 100644 index 00000000..8e56eeee --- /dev/null +++ b/docs/tech-specs/architecture-principles.ru.md @@ -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 и распределенной обработки. diff --git a/docs/tech-specs/architecture-principles.sw.md b/docs/tech-specs/architecture-principles.sw.md new file mode 100644 index 00000000..cfa93069 --- /dev/null +++ b/docs/tech-specs/architecture-principles.sw.md @@ -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. diff --git a/docs/tech-specs/architecture-principles.tr.md b/docs/tech-specs/architecture-principles.tr.md new file mode 100644 index 00000000..a0bb1cd1 --- /dev/null +++ b/docs/tech-specs/architecture-principles.tr.md @@ -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. diff --git a/docs/tech-specs/architecture-principles.zh-cn.md b/docs/tech-specs/architecture-principles.zh-cn.md new file mode 100644 index 00000000..1c2ed3ef --- /dev/null +++ b/docs/tech-specs/architecture-principles.zh-cn.md @@ -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 集成和分布式处理进行了优化。 diff --git a/docs/tech-specs/cassandra-consolidation.ar.md b/docs/tech-specs/cassandra-consolidation.ar.md new file mode 100644 index 00000000..57d380bd --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.ar.md @@ -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`: +إظهار قيم متغيرات البيئة كقيم افتراضية عند تعيينها +عدم عرض قيم كلمات المرور مطلقًا (إظهار `****` أو `` بدلاً من ذلك) +الإشارة بوضوح إلى ترتيب الحل في نص المساعدة + +مثال على إخراج المساعدة: +``` +--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: ) +``` + +## تفاصيل التنفيذ + +### ترتيب حل المعلمات + +لكل معلمة في 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: )" + 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). diff --git a/docs/tech-specs/cassandra-consolidation.es.md b/docs/tech-specs/cassandra-consolidation.es.md new file mode 100644 index 00000000..f77bebc2 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.es.md @@ -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 `` 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: ) +``` + +## 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` diff --git a/docs/tech-specs/cassandra-consolidation.he.md b/docs/tech-specs/cassandra-consolidation.he.md new file mode 100644 index 00000000..217eec8a --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.he.md @@ -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` חייב: +להציג ערכי משתני סביבה כברירות מחדל כאשר הם מוגדרים +לעולם לא להציג ערכי סיסמה (להציג `****` או `` במקום) +לציין בבירור את סדר הפתרון בטקסט העזרה + +דוגמה לפלט עזרה: +``` +--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: ) +``` + +## פרטי יישום + +### סדר פתרון פרמטרים + +עבור כל פרמטר של 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: )" + 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) diff --git a/docs/tech-specs/cassandra-consolidation.hi.md b/docs/tech-specs/cassandra-consolidation.hi.md new file mode 100644 index 00000000..a8961345 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.hi.md @@ -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` आउटपुट को: +जब सेट किया गया हो तो पर्यावरण चर मानों को डिफ़ॉल्ट के रूप में दिखाना चाहिए +पासवर्ड मानों को कभी भी प्रदर्शित नहीं करना चाहिए (इसके बजाय `****` या `` दिखाएं) +सहायता पाठ में समाधान क्रम को स्पष्ट रूप से इंगित करना चाहिए + +उदाहरण सहायता आउटपुट: +``` +--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: ) +``` + +## कार्यान्वयन विवरण + +### पैरामीटर समाधान का क्रम + +प्रत्येक कैसेंड्रा पैरामीटर के लिए, समाधान का क्रम इस प्रकार होगा: +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: )" + 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 फ़ाइलें) जोड़ने पर विचार करें diff --git a/docs/tech-specs/cassandra-consolidation.md b/docs/tech-specs/cassandra-consolidation.md index c22dca4d..fa2c6e31 100644 --- a/docs/tech-specs/cassandra-consolidation.md +++ b/docs/tech-specs/cassandra-consolidation.md @@ -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) \ No newline at end of file +- Consider adding configuration file support (.env files) diff --git a/docs/tech-specs/cassandra-consolidation.pt.md b/docs/tech-specs/cassandra-consolidation.pt.md new file mode 100644 index 00000000..428e5916 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.pt.md @@ -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 `` 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: ) +``` + +## 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: )" + 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) diff --git a/docs/tech-specs/cassandra-consolidation.ru.md b/docs/tech-specs/cassandra-consolidation.ru.md new file mode 100644 index 00000000..c13fd894 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.ru.md @@ -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` должен: +Показывать значения переменных окружения в качестве значений по умолчанию, если они установлены +Никогда не отображать значения паролей (показывать `****` или `` вместо этого) +Четко указывать порядок разрешения в тексте справки + +Пример вывода справки: +``` +--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: ) +``` + +## Детали реализации + +### Порядок разрешения параметров + +Для каждого параметра 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: )" + 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) diff --git a/docs/tech-specs/cassandra-consolidation.sw.md b/docs/tech-specs/cassandra-consolidation.sw.md new file mode 100644 index 00000000..f96731d8 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.sw.md @@ -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 `` 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: ) +``` + +## 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: )" + 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) diff --git a/docs/tech-specs/cassandra-consolidation.tr.md b/docs/tech-specs/cassandra-consolidation.tr.md new file mode 100644 index 00000000..84667434 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.tr.md @@ -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 `` 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: ) +``` + +## 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: )" + 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ı) diff --git a/docs/tech-specs/cassandra-consolidation.zh-cn.md b/docs/tech-specs/cassandra-consolidation.zh-cn.md new file mode 100644 index 00000000..e6dd3b48 --- /dev/null +++ b/docs/tech-specs/cassandra-consolidation.zh-cn.md @@ -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` 输出必须: +显示已设置的环境变量值作为默认值 +绝不显示密码值(显示 `****` 或 `` 代替) +在帮助文本中清楚地指示解析顺序 + +示例帮助输出: +``` +--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: ) +``` + +## 实现细节 + +### 参数解析顺序 + +对于每个 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: )" + 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 文件) diff --git a/docs/tech-specs/cassandra-performance-refactor.ar.md b/docs/tech-specs/cassandra-performance-refactor.ar.md new file mode 100644 index 00000000..ffcf5d70 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.ar.md @@ -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)، مما يضمن أن التعليمات البرمجية الحالية تستفيد تلقائيًا من تحسينات الأداء. diff --git a/docs/tech-specs/cassandra-performance-refactor.es.md b/docs/tech-specs/cassandra-performance-refactor.es.md new file mode 100644 index 00000000..75f92591 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.es.md @@ -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. diff --git a/docs/tech-specs/cassandra-performance-refactor.he.md b/docs/tech-specs/cassandra-performance-refactor.he.md new file mode 100644 index 00000000..1d890d3d --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.he.md @@ -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 מלאה, ומבטיחה שלקוד הקיים יש יתרונות אוטומטיים משיפורי הביצועים. diff --git a/docs/tech-specs/cassandra-performance-refactor.hi.md b/docs/tech-specs/cassandra-performance-refactor.hi.md new file mode 100644 index 00000000..240e58b9 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.hi.md @@ -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. **बेहतर क्लस्टरिंग प्रभावशीलता** समग्र विभाजन कुंजियों के माध्यम से जो लोड को ठीक से वितरित करते हैं + +यह दृष्टिकोण कैसेंड्रा की ताकत का लाभ उठाता है जबकि पूर्ण एपीआई संगतता बनाए रखता है, यह सुनिश्चित करता है कि मौजूदा कोड प्रदर्शन सुधारों से स्वचालित रूप से लाभान्वित होता है। diff --git a/docs/tech-specs/cassandra-performance-refactor.md b/docs/tech-specs/cassandra-performance-refactor.md index 847b9953..d17f5c65 100644 --- a/docs/tech-specs/cassandra-performance-refactor.md +++ b/docs/tech-specs/cassandra-performance-refactor.md @@ -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 diff --git a/docs/tech-specs/cassandra-performance-refactor.pt.md b/docs/tech-specs/cassandra-performance-refactor.pt.md new file mode 100644 index 00000000..5e6570f9 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.pt.md @@ -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. diff --git a/docs/tech-specs/cassandra-performance-refactor.ru.md b/docs/tech-specs/cassandra-performance-refactor.ru.md new file mode 100644 index 00000000..27e7bed2 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.ru.md @@ -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, что обеспечивает автоматическое получение преимуществ от улучшений производительности для существующего кода. diff --git a/docs/tech-specs/cassandra-performance-refactor.sw.md b/docs/tech-specs/cassandra-performance-refactor.sw.md new file mode 100644 index 00000000..4c073976 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.sw.md @@ -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. diff --git a/docs/tech-specs/cassandra-performance-refactor.tr.md b/docs/tech-specs/cassandra-performance-refactor.tr.md new file mode 100644 index 00000000..6807bd9c --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.tr.md @@ -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. diff --git a/docs/tech-specs/cassandra-performance-refactor.zh-cn.md b/docs/tech-specs/cassandra-performance-refactor.zh-cn.md new file mode 100644 index 00000000..e79d3fd4 --- /dev/null +++ b/docs/tech-specs/cassandra-performance-refactor.zh-cn.md @@ -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 兼容性,确保现有代码能够自动受益于性能改进。 diff --git a/docs/tech-specs/collection-management.ar.md b/docs/tech-specs/collection-management.ar.md new file mode 100644 index 00000000..ec0060de --- /dev/null +++ b/docs/tech-specs/collection-management.ar.md @@ -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, + 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` من جميع الواجهات الخلفية diff --git a/docs/tech-specs/collection-management.es.md b/docs/tech-specs/collection-management.es.md new file mode 100644 index 00000000..0c39fb03 --- /dev/null +++ b/docs/tech-specs/collection-management.es.md @@ -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, + 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 diff --git a/docs/tech-specs/collection-management.he.md b/docs/tech-specs/collection-management.he.md new file mode 100644 index 00000000..61b05205 --- /dev/null +++ b/docs/tech-specs/collection-management.he.md @@ -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, + 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 diff --git a/docs/tech-specs/collection-management.hi.md b/docs/tech-specs/collection-management.hi.md new file mode 100644 index 00000000..77bc9356 --- /dev/null +++ b/docs/tech-specs/collection-management.hi.md @@ -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, + 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` हैंडलर हटाए गए diff --git a/docs/tech-specs/collection-management.md b/docs/tech-specs/collection-management.md index 542abdd0..9bd7201d 100644 --- a/docs/tech-specs/collection-management.md +++ b/docs/tech-specs/collection-management.md @@ -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 - diff --git a/docs/tech-specs/collection-management.pt.md b/docs/tech-specs/collection-management.pt.md new file mode 100644 index 00000000..0bdd7069 --- /dev/null +++ b/docs/tech-specs/collection-management.pt.md @@ -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, + 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 diff --git a/docs/tech-specs/collection-management.ru.md b/docs/tech-specs/collection-management.ru.md new file mode 100644 index 00000000..f708485f --- /dev/null +++ b/docs/tech-specs/collection-management.ru.md @@ -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, + 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` из всех хранилищ diff --git a/docs/tech-specs/collection-management.sw.md b/docs/tech-specs/collection-management.sw.md new file mode 100644 index 00000000..817725b6 --- /dev/null +++ b/docs/tech-specs/collection-management.sw.md @@ -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, + 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 diff --git a/docs/tech-specs/collection-management.tr.md b/docs/tech-specs/collection-management.tr.md new file mode 100644 index 00000000..6d38e028 --- /dev/null +++ b/docs/tech-specs/collection-management.tr.md @@ -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, + 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ı diff --git a/docs/tech-specs/collection-management.zh-cn.md b/docs/tech-specs/collection-management.zh-cn.md new file mode 100644 index 00000000..59071266 --- /dev/null +++ b/docs/tech-specs/collection-management.zh-cn.md @@ -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, + 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` 处理程序 diff --git a/docs/tech-specs/config-push-poke.md b/docs/tech-specs/config-push-poke.md index 4273e46d..bec56046 100644 --- a/docs/tech-specs/config-push-poke.md +++ b/docs/tech-specs/config-push-poke.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Config Push 'Notify' Pattern Technical Specification" +parent: "Tech Specs" +--- + # Config Push "Notify" Pattern Technical Specification ## Overview diff --git a/docs/tech-specs/document-embeddings-chunk-id.ar.md b/docs/tech-specs/document-embeddings-chunk-id.ar.md new file mode 100644 index 00000000..22b0d7b7 --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.ar.md @@ -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. يتيح تتبع مصدر المعلومات في وقت الاستعلام عبر معرف الجزء. diff --git a/docs/tech-specs/document-embeddings-chunk-id.es.md b/docs/tech-specs/document-embeddings-chunk-id.es.md new file mode 100644 index 00000000..53ff3da0 --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.es.md @@ -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. diff --git a/docs/tech-specs/document-embeddings-chunk-id.he.md b/docs/tech-specs/document-embeddings-chunk-id.he.md new file mode 100644 index 00000000..18e75d14 --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.he.md @@ -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). diff --git a/docs/tech-specs/document-embeddings-chunk-id.hi.md b/docs/tech-specs/document-embeddings-chunk-id.hi.md new file mode 100644 index 00000000..1719f486 --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.hi.md @@ -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` के माध्यम से क्वेरी-टाइम उत्पत्ति को सक्षम करता है diff --git a/docs/tech-specs/document-embeddings-chunk-id.md b/docs/tech-specs/document-embeddings-chunk-id.md index 157ecba0..eab4ed06 100644 --- a/docs/tech-specs/document-embeddings-chunk-id.md +++ b/docs/tech-specs/document-embeddings-chunk-id.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Document Embeddings Chunk ID" +parent: "Tech Specs" +--- + # Document Embeddings Chunk ID ## Overview diff --git a/docs/tech-specs/document-embeddings-chunk-id.pt.md b/docs/tech-specs/document-embeddings-chunk-id.pt.md new file mode 100644 index 00000000..f1f7f93e --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.pt.md @@ -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 diff --git a/docs/tech-specs/document-embeddings-chunk-id.ru.md b/docs/tech-specs/document-embeddings-chunk-id.ru.md new file mode 100644 index 00000000..6e48036c --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.ru.md @@ -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. Обеспечивает отслеживание происхождения данных в момент запроса с помощью идентификатора фрагмента. diff --git a/docs/tech-specs/document-embeddings-chunk-id.sw.md b/docs/tech-specs/document-embeddings-chunk-id.sw.md new file mode 100644 index 00000000..80e46896 --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.sw.md @@ -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. diff --git a/docs/tech-specs/document-embeddings-chunk-id.tr.md b/docs/tech-specs/document-embeddings-chunk-id.tr.md new file mode 100644 index 00000000..8d1d490b --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.tr.md @@ -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. diff --git a/docs/tech-specs/document-embeddings-chunk-id.zh-cn.md b/docs/tech-specs/document-embeddings-chunk-id.zh-cn.md new file mode 100644 index 00000000..50c17463 --- /dev/null +++ b/docs/tech-specs/document-embeddings-chunk-id.zh-cn.md @@ -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 实现查询时的数据溯源 diff --git a/docs/tech-specs/embeddings-batch-processing.ar.md b/docs/tech-specs/embeddings-batch-processing.ar.md new file mode 100644 index 00000000..a12a0bc2 --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.ar.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.es.md b/docs/tech-specs/embeddings-batch-processing.es.md new file mode 100644 index 00000000..b25b6caf --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.es.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.he.md b/docs/tech-specs/embeddings-batch-processing.he.md new file mode 100644 index 00000000..a0ccca14 --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.he.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.hi.md b/docs/tech-specs/embeddings-batch-processing.hi.md new file mode 100644 index 00000000..ccaa1361 --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.hi.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.md b/docs/tech-specs/embeddings-batch-processing.md index 59feb0ff..ff9c22eb 100644 --- a/docs/tech-specs/embeddings-batch-processing.md +++ b/docs/tech-specs/embeddings-batch-processing.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Embeddings Batch Processing Technical Specification" +parent: "Tech Specs" +--- + # Embeddings Batch Processing Technical Specification ## Overview diff --git a/docs/tech-specs/embeddings-batch-processing.pt.md b/docs/tech-specs/embeddings-batch-processing.pt.md new file mode 100644 index 00000000..71b49563 --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.pt.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.ru.md b/docs/tech-specs/embeddings-batch-processing.ru.md new file mode 100644 index 00000000..a817407d --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.ru.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.sw.md b/docs/tech-specs/embeddings-batch-processing.sw.md new file mode 100644 index 00000000..d7dd581b --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.sw.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.tr.md b/docs/tech-specs/embeddings-batch-processing.tr.md new file mode 100644 index 00000000..76f189c7 --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.tr.md @@ -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) diff --git a/docs/tech-specs/embeddings-batch-processing.zh-cn.md b/docs/tech-specs/embeddings-batch-processing.zh-cn.md new file mode 100644 index 00000000..69453a4e --- /dev/null +++ b/docs/tech-specs/embeddings-batch-processing.zh-cn.md @@ -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) diff --git a/docs/tech-specs/entity-centric-graph.ar.md b/docs/tech-specs/entity-centric-graph.ar.md new file mode 100644 index 00000000..e34496bd --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.ar.md @@ -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 جداول للتعديل/الإصلاح | جدول بيانات واحد | +| دعم إعادة التعريف | تعقيد إضافي | مناسب بشكل طبيعي | +| تصفية أنواع الكائنات | غير متوفر | أصلي (عبر التجميع حسب نوع الكائن) | diff --git a/docs/tech-specs/entity-centric-graph.es.md b/docs/tech-specs/entity-centric-graph.es.md new file mode 100644 index 00000000..0da1d290 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.es.md @@ -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__]] diff --git a/docs/tech-specs/entity-centric-graph.he.md b/docs/tech-specs/entity-centric-graph.he.md new file mode 100644 index 00000000..e3ad2477 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.he.md @@ -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) | +פלט חוזה (יש לעקוב בדיוק אחר הפורמט). diff --git a/docs/tech-specs/entity-centric-graph.hi.md b/docs/tech-specs/entity-centric-graph.hi.md new file mode 100644 index 00000000..0179bbb1 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.hi.md @@ -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 क्लस्टरिंग के माध्यम से) | diff --git a/docs/tech-specs/entity-centric-graph.md b/docs/tech-specs/entity-centric-graph.md index 33f500f6..6651a006 100644 --- a/docs/tech-specs/entity-centric-graph.md +++ b/docs/tech-specs/entity-centric-graph.md @@ -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) | - diff --git a/docs/tech-specs/entity-centric-graph.pt.md b/docs/tech-specs/entity-centric-graph.pt.md new file mode 100644 index 00000000..50fb3d5a --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.pt.md @@ -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). diff --git a/docs/tech-specs/entity-centric-graph.ru.md b/docs/tech-specs/entity-centric-graph.ru.md new file mode 100644 index 00000000..7bcf57d8 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.ru.md @@ -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 таблица данных | +| Поддержка реификации | Дополнительная сложность | Естественная совместимость | +| Фильтрация по типу объекта | Недоступно | Нативно (через кластеризацию по типу объекта) | diff --git a/docs/tech-specs/entity-centric-graph.sw.md b/docs/tech-specs/entity-centric-graph.sw.md new file mode 100644 index 00000000..5c641ab4 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.sw.md @@ -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) | diff --git a/docs/tech-specs/entity-centric-graph.tr.md b/docs/tech-specs/entity-centric-graph.tr.md new file mode 100644 index 00000000..cfbd3ca6 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.tr.md @@ -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): diff --git a/docs/tech-specs/entity-centric-graph.zh-cn.md b/docs/tech-specs/entity-centric-graph.zh-cn.md new file mode 100644 index 00000000..45ba2ea0 --- /dev/null +++ b/docs/tech-specs/entity-centric-graph.zh-cn.md @@ -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 聚类) | +输出合同(必须严格遵守以下格式): diff --git a/docs/tech-specs/explainability-cli.ar.md b/docs/tech-specs/explainability-cli.ar.md new file mode 100644 index 00000000..88b36c5c --- /dev/null +++ b/docs/tech-specs/explainability-cli.ar.md @@ -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 ` في `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 ` +3. العثور على التركيز: `?focus prov:wasDerivedFrom ` +4. الحصول على الحواف المحددة: ` tg:selectedEdge ?edge` +5. لكل حافة، الحصول على `tg:edge` (سلسلة RDF) و `tg:reasoning` +6. العثور على التجميع: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.es.md b/docs/tech-specs/explainability-cli.es.md new file mode 100644 index 00000000..b5320759 --- /dev/null +++ b/docs/tech-specs/explainability-cli.es.md @@ -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 ` 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 ` +3. Encontrar el enfoque: `?focus prov:wasDerivedFrom ` +4. Obtener los bordes seleccionados: ` tg:selectedEdge ?edge` +5. Para cada borde, obtener `tg:edge` (triple acotado) y `tg:reasoning` +6. Encontrar la síntesis: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.he.md b/docs/tech-specs/explainability-cli.he.md new file mode 100644 index 00000000..a79287af --- /dev/null +++ b/docs/tech-specs/explainability-cli.he.md @@ -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 ` ב-`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 ` +3. מצא מיקוד: `?focus prov:wasDerivedFrom ` +4. קבל קשרים שנבחרו: ` tg:selectedEdge ?edge` +5. עבור כל קשר, קבל `tg:edge` (משולש מצוטט) ו-`tg:reasoning` +6. מצא סינתזה: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.hi.md b/docs/tech-specs/explainability-cli.hi.md new file mode 100644 index 00000000..a2ec3dde --- /dev/null +++ b/docs/tech-specs/explainability-cli.hi.md @@ -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 ` 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 ` +3. फोकस खोजें: `?focus prov:wasDerivedFrom ` +4. चयनित किनारों को प्राप्त करें: ` tg:selectedEdge ?edge` +5. प्रत्येक किनारे के लिए, `tg:edge` (उद्धृत ट्रिपल) और `tg:reasoning` प्राप्त करें। +6. संश्लेषण खोजें: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.md b/docs/tech-specs/explainability-cli.md index 8807ce9b..802c8093 100644 --- a/docs/tech-specs/explainability-cli.md +++ b/docs/tech-specs/explainability-cli.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Explainability CLI Technical Specification" +parent: "Tech Specs" +--- + # Explainability CLI Technical Specification ## Status diff --git a/docs/tech-specs/explainability-cli.pt.md b/docs/tech-specs/explainability-cli.pt.md new file mode 100644 index 00000000..3f0e3620 --- /dev/null +++ b/docs/tech-specs/explainability-cli.pt.md @@ -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 ` 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 ` +3. Encontrar o foco: `?focus prov:wasDerivedFrom ` +4. Obter as arestas selecionadas: ` tg:selectedEdge ?edge` +5. Para cada aresta, obter `tg:edge` (tripla entre aspas) e `tg:reasoning` +6. Encontrar a síntese: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.ru.md b/docs/tech-specs/explainability-cli.ru.md new file mode 100644 index 00000000..264b97bd --- /dev/null +++ b/docs/tech-specs/explainability-cli.ru.md @@ -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 ` в `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 ` +3. Найти фокус: `?focus prov:wasDerivedFrom ` +4. Получить выбранные связи: ` tg:selectedEdge ?edge` +5. Для каждой связи, получить `tg:edge` (цитируемая тройка) и `tg:reasoning` +6. Найти синтез: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.sw.md b/docs/tech-specs/explainability-cli.sw.md new file mode 100644 index 00000000..994bda79 --- /dev/null +++ b/docs/tech-specs/explainability-cli.sw.md @@ -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 ` 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 ` +3. Tafuta umakini: `?focus prov:wasDerivedFrom ` +4. Pata miunganisho iliyochaguliwa: ` tg:selectedEdge ?edge` +5. Kwa kila muunganisho, pata `tg:edge` (triple iliyotiwa mabano) na `tg:reasoning`. +6. Tafuta muhtasari: `?synth prov:wasDerivedFrom ` +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` diff --git a/docs/tech-specs/explainability-cli.tr.md b/docs/tech-specs/explainability-cli.tr.md new file mode 100644 index 00000000..fe16a131 --- /dev/null +++ b/docs/tech-specs/explainability-cli.tr.md @@ -0,0 +1,228 @@ +--- +layout: default +title: "Açıklanabilirlik CLI Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Açıklanabilirlik CLI 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. + +## Durum + +Taslak + +## Genel Bakış + +Bu özellik, TrustGraph'ta açıklanabilirlik verilerini hata ayıklamak ve incelemek için kullanılan CLI araçlarını tanımlar. Bu araçlar, kullanıcıların cevapların nasıl elde edildiğini izlemesini ve kenarlardan kaynak belgelere kadar olan köken zincirini hata ayıklamasını sağlar. + +Üç CLI aracı: + +1. **`tg-show-document-hierarchy`** - Belge → sayfa → parça → kenar hiyerarşisini gösterir +2. **`tg-list-explain-traces`** - Tüm GraphRAG oturumlarını sorularla birlikte listeler +3. **`tg-show-explain-trace`** - Bir oturum için tam açıklanabilirlik izini gösterir + +## Hedefler + +**Hata Ayıklama**: Geliştiricilerin belge işleme sonuçlarını incelemesini sağlar +**Denetlenebilirlik**: Herhangi bir çıkarılan gerçeği kaynak belgesine kadar izleme +**Şeffaflık**: GraphRAG'ın bir cevabı tam olarak nasıl elde ettiğini gösterme +**Kullanılabilirlik**: Akıllı varsayılanlarla basit bir CLI arayüzü + +## Arka Plan + +TrustGraph'un iki köken sistemi vardır: + +1. **Çıkarma zamanı kökeni** (bkz. `extraction-time-provenance.md`): Yükleme sırasında belge → sayfa → parça → kenar ilişkilerini kaydeder. `urn:graph:source` adlı grafte saklanır ve `prov:wasDerivedFrom` kullanılarak oluşturulur. + +2. **Sorgu zamanı açıklanabilirliği** (bkz. `query-time-explainability.md`): GraphRAG sorguları sırasında soru → keşif → odak → sentez zincirini kaydeder. `urn:graph:retrieval` adlı grafte saklanır. + +Mevcut sınırlamalar: +İşleme sonrası belge hiyerarşisini görselleştirmenin kolay bir yolu yok +Açıklanabilirlik verilerini görmek için üçlüleri manuel olarak sorgulamak gerekiyor +Bir GraphRAG oturumunun konsolide bir görünümü yok + +## Teknik Tasarım + +### Araç 1: tg-show-document-hierarchy + +**Amaç**: Bir belge kimliği verildiğinde, türetilen tüm varlıkları gezinerek ve görüntüleyerek. + +**Kullanım**: +```bash +tg-show-document-hierarchy "urn:trustgraph:doc:abc123" +tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123" +``` + +**Argümanlar**: +| Arg | Açıklama | +|-----|-------------| +| `document_id` | Belge URI'si (konumsal) | +| `-u/--api-url` | Ağ geçidi URL'si (varsayılan: `$TRUSTGRAPH_URL`) | +| `-t/--token` | Kimlik doğrulama belirteci (varsayılan: `$TRUSTGRAPH_TOKEN`) | +| `-U/--user` | Kullanıcı Kimliği (varsayılan: `trustgraph`) | +| `-C/--collection` | Koleksiyon (varsayılan: `default`) | +| `--show-content` | Blob/belge içeriğini dahil et | +| `--max-content` | Blob başına maksimum karakter sayısı (varsayılan: 200) | +| `--format` | Çıktı: `tree` (varsayılan), `json` | + +**Uygulama**: +1. Üçlüleri sorgula: `?child prov:wasDerivedFrom ` içinde `urn:graph:source` +2. Her sonucun çocuklarını yinelemeli olarak sorgula +3. Ağaç yapısını oluştur: Belge → Sayfalar → Parçalar +4. Eğer `--show-content` ise, içeriği kütüphaneci API'sinden al +5. Girintili bir ağaç veya JSON olarak göster + +**Çıktı Örneği**: +``` +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] +``` + +### Araç 2: tg-list-explain-traces + +**Amaç**: Bir koleksiyondaki tüm GraphRAG oturumlarını (soruları) listelemek. + +**Kullanım**: +```bash +tg-list-explain-traces +tg-list-explain-traces --limit 20 --format json +``` + +**Argümanlar**: +| Arg | Açıklama | +|-----|-------------| +| `-u/--api-url` | Ağ geçidi URL'si | +| `-t/--token` | Yetkilendirme belirteci | +| `-U/--user` | Kullanıcı Kimliği | +| `-C/--collection` | Koleksiyon | +| `--limit` | Maksimum sonuç sayısı (varsayılan: 50) | +| `--format` | Çıktı: `table` (varsayılan), `json` | + +**Uygulama**: +1. Sorgu: `?session tg:query ?text` içinde `urn:graph:retrieval` +2. Sorgu zaman damgaları: `?session prov:startedAtTime ?time` +3. Tablo olarak göster + +**Çıktı Örneği**: +``` +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 +``` + +### Araç 3: tg-show-explain-trace + +**Amaç**: Bir GraphRAG oturumu için tam açıklanabilirlik zincirini gösterir. + +**Kullanım**: +```bash +tg-show-explain-trace "urn:trustgraph:question:abc123" +tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123" +``` + +**Argümanlar**: +| Arg | Açıklama | +|-----|-------------| +| `question_id` | Soru URI'si (konumsal) | +| `-u/--api-url` | Ağ geçidi URL'si | +| `-t/--token` | Kimlik doğrulama belirteci | +| `-U/--user` | Kullanıcı Kimliği | +| `-C/--collection` | Koleksiyon | +| `--max-answer` | Cevap için maksimum karakter sayısı (varsayılan: 500) | +| `--show-provenance` | Kaynak belgelere kadar kenarları izle | +| `--format` | Çıktı: `text` (varsayılan), `json` | + +**Uygulama**: +1. `tg:query` özniteliğinden soru metnini al. +2. Keşfi bul: `?exp prov:wasGeneratedBy ` +3. Odak noktasını bul: `?focus prov:wasDerivedFrom ` +4. Seçilen kenarları al: ` tg:selectedEdge ?edge` +5. Her kenar için, `tg:edge` (alıntılanmış üçlü) ve `tg:reasoning`'i al. +6. Sentezi bul: `?synth prov:wasDerivedFrom ` +7. Cevabı `tg:document` aracılığıyla kütüphaneciden al. +8. Eğer `--show-provenance` ise, kaynak belgelere kadar kenarları izle. + +**Çıktı Örneği**: +``` +=== 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] +``` + +## Oluşturulacak Dosyalar + +| Dosya | Amaç | +|------|---------| +| `trustgraph-cli/trustgraph/cli/show_document_hierarchy.py` | Araç 1 | +| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Araç 2 | +| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Araç 3 | + +## Değiştirilecek Dosyalar + +| Dosya | Değişiklik | +|------|--------| +| `trustgraph-cli/setup.py` | console_scripts girişlerini ekle | + +## Uygulama Notları + +1. **İkili içerik güvenliği**: UTF-8 ile çözmeyi deneyin; başarısız olursa `[Binary: {size} bytes]` gösterin. +2. **Kısaltma**: `--max-content`/`--max-answer` ile `[truncated]` göstergesine saygı gösterin. +3. **Tırnak işaretli üçlüler**: `tg:edge` önekinden RDF-star formatını ayrıştırın. +4. **Desenler**: `query_graph.py`'dan mevcut CLI desenlerini izleyin. + +## Güvenlik Hususları + +Tüm sorgular, kullanıcı/koleksiyon sınırlarına saygı gösterir. +`--token` veya `$TRUSTGRAPH_TOKEN` aracılığıyla token kimlik doğrulaması desteklenir. + +## Test Stratejisi + +Örnek verilerle manuel doğrulama: +```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" +``` + +## Referanslar + +Sorgu zamanı açıklanabilirlik: `docs/tech-specs/query-time-explainability.md` +Çıkarım zamanı köken bilgisi: `docs/tech-specs/extraction-time-provenance.md` +Mevcut komut satırı örneği: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` diff --git a/docs/tech-specs/explainability-cli.zh-cn.md b/docs/tech-specs/explainability-cli.zh-cn.md new file mode 100644 index 00000000..b6a4ce7e --- /dev/null +++ b/docs/tech-specs/explainability-cli.zh-cn.md @@ -0,0 +1,192 @@ +--- +layout: default +title: "可解释 CLI 技术规范" +parent: "Chinese (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. + +## 状态 + +草稿 + +## 概述 + +本规范描述了用于在 TrustGraph 中调试和探索可解释数据的 CLI 工具。这些工具使用户能够跟踪答案的生成方式,并从边向源文档追溯查询的来源链。 + +三个 CLI 工具: + +1. **`tg-show-document-hierarchy`** - 显示文档 → 页面 → 块 → 边层级结构 +2. **`tg-list-explain-traces`** - 列出所有 GraphRAG 会话,包含问题 +3. **`tg-show-explain-trace`** - 显示会话的完整可解释性跟踪 + +## 目标 + +- **调试**: 允许开发者检查文档处理结果 +- **可追溯性**: 追踪任何提取的事实,追溯到其原始文档 +- **透明性**: 明确显示 GraphRAG 如何得出答案 +- **易用性**: 简单的 CLI 界面,带有合理的默认设置 + +## 背景 + +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` + +**目的**: 针对特定文档 ID,遍历并显示所有派生的实体。 + +**用法**: +```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` | API URL | +| `-t/--token` | 身份验证令牌 | +| `-U/--user` | 用户 ID (默认: `trustgraph`) | +| `-C/--collection` | 集合 (默认: `default`) | +| `--show-content` | 包含内容 (blob/文档内容) | +| `--max-content` | 每个 blob 的最大字符数 (默认: 200) | +| `--format` | 输出格式: `tree` (默认), `json` | + +**实现**: +1. 查询三元组: `?child prov:wasDerivedFrom ` 在 `urn:graph:source` 图表中 +2. 递归查询每个结果的子节点 +3. 构建树结构: 文档 → 页面 → 块 +4. 如果 `--show-content`,则从 librarian 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 +``` + +**参数**: +| 参数 | 描述 | +|---|---| +| `-u/--api-url` | API URL | +| `-t/--token` | 身份验证令牌 | +| `-U/--user` | 用户 ID | +| `-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` | API URL | +| `-t/--token` | 身份验证令牌 | +| `-U/--user` | 用户 ID | +| `-C/--collection` | 集合 | +| `--max-answer` | 答案的最大字符数 (默认: 500) | +| `--show-provenance` | 显示来源文档的边 | +| `--format` | 输出格式: `text` (默认), `json` | + +**实现**: +1. 从 `tg:query` 谓词中获取问题文本 +2. 查找探索: `?exp prov:wasGeneratedBy ` +3. 查找重点: `?focus prov:wasDerivedFrom ` +4. 获取选定的边: ` tg:selectedEdge ?edge` +5. 对于每个边,获取 `tg:edge` (三元组) 和 `tg:reasoning` +6. 查找总结: `?synth prov:wasDerivedFrom ` +7. 通过 librarian API 获取答案 +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 | + +## 引用 + +- 咨询时间可解释性: `docs/tech-specs/query-time-explainability.md` +- 摄取时来源: `docs/tech-specs/extraction-time-provenance.md` +- 现有 CLI 示例: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` diff --git a/docs/tech-specs/extraction-flows.ar.md b/docs/tech-specs/extraction-flows.ar.md new file mode 100644 index 00000000..3d68ac42 --- /dev/null +++ b/docs/tech-specs/extraction-flows.ar.md @@ -0,0 +1,355 @@ +--- +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، بدءًا من تقديم المستندات وصولًا إلى تخزينها في مستودعات المعرفة. + +## نظرة عامة + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## تخزين المحتوى + +### تخزين الكائنات (S3/Minio) + +يتم تخزين محتوى المستندات في تخزين الكائنات المتوافق مع S3: +تنسيق المسار: `doc/{object_id}` حيث object_id هو معرف فريد عالمي (UUID) +يتم تخزين جميع أنواع المستندات هنا: المستندات المصدر، الصفحات، الأجزاء + +### تخزين البيانات الوصفية (Cassandra) + +يتم تخزين البيانات الوصفية للمستندات في Cassandra وتشمل: +معرف المستند، العنوان، النوع (نوع MIME) +مرجع إلى تخزين الكائنات `object_id` +مرجع إلى المستندات الفرعية (الصفحات، الأجزاء) `parent_id` +`document_type`: "source"، "page"، "chunk"، "answer" + +### عتبة التضمين مقابل التدفق + +نقل المحتوى يستخدم استراتيجية تعتمد على الحجم: +**أقل من 2 ميجابايت**: يتم تضمين المحتوى مباشرة في الرسالة (مشفر بـ base64). +**أكبر من أو يساوي 2 ميجابايت**: يتم إرسال `document_id` فقط؛ يقوم المعالج باسترداد البيانات عبر واجهة برمجة التطبيقات الخاصة بالمكتبة. + +## المرحلة الأولى: تقديم المستند (المكتبة) + +### نقطة الدخول + +تدخل المستندات إلى النظام عبر عملية `add-document` الخاصة بالمكتبة: +1. يتم تحميل المحتوى إلى مساحة تخزين الكائنات. +2. يتم إنشاء سجل بيانات وصفية في Cassandra. +3. يتم إرجاع معرف المستند. + +### بدء عملية الاستخراج + +عملية `add-processing` تبدأ عملية الاستخراج: +تحدد `document_id`، و `flow` (معرف المسار)، و `collection` (مخزن الهدف). +تقوم عملية `load_document()` الخاصة بالمكتبة باسترداد المحتوى ونشره في قائمة انتظار الإدخال الخاصة بالتدفق. + +### المخطط: المستند + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**التوجيه:** بناءً على الحقل `kind`: +`application/pdf` → قائمة انتظار `document-load` → وحدة فك ترميز PDF +`text/plain` → قائمة انتظار `text-load` → وحدة تقسيم + +## المرحلة الثانية: وحدة فك ترميز PDF + +تحويل مستندات PDF إلى صفحات نصية. + +### العملية + +1. استرجاع المحتوى (مضمن في `data` أو عبر `document_id` من أمين المكتبة) +2. استخراج الصفحات باستخدام PyPDF +3. لكل صفحة: + حفظ كـ مستند فرعي في أمين المكتبة (`{doc_id}/p{page_num}`) + إرسال ثلاثيات المصدر (الصفحة مشتقة من المستند) + توجيه إلى وحدة التقسيم + +### المخطط: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## المرحلة الثالثة: تقسيم النص إلى أجزاء + +يقسم النص إلى أجزاء عند الحجم المحدد. + +### المعلمات (قابلة للتكوين من خلال التدفق) + +`chunk_size`: الحجم المستهدف للجزء الواحد بالأحرف (الافتراضي: 2000) +`chunk_overlap`: التداخل بين الأجزاء (الافتراضي: 100) + +### العملية + +1. استرجاع محتوى النص (مباشرة أو عبر أمين المكتبة) +2. التقسيم باستخدام مقسم الأحرف التكراري +3. لكل جزء: + حفظ كوثيقة فرعية في أمين المكتبة (`{parent_id}/c{index}`) + إرسال بيانات المصدر (الجزء مشتق من صفحة/مستند) + توجيه إلى معالجات الاستخراج + +### المخطط: جزء + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### التسلسل الهرمي لمعرف المستند + +تقوم المستندات الفرعية بتشفير أصلها في المعرف: +المصدر: `doc123` +الصفحة: `doc123/p5` +جزء من الصفحة: `doc123/p5/c2` +جزء من النص: `doc123/c2` + +## المرحلة 4: استخراج المعرفة + +تتوفر أنماط استخراج متعددة، يتم اختيارها بواسطة إعدادات التدفق. + +### النمط أ: GraphRAG الأساسي + +معالجتان متوازيتان: + +**kg-extract-definitions** +المدخلات: جزء +المخرجات: ثلاثيات (تعريفات الكيانات)، سياقات الكيانات +يستخرج: تسميات الكيانات، التعريفات + +**kg-extract-relationships** +المدخلات: جزء +المخرجات: ثلاثيات (علاقات)، سياقات الكيانات +يستخرج: علاقات الفاعل-الفعل-المفعول + +### النمط ب: مدفوع بالدلالات (kg-extract-ontology) + +المدخلات: جزء +المخرجات: ثلاثيات، سياقات الكيانات +يستخدم دلالات مُكوّنة لتوجيه الاستخراج + +### النمط ج: قائم على الوكيل (kg-extract-agent) + +المدخلات: جزء +المخرجات: ثلاثيات، سياقات الكيانات +يستخدم إطار عمل الوكيل للاستخراج + +### النمط د: استخراج الصفوف (kg-extract-rows) + +المدخلات: جزء +المخرجات: صفوف (بيانات منظمة، وليست ثلاثيات) +يستخدم تعريف المخطط لاستخراج سجلات منظمة + +### المخطط: ثلاثيات + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### المخطط: سياقات الكيانات + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### المخطط: الصفوف + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## المرحلة الخامسة: توليد التضمينات + +### تضمينات الرسم البياني + +تحويل سياقات الكيانات إلى تضمينات متجهة. + +**العملية:** +1. استقبال سياقات الكيانات. +2. استدعاء خدمة التضمينات مع نص السياق. +3. إخراج تضمينات الرسم البياني (ت mapping بين الكيان والمتجه). + +**النموذج: تضمينات الرسم البياني** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### تضمينات المستندات + +يحول النص المقسم مباشرةً إلى تضمينات متجهة. + +**العملية:** +1. استقبال الجزء +2. استدعاء خدمة التضمينات باستخدام نص الجزء +3. إخراج تضمينات المستندات + +**التركيب: تضمينات المستندات** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### تضمينات الصفوف + +تحويل حقول فهرس الصف إلى تضمينات متجهة. + +**العملية:** +1. استقبال الصفوف +2. تضمين حقول الفهرس المحددة +3. الإخراج إلى مخزن المتجهات الصفية + +## المرحلة 6: التخزين + +### مخزن ثلاثي + +يستقبل: ثلاثيات +التخزين: Cassandra (جداول تركز على الكيانات) +الرسوم البيانية المسماة تفصل المعرفة الأساسية عن المصادر: + `""` (افتراضي): حقائق المعرفة الأساسية + `urn:graph:source`: تتبع المصادر + `urn:graph:retrieval`: إمكانية الشرح في وقت الاستعلام + +### مخزن المتجهات (تضمينات الرسم البياني) + +يستقبل: تضمينات الرسم البياني +التخزين: Qdrant، Milvus، أو Pinecone +مفهرس بواسطة: IRI الكيان +البيانات الوصفية: chunk_id لتتبع المصادر + +### مخزن المتجهات (تضمينات المستندات) + +يستقبل: تضمينات المستندات +التخزين: Qdrant، Milvus، أو Pinecone +مفهرس بواسطة: chunk_id + +### مخزن الصفوف + +يستقبل: صفوف +التخزين: Cassandra +هيكل الجدول الموجه بالمخطط + +### مخزن المتجهات الصفية + +يستقبل: تضمينات الصفوف +التخزين: قاعدة بيانات المتجهات +مفهرس بواسطة: حقول فهرس الصف + +## تحليل حقول البيانات الوصفية + +### الحقول المستخدمة بنشاط + +| الحقل | الاستخدام | +|-------|-------| +| `metadata.id` | معرف المستند/الكتلة، التسجيل، تتبع المصادر | +| `metadata.user` | تعدد المستأجرين، توجيه التخزين | +| `metadata.collection` | اختيار المجموعة المستهدفة | +| `document_id` | مرجع أمين المكتبة، ربط تتبع المصادر | +| `chunk_id` | تتبع المصادر عبر مسار العمل | + +<<<<<<< HEAD +### الحقول التي قد تكون زائدة عن الحاجة + +| الحقل | الحالة | +|-------|--------| +| `metadata.metadata` | يتم تعيينه على `[]` بواسطة جميع المستخرجات؛ يتم التعامل مع بيانات وصفية على مستوى المستند الآن بواسطة أمين المكتبة في وقت الإرسال | +======= +### الحقول التي تمت إزالتها + +| الحقل | الحالة | +|-------|--------| +| `metadata.metadata` | تمت إزالته من الفئة `Metadata`. يتم الآن إرسال ثلاثيات البيانات الوصفية على مستوى المستند مباشرةً بواسطة أمين المكتبة إلى مخزن الثلاثيات في وقت الإرسال، ولا يتم نقلها عبر مسار العمل. | +>>>>>>> e3bcbf73 (قائمة البيانات الوصفية (الثلاثيات) في فئة مسار العمل Metadata) + +### نمط حقول البايت + +جميع حقول المحتوى (`data`، `text`، `chunk`) هي `bytes` ولكن يتم فك ترميزها على الفور إلى سلاسل UTF-8 بواسطة جميع المعالجات. لا يستخدم أي معالج بايت خام. + +## تكوين التدفق + +يتم تعريف التدفقات خارجيًا وتقديمها إلى أمين المكتبة عبر خدمة التكوين. يحدد كل تدفق: + +قوائم انتظار الإدخال (`text-load`، `document-load`) +سلسلة المعالجات +المعلمات (حجم الكتلة، طريقة الاستخراج، إلخ.) + +أمثلة على أنماط التدفق: +`pdf-graphrag`: PDF → Decoder → Chunker → Definitions + Relationships → Embeddings +`text-graphrag`: Text → Chunker → Definitions + Relationships → Embeddings +`pdf-ontology`: PDF → Decoder → Chunker → Ontology Extraction → Embeddings +`text-rows`: Text → Chunker → Row Extraction → Row Store diff --git a/docs/tech-specs/extraction-flows.es.md b/docs/tech-specs/extraction-flows.es.md new file mode 100644 index 00000000..ee42c190 --- /dev/null +++ b/docs/tech-specs/extraction-flows.es.md @@ -0,0 +1,355 @@ +--- +layout: default +title: "Flujos de extracción" +parent: "Spanish (Beta)" +--- + +# Flujos de extracción + +> **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. + +Este documento describe cómo los datos fluyen a través de la canalización de extracción de TrustGraph, desde la presentación del documento hasta el almacenamiento en almacenes de conocimiento. + +## Resumen + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## Almacenamiento de contenido + +### Almacenamiento de objetos (S3/Minio) + +El contenido de los documentos se almacena en un almacenamiento de objetos compatible con S3: +Formato de la ruta: `doc/{object_id}` donde object_id es un UUID +Todos los tipos de documentos se almacenan aquí: documentos fuente, páginas, fragmentos + +### Almacenamiento de metadatos (Cassandra) + +Los metadatos de los documentos almacenados en Cassandra incluyen: +ID del documento, título, tipo (MIME) +Referencia al almacenamiento de objetos `object_id` +Referencia `parent_id` para documentos secundarios (páginas, fragmentos) +`document_type`: "fuente", "página", "fragmento", "respuesta" + +### Umbral de contenido en línea frente a transmisión + +La transmisión de contenido utiliza una estrategia basada en el tamaño: +**< 2MB**: El contenido se incluye directamente en el mensaje (codificado en base64) +**≥ 2MB**: Solo se envía `document_id`; el procesador recupera el contenido a través de la API del bibliotecario + +## Etapa 1: Envío de documentos (Bibliotecario) + +### Punto de entrada + +Los documentos ingresan al sistema a través de la operación `add-document` del bibliotecario: +1. El contenido se carga en el almacenamiento de objetos +2. Se crea un registro de metadatos en Cassandra +3. Devuelve el ID del documento + +### Activación de la extracción + +La operación `add-processing` activa la extracción: +Especifica `document_id`, `flow` (ID de la canalización), `collection` (almacén de destino) +La operación `load_document()` del bibliotecario recupera el contenido y lo publica en la cola de entrada del flujo + +### Esquema: Documento + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**Enrutamiento**: Basado en el campo `kind`: +`application/pdf` → cola `document-load` → Decodificador de PDF +`text/plain` → cola `text-load` → Fragmentador + +## Etapa 2: Decodificador de PDF + +Convierte documentos PDF en páginas de texto. + +### Proceso + +1. Obtener contenido (inline `data` o a través de `document_id` desde el bibliotecario) +2. Extraer páginas utilizando PyPDF +3. Para cada página: + Guardar como documento hijo en el bibliotecario (`{doc_id}/p{page_num}`) + Emitir triples de procedencia (página derivada del documento) + Enviar al fragmentador + +### Esquema: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## Etapa 3: Fragmentador + +Divide el texto en fragmentos de un tamaño configurado. + +### Parámetros (configurables) + +`chunk_size`: Tamaño de fragmento objetivo en caracteres (predeterminado: 2000) +`chunk_overlap`: Solapamiento entre fragmentos (predeterminado: 100) + +### Proceso + +1. Obtener el contenido del texto (en línea o a través del bibliotecario) +2. Dividir utilizando un divisor de caracteres recursivo +3. Para cada fragmento: + Guardar como documento hijo en el bibliotecario (`{parent_id}/c{index}`) + Emitir triples de procedencia (fragmento derivado de página/documento) + Enviar a los procesadores de extracción + +### Esquema: Fragmento + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### Jerarquía de Identificadores de Documentos + +Los documentos secundarios codifican su linaje en el identificador: +Fuente: `doc123` +Página: `doc123/p5` +Fragmento de página: `doc123/p5/c2` +Fragmento de texto: `doc123/c2` + +## Etapa 4: Extracción de Conocimiento + +Múltiples patrones de extracción disponibles, seleccionados por la configuración del flujo. + +### Patrón A: Basic GraphRAG + +Dos procesadores paralelos: + +**kg-extract-definitions** +Entrada: Fragmento +Salida: Triples (definiciones de entidades), EntityContexts +Extrae: etiquetas de entidades, definiciones + +**kg-extract-relationships** +Entrada: Fragmento +Salida: Triples (relaciones), EntityContexts +Extrae: relaciones sujeto-predicado-objeto + +### Patrón B: Basado en Ontología (kg-extract-ontology) + +Entrada: Fragmento +Salida: Triples, EntityContexts +Utiliza una ontología configurada para guiar la extracción + +### Patrón C: Basado en Agente (kg-extract-agent) + +Entrada: Fragmento +Salida: Triples, EntityContexts +Utiliza un marco de agente para la extracción + +### Patrón D: Extracción de Filas (kg-extract-rows) + +Entrada: Fragmento +Salida: Filas (datos estructurados, no triples) +Utiliza una definición de esquema para extraer registros estructurados + +### Esquema: Triples + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### Esquema: EntityContexts + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### Esquema: Filas + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## Etapa 5: Generación de Incrustaciones (Embeddings) + +### Incrustaciones de Grafos (Graph Embeddings) + +Convierte los contextos de las entidades en incrustaciones vectoriales. + +**Proceso:** +1. Recibir EntityContexts (Contextos de Entidades) +2. Llamar al servicio de incrustaciones con el texto del contexto +3. Salida: GraphEmbeddings (mapeo de entidad a vector) + +**Esquema: GraphEmbeddings** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### Incrustaciones de documentos + +Convierte texto de fragmentos directamente en incrustaciones vectoriales. + +**Proceso:** +1. Recibir fragmento +2. Llamar al servicio de incrustaciones con el texto del fragmento +3. Salida: Incrustaciones de documentos + +**Esquema: Incrustaciones de documentos** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### Incrustaciones de filas + +Convierte los campos de índice de fila en incrustaciones vectoriales. + +**Proceso:** +1. Recibir filas +2. Incrustar campos de índice configurados +3. Salida a la tienda de vectores de filas + +## Etapa 6: Almacenamiento + +### Triple Store + +Recibe: Triples +Almacenamiento: Cassandra (tablas centradas en entidades) +Los grafos con nombre separan el conocimiento central de la procedencia: + `""` (predeterminado): Hechos de conocimiento central + `urn:graph:source`: Procedencia de extracción + `urn:graph:retrieval`: Explicabilidad en tiempo de consulta + +### Tienda de vectores (Incrustaciones de grafos) + +Recibe: GraphEmbeddings +Almacenamiento: Qdrant, Milvus o Pinecone +Indexado por: IRI de entidad +Metadatos: chunk_id para la procedencia + +### Tienda de vectores (Incrustaciones de documentos) + +Recibe: DocumentEmbeddings +Almacenamiento: Qdrant, Milvus o Pinecone +Indexado por: chunk_id + +### Tienda de filas + +Recibe: Filas +Almacenamiento: Cassandra +Estructura de tabla basada en esquema + +### Tienda de vectores de filas + +Recibe: Incrustaciones de filas +Almacenamiento: Base de datos de vectores +Indexado por: Campos de índice de fila + +## Análisis de campos de metadatos + +### Campos utilizados activamente + +| Campo | Uso | +|-------|-------| +| `metadata.id` | Identificador de documento/fragmento, registro, procedencia | +| `metadata.user` | Multitenencia, enrutamiento de almacenamiento | +| `metadata.collection` | Selección de colección de destino | +| `document_id` | Referencia de bibliotecario, enlace de procedencia | +| `chunk_id` | Seguimiento de la procedencia a través de la canalización | + +<<<<<<< HEAD +### Campos potencialmente redundantes + +| Campo | Estado | +|-------|--------| +| `metadata.metadata` | Establecido en `[]` por todos los extractores; los metadatos a nivel de documento ahora se gestionan por el bibliotecario en el momento de la presentación | +======= +### Campos eliminados + +| Campo | Estado | +|-------|--------| +| `metadata.metadata` | Eliminado de la clase `Metadata`. Los triples de metadatos a nivel de documento ahora se emiten directamente por el bibliotecario a la triple store en el momento de la presentación, y no se transmiten a través de la canalización de extracción. | +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### Patrón de campos de bytes + +Todos los campos de contenido (`data`, `text`, `chunk`) son `bytes`, pero se decodifican inmediatamente a cadenas UTF-8 por todos los procesadores. Ningún procesador utiliza bytes sin procesar. + +## Configuración del flujo + +Los flujos se definen externamente y se proporcionan al bibliotecario a través del servicio de configuración. Cada flujo especifica: + +Colas de entrada (`text-load`, `document-load`) +Cadena de procesadores +Parámetros (tamaño del fragmento, método de extracción, etc.) + +Patrones de flujo de ejemplo: +`pdf-graphrag`: PDF → Decodificador → Fragmentador → Definiciones + Relaciones → Incrustaciones +`text-graphrag`: Texto → Fragmentador → Definiciones + Relaciones → Incrustaciones +`pdf-ontology`: PDF → Decodificador → Fragmentador → Extracción de ontología → Incrustaciones +`text-rows`: Texto → Fragmentador → Extracción de filas → Tienda de filas diff --git a/docs/tech-specs/extraction-flows.he.md b/docs/tech-specs/extraction-flows.he.md new file mode 100644 index 00000000..8e8a9d8d --- /dev/null +++ b/docs/tech-specs/extraction-flows.he.md @@ -0,0 +1,355 @@ +--- +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, החל מהגשת המסמכים ועד לאחסון במאגרי ידע. + +## סקירה כללית + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## אחסון תוכן + +### אחסון בלובים (S3/Minio) + +תוכן מסמכים מאוחסן באחסון בלובים התואם ל-S3: +פורמט נתיב: `doc/{object_id}` כאשר object_id הוא מזהה UUID +כל סוגי המסמכים מאוחסנים כאן: מסמכים מקוריים, עמודים, חלקים + +### אחסון מטא-דאטה (Cassandra) + +מטא-דאטה של מסמכים המאוחסן ב-Cassandra כולל: +מזהה מסמך, כותרת, סוג (MIME type) +הפניה לאחסון הבלובים `object_id` +`parent_id` עבור מסמכים משניים (עמודים, חלקים) +`document_type`: "source", "page", "chunk", "answer" + +### סף בין הטמעה להזרמה + +העברת תוכן משתמשת באסטרטגיה המבוססת על גודל: +**פחות מ-2MB**: התוכן כלול בתוך ההודעה (מקודד ב-base64) +**גדול או שווה ל-2MB**: נשלח רק `document_id`; המעבד שולף דרך ממשק ה-librarian API + +## שלב 1: הגשת מסמך (Librarian) + +### נקודת כניסה + +מסמכים נכנסים למערכת דרך הפעולה `add-document` של ה-librarian: +1. התוכן מועלה לאחסון הבלובים +2. רשומה של מטא-דאטה נוצרת ב-Cassandra +3. מחזיר מזהה מסמך + +### הפעלת חילוץ + +הפעולה `add-processing` מפעילה חילוץ: +מציין `document_id`, `flow` (מזהה צינור), `collection` (מחסן יעד) +הפעולה `load_document()` של ה-librarian שולפת את התוכן ומפרסמת לתור הקלט של ה-flow + +### סכימה: מסמך + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**ניתוב:** בהתבסס על השדה `kind`: +`application/pdf` → תור `document-load` → מפענח PDF +`text/plain` → תור `text-load` → מפרק + +## שלב 2: מפענח PDF + +ממיר מסמכי PDF לעמודי טקסט. + +### תהליך + +1. שליפת תוכן (בשורת `data` או דרך `document_id` מהספרן) +2. חילוץ עמודים באמצעות PyPDF +3. עבור כל עמוד: + שמירה כמסמך משני בספרן (`{doc_id}/p{page_num}`) + שליחת טריפלים של מקור (עמוד שמקורו במסמך) + העברה למפרק + +### סכימה: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## שלב 3: חלוקה לחלקים + +מחלק טקסט לחלקים בגודל מוגדר. + +### פרמטרים (ניתנים להגדרה בתוך זרימת העבודה) + +`chunk_size`: גודל החלק המיועד בתווים (ברירת מחדל: 2000) +`chunk_overlap`: חפיפה בין חלקים (ברירת מחדל: 100) + +### תהליך + +1. שליפת תוכן הטקסט (בשורת הקוד או דרך הספרן) +2. חלוקה באמצעות מפריד תווים רקורסיבי +3. עבור כל חלק: + שמירה כמסמך משני בספרן (`{parent_id}/c{index}`) + שליחת טריפלים של מקור (החלק נגזר מדף/מסמך) + העברה למעבדי חילוץ + +### סכימה: חלק + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### היררכיית מזהי מסמכים + +מסמכים משניים מקודדים את שושלתם במזהה: +מקור: `doc123` +עמוד: `doc123/p5` +מקטע מעמוד: `doc123/p5/c2` +מקטע מטקסט: `doc123/c2` + +## שלב 4: חילוץ ידע + +קיימים דפוסי חילוץ מרובים, הנבחרים על ידי תצורת זרימת העבודה. + +### דפוס א': GraphRAG בסיסי + +שני מעבדים מקבילים: + +**kg-extract-definitions** +קלט: מקטע +פלט: משולשים (הגדרות ישויות), הקשרים של ישויות +מחלץ: תוויות ישויות, הגדרות + +**kg-extract-relationships** +קלט: מקטע +פלט: משולשים (יחסים), הקשרים של ישויות +מחלץ: יחסי נושא-נשוא-אובייקט + +### דפוס ב': מונחה אונטולוגיה (kg-extract-ontology) + +קלט: מקטע +פלט: משולשים, הקשרים של ישויות +משתמש באונטולוגיה מוגדרת כדי להנחות את החילוץ + +### דפוס ג': מבוסס סוכן (kg-extract-agent) + +קלט: מקטע +פלט: משולשים, הקשרים של ישויות +משתמש במסגרת סוכן לחילוץ + +### דפוס ד': חילוץ שורות (kg-extract-rows) + +קלט: מקטע +פלט: שורות (נתונים מובנים, לא משולשים) +משתמש בהגדרת סכימה כדי לחלץ רשומות מובנות + +### סכימה: משולשים + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### סכימה: EntityContexts + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### סכימה: שורות + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## שלב 5: יצירת הטמעות (Embeddings) + +### הטמעות גרפיות (Graph Embeddings) + +ממיר הקשרים של ישויות להטמעות וקטוריות. + +**תהליך:** +1. קבלת הקשרים של ישויות (EntityContexts) +2. הפעלת שירות הטמעות עם טקסט ההקשר +3. פלט הטמעות גרפיות (מיפוי ישות ← וקטור) + +**סכימה: הטמעות גרפיות (GraphEmbeddings)** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### הטמעות מסמכים + +ממיר טקסט מחולק ישירות להטמעות וקטוריות. + +**תהליך:** +1. קבלת מקטע +2. הפעלת שירות הטמעות עם טקסט המקטע +3. פלט הטמעות מסמכים + +**סכימה: הטמעות מסמכים** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### הטמעות שורות + +ממיר שדות אינדקס שורות להטמעות וקטוריות. + +**תהליך:** +1. קבלת שורות +2. הטמעת שדות אינדקס מוגדרים +3. פלט לאחסון וקטורים של שורות + +## שלב 6: אחסון + +### מאגר משולשות + +מקבל: משולשות +אחסון: Cassandra (טבלאות ממוקדות ישויות) +גרפים בעלי שמות מפרידים ידע ליבה ממידע על מקור: + `""` (ברירת מחדל): עובדות ידע ליבה + `urn:graph:source`: מידע על מקור החילוץ + `urn:graph:retrieval`: הסבר בזמן שאילתה + +### מאגר וקטורים (הטמעות גרפים) + +מקבל: הטמעות גרפים +אחסון: Qdrant, Milvus, או Pinecone +מאוּינדקס על ידי: IRI של ישות +מטא-דאטה: chunk_id עבור מידע על מקור + +### מאגר וקטורים (הטמעות מסמכים) + +מקבל: הטמעות מסמכים +אחסון: Qdrant, Milvus, או Pinecone +מאוּינדקס על ידי: chunk_id + +### מאגר שורות + +מקבל: שורות +אחסון: Cassandra +מבנה טבלאות המונחה סכימה + +### מאגר וקטורים של שורות + +מקבל: הטמעות שורות +אחסון: מסד נתונים וקטורי +מאוּנדקס על ידי: שדות אינדקס שורה + +## ניתוח שדות מטא-דאטה + +### שדות בשימוש פעיל + +| שדה | שימוש | +|-------|-------| +| `metadata.id` | מזהה מסמך/חלק, רישום, מקור +| `metadata.user` | ריבוי דיירים, ניתוב אחסון +| `metadata.collection` | בחירת אוסף יעד +| `document_id` | הפניה לספרן, קישור למקור +| `chunk_id` | מעקב אחר מקור לאורך הצינור + +<<<<<<< HEAD +### שדות שעלולים להיות מיותרים + +| שדה | סטטוס | +|-------|--------| +| `metadata.metadata` | מוגדר ל-`[]` על ידי כל המחלצים; מטא-דאטה ברמת המסמך מטופלים כעת על ידי הספרן בזמן ההגשה | +======= +### שדות שהוסרו + +| שדה | סטטוס | +|-------|--------| +| `metadata.metadata` | הוסר ממחלקת `Metadata`. משולשות מטא-דאטה ברמת המסמך משודרים כעת ישירות על ידי הספרן למאגר משולשות בזמן ההגשה, ולא מועברים דרך צינור החילוץ. | +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### תבניות שדות בייטים + +כל שדות התוכן (`data`, `text`, `chunk`) הם `bytes` אך מפענחים מיד לשרשורי UTF-8 על ידי כל המעבדים. אף מעבד לא משתמש בבייטים גולמיים. + +## תצורת זרימה + +זרימות מוגדרות מחוץ למערכת ומועברות לספרן באמצעות שירות התצורה. כל זרימה מציינת: + +תורי קלט (`text-load`, `document-load`) +שרשרת מעבדים +פרמטרים (גודל חתיכה, שיטת חילוץ, וכו') + +דוגמאות לתבניות זרימה: +`pdf-graphrag`: PDF → מפענח → חולק → הגדרות + קשרים → הטמעות +`text-graphrag`: טקסט → חולק → הגדרות + קשרים → הטמעות +`pdf-ontology`: PDF → מפענח → חולק → חילוץ אונטולוגיה → הטמעות +`text-rows`: טקסט → חולק → חילוץ שורות → אחסון שורות diff --git a/docs/tech-specs/extraction-flows.hi.md b/docs/tech-specs/extraction-flows.hi.md new file mode 100644 index 00000000..fb7bb88f --- /dev/null +++ b/docs/tech-specs/extraction-flows.hi.md @@ -0,0 +1,355 @@ +--- +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. + +यह दस्तावेज़ बताता है कि डेटा ट्रस्टग्राफ निष्कर्षण पाइपलाइन के माध्यम से कैसे प्रवाहित होता है, दस्तावेज़ जमा करने से लेकर ज्ञान भंडारों में भंडारण तक। + +## अवलोकन + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## सामग्री भंडारण + +### ब्लॉब भंडारण (S3/Minio) + +दस्तावेज़ सामग्री S3-संगत ब्लॉब भंडारण में संग्रहीत की जाती है: +पथ प्रारूप: `doc/{object_id}` जहाँ object_id एक UUID है +सभी दस्तावेज़ प्रकार यहां संग्रहीत किए जाते हैं: स्रोत दस्तावेज़, पृष्ठ, खंड + +### मेटाडेटा भंडारण (कैसेंड्रा) + +कैसेंड्रा में संग्रहीत दस्तावेज़ मेटाडेटा में शामिल हैं: +दस्तावेज़ आईडी, शीर्षक, प्रकार (MIME प्रकार) +ब्लॉब भंडारण के लिए `object_id` संदर्भ +चाइल्ड दस्तावेज़ों (पृष्ठों, खंडों) के लिए `parent_id` +`document_type`: "स्रोत", "पृष्ठ", "खंड", "उत्तर" + +### इनलाइन बनाम स्ट्रीमिंग थ्रेशोल्ड + +सामग्री प्रेषण एक आकार-आधारित रणनीति का उपयोग करता है: +**< 2MB**: सामग्री संदेश में इनलाइन शामिल है (base64-एन्कोडेड) +**≥ 2MB**: केवल `document_id` भेजा जाता है; प्रोसेसर लाइब्रेरियन API के माध्यम से प्राप्त करता है + +## चरण 1: दस्तावेज़ सबमिशन (लाइब्रेरियन) + +### प्रवेश बिंदु + +दस्तावेज़ लाइब्रेरियन के `add-document` ऑपरेशन के माध्यम से सिस्टम में प्रवेश करते हैं: +1. सामग्री को ब्लॉब भंडारण में अपलोड किया जाता है +2. कैसेंड्रा में मेटाडेटा रिकॉर्ड बनाया जाता है +3. दस्तावेज़ आईडी वापस करता है + +### निष्कर्षण को ट्रिगर करना + +`add-processing` ऑपरेशन निष्कर्षण को ट्रिगर करता है: +`document_id`, `flow` (पाइपलाइन आईडी), `collection` (लक्ष्य स्टोर) निर्दिष्ट करता है +लाइब्रेरियन का `load_document()` सामग्री प्राप्त करता है और फ्लो इनपुट कतार पर प्रकाशित करता है + +### स्कीमा: दस्तावेज़ + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**राउटिंग (Routing)**: `kind` फ़ील्ड के आधार पर: +`application/pdf` → `document-load` क्यू → पीडीएफ डिकोडर +`text/plain` → `text-load` क्यू → चंकर + +## चरण 2: पीडीएफ डिकोडर + +पीडीएफ दस्तावेजों को टेक्स्ट पृष्ठों में परिवर्तित करता है। + +### प्रक्रिया + +1. सामग्री प्राप्त करें (इनलाइन `data` या लाइब्रेरियन से `document_id` के माध्यम से) +2. PyPDF का उपयोग करके पृष्ठों को निकालें +3. प्रत्येक पृष्ठ के लिए: + लाइब्रेरियन में चाइल्ड दस्तावेज़ के रूप में सहेजें (`{doc_id}/p{page_num}`) + प्रामाणिकता ट्रिपल उत्सर्जित करें (पृष्ठ दस्तावेज़ से प्राप्त है) + चंकर को अग्रेषित करें + +### स्कीमा: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## चरण 3: चंकर (Chunker) + +यह टेक्स्ट को कॉन्फ़िगर किए गए आकार में टुकड़ों में विभाजित करता है। + +### पैरामीटर (फ्लो-कॉन्फ़िगर करने योग्य) + +`chunk_size`: अक्षरों में लक्षित टुकड़ा आकार (डिफ़ॉल्ट: 2000) +`chunk_overlap`: टुकड़ों के बीच ओवरलैप (डिफ़ॉल्ट: 100) + +### प्रक्रिया + +1. टेक्स्ट सामग्री प्राप्त करें (इनलाइन या लाइब्रेरियन के माध्यम से) +2. रिकर्सिव कैरेक्टर स्प्लिटर का उपयोग करके विभाजित करें +3. प्रत्येक टुकड़े के लिए: + लाइब्रेरियन में चाइल्ड दस्तावेज़ के रूप में सहेजें (`{parent_id}/c{index}`) + प्रामाणिकता ट्रिपल उत्सर्जित करें (टुकड़ा पृष्ठ/दस्तावेज़ से प्राप्त हुआ है) + निष्कर्षण प्रोसेसर को अग्रेषित करें + +### स्कीमा: टुकड़ा (Chunk) + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### दस्तावेज़ आईडी पदानुक्रम + +चाइल्ड दस्तावेज़ अपनी उत्पत्ति को आईडी में एन्कोड करते हैं: +स्रोत: `doc123` +पृष्ठ: `doc123/p5` +पृष्ठ से अंश: `doc123/p5/c2` +पाठ से अंश: `doc123/c2` + +## चरण 4: ज्ञान निष्कर्षण + +कई निष्कर्षण पैटर्न उपलब्ध हैं, जिन्हें प्रवाह कॉन्फ़िगरेशन द्वारा चुना जाता है। + +### पैटर्न ए: बेसिक ग्राफआरएजी + +दो समानांतर प्रोसेसर: + +**kg-extract-definitions** +इनपुट: अंश +आउटपुट: ट्रिपल (इकाई परिभाषाएँ), एंटिटीकॉन्टेक्स्ट +निष्कर्षण: इकाई लेबल, परिभाषाएँ + +**kg-extract-relationships** +इनपुट: अंश +आउटपुट: ट्रिपल (संबंध), एंटिटीकॉन्टेक्स्ट +निष्कर्षण: विषय-क्रिया-वस्तु संबंध + +### पैटर्न बी: ऑन्टोलॉजी-संचालित (kg-extract-ontology) + +इनपुट: अंश +आउटपुट: ट्रिपल, एंटिटीकॉन्टेक्स्ट +निष्कर्षण को निर्देशित करने के लिए कॉन्फ़िगर की गई ऑन्टोलॉजी का उपयोग करता है + +### पैटर्न सी: एजेंट-आधारित (kg-extract-agent) + +इनपुट: अंश +आउटपुट: ट्रिपल, एंटिटीकॉन्टेक्स्ट +निष्कर्षण के लिए एजेंट फ्रेमवर्क का उपयोग करता है + +### पैटर्न डी: पंक्ति निष्कर्षण (kg-extract-rows) + +इनपुट: अंश +आउटपुट: पंक्तियाँ (संरचित डेटा, ट्रिपल नहीं) +संरचित रिकॉर्ड निकालने के लिए स्कीमा परिभाषा का उपयोग करता है + +### स्कीमा: ट्रिपल + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### स्कीमा: एंटिटीकॉन्टेक्स्ट्स + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### स्कीमा: पंक्तियाँ + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## चरण 5: एम्बेडिंग पीढ़ी + +### ग्राफ एम्बेडिंग + +इकाई संदर्भों को वेक्टर एम्बेडिंग में परिवर्तित करता है। + +**प्रक्रिया:** +1. इकाई संदर्भ प्राप्त करें +2. संदर्भ पाठ के साथ एम्बेडिंग सेवा को कॉल करें +3. ग्राफ एम्बेडिंग आउटपुट करें (इकाई → वेक्टर मैपिंग) + +**स्कीमा: ग्राफ एम्बेडिंग** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### दस्तावेज़ एम्बेडिंग + +यह सीधे टेक्स्ट के टुकड़ों को वेक्टर एम्बेडिंग में परिवर्तित करता है। + +**प्रक्रिया:** +1. टेक्स्ट का टुकड़ा प्राप्त करें +2. टेक्स्ट के टुकड़े के साथ एम्बेडिंग सेवा को कॉल करें +3. दस्तावेज़एम्बेडिंग आउटपुट करें + +**स्कीमा: दस्तावेज़एम्बेडिंग** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### पंक्ति एम्बेडिंग (पंक्ति एम्बेडिंग) + +पंक्ति अनुक्रमणिका फ़ील्ड को वेक्टर एम्बेडिंग में परिवर्तित करता है। + +**प्रक्रिया:** +1. पंक्तियों को प्राप्त करें +2. कॉन्फ़िगर की गई अनुक्रमणिका फ़ील्ड को एम्बेड करें +3. पंक्ति वेक्टर स्टोर पर आउटपुट करें + +## चरण 6: भंडारण (चरण 6: भंडारण) + +### ट्रिपल स्टोर (ट्रिपल स्टोर) + +प्राप्त करता है: ट्रिपल (प्राप्त करता है: ट्रिपल) +भंडारण: कैसेंड्रा (इकाई-केंद्रित तालिकाएँ) (भंडारण: कैसेंड्रा (इकाई-केंद्रित तालिकाएँ)) +नामित ग्राफ मूल ज्ञान को उत्पत्ति से अलग करते हैं: (नामित ग्राफ मूल ज्ञान को उत्पत्ति से अलग करते हैं:) + `""` (डिफ़ॉल्ट): मूल ज्ञान तथ्य (डिफ़ॉल्ट: मूल ज्ञान तथ्य) + `urn:graph:source`: निष्कर्षण उत्पत्ति (निष्कर्षण उत्पत्ति) + `urn:graph:retrieval`: क्वेरी-टाइम व्याख्या (क्वेरी-टाइम व्याख्या) + +### वेक्टर स्टोर (ग्राफ एम्बेडिंग) (वेक्टर स्टोर (ग्राफ एम्बेडिंग)) + +प्राप्त करता है: GraphEmbeddings (प्राप्त करता है: GraphEmbeddings) +भंडारण: Qdrant, Milvus, या Pinecone (भंडारण: Qdrant, Milvus, या Pinecone) +अनुक्रमित: इकाई IRI द्वारा (अनुक्रमित: इकाई IRI द्वारा) +मेटाडेटा: उत्पत्ति के लिए chunk_id (मेटाडेटा: उत्पत्ति के लिए chunk_id) + +### वेक्टर स्टोर (दस्तावेज़ एम्बेडिंग) (वेक्टर स्टोर (दस्तावेज़ एम्बेडिंग)) + +प्राप्त करता है: DocumentEmbeddings (प्राप्त करता है: DocumentEmbeddings) +भंडारण: Qdrant, Milvus, या Pinecone (भंडारण: Qdrant, Milvus, या Pinecone) +अनुक्रमित: chunk_id द्वारा (अनुक्रमित: chunk_id द्वारा) + +### पंक्ति स्टोर (पंक्ति स्टोर) + +प्राप्त करता है: Rows (प्राप्त करता है: Rows) +भंडारण: कैसेंड्रा (भंडारण: कैसेंड्रा) +स्कीमा-संचालित तालिका संरचना (स्कीमा-संचालित तालिका संरचना) + +### पंक्ति वेक्टर स्टोर (पंक्ति वेक्टर स्टोर) + +प्राप्त होता है: पंक्ति एम्बेडिंग (पंक्ति एम्बेडिंग) +भंडारण: वेक्टर डेटाबेस (वेक्टर डेटाबेस) +अनुक्रमित किया गया: पंक्ति अनुक्रमणिका फ़ील्ड द्वारा (पंक्ति अनुक्रमणिका फ़ील्ड द्वारा) + +## मेटाडेटा फ़ील्ड विश्लेषण (मेटाडेटा फ़ील्ड विश्लेषण) + +### सक्रिय रूप से उपयोग किए जाने वाले फ़ील्ड (सक्रिय रूप से उपयोग किए जाने वाले फ़ील्ड) + +| फ़ील्ड | उपयोग | +|-------|-------| +| `metadata.id` | दस्तावेज़/चंक पहचानकर्ता, लॉगिंग, उत्पत्ति (दस्तावेज़/चंक पहचानकर्ता, लॉगिंग, उत्पत्ति) +| `metadata.user` | मल्टी-टेनेंसी, स्टोरेज रूटिंग (मल्टी-टेनेंसी, स्टोरेज रूटिंग) +| `metadata.collection` | लक्ष्य संग्रह चयन (लक्ष्य संग्रह चयन) +| `document_id` | लाइब्रेरियन संदर्भ, उत्पत्ति लिंकिंग (लाइब्रेरियन संदर्भ, उत्पत्ति लिंकिंग) +| `chunk_id` | पाइपलाइन के माध्यम से उत्पत्ति ट्रैकिंग (पाइपलाइन के माध्यम से उत्पत्ति ट्रैकिंग) + +<<<<<<< HEAD +### संभावित रूप से अनावश्यक फ़ील्ड (संभावित रूप से अनावश्यक फ़ील्ड) + +| फ़ील्ड | स्थिति | +|-------|--------| +| `metadata.metadata` | सभी एक्सट्रैक्टरों द्वारा `[]` पर सेट; दस्तावेज़-स्तरीय मेटाडेटा अब सबमिशन के समय लाइब्रेरियन द्वारा संभाला जाता है (सभी एक्सट्रैक्टरों द्वारा `[]` पर सेट; दस्तावेज़-स्तरीय मेटाडेटा अब सबमिशन के समय लाइब्रेरियन द्वारा संभाला जाता है) +======= +### हटाए गए फ़ील्ड (हटाए गए फ़ील्ड) + +| फ़ील्ड | स्थिति | +|-------|--------| +| `metadata.metadata` | `Metadata` वर्ग से हटा दिया गया। दस्तावेज़-स्तरीय मेटाडेटा ट्रिपल अब सीधे लाइब्रेरियन द्वारा ट्रिपल स्टोर को सबमिशन के समय भेजा जाता है, न कि निष्कर्षण पाइपलाइन के माध्यम से (`Metadata` वर्ग से हटा दिया गया। दस्तावेज़-स्तरीय मेटाडेटा ट्रिपल अब सीधे लाइब्रेरियन द्वारा ट्रिपल स्टोर को सबमिशन के समय भेजा जाता है, न कि निष्कर्षण पाइपलाइन के माध्यम से) +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### बाइट्स फ़ील्ड पैटर्न (बाइट्स फ़ील्ड पैटर्न) + +सभी सामग्री फ़ील्ड (`data`, `text`, `chunk`) `bytes` हैं लेकिन सभी प्रोसेसरों द्वारा तुरंत UTF-8 स्ट्रिंग में डिकोड किए जाते हैं। कोई भी प्रोसेसर कच्चे बाइट्स का उपयोग नहीं करता है। + +## फ्लो कॉन्फ़िगरेशन (फ्लो कॉन्फ़िगरेशन) + +फ्लो बाहरी रूप से परिभाषित किए जाते हैं और कॉन्फ़िगरेशन सेवा के माध्यम से लाइब्रेरियन को प्रदान किए जाते हैं। प्रत्येक फ्लो में निम्नलिखित निर्दिष्ट होता है: + +इनपुट क्यू (इनपुट क्यू) (`text-load`, `document-load`) +प्रोसेसर श्रृंखला (प्रोसेसर श्रृंखला) +पैरामीटर (चंक आकार, निष्कर्षण विधि, आदि) (पैरामीटर (चंक आकार, निष्कर्षण विधि, आदि)) + +फ्लो पैटर्न के उदाहरण: (फ्लो पैटर्न के उदाहरण:) +`pdf-graphrag`: PDF → Decoder → Chunker → Definitions + Relationships → Embeddings +`text-graphrag`: Text → Chunker → Definitions + Relationships → Embeddings +`pdf-ontology`: PDF → Decoder → Chunker → Ontology Extraction → Embeddings +`text-rows`: Text → Chunker → Row Extraction → Row Store diff --git a/docs/tech-specs/extraction-flows.md b/docs/tech-specs/extraction-flows.md index aee700c3..54506dc8 100644 --- a/docs/tech-specs/extraction-flows.md +++ b/docs/tech-specs/extraction-flows.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Extraction Flows" +parent: "Tech Specs" +--- + # Extraction Flows This document describes how data flows through the TrustGraph extraction pipeline, from document submission through to storage in knowledge stores. diff --git a/docs/tech-specs/extraction-flows.pt.md b/docs/tech-specs/extraction-flows.pt.md new file mode 100644 index 00000000..4bc08b98 --- /dev/null +++ b/docs/tech-specs/extraction-flows.pt.md @@ -0,0 +1,355 @@ +--- +layout: default +title: "Fluxos de Extração" +parent: "Portuguese (Beta)" +--- + +# Fluxos de Extração + +> **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. + +Este documento descreve como os dados fluem através do pipeline de extração do TrustGraph, desde o envio do documento até ao armazenamento nos repositórios de conhecimento. + +## Visão Geral + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## Armazenamento de Conteúdo + +### Armazenamento de Blobs (S3/Minio) + +O conteúdo do documento é armazenado em armazenamento de blobs compatível com S3: +Formato do caminho: `doc/{object_id}`, onde object_id é um UUID +Todos os tipos de documentos armazenados aqui: documentos de origem, páginas, trechos + +### Armazenamento de Metadados (Cassandra) + +Os metadados do documento armazenados no Cassandra incluem: +ID do documento, título, tipo (MIME) +Referência ao armazenamento de blobs `object_id` +Referência `parent_id` para documentos filhos (páginas, trechos) +`document_type`: "source", "page", "chunk", "answer" + +### Limiar de Incorporação vs. Streaming + +A transmissão de conteúdo usa uma estratégia baseada no tamanho: +**< 2MB**: O conteúdo é incluído inline na mensagem (codificado em base64) +**≥ 2MB**: Apenas `document_id` é enviado; o processador busca via API do bibliotecário + +## Etapa 1: Envio de Documento (Bibliotecário) + +### Ponto de Entrada + +Os documentos entram no sistema através da operação `add-document` do bibliotecário: +1. O conteúdo é carregado no armazenamento de blobs +2. Um registro de metadados é criado no Cassandra +3. Retorna o ID do documento + +### Disparando a Extração + +A operação `add-processing` dispara a extração: +Especifica `document_id`, `flow` (ID do pipeline), `collection` (loja de destino) +A operação `load_document()` do bibliotecário busca o conteúdo e o publica na fila de entrada do fluxo + +### Esquema: Documento + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**Roteamento**: Baseado no campo `kind`: +`application/pdf` → fila `document-load` → Decodificador PDF +`text/plain` → fila `text-load` → Fragmentador + +## Etapa 2: Decodificador PDF + +Converte documentos PDF em páginas de texto. + +### Processo + +1. Buscar conteúdo (inline `data` ou via `document_id` do bibliotecário) +2. Extrair páginas usando PyPDF +3. Para cada página: + Salvar como documento filho no bibliotecário (`{doc_id}/p{page_num}`) + Emitir triplas de procedência (página derivada do documento) + Enviar para o fragmentador + +### Esquema: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## Etapa 3: Divisor em Blocos + +Divide o texto em blocos de tamanho configurado. + +### Parâmetros (configuráveis no fluxo) + +`chunk_size`: Tamanho do bloco alvo em caracteres (padrão: 2000) +`chunk_overlap`: Sobreposição entre blocos (padrão: 100) + +### Processo + +1. Buscar o conteúdo do texto (inline ou via bibliotecário) +2. Dividir usando o divisor de caracteres recursivo +3. Para cada bloco: + Salvar como documento filho no bibliotecário (`{parent_id}/c{index}`) + Emitir triplas de procedência (bloco derivado da página/documento) + Encaminhar para os processadores de extração + +### Esquema: Bloco + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### Hierarquia de Identificação de Documentos + +Documentos filhos codificam sua linhagem no ID: +Fonte: `doc123` +Página: `doc123/p5` +Trecho da página: `doc123/p5/c2` +Trecho de texto: `doc123/c2` + +## Etapa 4: Extração de Conhecimento + +Múltiplos padrões de extração disponíveis, selecionados pela configuração do fluxo. + +### Padrão A: Basic GraphRAG + +Dois processadores paralelos: + +**kg-extract-definitions** +Entrada: Trecho +Saída: Triplas (definições de entidades), Contextos de Entidade +Extrai: rótulos de entidades, definições + +**kg-extract-relationships** +Entrada: Trecho +Saída: Triplas (relacionamentos), Contextos de Entidade +Extrai: relações sujeito-predicado-objeto + +### Padrão B: Orientado a Ontologia (kg-extract-ontology) + +Entrada: Trecho +Saída: Triplas, Contextos de Entidade +Utiliza uma ontologia configurada para guiar a extração + +### Padrão C: Baseado em Agente (kg-extract-agent) + +Entrada: Trecho +Saída: Triplas, Contextos de Entidade +Utiliza um framework de agente para a extração + +### Padrão D: Extração de Linhas (kg-extract-rows) + +Entrada: Trecho +Saída: Linhas (dados estruturados, não triplas) +Utiliza uma definição de esquema para extrair registros estruturados + +### Esquema: Triplas + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### Esquema: EntityContexts + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### Esquema: Linhas + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## Etapa 5: Geração de Embeddings + +### Embeddings de Grafos + +Converte contextos de entidades em embeddings vetoriais. + +**Processo:** +1. Receber EntityContexts +2. Chamar o serviço de embeddings com o texto do contexto +3. Output GraphEmbeddings (mapeamento de entidade para vetor) + +**Esquema: GraphEmbeddings** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### Incorporações de Documentos + +Converte texto em partes diretamente em incorporações vetoriais. + +**Processo:** +1. Receber Parte (Chunk) +2. Chamar o serviço de incorporação com o texto da parte +3. Saída: Incorporações de Documento (DocumentEmbeddings) + +**Esquema: Incorporações de Documento (DocumentEmbeddings)** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### Incorporações de Linhas + +Converte campos de índice de linha em incorporações vetoriais. + +**Processo:** +1. Receber Linhas +2. Incorporar campos de índice configurados +3. Saída para o armazenamento vetorial de linhas + +## Fase 6: Armazenamento + +### Armazenamento Triplo + +Recebe: Triplas +Armazenamento: Cassandra (tabelas centradas em entidades) +Grafos nomeados separam o conhecimento central da procedência: + `""` (padrão): Fatos de conhecimento central + `urn:graph:source`: Procedência de extração + `urn:graph:retrieval`: Explicabilidade em tempo de consulta + +### Armazenamento Vetorial (Incorporações de Grafos) + +Recebe: Incorporações de Grafos +Armazenamento: Qdrant, Milvus ou Pinecone +Indexado por: IRI da entidade +Metadados: chunk_id para procedência + +### Armazenamento Vetorial (Incorporações de Documentos) + +Recebe: Incorporações de Documentos +Armazenamento: Qdrant, Milvus ou Pinecone +Indexado por: chunk_id + +### Armazenamento de Linhas + +Recebe: Linhas +Armazenamento: Cassandra +Estrutura de tabela orientada por esquema + +### Armazenamento Vetorial de Linhas + +Recebe: Incorporações de linhas +Armazenamento: Banco de dados vetorial +Indexado por: campos de índice de linha + +## Análise de Campos de Metadados + +### Campos Ativamente Utilizados + +| Campo | Uso | +|-------|-------| +| `metadata.id` | Identificador de documento/fragmento, registro, procedência | +| `metadata.user` | Multilocação, roteamento de armazenamento | +| `metadata.collection` | Seleção de coleção de destino | +| `document_id` | Referência do bibliotecário, vinculação de procedência | +| `chunk_id` | Rastreamento de procedência através do pipeline | + +<<<<<<< HEAD +### Campos Potencialmente Redundantes + +| Campo | Status | +|-------|--------| +| `metadata.metadata` | Definido como `[]` por todos os extratores; metadados de nível de documento agora gerenciados pelo bibliotecário no momento do envio | +======= +### Campos Removidos + +| Campo | Status | +|-------|--------| +| `metadata.metadata` | Removido da classe `Metadata`. Triplas de metadados de nível de documento agora são emitidas diretamente pelo bibliotecário para o armazenamento de triplas no momento do envio, e não são transmitidas através do pipeline de extração. | +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### Padrão de Campos de Bytes + +Todos os campos de conteúdo (`data`, `text`, `chunk`) são `bytes`, mas são imediatamente decodificados para strings UTF-8 por todos os processadores. Nenhum processador usa bytes brutos. + +## Configuração do Fluxo + +Os fluxos são definidos externamente e fornecidos ao bibliotecário através do serviço de configuração. Cada fluxo especifica: + +Filas de entrada (`text-load`, `document-load`) +Cadeia de processadores +Parâmetros (tamanho do fragmento, método de extração, etc.) + +Padrões de fluxo de exemplo: +`pdf-graphrag`: PDF → Decodificador → Fragmentador → Definições + Relacionamentos → Incorporações +`text-graphrag`: Texto → Fragmentador → Definições + Relacionamentos → Incorporações +`pdf-ontology`: PDF → Decodificador → Fragmentador → Extração de Ontologia → Incorporações +`text-rows`: Texto → Fragmentador → Extração de Linhas → Armazenamento de Linhas diff --git a/docs/tech-specs/extraction-flows.ru.md b/docs/tech-specs/extraction-flows.ru.md new file mode 100644 index 00000000..c439cc23 --- /dev/null +++ b/docs/tech-specs/extraction-flows.ru.md @@ -0,0 +1,355 @@ +--- +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, начиная с отправки документов и заканчивая хранением в хранилищах знаний. + +## Обзор + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## Хранение контента + +### Blob-хранилище (S3/Minio) + +Содержимое документов хранится в блочном хранилище, совместимом с S3: +Формат пути: `doc/{object_id}`, где object_id - это UUID +Все типы документов хранятся здесь: исходные документы, страницы, фрагменты + +### Хранилище метаданных (Cassandra) + +Метаданные документов, хранящиеся в Cassandra, включают: +Идентификатор документа, заголовок, тип (MIME-тип) +Ссылку `object_id` на блочное хранилище +Ссылку `parent_id` для дочерних документов (страниц, фрагментов) +Тип `document_type`: "source", "page", "chunk", "answer" + +### Порог для встроенных данных и потоковой передачи + +Передача контента использует стратегию, основанную на размере: +**< 2 МБ**: Контент включается непосредственно в сообщение (в кодировке base64) +**≥ 2 МБ**: Отправляется только `document_id`; процессор извлекает данные через API librarian + +## Этап 1: Отправка документа (Librarian) + +### Точка входа + +Документы поступают в систему через операцию `add-document` librarian: +1. Контент загружается в блочное хранилище +2. Создается запись метаданных в Cassandra +3. Возвращается идентификатор документа + +### Запуск извлечения + +Операция `add-processing` запускает извлечение: +Указывает `document_id`, `flow` (идентификатор конвейера), `collection` (целевое хранилище) +Операция `load_document()` librarian извлекает контент и публикует его в очередь ввода конвейера + +### Схема: Document + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**Маршрутизация**: Основана на поле `kind`: +`application/pdf` → очередь `document-load` → Декодер PDF +`text/plain` → очередь `text-load` → Разделитель (Chunker) + +## Этап 2: Декодер PDF + +Преобразует документы PDF в текстовые страницы. + +### Процесс + +1. Получение содержимого (встроенное `data` или через `document_id` от библиотекаря) +2. Извлечение страниц с использованием PyPDF +3. Для каждой страницы: + Сохранение как дочерний документ в библиотеке (`{doc_id}/p{page_num}`) + Отправка информации о происхождении (страница получена из документа) + Передача разделителю (chunker) + +### Схема: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## Этап 3: Разделение на фрагменты + +Разделяет текст на фрагменты заданного размера. + +### Параметры (настраиваются в процессе выполнения) + +`chunk_size`: Целевой размер фрагмента в символах (по умолчанию: 2000) +`chunk_overlap`: Перекрытие между фрагментами (по умолчанию: 100) + +### Процесс + +1. Получение содержимого текста (встроенного или через библиотеку) +2. Разделение с использованием рекурсивного разделителя символов +3. Для каждого фрагмента: + Сохранение как дочерний документ в библиотеке (`{parent_id}/c{index}`) + Вывод информации о происхождении (фрагмент получен из страницы/документа) + Передача на этапы обработки извлечения + +### Схема: Фрагмент + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### Иерархия идентификаторов документов + +Дочерние документы кодируют свою родословную в идентификаторе: +Источник: `doc123` +Страница: `doc123/p5` +Часть страницы: `doc123/p5/c2` +Часть текста: `doc123/c2` + +## Этап 4: Извлечение знаний + +Доступно несколько шаблонов извлечения, выбираемых конфигурацией потока. + +### Шаблон A: Базовый GraphRAG + +Два параллельных процессора: + +**kg-extract-definitions** +Вход: Часть текста +Выход: Тройки (определения сущностей), Контексты сущностей +Извлекает: метки сущностей, определения + +**kg-extract-relationships** +Вход: Часть текста +Выход: Тройки (отношения), Контексты сущностей +Извлекает: отношения субъект-предикат-объект + +### Шаблон B: Основанный на онтологии (kg-extract-ontology) + +Вход: Часть текста +Выход: Тройки, Контексты сущностей +Использует настроенную онтологию для управления извлечением + +### Шаблон C: Основанный на агентах (kg-extract-agent) + +Вход: Часть текста +Выход: Тройки, Контексты сущностей +Использует агентную платформу для извлечения + +### Шаблон D: Извлечение строк (kg-extract-rows) + +Вход: Часть текста +Выход: Строки (структурированные данные, а не тройки) +Использует определение схемы для извлечения структурированных записей + +### Схема: Тройки + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### Схема: EntityContexts + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### Схема: Строки + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## Этап 5: Генерация векторных представлений (эмбеддингов) + +### Векторные представления графа + +Преобразует контексты сущностей в векторные представления. + +**Процесс:** +1. Получение контекстов сущностей (EntityContexts) +2. Вызов сервиса генерации векторных представлений с текстом контекста +3. Вывод векторных представлений графа (отображение сущности во вектор) + +**Схема: Векторные представления графа (GraphEmbeddings)** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### Векторные представления документов + +Преобразует текстовые фрагменты непосредственно в векторные представления. + +**Процесс:** +1. Получение фрагмента текста +2. Вызов сервиса векторизации с текстом фрагмента +3. Вывод векторного представления документа + +**Схема: Векторное представление документа** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### Встраивания строк + +Преобразует поля индекса строк в векторные представления. + +**Процесс:** +1. Получение строк +2. Встраивание настроенных полей индекса +3. Вывод в хранилище векторов строк + +## Этап 6: Хранение + +### Тройной магазин + +Получает: Тройки +Хранение: Cassandra (таблицы, ориентированные на сущности) +Именованные графы разделяют основные знания от информации об источнике: + `""` (по умолчанию): Факты основных знаний + `urn:graph:source`: Информация об источнике извлечения + `urn:graph:retrieval`: Объяснимость во время запроса + +### Хранилище векторов (Встраивания графов) + +Получает: Встраивания графов +Хранение: Qdrant, Milvus или Pinecone +Индексируется по: IRI сущности +Метаданные: chunk_id для информации об источнике + +### Хранилище векторов (Встраивания документов) + +Получает: Встраивания документов +Хранение: Qdrant, Milvus или Pinecone +Индексируется по: chunk_id + +### Хранилище строк + +Получает: Строки +Хранение: Cassandra +Структура таблицы, определяемая схемой + +### Хранилище векторов строк + +Получает: Встраивания строк +Хранение: Векторная база данных +Индексируется по: полям индекса строк + +## Анализ полей метаданных + +### Активно используемые поля + +| Поле | Использование | +|-------|-------| +| `metadata.id` | Идентификатор документа/фрагмента, ведение журнала, информация об источнике | +| `metadata.user` | Многопользовательский режим, маршрутизация хранения | +| `metadata.collection` | Выбор целевой коллекции | +| `document_id` | Ссылка на библиотекаря, связывание с информацией об источнике | +| `chunk_id` | Отслеживание информации об источнике через конвейер | + +<<<<<<< HEAD +### Потенциально избыточные поля + +| Поле | Статус | +|-------|--------| +| `metadata.metadata` | Устанавливается в `[]` всеми извлекателями; метаданные на уровне документа теперь обрабатываются библиотекарем при отправке | +======= +### Удаленные поля + +| Поле | Статус | +|-------|--------| +| `metadata.metadata` | Удалено из класса `Metadata`. Тройки метаданных на уровне документа теперь напрямую выдаются библиотекарем в тройной магазин при отправке, а не передаются через конвейер извлечения. | +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### Шаблон полей байтов + +Все поля содержимого (`data`, `text`, `chunk`) являются `bytes`, но немедленно декодируются в строки UTF-8 всеми процессорами. Ни один процессор не использует необработанные байты. + +## Конфигурация потока + +Потоки определяются внешне и предоставляются библиотекарию через сервис конфигурации. Каждый поток определяет: + +Входные очереди (`text-load`, `document-load`) +Цепочка процессоров +Параметры (размер фрагмента, метод извлечения и т. д.) + +Пример шаблонов потоков: +`pdf-graphrag`: PDF → Decoder → Chunker → Definitions + Relationships → Embeddings +`text-graphrag`: Text → Chunker → Definitions + Relationships → Embeddings +`pdf-ontology`: PDF → Decoder → Chunker → Ontology Extraction → Embeddings +`text-rows`: Text → Chunker → Row Extraction → Row Store diff --git a/docs/tech-specs/extraction-flows.sw.md b/docs/tech-specs/extraction-flows.sw.md new file mode 100644 index 00000000..2535dbb4 --- /dev/null +++ b/docs/tech-specs/extraction-flows.sw.md @@ -0,0 +1,355 @@ +--- +layout: default +title: "Mchakato wa Utoaji" +parent: "Swahili (Beta)" +--- + +# Mchakato wa Utoaji + +> **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. + +Hati hii inaeleza jinsi data inapita katika mfumo wa utoaji wa TrustGraph, kuanzia utoaji wa hati hadi uhifadhi katika hifadhia za maarifa. + +## Muhtasari + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## Hifadhi ya Maudhui + +### Uhifadhi wa Data (S3/Minio) + +Maudhui ya nyaraka huhifadhiwa katika uhifadhi wa data unaolingana na S3: +Muundo wa njia: `doc/{object_id}` ambapo object_id ni UUID +Aina zote za nyaraka huhifadhiwa hapa: nyaraka za asili, kurasa, sehemu + +### Uhifadhi wa MetaData (Cassandra) + +MetaData ya nyaraka iliyohifadhiwa katika Cassandra ni pamoja na: +Kitambulisho cha nyaraka, kichwa, aina (aina ya MIME) +Rejea ya `object_id` kwa uhifadhi wa data +`parent_id` kwa nyaraka za watoto (kurasa, sehemu) +`document_type`: "chanzo", "ukurasa", "sehemu", "jibu" + +### Kigezo cha Kwanza na la Kuendelea + +Usafirishaji wa maudhui hutumia mkakati unaotegemea saizi: +**< 2MB**: Maudhui yajumuishwa ndani ya ujumbe (yamekodishwa kwa base64) +**≥ 2MB**: `document_id` pekee hutumwa; mchakato hupata kupitia API ya msimamizi + +## Hatua ya 1: Uwasilishaji wa Nyaraka (Msimamizi) + +### Kifaa cha Kuanzia + +Nyaraka huingia katika mfumo kupitia operesheni ya `add-document` ya msimamizi: +1. Maudhui yamepakuliwa kwenye uhifadhi wa data +2. Rekodi ya metaData imeundwa katika Cassandra +3. Inarudisha kitambulisho cha nyaraka + +### Kuanzisha Utoaji + +Operesheni ya `add-processing` inaanzisha utoaji: +Inaonyesha `document_id`, `flow` (kitambulisho cha mnyororo), `collection` (hifadhi inayolengwa) +Msimamizi wa `load_document()` hupata maudhui na huyaweka kwenye folyo ya ingizo + +### Muundo: Nyaraka + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**Uelekezaji:** Kulingana na sehemu `kind`: +`application/pdf` → Kundi `document-load` → Kipangishi cha PDF +`text/plain` → Kundi `text-load` → Kipande + +## Hatua ya 2: Kipangishi cha PDF + +Hubadilisha hati za PDF kuwa kurasa za maandishi. + +### Mchakato + +1. Pata maudhui (moja kwa moja `data` au kupitia `document_id` kutoka kwa msimamizi) +2. Toa kurasa kwa kutumia PyPDF +3. Kwa kila ukurasa: + Hifadhi kama hati ndogo kwa msimamizi (`{doc_id}/p{page_num}`) + Toa matoleo ya asili (ukurasa ulichukuliwa kutoka hati) + Peleka kwa kipande + +### Mpango: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## Hatua ya 3: Kugawanya maandishi + +Hugawanya maandishi katika sehemu ndogo kulingana na ukubwa uliopangwa. + +### Vigezo (vielekezi ambavyo vinaweza kusanidiwa) + +`chunk_size`: Ukubwa unaolengwa wa sehemu ndogo kwa herufi (kiwango chachilia: 2000) +`chunk_overlap`: Mzunguko kati ya sehemu ndogo (kiwango chachilia: 100) + +### Mchakato + +1. Pata maudhui ya maandishi (moja kwa moja au kupitia mfumo wa kumbukumbu) +2. Gawanya kwa kutumia mgawaji wa herufi unaojielekeza +3. Kwa kila sehemu ndogo: + Hifadhi kama hati ndogo katika mfumo wa kumbukumbu (`{parent_id}/c{index}`) + Toa taarifa za asili (sehemu ndogo ilitokana na ukurasa/hati) + Peleka kwa vichakavu vya utoaji + +### Muundo: Sehemu Ndogo + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### Hierarkia ya Kitambulisho cha Hati + +Hati za chini huandika urithi wao katika kitambulisho: +Chanzo: `doc123` +Ukurasa: `doc123/p5` +Sehemu kutoka ukurasa: `doc123/p5/c2` +Sehemu kutoka maandishi: `doc123/c2` + +## Hatua ya 4: Utokaji wa Maarifa + +Mfumo mbalimbali wa utokaji unapatikana, unaochaguliwa na usanidi wa mtiririko. + +### Mfumo A: Basic GraphRAG + +Wasindikaji wawili sambamba: + +**kg-extract-definitions** +Ingizo: Sehemu +Patoto: Triples (ufafanuzi wa vitu), EntityContexts +Hutokaje: lebo za vitu, ufafanuzi + +**kg-extract-relationships** +Ingizo: Sehemu +Patoto: Triples (uhusiano), EntityContexts +Hutokaje: uhusiano wa subjekti-kivumbe-kijisumu + +### Mfumo B: Inayoendeshwa na Ontolojia (kg-extract-ontology) + +Ingizo: Sehemu +Patoto: Triples, EntityContexts +Hutumia ontolojia iliyosanidiwa ili kuongoza utokaji + +### Mfumo C: Inayoendeshwa na Wakala (kg-extract-agent) + +Ingizo: Sehemu +Patoto: Triples, EntityContexts +Hutumia mfumo wa wakala kwa utokaji + +### Mfumo D: Utokaji wa Mistari (kg-extract-rows) + +Ingizo: Sehemu +Patoto: Mistari (data iliyopangwa, si triples) +Hutumia ufafanuzi wa schema ili kutokaje rekodi zilizopangwa + +### Schema: Triples + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### Mfumo: EntityContexts + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### Mfumo: Safu + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## Hatua ya 5: Uzalishaji wa Uelekezo (Embeddings) + +### Uelekezo wa Grafu + +Hubadilisha muktadha wa vitu katika uelekezo wa vector. + +**Mchakato:** +1. Pokea Muktadha wa Vitu (EntityContexts) +2. Piga simu kwa huduma ya uelekezo (embeddings) kwa kutumia maandishi ya muktadha +3. Toa Uelekezo wa Grafu (ramani ya kitu hadi vector) + +**Muundo: Uelekezo wa Grafu (GraphEmbeddings)** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### Uelekezaji wa Hati + +Hubadilisha maandishi ya sehemu moja moja kwa uelekezaji wa vector. + +**Mchakato:** +1. Pokea Sehemu +2. Piga simu kwa huduma ya uelekezaji kwa kutumia maandishi ya sehemu +3. Toa Uelekezaji wa Hati + +**Muundo: Uelekezaji wa Hati** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### Ulinganisho wa Safu + +Hubadilisha nambari za safu kuwa ulinganisho wa vekta. + +**Mchakato:** +1. Pokea Safu +2. Linganisha nambari zilizoelezwa za safu +3. Toa kwenye hifadhi ya vekta ya safu + +## Hatua ya 6: Uhifadhi + +### Hifadhi ya Triple + +Inapokea: Triples +Uhifadhi: Cassandra (meza zenye msingi wa vitu) +Picha zilizoainishwa zinatenganisha maarifa ya msingi kutoka kwa asili: + `""` (ya kawaida): Ukweli wa maarifa ya msingi + `urn:graph:source`: Asili ya uondoaji + `urn:graph:retrieval`: Uwezekano wa kufafanua wakati wa kuuliza + +### Hifadhi ya Vektaja (Ulinganisho wa Picha) + +Inapokea: Ulinganisho wa Picha +Uhifadhi: Qdrant, Milvus, au Pinecone +Imeorodheshwa kwa: IRI ya kitu +Meta: chunk_id kwa asili + +### Hifadhi ya Vektaja (Ulinganisho wa Nyaraka) + +Inapokea: Ulinganisho wa Nyaraka +Uhifadhi: Qdrant, Milvus, au Pinecone +Imeorodheshwa kwa: chunk_id + +### Hifadhi ya Safu + +Inapokea: Safu +Uhifadhi: Cassandra +Muundo wa meza unaoongozwa na schema + +### Hifadhi ya Vektaja ya Safu + +Inapokea: Ulinganisho wa safu +Uhifadhi: Hifadhi ya Vektaja +Imeorodheshwa kwa: nambari za safu + +## Uchunguzi wa Uwanja wa Meta + +### Uwanja Unaotumika Kwa Kazi + +| Uwanja | Matumizi | +|-------|-------| +| `metadata.id` | Kitambulisho cha nyaraka/kipande, uandishi wa matukio, asili | +| `metadata.user` | Usimamizi wa wateja wengi, uelekezaji wa uhifadhi | +| `metadata.collection` | Uchaguzi wa mkusanyiko unaolengwa | +| `document_id` | Rejea ya mkusanyaji, kuunganisha asili | +| `chunk_id` | Kufuatilia asili kupitia mnyororo | + +<<<<<<< HEAD +### Uwanja Unaowezekana kuwa Ziada + +| Uwanja | Hali | +|-------|--------| +| `metadata.metadata` | Imepangwa kama `[]` na vichujio vyote; meta ya kiwango cha nyaraka sasa inashughulikiwa na mkusanyaji wakati wa kuwasilisha | +======= +### Uwanja Ulioondolewa + +| Uwanja | Hali | +|-------|--------| +| `metadata.metadata` | Imeondolewa kutoka kwa darasa la `Metadata`. Triples za meta ya kiwango cha nyaraka sasa hutolewa moja kwa moja na mkusanyaji kwenye hifadhi ya triples wakati wa kuwasilisha, sio kuletwa kupitia mnyororo wa uondoaji. | +>>>>>>> e3bcbf73 (Uwanja wa meta (orodha ya triples) katika darasa la Mnyororo wa Meta) + +### Mfumo wa Uwanja wa Bytes + +Uwanja wote wa yaliyomo (`data`, `text`, `chunk`) ni `bytes` lakini huondolewa mara moja kuwa maandishi ya UTF-8 na vichujio vyote. Hakuna kichujio kinachotumia bytes mbichi. + +## Usanidi wa Mnyororo + +Mnyororo huainishwa nje na hutolewa kwa mkusanyaji kupitia huduma ya usanidi. Kila mnyororo unaonyesha: + +Ndege za ingizo (`text-load`, `document-load`) +Mnyororo wa vichujio +Vigezo (ukubwa wa kipande, njia ya uondoaji, n.k.) + +Mifano ya mnyororo: +`pdf-graphrag`: PDF → Dekoda → Kipande → Maelezo + Mahusiano → Ulinganisho +`text-graphrag`: Nakshata → Kipande → Maelezo + Mahusiano → Ulinganisho +`pdf-ontology`: PDF → Dekoda → Kipande → Uondoaji wa Ontolojia → Ulinganisho +`text-rows`: Nakshata → Kipande → Uondoaji wa Safu → Hifadhi ya Safu diff --git a/docs/tech-specs/extraction-flows.tr.md b/docs/tech-specs/extraction-flows.tr.md new file mode 100644 index 00000000..b9376f85 --- /dev/null +++ b/docs/tech-specs/extraction-flows.tr.md @@ -0,0 +1,355 @@ +--- +layout: default +title: "Veri Çıkarma Akışları" +parent: "Turkish (Beta)" +--- + +# Veri Çıkarma Akışları + +> **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. + +Bu belge, verilerin TrustGraph veri çıkarma işlem hattı üzerinden nasıl aktığını, belge gönderiminden başlayarak bilgi depolarına kaydedilmesine kadar olan süreci açıklamaktadır. + +## Genel Bakış + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## İçerik Depolama + +### Blob Depolama (S3/Minio) + +Belge içeriği, S3 uyumlu blob depolama alanında saklanır: +Yol formatı: `doc/{object_id}`, burada object_id bir UUID'dir. +Tüm belge türleri burada saklanır: kaynak belgeler, sayfalar, parçalar. + +### Metaveri Depolama (Cassandra) + +Cassandra'da saklanan belge metaverileri şunları içerir: +Belge ID'si, başlık, tür (MIME türü). +Blob depolama alanına `object_id` referansı. +Alt belgelere (sayfalar, parçalar) ait `parent_id`. +`document_type`: "kaynak", "sayfa", "parça", "cevap". + +### İçerik vs. Akış Eşiği + +İçerik iletimi, boyuta dayalı bir strateji kullanır: +**< 2MB**: İçerik, mesaj içinde (base64 ile kodlanmış) yer alır. +**≥ 2MB**: Yalnızca `document_id` gönderilir; işlemci, kütüphaneci API'si aracılığıyla içeriği alır. + +## 1. Aşama: Belge Gönderimi (Kütüphaneci) + +### Giriş Noktası + +Belgeler, kütüphanecinin `add-document` işlemi aracılığıyla sisteme girer: +1. İçerik, blob depolama alanına yüklenir. +2. Cassandra'da bir metaveri kaydı oluşturulur. +3. Belge ID'si döndürülür. + +### Çıkarım Tetikleme + +`add-processing` işlemi, çıkarımı tetikler: +`document_id`, `flow` (işlem hattı ID'si) ve `collection` (hedef depolama alanı) belirtir. +Kütüphanecinin `load_document()` işlemi, içeriği alır ve akış giriş kuyruğuna yayınlar. + +### Şema: Belge + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**Yönlendirme**: `kind` alanına göre: +`application/pdf` → `document-load` kuyruğu → PDF Kod Çözücü +`text/plain` → `text-load` kuyruğu → Parçalayıcı + +## 2. Aşama: PDF Kod Çözücü + +PDF belgelerini metin sayfalarına dönüştürür. + +### İşlem + +1. İçeriği al (doğrudan `data` veya `document_id` üzerinden kütüphaneciden) +2. Sayfaları PyPDF kullanarak çıkar +3. Her sayfa için: + Kütüphanecide alt belge olarak kaydet (`{doc_id}/p{page_num}`) + Kaynak üçlülerini yayınla (sayfa, belgeden türetilmiştir) + Parçalayıcıya ilet + +### Şema: TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## 3. Aşama: Parçalayıcı (Chunker) + +Metni, yapılandırılmış boyutta parçalara ayırır. + +### Parametreler (akışa bağımlı olarak yapılandırılabilir) + +`chunk_size`: Karakter cinsinden hedef parça boyutu (varsayılan: 2000) +`chunk_overlap`: Parçalar arasındaki örtüşme (varsayılan: 100) + +### İşlem + +1. Metin içeriğini alın (doğrudan veya kütüphaneci aracılığıyla) +2. Özyinelemeli karakter ayırıcı kullanarak parçalara ayırın +3. Her parça için: + Kütüphanecide alt belge olarak kaydedin (`{parent_id}/c{index}`) + Kaynak bilgilerini yayınlayın (parça, sayfadan/belgeden türetilmiştir) + Çıkarma işleme modüllerine yönlendirin + +### Şema: Parça (Chunk) + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### Belge Kimlik Hiyerarşisi + +Alt belgeler, kimlik içinde kendi kökenlerini kodlar: +Kaynak: `doc123` +Sayfa: `doc123/p5` +Sayfadan parça: `doc123/p5/c2` +Metinden parça: `doc123/c2` + +## 4. Aşama: Bilgi Çıkarımı + +Kullanılabilir çoklu çıkarma kalıpları, akış yapılandırması tarafından seçilir. + +### Kalıp A: Temel GraphRAG + +İki paralel işlemci: + +**kg-extract-definitions** +Giriş: Parça +Çıkış: Üçlüler (varlık tanımları), Varlık Bağlamları +Çıkarır: varlık etiketleri, tanımlar + +**kg-extract-relationships** +Giriş: Parça +Çıkış: Üçlüler (ilişkiler), Varlık Bağlamları +Çıkarır: özne-yüklem-nesne ilişkileri + +### Kalıp B: Ontoloji Odaklı (kg-extract-ontology) + +Giriş: Parça +Çıkış: Üçlüler, Varlık Bağlamları +Çıkarımı yönlendirmek için yapılandırılmış bir ontoloji kullanır + +### Kalıp C: Ajan Tabanlı (kg-extract-agent) + +Giriş: Parça +Çıkış: Üçlüler, Varlık Bağlamları +Çıkarım için ajan çerçevesini kullanır + +### Kalıp D: Satır Çıkarımı (kg-extract-rows) + +Giriş: Parça +Çıkış: Satırlar (üçlüler değil, yapılandırılmış veri) +Yapılandırılmış kayıtları çıkarmak için şema tanımını kullanır + +### Şema: Üçlüler + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### Şema: Varlık Bağlamları + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### Şema: Satırlar + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## 5. Aşama: Gömme (Embedding) Oluşturma + +### Grafik Gömme (Graph Embeddings) + +Varlık bağlamlarını vektör gömmelerine dönüştürür. + +**Süreç:** +1. Varlık Bağlamlarını Alın +2. Bağlam metniyle gömme hizmetini çağırın +3. GrafikGömme'leri Çıktılayın (varlık → vektör eşlemesi) + +**Şema: GrafikGömme (GraphEmbeddings)** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### Belge Gömme (Document Embeddings) + +Parça metnini doğrudan vektör gömmelerine dönüştürür. + +**Süreç:** +1. Parçayı Al +2. Parça metniyle gömme hizmetini çağır +3. DocumentEmbeddings çıktısını ver + +**Şema: DocumentEmbeddings** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### Satır Gömme (Row Embeddings) + +Satır indeks alanlarını vektör gömmelerine dönüştürür. + +**İşlem:** +1. Satırları Al +2. Yapılandırılmış indeks alanlarını göm +3. Satır vektör deposuna çıktı ver + +## 6. Aşama: Depolama + +### Üçlü Depo (Triple Store) + +Gelen: Üçlüler +Depolama: Cassandra (varlık odaklı tablolar) +İsimlendirilmiş grafikler, temel bilgiyi köken bilgisinden ayırır: + `""` (varsayılan): Temel bilgi gerçekleri + `urn:graph:source`: Çıkarma kökeni + `urn:graph:retrieval`: Sorgu zamanı açıklanabilirliği + +### Vektör Deposu (Grafik Gömme) + +Gelen: GrafikGömme (GraphEmbeddings) +Depolama: Qdrant, Milvus veya Pinecone +Dizin: Varlık IRI'si ile +Metaveri: Köken için chunk_id + +### Vektör Deposu (Belge Gömme) + +Gelen: BelgeGömme (DocumentEmbeddings) +Depolama: Qdrant, Milvus veya Pinecone +Dizin: chunk_id ile + +### Satır Deposu (Row Store) + +Gelen: Satırlar +Depolama: Cassandra +Şema odaklı tablo yapısı + +### Satır Vektör Deposu + +Gelen: Satır gömmeleri +Depolama: Vektör Veritabanı +Dizin: Satır indeks alanları ile + +## Metaveri Alanı Analizi + +### Aktif Olarak Kullanılan Alanlar + +| Alan | Kullanım | +|-------|-------| +| `metadata.id` | Belge/parça tanımlayıcı, günlükleme, köken | +| `metadata.user` | Çoklu kiracılık, depolama yönlendirme | +| `metadata.collection` | Hedef koleksiyon seçimi | +| `document_id` | Kütüphaneci referansı, köken bağlantısı | +| `chunk_id` | İşlem hattı boyunca köken takibi | + +<<<<<<< HEAD +### Potansiyel Olarak Gereksiz Alanlar + +| Alan | Durum | +|-------|--------| +| `metadata.metadata` | Tüm çıkarıcılar tarafından `[]` olarak ayarlanır; belge düzeyindeki metaveri artık gönderim zamanında kütüphaneci tarafından işlenir | +======= +### Kaldırılan Alanlar + +| Alan | Durum | +|-------|--------| +| `metadata.metadata` | `Metadata` sınıfından kaldırıldı. Belge düzeyindeki metaveri üçlüleri artık kütüphaneci tarafından doğrudan üçlü depoya gönderim zamanında gönderilir, çıkarma hattı üzerinden taşınmaz. | +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### Bayt Alanı Modeli + +Tüm içerik alanları (`data`, `text`, `chunk`) `bytes`'tür, ancak tüm işlemciler tarafından hemen UTF-8 dizelerine kod çözülür. İşlemci tarafından ham bayt kullanılmaz. + +## Akış Yapılandırması + +Akışlar harici olarak tanımlanır ve kütüphaneci aracılığıyla yapılandırma hizmetinden sağlanır. Her akış şunları belirtir: + +Giriş kuyrukları (`text-load`, `document-load`) +İşlemci zinciri +Parametreler (parça boyutu, çıkarma yöntemi, vb.) + +Örnek akış modelleri: +`pdf-graphrag`: PDF → Kod Çözücü → Parçalayıcı → Tanımlar + İlişkiler → Gömme +`text-graphrag`: Metin → Parçalayıcı → Tanımlar + İlişkiler → Gömme +`pdf-ontology`: PDF → Kod Çözücü → Parçalayıcı → Ontoloji Çıkarma → Gömme +`text-rows`: Metin → Parçalayıcı → Satır Çıkarma → Satır Deposu diff --git a/docs/tech-specs/extraction-flows.zh-cn.md b/docs/tech-specs/extraction-flows.zh-cn.md new file mode 100644 index 00000000..faa1fdb1 --- /dev/null +++ b/docs/tech-specs/extraction-flows.zh-cn.md @@ -0,0 +1,355 @@ +--- +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 提取流程进行流动,从文档提交到存储在知识库中。 + +## 概述 + +``` +┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌────────────────────┐ +│ Librarian│────▶│ PDF Decoder │────▶│ Chunker │────▶│ Knowledge │ +│ │ │ (PDF only) │ │ │ │ Extraction │ +│ │────────────────────────▶│ │ │ │ +└──────────┘ └─────────────┘ └─────────┘ └────────────────────┘ + │ │ + │ ├──▶ Triples + │ ├──▶ Entity Contexts + │ └──▶ Rows + │ + └──▶ Document Embeddings +``` + +## 内容存储 + +### 对象存储 (S3/Minio) + +文档内容存储在兼容 S3 的对象存储中: +路径格式:`doc/{object_id}`,其中 object_id 是一个 UUID +所有文档类型都存储在此处:源文档、页面、分块 + +### 元数据存储 (Cassandra) + +文档元数据存储在 Cassandra 中,包括: +文档 ID、标题、类型 (MIME 类型) +`object_id` 引用对象存储 +`parent_id` 用于子文档 (页面、分块) +`document_type`: "source", "page", "chunk", "answer" + +### 内联与流式传输阈值 + +内容传输使用基于大小的策略: +**< 2MB**: 内容以内联方式包含在消息中 (base64 编码) +**≥ 2MB**: 仅发送 `document_id`;处理器通过 librarian API 获取 + +## 阶段 1:文档提交 (Librarian) + +### 入口点 + +文档通过 librarian 的 `add-document` 操作进入系统: +1. 内容上传到对象存储 +2. 在 Cassandra 中创建元数据记录 +3. 返回文档 ID + +### 触发提取 + +`add-processing` 操作触发提取: +指定 `document_id`、`flow` (pipeline ID)、`collection` (目标存储) +Librarian 的 `load_document()` 获取内容并发布到 flow 输入队列 + +### 模式:Document + +``` +Document +├── metadata: Metadata +│ ├── id: str # Document identifier +│ ├── user: str # Tenant/user ID +│ ├── collection: str # Target collection +│ └── metadata: list[Triple] # (largely unused, historical) +├── data: bytes # PDF content (base64, if inline) +└── document_id: str # Librarian reference (if streaming) +``` + +**路由 (Routing)**: 基于 `kind` 字段: +`application/pdf` → `document-load` 队列 → PDF 解码器 +`text/plain` → `text-load` 队列 → 分块器 + +## 第二阶段:PDF 解码器 + +将 PDF 文档转换为文本页面。 + +### 流程 + +1. 获取内容(内联 `data` 或通过 `document_id` 从管理员处获取) +2. 使用 PyPDF 提取页面 +3. 对于每个页面: + 另存为管理员中的子文档(`{doc_id}/p{page_num}`) + 发出来源三元组(页面源自文档) + 转发到分块器 + +### 模式:TextDocument + +``` +TextDocument +├── metadata: Metadata +│ ├── id: str # Page URI (e.g., https://trustgraph.ai/doc/xxx/p1) +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── text: bytes # Page text content (if inline) +└── document_id: str # Librarian reference (e.g., "doc123/p1") +``` + +## 第三阶段:分块器 + +将文本分割成配置大小的块。 + +### 参数(可配置) + +`chunk_size`:目标块大小(以字符为单位)(默认:2000) +`chunk_overlap`:块之间的重叠量(默认:100) + +### 流程 + +1. 获取文本内容(内联或通过 librarian) +2. 使用递归字符分割器进行分割 +3. 对于每个块: + 另存为 librarian 中的子文档(`{parent_id}/c{index}`) + 发出来源三元组(块源自页面/文档) + 转发到提取处理器 + +### 模式:Chunk + +``` +Chunk +├── metadata: Metadata +│ ├── id: str # Chunk URI +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] +├── chunk: bytes # Chunk text content +└── document_id: str # Librarian chunk ID (e.g., "doc123/p1/c3") +``` + +### 文档ID层级结构 + +子文档在其ID中编码了其来源信息: +来源:`doc123` +页面:`doc123/p5` +页面中的块:`doc123/p5/c2` +文本中的块:`doc123/c2` + +## 第4阶段:知识提取 + +可用多种提取模式,由流程配置选择。 + +### 模式A:基本GraphRAG + +两个并行处理器: + +**kg-extract-definitions** +输入:块 +输出:三元组(实体定义),实体上下文 +提取内容:实体标签,定义 + +**kg-extract-relationships** +输入:块 +输出:三元组(关系),实体上下文 +提取内容:主语-谓语-宾语关系 + +### 模式B:基于本体论的 (kg-extract-ontology) + +输入:块 +输出:三元组,实体上下文 +使用配置的本体论来指导提取 + +### 模式C:基于代理的 (kg-extract-agent) + +输入:块 +输出:三元组,实体上下文 +使用代理框架进行提取 + +### 模式D:行提取 (kg-extract-rows) + +输入:块 +输出:行(结构化数据,不是三元组) +使用模式定义来提取结构化记录 + +### 模式:三元组 + +``` +Triples +├── metadata: Metadata +│ ├── id: str +│ ├── user: str +│ ├── collection: str +│ └── metadata: list[Triple] # (set to [] by extractors) +└── triples: list[Triple] + └── Triple + ├── s: Term # Subject + ├── p: Term # Predicate + ├── o: Term # Object + └── g: str | None # Named graph +``` + +### Schema: EntityContexts + +``` +EntityContexts +├── metadata: Metadata +└── entities: list[EntityContext] + └── EntityContext + ├── entity: Term # Entity identifier (IRI) + ├── context: str # Textual description for embedding + └── chunk_id: str # Source chunk ID (provenance) +``` + +### Schema: Rows + +``` +Rows +├── metadata: Metadata +├── row_schema: RowSchema +│ ├── name: str +│ ├── description: str +│ └── fields: list[Field] +└── rows: list[dict[str, str]] # Extracted records +``` + +## 第 5 阶段:嵌入式表示生成 + +### 图嵌入 + +将实体上下文转换为向量嵌入。 + +**流程:** +1. 接收 EntityContexts (实体上下文) +2. 使用上下文文本调用嵌入服务 +3. 输出 GraphEmbeddings (实体 → 向量映射) + +**模式:GraphEmbeddings** + +``` +GraphEmbeddings +├── metadata: Metadata +└── entities: list[EntityEmbeddings] + └── EntityEmbeddings + ├── entity: Term # Entity identifier + ├── vector: list[float] # Embedding vector + └── chunk_id: str # Source chunk (provenance) +``` + +### 文档嵌入 + +将文本块直接转换为向量嵌入。 + +**流程:** +1. 接收文本块 +2. 使用文本块调用嵌入服务 +3. 输出文档嵌入 + +**模式:文档嵌入** + +``` +DocumentEmbeddings +├── metadata: Metadata +└── chunks: list[ChunkEmbeddings] + └── ChunkEmbeddings + ├── chunk_id: str # Chunk identifier + └── vector: list[float] # Embedding vector +``` + +### 行嵌入 (Row Embeddings) + +将行索引字段转换为向量嵌入。 + +**流程:** +1. 接收行 (Receive Rows) +2. 嵌入配置的索引字段 (Embed configured index fields) +3. 输出到行向量存储 (Output to row vector store) + +## 第 6 阶段:存储 (Stage 6: Storage) + +### 三元组存储 (Triple Store) + +接收:三元组 (Receives: Triples) +存储:Cassandra (以实体为中心的表) (Storage: Cassandra (entity-centric tables)) +命名图将核心知识与来源信息分开: (Named graphs separate core knowledge from provenance:) + `""` (默认): 核心知识事实 (default): Core knowledge facts + `urn:graph:source`: 提取来源 (Extraction provenance) + `urn:graph:retrieval`: 查询时的可解释性 (Query-time explainability) + +### 向量存储 (图嵌入) (Vector Store (Graph Embeddings)) + +接收:图嵌入 (Receives: GraphEmbeddings) +存储:Qdrant、Milvus 或 Pinecone (Storage: Qdrant, Milvus, or Pinecone) +索引:实体 IRI (Indexed by: entity IRI) +元数据:用于来源信息的 chunk_id (Metadata: chunk_id for provenance) + +### 向量存储 (文档嵌入) (Vector Store (Document Embeddings)) + +接收:文档嵌入 (Receives: DocumentEmbeddings) +存储:Qdrant、Milvus 或 Pinecone (Storage: Qdrant, Milvus, or Pinecone) +索引:chunk_id (Indexed by: chunk_id) + +### 行存储 (Row Store) + +接收:行 (Receives: Rows) +存储:Cassandra (Storage: Cassandra) +基于模式的表结构 (Schema-driven table structure) + +### 行向量存储 (Row Vector Store) + +接收:行嵌入 +存储:向量数据库 +索引依据:行索引字段 + +## 元数据字段分析 + +### 正在使用的字段 + +| 字段 | 用途 | +|-------|-------| +| `metadata.id` | 文档/块标识符,日志记录,来源 | +| `metadata.user` | 多租户,存储路由 | +| `metadata.collection` | 目标集合选择 | +| `document_id` | 馆员引用,来源链接 | +| `chunk_id` | 通过流水线进行来源跟踪 | + +<<<<<<< HEAD +### 潜在的冗余字段 + +| 字段 | 状态 | +|-------|--------| +| `metadata.metadata` | 由所有提取器设置为 `[]`;文档级别的元数据现在由馆员在提交时处理 | +======= +### 已移除的字段 + +| 字段 | 状态 | +|-------|--------| +| `metadata.metadata` | 从 `Metadata` 类中移除。文档级别的元数据三元组现在由馆员直接发送到三元存储,而不是通过提取流水线。 | +>>>>>>> e3bcbf73 (The metadata field (list of triples) in the pipeline Metadata class) + +### 字节字段模式 + +所有内容字段(`data`,`text`,`chunk`)都是 `bytes`,但立即被所有处理器解码为 UTF-8 字符串。没有处理器使用原始字节。 + +## 流配置 + +流在外部定义,并通过配置服务提供给馆员。每个流都指定: + +输入队列(`text-load`,`document-load`) +处理器链 +参数(块大小,提取方法等) + +示例流模式: +`pdf-graphrag`:PDF → 解码器 → 分块器 → 定义 + 关系 → 嵌入 +`text-graphrag`:文本 → 分块器 → 定义 + 关系 → 嵌入 +`pdf-ontology`:PDF → 解码器 → 分块器 → 本体提取 → 嵌入 +`text-rows`:文本 → 分块器 → 行提取 → 行存储 diff --git a/docs/tech-specs/extraction-provenance-subgraph.ar.md b/docs/tech-specs/extraction-provenance-subgraph.ar.md new file mode 100644 index 00000000..46021daa --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.ar.md @@ -0,0 +1,265 @@ +--- +layout: default +title: "أصل الاستخراج: نموذج الرسم البياني الفرعي" +parent: "Arabic (Beta)" +--- + +<<<<<<< HEAD +# أصل الاستخراج: نموذج الرسم البياني الفرعي + +> **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. + +## المشكلة + +حاليًا، يقوم تتبع أصل الاستخراج بإنشاء تجسيد كامل لكل ثلاثية مستخرجة: +معرف فريد `stmt_uri`، و `activity_uri`، وبيانات وصفية PROV-O مرتبطة +لكل حقيقة معرفية. يؤدي معالجة جزء واحد ينتج عنه 20 علاقة إلى إنتاج حوالي 220 ثلاثية لتتبع الأصل بالإضافة إلى +حوالي 20 ثلاثية معرفية - وهو عبء إضافي يقدر بحوالي 10:1. + +======= +# المصدر: نموذج الرسم البياني الفرعي. + +## المشكلة + +في الوقت الحالي، تقوم عملية تتبع مصدر البيانات في وقت الاستخراج بإنشاء تجسيد كامل لكل +ثلاثية مستخرجة: معرف فريد `stmt_uri`، و `activity_uri`، والبيانات الوصفية المرتبطة بـ PROV-O لكل حقيقة معرفية. معالجة جزء واحد +... +والتي تؤدي إلى 20 علاقة، تنتج حوالي 220 ثلاثية بيانات أصلية بالإضافة إلى +حوالي 20 ثلاثية معرفة - وهو عبء إضافي يقدر بحوالي 10:1. +>>>>>>> 82edf2d (New md files from RunPod) + +هذا مكلف للغاية (من حيث التخزين والفهرسة والنقل) وغير دقيق من الناحية الدلالية. +تتم معالجة كل جزء بواسطة استدعاء واحد لنموذج اللغة الكبير (LLM) ينتج +جميع الثلاثيات الخاصة به في معاملة واحدة. +يخفي النموذج الحالي لكل ثلاثية ذلك من خلال خلق وهم بوجود 20 عملية استخراج +مستقلة. + +بالإضافة إلى ذلك، لا توجد أي معلومات عن مصدرين من أصل أربعة معالجات للاستخراج (kg-extract-ontology، +kg-extract-agent)، مما يترك فجوات في مسار التدقيق. + + +## الحل + +<<<<<<< HEAD +استبدال عملية التجسيد لكل ثلاثية بنموذج **رسم بياني فرعي**: سجل واحد للبيانات الوصفية لكل جزء مستخرج، ويتم مشاركته عبر جميع الثلاثيات الناتجة عن هذا الجزء. +======= +استبدل عملية التجسيد لكل ثلاثية بنموذج **رسم بياني فرعي**: سجل واحد للبيانات الوصفية لكل جزء مستخرج، ويتم مشاركته عبر جميع الثلاثيات الناتجة عن هذا الجزء. +>>>>>>> 82edf2d (New md files from RunPod) + + + +### تغيير في المصطلحات + +| القديم | الجديد | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +<<<<<<< HEAD +| `tg:reifies` (1:1، تطابق) | `tg:contains` (1:كثير، احتواء) | +======= +| `tg:reifies` (1:1، تطابق) | `tg:contains` (1:متعدد، احتواء) | +>>>>>>> 82edf2d (New md files from RunPod) + +### الهيكل المستهدف + +يجب أن تضاف جميع الثلاثيات المتعلقة بأصل البيانات إلى الرسم البياني المسمى `urn:graph:source`. + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### مقارنة الحجم + +لكل جزء ينتج عنه N من الثلاثيات المستخرجة: + +| | القديم (لكل ثلاثية) | الجديد (الرسم البياني الفرعي) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| ثلاثيات النشاط | ~9 × N | ~9 | +| ثلاثيات الوكيل | 2 × N | 2 | +| بيانات التعريف/الرسم البياني الفرعي | 2 × N | 2 | +| **إجمالي ثلاثيات التتبع** | **~13N** | **N + 13** | +| **مثال (N=20)** | **~260** | **33** | + +## النطاق + +### المعالجات التي سيتم تحديثها (التتبع الحالي، لكل ثلاثية) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +حاليًا، تستدعي `statement_uri()` + `triple_provenance_triples()` داخل +حلقة التعريف لكل عنصر. + +التغييرات: +نقل إنشاء `subgraph_uri()` و `activity_uri()` قبل الحلقة +جمع ثلاثيات `tg:contains` داخل الحلقة +إخراج كتلة النشاط/الوكيل/الاشتقاق المشتركة مرة واحدة بعد الحلقة + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +نفس النمط مثل التعريفات. نفس التغييرات. + +<<<<<<< HEAD +### المعالجات التي يجب إضافتها للتتبع (مفقودة حاليًا) +======= +### المعالجات التي سيتم إضافة التتبع إليها (مفقودة حاليًا) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +<<<<<<< HEAD +حاليًا، يقوم بإخراج ثلاثيات بدون مصدر. أضف مصدر الرسم البياني الفرعي. +======= +حاليًا، يقوم بإخراج ثلاثيات بدون مصدر. أضف مصدر الرسوم البيانية الفرعية. +>>>>>>> 82edf2d (New md files from RunPod) +باستخدام نفس النمط: رسم بياني فرعي واحد لكل جزء، `tg:contains` لكل +ثلاثية مستخرجة. + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +<<<<<<< HEAD +حاليًا، يقوم بإخراج ثلاثيات بدون مصدر. أضف مصدر الرسم البياني الفرعي +======= +حاليًا، يقوم بإخراج ثلاثيات بدون مصدر. أضف مصدر الرسوم البيانية الفرعية +>>>>>>> 82edf2d (New md files from RunPod) +باستخدام نفس النمط. + +### تغييرات في مكتبة المصادر المشتركة + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +استبدل `triple_provenance_triples()` بـ `subgraph_provenance_triples()` +<<<<<<< HEAD +تقبل الدالة الجديدة قائمة بالثلاثيات المستخرجة بدلاً من ثلاثية واحدة. +تقوم بإنشاء `tg:contains` واحد لكل ثلاثية، كتلة نشاط/وكيل مشتركة. +قم بإزالة `triple_provenance_triples()` القديم. +======= +تقبل الدالة الجديدة قائمة بالثلاثيات المستخرجة بدلاً من ثلاثية واحدة +تقوم بإنشاء `tg:contains` واحد لكل ثلاثية، كتلة نشاط/وكيل مشتركة +قم بإزالة `triple_provenance_triples()` القديم +>>>>>>> 82edf2d (New md files from RunPod) + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +استبدل `statement_uri()` بـ `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +استبدل `TG_REIFIES` بـ `TG_CONTAINS` + +<<<<<<< HEAD +### ليس ضمن النطاق +======= +### خارج النطاق +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-topics**: معالج بنمط قديم، ولا يتم استخدامه حاليًا في + العمليات القياسية. +**kg-extract-rows**: ينتج صفوفًا وليست ثلاثيات، ومن مصدر مختلف. + نموذج. +**تتبع المصدر في وقت الاستعلام** (`urn:graph:retrieval`): مسألة منفصلة، + تستخدم بالفعل نمطًا مختلفًا (سؤال/استكشاف/تركيز/توليف). +**أصل المستند/الصفحة/الجزء** (فك تشفير PDF، تقسيم النص): تستخدم بالفعل. + `derived_entity_triples()` وهو خاص بكل كيان، وليس لكل ثلاثية - لا. + مشكلة التكرار. + +## ملاحظات حول التنفيذ + +### إعادة هيكلة حلقة المعالج + +قبل (لكل ثلاثية، في العلاقات): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +<<<<<<< HEAD +بعد (رسم بياني فرعي): +======= +بعد (الرسم البياني الفرعي): +>>>>>>> 82edf2d (New md files from RunPod) +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### التوقيع المساعد الجديد + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### تغيير جذري + +<<<<<<< HEAD +هذا تغيير جذري في نموذج التتبع. لم يتم +تم إصدارها، لذا لا توجد حاجة إلى ترحيل. الكود القديم `tg:reifies` / +يمكن إزالة كود `statement_uri` تمامًا. +======= +هذا تغيير جذري في نموذج التتبع. لم يتم إصدار التتبع بعد، لذا لا توجد حاجة إلى ترحيل. يمكن إزالة الكود القديم ⟦CODE_0⟧ / ⟦CODE_0⟧ مباشرةً. +been released, so no migration is needed. The old `tg:reifies` / +`statement_uri` code can be removed outright. +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/extraction-provenance-subgraph.es.md b/docs/tech-specs/extraction-provenance-subgraph.es.md new file mode 100644 index 00000000..ff33b27d --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.es.md @@ -0,0 +1,213 @@ +--- +layout: default +title: "Origen de la extracción: Modelo de subgrafo" +parent: "Spanish (Beta)" +--- + +# Origen de la extracción: Modelo de subgrafo + +> **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. + +## Problema + +Actualmente, la generación de la procedencia en tiempo de extracción crea una reificación completa por cada +triple extraído: un `stmt_uri`, `activity_uri` y metadatos PROV-O asociados para cada hecho de conocimiento. El procesamiento de un bloque +que produce 20 relaciones genera aproximadamente 220 triples de procedencia además de los aproximadamente 20 triples de conocimiento, lo que supone una sobrecarga de aproximadamente 10:1. + +Esto es costoso (almacenamiento, indexación, transmisión) y semánticamente +inexacto. Cada bloque se procesa mediante una única llamada a un LLM que produce +todos sus triples en una sola transacción. El modelo actual, que es por triple, +oscurece esto al crear la ilusión de 20 eventos de extracción independientes. + + +Además, dos de los cuatro procesadores de extracción (kg-extract-ontology, +kg-extract-agent) no tienen ninguna procedencia, lo que deja lagunas en el +registro de auditoría. + + +## Solución + + +Reemplazar la reificación por triple con un **modelo de subgrafo**: un único +registro de procedencia por extracción de bloque, compartido entre todos los triples producidos a partir de ese +bloque. + +### Cambio de terminología + +| Antiguo | Nuevo | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +| `tg:reifies` (1:1, identidad) | `tg:contains` (1:muchos, contención) | + +### Estructura objetivo + +Todos los triples de procedencia se almacenan en el grafo con nombre `urn:graph:source`. + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### Comparación de volúmenes + +Para un bloque que produce N triples extraídos: + +| | Viejo (por triple) | Nuevo (subgrafo) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| Triples de actividad | ~9 x N | ~9 | +| Triples de agente | 2 x N | 2 | +| Metadatos de declaración/subgrafo | 2 x N | 2 | +| **Total de triples de procedencia** | **~13N** | **N + 13** | +| **Ejemplo (N=20)** | **~260** | **33** | + +## Alcance + +### Procesadores a Actualizar (procedencia existente, por triple) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +Actualmente llama a `statement_uri()` + `triple_provenance_triples()` dentro +del bucle por definición. + +Cambios: +Mover la creación de `subgraph_uri()` y `activity_uri()` antes del bucle +Recolectar los triples `tg:contains` dentro del bucle +Emitir el bloque compartido de actividad/agente una vez después del bucle + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +Mismo patrón que definiciones. Mismos cambios. + +### Procesadores a Agregar Procedencia (actualmente ausente) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +Actualmente emite triples sin procedencia. Agregar procedencia de subgrafo +utilizando el mismo patrón: un subgrafo por bloque, `tg:contains` para cada +triple extraído. + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +Actualmente emite triples sin procedencia. Agregar procedencia de subgrafo +utilizando el mismo patrón. + +### Cambios en la Biblioteca Compartida de Procedencia + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +Reemplazar `triple_provenance_triples()` con `subgraph_provenance_triples()` +Nueva función acepta una lista de triples extraídos en lugar de uno solo +Genera un `tg:contains` por triple, bloque compartido de actividad/agente +Eliminar el `triple_provenance_triples()` antiguo + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +Reemplazar `statement_uri()` con `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +Reemplazar `TG_REIFIES` con `TG_CONTAINS` + +### No Incluido en el Alcance + +**kg-extract-topics**: procesador de estilo antiguo, no se utiliza actualmente en + flujos estándar +**kg-extract-rows**: produce filas no triples, modelo de procedencia + diferente +**Procedencia en tiempo de consulta** (`urn:graph:retrieval`): preocupación separada, + ya utiliza un patrón diferente (pregunta/exploración/énfasis/síntesis) +**Procedencia de documento/página/bloque** (decodificador de PDF, segmentador): ya utiliza + `derived_entity_triples()` que es por entidad, no por triple — no hay + problema de redundancia + +## Notas de Implementación + +### Reestructuración del Bucle del Procesador + +Antes (por triple, en relaciones): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +Después (subgrafo): +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### Nueva Firma de Asistente + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### Cambio importante + +Este es un cambio importante en el modelo de trazabilidad. La trazabilidad no +se ha publicado, por lo que no se necesita ninguna migración. El código antiguo `tg:reifies` / +`statement_uri` se puede eliminar por completo. diff --git a/docs/tech-specs/extraction-provenance-subgraph.he.md b/docs/tech-specs/extraction-provenance-subgraph.he.md new file mode 100644 index 00000000..4b572821 --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.he.md @@ -0,0 +1,243 @@ +--- +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. + +## בעיה + +מעקב מקורות מידע בזמן החילוץ מייצר כיום מימוש מלא לכל טריפל +<<<<<<< HEAD +שחולץ: `stmt_uri` ייחודי, `activity_uri` ו-מטא-דאטה של PROV-O עבור כל +עובדה ידע בודדת. עיבוד של חלק אחד שמייצר 20 קשרים מייצר כ-220 +טריפלי מעקב מקורות מידע בנוסף ל-כ-20 טריפלי ידע - תקורה של בערך 10:1. +======= +שחולץ: `stmt_uri` ייחודי, `activity_uri` ו-מטא-דאטה של PROV-O הקשורים +לכל עובדה בידע. עיבוד של חלק אחד שמניב 20 קשרים מייצר כ-220 טריפלי +מעקב מקורות מידע בנוסף ל-כ-20 טריפלי ידע - תקורה של בערך 10:1. +>>>>>>> 82edf2d (New md files from RunPod) + + +זה יקר (אחסון, אינדקס, העברה) וגם לא מדויק מבחינה סמנטית. כל חלק +מעובד על ידי קריאה אחת של מודל שפה גדול (LLM) שמייצר את כל +<<<<<<< HEAD +הטריפלים שלו בעסקה אחת. המודל הנוכחי של טריפל בודד מטשטש את זה +על ידי יצירת האשליה של 20 אירועי חילוץ עצמאיים. + + +בנוסף, לשני מתוך ארבעה מעבדי החילוץ (kg-extract-ontology, +======= +הטריפלים שלו בפעולה אחת. המודל הנוכחי, שמבוסס על טריפל בודד, +מטעה בכך שהוא יוצר את האשליה של 20 אירועי חילוץ עצמאיים. + + +בנוסף, לשני מתוך ארבעת מעבדי החילוץ (kg-extract-ontology, +>>>>>>> 82edf2d (New md files from RunPod) +kg-extract-agent) אין מעקב מקורות מידע כלל, מה שמשאיר פערים +במסלול הביקורת. + +## פתרון + +<<<<<<< HEAD +החליפו את הפירוט של כל שלישייה במודל תת-גרף: רשומת מוצא אחת לכל חילוץ, המשותפת לכל השלישיות שנוצרו מחלק זה. +======= +החליפו את הפירוט של כל טריפל במודל תת-גרף: רשומת מוצא אחת לכל חילוץ, המשותפת לכל הטריפלים שנוצרו מחלק זה. +>>>>>>> 82edf2d (New md files from RunPod) + + +### שינוי מונחים + + +| ישן | חדש | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +| `tg:reifies` (1:1, זהות) | `tg:contains` (1:רבים, הכלה) | + +### מבנה מטרה + +<<<<<<< HEAD +כל השלישיות של המוצא נכנסות לגרף המקוּם בשם `urn:graph:source`. +======= +כל הטריפלים של המוצא נכנסים לגרף המקוּם `urn:graph:source`. +>>>>>>> 82edf2d (New md files from RunPod) + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### השוואת נפחים + +עבור קטע המייצר N משולשים חילוצים: + +| | ישן (למשולש) | חדש (תת-גרף) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| משולשי פעילות | ~9 x N | ~9 | +| משולשי סוכנים | 2 x N | 2 | +| מטא-נתונים של הצהרה/תת-גרף | 2 x N | 2 | +| **סה"כ משולשי מקור** | **~13N** | **N + 13** | +| **דוגמה (N=20)** | **~260** | **33** | + +## היקף + +### מעבדים לעדכון (מקור קיים, לכל משולש) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +כיום קורא ל-`statement_uri()` + `triple_provenance_triples()` בתוך +הלולאה לכל הגדרה. + +שינויים: +העברת יצירת `subgraph_uri()` ו-`activity_uri()` לפני הלולאה +איסוף משולשי `tg:contains` בתוך הלולאה +פליטת בלוק פעילות/סוכן/הסקה משותף פעם אחת לאחר הלולאה + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +דפוס זהה כמו הגדרות. שינויים זהים. + +### מעבדים להוספת מקור (חסרים כרגע) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +כיום פולט משולשים ללא מקור. הוספת מקור תת-גרף +באמצעות הדפוס הזהה: תת-גרף אחד לכל קטע, `tg:contains` עבור כל +משולש חילוץ. + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +כיום פולט משולשים ללא מקור. הוספת מקור תת-גרף +באמצעות הדפוס הזהה. + +### שינויים בספריית המקור המשותפת + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +החלפת `triple_provenance_triples()` עם `subgraph_provenance_triples()` +פונקציה חדשה מקבלת רשימה של משולשים חילוצים במקום משולש בודד +מייצרת `tg:contains` אחד לכל משולש, בלוק פעילות/סוכן משותף +הסרת `triple_provenance_triples()` הישן + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +החלפת `statement_uri()` עם `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +החלפת `TG_REIFIES` עם `TG_CONTAINS` + +### לא בתחום + +**kg-extract-topics**: מעבד מסוג ישן, לא בשימוש כרגע ב + זרימות סטנדרטיות +**kg-extract-rows**: מייצר שורות ולא משולשים, מודל מקור + שונה +**מקור בזמן שאילתה** (`urn:graph:retrieval`): נושא נפרד, + כבר משתמש בדפוס שונה (שאילתה/חקירה/מיקוד/סינתזה) +<<<<<<< HEAD +**מקור של מסמך/עמוד/קטע** (מקודד PDF, מפצל): כבר משתמש +======= +**מקור של מסמך/עמוד/קטע** (מקודד PDF, חותך): כבר משתמש +>>>>>>> 82edf2d (New md files from RunPod) + ב-`derived_entity_triples()` שהוא לכל ישות, ולא לכל משולש — אין + בעיית יתירות + +## הערות יישום + +### שינוי מבנה הלולאה של המעבד + +לפני (לכל משולש, ביחסים): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +אחרי (תת-גרף): +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +<<<<<<< HEAD +### חתימה חדשה של עוזר +======= +### חתימה חדשה עבור עוזר +>>>>>>> 82edf2d (New md files from RunPod) + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### שינוי משמעותי + +זוהי שינוי משמעותי במודל המקור. המקור טרם פורסם, ולכן אין צורך בביצוע שדרוג. ניתן להסיר את קוד ⟦CODE_0⟧ / +`tg:reifies` הישן לחלוטין. +קוד `statement_uri` ניתן להסרה לחלוטין. diff --git a/docs/tech-specs/extraction-provenance-subgraph.hi.md b/docs/tech-specs/extraction-provenance-subgraph.hi.md new file mode 100644 index 00000000..e165d9cd --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.hi.md @@ -0,0 +1,260 @@ +--- +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. + +## समस्या + +निष्कर्षण के समय का वर्तमान स्रोत जानकारी एक पूर्ण पुन: निरूपण प्रति उत्पन्न करता है +निष्कर्षित त्रिगुट: प्रत्येक ज्ञान तथ्य के लिए एक अद्वितीय `stmt_uri`, `activity_uri`, और संबंधित +<<<<<<< HEAD +PROV-O मेटाडेटा। एक ऐसे खंड को संसाधित करना जो 20 संबंधों का उत्पादन करता है, उसमें लगभग 220 स्रोत जानकारी त्रिगुट होते हैं, इसके अतिरिक्त +======= +PROV-O मेटाडेटा। एक ऐसे खंड को संसाधित करना जो 20 संबंध उत्पन्न करता है, उसमें लगभग 220 स्रोत जानकारी त्रिगुट होते हैं, इसके अतिरिक्त +>>>>>>> 82edf2d (New md files from RunPod) +लगभग 20 ज्ञान त्रिगुट - लगभग 10:1 का ओवरहेड। + + +यह महंगा है (भंडारण, अनुक्रमण, प्रसारण) और अर्थपूर्ण रूप से +गलत है। प्रत्येक खंड को एक एकल LLM कॉल द्वारा संसाधित किया जाता है जो सभी त्रिगुटों को एक लेनदेन में उत्पन्न करता है। +वर्तमान प्रति-त्रिगुट मॉडल 20 स्वतंत्र निष्कर्षण +घटनाओं का भ्रम पैदा करके इसे अस्पष्ट करता है। + + +इसके अतिरिक्त, चार निष्कर्षण प्रोसेसरों में से दो (kg-extract-ontology, +kg-extract-agent) में कोई स्रोत जानकारी नहीं है, जिससे ऑडिट +में अंतराल पैदा होते हैं। + +## समाधान + +प्रति-त्रिगुट पुन: निरूपण को एक **सबग्राफ मॉडल** से बदलें: एक स्रोत जानकारी +रिकॉर्ड प्रति खंड निष्कर्षण, उस खंड से उत्पन्न सभी त्रिगुटों में साझा किया जाता है। + + +### शब्दावली परिवर्तन + +| पुराना | नया | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +| `tg:reifies` (1:1, पहचान) | `tg:contains` (1:कई, समावेशन) | + +### लक्षित संरचना + +सभी स्रोत जानकारी त्रिगुट `urn:graph:source` नामित ग्राफ में जाते हैं। + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### मात्रा की तुलना + +<<<<<<< HEAD +एक ऐसे खंड के लिए जो N निकाले गए त्रिगुण उत्पन्न करता है: +======= +एक ऐसे खंड के लिए जो N निकाले गए त्रिगुण (ट्रिपल्स) उत्पन्न करता है: +>>>>>>> 82edf2d (New md files from RunPod) + +| | पुराना (प्रति-त्रिगुण) | नया (उप-ग्राफ) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| गतिविधि त्रिगुण | ~9 x N | ~9 | +| एजेंट त्रिगुण | 2 x N | 2 | +| कथन/उप-ग्राफ मेटाडेटा | 2 x N | 2 | +| **कुल प्रामाणिकता त्रिगुण** | **~13N** | **N + 13** | +| **उदाहरण (N=20)** | **~260** | **33** | + +## दायरा + +### अपडेट करने के लिए प्रोसेसर (मौजूदा प्रामाणिकता, प्रति-त्रिगुण) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +वर्तमान में, यह `statement_uri()` + `triple_provenance_triples()` को परिभाषा के प्रत्येक लूप के अंदर कॉल करता है। + + +परिवर्तन: +लूप से पहले `subgraph_uri()` और `activity_uri()` का निर्माण करें। +लूप के अंदर `tg:contains` त्रिकों को एकत्र करें। +लूप के बाद एक बार साझा गतिविधि/एजेंट/व्युत्पत्ति ब्लॉक उत्सर्जित करें। + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +परिभाषाओं के समान पैटर्न। समान परिवर्तन। + +### उत्पत्ति जोड़ने के लिए प्रोसेसर (वर्तमान में गायब) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +<<<<<<< HEAD +वर्तमान में, यह बिना किसी स्रोत जानकारी के त्रिक उत्पन्न करता है। उपग्राफ स्रोत जानकारी जोड़ें। +उसी पैटर्न का उपयोग करके: प्रत्येक खंड के लिए एक उपग्राफ, प्रत्येक के लिए `tg:contains`। +निकाले गए त्रिगुट। +======= +वर्तमान में, यह बिना किसी स्रोत जानकारी के त्रिक (triples) उत्पन्न करता है। उप-ग्राफ (subgraph) की स्रोत जानकारी जोड़ें। +उसी पैटर्न का उपयोग करके: प्रत्येक खंड (chunk) के लिए एक उप-ग्राफ, प्रत्येक निकाले गए त्रिक के लिए `tg:contains`। + +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +<<<<<<< HEAD +वर्तमान में, यह बिना किसी स्रोत जानकारी के त्रिक (triples) उत्पन्न करता है। समान पैटर्न का उपयोग करके सबग्राफ (subgraph) स्रोत जानकारी जोड़ें। + + +### साझा उत्पत्ति लाइब्रेरी में परिवर्तन + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +`triple_provenance_triples()` को `subgraph_provenance_triples()` से बदलें +नया फ़ंक्शन एक एकल के बजाय निकाले गए त्रिपुलों की सूची को स्वीकार करता है +प्रत्येक ट्रिपल के लिए एक `tg:contains` उत्पन्न करता है, साझा गतिविधि/एजेंट ब्लॉक +पुराने `triple_provenance_triples()` को हटा दें +======= +वर्तमान में, यह बिना किसी स्रोत जानकारी के त्रिक (triples) उत्पन्न करता है। उप-ग्राफ (subgraph) की स्रोत जानकारी उसी पैटर्न का उपयोग करके जोड़ें। + + +### साझा स्रोत पुस्तकालय (Shared Provenance Library) में परिवर्तन + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +`triple_provenance_triples()` को `subgraph_provenance_triples()` से बदलें। +नया फ़ंक्शन एक एकल त्रिक के बजाय निकाले गए त्रिकों की एक सूची स्वीकार करता है। +प्रत्येक त्रिक के लिए एक `tg:contains` उत्पन्न करता है, जो साझा गतिविधि/एजेंट ब्लॉक है। +पुराने `triple_provenance_triples()` को हटा दें। +>>>>>>> 82edf2d (New md files from RunPod) + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +`statement_uri()` को `subgraph_uri()` से बदलें। + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +`TG_REIFIES` को `TG_CONTAINS` से बदलें। + +### दायरे में नहीं + +<<<<<<< HEAD +**kg-extract-topics**: पुराना-शैली का प्रोसेसर, वर्तमान में उपयोग में नहीं है। + मानक प्रक्रियाओं में। +**kg-extract-rows**: पंक्तियाँ उत्पन्न करता है, ट्रिपल नहीं, अलग उत्पत्ति मॉडल। + मॉडल। +**क्वेरी-टाइम प्रोवेनेंस** (`urn:graph:retrieval`): एक अलग चिंता का विषय, + पहले से ही एक अलग पैटर्न का उपयोग करता है (प्रश्न/अन्वेषण/फोकस/संश्लेषण)। +======= +**kg-extract-topics**: पुराना शैली का प्रोसेसर, वर्तमान में उपयोग में नहीं है। + मानक प्रक्रियाओं में। +**kg-extract-rows**: पंक्तियाँ उत्पन्न करता है, ट्रिपल नहीं, अलग उत्पत्ति मॉडल। + मॉडल। +**क्वेरी-टाइम प्रोवेनेंस** (`urn:graph:retrieval`): एक अलग विषय, + पहले से ही एक अलग पैटर्न का उपयोग करता है (प्रश्न/अन्वेषण/ध्यान/संश्लेषण)। +>>>>>>> 82edf2d (New md files from RunPod) +**दस्तावेज़/पृष्ठ/खंड प्रोवेनेंस** (पीडीएफ डिकोडर, चंकर): पहले से ही उपयोग करता है + `derived_entity_triples()` जो प्रति-एंटिटी है, प्रति-ट्रिपल नहीं - कोई + अनावश्यकता समस्या नहीं। + +## कार्यान्वयन संबंधी टिप्पणियाँ + +### प्रोसेसर लूप का पुनर्गठन + +पहले (प्रत्येक त्रिक के लिए, संबंधों में): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +<<<<<<< HEAD +(उपग्राफ के बाद): +======= +(उप-ग्राफ के बाद): +>>>>>>> 82edf2d (New md files from RunPod) +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### नया सहायक हस्ताक्षर + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### महत्वपूर्ण परिवर्तन + +<<<<<<< HEAD +यह उत्पत्ति मॉडल में एक महत्वपूर्ण बदलाव है। उत्पत्ति (प्रोवेनेंस) का +जारी किया गया है, इसलिए माइग्रेशन की आवश्यकता नहीं है। पुराना `tg:reifies` / +`statement_uri` कोड पूरी तरह से हटाया जा सकता है। +======= +यह प्रामाणिकता मॉडल में एक महत्वपूर्ण बदलाव है। प्रामाणिकता अभी तक जारी नहीं की गई है, इसलिए किसी माइग्रेशन की आवश्यकता नहीं है। पुराना ⟦CODE_0⟧ / ⟦CODE_0⟧ कोड पूरी तरह से हटाया जा सकता है। +यह प्रामाणिकता मॉडल में एक महत्वपूर्ण बदलाव है। प्रामाणिकता अभी तक जारी नहीं की गई है, इसलिए किसी माइग्रेशन की आवश्यकता नहीं है। पुराना `tg:reifies` / `tg:reifies` कोड पूरी तरह से हटाया जा सकता है। +यह प्रामाणिकता मॉडल में एक महत्वपूर्ण बदलाव है। प्रामाणिकता अभी तक जारी नहीं की गई है, इसलिए किसी माइग्रेशन की आवश्यकता नहीं है। पुराना `statement_uri` / `statement_uri` कोड पूरी तरह से हटाया जा सकता है। +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/extraction-provenance-subgraph.md b/docs/tech-specs/extraction-provenance-subgraph.md index 27a3775b..62d3a701 100644 --- a/docs/tech-specs/extraction-provenance-subgraph.md +++ b/docs/tech-specs/extraction-provenance-subgraph.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Extraction Provenance: Subgraph Model" +parent: "Tech Specs" +--- + # Extraction Provenance: Subgraph Model ## Problem diff --git a/docs/tech-specs/extraction-provenance-subgraph.pt.md b/docs/tech-specs/extraction-provenance-subgraph.pt.md new file mode 100644 index 00000000..e3a5276a --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.pt.md @@ -0,0 +1,247 @@ +--- +layout: default +title: "Proveniência de Extração: Modelo de Subgrafo" +parent: "Portuguese (Beta)" +--- + +# Proveniência de Extração: Modelo de Subgrafo + +> **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. + +## Problema + +A proveniência em tempo de extração atualmente gera uma reificação completa para cada +<<<<<<< HEAD +tripla extraída: um `stmt_uri`, `activity_uri` e metadados PROV-O associados para cada +fato de conhecimento. O processamento de um bloco que gera 20 relacionamentos produz aproximadamente 220 triplas de proveniência, além de +aproximadamente 20 triplas de conhecimento — uma sobrecarga de aproximadamente 10:1. + + +Isso é caro (armazenamento, indexação, transmissão) e semanticamente +impreciso. Cada bloco é processado por uma única chamada de LLM que produz +todas as suas triplas em uma única transação. O modelo atual, baseado em tripla, +======= +tripla extraída: um `stmt_uri`, `activity_uri` e metadados PROV-O associados para +cada fato de conhecimento. O processamento de um bloco que gera 20 relacionamentos produz +aproximadamente 220 triplas de proveniência, além das aproximadamente 20 triplas de +conhecimento — uma sobrecarga de aproximadamente 10:1. + +Isso é caro (armazenamento, indexação, transmissão) e semanticamente +impreciso. Cada bloco é processado por uma única chamada de LLM que produz +todas as suas triplas em uma única transação. O modelo atual, por tripla, +>>>>>>> 82edf2d (New md files from RunPod) +obscure isso, criando a ilusão de 20 eventos de extração independentes. + + +Além disso, dois dos quatro processadores de extração (kg-extract-ontology, +<<<<<<< HEAD +kg-extract-agent) não possuem proveniência, deixando lacunas no registro de auditoria. + + +## Solução + +Substituir a reificação por tripla por um **modelo de subgrafo**: um registro de proveniência +por extração de bloco, compartilhado entre todas as triplas produzidas a partir desse +bloco. +======= +kg-extract-agent) não possuem proveniência, deixando lacunas no registro de +auditoria. + +## Solução + +Substituir a reificação por tripla por um **modelo de subgrafo**: um registro de +proveniência por extração de bloco, compartilhado entre todas as triplas produzidas +a partir desse bloco. +>>>>>>> 82edf2d (New md files from RunPod) + +### Mudança de Terminologia + +| Antigo | Novo | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +| `tg:reifies` (1:1, identidade) | `tg:contains` (1:muitos, contenção) | + +### Estrutura Alvo + +Todas as triplas de proveniência devem ser inseridas no grafo nomeado `urn:graph:source`. + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### Comparação de Volume + +Para um conjunto de dados que produz N triplas extraídas: + +| | Antigo (por tripla) | Novo (subgrafo) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| Triplas de atividade | ~9 x N | ~9 | +| Triplas de agente | 2 x N | 2 | +| Metadados de declaração/subgrafo | 2 x N | 2 | +| **Total de triplas de rastreabilidade** | **~13N** | **N + 13** | +| **Exemplo (N=20)** | **~260** | **33** | + +## Escopo + +### Processadores a serem Atualizados (rastreabilidade existente, por tripla) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +Atualmente, chama `statement_uri()` + `triple_provenance_triples()` dentro +do loop por definição. + +Alterações: +Mover a criação de `subgraph_uri()` e `activity_uri()` antes do loop +Coletar triplas `tg:contains` dentro do loop +Emitir bloco compartilhado de atividade/agente/derivação uma vez após o loop + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +Mesmo padrão que definições. As mesmas alterações. + +### Processadores a serem Adicionados para Rastreabilidade (atualmente ausente) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +Atualmente, emite triplas sem rastreabilidade. Adicionar rastreabilidade de subgrafo +usando o mesmo padrão: um subgrafo por conjunto de dados, `tg:contains` para cada +tripla extraída. + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +Atualmente, emite triplas sem rastreabilidade. Adicionar rastreabilidade de subgrafo +usando o mesmo padrão. + +### Alterações na Biblioteca Compartilhada de Rastreabilidade + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +Substituir `triple_provenance_triples()` por `subgraph_provenance_triples()` +Nova função aceita uma lista de triplas extraídas em vez de uma única +Gera um `tg:contains` por tripla, bloco compartilhado de atividade/agente +Remover `triple_provenance_triples()` antigo + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +Substituir `statement_uri()` por `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +Substituir `TG_REIFIES` por `TG_CONTAINS` + +<<<<<<< HEAD +### Não no Escopo +======= +### Não está no Escopo +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-topics**: processador de estilo antigo, não usado atualmente em + fluxos padrão +**kg-extract-rows**: produz linhas, não triplas, modelo de rastreabilidade + diferente +**Rastreabilidade em tempo de consulta** (`urn:graph:retrieval`): questão separada, + já usa um padrão diferente (pergunta/exploração/foco/síntese) +**Rastreabilidade de documento/página/conjunto de dados** (decodificador PDF, divisor): já usa + `derived_entity_triples()` que é por entidade, não por tripla — não há + problema de redundância + +## Notas de Implementação + +### Reestruturação do Loop do Processador + +Antes (por tripla, em relacionamentos): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +Após (subgrafo): +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +<<<<<<< HEAD +### Nova Assinatura de Auxílio +======= +### Nova Assinatura de Ajuda +>>>>>>> 82edf2d (New md files from RunPod) + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### Mudança Significativa + +<<<<<<< HEAD +Esta é uma mudança significativa no modelo de rastreabilidade. A rastreabilidade não +======= +Esta é uma mudança significativa no modelo de rastreabilidade. A rastreabilidade ainda não +>>>>>>> 82edf2d (New md files from RunPod) +foi lançada, portanto, nenhuma migração é necessária. O código antigo `tg:reifies` / +`statement_uri` pode ser removido completamente. diff --git a/docs/tech-specs/extraction-provenance-subgraph.ru.md b/docs/tech-specs/extraction-provenance-subgraph.ru.md new file mode 100644 index 00000000..a766ca9a --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.ru.md @@ -0,0 +1,268 @@ +--- +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. + +## Проблема + +<<<<<<< HEAD +В настоящее время механизм отслеживания происхождения, работающий во время извлечения, создает полную реификацию для каждого +извлеченного тройства: уникальный `stmt_uri`, `activity_uri` и связанные +метаданные PROV-O для каждого отдельного факта знаний. Обработка одного блока +данных, который дает 20 отношений, приводит к появлению примерно 220 тройств отслеживания происхождения в дополнение к +примерно 20 тройствам знаний — это примерно 10:1 избыточности. + +Это дорого (хранение, индексация, передача) и семантически +неточно. Каждый блок обрабатывается одним вызовом LLM, который создает +все свои тройства за одну транзакцию. Текущая модель, основанная на тройствах, +искажает это, создавая иллюзию 20 независимых событий извлечения. + + +Кроме того, два из четырех процессоров извлечения (kg-extract-ontology, +kg-extract-agent) вообще не имеют информации об отслеживании происхождения, что оставляет пробелы в журнале аудита. + + +## Решение + +Заменить реификацию на уровне тройств на **модель подграфа**: одна запись отслеживания происхождения для каждого блока извлечения, +используемая для всех тройств, созданных из этого блока. + +======= +В настоящее время механизм отслеживания происхождения, действующий во время извлечения, создает полную реификацию для каждого +извлеченного тройного набора: уникальный `stmt_uri`, `activity_uri` и связанные +метаданные PROV-O для каждого отдельного факта знаний. Обработка одного блока, +который дает 20 отношений, приводит к появлению примерно 220 тройных наборов отслеживания происхождения, помимо +примерно 20 тройных наборов знаний — это примерно 10:1 избыточности. + +Это дорого (хранение, индексация, передача) и семантически +неточно. Каждый блок обрабатывается одним вызовом LLM, который создает +все свои тройные наборы за одну транзакцию. Текущая модель для каждого тройного набора +создает иллюзию 20 независимых событий извлечения. + + +Кроме того, два из четырех процессоров извлечения (kg-extract-ontology, +kg-extract-agent) вообще не имеют информации об отслеживании происхождения, что создает пробелы в +журнале аудита. + +## Решение + +Заменить реификацию для каждого тройного набора на **модель подграфа**: один +набор отслеживания происхождения для каждого извлеченного блока, который используется +для всех тройных наборов, созданных из этого блока. +>>>>>>> 82edf2d (New md files from RunPod) + +### Изменение терминологии + +| Старое | Новое | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +| `tg:reifies` (1:1, идентичность) | `tg:contains` (1:много, содержательность) | + +### Целевая структура + +<<<<<<< HEAD +Все тройства отслеживания происхождения должны быть помещены в именованный граф `urn:graph:source`. +======= +Все тройные наборы отслеживания происхождения должны быть помещены в именованный граф `urn:graph:source`. +>>>>>>> 82edf2d (New md files from RunPod) + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### Сравнение объемов + +Для блока, генерирующего N извлеченных троек: + +| | Старый (на тройку) | Новый (подграф) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| Тройки активности | ~9 x N | ~9 | +| Тройки агентов | 2 x N | 2 | +| Метаданные утверждения/подграфа | 2 x N | 2 | +<<<<<<< HEAD +| **Всего троек происхождения** | **~13N** | **N + 13** | +======= +| **Общее количество троек происхождения** | **~13N** | **N + 13** | +>>>>>>> 82edf2d (New md files from RunPod) +| **Пример (N=20)** | **~260** | **33** | + +## Область применения + +<<<<<<< HEAD +### Модули для обновления (существующее происхождение, на тройку) +======= +### Процессоры для обновления (существующее происхождение, на тройку) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +В настоящее время вызывает `statement_uri()` + `triple_provenance_triples()` внутри +цикла для каждой сущности. + +Изменения: +Переместить создание `subgraph_uri()` и `activity_uri()` перед циклом +Собирать тройки `tg:contains` внутри цикла +Выводить общий блок активности/агента/происхождения один раз после цикла + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +Та же схема, что и для сущностей. Те же изменения. + +<<<<<<< HEAD +### Модули для добавления информации о происхождении (в настоящее время отсутствуют) +======= +### Процессоры для добавления происхождения (в настоящее время отсутствуют) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +<<<<<<< HEAD +В настоящее время генерируются тройки без указания источника. Добавить информацию об источнике подграфа, +используя ту же схему: один подграф для каждого фрагмента, `tg:contains` для каждой +извлеченной тройки. +======= +В настоящее время генерируются тройки данных без указания источника. Добавить информацию об источнике подграфа, +используя ту же схему: один подграф для каждого блока, `tg:contains` для каждой +извлеченной тройки данных. +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +<<<<<<< HEAD +В настоящее время генерируются тройки без указания источника. Добавить информацию об источнике подграфа, +======= +В настоящее время генерируются тройки данных без указания источника. Добавить информацию об источнике подграфа, +>>>>>>> 82edf2d (New md files from RunPod) +используя ту же схему. + +### Изменения в общей библиотеке отслеживания происхождения данных + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +Заменить `triple_provenance_triples()` на `subgraph_provenance_triples()` +<<<<<<< HEAD +Новая функция принимает список извлеченных троек вместо одной +Генерирует один `tg:contains` для каждой тройки, общий блок активности/агента +======= +Новая функция принимает список извлеченных троек данных вместо одной +Генерирует один `tg:contains` для каждой тройки данных, общий блок активности/агента +>>>>>>> 82edf2d (New md files from RunPod) +Удалить старый `triple_provenance_triples()` + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +Заменить `statement_uri()` на `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +Заменить `TG_REIFIES` на `TG_CONTAINS` + +### Не входит в область действия + +**kg-extract-topics**: устаревший процессор, в настоящее время не используется в + стандартных процессах. +**kg-extract-rows**: генерирует строки, а не тройки, имеет другую модель + происхождения. +**Происхождение во время запроса** (`urn:graph:retrieval`): отдельная задача, + уже использует другую схему (вопрос/исследование/фокус/синтез). +**Происхождение документа/страницы/фрагмента** (декодер PDF, разбиение на фрагменты): уже использует + `derived_entity_triples()`, который применяется к каждой сущности, а не к каждой тройке — нет + проблемы избыточности. + +## Замечания по реализации + +### Реструктуризация цикла процессора + +До (для каждой тройки, в отношениях): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +После (подграфа): +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### Новая вспомогательная подпись + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### Существенное изменение + +Это существенное изменение модели отслеживания происхождения. Отслеживание происхождения еще не было выпущено, поэтому миграция не требуется. Старый код ⟦CODE_0⟧ / +`tg:reifies` можно удалить безвозвратно. +Код `statement_uri` можно удалить полностью. diff --git a/docs/tech-specs/extraction-provenance-subgraph.sw.md b/docs/tech-specs/extraction-provenance-subgraph.sw.md new file mode 100644 index 00000000..6bdc4cc9 --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.sw.md @@ -0,0 +1,258 @@ +--- +layout: default +title: "Asili ya Utoaji: Mfumo wa Subgraph" +parent: "Swahili (Beta)" +--- + +# Asili ya Utoaji: Mfumo wa Subgraph + +> **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. + +## Tatizo + +<<<<<<< HEAD +Hivi sasa, utoaji wa wakati wa uondoaji huunda uelekezaji kamili kwa kila +triple iliyoundwa: `stmt_uri`, `activity_uri`, na metadata inayohusiana +ya PROV-O kwa kila ukweli wa maarifa. Kushughulikia sehemu moja +ambayo hutoa uhusiano wa 20 hutoa triples ~220 za utoaji pamoja na +triples ~20 za maarifa - mzigo wa takriban 10:1. + +Hii ni ghali (uhifadhi, uwekaji wa indexi, usambazaji) na pia si sahihi +kimaana. Kila sehemu hushughulikiwa na simu moja ya LLM ambayo hutoa +triples zake zote katika mshono mmoja. Mfumo wa sasa wa kila triple +huficha hili kwa kuunda udanganyifu wa matukio 20 ya uondoaji +huru. + +Zaidi ya hayo, vichakavu viwili vya nne vya uondoaji (kg-extract-ontology, +kg-extract-agent) havina utoaji wowote, na hivyo kuacha pengo katika +======= +Hivi sasa, utoaji wa taarifa wakati wa utoaji huunda uelekezaji kamili kwa kila +triple iliyotoa: `stmt_uri`, `activity_uri`, na metadata inayohusiana +ya PROV-O kwa kila ukweli wa maarifa. Kushughulikia sehemu moja +ambayo hutoa uhusiano wa 20 hutoa triples ~220 za taarifa juu ya +triples ~20 za maarifa - mzigo wa takriban 10:1. + +Hii ni ghali (uhifadhi, urekebishaji, usambazaji) na pia si sahihi kimaana. +Kila sehemu hushughulikiwa na simu moja ya LLM ambayo hutoa triples zake zote +katika mshughuliko mmoja. Mfumo wa sasa wa kila triple huficha hili kwa +kuunda udanganyifu wa matukio 20 ya kujitenga ya utoaji. + + +Zaidi ya hayo, vichakavu viwili vya utoaji vifo (kg-extract-ontology, +kg-extract-agent) havina taarifa zozote, na hivyo kuacha pengo katika +>>>>>>> 82edf2d (New md files from RunPod) +njia ya ukaguzi. + +## Suluhisho + +Badilisha uelekezaji wa kila triple na **mfumo wa subgraph**: rekodi moja +<<<<<<< HEAD +ya utoaji kwa kila uondoaji wa sehemu, inayoshirikiwa na triples zote +======= +ya taarifa kwa kila utoaji wa sehemu, inayoshirikiwa na triples zote +>>>>>>> 82edf2d (New md files from RunPod) +zilizozalishwa kutoka sehemu hiyo. + +### Mabadiliko ya Dhana + +| Zamani | Mpya | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +<<<<<<< HEAD +| `tg:reifies` (1:1, utambulisho) | `tg:contains` (1:wengi, uwezeshaji) | + +### Muundo Unaolengwa + +Triples zote za utoaji huwekwa katika grafu iliyoitwa `urn:graph:source`. +======= +| `tg:reifies` (1:1, utambulisho) | `tg:contains` (1:wengi, kuingia) | + +### Muundo Unaolengwa + +Triples zote za taarifa huwekwa katika grafu iliyoitwa `urn:graph:source`. +>>>>>>> 82edf2d (New md files from RunPod) + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### Kulinganisha Kiasi + +Kwa kila sehemu inayozalisha triples tatu zilizochukuliwa: + +| | Zamani (kwa kila triple) | Mpya (subgraph) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| Triples za shughuli | ~9 x N | ~9 | +| Triples za wakala | 2 x N | 2 | +| Metadata ya taarifa/subgraph | 2 x N | 2 | +| **Triples tatu za jumla za asili** | **~13N** | **N + 13** | +| **Mfano (N=20)** | **~260** | **33** | + +## Upeo + +### Wasindikaji ambao Watasasishwa (asili iliyopo, kwa kila triple) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +Hivi sasa huita `statement_uri()` + `triple_provenance_triples()` ndani +ya loop ya kila ufafanuzi. + +Mabadiliko: +Hamisha `subgraph_uri()` na `activity_uri()` kabla ya loop +Kusanya triples za `tg:contains` ndani ya loop +Toa kundi la shughuli/wakala/uzalishaji mara moja baada ya loop + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +Mfano sawa na ufafanuzi. Mabadiliko sawa. + +<<<<<<< HEAD +### Wasindikaji ambao Watasasishwa ili Kuongeza Asili (sasa hayapo) +======= +### Wasindikaji ambao Wataongezwa Asili (sasa hayapo) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +Hivi sasa hutoa triples bila asili. Ongeza asili ya subgraph +kwa kutumia mfano sawa: subgraph moja kwa kila sehemu, `tg:contains` kwa kila +triple iliyochukuliwa. + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +Hivi sasa hutoa triples bila asili. Ongeza asili ya subgraph +kwa kutumia mfano sawa. + +<<<<<<< HEAD +### Mabadiliko ya Maktaba ya Asili iliyoshirikiwa +======= +### Mabadiliko ya Maktaba ya Asili Iliyoshirikiwa +>>>>>>> 82edf2d (New md files from RunPod) + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +Badilisha `triple_provenance_triples()` na `subgraph_provenance_triples()` +Kazi mpya inakubali orodha ya triples zilizochukuliwa badala ya moja +Inazalisha `tg:contains` moja kwa kila triple, kundi la shughuli/wakala lililoshirikiwa +Ondoa `triple_provenance_triples()` ya zamani + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +Badilisha `statement_uri()` na `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +Badilisha `TG_REIFIES` na `TG_CONTAINS` + +<<<<<<< HEAD +### Hayajajumuishwa katika Upeo +======= +### Hayako Katika Upeo +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-topics**: wasindikaji wa mtindo wa zamani, hawatumiki kwa sasa katika + mtiririko wa kawaida +**kg-extract-rows**: hutoa mistari si triples, mfumo tofauti wa + asili +**Asili ya wakati wa swali** (`urn:graph:retrieval`): suala tofauti, + tayari hutumia mfumo tofauti (swali/uchunguzi/lengo/muhtasari) +**Asili ya hati/ukurasa/sehemu** (dekoda ya PDF, kichunguzi): tayari hutumia + `derived_entity_triples()` ambayo ni kwa kila kitu, si kwa kila triple — hakuna + suala la ziada + +## Maelezo ya Utendaji + +### Upangaji Upya wa Loop ya Msindikaji + +Kabla (kwa kila triple, katika uhusiano): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +Baada ya (mfumo mdogo): +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### Saini Mpya ya Msaidizi + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### Mabadiliko Makubwa + +<<<<<<< HEAD +Hii ni mabadiliko makubwa kwa mfumo wa asili ya data. Asili ya data haijatolewa, kwa hivyo hakuna uhamishaji unaohitajika. Msimbo wa zamani wa ⟦CODE_0⟧ / +======= +Hii ni mabadiliko makubwa kwa mfumo wa uhakikisho. Uhakikisho haujatolewa, kwa hivyo hakuna uhamishaji unaohitajika. Msimbo wa zamani wa ⟦CODE_0⟧ / +>>>>>>> 82edf2d (New md files from RunPod) +`tg:reifies` unaweza kuondolewa kabisa. +Msimbo `statement_uri` unaweza kufutwa kabisa. diff --git a/docs/tech-specs/extraction-provenance-subgraph.tr.md b/docs/tech-specs/extraction-provenance-subgraph.tr.md new file mode 100644 index 00000000..c98be537 --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.tr.md @@ -0,0 +1,275 @@ +--- +layout: default +title: "Çıkarma Kaynağı: Alt Grafik Modeli" +parent: "Turkish (Beta)" +--- + +# Çıkarma Kaynağı: Alt Grafik Modeli + +> **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. + +## Sorun + +Çıkarma zamanı köken bilgisi şu anda her +çıkarılan üçlü için tam bir somutlaştırma oluşturur: benzersiz bir `stmt_uri`, `activity_uri` ve ilgili +PROV-O meta verileri, her bir bilgi parçası için. Bir parça işlenirken +<<<<<<< HEAD +ve bu parça 20 ilişki üretiyorsa, yaklaşık 220 köken bilgisi üçlüsü, bunun üzerine +yaklaşık 20 bilgi üçlüsü bulunur; bu da yaklaşık 10:1'lik bir ek yük demektir. + +Bu hem pahalıdır (depolama, indeksleme, iletim) hem de anlamsal olarak +yanlıştır. Her bir parça, tek bir LLM çağrısı ile işlenir ve bu çağrı, +tüm üçlemelerini tek bir işlemde üretir. Mevcut üçleme bazlı model, +20 bağımsız çıkarma olayının yanılsamasını yaratarak bunu gizler. +======= +ve bu parça 20 ilişki üretiyorsa, yaklaşık 220 köken bilgisi üçlüsü, +yaklaşık 20 bilgi üçlüsünün üzerine eklenir; bu da yaklaşık 10:1'lik bir ek yük demektir. + +Bu hem pahalıdır (depolama, indeksleme, iletim) hem de anlamsal olarak +yanlıştır. Her bir parça, tek bir LLM çağrısı ile işlenir ve bu çağrı, +tüm üçlülerini tek bir işlemde üretir. Mevcut üçlü bazlı model, +bu durumu 20 bağımsız çıkarma olayının yanılsamasını yaratarak gizler. +>>>>>>> 82edf2d (New md files from RunPod) + + +Ayrıca, dört çıkarma işlemcisinden ikisi (kg-extract-ontology, +kg-extract-agent), hiçbir kaynak bilgisini içermemektedir, bu da denetim +izinde boşluklara neden olmaktadır. + +## Çözüm + +<<<<<<< HEAD +Her üçlü için yapılan somutlaştırmayı, **bir alt grafik modeli** ile değiştirin: her bir parça çıkarımı için bir köken kaydı, bu parçadan üretilen tüm üçlüler arasında paylaşılan. + +======= +Her üçlü için yapılan somutlaştırmayı, **alt grafik modeli** ile değiştirin: bir veri kaynağı +kaydı, o parçadan üretilen tüm üçlüler için ortak kullanılan bir parça çıkarımı için. +>>>>>>> 82edf2d (New md files from RunPod) + + +### Terminoloji Değişikliği + +| Eski | Yeni | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +<<<<<<< HEAD +| `tg:reifies` (1:1, eşlik) | `tg:contains` (1:çok, içerik) | + +### Hedef Yapı + +Tüm köken bilgisi üçlüleri, `urn:graph:source` adlı grafikte yer alır. +======= +| `tg:reifies` (1:1, özdeşlik) | `tg:contains` (1:çok, içerik) | + +### Hedef Yapı + +Tüm veri kaynağı üçlüleri, `urn:graph:source` adlı grafiğe yerleştirilir. +>>>>>>> 82edf2d (New md files from RunPod) + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### Hacim Karşılaştırması + +N sayıda çıkarılan üçlü üreten bir parça için: + +| | Eski (üçlü başına) | Yeni (alt grafik) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| Aktivite üçlüleri | ~9 x N | ~9 | +| Ajan üçlüleri | 2 x N | 2 | +| İfade/alt grafik meta verileri | 2 x N | 2 | +<<<<<<< HEAD +| **Toplam kaynak üçlüleri** | **~13N** | **N + 13** | +======= +| **Toplam köken üçlüleri** | **~13N** | **N + 13** | +>>>>>>> 82edf2d (New md files from RunPod) +| **Örnek (N=20)** | **~260** | **33** | + +## Kapsam + +<<<<<<< HEAD +### Güncellenecek İşlemciler (mevcut kaynak, üçlü başına) +======= +### Güncellenecek İşlemciler (mevcut köken, üçlü başına) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +Şu anda her bir tanım döngüsü içinde `statement_uri()` + `triple_provenance_triples()`'i çağırıyor. + + +Değişiklikler: +`subgraph_uri()` ve `activity_uri()` oluşturmayı döngüden önce taşıyın +`tg:contains` üçlülerini döngü içinde toplayın +Paylaşılan aktivite/ajan/türetme bloğunu döngüden sonra bir kez yayınlayın + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +Tanımlarla aynı desen. Aynı değişiklikler. + +<<<<<<< HEAD +### Kaynak Eklenmesi Gereken İşlemciler (şu anda eksik) +======= +### Köken Eklenmesi Gereken İşlemciler (şu anda eksik) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +<<<<<<< HEAD +Şu anda, herhangi bir kaynak bilgisi olmadan üçlüler oluşturuluyor. Alt grafik kaynak bilgisini ekleyin. +======= +Şu anda, herhangi bir köken bilgisi olmadan üçlüler oluşturuluyor. Alt grafik köken bilgisini ekleyin. +>>>>>>> 82edf2d (New md files from RunPod) +Aynı kalıbı kullanarak: her parça için bir alt grafik, her çıkarılan üçlü için `tg:contains`. + + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +<<<<<<< HEAD +Şu anda, herhangi bir kaynak bilgisi olmadan üçlüler oluşturuluyor. Alt grafik kaynak bilgisini aynı kalıbı kullanarak ekleyin. + + +### Paylaşılan Kaynak Bilgisi Kütüphanesi Değişiklikleri +======= +Şu anda, herhangi bir köken bilgisi olmadan üçlüler oluşturuluyor. Alt grafik köken bilgisini aynı kalıbı kullanarak ekleyin. + + +### Paylaşılan Köken Bilgisi Kütüphanesi Değişiklikleri +>>>>>>> 82edf2d (New md files from RunPod) + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +`triple_provenance_triples()`'ı `subgraph_provenance_triples()` ile değiştirin. +Yeni fonksiyon, tek bir üçlü yerine çıkarılan üçlülerin bir listesini kabul ediyor. +<<<<<<< HEAD +Her üçlü için bir `tg:contains` oluşturuyor, paylaşılan etkinlik/ajan bloğu. +======= +Her üçlü için bir `tg:contains` oluşturuyor, paylaşılan aktivite/ajan bloğu. +>>>>>>> 82edf2d (New md files from RunPod) +Eski `triple_provenance_triples()`'ı kaldırın. + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +`statement_uri()`'ı `subgraph_uri()` ile değiştirin. + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +`TG_REIFIES`'ı `TG_CONTAINS` ile değiştirin. + +<<<<<<< HEAD +### Kapsam Dışında +======= +### Kapsam Dışı +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-topics**: eski tip işlemci, şu anda standart akışlarda kullanılmıyor. + **kg-extract-rows**: satırlar üretiyor, üçlüler değil, farklı bir köken modeline sahip. +**Çalışma zamanı köken bilgisi** (⟦CODE_0⟧): ayrı bir konu. + model +<<<<<<< HEAD +**Çalışma zamanı veri kaynağı bilgisi** (`urn:graph:retrieval`): ayrı bir konu, + zaten farklı bir kalıp kullanıyor (soru/keşif/odaklanma/sentez). +**Belge/sayfa/parça kaynağı** (PDF çözücü, parçalayıcı): zaten kullanılıyor. + `derived_entity_triples()` ki bu, her bir varlık için, her bir üçlü için değil; yani bir sorun yok. + gereksiz veri sorunu yok. +======= +**Çalışma zamanı köken bilgisi** (`urn:graph:retrieval`): ayrı bir konu, + zaten farklı bir kalıp kullanıyor (soru/keşif/odaklanma/sentez). +**Belge/sayfa/parça kaynağı** (PDF çözücü, parçalayıcı): zaten kullanılıyor. + `derived_entity_triples()` ki bu, her bir varlık için, her bir üçlü için değil; yani hayır. + tekrar sorun yok. +>>>>>>> 82edf2d (New md files from RunPod) + +## Uygulama Notları + +### İşlemci Döngüsü Yeniden Yapılandırması + +Önce (her üçlü için, ilişkilerde): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +(Alt grafik): +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### Yeni Yardımcı İmza + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### Önemli Değişiklik + +Bu, köken modeli için önemli bir değişikliktir. Köken henüz yayınlanmadığı için, herhangi bir geçiş işlemine gerek yoktur. Eski ⟦CODE_0⟧ / +`tg:reifies` kodu tamamen kaldırılabilir. +`statement_uri` kodu tamamen kaldırılabilir. diff --git a/docs/tech-specs/extraction-provenance-subgraph.zh-cn.md b/docs/tech-specs/extraction-provenance-subgraph.zh-cn.md new file mode 100644 index 00000000..80d56a98 --- /dev/null +++ b/docs/tech-specs/extraction-provenance-subgraph.zh-cn.md @@ -0,0 +1,267 @@ +--- +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. + +## 问题 + +<<<<<<< HEAD +提取时 provenance 目前为每个提取的三元组生成完整的重构:一个唯一的 ⟦CODE_0⟧、⟦CODE_1⟧,以及与每个知识事实相关的 PROV-O 元数据。处理一个块 +提取时 provenance 目前为每个提取的三元组生成完整的重构:一个唯一的 `stmt_uri`、`activity_uri`,以及与每个知识事实相关的 PROV-O 元数据。处理一个块 +提取时 provenance 目前为每个提取的三元组生成完整的重构:一个唯一的 ⟦CODE_0⟧、⟦CODE_1⟧,以及与每个知识事实相关的 PROV-O 元数据。处理一个块 +这会产生 20 个关系,并在其基础上产生约 220 个溯源三元组,而知识三元组约为 20 个,这导致了大约 10:1 的开销。 + + +这既成本高昂(存储、索引、传输),又在语义上 +不准确。每个片段都由单个 LLM 调用处理,该调用在一个事务中生成 +所有其三元组。当前的每个三元组模型 +通过制造 20 个独立提取 +事件的假象来掩盖这一点。 +======= +提取时段的溯源信息目前会生成完整的实体化表示。 +提取的三元组:一个唯一的 `stmt_uri`,`activity_uri`,以及与之相关的 +PROV-O 元数据,用于每个知识事实。处理一个块 +这会产生 20 个关系,并在其基础上产生约 220 个溯源三元组,而知识三元组约为 20 个,这导致了大约 10:1 的开销。 + + +这既昂贵(存储、索引、传输),又在语义上 +不准确。每个片段都由单个 LLM 调用处理,该调用在一个事务中生成 +所有三元组。当前的每个三元组模型 +通过产生 20 个独立提取 +事件的幻觉来掩盖这一点。 +>>>>>>> 82edf2d (New md files from RunPod) + +此外,四个提取处理器中的两个(kg-extract-ontology、 +kg-extract-agent)完全没有来源信息,这在审计 +跟踪中留下了空白。 + +## 解决方案 + +<<<<<<< HEAD +将每个三元组的显式化替换为**子图模型**:每个数据块提取一个溯源记录,该记录在从该数据块生成的所有三元组中共享。 +======= +用 **子图模型** 替换三元组级别的显式化:每个数据块提取一个溯源记录,该记录与从该数据块生成的所有三元组共享。 +>>>>>>> 82edf2d (New md files from RunPod) + + + +### 术语变更 + +| 旧术语 | 新术语 | +|-----|-----| +| `stmt_uri` (`https://trustgraph.ai/stmt/{uuid}`) | `subgraph_uri` (`https://trustgraph.ai/subgraph/{uuid}`) | +| `statement_uri()` | `subgraph_uri()` | +<<<<<<< HEAD +| `tg:reifies` (1:1, 相同) | `tg:contains` (1:多, 包含) | + +### 目标结构 + +所有溯源三元组都放入名为 `urn:graph:source` 的命名图中。 +======= +| `tg:reifies` (1:1, 身份) | `tg:contains` (1:多, 包含) | + +### 目标结构 + +所有溯源三元组都存储在名为 `urn:graph:source` 的图中。 +>>>>>>> 82edf2d (New md files from RunPod) + +``` +# Subgraph contains each extracted triple (RDF-star quoted triples) + tg:contains <> . + tg:contains <> . + tg:contains <> . + +# Derivation from source chunk + prov:wasDerivedFrom . + prov:wasGeneratedBy . + +# Activity: one per chunk extraction + rdf:type prov:Activity . + rdfs:label "{component_name} extraction" . + prov:used . + prov:wasAssociatedWith . + prov:startedAtTime "2026-03-13T10:00:00Z" . + tg:componentVersion "0.25.0" . + tg:llmModel "gpt-4" . # if available + tg:ontology . # if available + +# Agent: stable per component + rdf:type prov:Agent . + rdfs:label "{component_name}" . +``` + +### 比较数据量 + +对于一个产生 N 个提取三元组的模块: + +| | 旧方式(每个三元组) | 新方式(子图) | +|---|---|---| +| `tg:contains` / `tg:reifies` | N | N | +| 活动三元组 | ~9 x N | ~9 | +| 代理三元组 | 2 x N | 2 | +| 语句/子图元数据 | 2 x N | 2 | +| **总的溯源三元组** | **~13N** | **N + 13** | +| **示例(N=20)** | **~260** | **33** | + +## 范围 + +### 需要更新的处理器(现有溯源,每个三元组) + +**kg-extract-definitions** +(`trustgraph-flow/trustgraph/extract/kg/definitions/extract.py`) + +<<<<<<< HEAD +目前,它在每个定义的循环内部调用 `statement_uri()` + `triple_provenance_triples()`。 +======= +当前,它在每个定义的循环内部调用 `statement_uri()` + `triple_provenance_triples()`。 +>>>>>>> 82edf2d (New md files from RunPod) + + +更改: +将 `subgraph_uri()` 和 `activity_uri()` 的创建移到循环之前。 +在循环内部收集 `tg:contains` 三元组。 +循环结束后,一次性输出共享的活动/主体/推导块。 + +**kg-extract-relationships** +(`trustgraph-flow/trustgraph/extract/kg/relationships/extract.py`) + +模式与定义相同。 更改也相同。 + +<<<<<<< HEAD +### 需要添加的处理器,用于添加来源信息(目前缺失) +======= +### 需要添加的处理器,用于添加来源信息(当前缺失) +>>>>>>> 82edf2d (New md files from RunPod) + +**kg-extract-ontology** +(`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py`) + +<<<<<<< HEAD +目前会生成不带来源信息的三元组。添加子图来源信息。 +======= +目前会输出不带来源信息的三元组。添加子图来源信息。 +>>>>>>> 82edf2d (New md files from RunPod) +使用相同的模式:每个块一个子图,对于每个提取的三元组使用 `tg:contains`。 + + +**kg-extract-agent** +(`trustgraph-flow/trustgraph/extract/kg/agent/extract.py`) + +<<<<<<< HEAD +目前会生成不带来源信息的三元组。添加子图来源信息。 +======= +目前会输出不带来源信息的三元组。添加子图来源信息。 +>>>>>>> 82edf2d (New md files from RunPod) +使用相同的模式。 + +### 共享来源库的更改 + +**`trustgraph-base/trustgraph/provenance/triples.py`** + +将 `triple_provenance_triples()` 替换为 `subgraph_provenance_triples()` +<<<<<<< HEAD +新函数接受一个提取的三元组列表,而不是单个三元组。 +======= +新函数接受提取的三元组列表,而不是单个三元组。 +>>>>>>> 82edf2d (New md files from RunPod) +为每个三元组生成一个 `tg:contains`,共享活动/代理块。 +移除旧的 `triple_provenance_triples()` + +**`trustgraph-base/trustgraph/provenance/uris.py`** + +将 `statement_uri()` 替换为 `subgraph_uri()` + +**`trustgraph-base/trustgraph/provenance/namespaces.py`** + +将 `TG_REIFIES` 替换为 `TG_CONTAINS` + +### 不在范围之内 + +**kg-extract-topics**: 较旧的处理器,目前未在标准流程中使用。 + **kg-extract-rows**: 生成的是行,而不是三元组,具有不同的数据来源模型。 +**查询时的数据来源** (⟦CODE_0⟧): 独立的关注点。 + 模型 +<<<<<<< HEAD +**查询时的数据来源信息** (`urn:graph:retrieval`):独立的关注点, + 已经使用了不同的模式(提问/探索/聚焦/综合)。 +**文档/页面/块的来源**(PDF解码器,分块器):已经使用了。 + `derived_entity_triples()`,这对于每个实体而言,而不是每个三元组而言,因此没有 + 重复的问题。 +======= +**查询时的数据来源信息** (`urn:graph:retrieval`): 独立的关注点, + 已经使用了不同的模式(问题/探索/重点/综合)。 +**文档/页面/块的来源**(PDF解码器,分块器):已经使用了。 + `derived_entity_triples()`,这对于每个实体而言,而不是每个三元组而言——没有。 + 重复问题。 +>>>>>>> 82edf2d (New md files from RunPod) + +## 实现说明 + +### 处理器循环重构 + +之前(每个三元组,在关系中): +```python +for rel in rels: + # ... build relationship_triple ... + stmt_uri = statement_uri() + prov_triples = triple_provenance_triples( + stmt_uri=stmt_uri, + extracted_triple=relationship_triple, + ... + ) + triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +在 (子图) 之后: +```python +sg_uri = subgraph_uri() + +for rel in rels: + # ... build relationship_triple ... + extracted_triples.append(relationship_triple) + +prov_triples = subgraph_provenance_triples( + subgraph_uri=sg_uri, + extracted_triples=extracted_triples, + chunk_uri=chunk_uri, + component_name=default_ident, + component_version=COMPONENT_VERSION, + llm_model=llm_model, + ontology_uri=ontology_uri, +) +triples.extend(set_graph(prov_triples, GRAPH_SOURCE)) +``` + +### 新的辅助签名 + +```python +def subgraph_provenance_triples( + subgraph_uri: str, + extracted_triples: List[Triple], + chunk_uri: str, + component_name: str, + component_version: str, + llm_model: Optional[str] = None, + ontology_uri: Optional[str] = None, + timestamp: Optional[str] = None, +) -> List[Triple]: + """ + Build provenance triples for a subgraph of extracted knowledge. + + Creates: + - tg:contains link for each extracted triple (RDF-star quoted) + - One prov:wasDerivedFrom link to source chunk + - One activity with agent metadata + """ +``` + +### 破坏性变更 + +这是一个对溯源模型的重大更改。 +溯源功能尚未发布,因此无需迁移。旧的 `tg:reifies` / `tg:reifies` 代码可以直接删除。 +`statement_uri` 代码可以直接删除。 diff --git a/docs/tech-specs/extraction-time-provenance.ar.md b/docs/tech-specs/extraction-time-provenance.ar.md new file mode 100644 index 00000000..1856e3ac --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.ar.md @@ -0,0 +1,886 @@ +--- +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. + +## نظرة عامة + +يوثق هذا المستند ملاحظات حول أصل البيانات في وقت الاستخراج لأعمال المواصفات المستقبلية. يسجل أصل البيانات في وقت الاستخراج "الطبقة المصدر" - من أين أتت البيانات في الأصل، وكيف تم استخراجها وتحويلها. + +هذا يختلف عن أصل البيانات في وقت الاستعلام (انظر `query-time-provenance.md`) الذي يسجل استنتاجات الوكيل. + +## بيان المشكلة + +### التنفيذ الحالي + +يعمل أصل البيانات حاليًا على النحو التالي: +<<<<<<< HEAD +يتم تخزين بيانات وصف المستند كـ RDF triples في الرسم البياني المعرفي. +======= +يتم تخزين بيانات وصف المستند كـ "ثلاثيات" RDF في الرسم البياني للمعرفة. +>>>>>>> 82edf2d (New md files from RunPod) +يربط معرف المستند البيانات الوصفية بالمستند، بحيث يظهر المستند كعقدة في الرسم البياني. +عند استخراج الحواف (العلاقات/الحقائق) من المستندات، تربط علاقة `subjectOf` الحافة المستخرجة بالمستند المصدر. + +### المشاكل في النهج الحالي + +<<<<<<< HEAD +1. **تحميل البيانات الوصفية المتكرر:** يتم تجميع بيانات وصف المستند وتحميلها بشكل متكرر مع كل مجموعة من الـ triples المستخرجة من هذا المستند. هذا مضيعة ويزيد من التكرار - نفس البيانات الوصفية تنتقل كحمولة مع كل مخرج استخراج. +======= +1. **تحميل البيانات الوصفية المتكرر:** يتم تجميع بيانات وصف المستند وتحميلها بشكل متكرر مع كل مجموعة من "الثلاثيات" المستخرجة من هذا المستند. هذا مضيعة ويزيد من التكرار - حيث تنتقل نفس البيانات الوصفية كحمولة مع كل مخرج استخراج. +>>>>>>> 82edf2d (New md files from RunPod) + +2. **أصل بيانات سطحي:** تربط العلاقة `subjectOf` الحالية الحقائق مباشرة بالمستند ذي المستوى الأعلى فقط. لا توجد رؤية لسلسلة التحويل - أي الصفحة التي جاءت منها الحقيقة، أو الجزء، أو طريقة الاستخراج المستخدمة. + +### الحالة المرغوبة + +<<<<<<< HEAD +1. **تحميل البيانات الوصفية مرة واحدة:** يجب تحميل بيانات وصف المستند مرة واحدة وإرفاقها بعقدة المستند ذات المستوى الأعلى، وليس تكرارها مع كل مجموعة من الـ triples. +======= +1. **تحميل البيانات الوصفية مرة واحدة:** يجب تحميل بيانات وصف المستند مرة واحدة وإرفاقها بعقدة المستند ذات المستوى الأعلى، وليس تكرارها مع كل مجموعة من "الثلاثيات". +>>>>>>> 82edf2d (New md files from RunPod) + +2. **رسم بياني كامل لأصل البيانات:** التقاط سلسلة التحويل الكاملة من المستند المصدر عبر جميع القطع الأثرية الوسيطة وصولاً إلى الحقائق المستخرجة. على سبيل المثال، تحويل مستند PDF: + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +<<<<<<< HEAD +3. **التخزين الموحد:** يتم تخزين الرسم البياني للأصل (provenance DAG) في نفس الرسم البياني للمعرفة كما يتم تخزين المعرفة المستخرجة. يتيح ذلك الاستعلام عن الأصل بنفس الطريقة التي يتم بها الاستعلام عن المعرفة - من خلال تتبع الحواف صعودًا في السلسلة من أي حقيقة إلى موقع مصدرها الدقيق. + +4. **معرفات مستقرة:** لكل قطعة أثرية وسيطة (صفحة، جزء) معرف مستقر كعقدة في الرسم البياني. + +5. **الربط بين الأب والطفل:** يتم ربط المستندات المشتقة بآبائها وصولاً إلى المستند المصدر الرئيسي باستخدام أنواع علاقات متسقة. + +6. **تخصيص الحقائق بدقة:** تشير العلاقة `subjectOf` في الحواف المستخرجة إلى الأصل الفوري (الجزء)، وليس المستند الرئيسي. يتم استعادة الأصل الكامل من خلال التنقل عبر الرسم البياني للأصل. +======= +3. **التخزين الموحد:** يتم تخزين الرسم البياني للأصل (provenance DAG) في نفس الرسم البياني للمعرفة مثل المعرفة المستخرجة. يتيح ذلك الاستعلام عن الأصل بنفس الطريقة التي يتم بها الاستعلام عن المعرفة - من خلال تتبع الحواف صعودًا في السلسلة من أي حقيقة إلى موقع مصدرها الدقيق. + +4. **معرفات مستقرة:** لكل قطعة أثرية وسيطة (صفحة، جزء) معرف مستقر كعقدة في الرسم البياني. + +5. **الربط بين الأبناء والآباء:** يتم ربط المستندات المشتقة بآبائها وصولاً إلى المستند المصدر الرئيسي باستخدام أنواع علاقات متسقة. + +6. **تخصيص الحقائق بدقة:** تشير العلاقة `subjectOf` في الحواف المستخرجة إلى الأصل الفوري (الجزء)، وليس المستند الرئيسي. يتم استعادة الأصل الكامل من خلال اجتياز الرسم البياني للأصل. +>>>>>>> 82edf2d (New md files from RunPod) + +## حالات الاستخدام + +### UC1: تحديد مصدر المعلومات في استجابات GraphRAG + +**السيناريو:** يقوم المستخدم بتشغيل استعلام GraphRAG ويتلقى استجابة من الوكيل. + +**التدفق:** +1. يرسل المستخدم استعلامًا إلى وكيل GraphRAG. +2. يسترجع الوكيل الحقائق ذات الصلة من الرسم البياني للمعرفة لصياغة استجابة. +3. وفقًا لمواصفات الأصل في وقت الاستعلام، يقوم الوكيل بالإبلاغ عن الحقائق التي ساهمت في الاستجابة. +<<<<<<< HEAD +4. يربط كل حقيقة بمصدره (الجزء) عبر الرسم البياني للأصل. +5. ترتبط الأجزاء بالصفحات، وترتبط الصفحات بمستندات المصدر. + +**النتيجة في تجربة المستخدم:** يعرض الواجهة استجابة نموذج اللغة الكبير (LLM) جنبًا إلى جنب مع تحديد مصدر المعلومات. يمكن للمستخدم: +رؤية الحقائق التي دعمت الاستجابة. +النزول من الحقائق إلى الأجزاء إلى الصفحات إلى المستندات. +مراجعة المستندات المصدر الأصلية للتحقق من صحة الادعاءات. +فهم بالضبط من أين في المستند (في أي صفحة، في أي قسم) نشأت الحقيقة. + +**القيمة:** يمكن للمستخدمين التحقق من صحة الاستجابات التي تم إنشاؤها بواسطة الذكاء الاصطناعي مقابل المصادر الأولية، مما يعزز الثقة ويمكن المستخدمين من التحقق من الحقائق. +======= +4. ترتبط كل حقيقة بمصدرها من خلال الرسم البياني للأصل. +5. ترتبط الأجزاء بالصفحات، وترتبط الصفحات بمستندات المصدر. + +**النتيجة في تجربة المستخدم:** يعرض الواجهة استجابة نموذج اللغة (LLM) جنبًا إلى جنب مع تحديد مصدر المعلومات. يمكن للمستخدم: +رؤية الحقائق التي دعمت الاستجابة. +الانتقال من الحقائق إلى الأجزاء إلى الصفحات إلى المستندات. +مراجعة المستندات المصدر الأصلية للتحقق من الادعاءات. +فهم بالضبط من أين في المستند (في أي صفحة، في أي قسم) نشأت الحقيقة. + +**القيمة:** يمكن للمستخدمين التحقق من الاستجابات التي تم إنشاؤها بواسطة الذكاء الاصطناعي مقابل المصادر الأولية، مما يعزز الثقة ويمكن المستخدمين من التحقق من الحقائق. +>>>>>>> 82edf2d (New md files from RunPod) + +### UC2: تصحيح جودة الاستخراج + +تبدو حقيقة خاطئة. تتبعها من خلال الجزء إلى الصفحة إلى المستند لمعرفة النص الأصلي. هل كان استخراجًا سيئًا، أم أن المصدر نفسه كان خاطئًا؟ + +### UC3: إعادة استخراج تدريجي + +يتم تحديث مستند المصدر. ما هي الأجزاء/الحقائق التي تم اشتقاقها منه؟ قم بإبطالها وإعادة إنشائها فقط لتلك الأجزاء، بدلاً من إعادة معالجة كل شيء. + +### UC4: حذف البيانات / الحق في النسيان + +<<<<<<< HEAD +يجب إزالة مستند المصدر (بسبب اللائحة العامة لحماية البيانات، أو لأسباب قانونية، إلخ). تتبع الرسم البياني للأصل للعثور على جميع الحقائق المشتقة وإزالتها. + +### UC5: حل النزاعات + +تتناقض حقائق مع بعضها البعض. تتبع كلتا الحالتين إلى مصادرها لفهم السبب واتخاذ قرار بشأن أي منهما يجب الوثوق به (المصدر الأكثر موثوقية، أو الأحدث، إلخ). + +### UC6: وزن سلطة المصدر + +بعض المصادر أكثر موثوقية من غيرها. يمكن ترجيح الحقائق أو تصفيتها بناءً على سلطة/جودة مستندات الأصل. + +### UC7: مقارنة مسار الاستخراج +======= +يجب إزالة مستند المصدر (بسبب GDPR، أو لأسباب قانونية، وما إلى ذلك). ابحث في الرسم البياني للأصل وأزل جميع الحقائق المشتقة. + +### UC5: حل النزاعات + +تتناقض حقيقتان مع بعضهما البعض. تتبع كلتاهما إلى مصادرهما لفهم السبب واتخاذ قرار بشأن أي منهما يجب الوثوق به (المصدر الأكثر موثوقية، أو الأحدث، وما إلى ذلك). + +### UC6: وزن سلطة المصدر + +بعض المصادر أكثر موثوقية من غيرها. يمكن وزن الحقائق أو تصفيتها بناءً على سلطة/جودة مستندات الأصل. + +### UC7: مقارنة مسارات الاستخراج +>>>>>>> 82edf2d (New md files from RunPod) + +قارن المخرجات من طرق/إصدارات استخراج مختلفة. أي أداة استخراج أنتجت حقائق أفضل من نفس المصدر؟ + +## نقاط التكامل + +### أمين المكتبة + +يوفر مكون أمين المكتبة بالفعل تخزين المستندات بمعرفات مستندات فريدة. يتكامل نظام التتبع مع هذه البنية التحتية الحالية. + +#### القدرات الحالية (تم تنفيذها بالفعل) + +<<<<<<< HEAD +**ربط المستندات من الأب إلى الابن:** +`parent_id` الحقل في `DocumentMetadata` - يربط المستند الابن بالمستند الأب +`document_type` الحقل - القيم: `"source"` (أصلي) أو `"extracted"` (مشتق) +واجهة برمجة تطبيقات `add-child-document` - لإنشاء مستند ابن بمعرف `document_type = "extracted"` تلقائيًا +واجهة برمجة تطبيقات `list-children` - لاسترداد جميع المستندات الابناء لمستند أب معين +الحذف المتتالي - يؤدي إزالة مستند الأب تلقائيًا إلى حذف جميع مستندات الأبناء + +**تحديد المستند:** +معرفات المستندات محددة من قبل العميل (وليس تم إنشاؤها تلقائيًا) +المستندات مفهرسة باستخدام `(user, document_id)` المركب في Cassandra +يتم إنشاء معرفات الكائنات (UUIDs) داخليًا لتخزين الكائنات الثنائية + +**دعم البيانات الوصفية:** +`metadata: list[Triple]` الحقل - ثلاثيات RDF للبيانات الوصفية المنظمة +`title`، `comments`، `tags` - بيانات وصفية أساسية للمستند +`time` - الطابع الزمني، `kind` - نوع MIME + +**هيكل التخزين:** +يتم تخزين البيانات الوصفية في Cassandra (مساحة مفاتيح `librarian`، جدول `document`) +يتم تخزين المحتوى في تخزين الكائنات الثنائية MinIO/S3 (دلو `library`) +تسليم محتوى ذكي: يتم تضمين المستندات الأقل من 2 ميجابايت، ويتم بث المستندات الأكبر حجمًا + +#### الملفات الرئيسية + +`trustgraph-flow/trustgraph/librarian/librarian.py` - العمليات الأساسية لأمين المكتبة +`trustgraph-flow/trustgraph/librarian/service.py` - معالج الخدمة، تحميل المستند +`trustgraph-flow/trustgraph/tables/library.py` - تخزين جدول Cassandra +`trustgraph-base/trustgraph/schema/services/library.py` - تعريفات المخططات +======= +**ربط المستندات من النوع "الأب-الابن":** +الحقل `parent_id` في `DocumentMetadata` - يربط المستند الابن بالمستند الأب. +الحقل `document_type` - القيم: `"source"` (أصلي) أو `"extracted"` (مشتق). +واجهة برمجة تطبيقات `add-child-document` - لإنشاء مستند ابن مع `document_type = "extracted"` تلقائيًا. +واجهة برمجة تطبيقات `list-children` - لاسترداد جميع المستندات الابناء لمستند أب معين. +الحذف المتتالي - يؤدي إزالة مستند الأب تلقائيًا إلى حذف جميع مستندات الأبناء. + +**تحديد المستند:** +معرفات المستندات محددة من قبل العميل (وليس تم إنشاؤها تلقائيًا). +المستندات مفهرسة بواسطة مفتاح مركب `(user, document_id)` في Cassandra. +يتم إنشاء معرفات الكائنات (UUIDs) داخليًا لتخزين الكائنات الثنائية. + +**دعم البيانات الوصفية:** +الحقل `metadata: list[Triple]` - ثلاثيات RDF للبيانات الوصفية المنظمة. +`title`، `comments`، `tags` - بيانات وصفية أساسية للمستند. +`time` - الطابع الزمني، `kind` - نوع MIME. + +**هيكل التخزين:** +يتم تخزين البيانات الوصفية في Cassandra (مساحة مفاتيح `librarian`، جدول `document`). +يتم تخزين المحتوى في تخزين الكائنات الثنائية MinIO/S3 (حاوية `library`). +تسليم محتوى ذكي: المستندات الأقل من 2 ميجابايت مضمنة، ويتم بث المستندات الأكبر حجمًا. + +#### الملفات الرئيسية + +`trustgraph-flow/trustgraph/librarian/librarian.py` - العمليات الأساسية لأمين المكتبة. +`trustgraph-flow/trustgraph/librarian/service.py` - معالج الخدمة، تحميل المستند. +`trustgraph-flow/trustgraph/tables/library.py` - متجر جدول Cassandra. +`trustgraph-base/trustgraph/schema/services/library.py` - تعريفات المخططات. +>>>>>>> 82edf2d (New md files from RunPod) + +#### الثغرات التي يجب معالجتها + +يحتوي أمين المكتبة على اللبنات الأساسية ولكن حاليًا: +<<<<<<< HEAD +1. الربط من الأب إلى الابن ذو مستوى واحد فقط - لا توجد أدوات مساعدة لتصفح الرسوم البيانية متعددة المستويات +2. لا يوجد مفردات قياسية لأنواع العلاقات (مثل `derivedFrom`، `extractedFrom`) +3. بيانات التتبع الوصفية (طريقة الاستخراج، والثقة، وموضع الجزء) غير موحدة +4. لا توجد واجهة برمجة تطبيقات للاستعلام للتنقل عبر سلسلة التتبع الكاملة من حقيقة إلى المصدر +======= +1. ربط الأب-الابن ذو مستوى واحد فقط - لا توجد أدوات مساعدة لتصفح الرسوم البيانية متعددة المستويات. +2. لا يوجد مفردات قياسية لأنواع العلاقات (مثل `derivedFrom`، `extractedFrom`). +3. بيانات التتبع الوصفية (طريقة الاستخراج، والثقة، وموضع الجزء) غير موحدة. +4. لا توجد واجهة برمجة تطبيقات للاستعلام للتنقل عبر سلسلة التتبع الكاملة من حقيقة إلى المصدر. +>>>>>>> 82edf2d (New md files from RunPod) + +## تصميم التدفق الشامل + +يتبع كل معالج في خط الأنابيب نمطًا متسقًا: +<<<<<<< HEAD +استقبال معرف المستند من البنية التحتية +جلب المحتوى من أمين المكتبة +إنتاج القطع الأثرية الفرعية +لكل قطعة أثرية فرعية: حفظ في أمين المكتبة، وإصدار حافة إلى الرسم البياني، وتمرير المعرف إلى البنية التحتية +======= +استقبال معرف المستند من المصدر العلوي. +جلب المحتوى من أمين المكتبة. +إنتاج القطع الأثرية الفرعية. +لكل قطعة أثرية فرعية: حفظ في أمين المكتبة، وإصدار حافة إلى الرسم البياني، وتمرير المعرف إلى المكون التالي. +>>>>>>> 82edf2d (New md files from RunPod) + +### تدفقات المعالجة + +هناك تدفقان اعتمادًا على نوع المستند: + +#### تدفق مستند PDF + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### تدفق مستندات النص + +تتجاوز مستندات النص أداة استخراج ملفات PDF وتنتقل مباشرةً إلى وحدة التقسيم: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +الرسم البياني الموجه الناتج أقصر بمستوى واحد: + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +<<<<<<< HEAD +التصميم يتكيف مع كل من المصدر والصفحة لأن وحدة التقسيم تعالج مدخلاتها بشكل عام - فهي تستخدم أي معرف مستند تتلقاه كمعرف رئيسي، بغض النظر عما إذا كان ذلك مستند مصدر أم صفحة. + +### مخطط البيانات الوصفية (PROV-O) + +تستخدم البيانات الوصفية المتعلقة بالأصل علم الوجود W3C PROV-O. يوفر هذا مفردات قياسية ويمكن أن يمكّن التوقيع/المصادقة المستقبلية لنتائج الاستخراج. +======= +التصميم يتكيف مع كلتا الحالتين لأن وحدة التقسيم تعالج مدخلاتها بشكل عام - فهي تستخدم أي معرف مستند تتلقاه كمعرف رئيسي، بغض النظر عما إذا كان ذلك مستندًا أصليًا أم صفحة. + +### مخطط البيانات الوصفية (PROV-O) + +تستخدم البيانات الوصفية المتعلقة بالأصل علم الوجود W3C PROV-O. يوفر هذا مفردات قياسية ويمكن أن يتيح في المستقبل التوقيع والمصادقة على مخرجات الاستخراج. +>>>>>>> 82edf2d (New md files from RunPod) + +#### المفاهيم الأساسية في PROV-O + +| نوع PROV-O | استخدام TrustGraph | +|-------------|------------------| +| `prov:Entity` | مستند، صفحة، جزء، ثلاثي، تضمين | +| `prov:Activity` | حالات عمليات الاستخراج | +| `prov:Agent` | مكونات TG (مثل أداة استخراج PDF، ووحدة التقسيم، إلخ) مع الإصدارات | + +#### علاقات PROV-O + +| الرابط | المعنى | مثال | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | كيان مشتق من كيان آخر | الصفحة مشتقة من المستند | +| `prov:wasGeneratedBy` | كيان تم إنشاؤه بواسطة نشاط | الصفحة تم إنشاؤها بواسطة نشاط استخراج PDF | +| `prov:used` | نشاط استخدم كيانًا كمدخل | نشاط استخراج PDF استخدم المستند | +| `prov:wasAssociatedWith` | نشاط تم تنفيذه بواسطة وكيل | نشاط استخراج PDF مرتبط بـ tg:PDFExtractor | + +#### البيانات الوصفية في كل مستوى + +<<<<<<< HEAD +**المستند المصدر (يتم إصداره بواسطة Librarian):** +======= +**المستند الأصلي (يتم إصداره بواسطة Librarian):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +**الصفحة (تم إنشاؤها بواسطة مُستخرج PDF):** +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +<<<<<<< HEAD +**الجزء (يتم إصداره بواسطة وحدة التجميع):** +======= +**جزء (يتم إصداره بواسطة أداة التقسيم):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**ثلاثي (تم إصداره بواسطة مُستخلص المعرفة):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**التضمين (يتم تخزينه في مخزن المتجهات، وليس في مخزن الثلاثيات):** + +يتم تخزين التضمينات في مخزن المتجهات مع البيانات الوصفية، وليس كـ RDF triples. يحتوي كل سجل تضمين على: + +| الحقل | الوصف | مثال | +|-------|-------------|---------| +| vector | متجه التضمين | [0.123, -0.456, ...] | +| entity | عنوان URI للعقدة التي يمثلها التضمين | `entity:JohnSmith` | +| chunk_id | الجزء المصدر (الأصل) | `chunk:123-1-1` | +| model | نموذج التضمين المستخدم | `text-embedding-ada-002` | +| component_version | إصدار مُحسِّن التضمين (TG embedder) | `1.0.0` | + +يربط الحقل `entity` التضمين بالرسم البياني المعرفي (عنوان URI للعقدة). يوفر الحقل `chunk_id` معلومات عن الأصل إلى الجزء المصدر، مما يتيح التنقل صعودًا في الرسم البياني الموجه (DAG) إلى المستند الأصلي. + +#### امتدادات مساحة اسم TrustGraph + +محددات مخصصة ضمن مساحة الاسم `tg:` لبيانات وصفية خاصة بالاستخراج: + +| المحدد | النطاق | الوصف | +|-----------|--------|-------------| +| `tg:contains` | Subgraph | يشير إلى ثلاثية موجودة في هذا الرسوم البيانية الفرعية للاستخراج | +| `tg:pageCount` | Document | العدد الإجمالي لصفحات المستند المصدر | +| `tg:mimeType` | Document | نوع MIME للمستند المصدر | +| `tg:pageNumber` | Page | رقم الصفحة في المستند المصدر | +| `tg:chunkIndex` | Chunk | فهرس الجزء داخل الأصل | +| `tg:charOffset` | Chunk | الإزاحة الحرفية في النص الأصل | +| `tg:charLength` | Chunk | طول الجزء بالأحرف | +| `tg:chunkSize` | Activity | حجم الجزء المُكوَّن | +| `tg:chunkOverlap` | Activity | التداخل المُكوَّن بين الأجزاء | +| `tg:componentVersion` | Activity | إصدار مكون TG | +| `tg:llmModel` | Activity | نموذج LLM المستخدم للاستخراج | +<<<<<<< HEAD +| `tg:ontology` | Activity | عنوان URI للأنطولوجيا المستخدم لتوجيه الاستخراج | +======= +| `tg:ontology` | Activity | عنوان URI للدلالة المستخدم لتوجيه الاستخراج | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:embeddingModel` | Activity | النموذج المستخدم للتضمينات | +| `tg:sourceText` | Statement | النص الدقيق الذي تم استخراج ثلاثية منه | +| `tg:sourceCharOffset` | Statement | الإزاحة الحرفية داخل الجزء حيث يبدأ النص المصدر | +| `tg:sourceCharLength` | Statement | طول النص المصدر بالأحرف | + +#### تهيئة المفردات (لكل مجموعة) + +<<<<<<< HEAD +الرسم البياني المعرفي محايد للأنطولوجيا ويبدأ فارغًا. عند كتابة بيانات سلالة PROV-O إلى مجموعة لأول مرة، يجب تهيئة المفردات باستخدام تسميات RDF لجميع الفئات والمحددات. يضمن ذلك عرضًا قابلاً للقراءة بواسطة الإنسان في الاستعلامات وواجهة المستخدم. +======= +الرسم البياني المعرفي محايد بالنسبة للدلالات ويبدأ فارغًا. عند كتابة بيانات سلالة PROV-O إلى مجموعة لأول مرة، يجب تهيئة المفردات باستخدام تسميات RDF لجميع الفئات والمحددات. يضمن ذلك عرضًا قابلاً للقراءة بواسطة الإنسان في الاستعلامات وواجهة المستخدم. +>>>>>>> 82edf2d (New md files from RunPod) + +**فئات PROV-O:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +<<<<<<< HEAD +**المُتَعَدِّيات (Predicates) الخاصة بـ PROV-O:** +======= +**المفردات (Predicates) الخاصة بـ PROV-O:** +>>>>>>> 82edf2d (New md files from RunPod) +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**عبارات TrustGraph:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +**ملاحظة حول التنفيذ:** يجب أن يكون هذا الإطار اللغوي ذاتي الإعادة - آمنًا للتشغيل عدة مرات دون إنشاء تكرارات. يمكن تشغيله في معالجة المستند الأول في المجموعة، أو كخطوة منفصلة لتهيئة المجموعة. + +<<<<<<< HEAD +#### أصل الجزء الفرعي (طموح) + +للحصول على معلومات تفصيلية حول الأصل، سيكون من المفيد تسجيل المكان الدقيق داخل جزء معين حيث تم استخراج الثلاثي. هذا يسمح بـ: + +تسليط الضوء على النص المصدر الدقيق في واجهة المستخدم. +التحقق من دقة الاستخراج مقابل المصدر. +======= +#### مصدر المعلومات التفصيلية (طموح) + +للحصول على معلومات تفصيلية حول المصدر، سيكون من المفيد تسجيل المكان الدقيق داخل جزء معين حيث تم استخراج الثلاثيات منه. هذا يسمح بـ: + +تسليط الضوء على النص المصدر الدقيق في واجهة المستخدم. +التحقق من دقة الاستخراج مقارنة بالمصدر. +>>>>>>> 82edf2d (New md files from RunPod) +تصحيح جودة الاستخراج على مستوى الجملة. + +**مثال مع تتبع الموضع:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**مثال مع نطاق نص (بديل):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**اعتبارات التنفيذ:** + +<<<<<<< HEAD +قد لا توفر استخراج البيانات باستخدام نماذج اللغة الكبيرة (LLM) بشكل طبيعي مواقع الأحرف. +يمكن توجيه نموذج اللغة الكبيرة لإرجاع الجملة/العبارة المصدرية بالإضافة إلى الثلاثيات المستخرجة. +بدلاً من ذلك، يمكن إجراء معالجة لاحقة لمطابقة الكيانات المستخرجة بشكل تقريبي مع النص المصدر. +يوجد مقايضة بين تعقيد الاستخراج ودقة تتبع المصدر. +قد يكون من الأسهل تحقيق ذلك باستخدام طرق الاستخراج المنظمة بدلاً من استخراج البيانات المجردة باستخدام نماذج اللغة الكبيرة. +======= +قد لا توفر عملية الاستخراج القائمة على نماذج اللغة الكبيرة (LLM) بشكل طبيعي مواقع الأحرف. +يمكن توجيه نموذج اللغة الكبيرة لإرجاع الجملة/العبارة المصدرية بالإضافة إلى الثلاثيات المستخرجة. +بدلاً من ذلك، يمكن إجراء معالجة لاحقة لمطابقة الكيانات المستخرجة بشكل تقريبي مع النص الأصلي. +يوجد مقايضة بين تعقيد الاستخراج ودقة تتبع المصدر. +قد يكون من الأسهل تحقيق ذلك باستخدام طرق الاستخراج المنظمة بدلاً من استخراج نماذج اللغة الكبيرة غير المنظمة. +>>>>>>> 82edf2d (New md files from RunPod) + +هذا الأمر مصنف على أنه طموح - يجب تنفيذ تتبع المصدر على مستوى المقطع أولاً، مع تتبع المقطع الفرعي كتحسين مستقبلي إذا كان ذلك ممكنًا. + +### نموذج التخزين المزدوج + +<<<<<<< HEAD +يتم بناء رسم بياني لتتبع المصدر بشكل تدريجي أثناء تدفق المستندات عبر مسار العمل: +======= +يتم بناء رسم بياني (DAG) لتتبع المصدر تدريجيًا أثناء تدفق المستندات عبر مسار العمل: +>>>>>>> 82edf2d (New md files from RunPod) + +| التخزين | ما يتم تخزينه | الغرض | +|-------|---------------|---------| +| أمين المكتبة | محتوى المستند + روابط الأبناء | استرجاع المحتوى، حذف متسلسل | +<<<<<<< HEAD +| الرسم البياني للمعرفة | حواف الأبناء، وبيانات وصفية | استعلامات تتبع المصدر، إسناد الحقائق | + +تحتفظ كلا التخزينين بنفس هيكل الرسم البياني. يحتوي أمين المكتبة على المحتوى، بينما يحتوي الرسم البياني على العلاقات ويمكنه تمكين استعلامات التصفح. + +### المبادئ الأساسية للتصميم + +1. **معرف المستند كوحدة تدفق** - تمرر المعالجات المعرفات، وليس المحتوى. يتم استرداد المحتوى من أمين المكتبة عند الحاجة. + +2. **الإرسال مرة واحدة من المصدر** - يتم كتابة البيانات الوصفية في الرسم البياني مرة واحدة عند بدء المعالجة، وليس بشكل متكرر في المراحل اللاحقة. + +3. **نمط معالج متسق** - يتبع كل معالج نفس النمط: الاستقبال/الاسترداد/الإنتاج/الحفظ/الإرسال/التوجيه. + +4. **بناء تدريجي للرسم البياني** - يضيف كل معالج مستواه إلى الرسم البياني. يتم بناء سلسلة تتبع المصدر الكاملة بشكل تدريجي. + +5. **تحسين ما بعد التقطيع** - بعد التقطيع، تحمل الرسائل كلاً من المعرف والمحتوى. تكون القطع صغيرة (2-4 كيلوبايت)، لذلك يؤدي تضمين المحتوى إلى تجنب عمليات الذهاب والإياب غير الضرورية إلى أمين المكتبة مع الحفاظ على تتبع المصدر عبر المعرف. +======= +| الرسم البياني المعرفي | حواف الأبناء، بالإضافة إلى البيانات الوصفية | استعلامات تتبع المصدر، إسناد الحقائق | + +تحتفظ كلتا الحالتين بنفس هيكل الرسم البياني. تحتفظ أمين المكتبة بالمحتوى، بينما يحتفظ الرسم البياني بالعلاقات ويمكنه تمكين استعلامات التصفح. + +### المبادئ الأساسية للتصميم + +1. **معرف المستند كوحدة تدفق** - تمرر المعالجات المعرفات، وليس المحتوى. يتم جلب المحتوى من أمين المكتبة عند الحاجة. + +2. **الإرسال مرة واحدة من المصدر** - يتم كتابة البيانات الوصفية في الرسم البياني مرة واحدة عند بدء المعالجة، وليس بشكل متكرر في المراحل اللاحقة. + +3. **نمط معالج متسق** - يتبع كل معالج نفس النمط: الاستقبال/الجلب/الإنتاج/الحفظ/الإرسال/التوجيه. + +4. **بناء تدريجي للرسم البياني** - يضيف كل معالج مستواه إلى الرسم البياني. يتم بناء سلسلة تتبع المصدر الكاملة بشكل تدريجي. + +5. **تحسين ما بعد التقسيم إلى أجزاء** - بعد التقسيم إلى أجزاء، تحمل الرسائل كلاً من المعرف والمحتوى. الأجزاء صغيرة (2-4 كيلوبايت)، لذا فإن تضمين المحتوى يتجنب عمليات الذهاب والإياب غير الضرورية إلى أمين المكتبة مع الحفاظ على تتبع المصدر عبر المعرف. +>>>>>>> 82edf2d (New md files from RunPod) + +## مهام التنفيذ + +### تغييرات أمين المكتبة + +#### الحالة الحالية + +يبدأ معالجة المستند عن طريق إرسال معرف المستند إلى المعالج الأول. +لا يوجد اتصال بمخزن الثلاثيات - يتم تجميع البيانات الوصفية مع مخرجات الاستخراج. +`add-child-document` ينشئ روابط الأبناء من مستوى واحد. +`list-children` يُرجع فقط الأبناء المباشرين. + +#### التغييرات المطلوبة + +**1. واجهة جديدة: اتصال بمخزن الثلاثيات** + +<<<<<<< HEAD +يحتاج أمين المكتبة إلى إرسال حواف بيانات وصفية للمستند مباشرة إلى الرسم البياني للمعرفة عند بدء المعالجة. +======= +تحتاج أمين المكتبة إلى إرسال حواف بيانات وصفية لمستندات الأبناء مباشرة إلى الرسم البياني المعرفي عند بدء المعالجة. +>>>>>>> 82edf2d (New md files from RunPod) +إضافة عميل/ناشر مخزن الثلاثيات إلى خدمة أمين المكتبة. +عند بدء المعالجة: إرسال بيانات وصفية للمستند الجذر كحواف في الرسم البياني (مرة واحدة). + +**2. مفردات أنواع المستندات** + +<<<<<<< HEAD +توحيد قيم `document_type` لأبناء المستند: +======= +توحيد قيم `document_type` لمستندات الأبناء: +>>>>>>> 82edf2d (New md files from RunPod) +`source` - المستند الذي تم تحميله أصلاً. +`page` - صفحة مستخرجة من المصدر (PDF، إلخ). +`chunk` - جزء نصي مشتق من الصفحة أو المصدر. + +#### ملخص تغييرات الواجهة + +| الواجهة | التغيير | +|-----------|--------| +<<<<<<< HEAD +| مخزن الثلاثيات | اتصال صادر جديد - إرسال حواف بيانات وصفية للمستند | +======= +| مخزن الثلاثيات | اتصال صادر جديد - إرسال حواف بيانات وصفية لمستندات الأبناء | +>>>>>>> 82edf2d (New md files from RunPod) +| بدء المعالجة | إرسال البيانات الوصفية إلى الرسم البياني قبل توجيه معرف المستند | + +### تغييرات مستخرج PDF + +#### الحالة الحالية + +<<<<<<< HEAD +يتلقى محتوى المستند (أو يتدفق المستندات الكبيرة). +يستخرج النص من صفحات PDF. +يوجه محتوى الصفحة إلى وحدة التقطيع. +======= +يتلقى محتوى المستند (أو يقوم بتدفق المستندات الكبيرة). +يستخرج النص من صفحات PDF. +يوجه محتوى الصفحة إلى وحدة تقسيم إلى أجزاء. +>>>>>>> 82edf2d (New md files from RunPod) +لا يوجد تفاعل مع أمين المكتبة أو مخزن الثلاثيات. + +#### التغييرات المطلوبة + +**1. واجهة جديدة: عميل أمين المكتبة** + +يحتاج مستخرج PDF إلى حفظ كل صفحة كمستند تابع في أمين المكتبة. +إضافة عميل أمين المكتبة إلى خدمة مستخرج PDF. +لكل صفحة: استدعاء `add-child-document` مع parent = معرف المستند الجذر. + +**2. واجهة جديدة: اتصال بمخزن الثلاثيات** + +<<<<<<< HEAD +يحتاج مستخرج PDF إلى إرسال حواف الأبناء إلى الرسم البياني للمعرفة. +======= +يحتاج مستخرج PDF إلى إرسال حواف الأبناء إلى الرسم البياني المعرفي. +>>>>>>> 82edf2d (New md files from RunPod) +إضافة عميل/ناشر مخزن الثلاثيات. +لكل صفحة: إرسال حافة تربط مستند الصفحة بالمستند الأصل. + +**3. تغيير تنسيق الإخراج** + +بدلًا من إرسال محتوى الصفحة مباشرةً، أرسل مُعرّف مستند الصفحة. +<<<<<<< HEAD +سيقوم المقطع (Chunker) بجلب المحتوى من أمين المكتبة (librarian) باستخدام المعرّف. +======= +سيقوم المقطع (Chunker) بجلب المحتوى من المكتبة (librarian) باستخدام المعرّف. +>>>>>>> 82edf2d (New md files from RunPod) + +#### ملخص التغييرات في الواجهة + +| الواجهة | التغيير | +|-----------|--------| +<<<<<<< HEAD +| أمين المكتبة (Librarian) | واجهة تصدير جديدة - حفظ المستندات الفرعية | +| قاعدة البيانات الثلاثية (Triple store) | واجهة تصدير جديدة - إرسال علاقات الأبناء والبنات | +======= +| المكتبة (librarian) | إخراج جديد - حفظ المستندات الفرعية | +| المستودع الثلاثي (Triple store) | إخراج جديد - إرسال علاقات الأبناء | +>>>>>>> 82edf2d (New md files from RunPod) +| رسالة الإخراج | تغيير من المحتوى إلى مُعرّف المستند | + +### تغييرات المقطع (Chunker) + +#### الحالة الحالية + +<<<<<<< HEAD +يستقبل محتوى الصفحة/النص +يقسم إلى أجزاء (chunks) +يرسل محتوى الجزء إلى المعالجات اللاحقة +لا يوجد تفاعل مع أمين المكتبة أو قاعدة البيانات الثلاثية +======= +يتلقى محتوى الصفحة/النص +يقسم إلى أجزاء +يرسل محتوى الجزء إلى المعالجات اللاحقة +لا يوجد تفاعل مع المكتبة أو المستودع الثلاثي +>>>>>>> 82edf2d (New md files from RunPod) + +#### التغييرات المطلوبة + +**1. تغيير طريقة معالجة الإدخال** + +<<<<<<< HEAD +استقبل مُعرّف المستند بدلًا من المحتوى، وجلبه من أمين المكتبة. +أضف عميل أمين المكتبة إلى خدمة المقطع. +جلب محتوى الصفحة باستخدام مُعرّف المستند. + +**2. واجهة جديدة: عميل أمين المكتبة (للكتابة)** + +احفظ كل جزء كمستند فرعي في أمين المكتبة. +لكل جزء: استدعِ `add-child-document` مع `parent = page document ID` + +**3. واجهة جديدة: اتصال بقاعدة البيانات الثلاثية** + +أرسل علاقات الأبناء والبنات إلى الرسم البياني المعرفي. +أضف عميل/ناشر قاعدة البيانات الثلاثية. +======= +استقبل مُعرّف المستند بدلاً من المحتوى، وجلبه من المكتبة. +أضف عميل المكتبة إلى خدمة المقطع. +جلب محتوى الصفحة باستخدام مُعرّف المستند. + +**2. واجهة جديدة: عميل المكتبة (للكتابة)** + +احفظ كل جزء كمستند فرعي في المكتبة. +لكل جزء: اتصل بـ `add-child-document` مع `parent = مُعرّف مستند الصفحة` + +**3. واجهة جديدة: اتصال بالمستودع الثلاثي** + +أرسل علاقات الأبناء إلى الرسم البياني المعرفي. +أضف عميل/ناشر المستودع الثلاثي. +>>>>>>> 82edf2d (New md files from RunPod) +لكل جزء: أرسل علاقة تربط مستند الجزء بمستند الصفحة. + +**4. تغيير تنسيق الإخراج** + +<<<<<<< HEAD +أرسل كلاً من مُعرّف مستند الجزء ومحتوى الجزء (تحسين لاحق للمقطع). +تستقبل المعالجات اللاحقة المعرّف لأغراض التتبع + المحتوى للعمل به. +======= +أرسل كلاً من مُعرّف مستند الجزء ومحتوى الجزء (تحسين بعد تقسيم الجزء). +تتلقى المعالجات اللاحقة المعرّف لتتبع المصدر + المحتوى للعمل به. +>>>>>>> 82edf2d (New md files from RunPod) + +#### ملخص التغييرات في الواجهة + +| الواجهة | التغيير | +|-----------|--------| +| رسالة الإدخال | تغيير من المحتوى إلى مُعرّف المستند | +<<<<<<< HEAD +| أمين المكتبة (Librarian) | واجهة تصدير جديدة (قراءة وكتابة) - جلب المحتوى، حفظ المستندات الفرعية | +| قاعدة البيانات الثلاثية (Triple store) | واجهة تصدير جديدة - إرسال علاقات الأبناء والبنات | +======= +| المكتبة (librarian) | إخراج جديد (قراءة وكتابة) - جلب المحتوى، حفظ المستندات الفرعية | +| المستودع الثلاثي (Triple store) | إخراج جديد - إرسال علاقات الأبناء | +>>>>>>> 82edf2d (New md files from RunPod) +| رسالة الإخراج | تغيير من المحتوى فقط إلى المعرّف + المحتوى | + +### تغييرات مُستخرج المعرفة (Knowledge Extractor) + +#### الحالة الحالية + +<<<<<<< HEAD +يستقبل محتوى الجزء +يستخرج الثلاثيات والتضمينات +يرسل إلى قاعدة البيانات الثلاثية ومخزن التضمينات +`subjectOf` تشير العلاقة إلى المستند ذي المستوى الأعلى (وليس الجزء) +======= +يتلقى محتوى الجزء +يستخرج الثلاثيات والتضمينات +يرسل إلى المستودع الثلاثي ومستودع التضمينات +تشير علاقة `subjectOf` إلى المستند ذي المستوى الأعلى (وليس الجزء). +>>>>>>> 82edf2d (New md files from RunPod) + +#### التغييرات المطلوبة + +**1. تغيير طريقة معالجة الإدخال** + +استقبل مُعرّف مستند الجزء بالإضافة إلى المحتوى. +<<<<<<< HEAD +استخدم مُعرّف الجزء لأغراض الربط (المحتوى مدرج بالفعل كتحسين). + +**2. تحديث أثر الثلاثيات** + +اربط الثلاثيات المستخرجة بالجزء (وليس المستند ذي المستوى الأعلى). +استخدم التجريد لإنشاء حافة تشير إلى الحافة +`subjectOf` العلاقة: ثلاثية → مُعرّف مستند الجزء +الاستخدام الأول للدعم الحالي للتجريد + +**3. تحديث أثر التضمينات** + +اربط معرفات كيانات التضمين بالجزء. +أرسل حافة: معرف كيان التضمين → مُعرّف مستند الجزء +======= +استخدم مُعرّف الجزء لتتبع المصدر (تم تضمين المحتوى بالفعل كجزء من التحسين). + +**2. تحديث تتبع المصدر** + +اربط الثلاثيات المستخرجة بالجزء (وليس المستند ذي المستوى الأعلى). +استخدم التجريد لإنشاء حافة تشير إلى الحافة. +علاقة `subjectOf`: الثلاثية → مُعرّف مستند الجزء +الاستخدام الأول للدعم الحالي للتجريد. + +**3. تحديث تتبع التضمينات** + +اربط معرفات كيانات التضمين بالجزء. +أرسل حافة: معرف كيان التضمين → مُعرّف مستند الجزء. +>>>>>>> 82edf2d (New md files from RunPod) + +#### ملخص التغييرات في الواجهة + +| الواجهة | التغيير | +|-----------|--------| +| رسالة الإدخال | توقع مُعرّف الجزء + المحتوى (وليس المحتوى فقط) | +<<<<<<< HEAD +| قاعدة البيانات الثلاثية | استخدم التجريد لأثر الثلاثية → الجزء | +| أثر التضمين | اربط معرف الكيان → معرف الجزء | + +## المراجع + +أثر وقت الاستعلام: `docs/tech-specs/query-time-provenance.md` +معيار PROV-O لنمذجة الأثر +البيانات الوصفية المصدر الحالية في الرسم البياني المعرفي (تحتاج إلى تدقيق) +======= +| المستودع الثلاثي (Triple store) | استخدم التجريد لتتبع الثلاثية → الجزء | +| تتبع التضمينات | اربط معرف الكيان → معرف الجزء | + +## المراجع + +تتبع وقت الاستعلام: `docs/tech-specs/query-time-provenance.md` +معيار PROV-O لنمذجة التتبع. +البيانات الوصفية المصدر الحالية في الرسم البياني المعرفي (تحتاج إلى تدقيق). +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/extraction-time-provenance.es.md b/docs/tech-specs/extraction-time-provenance.es.md new file mode 100644 index 00000000..9480398e --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.es.md @@ -0,0 +1,803 @@ +--- +layout: default +title: "Proveniencia en Tiempo de Extracción: Capa de Origen" +parent: "Spanish (Beta)" +--- + +# Proveniencia en Tiempo de Extracción: Capa 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 + +Este documento captura notas sobre la proveniencia en tiempo de extracción para futuros trabajos de especificación. La proveniencia en tiempo de extracción registra la "capa de origen": de dónde provienen los datos originalmente, cómo se extrajeron y transformaron. + +Esto es diferente de la proveniencia en tiempo de consulta (ver `query-time-provenance.md`), que registra el razonamiento del agente. + +## Declaración del Problema + +### Implementación Actual + +Actualmente, la proveniencia funciona de la siguiente manera: +Los metadatos del documento se almacenan como triples RDF en el grafo de conocimiento. +Un ID de documento vincula los metadatos al documento, de modo que el documento aparece como un nodo en el grafo. +Cuando se extraen aristas (relaciones/hechos) de los documentos, una relación `subjectOf` vincula la arista extraída con el documento de origen. + +### Problemas con el Enfoque Actual + +1. **Carga repetitiva de metadatos:** Los metadatos del documento se empaquetan y cargan repetidamente con cada lote de triples extraídos de ese documento. Esto es un desperdicio y redundante: los mismos metadatos viajan como carga con cada salida de extracción. + +<<<<<<< HEAD +2. **Proveniencia superficial:** La relación `subjectOf` actual solo vincula los hechos directamente con el documento de nivel superior. No hay visibilidad de la cadena de transformación: qué página proporcionó el hecho, qué fragmento, qué método de extracción se utilizó. +======= +2. **Proveniencia superficial:** La relación `subjectOf` actual solo vincula los hechos directamente al documento de nivel superior. No hay visibilidad de la cadena de transformación: qué página proporcionó el hecho, qué fragmento, qué método de extracción se utilizó. +>>>>>>> 82edf2d (New md files from RunPod) + +### Estado Deseado + +1. **Cargar metadatos una vez:** Los metadatos del documento deben cargarse una vez y adjuntarse al nodo del documento de nivel superior, no repetirse con cada lote de triples. + +<<<<<<< HEAD +2. **DAG de proveniencia rica:** Capturar toda la cadena de transformación desde el documento de origen a través de todos los artefactos intermedios hasta los hechos extraídos. Por ejemplo, una transformación de un documento PDF: +======= +2. **DAG de proveniencia enriquecido:** Capturar la cadena de transformación completa desde el documento de origen a través de todos los artefactos intermedios hasta los hechos extraídos. Por ejemplo, una transformación de un documento PDF: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +3. **Almacenamiento unificado:** El grafo de procedencia se almacena en el mismo grafo de conocimiento que el conocimiento extraído. Esto permite consultar la procedencia de la misma manera que se consulta el conocimiento: siguiendo los enlaces hacia atrás a lo largo de la cadena desde cualquier hecho hasta su ubicación de origen exacta. + +<<<<<<< HEAD +4. **Identificadores estables:** Cada artefacto intermedio (página, fragmento) tiene un identificador estable como un nodo en el grafo. +======= +4. **Identificadores estables:** Cada artefacto intermedio (página, fragmento) tiene un identificador estable como nodo en el grafo. +>>>>>>> 82edf2d (New md files from RunPod) + +5. **Enlace padre-hijo:** Los documentos derivados se vinculan a sus padres hasta el documento fuente de nivel superior, utilizando tipos de relación consistentes. + +6. **Atribución precisa de hechos:** La relación `subjectOf` en los bordes extraídos apunta al padre inmediato (fragmento), no al documento de nivel superior. La procedencia completa se recupera recorriendo el DAG. + +## Casos de uso + +### UC1: Atribución de la fuente en las respuestas de GraphRAG + +**Escenario:** Un usuario ejecuta una consulta de GraphRAG y recibe una respuesta del agente. + +**Flujo:** +1. El usuario envía una consulta al agente de GraphRAG. +2. El agente recupera hechos relevantes del grafo de conocimiento para formular una respuesta. +3. De acuerdo con la especificación de procedencia en tiempo de consulta, el agente informa qué hechos contribuyeron a la respuesta. +4. Cada hecho se vincula a su fragmento de origen a través del grafo de procedencia. +5. Los fragmentos se vinculan a páginas, las páginas se vinculan a documentos fuente. + +<<<<<<< HEAD +**Resultado de la experiencia de usuario:** La interfaz muestra la respuesta del LLM junto con la atribución de la fuente. El usuario puede: +======= +**Resultado de la experiencia del usuario:** La interfaz muestra la respuesta del LLM junto con la atribución de la fuente. El usuario puede: +>>>>>>> 82edf2d (New md files from RunPod) +Ver qué hechos respaldaron la respuesta. +Profundizar desde hechos → fragmentos → páginas → documentos. +Examinar los documentos fuente originales para verificar las afirmaciones. +Comprender exactamente dónde en un documento (en qué página, en qué sección) se originó un hecho. + +**Valor:** Los usuarios pueden verificar las respuestas generadas por la IA con fuentes primarias, lo que genera confianza y permite la verificación de hechos. + +### UC2: Depuración de la calidad de la extracción + +Un hecho parece incorrecto. Rastrear hacia atrás a través del fragmento → página → documento para ver el texto original. ¿Fue una mala extracción, o la fuente en sí misma estaba equivocada? + +### UC3: Reextracción incremental + +El documento fuente se actualiza. ¿Qué fragmentos/hechos se derivaron de él? Invalidar y regenerar solo esos, en lugar de volver a procesar todo. + +### UC4: Eliminación de datos / Derecho al olvido + +Se debe eliminar un documento fuente (GDPR, legal, etc.). Recorrer el DAG para encontrar y eliminar todos los hechos derivados. + +### UC5: Resolución de conflictos + +Dos hechos se contradicen. Rastrear ambos hasta sus fuentes para comprender por qué y decidir a cuál confiar (fuente más autorizada, más reciente, etc.). + +### UC6: Ponderación de la autoridad de la fuente + +Algunas fuentes son más autorizadas que otras. Los hechos se pueden ponderar o filtrar según la autoridad/calidad de sus documentos de origen. + +### UC7: Comparación de la canalización de extracción + +Comparar los resultados de diferentes métodos/versiones de extracción. ¿Qué extractor produjo mejores hechos del mismo documento fuente? + +## Puntos de integración + +<<<<<<< HEAD +### Bibliotecario + +El componente de bibliotecario ya proporciona almacenamiento de documentos con identificadores de documentos únicos. El sistema de procedencia se integra con esta infraestructura existente. + +#### Capacidades existentes (ya implementadas) + +**Vinculación de documentos padre-hijo:** +Campo `parent_id` en `DocumentMetadata`: vincula el documento hijo al documento padre. +Campo `document_type`: valores: `"source"` (original) o `"extracted"` (derivado). +API `add-child-document`: crea un documento hijo con `document_type = "extracted"` automático. +API `list-children`: recupera todos los hijos de un documento padre. +Eliminación en cascada: eliminar un padre elimina automáticamente todos los documentos hijo. + +**Identificación de documentos:** +======= +### Librarian + +El componente de "Librarian" ya proporciona almacenamiento de documentos con identificadores de documentos únicos. El sistema de procedencia se integra con esta infraestructura existente. + +#### Capacidades Existentes (ya implementadas) + +**Vinculación de Documentos Padre-Hijo:** +Campo `parent_id` en `DocumentMetadata`: vincula el documento hijo al documento padre. +Campo `document_type`: valores: `"source"` (original) o `"extracted"` (derivado). +API `add-child-document`: crea un documento hijo con `document_type = "extracted"` automáticamente. +API `list-children`: recupera todos los hijos de un documento padre. +Eliminación en cascada: eliminar un padre elimina automáticamente todos los documentos hijos. + +**Identificación de Documentos:** +>>>>>>> 82edf2d (New md files from RunPod) +Los identificadores de documentos son especificados por el cliente (no generados automáticamente). +Documentos indexados por una clave compuesta `(user, document_id)` en Cassandra. +Identificadores de objetos (UUID) generados internamente para el almacenamiento de blobs. + +<<<<<<< HEAD +**Soporte de metadatos:** +======= +**Soporte de Metadatos:** +>>>>>>> 82edf2d (New md files from RunPod) +Campo `metadata: list[Triple]`: triples RDF para metadatos estructurados. +`title`, `comments`, `tags`: metadatos básicos del documento. +`time`: marca de tiempo, `kind`: tipo MIME. + +<<<<<<< HEAD +**Arquitectura de almacenamiento:** +Los metadatos se almacenan en Cassandra (espacio de claves `librarian`, tabla `document`). +El contenido se almacena en MinIO/S3 blob storage (cubeta `library`). +Entrega inteligente de contenido: documentos < 2 MB incrustados, documentos más grandes transmitidos por flujo. + +#### Archivos clave + +`trustgraph-flow/trustgraph/librarian/librarian.py`: operaciones principales del bibliotecario. +`trustgraph-flow/trustgraph/librarian/service.py`: procesador de servicios, carga de documentos. +`trustgraph-flow/trustgraph/tables/library.py`: almacén de tablas de Cassandra. +`trustgraph-base/trustgraph/schema/services/library.py`: definiciones de esquema. + +#### Aspectos a abordar + +El bibliotecario tiene los componentes básicos, pero actualmente: +1. La vinculación padre-hijo es de un solo nivel: no hay ayudantes de recorrido de DAG multinivel. +======= +**Arquitectura de Almacenamiento:** +Los metadatos se almacenan en Cassandra (espacio de claves `librarian`, tabla `document`). +El contenido se almacena en MinIO/S3 (cubeta `library`). +Entrega inteligente de contenido: documentos < 2MB incrustados, documentos más grandes transmitidos por flujo. + +#### Archivos Clave + +`trustgraph-flow/trustgraph/librarian/librarian.py`: Operaciones principales de "Librarian". +`trustgraph-flow/trustgraph/librarian/service.py`: Procesador de servicios, carga de documentos. +`trustgraph-flow/trustgraph/tables/library.py`: Almacén de tablas de Cassandra. +`trustgraph-base/trustgraph/schema/services/library.py`: Definiciones de esquema. + +#### Aspectos a Abordar + +"Librarian" tiene los componentes básicos, pero actualmente: +1. La vinculación padre-hijo es de un solo nivel: no hay ayudantes para la travesía de DAG de varios niveles. +>>>>>>> 82edf2d (New md files from RunPod) +2. No hay un vocabulario estándar de tipos de relación (por ejemplo, `derivedFrom`, `extractedFrom`). +3. Los metadatos de procedencia (método de extracción, confianza, posición de fragmento) no están estandarizados. +4. No hay una API de consulta para recorrer toda la cadena de procedencia desde un hecho hasta la fuente. + +<<<<<<< HEAD +## Diseño de flujo de extremo a extremo + +Cada procesador en la canalización sigue un patrón consistente: +Recibe el ID del documento del componente anterior. +Recupera el contenido del bibliotecario. +Produce artefactos secundarios. +Para cada hijo: guarda en el bibliotecario, emite un borde al gráfico, reenvía el ID al componente posterior. + +### Flujos de procesamiento + +Existen dos flujos dependiendo del tipo de documento: + +#### Flujo de documento PDF +======= +## Diseño de Flujo de Extremo a Extremo + +Cada procesador en la canalización sigue un patrón consistente: +Recibe el ID del documento desde el componente anterior. +Recupera el contenido de "Librarian". +Produce artefactos hijos. +Para cada hijo: guarda en "Librarian", emite un borde al grafo, reenvía el ID al componente posterior. + +### Flujos de Procesamiento + +Existen dos flujos dependiendo del tipo de documento: + +#### Flujo de Documentos PDF +>>>>>>> 82edf2d (New md files from RunPod) + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### Flujo de documentos de texto + +<<<<<<< HEAD +Los documentos de texto omiten el extractor de PDF y van directamente al fragmentador: +======= +Los documentos de texto omiten el extractor de PDF y van directamente al procesador de fragmentos: +>>>>>>> 82edf2d (New md files from RunPod) + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +El DAG resultante es un nivel más corto: + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +<<<<<<< HEAD +El diseño se adapta a ambos porque el componente de segmentación trata su entrada de forma genérica; utiliza cualquier ID de documento que reciba como elemento padre, independientemente de si se trata de un documento fuente o de una página. +======= +El diseño se adapta a ambos casos porque el componente de división de texto (chunker) trata su entrada de forma genérica; utiliza cualquier ID de documento que reciba como elemento padre, independientemente de si se trata de un documento fuente o de una página. +>>>>>>> 82edf2d (New md files from RunPod) + +### Esquema de metadatos (PROV-O) + +Los metadatos de procedencia utilizan la ontología W3C PROV-O. Esto proporciona un vocabulario estándar y permite la futura firma/autenticación de los resultados de la extracción. + +<<<<<<< HEAD +#### Conceptos principales de PROV-O + +| Tipo PROV-O | Uso en TrustGraph | +|-------------|------------------| +| `prov:Entity` | Documento, Página, Segmento, Triple, Incrustación | +| `prov:Activity` | Instancias de operaciones de extracción | +| `prov:Agent` | Componentes de TG (extractor de PDF, segmentador, etc.) con versiones | +======= +#### Conceptos básicos de PROV-O + +| Tipo PROV-O | Uso en TrustGraph | +|-------------|------------------| +| `prov:Entity` | Documento, Página, Fragmento, Triple, Incrustación | +| `prov:Activity` | Instancias de operaciones de extracción | +| `prov:Agent` | Componentes de TG (extractor de PDF, componente de división de texto, etc.) con versiones | +>>>>>>> 82edf2d (New md files from RunPod) + +#### Relaciones PROV-O + +| Predicado | Significado | Ejemplo | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | Entidad derivada de otra entidad | Página wasDerivedFrom Documento | +| `prov:wasGeneratedBy` | Entidad generada por una actividad | Página wasGeneratedBy PDFExtractionActivity | +| `prov:used` | Actividad que utiliza una entidad como entrada | PDFExtractionActivity used Documento | +| `prov:wasAssociatedWith` | Actividad realizada por un agente | PDFExtractionActivity wasAssociatedWith tg:PDFExtractor | + +#### Metadatos en cada nivel + +**Documento fuente (emitido por Librarian):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +**Página (emitida por el extractor de PDF):** +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +**Fragmento (emitido por el procesador de fragmentos):** +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**Triple (emitido por el Extractor de Conocimiento):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**Incrustación (almacenada en un almacén de vectores, no en un almacén de triples):** + +Las incrustaciones se almacenan en el almacén de vectores con metadatos, no como triples RDF. Cada registro de incrustación contiene: + +| Campo | Descripción | Ejemplo | +|-------|-------------|---------| +| vector | El vector de incrustación | [0.123, -0.456, ...] | +| entity | URI del nodo que representa la incrustación | `entity:JohnSmith` | +| chunk_id | Fragmento de origen (procedencia) | `chunk:123-1-1` | +| model | Modelo de incrustación utilizado | `text-embedding-ada-002` | +| component_version | Versión del incrustador de TG | `1.0.0` | + +El campo `entity` vincula la incrustación al grafo de conocimiento (URI del nodo). El campo `chunk_id` proporciona la procedencia de vuelta al fragmento de origen, lo que permite el recorrido ascendente del DAG hasta el documento original. + +#### Extensiones del Espacio de Nombres de TrustGraph + +Predicados personalizados dentro del espacio de nombres `tg:` para metadatos específicos de la extracción: + +| Predicado | Dominio | Descripción | +|-----------|--------|-------------| +<<<<<<< HEAD +| `tg:contains` | Subgrafo | Indica un triple contenido en este subgrafo de extracción | +======= +| `tg:contains` | Subgrafo | Apunta a un triple contenido en este subgrafo de extracción | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:pageCount` | Documento | Número total de páginas en el documento de origen | +| `tg:mimeType` | Documento | Tipo MIME del documento de origen | +| `tg:pageNumber` | Página | Número de página en el documento de origen | +| `tg:chunkIndex` | Fragmento | Índice del fragmento dentro del fragmento principal | +| `tg:charOffset` | Fragmento | Desplazamiento de caracteres en el texto principal | +| `tg:charLength` | Fragmento | Longitud del fragmento en caracteres | +| `tg:chunkSize` | Actividad | Tamaño de fragmento configurado | +| `tg:chunkOverlap` | Actividad | Solapamiento configurado entre fragmentos | +| `tg:componentVersion` | Actividad | Versión del componente de TG | +| `tg:llmModel` | Actividad | LLM utilizado para la extracción | +| `tg:ontology` | Actividad | URI de la ontología utilizada para guiar la extracción | +| `tg:embeddingModel` | Actividad | Modelo utilizado para las incrustaciones | +| `tg:sourceText` | Declaración | Texto exacto del cual se extrajo un triple | +| `tg:sourceCharOffset` | Declaración | Desplazamiento de caracteres dentro del fragmento donde comienza el texto de origen | +| `tg:sourceCharLength` | Declaración | Longitud del texto de origen en caracteres | + +<<<<<<< HEAD +#### Inicialización del Vocabulario (Por Colección) +======= +#### Arranque del Vocabulario (Por Colección) +>>>>>>> 82edf2d (New md files from RunPod) + +El grafo de conocimiento es neutral con respecto a la ontología y se inicializa vacío. Cuando se escriben datos de procedencia PROV-O en una colección por primera vez, el vocabulario debe inicializarse con etiquetas RDF para todas las clases y predicados. Esto garantiza una visualización legible por humanos en las consultas y la interfaz de usuario. + +**Clases PROV-O:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**Predicados PROV-O:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**Predicados de TrustGraph:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**Nota de implementación:** Este vocabulario de inicio debe ser idempotente, es decir, seguro de ejecutar varias veces sin crear duplicados. Podría activarse durante el procesamiento inicial de un documento en una colección, o como un paso separado de inicialización de la colección. +======= +**Nota de implementación:** Este proceso de inicialización del vocabulario debe ser idempotente, es decir, seguro de ejecutar varias veces sin crear duplicados. Podría activarse durante el procesamiento inicial de un documento en una colección, o como un paso separado de inicialización de la colección. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Origen de los Sub-Fragmentos (Aspiracional) + +Para un seguimiento de origen más detallado, sería valioso registrar exactamente dónde dentro de un fragmento se extrajo una tripleta. Esto permite: + +Resaltar el texto fuente exacto en la interfaz de usuario. +Verificar la precisión de la extracción en comparación con la fuente. +Depurar la calidad de la extracción a nivel de oración. + +**Ejemplo con seguimiento de posición:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**Ejemplo con rango de texto (alternativa):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**Consideraciones de implementación:** + +La extracción basada en LLM puede no proporcionar naturalmente las posiciones de los caracteres. +<<<<<<< HEAD +Se podría solicitar al LLM que devuelva la oración/frase original junto con las triples extraídas. +======= +Se podría solicitar al LLM que devuelva la oración/frase fuente junto con las triples extraídas. +>>>>>>> 82edf2d (New md files from RunPod) +Alternativamente, se puede realizar un procesamiento posterior para hacer coincidir de forma difusa las entidades extraídas con el texto fuente. +Compromiso entre la complejidad de la extracción y la granularidad de la procedencia. +Puede ser más fácil de lograr con métodos de extracción estructurados que con la extracción de LLM de formato libre. + +Esto se considera una meta a largo plazo; primero se debe implementar la procedencia a nivel de fragmento, y el seguimiento de subfragmentos puede ser una mejora futura si es factible. + +### Modelo de almacenamiento dual + +El DAG de procedencia se construye progresivamente a medida que los documentos fluyen a través de la canalización: + +| Almacén | ¿Qué se almacena | Propósito | +|-------|---------------|---------| +| Bibliotecario | Contenido del documento + enlaces padre-hijo | Recuperación de contenido, eliminación en cascada | +| Gráfico de conocimiento | Bordes padre-hijo + metadatos | Consultas de procedencia, atribución de hechos | + +Ambos almacenes mantienen la misma estructura DAG. El bibliotecario almacena el contenido; el gráfico almacena las relaciones y permite las consultas de recorrido. + +### Principios de diseño clave + +<<<<<<< HEAD +1. **El ID del documento como unidad de flujo**: Los procesadores pasan ID, no contenido. El contenido se recupera del bibliotecario cuando es necesario. + +2. **Emitir una vez en la fuente**: Los metadatos se escriben en el gráfico una vez al inicio del procesamiento, no se repiten en procesos posteriores. +======= +1. **ID del documento como unidad de flujo**: Los procesadores pasan ID, no contenido. El contenido se recupera del bibliotecario cuando es necesario. + +2. **Emitir una vez en la fuente**: Los metadatos se escriben en el gráfico una vez al inicio del procesamiento, no se repiten aguas abajo. +>>>>>>> 82edf2d (New md files from RunPod) + +3. **Patrón de procesador consistente**: Cada procesador sigue el mismo patrón de recepción/recuperación/producción/guardado/emisión/reenvío. + +4. **Construcción progresiva del DAG**: Cada procesador agrega su nivel al DAG. La cadena completa de procedencia se construye de forma incremental. + +<<<<<<< HEAD +5. **Optimización posterior al fragmentador**: Después de la fragmentación, los mensajes contienen tanto el ID como el contenido. Los fragmentos son pequeños (2-4 KB), por lo que incluir el contenido evita viajes de ida y vuelta innecesarios al bibliotecario, al tiempo que preserva la procedencia a través del ID. +======= +5. **Optimización posterior al fragmentador**: Después de la fragmentación, los mensajes contienen tanto el ID como el contenido. Los fragmentos son pequeños (2-4 KB), por lo que incluir el contenido evita viajes de ida y vuelta innecesarios al bibliotecario al tiempo que preserva la procedencia a través del ID. +>>>>>>> 82edf2d (New md files from RunPod) + +## Tareas de implementación + +### Cambios en el bibliotecario + +#### Estado actual + +Inicia el procesamiento de documentos enviando el ID del documento al primer procesador. +<<<<<<< HEAD +No tiene conexión con el almacén de triples; los metadatos se incluyen en los resultados de la extracción. +======= +No hay conexión con el almacén de triples; los metadatos se incluyen en los resultados de la extracción. +>>>>>>> 82edf2d (New md files from RunPod) +`add-child-document` crea enlaces padre-hijo de un solo nivel. +`list-children` devuelve solo los hijos inmediatos. + +#### Cambios requeridos + +**1. Nueva interfaz: Conexión al almacén de triples** + +El bibliotecario debe emitir directamente los bordes de metadatos del documento al gráfico de conocimiento al iniciar el procesamiento. +Agregar un cliente/publicador del almacén de triples al servicio del bibliotecario. +Al iniciar el procesamiento: emitir los metadatos del documento raíz como bordes del gráfico (una vez). + +**2. Vocabulario de tipos de documentos** + +Estandarizar los valores de `document_type` para los documentos hijo: +<<<<<<< HEAD +`source` - documento original cargado. +`page` - página extraída de la fuente (PDF, etc.). +`chunk` - fragmento de texto derivado de la página o la fuente. +======= +`source`: documento original cargado. +`page`: página extraída de la fuente (PDF, etc.). +`chunk`: fragmento de texto derivado de la página o la fuente. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Resumen de cambios de interfaz + +| Interfaz | Cambio | +|-----------|--------| +| Almacén de triples | Nueva conexión de salida: emitir bordes de metadatos del documento | +| Inicio del procesamiento | Emitir metadatos al gráfico antes de reenviar el ID del documento | + +### Cambios en el extractor de PDF + +#### Estado actual + +Recibe el contenido del documento (o transmite documentos grandes). +Extrae texto de las páginas PDF. +Envía el contenido de la página al fragmentador. +No interactúa con el bibliotecario ni con el almacén de triples. + +#### Cambios requeridos + +**1. Nueva interfaz: Cliente del bibliotecario** + +El extractor de PDF debe guardar cada página como un documento hijo en el bibliotecario. +Agregar un cliente del bibliotecario al servicio del extractor de PDF. +Para cada página: llamar a `add-child-document` con padre = ID del documento raíz. + +**2. Nueva interfaz: Conexión al almacén de triples** + +El extractor de PDF debe emitir bordes padre-hijo al gráfico de conocimiento. +Agregar un cliente/publicador del almacén de triples. +Para cada página: emitir un borde que vincule el documento de la página con el documento padre. + +**3. Cambiar el formato de salida** + +En lugar de reenviar el contenido de la página directamente, reenvíe el ID del documento de la página. +<<<<<<< HEAD +El componente "Chunker" recuperará el contenido del "librarian" utilizando el ID. +======= +El componente "Chunker" obtendrá el contenido del "librarian" utilizando el ID. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Resumen de Cambios en la Interfaz + +| Interfaz | Cambio | +|-----------|--------| +| Librarian | Nueva salida: guardar documentos hijos | +| Triple store | Nueva salida: emitir aristas padre-hijo | +| Mensaje de salida | Cambio de contenido a ID de documento | + +### Cambios en el Componente "Chunker" + +#### Estado Actual + +Recibe contenido de página/texto +Lo divide en fragmentos +Reenvía el contenido del fragmento a los procesadores posteriores +No interactúa con el "librarian" ni con el "triple store" + +#### Cambios Requeridos + +**1. Cambiar el manejo de la entrada** + +<<<<<<< HEAD +Recibir el ID del documento en lugar del contenido, y recuperarlo del "librarian". +Agregar un cliente de "librarian" al servicio "chunker" +Recuperar el contenido de la página utilizando el ID del documento +======= +Recibir el ID del documento en lugar del contenido, obtenerlo del "librarian". +Agregar un cliente de "librarian" al servicio "chunker" +Obtener el contenido de la página utilizando el ID del documento +>>>>>>> 82edf2d (New md files from RunPod) + +**2. Nueva interfaz: Cliente de "Librarian" (escritura)** + +Guardar cada fragmento como un documento hijo en el "librarian". +Para cada fragmento: llamar a `add-child-document` con parent = ID del documento de la página + +<<<<<<< HEAD +**3. Nueva interfaz: Conexión con el "Triple store"** + +Emitir aristas padre-hijo al grafo de conocimiento. +Agregar un cliente/publicador de "triple store" +======= +**3. Nueva interfaz: Conexión al "Triple Store"** + +Emitir aristas padre-hijo al grafo de conocimiento. +Agregar un cliente/publicador del "triple store" +>>>>>>> 82edf2d (New md files from RunPod) +Para cada fragmento: emitir una arista que vincule el documento del fragmento con el documento de la página + +**4. Cambiar el formato de salida** + +Reenviar tanto el ID del documento del fragmento como el contenido del fragmento (optimización posterior al componente "chunker"). +<<<<<<< HEAD +Los procesadores posteriores reciben el ID para la trazabilidad y el contenido para trabajar con él +======= +Los procesadores posteriores reciben el ID para la trazabilidad + el contenido para trabajar con él +>>>>>>> 82edf2d (New md files from RunPod) + +#### Resumen de Cambios en la Interfaz + +| Interfaz | Cambio | +|-----------|--------| +| Mensaje de entrada | Cambio de contenido a ID de documento | +<<<<<<< HEAD +| Librarian | Nueva salida (lectura + escritura) - recuperar contenido, guardar documentos hijos | +| Triple store | Nueva salida - emitir aristas padre-hijo | +| Mensaje de salida | Cambio de contenido-único a ID + contenido | + +### Cambios en el Extractor de Conocimiento +======= +| Librarian | Nueva salida (lectura + escritura) - obtener contenido, guardar documentos hijos | +| Triple store | Nueva salida - emitir aristas padre-hijo | +| Mensaje de salida | Cambio de contenido-único a ID + contenido | + +### Cambios en el "Knowledge Extractor" +>>>>>>> 82edf2d (New md files from RunPod) + +#### Estado Actual + +Recibe contenido del fragmento +Extrae triples y embeddings +<<<<<<< HEAD +Los emite al "triple store" y al almacén de "embeddings" +======= +Los emite al "triple store" y al "embedding store" +>>>>>>> 82edf2d (New md files from RunPod) +La relación `subjectOf` apunta al documento de nivel superior (no al fragmento) + +#### Cambios Requeridos + +**1. Cambiar el manejo de la entrada** + +Recibir el ID del fragmento junto con el contenido. +Utilizar el ID del fragmento para la vinculación de trazabilidad (el contenido ya está incluido según la optimización) + +<<<<<<< HEAD +**2. Actualizar la trazabilidad de los triples** +======= +**2. Actualizar la trazabilidad de triples** +>>>>>>> 82edf2d (New md files from RunPod) + +Vincular los triples extraídos al fragmento (no al documento de nivel superior). +Utilizar la reificación para crear una arista que apunte a la arista +Relación `subjectOf`: triple → ID del documento del fragmento +Primer uso del soporte de reificación existente + +<<<<<<< HEAD +**3. Actualizar la trazabilidad de los "embeddings"** + +Vincular los ID de las entidades de "embedding" al fragmento. +Emitir una arista: ID de la entidad de "embedding" → ID del documento del fragmento +======= +**3. Actualizar la trazabilidad de embeddings** + +Vincular los ID de las entidades de embedding al fragmento. +Emitir una arista: ID de la entidad de embedding → ID del documento del fragmento +>>>>>>> 82edf2d (New md files from RunPod) + +#### Resumen de Cambios en la Interfaz + +| Interfaz | Cambio | +|-----------|--------| +<<<<<<< HEAD +| Mensaje de entrada | Se espera el ID del fragmento + contenido (no solo contenido) | +| Triple store | Utilizar la reificación para la trazabilidad de triple → fragmento | +| Trazabilidad de "embeddings" | Vincular ID de entidad → ID de fragmento | +======= +| Mensaje de entrada | Esperar ID del fragmento + contenido (no solo contenido) | +| Triple store | Utilizar la reificación para la trazabilidad de triple → fragmento | +| Trazabilidad de embeddings | Vincular ID de entidad → ID de fragmento | +>>>>>>> 82edf2d (New md files from RunPod) + +## Referencias + +Trazabilidad en tiempo de consulta: `docs/tech-specs/query-time-provenance.md` +Estándar PROV-O para el modelado de trazabilidad +Metadatos de origen existentes en el grafo de conocimiento (necesitan auditoría) diff --git a/docs/tech-specs/extraction-time-provenance.he.md b/docs/tech-specs/extraction-time-provenance.he.md new file mode 100644 index 00000000..c8d6620e --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.he.md @@ -0,0 +1,830 @@ +--- +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. + +## סקירה כללית + +מסמך זה מתעד הערות על מקור המידע בזמן החילוץ לצורך עבודה עתידית על מפרטים. מקור המידע בזמן החילוץ מתעד את "שכבת המקור" - מאיפה הנתונים הגיעו במקור, וכיצד הם חולצו ועובדו. + +זה נפרד ממקור המידע בזמן השאילתה (ראה `query-time-provenance.md`) אשר מתעד את הנימוקים של המערכת. + +## הצהרת בעיה + +### יישום נוכחי + +כיום, מקור המידע פועל באופן הבא: +מטא-נתונים של מסמכים מאוחסנים כמשולשים RDF בגרף הידע. +מזהה מסמך מקשר בין מטא-נתונים למסמך, כך שהמסמך מופיע כצומת בגרף. +כאשר קשרים (יחסים/עובדות) מחולצים ממסמכים, קשר `subjectOf` מקשר את הקשר המחולץ בחזרה למסמך המקור. + +### בעיות בגישה הנוכחית + +1. **טעינת מטא-נתונים חוזרת:** מטא-נתונים של מסמכים מקובצים ונטענים שוב ושוב עם כל אצווה של משולשים המחולצים ממסמך זה. זה בזבוז ומיותר - אותם מטא-נתונים מועברים כחלק מהפלט בכל חילוץ. + +<<<<<<< HEAD +2. **מקור מידע שטחי:** הקשר `subjectOf` הנוכחי מקשר רק עובדות ישירות למסמך הראשי. אין נראות לגבי שרשרת השינויים - מאיזו עמוד הגיעה העובדה, מאיזה חלק, באיזו שיטת חילוץ נעשה שימוש. +======= +2. **מקור מידע שטחי:** הקשר `subjectOf` הנוכחי מקשר רק עובדות ישירות למסמך הראשי. אין נראות לגבי שרשרת השינויים - מאיזו עמוד הגיעה העובדה, מאיזה חלק, באיזו שיטת חילוץ השתמשו. +>>>>>>> 82edf2d (New md files from RunPod) + +### מצב רצוי + +1. **טעינת מטא-נתונים פעם אחת:** מטא-נתונים של מסמכים צריכים להיטען פעם אחת ולהיות מחוברים לצומת המסמך הראשי, ולא לחזור על עצמם עם כל אצווה של משולשים. + +<<<<<<< HEAD +2. **גרף מקור מידע עשיר:** לתפוס את שרשרת השינויים המלאה ממסמך המקור דרך כל הארטיפקטים הביניים ועד לעובדות המחולצות. לדוגמה, טרנספורמציה של מסמך PDF: +======= +2. **גרף מקור מידע עשיר:** לתפוס את שרשרת השינויים המלאה מהמסמך המקור דרך כל הארטיפקטים הביניים ועד לעובדות המחולצות. לדוגמה, טרנספורמציה של מסמך PDF: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +3. **אחסון מאוחד:** גרף המוצא (provenance DAG) מאוחסן באותו גרף ידע כמו הידע שחולץ. זה מאפשר שאילתת מוצא באותה צורה כמו שאילתת ידע - מעקב אחר קשרים לאחור בשרשרת מכל עובדה למיקום המקור המדויק שלה. + +4. **מזהים יציבים:** לכל ארטיפקט ביניים (עמוד, מקטע) יש מזהה יציב כצומת בגרף. + +5. **קישור הורה-ילד:** מסמכים נגזרים מקושרים להוריהם עד למסמך המקור העליון באמצעות סוגי קשרים עקביים. + +6. **הקצאת עובדות מדויקת:** הקשר `subjectOf` בקשרים שחולצו מצביע על ההורה המיידי (מקטע), ולא על מסמך המקור העליון. ניתן לשחזר את כל המוצא על ידי מעבר ב-DAG. + +## תרחישי שימוש + +<<<<<<< HEAD +### UC1: הקצאת מקור בתגובות GraphRAG +======= +### תרחיש שימוש 1: הקצאת מקור בתגובות GraphRAG +>>>>>>> 82edf2d (New md files from RunPod) + +**תרחיש:** משתמש מריץ שאילתה של GraphRAG ומקבל תגובה מהסוכן. + +**תהליך:** +1. משתמש מגיש שאילתה לסוכן GraphRAG. +2. הסוכן שולף עובדות רלוונטיות מגרף הידע כדי לנסח תגובה. +3. בהתאם למפרט המוצא בזמן השאילתה, הסוכן מדווח אילו עובדות תרמו לתגובה. +4. כל עובדה מקושרת למקטע המקור שלה באמצעות גרף המוצא. +5. מקטעים מקושרים לעמודים, עמודים מקושרים למסמכי מקור. + +**תוצאה עבור המשתמש:** הממשק מציג את תגובת מודל השפה הגדול (LLM) יחד עם הקצאת מקור. המשתמש יכול: +לראות אילו עובדות תמכו בתגובה. +לעבור ממקטעים → עמודים → מסמכים. +לעיין במסמכי המקור המקוריים כדי לאמת טענות. +להבין בדיוק מאיפה במסמך (איזה עמוד, איזה חלק) עובדה מסוימת הגיעה. + +**ערך:** משתמשים יכולים לאמת תגובות שנוצרו על ידי AI מול מקורות ראשוניים, ובכך לבנות אמון ולאפשר בדיקת עובדות. + +<<<<<<< HEAD +### UC2: ניפוי באגים של איכות חילוץ + +עובדה נראית שגויה. ניתן לעקוב אחורה דרך מקטע → עמוד → מסמך כדי לראות את הטקסט המקורי. האם זו הייתה שגיאת חילוץ, או שהמקור עצמו היה שגוי? + +### UC3: חילוץ חוזר מצטבר + +מסמך מקור מתעדכן. אילו מקטעים/עובדות נגזרו ממנו? לבטל ולחדש רק את אלה, ולא לעבד הכל מחדש. + +### UC4: מחיקת נתונים / הזכות להיות נשכח + +יש להסיר מסמך מקור (GDPR, סיבות משפטיות וכו'). יש לעבור ב-DAG כדי למצוא ולהסיר את כל העובדות הנגזרות. + +### UC5: פתרון קונפליקטים + +שתי עובדות סותרות אחת את השנייה. ניתן לעקוב אחורה לשני המקורות שלהן כדי להבין מדוע ולהחליט איזו עובדה לתת לה עדיפות (מקור סמכותי יותר, עדכני יותר וכו'). + +### UC6: שקלול סמכות מקור + +למקורות מסוימים יש סמכות רבה יותר מאחרים. ניתן לשקלל או לסנן עובדות בהתאם לסמכות/איכות מסמכי המקור שלהן. + +### UC7: השוואת צינורות חילוץ +======= +### תרחיש שימוש 2: ניפוי באגים של איכות חילוץ + +עובדה נראית שגויה. ניתן לחזור אחורה דרך מקטע → עמוד → מסמך כדי לראות את הטקסט המקורי. האם זו הייתה שגיאת חילוץ, או שהמקור עצמו שגוי? + +### תרחיש שימוש 3: חילוץ חוזר מצטבר + +מסמך מקור מתעדכן. אילו מקטעים/עובדות נגזרו ממנו? לבטל ולחדש רק את אלה, ולא לעבד הכל מחדש. + +### תרחיש שימוש 4: מחיקת נתונים / הזכות להימחק + +יש להסיר מסמך מקור (GDPR, סיבות משפטיות וכו'). יש לעבור ב-DAG כדי למצוא ולהסיר את כל העובדות הנגזרות. + +### תרחיש שימוש 5: פתרון קונפליקטים + +שתי עובדות סותרות אחת את השנייה. ניתן לחזור לשתי העובדות למקורות שלהן כדי להבין מדוע ולהחליט איזו מהן לתת לה עדיפות (מקור סמכותי יותר, עדכני יותר וכו'). + +### תרחיש שימוש 6: שקלול סמכות מקור + +למקורות מסוימים יש סמכות רבה יותר מאחרים. ניתן לשקלל או לסנן עובדות בהתאם לסמכות/איכות מסמכי המקור שלהן. + +### תרחיש שימוש 7: השוואת צינורות חילוץ +>>>>>>> 82edf2d (New md files from RunPod) + +השוואת תוצאות משיטות/גרסאות חילוץ שונות. איזה מחלץ הפיק עובדות טובות יותר מאותו מקור? + +## נקודות אינטגרציה + +### ספרן + +רכיב הספרן כבר מספק אחסון מסמכים עם מזהי מסמכים ייחודיים. מערכת המקור משתלבת בתשתית הקיימת. + +#### יכולות קיימות (שיושמו כבר) + +**קישור מסמכים הורה-ילד:** +`parent_id` שדה ב-`DocumentMetadata` - מקשר מסמך ילד למסמך הורה +`document_type` שדה - ערכים: `"source"` (מקור) או `"extracted"` (נגזר) +`add-child-document` API - יוצר מסמך ילד עם `document_type = "extracted"` אוטומטי +`list-children` API - שולף את כל ילדי מסמך הורה +מחיקה מדורגת - הסרת מסמך הורה מוחקת אוטומטית את כל מסמכי הילד + +**זיהוי מסמכים:** +מזהי מסמכים מוגדרים על ידי הלקוח (לא נוצרים אוטומטית) +מסמכים מאוחסנים לפי מפתח מורכב `(user, document_id)` ב-Cassandra +מזהי אובייקטים (UUIDs) נוצרים באופן פנימי עבור אחסון בלובים + +**תמיכה במטא-נתונים:** +`metadata: list[Triple]` שדה - משולשים RDF עבור מטא-נתונים מובנים +`title`, `comments`, `tags` - מטא-נתונים בסיסיים של מסמך +`time` - חותמת זמן, `kind` - סוג MIME + +**ארכיטקטורת אחסון:** +מטא-נתונים מאוחסנים ב-Cassandra (מרחב מפתחות `librarian`, טבלה `document`) +תוכן מאוחסן ב-MinIO/S3 blob storage (דלי `library`) +העברת תוכן חכמה: מסמכים קטנים מ-2MB משובצים, מסמכים גדולים יותר מועברים + +#### קבצים מרכזיים + +`trustgraph-flow/trustgraph/librarian/librarian.py` - פעולות ליבה של הספרן +`trustgraph-flow/trustgraph/librarian/service.py` - מעבד שירות, טעינת מסמכים +`trustgraph-flow/trustgraph/tables/library.py` - חנות טבלאות Cassandra +`trustgraph-base/trustgraph/schema/services/library.py` - הגדרות סכימה + +#### פערים לטיפול + +ל-ספרן יש את אבני הבניין, אך כרגע: +1. קישור הורה-ילד הוא בעומק של רמה אחת - אין עזרי מעבר DAG מרובי רמות +2. אין אוצר מילים סטנדרטי לסוגי יחסים (לדוגמה, `derivedFrom`, `extractedFrom`) +3. מטא-נתונים של מקור (שיטת חילוץ, רמת אמון, מיקום מקטע) אינם סטנדרטיים +4. אין API שאילתה למעבר על שרשרת המקור המלאה מעובדה חזרה למקור + +## תכנון זרימת עבודה מקצה לקצה + +כל מעבד בצינור עוקב אחר דפוס עקבי: +מקבל מזהה מסמך מהשורה העליונה +שולף תוכן מהספרן +מייצר ארטיפקטים ילדים +עבור כל ילד: שומר בספרן, פולט קצה לגרף, מעביר מזהה לשורה התחתונה + +### זרימות עיבוד + +ישנן שתי זרימות בהתאם לסוג המסמך: + +#### זרימת מסמכי PDF + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### זרימת מסמכי טקסט + +מסמכי טקסט עוקפים את מודל החילוץ של PDF ועוברים ישירות למקטע: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +הגרף המכוון (DAG) המתקבל הוא ברמה אחת קצרה יותר: + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +העיצוב מתאים לשני המקרים מכיוון שהמקטע (chunker) מטפל בקלט שלו באופן כללי - הוא משתמש בכל מזהה מסמך שהוא מקבל כאב, ללא קשר לשאלה האם מדובר במסמך מקור או בעמוד. + +### סכימת מטא-נתונים (PROV-O) + +מטא-נתונים של מקור (Provenance) משתמשים באונטולוגיה W3C PROV-O. זה מספק אוצר מילים סטנדרטי ומאפשר חתימה/אימות עתידי של תוצרי חילוץ. + +#### מושגים מרכזיים ב-PROV-O + +| סוג PROV-O | שימוש ב-TrustGraph | +|-------------|------------------| +| `prov:Entity` | מסמך, עמוד, מקטע, טריפל, הטמעה | +| `prov:Activity` | מופעים של פעולות חילוץ | +| `prov:Agent` | רכיבי TG (תוכנת חילוץ PDF, מקטע, וכו') עם גרסאות | + +#### קשרים ב-PROV-O + +| פרידיקט | משמעות | דוגמה | +|-----------|---------|---------| +<<<<<<< HEAD +| `prov:wasDerivedFrom` | ישות שמקורה בישות אחרת | עמוד היה-מבוסס-על מסמך | +| `prov:wasGeneratedBy` | ישות שנוצרה על ידי פעילות | עמוד נוצר-על-ידי פעולת חילוץ PDF | +| `prov:used` | פעילות השתמשה בישות כקלט | פעולת חילוץ PDF השתמשה במסמך | +| `prov:wasAssociatedWith` | פעילות בוצעה על ידי סוכן | פעולת חילוץ PDF הייתה-קשורה ל-tg:PDFExtractor | +======= +| `prov:wasDerivedFrom` | ישות שמקורה בישות אחרת | עמוד wasDerivedFrom מסמך | +| `prov:wasGeneratedBy` | ישות שנוצרה על ידי פעילות | עמוד wasGeneratedBy PDFExtractionActivity | +| `prov:used` | פעילות השתמשה בישות כקלט | PDFExtractionActivity used Document | +| `prov:wasAssociatedWith` | פעילות בוצעה על ידי סוכן | PDFExtractionActivity wasAssociatedWith tg:PDFExtractor | +>>>>>>> 82edf2d (New md files from RunPod) + +#### מטא-נתונים בכל רמה + +**מסמך מקור (נפלט על ידי הספרן):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +<<<<<<< HEAD +**עמוד (נפלט על ידי מופשט PDF):** +======= +**עמוד (נפלט על ידי מחלץ PDF):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +**חלק (נפלט על ידי מודול החלוקה):** +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**משולש (נפלט על ידי מפיק ידע):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**הטמעה (מאוחסנת במאגר וקטורים, ולא במאגר משולשות):** + +הטמעות מאוחסנות במאגר הווקטורים עם מטא-נתונים, ולא כמשולשות RDF. כל רשומה של הטמעה מכילה: + +| שדה | תיאור | דוגמה | +|-------|-------------|---------| +| וקטור | וקטור ההטמעה | [0.123, -0.456, ...] | +| ישות | מזהה צומת שההטמעה מייצגת | `entity:JohnSmith` | +| מזהה_קטע | קטע מקור (מקור) | `chunk:123-1-1` | +| מודל | מודל הטמעה ששימש | `text-embedding-ada-002` | +| גרסת_רכיב | גרסת הטמעת TG | `1.0.0` | + +השדה `entity` מקשר את ההטמעה לגרף הידע (מזהה צומת). השדה `chunk_id` מספק מידע על המקור חזרה לקטע המקור, ומאפשר מעבר במבנה ה-DAG אל המסמך המקורי. + +#### הרחבות מרחב השמות של TrustGraph + +פרדיקטים מותאמים אישית תחת מרחב השמות `tg:` עבור מטא-נתונים ספציפיים לחילוץ: + +| פרדיקט | תחום | תיאור | +|-----------|--------|-------------| +| `tg:contains` | תת-גרף | מצביע על משולש הכלול בתת-גרף החילוץ הזה | +| `tg:pageCount` | מסמך | מספר כולל של עמודים במסמך המקור | +| `tg:mimeType` | מסמך | סוג MIME של המסמך המקור | +| `tg:pageNumber` | עמוד | מספר עמוד במסמך המקור | +<<<<<<< HEAD +| `tg:chunkIndex` | קטע | אינדקס של קטע בתוך הורה | +| `tg:charOffset` | קטע | התאמה אופסט בטקסט הורה | +| `tg:charLength` | קטע | אורך הקטע בתווים | +| `tg:chunkSize` | פעילות | גודל קטע מוגדר | +| `tg:chunkOverlap` | פעילות | חפיפה מוגדרת בין קטעים | +| `tg:componentVersion` | פעילות | גרסת רכיב TG | +======= +| `tg:chunkIndex` | קטע | אינדקס של קטע בתוך ההורה | +| `tg:charOffset` | קטע | התאמה אופסט בטקסט ההורה | +| `tg:charLength` | קטע | אורך הקטע בתווים | +| `tg:chunkSize` | פעילות | גודל קטע מוגדר | +| `tg:chunkOverlap` | פעילות | חפיפה מוגדרת בין קטעים | +| `tg:componentVersion` | פעילות | גרסה של רכיב TG | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:llmModel` | פעילות | מודל LLM ששימש לחילוץ | +| `tg:ontology` | פעילות | אונטולוגיה ששימשה להכוונת החילוץ | +| `tg:embeddingModel` | פעילות | מודל ששימש להטמעות | +| `tg:sourceText` | הצהרה | הטקסט המדויק ממנו חולצה משולשת | +<<<<<<< HEAD +| `tg:sourceCharOffset` | הצהרה | התאמה אופסט בתוך קטע שבו מתחיל הטקסט המקור | +======= +| `tg:sourceCharOffset` | הצהרה | התאמה אופסט בתוך הקטע שבו מתחיל הטקסט המקור | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:sourceCharLength` | הצהרה | אורך הטקסט המקור בתווים | + +#### אתחול אוצר מילים (לכל אוסף) + +<<<<<<< HEAD +גרף הידע הוא ניטרלי אוטולוגי ומתחיל ריק. בעת כתיבת נתוני provenance של PROV-O לאוסף בפעם הראשונה, יש לאתחל את אוצר המילים עם תגיות RDF עבור כל מחלקות ופרדיקטים. זה מבטיח תצוגה קריאה על ידי בני אדם בשאילתות ובממשק המשתמש. +======= +גרף הידע הוא ניטרלי מבחינת אונטולוגיה ומתחיל ריק. בעת כתיבת נתוני provenance של PROV-O לאוסף בפעם הראשונה, יש לאתחל את אוצר המילים עם תגיות RDF עבור כל מחלקות ופרדיקטים. זה מבטיח תצוגה קריאה על ידי בני אדם בשאילתות ובממשק המשתמש. +>>>>>>> 82edf2d (New md files from RunPod) + +**מחלקות PROV-O:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**נשואים של PROV-O:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**משפטי TrustGraph:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**הערה בנושא יישום:** אוצר המילים הזה צריך להיות בעל תכונה של אידמפוטנטיות - בטוח להפעיל אותו מספר פעמים מבלי ליצור כפילויות. ניתן להפעיל אותו בפעם הראשונה בעיבוד מסמך באוסף, או כשלב נפרד של אתחול אוסף. + +#### מקור של חלקים קטנים (שאפתני) + +לצורך מעקב מקור מדויק יותר, יהיה שימושי לתעד בדיוק מאיפה בתוך חלק קטן נשלפה טריפלט. זה מאפשר: +======= +**הערה בנושא יישום:** אוצר המילים הזה צריך להיות בעל תכונה של "אידמפוטנטיות" - בטוח להפעיל אותו מספר פעמים מבלי ליצור כפילויות. ניתן להפעיל אותו בפעם הראשונה בעיבוד מסמך באוסף, או כשלב נפרד של אתחול אוסף. + +#### מקור (Provenance) של תת-קטע (שאיפה) + +לצורך מעקב מדויק יותר, יהיה מועיל לתעד בדיוק מאיפה בתוך קטע נשלפה טריפלט. זה מאפשר: +>>>>>>> 82edf2d (New md files from RunPod) + +הדגשת הטקסט המדויק ממנו נשלף הטריפלט בממשק המשתמש +אימות דיוק החילוץ מול המקור +ניפוי באגים באיכות החילוץ ברמת המשפט + +**דוגמה עם מעקב מיקום:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**דוגמה עם טווח טקסט (חלופה):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**שיקולי יישום:** + +<<<<<<< HEAD +חילוץ מבוסס מודל שפה גדול (LLM) עשוי שלא לספק באופן טבעי מיקומי תווים. +ניתן לבקש מה-LLM להחזיר את המשפט/הביטוי המקורי יחד עם הטריפלים החילוצים. +לחלופין, ניתן לבצע עיבוד לאחר החילוץ כדי להתאים את הישויות החילוצות בחזרה לטקסט המקור. +איזון בין מורכבות החילוץ ובין רמת הפירוט של מקור המידע. +ייתכן שיהיה קל יותר להשיג זאת באמצעות שיטות חילוץ מובנות מאשר חילוץ חופשי מבוסס LLM. + +זה מסומן כשאיפה - יש ליישם תחילה את מקור המידע ברמת החלקים, כאשר מעקב אחר תת-חלקים הוא שיפור עתידי אם אפשרי. + +### מודל אחסון כפול + +גרף מקור המידע נבנה בהדרגה ככל שהמסמכים עוברים דרך הצינור: + +| אחסון | מה מאוחסן | מטרה | +|-------|---------------|---------| +| ספרן (Librarian) | תוכן מסמך + קישורים הורה-ילד | אחזור תוכן, מחיקה מדורגת | +| גרף ידע (Knowledge Graph) | קצוות הורה-ילד + מטא-נתונים | שאילתות מקור מידע, ייחוס עובדות | + +שני האחסונים שומרים על מבנה גרף זהה. הספרן שומר על התוכן; הגרף שומר על קשרים ומאפשר שאילתות מעבר. + +### עקרונות עיצוב מרכזיים + +1. **מזהה מסמך כיחידת זרימה** - מעבדים מעבירים מזהים, לא תוכן. התוכן נשאב מהספרן בעת הצורך. + +2. **פליטה חד-פעמית במקור** - מטא-נתונים נכתבים לגרף פעם אחת בתחילת העיבוד, ולא חוזרים על עצמם במעלה הצינור. + +3. **תבנית מעבד עקבית** - כל מעבד פועל לפי אותה תבנית של קבלה/שאילתא/יצירה/שמירה/פליטה/העברה. + +4. **בניית גרף הדרגתית** - כל מעבד מוסיף את השכבה שלו לגרף. שרשרת מקור המידע השלמה נבנית בהדרגה. + +5. **אופטימיזציה לאחר חלוקה לחלקים** - לאחר חלוקה לחלקים, הודעות נושאות גם מזהה וגם תוכן. החלקים קטנים (2-4KB), כך שכלול התוכן מונע מעברים מיותרים לספרן תוך שמירה על מקור המידע באמצעות המזהה. +======= +חילוץ מבוסס מודל שפה גדול (LLM) עשוי שלא לספק באופן טבעי מיקומי תווים +ניתן לבקש מה-LLM להחזיר את המשפט/הביטוי המקורי יחד עם הטריפלים החולצים +לחלופין, ניתן לבצע עיבוד לאחר החילוץ כדי להתאים את הישויות החולצות בחזרה לטקסט המקור +פשרה בין מורכבות החילוץ וגרנולריות המקור +ייתכן שיהיה קל יותר להשיג זאת באמצעות שיטות חילוץ מובנות מאשר חילוץ LLM חופשי + +זה מסומן כשאיפה - יש ליישם תחילה את המקור הבסיסי ברמת החלקים, כאשר מעקב אחר תת-חלקים הוא שיפור עתידי אם זה אפשרי. + +### מודל אחסון כפול + +גרף המקור נבנה בהדרגה ככל שהמסמכים עוברים דרך הצינור: + +| חנות | מה מאוחסן | מטרה | +|-------|---------------|---------| +| ספרן | תוכן מסמך + קישורים הורה-ילד | אחזור תוכן, מחיקה מדורגת | +| גרף ידע | קצוות הורה-ילד + מטא-נתונים | שאילתות מקור, הקצאת עובדות | + +שתי החנויות שומרות על מבנה גרף זהה. הספרן מחזיק בתוכן; הגרף מחזיק ביחסים ומאפשר שאילתות ניווט. + +### עקרונות עיצוב מרכזיים + +1. **מזהה מסמך כיחידת זרימה** - מעבדים מעבירים מזהים, לא תוכן. תוכן נשאב מהספרן בעת הצורך. + +2. **פליטה פעם אחת במקור** - מטא-נתונים נכתבים לגרף פעם אחת כאשר עיבוד מתחיל, ולא חוזרים על עצמם במורד הזרם. + +3. **דפוס מעבד עקבי** - כל מעבד עוקב אחר דפוס קבלה/שאילתא/יצירה/שמירה/פליטה/העברה זהה. + +4. **בניית גרף הדרגתית** - כל מעבד מוסיף את השכבה שלו לגרף. שרשרת המקור השלמה נבנית באופן מצטבר. + +5. **אופטימיזציה לאחר חלוקה לחלקים** - לאחר חלוקה לחלקים, הודעות נושאות גם מזהה וגם תוכן. החלקים קטנים (2-4KB), כך שכלול התוכן נמנע ממסעות הלוך ושוב מיותרים לספרן תוך שמירה על המקור באמצעות המזהה. +>>>>>>> 82edf2d (New md files from RunPod) + +## משימות יישום + +### שינויים בספרן + +#### מצב נוכחי + +<<<<<<< HEAD +מתחיל עיבוד מסמכים על ידי שליחת מזהה מסמך למעבד הראשון. +אין חיבור למאגר טריפלים - מטא-נתונים נכללים בפלט החילוץ. +`add-child-document` יוצר קישורים הורה-ילד ברמה אחת. +`list-children` מחזיר רק ילדים מיידיים. +======= +מתחיל עיבוד מסמכים על ידי שליחת מזהה מסמך למעבד הראשון +אין חיבור למאגר טריפלים - מטא-נתונים מקובצים עם פלטי חילוץ +`add-child-document` יוצר קישורים הורה-ילד חד-שכבתיים +`list-children` מחזיר רק ילדים מיידיים +>>>>>>> 82edf2d (New md files from RunPod) + +#### שינויים נדרשים + +**1. ממשק חדש: חיבור למאגר טריפלים** + +<<<<<<< HEAD +הספרן צריך לפלוט קצוות מטא-נתונים של מסמכים ישירות לגרף הידע בעת התחלת העיבוד. +הוספת לקוח/מפרסם של מאגר טריפלים לשירות הספרן. +בעת התחלת עיבוד: פליטת מטא-נתונים של מסמך השורש כקצוות גרף (פעם אחת). + +**2. אוצר מילים של סוגי מסמכים** + +סטנדרטיזציה של ערכים `document_type` עבור מסמכי ילד: +`source` - מסמך שהועלה במקור. +`page` - עמוד שחולץ מהמקור (PDF, וכו'). +`chunk` - חלק טקסט שמקורו בעמוד או במקור. + +#### סיכום שינויים בממשק + +| ממשק | שינוי | +|-----------|--------| +| מאגר טריפלים | חיבור יוצא חד - פליטת קצוות מטא-נתונים של מסמכים | +| התחלת עיבוד | פליטת מטא-נתונים לגרף לפני העברת מזהה מסמך | +======= +הספרן צריך לפלוט קצוות מטא-נתונים של מסמכים ישירות לגרף הידע בעת התחלת עיבוד. +הוסף לקוח/מפרסם של מאגר טריפלים לשירות הספרן +בעת התחלת עיבוד: פלט מטא-נתונים של מסמך שורש כקצוות גרף (פעם אחת) + +**2. אוצר מילים של סוגי מסמכים** + +תקנן ערכים של `document_type` עבור מסמכי ילד: +`source` - מסמך שהועלה במקור +`page` - עמוד שחולץ מהמקור (PDF, וכו') +`chunk` - חלק טקסט שמקורו בעמוד או במקור + +#### סיכום שינויי ממשק + +| ממשק | שינוי | +|-----------|--------| +| מאגר טריפלים | חיבור יוצא חד - פלט קצוות מטא-נתונים של מסמכים | +| התחלת עיבוד | פלט מטא-נתונים לגרף לפני העברת מזהה מסמך | +>>>>>>> 82edf2d (New md files from RunPod) + +### שינויים בחולץ PDF + +#### מצב נוכחי + +<<<<<<< HEAD +מקבל תוכן מסמך (או זורם מסמכים גדולים). +מחלץ טקסט מעמודי PDF. +מעביר תוכן עמוד לחולץ חלקים. +אין אינטראקציה עם הספרן או מאגר הטריפלים. +======= +מקבל תוכן מסמך (או זורם מסמכים גדולים) +מחלץ טקסט מעמודי PDF +מעביר תוכן עמוד לחולץ +אין אינטראקציה עם הספרן או מאגר הטריפלים +>>>>>>> 82edf2d (New md files from RunPod) + +#### שינויים נדרשים + +**1. ממשק חדש: לקוח ספרן** + +חולץ PDF צריך לשמור כל עמוד כמסמך ילד בספרן. +<<<<<<< HEAD +הוספת לקוח ספרן לשירות חולץ PDF. +עבור כל עמוד: קריאה ל-`add-child-document` עם מזהה הורה = מזהה מסמך השורש. +======= +הוסף לקוח ספרן לשירות חולץ PDF +עבור כל עמוד: התקשר ל-`add-child-document` עם parent = מזהה מסמך שורש +>>>>>>> 82edf2d (New md files from RunPod) + +**2. ממשק חדש: חיבור למאגר טריפלים** + +חולץ PDF צריך לפלוט קצוות הורה-ילד לגרף הידע. +<<<<<<< HEAD +הוספת לקוח/מפרסם של מאגר טריפלים. +עבור כל עמוד: פליטת קצה המקשר עמוד מסמך למסמך הורה. + +**3. שינוי פורמט פלט** +פלט חוזה (יש לעקוב בדיוק אחר הפורמט הבא). +======= +הוסף לקוח/מפרסם של מאגר טריפלים +עבור כל עמוד: פלט קצה המקשר את מסמך העמוד למסמך הורה + +**3. שנה פורמט פלט** +פלט חוזה (יש לעקוב אחר הפורמט המדויק). +>>>>>>> 82edf2d (New md files from RunPod) +במקום להעביר ישירות את תוכן העמוד, יש להעביר את מזהה המסמך של העמוד. +ה-Chunker ישלוף את התוכן מה-librarian באמצעות המזהה. + +#### סיכום שינויים בממשק + +| ממשק | שינוי | +|-----------|--------| +| Librarian | יציאה חדשה - שמירת מסמכים ילדים | +| Triple store | יציאה חדשה - פליטת קשרים הורה-ילד | +| הודעת פלט | שינוי מתוכן למזהה מסמך | + +### שינויים ב-Chunker + +#### מצב נוכחי + +מקבל תוכן עמוד/טקסט +מחלק לחלקים +מעביר את תוכן החלק למעבדים downstream +אין אינטראקציה עם ה-librarian או ה-triple store + +#### שינויים נדרשים + +**1. שינוי טיפול בקלט** + +<<<<<<< HEAD +לקבל מזהה מסמך במקום תוכן, לשלוף מה-librarian. +להוסיף לקוח librarian לשירות ה-chunker +לשלוף תוכן עמוד באמצעות מזהה מסמך + +**2. ממשק חדש: לקוח Librarian (כתיבה)** + +לשמור כל חלק כמסמך ילד ב-librarian. +עבור כל חלק: לקרוא לפונקציה `add-child-document` עם parent = מזהה מסמך העמוד + +**3. ממשק חדש: חיבור ל-Triple store** + +לפלוט קשרים הורה-ילד לגרף הידע. +להוסיף לקוח/מפרסם triple store +עבור כל חלק: לפלוט קשר המקשר בין מסמך החלק למסמך העמוד + +**4. שינוי פורמט פלט** + +להעביר גם את מזהה מסמך החלק וגם את תוכן החלק (אופטימיזציה לאחר ה-chunker). +מעבדים downstream מקבלים מזהה לצורך מעקב מקור + תוכן לעבודה איתו +======= +יש לקבל מזהה מסמך במקום תוכן, ולשלוף אותו מה-librarian. +יש להוסיף לקוח librarian לשירות ה-chunker +יש לשלוף את תוכן העמוד באמצעות מזהה המסמך + +**2. ממשק חדש: לקוח Librarian (כתיבה)** + +יש לשמור כל חלק כמסמך ילד ב-librarian. +עבור כל חלק: יש לקרוא ל-`add-child-document` עם parent = מזהה מסמך העמוד + +**3. ממשק חדש: חיבור ל-Triple store** + +יש לפלוט קשרים הורה-ילד לגרף הידע. +יש להוסיף לקוח/מפרסם triple store +עבור כל חלק: יש לפלוט קשר המקשר בין מסמך החלק למסמך העמוד + +**4. שינוי פורמט פלט** + +יש להעביר גם את מזהה מסמך החלק וגם את תוכן החלק (אופטימיזציה לאחר חלוקה). +מעבדים downstream מקבלים מזהה לצורך מעקב מקור + תוכן לעבודה +>>>>>>> 82edf2d (New md files from RunPod) + +#### סיכום שינויים בממשק + +| ממשק | שינוי | +|-----------|--------| +| הודעת קלט | שינוי מתוכן למזהה מסמך | +| Librarian | יציאה חדשה (קריאה + כתיבה) - שליפת תוכן, שמירת מסמכים ילדים | +| Triple store | יציאה חדשה - פליטת קשרים הורה-ילד | +<<<<<<< HEAD +| הודעת פלט | שינוי מתוכן בלבד ל-ID + תוכן | +======= +| הודעת פלט | שינוי מתוכן בלבד ל-מזהה + תוכן | +>>>>>>> 82edf2d (New md files from RunPod) + +### שינויים ב-Knowledge Extractor + +#### מצב נוכחי + +<<<<<<< HEAD +מקבל תוכן חלק +======= +מקבל תוכן של חלק +>>>>>>> 82edf2d (New md files from RunPod) +מחלץ טריפל ו-embeddings +פולט ל-triple store ול-embedding store +`subjectOf` הקשר מצביע למסמך ברמה העליונה (ולא לחלק) + +#### שינויים נדרשים + +**1. שינוי טיפול בקלט** + +<<<<<<< HEAD +לקבל מזהה מסמך חלק יחד עם התוכן. +להשתמש במזהה החלק לצורך קישור מעקב מקור (תוכן כלול כבר בהתאם לאופטימיזציה) + +**2. עדכון מעקב טריפל** + +לקשר טריפל מחולץ לחלק (ולא למסמך ברמה העליונה). +להשתמש ב-reification ליצירת קשר המצביע לקשר +`subjectOf` הקשר: טריפל → מזהה מסמך חלק +======= +יש לקבל מזהה מסמך של חלק יחד עם התוכן. +יש להשתמש במזהה החלק לצורך קישור מעקב מקור (תוכן כלול כבר בהתאם לאופטימיזציה) + +**2. עדכון מעקב טריפל** + +יש לקשר טריפל מחולץ לחלק (ולא למסמך ברמה העליונה). +יש להשתמש ב-reification ליצירת קשר המצביע לקשר +`subjectOf` קשר: טריפל → מזהה מסמך של חלק +>>>>>>> 82edf2d (New md files from RunPod) +שימוש ראשון בתמיכה קיימת ב-reification + +**3. עדכון מעקב embedding** + +<<<<<<< HEAD +לקשר מזהי ישויות embedding לחלק. +לפלוט קשר: מזהה ישות embedding → מזהה מסמך חלק +======= +יש לקשר מזהי ישויות embedding לחלק. +יש לפלוט קשר: מזהה ישות embedding → מזהה מסמך של חלק +>>>>>>> 82edf2d (New md files from RunPod) + +#### סיכום שינויים בממשק + +| ממשק | שינוי | +|-----------|--------| +| הודעת קלט | מצפים למזהה חלק + תוכן (ולא רק תוכן) | +<<<<<<< HEAD +| Triple store | להשתמש ב-reification למעקב טריפל → חלק | +| מעקב embedding | לקשר מזהה ישות → מזהה חלק | +======= +| Triple store | שימוש ב-reification למעקב טריפל → חלק | +| מעקב embedding | קישור מזהה ישות → מזהה חלק | +>>>>>>> 82edf2d (New md files from RunPod) + +## הפניות + +מעקב בזמן שאילתה: `docs/tech-specs/query-time-provenance.md` +תקן PROV-O למודל מעקב מקור +מטא-נתונים קיימים ממקור בגרף הידע (דורש ביקורת) diff --git a/docs/tech-specs/extraction-time-provenance.hi.md b/docs/tech-specs/extraction-time-provenance.hi.md new file mode 100644 index 00000000..99d78b41 --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.hi.md @@ -0,0 +1,767 @@ +--- +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. + +## अवलोकन + +यह दस्तावेज़ भविष्य के विनिर्देशन कार्य के लिए निष्कर्षण-समय के प्रमाण पर नोट्स एकत्र करता है। निष्कर्षण-समय का प्रमाण "स्रोत परत" को रिकॉर्ड करता है - डेटा मूल रूप से कहाँ से आया, इसे कैसे निकाला और रूपांतरित किया गया। + +यह क्वेरी-समय के प्रमाण (देखें `query-time-provenance.md`) से अलग है, जो एजेंट तर्क को रिकॉर्ड करता है। + +## समस्या विवरण + +### वर्तमान कार्यान्वयन + +वर्तमान में, प्रमाण इस प्रकार काम करता है: +दस्तावेज़ मेटाडेटा को ज्ञान ग्राफ में RDF ट्रिपल के रूप में संग्रहीत किया जाता है +एक दस्तावेज़ आईडी मेटाडेटा को दस्तावेज़ से जोड़ती है, इसलिए दस्तावेज़ ग्राफ में एक नोड के रूप में दिखाई देता है +जब दस्तावेज़ों से किनारे (संबंध/तथ्य) निकाले जाते हैं, तो एक `subjectOf` संबंध निकाले गए किनारे को स्रोत दस्तावेज़ से जोड़ता है + +### वर्तमान दृष्टिकोण की समस्याएं + +<<<<<<< HEAD +1. **दोहरा मेटाडेटा लोडिंग:** दस्तावेज़ मेटाडेटा को प्रत्येक दस्तावेज़ से निकाले गए ट्रिपल बैच के साथ बार-बार बंडल किया जाता है और लोड किया जाता है। यह अनावश्यक और दोहराव वाला है - समान मेटाडेटा प्रत्येक निष्कर्षण आउटपुट के साथ पेलोड के रूप में यात्रा करता है। + +2. **उथला प्रमाण:** वर्तमान `subjectOf` संबंध केवल तथ्यों को सीधे शीर्ष-स्तरीय दस्तावेज़ से जोड़ता है। परिवर्तन श्रृंखला में कोई दृश्यता नहीं है - तथ्य किस पृष्ठ से आया, किस भाग से, किस निष्कर्षण विधि का उपयोग किया गया था। +======= +1. **दोहरा मेटाडेटा लोडिंग:** दस्तावेज़ मेटाडेटा को प्रत्येक दस्तावेज़ से निकाले गए ट्रिपल के प्रत्येक बैच के साथ बार-बार बंडल किया जाता है और लोड किया जाता है। यह अनावश्यक और दोहराव वाला है - समान मेटाडेटा प्रत्येक निष्कर्षण आउटपुट के साथ पेलोड के रूप में यात्रा करता है। + +2. **उथला प्रमाण:** वर्तमान `subjectOf` संबंध केवल तथ्यों को सीधे शीर्ष-स्तरीय दस्तावेज़ से जोड़ता है। परिवर्तन श्रृंखला में कोई दृश्यता नहीं है - तथ्य किस पृष्ठ से आया, किस खंड से, किस निष्कर्षण विधि का उपयोग किया गया था। +>>>>>>> 82edf2d (New md files from RunPod) + +### वांछित स्थिति + +1. **मेटाडेटा को एक बार लोड करें:** दस्तावेज़ मेटाडेटा को एक बार लोड किया जाना चाहिए और शीर्ष-स्तरीय दस्तावेज़ नोड से जोड़ा जाना चाहिए, न कि प्रत्येक ट्रिपल बैच के साथ दोहराया जाना चाहिए। + +<<<<<<< HEAD +2. **समृद्ध प्रमाण DAG:** स्रोत दस्तावेज़ से सभी मध्यवर्ती कलाकृतियों से लेकर निकाले गए तथ्यों तक, संपूर्ण परिवर्तन श्रृंखला को कैप्चर करें। उदाहरण के लिए, एक PDF दस्तावेज़ रूपांतरण: +======= +2. **समृद्ध प्रमाण DAG:** स्रोत दस्तावेज़ से सभी मध्यवर्ती कलाकृतियों से लेकर निकाले गए तथ्यों तक, पूर्ण परिवर्तन श्रृंखला को कैप्चर करें। उदाहरण के लिए, एक PDF दस्तावेज़ रूपांतरण: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +<<<<<<< HEAD +3. **एकीकृत भंडारण:** उत्पत्ति (provenance) DAG को उसी ज्ञान ग्राफ में संग्रहीत किया जाता है जैसे कि निकाले गए ज्ञान को। यह उत्पत्ति को ज्ञान की तरह ही क्वेरी करने की अनुमति देता है - किसी भी तथ्य से लेकर उसके सटीक स्रोत स्थान तक, श्रृंखला में किनारों का पालन करके। + +4. **स्थिर आईडी:** प्रत्येक मध्यवर्ती कलाकृति (पेज, चंक) का ग्राफ में एक नोड के रूप में एक स्थिर आईडी होता है। + +5. **पैरेंट-चाइल्ड लिंकिंग:** व्युत्पन्न दस्तावेज़ों को सुसंगत संबंध प्रकारों का उपयोग करके शीर्ष-स्तरीय स्रोत दस्तावेज़ तक उनके माता-पिता से जोड़ा जाता है। +======= +3. **एकीकृत भंडारण:** उत्पत्ति (provenance) DAG को उसी ज्ञान ग्राफ में संग्रहीत किया जाता है जैसे कि निकाले गए ज्ञान को। यह उत्पत्ति को ज्ञान की तरह ही क्वेरी करने की अनुमति देता है - किसी भी तथ्य से लेकर उसके सटीक स्रोत स्थान तक, श्रृंखला में वापस किनारों का पालन करना। + +4. **स्थिर आईडी:** प्रत्येक मध्यवर्ती कलाकृति (पेज, चंक) का ग्राफ में एक नोड के रूप में एक स्थिर आईडी होता है। + +5. **माता-पिता-बच्चे संबंध:** व्युत्पन्न दस्तावेज़ों को सुसंगत संबंध प्रकारों का उपयोग करके शीर्ष-स्तरीय स्रोत दस्तावेज़ तक उनके माता-पिता से जोड़ा जाता है। +>>>>>>> 82edf2d (New md files from RunPod) + +6. **सटीक तथ्यattribution:** निकाले गए किनारों पर `subjectOf` संबंध तत्काल माता-पिता (चंक) की ओर इशारा करता है, न कि शीर्ष-स्तरीय दस्तावेज़ की ओर। पूर्ण उत्पत्ति को DAG के माध्यम से ऊपर की ओर ट्रैवर्स करके पुनर्प्राप्त किया जाता है। + +## उपयोग के मामले + +### UC1: GraphRAG प्रतिक्रियाओं में स्रोत attribution + +<<<<<<< HEAD +**परिदृश्य:** एक उपयोगकर्ता GraphRAG क्वेरी चलाता है और एजेंट से एक प्रतिक्रिया प्राप्त करता है। + +**प्रवाह:** +1. उपयोगकर्ता GraphRAG एजेंट को एक क्वेरी सबमिट करता है +2. एजेंट प्रतिक्रिया तैयार करने के लिए ज्ञान ग्राफ से प्रासंगिक तथ्यों को पुनर्प्राप्त करता है +3. क्वेरी-टाइम provenance विनिर्देश के अनुसार, एजेंट उन तथ्यों की रिपोर्ट करता है जिन्होंने प्रतिक्रिया में योगदान दिया +4. प्रत्येक तथ्य provenance DAG के माध्यम से अपने स्रोत चंक से जुड़ा होता है +5. चंक पृष्ठों से जुड़ते हैं, पृष्ठ स्रोत दस्तावेज़ों से जुड़ते हैं + +**उपयोगकर्ता अनुभव परिणाम:** इंटरफ़ेस LLM प्रतिक्रिया के साथ स्रोत attribution प्रदर्शित करता है। उपयोगकर्ता: +प्रतिक्रिया का समर्थन करने वाले तथ्यों को देख सकते हैं +तथ्यों → चंक → पृष्ठ → दस्तावेज़ से ड्रिल डाउन कर सकते हैं +दावों को सत्यापित करने के लिए मूल स्रोत दस्तावेज़ों की समीक्षा कर सकते हैं +यह समझ सकते हैं कि एक तथ्य दस्तावेज़ में कहाँ से (किस पृष्ठ, किस अनुभाग से) उत्पन्न हुआ था +======= +**परिदृश्य:** एक उपयोगकर्ता GraphRAG क्वेरी चलाता है और एजेंट से प्रतिक्रिया प्राप्त करता है। + +**प्रक्रिया:** +1. उपयोगकर्ता GraphRAG एजेंट को एक क्वेरी सबमिट करता है। +2. एजेंट प्रतिक्रिया तैयार करने के लिए ज्ञान ग्राफ से प्रासंगिक तथ्यों को पुनः प्राप्त करता है। +3. क्वेरी-समय provenance विनिर्देश के अनुसार, एजेंट उन तथ्यों की रिपोर्ट करता है जिन्होंने प्रतिक्रिया में योगदान दिया। +4. प्रत्येक तथ्य अपने स्रोत चंक से provenance DAG के माध्यम से जुड़ा होता है। +5. चंक पृष्ठों से जुड़े होते हैं, पृष्ठ स्रोत दस्तावेज़ों से जुड़े होते हैं। + +**उपयोगकर्ता अनुभव परिणाम:** इंटरफ़ेस LLM प्रतिक्रिया के साथ स्रोत attribution प्रदर्शित करता है। उपयोगकर्ता निम्न कार्य कर सकते हैं: +प्रतिक्रिया का समर्थन करने वाले तथ्यों को देखें। +तथ्यों → चंक → पृष्ठ → दस्तावेज़ से नीचे ड्रिल करें। +दावों को सत्यापित करने के लिए मूल स्रोत दस्तावेज़ों की समीक्षा करें। +समझें कि एक तथ्य दस्तावेज़ में (किस पृष्ठ पर, किस अनुभाग में) से उत्पन्न हुआ था। +>>>>>>> 82edf2d (New md files from RunPod) + +**मूल्य:** उपयोगकर्ता AI-जनित प्रतिक्रियाओं को प्राथमिक स्रोतों के विरुद्ध सत्यापित कर सकते हैं, जिससे विश्वास बढ़ता है और तथ्य-जांच सक्षम होती है। + +### UC2: निष्कर्षण गुणवत्ता का डिबगिंग + +एक तथ्य गलत दिखता है। मूल पाठ देखने के लिए चंक → पृष्ठ → दस्तावेज़ के माध्यम से वापस ट्रेस करें। क्या यह एक खराब निष्कर्षण था, या क्या स्रोत स्वयं गलत था? + +### UC3: वृद्धिशील पुन: निष्कर्षण + +<<<<<<< HEAD +स्रोत दस्तावेज़ अपडेट किया गया है। किन चंक/तथ्यों को इससे व्युत्पन्न किया गया था? केवल उन चंक/तथ्यों को अमान्य करें और पुन: उत्पन्न करें, न कि सब कुछ को पुन: संसाधित करें। +======= +स्रोत दस्तावेज़ अपडेट किया गया है। किन चंक/तथ्यों को इससे व्युत्पन्न किया गया था? केवल उन चंक को अमान्य करें और पुन: उत्पन्न करें, न कि सब कुछ को फिर से संसाधित करें। +>>>>>>> 82edf2d (New md files from RunPod) + +### UC4: डेटा हटाना / भुलाए जाने का अधिकार + +एक स्रोत दस्तावेज़ को हटाया जाना चाहिए (GDPR, कानूनी, आदि)। सभी व्युत्पन्न तथ्यों को खोजने और हटाने के लिए DAG को पार करें। + +### UC5: संघर्ष समाधान + +दो तथ्य एक-दूसरे का खंडन करते हैं। कारण को समझने और यह तय करने के लिए कि किस पर भरोसा करना है (अधिक आधिकारिक स्रोत, अधिक हालिया, आदि), दोनों को उनके स्रोतों तक वापस ट्रेस करें। + +### UC6: स्रोत प्राधिकरण भार + +कुछ स्रोत दूसरों की तुलना में अधिक आधिकारिक होते हैं। तथ्यों को उनके मूल दस्तावेज़ों के प्राधिकरण/गुणवत्ता के आधार पर भारित या फ़िल्टर किया जा सकता है। + +### UC7: निष्कर्षण पाइपलाइन तुलना + +<<<<<<< HEAD +विभिन्न निष्कर्षण विधियों/संस्करणों से आउटपुट की तुलना करें। किस निष्कर्षण ने समान स्रोत से बेहतर तथ्य उत्पन्न किए? +======= +विभिन्न निष्कर्षण विधियों/संस्करणों से प्राप्त परिणामों की तुलना करें। किस निष्कर्षण ने समान स्रोत से बेहतर तथ्य उत्पन्न किए? +>>>>>>> 82edf2d (New md files from RunPod) + +## एकीकरण बिंदु + +### लाइब्रेरियन + +लाइब्रेरियन घटक पहले से ही अद्वितीय दस्तावेज़ आईडी के साथ दस्तावेज़ भंडारण प्रदान करता है। प्रोवेनेंस सिस्टम इस मौजूदा बुनियादी ढांचे के साथ एकीकृत होता है। + +#### मौजूदा क्षमताएं (पहले से लागू) + +**पैरेंट-चाइल्ड दस्तावेज़ लिंकिंग:** +`parent_id` फ़ील्ड `DocumentMetadata` में - चाइल्ड को पैरेंट दस्तावेज़ से जोड़ता है +`document_type` फ़ील्ड - मान: `"source"` (मूल) या `"extracted"` (व्युत्पन्न) +`add-child-document` एपीआई - स्वचालित `document_type = "extracted"` के साथ चाइल्ड दस्तावेज़ बनाता है +`list-children` एपीआई - एक पैरेंट दस्तावेज़ के सभी चाइल्ड को पुनः प्राप्त करता है +<<<<<<< HEAD +कैस्केड डिलीशन - एक पैरेंट को हटाने से स्वचालित रूप से सभी चाइल्ड दस्तावेज़ हटा दिए जाते हैं +======= +कैस्केड डिलीशन - एक पैरेंट को हटाने से स्वचालित रूप से सभी चाइल्ड दस्तावेज़ हट जाते हैं +>>>>>>> 82edf2d (New md files from RunPod) + +**दस्तावेज़ पहचान:** +दस्तावेज़ आईडी क्लाइंट द्वारा निर्दिष्ट हैं (स्वचालित रूप से उत्पन्न नहीं) +दस्तावेज़ों को कैसेंड्रा में समग्र `(user, document_id)` द्वारा कुंजीबद्ध किया जाता है +ऑब्जेक्ट आईडी (UUID) आंतरिक रूप से ब्लब स्टोरेज के लिए उत्पन्न होते हैं + +**मेटाडेटा समर्थन:** +`metadata: list[Triple]` फ़ील्ड - संरचित मेटाडेटा के लिए आरडीएफ ट्रिपल +`title`, `comments`, `tags` - बुनियादी दस्तावेज़ मेटाडेटा +`time` - टाइमस्टैम्प, `kind` - एमआईएमई प्रकार + +**भंडारण आर्किटेक्चर:** +मेटाडेटा कैसेंड्रा में संग्रहीत है (`librarian` कीस्पेस, `document` टेबल) +सामग्री MinIO/S3 ब्लब स्टोरेज में संग्रहीत है (`library` बकेट) +<<<<<<< HEAD +स्मार्ट सामग्री वितरण: 2MB से कम दस्तावेज़ एम्बेडेड हैं, बड़े दस्तावेज़ स्ट्रीम किए जाते हैं +======= +स्मार्ट सामग्री वितरण: 2MB से छोटे दस्तावेज़ एम्बेडेड होते हैं, बड़े दस्तावेज़ स्ट्रीम किए जाते हैं +>>>>>>> 82edf2d (New md files from RunPod) + +#### मुख्य फाइलें + +`trustgraph-flow/trustgraph/librarian/librarian.py` - मुख्य लाइब्रेरियन ऑपरेशन +`trustgraph-flow/trustgraph/librarian/service.py` - सर्विस प्रोसेसर, दस्तावेज़ लोडिंग +`trustgraph-flow/trustgraph/tables/library.py` - कैसेंड्रा टेबल स्टोर +`trustgraph-base/trustgraph/schema/services/library.py` - स्कीमा परिभाषाएं + +#### संबोधित करने योग्य कमियां + +लाइब्रेरियन में बिल्डिंग ब्लॉक्स हैं लेकिन वर्तमान में: +1. पैरेंट-चाइल्ड लिंकिंग एक स्तर गहरा है - मल्टी-लेवल डीएजी ट्रैवर्सल हेल्पर नहीं हैं +2. कोई मानक संबंध प्रकार शब्दावली नहीं (जैसे, `derivedFrom`, `extractedFrom`) +3. प्रोवेनेंस मेटाडेटा (निष्कर्षण विधि, आत्मविश्वास, चंक स्थिति) मानकीकृत नहीं है +4. तथ्य से स्रोत तक संपूर्ण प्रोवेनेंस श्रृंखला को पार करने के लिए कोई क्वेरी एपीआई नहीं है + +## एंड-टू-एंड फ्लो डिज़ाइन + +पाइपलाइन में प्रत्येक प्रोसेसर एक सुसंगत पैटर्न का पालन करता है: +अपस्ट्रीम से दस्तावेज़ आईडी प्राप्त करें +लाइब्रेरियन से सामग्री प्राप्त करें +चाइल्ड आर्टिफैक्ट उत्पन्न करें +प्रत्येक चाइल्ड के लिए: लाइब्रेरियन में सहेजें, ग्राफ में एज उत्सर्जित करें, आईडी को डाउनस्ट्रीम पर अग्रेषित करें + +### प्रोसेसिंग फ्लो + +दस्तावेज़ के प्रकार के आधार पर दो फ्लो हैं: + +#### पीडीएफ दस्तावेज़ फ्लो + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### पाठ दस्तावेज़ प्रवाह + +पाठ दस्तावेज़ पीडीएफ एक्सट्रैक्टर को छोड़ देते हैं और सीधे चंकर पर जाते हैं: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +<<<<<<< HEAD +परिणामी निर्देशित एसाइक्लिक ग्राफ (DAG) एक स्तर छोटा होता है: +======= +परिणामी DAG एक स्तर छोटा होता है: +>>>>>>> 82edf2d (New md files from RunPod) + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +डिज़ाइन दोनों को समायोजित करता है क्योंकि चंकर अपने इनपुट को सामान्य रूप से संसाधित करता है - यह जो भी दस्तावेज़ आईडी प्राप्त करता है, उसे पैरेंट के रूप में उपयोग करता है, चाहे वह स्रोत दस्तावेज़ हो या पृष्ठ। + +### मेटाडेटा स्कीमा (PROV-O) + +प्रामाणिकता मेटाडेटा W3C PROV-O ऑन्टोलॉजी का उपयोग करता है। यह एक मानक शब्दावली प्रदान करता है और निष्कर्षण आउटपुट के भविष्य के हस्ताक्षर/प्रमाणीकरण को सक्षम बनाता है। + +#### PROV-O मुख्य अवधारणाएँ + +| PROV-O प्रकार | ट्रस्टग्राफ उपयोग | +|-------------|------------------| +| `prov:Entity` | दस्तावेज़, पृष्ठ, चंक, ट्रिपल, एम्बेडिंग | +| `prov:Activity` | निष्कर्षण कार्यों के उदाहरण | +| `prov:Agent` | टीजी घटक (पीडीएफ एक्सट्रैक्टर, चंकर, आदि) संस्करणों के साथ | + +#### PROV-O संबंध + +| विधेय | अर्थ | उदाहरण | +|-----------|---------|---------| +<<<<<<< HEAD +| `prov:wasDerivedFrom` | एक इकाई से व्युत्पन्न अन्य इकाई | पृष्ठ दस्तावेज़ से व्युत्पन्न था | +| `prov:wasGeneratedBy` | एक गतिविधि द्वारा उत्पन्न इकाई | पृष्ठ पीडीएफ निष्कर्षण गतिविधि द्वारा उत्पन्न किया गया था | +| `prov:used` | गतिविधि ने एक इकाई को इनपुट के रूप में उपयोग किया | पीडीएफ निष्कर्षण गतिविधि ने दस्तावेज़ का उपयोग किया | +| `prov:wasAssociatedWith` | एक एजेंट द्वारा की गई गतिविधि | पीडीएफ निष्कर्षण गतिविधि tg:पीडीएफएक्सट्रैक्टर से जुड़ी थी | +======= +| `prov:wasDerivedFrom` | एक इकाई किसी अन्य इकाई से प्राप्त हुई | पृष्ठ दस्तावेज़ से प्राप्त हुआ | +| `prov:wasGeneratedBy` | एक इकाई एक गतिविधि द्वारा उत्पन्न हुई | पृष्ठ पीडीएफ निष्कर्षण गतिविधि द्वारा उत्पन्न हुआ | +| `prov:used` | एक गतिविधि ने एक इकाई को इनपुट के रूप में उपयोग किया | पीडीएफ निष्कर्षण गतिविधि ने दस्तावेज़ का उपयोग किया | +| `prov:wasAssociatedWith` | एक गतिविधि एक एजेंट द्वारा की गई | पीडीएफ निष्कर्षण गतिविधि tg:पीडीएफएक्सट्रैक्टर से जुड़ी थी | +>>>>>>> 82edf2d (New md files from RunPod) + +#### प्रत्येक स्तर पर मेटाडेटा + +**स्रोत दस्तावेज़ (लाइब्रेरियन द्वारा उत्सर्जित):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +<<<<<<< HEAD +**पृष्ठ (पीडीएफ एक्सट्रैक्टर द्वारा उत्सर्जित):** +======= +**पृष्ठ (पीडीएफ एक्सट्रैक्टर द्वारा उत्पन्न):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +**खंड (चंकर द्वारा उत्सर्जित):** +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**ट्रिपल (नॉलेज एक्सट्रैक्टर द्वारा उत्सर्जित):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**एम्बेडिंग (वेक्टर स्टोर में संग्रहीत, ट्रिपल स्टोर में नहीं):** + +एम्बेडिंग को मेटाडेटा के साथ वेक्टर स्टोर में संग्रहीत किया जाता है, न कि आरडीएफ ट्रिपल के रूप में। प्रत्येक एम्बेडिंग रिकॉर्ड में निम्नलिखित शामिल हैं: + +| फ़ील्ड | विवरण | उदाहरण | +|-------|-------------|---------| +| वेक्टर | एम्बेडिंग वेक्टर | [0.123, -0.456, ...] | +| एंटिटी | नोड यूआरआई जिसे एम्बेडिंग दर्शाता है | `entity:JohnSmith` | +| चंक_आईडी | स्रोत चंक (उत्पत्ति) | `chunk:123-1-1` | +| मॉडल | उपयोग किया गया एम्बेडिंग मॉडल | `text-embedding-ada-002` | +| कंपोनेंट_वर्जन | टीजी एम्बेडर संस्करण | `1.0.0` | + +`entity` फ़ील्ड एम्बेडिंग को नॉलेज ग्राफ (नोड यूआरआई) से जोड़ता है। `chunk_id` फ़ील्ड स्रोत चंक तक उत्पत्ति जानकारी प्रदान करता है, जिससे मूल दस्तावेज़ तक डीएजी (DAG) के माध्यम से ट्रैवर्स करना संभव हो जाता है। + +#### ट्रस्टग्राफ नेमस्पेस एक्सटेंशन + +<<<<<<< HEAD +निष्कर्षण-विशिष्ट मेटाडेटा के लिए `tg:` नेमस्पेस के अंतर्गत कस्टम प्रेडिकेट: +======= +निष्कर्षण-विशिष्ट मेटाडेटा के लिए `tg:` नेमस्पेस के तहत कस्टम प्रेडिकेट: +>>>>>>> 82edf2d (New md files from RunPod) + +| प्रेडिकेट | डोमेन | विवरण | +|-----------|--------|-------------| +| `tg:contains` | सबग्राफ | इस निष्कर्षण सबग्राफ में निहित ट्रिपल की ओर इंगित करता है | +| `tg:pageCount` | दस्तावेज़ | स्रोत दस्तावेज़ में पृष्ठों की कुल संख्या | +| `tg:mimeType` | दस्तावेज़ | स्रोत दस्तावेज़ का एमआईएमई (MIME) प्रकार | +| `tg:pageNumber` | पृष्ठ | स्रोत दस्तावेज़ में पृष्ठ संख्या | +| `tg:chunkIndex` | चंक | मूल में चंक का इंडेक्स | +| `tg:charOffset` | चंक | मूल पाठ में कैरेक्टर ऑफसेट | +| `tg:charLength` | चंक | कैरेक्टर में चंक की लंबाई | +| `tg:chunkSize` | गतिविधि | कॉन्फ़िगर किया गया चंक आकार | +<<<<<<< HEAD +| `tg:chunkOverlap` | गतिविधि | चंक के बीच कॉन्फ़िगर किया गया ओवरलैप | +| `tg:componentVersion` | गतिविधि | टीजी घटक का संस्करण | +| `tg:llmModel` | गतिविधि | निष्कर्षण के लिए उपयोग किया गया एलएलएम (LLM) | +| `tg:ontology` | गतिविधि | निष्कर्षण का मार्गदर्शन करने के लिए उपयोग किया गया ऑन्टोलॉजी यूआरआई | +======= +| `tg:chunkOverlap` | गतिविधि | चंक्स के बीच कॉन्फ़िगर किया गया ओवरलैप | +| `tg:componentVersion` | गतिविधि | टीजी घटक का संस्करण | +| `tg:llmModel` | गतिविधि | निष्कर्षण के लिए उपयोग किया गया एलएलएम (LLM) | +| `tg:ontology` | गतिविधि | निष्कर्षण को निर्देशित करने के लिए उपयोग किया गया ऑन्टोलॉजी यूआरआई | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:embeddingModel` | गतिविधि | एम्बेडिंग के लिए उपयोग किया गया मॉडल | +| `tg:sourceText` | स्टेटमेंट | ट्रिपल से निकाले गए सटीक पाठ | +| `tg:sourceCharOffset` | स्टेटमेंट | चंक के भीतर स्रोत पाठ की शुरुआत का कैरेक्टर ऑफसेट | +| `tg:sourceCharLength` | स्टेटमेंट | कैरेक्टर में स्रोत पाठ की लंबाई | + +#### शब्दावली बूटस्ट्रैप (प्रत्येक संग्रह के लिए) + +नॉलेज ग्राफ ऑन्टोलॉजी-तटस्थ है और खाली अवस्था में शुरू होता है। पहली बार किसी संग्रह में पीआरओवी-ओ (PROV-O) उत्पत्ति डेटा लिखते समय, सभी क्लास और प्रेडिकेट के लिए आरडीएफ लेबल के साथ शब्दावली को बूटस्ट्रैप किया जाना चाहिए। यह प्रश्नों और यूआई (UI) में मानव-पठनीय प्रदर्शन सुनिश्चित करता है। + +**पीआरओवी-ओ क्लास:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**प्रोव-ओ विधेय:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**ट्रस्टग्राफ प्रेडिकेट्स:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**कार्यान्वयन नोट:** यह शब्दावली बूटस्ट्रैप आइडेंम्पोटेंट होना चाहिए - बिना डुप्लिकेट बनाए कई बार चलाने के लिए सुरक्षित। इसे किसी संग्रह में पहली बार दस्तावेज़ प्रसंस्करण के दौरान या एक अलग संग्रह आरंभीकरण चरण के रूप में ट्रिगर किया जा सकता है। + +#### उप-खंड उत्पत्ति (आदर्श) + +अधिक बारीक उत्पत्ति के लिए, यह महत्वपूर्ण होगा कि एक त्रिक को एक खंड के भीतर से ठीक कहाँ से निकाला गया था, इसका रिकॉर्ड रखा जाए। यह निम्नलिखित को सक्षम करता है: +======= +**कार्यान्वयन नोट:** यह शब्दावली बूटस्ट्रैप आइडेंम्पोटेंट होना चाहिए - डुप्लिकेट बनाए बिना कई बार चलाने के लिए सुरक्षित। इसे किसी संग्रह में पहली बार दस्तावेज़ प्रसंस्करण के दौरान या एक अलग संग्रह आरंभीकरण चरण के रूप में ट्रिगर किया जा सकता है। + +#### उप-खंड उत्पत्ति (आकांक्षी) + +अधिक बारीक उत्पत्ति के लिए, यह महत्वपूर्ण होगा कि एक त्रिक को एक खंड के भीतर से कहाँ से निकाला गया था, यह सटीक रूप से रिकॉर्ड किया जाए। यह निम्नलिखित को सक्षम करता है: +>>>>>>> 82edf2d (New md files from RunPod) + +यूआई में सटीक स्रोत पाठ को हाइलाइट करना +स्रोत के विरुद्ध निष्कर्षण सटीकता को सत्यापित करना +वाक्य स्तर पर निष्कर्षण गुणवत्ता को डीबग करना + +**स्थिति ट्रैकिंग के साथ उदाहरण:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**उदाहरण पाठ सीमा के साथ (वैकल्पिक):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**कार्यान्वयन संबंधी विचार:** + +एलएलएम-आधारित निष्कर्षण स्वाभाविक रूप से वर्ण स्थिति प्रदान नहीं कर सकता है। +एलएलएम को निकाले गए त्रिगुटों के साथ स्रोत वाक्य/वाक्यांश वापस करने के लिए प्रेरित किया जा सकता है। +वैकल्पिक रूप से, निकाले गए संस्थाओं को स्रोत पाठ से "फजी-मैच" करके पोस्ट-प्रोसेस करें। +निष्कर्षण की जटिलता और उत्पत्ति की सूक्ष्मता के बीच एक समझौता। +यह संरचित निष्कर्षण विधियों की तुलना में मुफ्त-रूप एलएलएम निष्कर्षण से प्राप्त करना आसान हो सकता है। + +यह एक महत्वाकांक्षी लक्ष्य के रूप में चिह्नित है - मूल रूप से, बुनियादी चंक-स्तरीय उत्पत्ति को पहले लागू किया जाना चाहिए, और यदि संभव हो तो, उप-चंक ट्रैकिंग को भविष्य में एक संवर्द्धन के रूप में लागू किया जा सकता है। + +### दोहरी भंडारण मॉडल + +<<<<<<< HEAD +उत्पत्ति डीएजी (DAG) को क्रमिक रूप से बनाया जाता है क्योंकि दस्तावेज़ पाइपलाइन के माध्यम से प्रवाहित होते हैं: +======= +उत्पत्ति DAG (डायरेक्टेड एसाइक्लिक ग्राफ) को क्रमिक रूप से बनाया जाता है क्योंकि दस्तावेज़ पाइपलाइन के माध्यम से प्रवाहित होते हैं: +>>>>>>> 82edf2d (New md files from RunPod) + +| स्टोर | क्या संग्रहीत है | उद्देश्य | +|-------|---------------|---------| +| लाइब्रेरियन | दस्तावेज़ सामग्री + माता-पिता-बच्चे लिंक | सामग्री पुनर्प्राप्ति, कैस्केड विलोपन | +<<<<<<< HEAD +| ज्ञान ग्राफ | माता-पिता-बच्चे किनारे + मेटाडेटा | उत्पत्ति प्रश्न, तथ्य का श्रेय | + +दोनों स्टोर समान डीएजी संरचना बनाए रखते हैं। लाइब्रेरियन सामग्री रखता है; ग्राफ संबंधों को रखता है और ट्रैवर्सल प्रश्नों को सक्षम करता है। + +### प्रमुख डिज़ाइन सिद्धांत + +1. **दस्तावेज़ आईडी प्रवाह की इकाई के रूप में** - प्रोसेसर आईडी, सामग्री नहीं, पास करते हैं। जब आवश्यक हो तो सामग्री लाइब्रेरियन से प्राप्त की जाती है। +======= +| नॉलेज ग्राफ | माता-पिता-बच्चे किनारे + मेटाडेटा | उत्पत्ति प्रश्न, तथ्य का श्रेय | + +दोनों स्टोर समान DAG संरचना बनाए रखते हैं। लाइब्रेरियन सामग्री रखता है; ग्राफ संबंधों को रखता है और ट्रैवर्सल प्रश्नों को सक्षम बनाता है। + +### प्रमुख डिज़ाइन सिद्धांत + +1. **दस्तावेज़ आईडी प्रवाह की इकाई के रूप में** - प्रोसेसर आईडी, सामग्री नहीं, पास करते हैं। जब आवश्यक हो तो सामग्री को लाइब्रेरियन से प्राप्त किया जाता है। +>>>>>>> 82edf2d (New md files from RunPod) + +2. **स्रोत पर एक बार उत्सर्जित करें** - प्रसंस्करण शुरू होने पर मेटाडेटा को ग्राफ में एक बार लिखा जाता है, न कि बाद में दोहराया जाता है। + +3. **संगत प्रोसेसर पैटर्न** - प्रत्येक प्रोसेसर एक ही प्राप्त/प्राप्त/उत्पादित/सहेजें/उत्सर्जित/फॉरवर्ड पैटर्न का पालन करता है। + +<<<<<<< HEAD +4. **प्रगतिशील डीएजी निर्माण** - प्रत्येक प्रोसेसर अपने स्तर को डीएजी में जोड़ता है। पूर्ण उत्पत्ति श्रृंखला क्रमिक रूप से बनाई जाती है। + +5. **चंक-प्रोसेसर के बाद अनुकूलन** - चंकिंग के बाद, संदेशों में आईडी और सामग्री दोनों होते हैं। चंक छोटे होते हैं (2-4KB), इसलिए सामग्री को शामिल करने से अनावश्यक लाइब्रेरियन राउंड-ट्रिप से बचा जा सकता है, जबकि आईडी के माध्यम से उत्पत्ति को संरक्षित किया जा सकता है। +======= +4. **प्रगतिशील DAG निर्माण** - प्रत्येक प्रोसेसर अपने स्तर को DAG में जोड़ता है। पूर्ण उत्पत्ति श्रृंखला क्रमिक रूप से बनाई जाती है। + +5. **चंक-प्रोसेसर के बाद अनुकूलन** - चंकिंग के बाद, संदेशों में आईडी और सामग्री दोनों होते हैं। चंक छोटे होते हैं (2-4KB), इसलिए सामग्री को शामिल करने से अनावश्यक लाइब्रेरियन राउंड-ट्रिप से बचा जाता है, जबकि आईडी के माध्यम से उत्पत्ति को संरक्षित किया जाता है। +>>>>>>> 82edf2d (New md files from RunPod) + +## कार्यान्वयन कार्य + +### लाइब्रेरियन परिवर्तन + +#### वर्तमान स्थिति + +दस्तावेज़ प्रसंस्करण शुरू करता है दस्तावेज़ आईडी को पहले प्रोसेसर को भेजकर। +ट्रिपल स्टोर से कोई कनेक्शन नहीं - मेटाडेटा निष्कर्षण आउटपुट के साथ बंडल किया गया है। +`add-child-document` एक-स्तरीय माता-पिता-बच्चे लिंक बनाता है। +`list-children` केवल तत्काल बच्चों को वापस करता है। + +#### आवश्यक परिवर्तन + +**1. नया इंटरफ़ेस: ट्रिपल स्टोर कनेक्शन** + +<<<<<<< HEAD +लाइब्रेरियन को प्रसंस्करण शुरू करते समय दस्तावेज़ मेटाडेटा किनारों को सीधे ज्ञान ग्राफ में उत्सर्जित करने की आवश्यकता है। +======= +लाइब्रेरियन को प्रसंस्करण शुरू करते समय दस्तावेज़ मेटाडेटा किनारों को सीधे नॉलेज ग्राफ में उत्सर्जित करने की आवश्यकता है। +>>>>>>> 82edf2d (New md files from RunPod) +लाइब्रेरियन सेवा में ट्रिपल स्टोर क्लाइंट/प्रकाशक जोड़ें। +प्रसंस्करण शुरू होने पर: रूट दस्तावेज़ मेटाडेटा को ग्राफ किनारों के रूप में उत्सर्जित करें (एक बार)। + +**2. दस्तावेज़ प्रकार शब्दावली** + +चाइल्ड दस्तावेज़ों के लिए `document_type` मानों का मानकीकरण करें: +`source` - मूल अपलोड किया गया दस्तावेज़। +<<<<<<< HEAD +`page` - स्रोत से निकाला गया पृष्ठ (पीडीएफ, आदि)। +======= +`page` - स्रोत (पीडीएफ, आदि) से निकाला गया पृष्ठ। +>>>>>>> 82edf2d (New md files from RunPod) +`chunk` - पृष्ठ या स्रोत से प्राप्त पाठ चंक। + +#### इंटरफ़ेस परिवर्तन सारांश + +| इंटरफ़ेस | परिवर्तन | +|-----------|--------| +| ट्रिपल स्टोर | नया आउटबाउंड कनेक्शन - दस्तावेज़ मेटाडेटा किनारों को उत्सर्जित करें | +| प्रसंस्करण प्रारंभ | ग्राफ पर मेटाडेटा उत्सर्जित करें प्रसंस्करण को अग्रेषित करने से पहले | + +### पीडीएफ एक्सट्रैक्टर परिवर्तन + +#### वर्तमान स्थिति + +दस्तावेज़ सामग्री प्राप्त करता है (या बड़े दस्तावेज़ों को स्ट्रीम करता है)। +पीडीएफ पृष्ठों से पाठ निकालता है। +पृष्ठ सामग्री को चंकर को अग्रेषित करता है। +लाइब्रेरियन या ट्रिपल स्टोर के साथ कोई इंटरैक्शन नहीं। + +#### आवश्यक परिवर्तन + +**1. नया इंटरफ़ेस: लाइब्रेरियन क्लाइंट** + +<<<<<<< HEAD +पीडीएफ एक्सट्रैक्टर को प्रत्येक पृष्ठ को लाइब्रेरियन में एक चाइल्ड दस्तावेज़ के रूप में सहेजना होगा। +======= +पीडीएफ एक्सट्रैक्टर को प्रत्येक पृष्ठ को लाइब्रेरियन में एक चाइल्ड दस्तावेज़ के रूप में सहेजने की आवश्यकता है। +>>>>>>> 82edf2d (New md files from RunPod) +पीडीएफ एक्सट्रैक्टर सेवा में लाइब्रेरियन क्लाइंट जोड़ें। +प्रत्येक पृष्ठ के लिए: `add-child-document` को रूट दस्तावेज़ आईडी के साथ कॉल करें। + +**2. नया इंटरफ़ेस: ट्रिपल स्टोर कनेक्शन** + +<<<<<<< HEAD +पीडीएफ एक्सट्रैक्टर को ज्ञान ग्राफ में माता-पिता-बच्चे किनारे उत्सर्जित करने की आवश्यकता है। +======= +पीडीएफ एक्सट्रैक्टर को नॉलेज ग्राफ में माता-पिता-बच्चे किनारों को उत्सर्जित करने की आवश्यकता है। +>>>>>>> 82edf2d (New md files from RunPod) +ट्रिपल स्टोर क्लाइंट/प्रकाशक जोड़ें। +प्रत्येक पृष्ठ के लिए: पृष्ठ दस्तावेज़ को माता-पिता दस्तावेज़ से जोड़ने वाले किनारे को उत्सर्जित करें। + +**3. आउटपुट प्रारूप बदलें** + +सीधे पृष्ठ सामग्री अग्रेषित करने के बजाय, पृष्ठ दस्तावेज़ आईडी अग्रेषित करें। +<<<<<<< HEAD +चंकर लाइब्रेरियन का उपयोग करके आईडी के साथ सामग्री प्राप्त करेगा +======= +चंकर लाइब्रेरियन का उपयोग करके आईडी के साथ सामग्री प्राप्त करेगा। +>>>>>>> 82edf2d (New md files from RunPod) + +#### इंटरफ़ेस परिवर्तनों का सारांश + +| इंटरफ़ेस | परिवर्तन | +|-----------|--------| +| लाइब्रेरियन | नया आउटबाउंड - चाइल्ड दस्तावेज़ सहेजें | +| ट्रिपल स्टोर | नया आउटबाउंड - पैरेंट-चाइल्ड किनारे उत्सर्जित करें | +| आउटपुट संदेश | सामग्री से दस्तावेज़ आईडी में परिवर्तन | + +### चंकर परिवर्तन + +#### वर्तमान स्थिति + +पृष्ठ/पाठ सामग्री प्राप्त करता है +टुकड़ों में विभाजित करता है +डाउनस्ट्रीम प्रोसेसर को टुकड़े सामग्री अग्रेषित करता है +लाइब्रेरियन या ट्रिपल स्टोर के साथ कोई इंटरैक्शन नहीं + +#### आवश्यक परिवर्तन + +**1. इनपुट हैंडलिंग बदलें** + +सामग्री के बजाय दस्तावेज़ आईडी प्राप्त करें, लाइब्रेरियन से प्राप्त करें। +चंकर सेवा में लाइब्रेरियन क्लाइंट जोड़ें +दस्तावेज़ आईडी का उपयोग करके पृष्ठ सामग्री प्राप्त करें + +**2. नया इंटरफ़ेस: लाइब्रेरियन क्लाइंट (लिखना)** + +प्रत्येक टुकड़े को लाइब्रेरियन में एक चाइल्ड दस्तावेज़ के रूप में सहेजें। +प्रत्येक टुकड़े के लिए: `add-child-document` को पैरेंट = पृष्ठ दस्तावेज़ आईडी के साथ कॉल करें + +**3. नया इंटरफ़ेस: ट्रिपल स्टोर कनेक्शन** + +नॉलेज ग्राफ में पैरेंट-चाइल्ड किनारे उत्सर्जित करें। +ट्रिपल स्टोर क्लाइंट/प्रकाशक जोड़ें +प्रत्येक टुकड़े के लिए: टुकड़े दस्तावेज़ को पृष्ठ दस्तावेज़ से जोड़ने वाला किनारा उत्सर्जित करें + +**4. आउटपुट प्रारूप बदलें** + +टुकड़े दस्तावेज़ आईडी और टुकड़े सामग्री दोनों अग्रेषित करें (टुकड़े-टुकड़े अनुकूलन के बाद)। +डाउनस्ट्रीम प्रोसेसर उत्पत्ति के लिए आईडी और काम करने के लिए सामग्री प्राप्त करते हैं + +#### इंटरफ़ेस परिवर्तनों का सारांश + +| इंटरफ़ेस | परिवर्तन | +|-----------|--------| +| इनपुट संदेश | सामग्री से दस्तावेज़ आईडी में परिवर्तन | +| लाइब्रेरियन | नया आउटबाउंड (पढ़ना + लिखना) - सामग्री प्राप्त करें, चाइल्ड दस्तावेज़ सहेजें | +| ट्रिपल स्टोर | नया आउटबाउंड - पैरेंट-चाइल्ड किनारे उत्सर्जित करें | +| आउटपुट संदेश | सामग्री-केवल से आईडी + सामग्री में परिवर्तन | + +### नॉलेज एक्सट्रैक्टर परिवर्तन + +#### वर्तमान स्थिति + +टुकड़े सामग्री प्राप्त करता है +ट्रिपल और एम्बेडिंग निकालता है +ट्रिपल स्टोर और एम्बेडिंग स्टोर में उत्सर्जित करता है +`subjectOf` संबंध शीर्ष-स्तरीय दस्तावेज़ (टुकड़े नहीं) की ओर इशारा करता है + +#### आवश्यक परिवर्तन + +**1. इनपुट हैंडलिंग बदलें** + +<<<<<<< HEAD +टुकड़े दस्तावेज़ आईडी के साथ-साथ सामग्री प्राप्त करें। +======= +सामग्री के साथ-साथ टुकड़े दस्तावेज़ आईडी प्राप्त करें। +>>>>>>> 82edf2d (New md files from RunPod) +उत्पत्ति लिंकिंग के लिए टुकड़े आईडी का उपयोग करें (सामग्री पहले से ही अनुकूलन के अनुसार शामिल है) + +**2. ट्रिपल उत्पत्ति को अपडेट करें** + +निकाले गए ट्रिपल को टुकड़े (शीर्ष-स्तरीय दस्तावेज़ नहीं) से लिंक करें। +किनारे को इंगित करने वाले किनारे को बनाने के लिए पुन: उपयोग करें +`subjectOf` संबंध: ट्रिपल → टुकड़े दस्तावेज़ आईडी +मौजूदा पुन: उपयोग समर्थन का पहला उपयोग + +**3. एम्बेडिंग उत्पत्ति को अपडेट करें** + +<<<<<<< HEAD +एम्बेडिंग इकाई आईडी को टुकड़े से लिंक करें। +किनारा उत्सर्जित करें: एम्बेडिंग इकाई आईडी → टुकड़े दस्तावेज़ आईडी +======= +एम्बेडिंग एंटिटी आईडी को टुकड़े से लिंक करें। +किनारा उत्सर्जित करें: एम्बेडिंग एंटिटी आईडी → टुकड़े दस्तावेज़ आईडी +>>>>>>> 82edf2d (New md files from RunPod) + +#### इंटरफ़ेस परिवर्तनों का सारांश + +| इंटरफ़ेस | परिवर्तन | +|-----------|--------| +<<<<<<< HEAD +| इनपुट संदेश | टुकड़े आईडी + सामग्री की अपेक्षा करें (केवल सामग्री नहीं) | +| ट्रिपल स्टोर | ट्रिपल → टुकड़े उत्पत्ति के लिए पुन: उपयोग का उपयोग करें | +| एम्बेडिंग उत्पत्ति | इकाई आईडी → टुकड़े आईडी से लिंक करें | +======= +| इनपुट संदेश | सामग्री के साथ टुकड़े आईडी + सामग्री की अपेक्षा करें (केवल सामग्री नहीं) | +| ट्रिपल स्टोर | ट्रिपल → टुकड़े उत्पत्ति के लिए पुन: उपयोग का उपयोग करें | +| एम्बेडिंग उत्पत्ति | एंटिटी आईडी → टुकड़े आईडी से लिंक करें | +>>>>>>> 82edf2d (New md files from RunPod) + +## संदर्भ + +क्वेरी-टाइम उत्पत्ति: `docs/tech-specs/query-time-provenance.md` +उत्पत्ति मॉडलिंग के लिए PROV-O मानक +नॉलेज ग्राफ में मौजूदा स्रोत मेटाडेटा (ऑडिट की आवश्यकता है) diff --git a/docs/tech-specs/extraction-time-provenance.md b/docs/tech-specs/extraction-time-provenance.md index 782bf5de..6c4b4513 100644 --- a/docs/tech-specs/extraction-time-provenance.md +++ b/docs/tech-specs/extraction-time-provenance.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Extraction-Time Provenance: Source Layer" +parent: "Tech Specs" +--- + # Extraction-Time Provenance: Source Layer ## Overview diff --git a/docs/tech-specs/extraction-time-provenance.pt.md b/docs/tech-specs/extraction-time-provenance.pt.md new file mode 100644 index 00000000..f3cc34cc --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.pt.md @@ -0,0 +1,758 @@ +--- +layout: default +title: "Proveniência no Momento da Extração: Camada de Origem" +parent: "Portuguese (Beta)" +--- + +# Proveniência no Momento da Extração: Camada de Origem + +> **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 registra notas sobre a proveniência no momento da extração para trabalhos de especificação futuros. A proveniência no momento da extração registra a "camada de origem" - de onde os dados vieram originalmente, como foram extraídos e transformados. + +Isso é diferente da proveniência no momento da consulta (veja `query-time-provenance.md`), que registra o raciocínio do agente. + +## Declaração do Problema + +### Implementação Atual + +Atualmente, a proveniência funciona da seguinte forma: +Metadados do documento são armazenados como triplas RDF no grafo de conhecimento. +Um ID de documento associa metadados ao documento, de modo que o documento aparece como um nó no grafo. +Quando arestas (relacionamentos/fatos) são extraídas de documentos, um relacionamento `subjectOf` vincula a aresta extraída ao documento de origem. + +### Problemas com a Abordagem Atual + +<<<<<<< HEAD +1. **Carregamento repetitivo de metadados:** Os metadados do documento são agrupados e carregados repetidamente com cada lote de triplas extraídas daquele documento. Isso é um desperdício e redundante - os mesmos metadados viajam como carga com cada saída de extração. +======= +1. **Carregamento repetitivo de metadados:** Os metadados do documento são agrupados e carregados repetidamente com cada lote de triplas extraídas daquele documento. Isso é um desperdício e redundante - os mesmos metadados viajam como carga útil com cada saída de extração. +>>>>>>> 82edf2d (New md files from RunPod) + +2. **Proveniência superficial:** O relacionamento `subjectOf` atual vincula apenas os fatos diretamente ao documento de nível superior. Não há visibilidade da cadeia de transformação - qual página o fato veio, qual trecho, qual método de extração foi usado. + +### Estado Desejado + +1. **Carregar metadados uma vez:** Os metadados do documento devem ser carregados uma vez e anexados ao nó do documento de nível superior, não repetidos com cada lote de triplas. + +2. **DAG de proveniência rica:** Capture toda a cadeia de transformação desde o documento de origem, passando por todos os artefatos intermediários, até os fatos extraídos. Por exemplo, uma transformação de documento PDF: + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +<<<<<<< HEAD +3. **Armazenamento unificado:** O grafo de proveniência é armazenado no mesmo grafo de conhecimento que o conhecimento extraído. Isso permite que a proveniência seja consultada da mesma forma que o conhecimento - seguindo as arestas de volta à cadeia de qualquer fato para sua localização de origem exata. +======= +3. **Armazenamento unificado:** O grafo de proveniência é armazenado no mesmo grafo de conhecimento que o conhecimento extraído. Isso permite que a proveniência seja consultada da mesma forma que o conhecimento - seguindo as arestas de volta à cadeia de qualquer fato até sua localização de origem exata. +>>>>>>> 82edf2d (New md files from RunPod) + +4. **IDs estáveis:** Cada artefato intermediário (página, trecho) possui um ID estável como um nó no grafo. + +5. **Vinculação pai-filho:** Documentos derivados são vinculados aos seus pais até o documento de origem de nível superior, usando tipos de relacionamento consistentes. + +<<<<<<< HEAD +6. **Atribuição precisa de fatos:** O relacionamento `subjectOf` nas arestas extraídas aponta para o pai imediato (trecho), não para o documento de nível superior. A proveniência completa é recuperada percorrendo o DAG. +======= +6. **Atribuição precisa de fatos:** O relacionamento `subjectOf` nas arestas extraídas aponta para o pai imediato (trecho), e não para o documento de nível superior. A proveniência completa é recuperada percorrendo o DAG. +>>>>>>> 82edf2d (New md files from RunPod) + +## Casos de Uso + +### UC1: Atribuição de Fonte em Respostas GraphRAG + +**Cenário:** Um usuário executa uma consulta GraphRAG e recebe uma resposta do agente. + +**Fluxo:** +1. O usuário envia uma consulta para o agente GraphRAG. +2. O agente recupera fatos relevantes do grafo de conhecimento para formular uma resposta. +3. De acordo com a especificação de proveniência em tempo de consulta, o agente informa quais fatos contribuíram para a resposta. +4. Cada fato vincula-se ao seu trecho de origem através do grafo de proveniência. +5. Trechos vinculam-se a páginas, páginas vinculam-se a documentos de origem. + +**Resultado da Experiência do Usuário:** A interface exibe a resposta do LLM juntamente com a atribuição da fonte. O usuário pode: +<<<<<<< HEAD +Ver quais fatos apoiaram a resposta. +======= +Ver quais fatos suportaram a resposta. +>>>>>>> 82edf2d (New md files from RunPod) +Acessar informações detalhadas de fatos → trechos → páginas → documentos. +Examinar os documentos de origem para verificar as alegações. +Entender exatamente onde em um documento (qual página, qual seção) um fato se originou. + +**Valor:** Os usuários podem verificar as respostas geradas por IA em relação às fontes primárias, construindo confiança e permitindo a verificação de fatos. + +### UC2: Depuração da Qualidade da Extração + +Um fato parece incorreto. Rastreie de volta através do trecho → página → documento para ver o texto original. Foi uma extração ruim ou a fonte em si estava incorreta? + +<<<<<<< HEAD +### UC3: Reextração Incremental +======= +### UC3: Re-extração Incremental +>>>>>>> 82edf2d (New md files from RunPod) + +O documento de origem é atualizado. Quais trechos/fatos foram derivados dele? Invalide e regenere apenas esses, em vez de reprocessar tudo. + +### UC4: Exclusão de Dados / Direito ao Esquecimento + +Um documento de origem deve ser removido (GDPR, legal, etc.). Percorra o DAG para encontrar e remover todos os fatos derivados. + +### UC5: Resolução de Conflitos + +<<<<<<< HEAD +Dois fatos se contradizem. Rastreie ambos de volta às suas fontes para entender por que e decidir qual confiar (fonte mais autoritária, mais recente, etc.). +======= +Dois fatos se contradizem. Rastreie ambos de volta às suas fontes para entender o porquê e decidir qual confiar (fonte mais autoritária, mais recente, etc.). +>>>>>>> 82edf2d (New md files from RunPod) + +### UC6: Ponderação da Autoridade da Fonte + +Algumas fontes são mais autoritárias do que outras. Os fatos podem ser ponderados ou filtrados com base na autoridade/qualidade de seus documentos de origem. + +### UC7: Comparação de Pipelines de Extração + +Compare os resultados de diferentes métodos/versões de extração. Qual extrator produziu melhores fatos da mesma fonte? + +## Pontos de Integração + +### Bibliotecário + +<<<<<<< HEAD +O componente bibliotecário já fornece armazenamento de documentos com IDs de documento exclusivos. O sistema de rastreabilidade se integra com essa infraestrutura existente. +======= +O componente bibliotecário já fornece armazenamento de documentos com IDs de documentos exclusivos. O sistema de rastreabilidade se integra a essa infraestrutura existente. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Capacidades Existentes (já implementadas) + +**Vinculação de Documentos Pai-Filho:** +Campo `parent_id` em `DocumentMetadata` - vincula o documento filho ao documento pai +Campo `document_type` - valores: `"source"` (original) ou `"extracted"` (derivado) +API `add-child-document` - cria um documento filho com `document_type = "extracted"` automático +API `list-children` - recupera todos os filhos de um documento pai +Exclusão em cascata - a remoção de um pai exclui automaticamente todos os documentos filhos + +**Identificação de Documentos:** +<<<<<<< HEAD +Os IDs de documento são especificados pelo cliente (não gerados automaticamente) +Documentos indexados por `(user, document_id)` composto no Cassandra +IDs de objeto (UUIDs) gerados internamente para armazenamento de blobs +======= +Os IDs dos documentos são especificados pelo cliente (não gerados automaticamente) +Documentos indexados por `(user, document_id)` composto no Cassandra +IDs de objetos (UUIDs) gerados internamente para armazenamento de blobs +>>>>>>> 82edf2d (New md files from RunPod) + +**Suporte a Metadados:** +Campo `metadata: list[Triple]` - triplas RDF para metadados estruturados +`title`, `comments`, `tags` - metadados básicos do documento +`time` - carimbo de data/hora, `kind` - tipo MIME + +**Arquitetura de Armazenamento:** +Metadados armazenados no Cassandra (espaço de chaves `librarian`, tabela `document`) +Conteúdo armazenado no armazenamento de blobs MinIO/S3 (bucket `library`) +Entrega inteligente de conteúdo: documentos < 2MB incorporados, documentos maiores transmitidos + +#### Arquivos Chave + +`trustgraph-flow/trustgraph/librarian/librarian.py` - Operações principais do bibliotecário +<<<<<<< HEAD +`trustgraph-flow/trustgraph/librarian/service.py` - Processador de serviço, carregamento de documento +======= +`trustgraph-flow/trustgraph/librarian/service.py` - Processador de serviço, carregamento de documentos +>>>>>>> 82edf2d (New md files from RunPod) +`trustgraph-flow/trustgraph/tables/library.py` - Armazenamento de tabela Cassandra +`trustgraph-base/trustgraph/schema/services/library.py` - Definições de esquema + +#### Lacunas a Serem Abordadas + +O bibliotecário tem os blocos de construção, mas atualmente: +1. A vinculação pai-filho é de um único nível - não há auxiliares de travessia de DAG de vários níveis +2. Não há vocabulário padrão de tipo de relacionamento (por exemplo, `derivedFrom`, `extractedFrom`) +3. Metadados de rastreabilidade (método de extração, confiança, posição do fragmento) não estão padronizados +<<<<<<< HEAD +4. Não há API de consulta para percorrer toda a cadeia de rastreabilidade de um fato até a fonte +======= +4. Não há API de consulta para percorrer toda a cadeia de rastreabilidade de um fato até a origem +>>>>>>> 82edf2d (New md files from RunPod) + +## Design de Fluxo de Extremo a Extremo + +Cada processador no pipeline segue um padrão consistente: +Recebe o ID do documento do upstream +Recupera o conteúdo do bibliotecário +Produz artefatos filhos +Para cada filho: salva no bibliotecário, emite uma aresta para o grafo, encaminha o ID para o downstream + +### Fluxos de Processamento + +Existem dois fluxos dependendo do tipo de documento: + +#### Fluxo de Documento PDF + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### Fluxo de Documentos de Texto + +Documentos de texto ignoram o extrator de PDF e vão diretamente para o processador de fragmentos: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +<<<<<<< HEAD +O grafo acíclico dirigido (DAG) resultante é um nível mais curto: +======= +O grafo acíclico direcionado (DAG) resultante é um nível mais curto: +>>>>>>> 82edf2d (New md files from RunPod) + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +O design acomoda ambos porque o processador divide o conteúdo de forma genérica - ele usa qualquer ID de documento que recebe como pai, independentemente de ser um documento de origem ou uma página. + +### Esquema de Metadados (PROV-O) + +Os metadados de procedência utilizam a ontologia W3C PROV-O. Isso fornece um vocabulário padrão e permite a futura assinatura/autenticação dos resultados da extração. + +#### Conceitos Principais do PROV-O + +| Tipo PROV-O | Uso no TrustGraph | +|-------------|------------------| +| `prov:Entity` | Documento, Página, Trecho, Tripla, Incorporação | +| `prov:Activity` | Instâncias de operações de extração | +| `prov:Agent` | Componentes do TG (extrator de PDF, processador, etc.) com versões | + +#### Relacionamentos do PROV-O + +| Predicado | Significado | Exemplo | +|-----------|---------|---------| +<<<<<<< HEAD +| `prov:wasDerivedFrom` | Entidade derivada de outra entidade | Página foiDerivadaDe Documento | +| `prov:wasGeneratedBy` | Entidade gerada por uma atividade | Página foiGeradaPor AtividadeDeExtraçãoDePDF | +| `prov:used` | Atividade que usou uma entidade como entrada | AtividadeDeExtraçãoDePDF usou Documento | +| `prov:wasAssociatedWith` | Atividade realizada por um agente | AtividadeDeExtraçãoDePDF foiAssociadaA tg:ExtratorDePDF | +======= +| `prov:wasDerivedFrom` | Entidade derivada de outra entidade | Página derivadaDocumento | +| `prov:wasGeneratedBy` | Entidade gerada por uma atividade | Página geradaPor AtividadeDeExtraçãoDePDF | +| `prov:used` | Atividade que usou uma entidade como entrada | AtividadeDeExtraçãoDePDF usou Documento | +| `prov:wasAssociatedWith` | Atividade realizada por um agente | AtividadeDeExtraçãoDePDF associadaA tg:ExtratorDePDF | +>>>>>>> 82edf2d (New md files from RunPod) + +#### Metadados em Cada Nível + +**Documento de Origem (emitido pelo Librarian):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +**Página (emitida pelo Extrator de PDF):** +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +**Bloco (emitido pelo Chunker):** +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**Tripla (emitida pelo Extrator de Conhecimento):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**Incorporação (armazenada em um armazenamento vetorial, não em um armazenamento triplo):** + +As incorporações são armazenadas no armazenamento vetorial com metadados, e não como triplos RDF. Cada registro de incorporação contém: + +| Campo | Descrição | Exemplo | +|-------|-------------|---------| +| vetor | O vetor de incorporação | [0.123, -0.456, ...] | +| entidade | URI do nó que a incorporação representa | `entity:JohnSmith` | +| chunk_id | Fragmento de origem (proveniência) | `chunk:123-1-1` | +| modelo | Modelo de incorporação usado | `text-embedding-ada-002` | +| component_version | Versão do incorporador TG | `1.0.0` | + +<<<<<<< HEAD +O campo `entity` vincula a incorporação ao grafo de conhecimento (URI do nó). O campo `chunk_id` fornece a proveniência de volta ao fragmento de origem, permitindo a navegação ascendente no DAG até o documento original. +======= +O campo `entity` vincula a incorporação ao grafo de conhecimento (URI do nó). O campo `chunk_id` fornece a proveniência de volta ao fragmento de origem, permitindo a travessia ascendente do DAG até o documento original. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Extensões do Namespace TrustGraph + +Predicados personalizados sob o namespace `tg:` para metadados específicos de extração: + +| Predicado | Domínio | Descrição | +|-----------|--------|-------------| +| `tg:contains` | Subgrafo | Aponta para um triplo contido neste subgrafo de extração | +| `tg:pageCount` | Documento | Número total de páginas no documento de origem | +| `tg:mimeType` | Documento | Tipo MIME do documento de origem | +| `tg:pageNumber` | Página | Número da página no documento de origem | +| `tg:chunkIndex` | Fragmento | Índice do fragmento dentro do fragmento pai | +| `tg:charOffset` | Fragmento | Deslocamento de caractere no texto pai | +| `tg:charLength` | Fragmento | Comprimento do fragmento em caracteres | +| `tg:chunkSize` | Atividade | Tamanho do fragmento configurado | +| `tg:chunkOverlap` | Atividade | Sobreposição configurada entre fragmentos | +| `tg:componentVersion` | Atividade | Versão do componente TG | +| `tg:llmModel` | Atividade | LLM usado para extração | +| `tg:ontology` | Atividade | URI da ontologia usada para guiar a extração | +| `tg:embeddingModel` | Atividade | Modelo usado para incorporações | +| `tg:sourceText` | Declaração | Texto exato do qual um triplo foi extraído | +| `tg:sourceCharOffset` | Declaração | Deslocamento de caractere dentro do fragmento onde o texto de origem começa | +| `tg:sourceCharLength` | Declaração | Comprimento do texto de origem em caracteres | + +#### Inicialização do Vocabulário (Por Coleção) + +O grafo de conhecimento é neutro em relação à ontologia e é inicializado como vazio. Ao gravar dados de proveniência PROV-O em uma coleção pela primeira vez, o vocabulário deve ser inicializado com rótulos RDF para todas as classes e predicados. Isso garante a exibição legível por humanos em consultas e na interface do usuário. + +**Classes PROV-O:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**Predicados PROV-O:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +<<<<<<< HEAD +**Predicados TrustGraph:** +======= +**Predicados do TrustGraph:** +>>>>>>> 82edf2d (New md files from RunPod) +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**Observação sobre a implementação:** Este processo de inicialização do vocabulário deve ser idempotente - seguro para executar várias vezes sem criar duplicatas. Pode ser acionado no processamento do primeiro documento em uma coleção, ou como uma etapa separada de inicialização da coleção. +======= +**Observação sobre a implementação:** Este vocabulário de inicialização deve ser idempotente - seguro para executar várias vezes sem criar duplicatas. Pode ser acionado no processamento do primeiro documento em uma coleção, ou como uma etapa separada de inicialização da coleção. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Proveniência de Sub-Fragmentos (Alvo) + +Para uma rastreabilidade mais detalhada, seria valioso registrar exatamente onde, dentro de um fragmento, uma tripla foi extraída. Isso permite: + +Destacar o texto de origem exato na interface do usuário +<<<<<<< HEAD +Verificar a precisão da extração em relação à fonte +======= +Verificar a precisão da extração em relação à origem +>>>>>>> 82edf2d (New md files from RunPod) +Depurar a qualidade da extração no nível da frase + +**Exemplo com rastreamento de posição:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**Exemplo com intervalo de texto (alternativa):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**Considerações de implementação:** + +A extração baseada em LLM pode não fornecer naturalmente as posições dos caracteres. +Poderia solicitar ao LLM que retornasse a frase/frase de origem junto com as triplas extraídas. +<<<<<<< HEAD +Alternativamente, pós-processe para fazer uma correspondência aproximada das entidades extraídas com o texto de origem. +======= +Alternativamente, pós-processar para fazer uma correspondência aproximada das entidades extraídas com o texto de origem. +>>>>>>> 82edf2d (New md files from RunPod) +Compromisso entre a complexidade da extração e a granularidade da procedência. +Pode ser mais fácil de alcançar com métodos de extração estruturados do que com a extração de LLM de formato livre. + +Isso está marcado como uma meta a longo prazo - a procedência no nível do bloco deve ser implementada primeiro, com o rastreamento de subblocos como um aprimoramento futuro, se viável. + +### Modelo de Armazenamento Duplo + +O grafo de procedência é construído progressivamente à medida que os documentos fluem pelo pipeline: + +| Armazenamento | O que é armazenado | Propósito | +|-------|---------------|---------| +<<<<<<< HEAD +| Bibliotecário | Conteúdo do documento + links pai-filho | Recuperação de conteúdo, exclusão em cascata | +| Grafo de Conhecimento | Arestas pai-filho + metadados | Consultas de procedência, atribuição de fatos | + +Ambos os armazenamentos mantêm a mesma estrutura de grafo. O bibliotecário armazena o conteúdo; o grafo armazena os relacionamentos e permite consultas de travessia. + +### Princípios de Design Chave + +1. **ID do documento como a unidade de fluxo** - Os processadores passam IDs, não o conteúdo. O conteúdo é buscado do bibliotecário quando necessário. +======= +| Librarian | Conteúdo do documento + links pai-filho | Recuperação de conteúdo, exclusão em cascata | +| Knowledge Graph | Arestas pai-filho + metadados | Consultas de procedência, atribuição de fatos | + +Ambos os armazenamentos mantêm a mesma estrutura de grafo. O librarian armazena o conteúdo; o grafo armazena os relacionamentos e permite consultas de travessia. + +### Princípios de Design Chave + +1. **ID do documento como a unidade de fluxo** - Os processadores passam IDs, não o conteúdo. O conteúdo é buscado do librarian quando necessário. +>>>>>>> 82edf2d (New md files from RunPod) + +2. **Emitir uma vez na origem** - Os metadados são gravados no grafo uma vez quando o processamento começa, e não repetidos downstream. + +3. **Padrão de processador consistente** - Cada processador segue o mesmo padrão de receber/buscar/produzir/salvar/emitir/transmitir. + +4. **Construção progressiva do grafo** - Cada processador adiciona seu nível ao grafo. A cadeia completa de procedência é construída incrementalmente. + +<<<<<<< HEAD +5. **Otimização pós-fragmentação** - Após a fragmentação, as mensagens carregam tanto o ID quanto o conteúdo. Os fragmentos são pequenos (2-4 KB), portanto, incluir o conteúdo evita viagens de ida e volta desnecessárias ao bibliotecário, preservando a procedência por meio do ID. + +## Tarefas de Implementação + +### Alterações no Bibliotecário +======= +5. **Otimização pós-fragmentação** - Após a fragmentação, as mensagens carregam tanto o ID quanto o conteúdo. Os fragmentos são pequenos (2-4 KB), portanto, incluir o conteúdo evita viagens de ida e volta desnecessárias ao librarian, preservando a procedência por meio do ID. + +## Tarefas de Implementação + +### Alterações no Librarian +>>>>>>> 82edf2d (New md files from RunPod) + +#### Estado Atual + +Inicia o processamento do documento enviando o ID do documento para o primeiro processador. +<<<<<<< HEAD +Não possui conexão com o armazenamento de triplas - os metadados são agrupados com as saídas de extração. +======= +Não possui conexão com o triple store - os metadados são agrupados com as saídas de extração. +>>>>>>> 82edf2d (New md files from RunPod) +`add-child-document` cria links pai-filho de um nível. +`list-children` retorna apenas os filhos imediatos. + +#### Alterações Necessárias + +<<<<<<< HEAD +**1. Nova interface: Conexão com o armazenamento de triplas** + +O bibliotecário precisa emitir as bordas de metadados do documento diretamente para o grafo de conhecimento ao iniciar o processamento. +Adicione um cliente/publicador de armazenamento de triplas ao serviço do bibliotecário. +Na inicialização do processamento: emita os metadados do documento raiz como bordas do grafo (uma vez). + +**2. Vocabulário de tipo de documento** + +Padronize os valores de `document_type` para documentos filhos: +======= +**1. Nova interface: Conexão com o triple store** + +O librarian precisa emitir as bordas de metadados do documento diretamente para o knowledge graph ao iniciar o processamento. +Adicionar cliente/publicador do triple store ao serviço do librarian. +Na inicialização do processamento: emitir os metadados do documento raiz como bordas do grafo (uma vez). + +**2. Vocabulário de tipo de documento** + +Padronizar os valores de `document_type` para documentos filhos: +>>>>>>> 82edf2d (New md files from RunPod) +`source` - documento original carregado. +`page` - página extraída da fonte (PDF, etc.). +`chunk` - fragmento de texto derivado da página ou da fonte. + +#### Resumo das Alterações na Interface + +| Interface | Alteração | +|-----------|--------| +<<<<<<< HEAD +| Armazenamento de triplas | Nova conexão de saída - emita bordas de metadados do documento | +| Início do processamento | Emita metadados para o grafo antes de encaminhar o ID do documento | +======= +| Triple store | Nova conexão de saída - emitir bordas de metadados do documento | +| Início do processamento | Emitir metadados para o grafo antes de encaminhar o ID do documento | +>>>>>>> 82edf2d (New md files from RunPod) + +### Alterações no Extrator de PDF + +#### Estado Atual + +Recebe o conteúdo do documento (ou transmite documentos grandes). +Extrai texto das páginas PDF. +Transmite o conteúdo da página para o fragmentador. +<<<<<<< HEAD +Não interage com o bibliotecário ou o armazenamento de triplas. + +#### Alterações Necessárias + +**1. Nova interface: Cliente do bibliotecário** + +O extrator de PDF precisa salvar cada página como um documento filho no bibliotecário. +Adicione um cliente do bibliotecário ao serviço do extrator de PDF. +Para cada página: chame `add-child-document` com pai = ID do documento raiz. + +**2. Nova interface: Conexão com o armazenamento de triplas** + +O extrator de PDF precisa emitir bordas pai-filho para o grafo de conhecimento. +Adicione um cliente/publicador de armazenamento de triplas. +Para cada página: emita uma borda que vincule o documento da página ao documento pai. +======= +Não interage com o librarian ou o triple store. + +#### Alterações Necessárias + +**1. Nova interface: Cliente do librarian** + +O extrator de PDF precisa salvar cada página como um documento filho no librarian. +Adicionar cliente do librarian ao serviço do extrator de PDF. +Para cada página: chamar `add-child-document` com pai = ID do documento raiz. + +**2. Nova interface: Conexão com o triple store** + +O extrator de PDF precisa emitir bordas pai-filho para o knowledge graph. +Adicionar cliente/publicador do triple store. +Para cada página: emitir uma borda que vincule o documento da página ao documento pai. +>>>>>>> 82edf2d (New md files from RunPod) + +**3. Alterar o formato de saída** + +Em vez de encaminhar o conteúdo da página diretamente, encaminhe o ID do documento da página. +O Chunker buscará o conteúdo do "librarian" usando o ID. + +#### Resumo das Alterações na Interface + +| Interface | Mudança | +|-----------|--------| +| Librarian | Nova saída - salvar documentos filhos | +| Triple store | Nova saída - emitir arestas pai-filho | +| Mensagem de saída | Mudança de conteúdo para ID do documento | + +### Mudanças no Chunker + +#### Estado Atual + +Recebe conteúdo da página/texto +Divide em partes (chunks) +Encaminha o conteúdo da parte para processadores subsequentes +Sem interação com o "librarian" ou o "triple store" + +#### Mudanças Necessárias + +**1. Alterar o tratamento da entrada** + +Receber o ID do documento em vez do conteúdo, buscar do "librarian". +Adicionar cliente do "librarian" ao serviço do Chunker +Buscar o conteúdo da página usando o ID do documento + +**2. Nova interface: Cliente do "Librarian" (escrita)** + +Salvar cada parte como um documento filho no "librarian". +Para cada parte: chamar `add-child-document` com parent = ID do documento da página + +**3. Nova interface: Conexão com o "Triple store"** + +Emitir arestas pai-filho para o grafo de conhecimento. +Adicionar cliente/publicador do "triple store" +Para cada parte: emitir aresta ligando o documento da parte ao documento da página + +**4. Alterar o formato de saída** + +Encaminhar tanto o ID do documento da parte quanto o conteúdo da parte (otimização pós-chunker). +Os processadores subsequentes recebem o ID para rastreabilidade + o conteúdo para trabalhar + +#### Resumo das Alterações na Interface + +| Interface | Mudança | +|-----------|--------| +| Mensagem de entrada | Mudança de conteúdo para ID do documento | +| Librarian | Nova saída (leitura + escrita) - buscar conteúdo, salvar documentos filhos | +| Triple store | Nova saída - emitir arestas pai-filho | +| Mensagem de saída | Mudança de conteúdo-apenas para ID + conteúdo | + +### Mudanças no Extrator de Conhecimento + +#### Estado Atual + +Recebe conteúdo da parte +Extrai triplas e embeddings +Emite para o "triple store" e o "embedding store" +A relação `subjectOf` aponta para o documento de nível superior (não para a parte) + +#### Mudanças Necessárias + +**1. Alterar o tratamento da entrada** + +Receber o ID do documento da parte junto com o conteúdo. +Usar o ID da parte para rastreabilidade (o conteúdo já está incluído por otimização) + +**2. Atualizar a rastreabilidade das triplas** + +Ligar as triplas extraídas à parte (não ao documento de nível superior). +Usar a reificação para criar uma aresta apontando para a aresta +Relação `subjectOf`: tripla → ID do documento da parte +Primeiro uso do suporte de reificação existente + +**3. Atualizar a rastreabilidade dos embeddings** + +Ligar os IDs das entidades de embedding à parte. +Emitir aresta: ID da entidade de embedding → ID do documento da parte + +#### Resumo das Alterações na Interface + +| Interface | Mudança | +|-----------|--------| +| Mensagem de entrada | Esperar ID da parte + conteúdo (não apenas conteúdo) | +| Triple store | Usar reificação para rastreabilidade de tripla → parte | +| Rastreabilidade de embedding | Ligar ID da entidade → ID da parte | + +## Referências + +Rastreabilidade em tempo de consulta: `docs/tech-specs/query-time-provenance.md` +Padrão PROV-O para modelagem de rastreabilidade +Metadados de origem existentes no grafo de conhecimento (precisa de auditoria) diff --git a/docs/tech-specs/extraction-time-provenance.ru.md b/docs/tech-specs/extraction-time-provenance.ru.md new file mode 100644 index 00000000..e5966643 --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.ru.md @@ -0,0 +1,770 @@ +--- +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. + +## Обзор + +Этот документ содержит заметки о происхождении данных во время извлечения для будущих работ по спецификации. Происхождение данных во время извлечения фиксирует "исходный слой" - откуда данные были получены изначально, как они были извлечены и преобразованы. + +Это отличается от происхождения данных во время запроса (см. `query-time-provenance.md`), которое фиксирует логику работы агента. + +## Описание проблемы + +### Текущая реализация + +В настоящее время происхождение данных работает следующим образом: +Метаданные документа хранятся в виде RDF-триплетов в графе знаний. +Идентификатор документа связывает метаданные с документом, поэтому документ отображается как узел в графе. +Когда связи (отношения/факты) извлекаются из документов, связь `subjectOf` связывает извлеченную связь с исходным документом. + +### Проблемы текущего подхода + +1. **Повторная загрузка метаданных:** Метаданные документа группируются и загружаются повторно при каждой партии триплетов, извлеченных из этого документа. Это неэффективно и избыточно - одни и те же метаданные передаются как "груз" с каждым результатом извлечения. + +2. **Поверхностное происхождение данных:** Текущая связь `subjectOf` связывает факты только с верхним уровнем документа. Нет информации о цепочке преобразований - с какой страницы был получен факт, из какого фрагмента, какой метод извлечения был использован. + +### Желаемое состояние + +1. **Загрузка метаданных один раз:** Метаданные документа должны быть загружены один раз и привязаны к узлу верхнего уровня документа, а не повторяться с каждой партией триплетов. + +<<<<<<< HEAD +2. **Разветвленная структура данных о происхождении:** Захватите полную цепочку преобразований от исходного документа через все промежуточные артефакты до извлеченных фактов. Например, преобразование PDF-документа: +======= +2. **Разветвленная структура происхождения данных:** Захватите полную цепочку преобразований от исходного документа через все промежуточные артефакты до извлеченных фактов. Например, преобразование PDF-документа: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +<<<<<<< HEAD +3. **Унифицированное хранилище:** Граф происхождения хранится в той же базе знаний, что и извлеченные знания. Это позволяет запрашивать происхождение так же, как и знания, прослеживая связи обратно по цепочке от любого факта к его точному источнику. +======= +3. **Унифицированное хранилище:** Граф происхождения хранится в той же базе знаний, что и извлеченные знания. Это позволяет запрашивать происхождение так же, как и знания, прослеживая связи вверх по цепочке от любого факта к его точному источнику. +>>>>>>> 82edf2d (New md files from RunPod) + +4. **Стабильные идентификаторы:** Каждый промежуточный артефакт (страница, фрагмент) имеет стабильный идентификатор в виде узла в графе. + +5. **Связь родитель-потомок:** Производные документы связаны с их родительскими документами до самого верхнего уровня, используя согласованные типы отношений. + +6. **Точное определение источника факта:** Отношение `subjectOf` на извлеченных связях указывает на непосредственный родительский элемент (фрагмент), а не на верхний документ. Полное происхождение восстанавливается путем прохода по графу. + +## Случаи использования + +### UC1: Определение источника в ответах GraphRAG + +**Сценарий:** Пользователь выполняет запрос GraphRAG и получает ответ от агента. + +**Процесс:** +1. Пользователь отправляет запрос агенту GraphRAG. +2. Агент извлекает соответствующие факты из базы знаний для формирования ответа. +<<<<<<< HEAD +3. В соответствии со спецификацией происхождения во время запроса, агент сообщает, какие факты внесли вклад в ответ. +======= +3. В соответствии со спецификацией происхождения для запросов, агент сообщает, какие факты послужили основой для ответа. +>>>>>>> 82edf2d (New md files from RunPod) +4. Каждый факт связан с его исходным фрагментом через граф происхождения. +5. Фрагменты связаны со страницами, страницы связаны с исходными документами. + +**Результат для пользователя:** Интерфейс отображает ответ LLM вместе с указанием источника. Пользователь может: +<<<<<<< HEAD +Увидеть, какие факты подтверждают ответ. +Переходить от фактов к фрагментам, страницам и документам. +Просматривать исходные документы для проверки утверждений. +Понимать, откуда в документе (на какой странице, в каком разделе) произошел факт. +======= +Увидеть, какие факты послужили основой для ответа. +Переходить от фактов к фрагментам, страницам и документам. +Просматривать исходные документы для проверки утверждений. +Понимать, откуда в документе (на какой странице, в каком разделе) произошел тот или иной факт. +>>>>>>> 82edf2d (New md files from RunPod) + +**Преимущество:** Пользователи могут проверять ответы, сгенерированные ИИ, по сравнению с первичными источниками, что повышает доверие и позволяет проводить проверку фактов. + +### UC2: Отладка качества извлечения + +<<<<<<< HEAD +Факт кажется неверным. Проследите обратно через фрагмент, страницу и документ, чтобы увидеть исходный текст. Это была ошибка извлечения, или исходный документ был неверным? + +### UC3: Инкрементное повторное извлечение + +Исходный документ обновлен. Какие фрагменты/факты были получены из него? Отмените и перезапустите только эти, а не перерабатывайте все. + +### UC4: Удаление данных / Право на забвение + +Исходный документ должен быть удален (GDPR, юридические требования и т.д.). Найдите и удалите все производные факты, пройдя по графу. + +### UC5: Разрешение конфликтов + +Два факта противоречат друг другу. Проследите оба обратно к их источникам, чтобы понять, почему, и решить, кому доверять (более авторитетному источнику, более свежему и т.д.). +======= +Факт кажется неверным. Проследите по цепочке от фрагмента к странице и документу, чтобы увидеть исходный текст. Была ли это ошибка извлечения, или исходный текст был неверным? + +### UC3: Инкрементное повторное извлечение + +Исходный документ был обновлен. Какие фрагменты/факты были получены из него? Отмените и перегенерируйте только эти, а не перерабатывайте все. + +### UC4: Удаление данных / Право на забвение + +Исходный документ должен быть удален (GDPR, юридические требования и т.д.). Пройдите по графу, чтобы найти и удалить все производные факты. + +### UC5: Разрешение конфликтов + +Два факта противоречат друг другу. Проследите оба факта до их источников, чтобы понять причину и решить, кому доверять (более авторитетному источнику, более свежему и т.д.). +>>>>>>> 82edf2d (New md files from RunPod) + +### UC6: Взвешивание авторитетности источника + +Некоторые источники более авторитетны, чем другие. Факты могут быть взвешены или отфильтрованы на основе авторитетности/качества исходных документов. + +### UC7: Сравнение конвейеров извлечения + +Сравните результаты, полученные с использованием различных методов/версий извлечения. Какой экстрактор выдал лучшие факты из одного и того же источника? + +## Точки интеграции + +### Библиотекарь + +Компонент "библиотекарь" уже предоставляет хранение документов с уникальными идентификаторами документов. Система отслеживания происхождения интегрируется с существующей инфраструктурой. + +#### Существующие возможности (уже реализовано) + +**Связывание документов "родитель-потомок":** +Поле `parent_id` в `DocumentMetadata` - связывает дочерний документ с родительским документом. +<<<<<<< HEAD +Поле `document_type` - значения: `"source"` (оригинальный) или `"extracted"` (производный). +======= +Поле `document_type` - значения: `"source"` (исходный) или `"extracted"` (производный). +>>>>>>> 82edf2d (New md files from RunPod) +API `add-child-document` - создает дочерний документ с автоматическим `document_type = "extracted"`. +API `list-children` - извлекает все дочерние документы родительского документа. +Каскадное удаление - удаление родительского документа автоматически удаляет все дочерние документы. + +**Идентификация документов:** +Идентификаторы документов задаются клиентом (не генерируются автоматически). +Документы индексируются по составному ключу `(user, document_id)` в Cassandra. +Объектные идентификаторы (UUID) генерируются внутренне для хранения двоичных данных. + +**Поддержка метаданных:** +Поле `metadata: list[Triple]` - тройки RDF для структурированных метаданных. +`title`, `comments`, `tags` - основные метаданные документа. +`time` - метка времени, `kind` - MIME-тип. + +**Архитектура хранения:** +Метаданные хранятся в Cassandra (пространство ключей `librarian`, таблица `document`). +Содержимое хранится в хранилище двоичных данных MinIO/S3 (контейнер `library`). +Интеллектуальная доставка контента: документы размером менее 2 МБ встраиваются, более крупные документы передаются потоком. + +#### Основные файлы + +`trustgraph-flow/trustgraph/librarian/librarian.py` - Основные операции "библиотекаря". +`trustgraph-flow/trustgraph/librarian/service.py` - Сервисный процессор, загрузка документов. +`trustgraph-flow/trustgraph/tables/library.py` - Хранилище таблиц Cassandra. +`trustgraph-base/trustgraph/schema/services/library.py` - Определения схемы. + +<<<<<<< HEAD +#### Необходимые улучшения +======= +#### Проблемы, требующие решения +>>>>>>> 82edf2d (New md files from RunPod) + +"Библиотекарь" имеет необходимые компоненты, но в настоящее время: +1. Связывание "родитель-потомок" ограничено одним уровнем - отсутствуют вспомогательные функции для обхода многоуровневых графов. +2. Отсутствует стандартная терминология для типов отношений (например, `derivedFrom`, `extractedFrom`). +<<<<<<< HEAD +3. Метаданные происхождения (метод извлечения, уверенность, позиция фрагмента) не стандартизированы. +======= +3. Метаданные происхождения (метод извлечения, достоверность, позиция фрагмента) не стандартизированы. +>>>>>>> 82edf2d (New md files from RunPod) +4. Отсутствует API запросов для прослеживания полной цепочки происхождения от факта до исходного источника. + +## Проектирование сквозного потока + +Каждый процессор в конвейере следует последовательной схеме: +Получает идентификатор документа от предыдущего этапа. +Извлекает содержимое из "библиотекаря". +Создает дочерние артефакты. +Для каждого дочернего элемента: сохраняет в "библиотекаре", создает связь в графе и передает идентификатор на следующий этап. + +### Потоки обработки + +Существуют два потока в зависимости от типа документа: + +#### Поток обработки документов PDF + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### Поток текстовых документов + +Текстовые документы пропускают этап извлечения из PDF и сразу поступают в компоновщик: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +Полученный ориентированный ациклический граф (DAG) имеет на один уровень меньше: + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +Дизайн учитывает оба варианта, поскольку компонент, разделяющий текст на части, обрабатывает входные данные универсально - он использует любой идентификатор документа, который он получает, в качестве родительского, независимо от того, является ли это исходным документом или страницей. + +### Схема метаданных (PROV-O) + +Метаданные происхождения используют онтологию W3C PROV-O. Это обеспечивает стандартный словарь и позволяет в будущем осуществлять подпись/аутентификацию результатов извлечения. + +#### Основные концепции PROV-O + +| Тип PROV-O | Использование в TrustGraph | +|-------------|------------------| +| `prov:Entity` | Документ, страница, фрагмент, тройка, вложение | +| `prov:Activity` | Экземпляры операций извлечения | +| `prov:Agent` | Компоненты TG (извлечение PDF, компонент, разделяющий текст на части и т.д.) с версиями | + +#### Отношения PROV-O + +| Предикат | Значение | Пример | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | Сущность, полученная из другой сущности | Страница была получена из документа | +| `prov:wasGeneratedBy` | Сущность, сгенерированная действием | Страница была сгенерирована действием извлечения PDF | +| `prov:used` | Действие, использующее сущность в качестве входных данных | Действие извлечения PDF использовало документ | +| `prov:wasAssociatedWith` | Действие, выполненное агентом | Действие извлечения PDF было связано с tg:PDFExtractor | + +#### Метаданные на каждом уровне + +**Исходный документ (генерируется Librarian):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +**Страница (сгенерирована извлечением из PDF):** +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +<<<<<<< HEAD +**Раздел (выдан разделителем):** +======= +**Раздел (выдан Компоновщиком):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +<<<<<<< HEAD +**Жирный шрифт (вывод Knowledge Extractor):** +======= +**Жирный шрифт (выделен извлечением знаний):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +<<<<<<< HEAD +**Встраивание (хранится в векторной базе данных, а не в тройной базе данных):** +======= +**Встраивания (хранятся в векторной базе данных, а не в тройной базе данных):** +>>>>>>> 82edf2d (New md files from RunPod) + +Встраивания хранятся в векторной базе данных вместе с метаданными, а не в виде RDF-троек. Каждая запись встраивания содержит: + +| Поле | Описание | Пример | +|-------|-------------|---------| +| vector | Вектор встраивания | [0.123, -0.456, ...] | +| entity | URI узла, который представляет встраивание | `entity:JohnSmith` | +| chunk_id | Исходный фрагмент (происхождение) | `chunk:123-1-1` | +| model | Используемая модель встраивания | `text-embedding-ada-002` | +| component_version | Версия компонента TG | `1.0.0` | + +<<<<<<< HEAD +Поле `entity` связывает встраивание с графом знаний (URI узла). Поле `chunk_id` предоставляет информацию о происхождении, указывающую на исходный фрагмент, что позволяет проследить путь до исходного документа. +======= +Поле `entity` связывает встраивание с графом знаний (URI узла). Поле `chunk_id` предоставляет информацию о происхождении, указывающую на исходный фрагмент, что позволяет проследить путь вверх по DAG к исходному документу. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Расширения пространства имен TrustGraph + +Пользовательские предикаты в пространстве имен `tg:` для метаданных, специфичных для извлечения: + +| Предикат | Область | Описание | +|-----------|--------|-------------| +| `tg:contains` | Подграф | Указывает на тройку, содержащуюся в этом подграфе извлечения | +| `tg:pageCount` | Документ | Общее количество страниц в исходном документе | +| `tg:mimeType` | Документ | MIME-тип исходного документа | +| `tg:pageNumber` | Страница | Номер страницы в исходном документе | +<<<<<<< HEAD +| `tg:chunkIndex` | Фрагмент | Индекс фрагмента внутри родительского фрагмента | +======= +| `tg:chunkIndex` | Фрагмент | Индекс фрагмента внутри родительского элемента | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:charOffset` | Фрагмент | Смещение символов в родительском тексте | +| `tg:charLength` | Фрагмент | Длина фрагмента в символах | +| `tg:chunkSize` | Действие | Настроенный размер фрагмента | +| `tg:chunkOverlap` | Действие | Настроенное перекрытие между фрагментами | +| `tg:componentVersion` | Действие | Версия компонента TG | +| `tg:llmModel` | Действие | LLM, используемый для извлечения | +| `tg:ontology` | Действие | URI онтологии, используемой для управления извлечением | +| `tg:embeddingModel` | Действие | Модель, используемая для встраиваний | +| `tg:sourceText` | Утверждение | Точный текст, из которого была извлечена тройка | +| `tg:sourceCharOffset` | Утверждение | Смещение символов внутри фрагмента, где начинается исходный текст | +| `tg:sourceCharLength` | Утверждение | Длина исходного текста в символах | + +#### Начальная загрузка словаря (для каждой коллекции) + +<<<<<<< HEAD +Граф знаний является онтологически нейтральным и изначально пуст. При первом добавлении данных о происхождении PROV-O в коллекцию словарь должен быть инициализирован с помощью RDF-меток для всех классов и предикатов. Это обеспечивает удобочитаемое отображение в запросах и пользовательском интерфейсе. +======= +Граф знаний является онтологически нейтральным и изначально пуст. При записи данных о происхождении PROV-O в коллекцию в первый раз словарь должен быть инициализирован с помощью меток RDF для всех классов и предикатов. Это обеспечивает удобочитаемое отображение в запросах и пользовательском интерфейсе. +>>>>>>> 82edf2d (New md files from RunPod) + +**Классы PROV-O:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**Предикаты PROV-O:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**Предикаты TrustGraph:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**Примечания по реализации:** Этот механизм начальной загрузки словаря должен быть идемпотентным, то есть его можно безопасно запускать несколько раз без создания дубликатов. Его можно запускать при первой обработке документа в коллекции или как отдельный этап инициализации коллекции. + +#### Происхождение подраздела (желательно) + +Для более детальной информации о происхождении полезно записывать, из какой именно части фрагмента была извлечена тройка. Это позволяет: +======= +**Примечания по реализации:** Этот начальный набор словаря должен быть идемпотентным - его можно безопасно запускать несколько раз без создания дубликатов. Его можно запускать при первой обработке документа в коллекции или как отдельный этап инициализации коллекции. + +#### Происхождение под-фрагментов (желательно) + +Для более детальной информации о происхождении, было бы полезно записывать, из какой именно части фрагмента была извлечена тройка. Это позволяет: +>>>>>>> 82edf2d (New md files from RunPod) + +Выделять точный исходный текст в пользовательском интерфейсе +Проверять точность извлечения по отношению к исходному тексту +Отлаживать качество извлечения на уровне предложений + +**Пример с отслеживанием позиции:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**Пример с выделением текста (альтернативный):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**Соображения по реализации:** + +Извлечение на основе LLM может не всегда предоставлять информацию о позициях символов. +<<<<<<< HEAD +Можно запросить LLM, чтобы он возвращал исходное предложение/фразу вместе с извлеченными тройками. +======= +Можно запросить LLM, чтобы она возвращала исходное предложение/фразу вместе с извлеченными тройками. +>>>>>>> 82edf2d (New md files from RunPod) +Альтернативно, можно выполнить постобработку для сопоставления извлеченных сущностей с исходным текстом. +Компромисс между сложностью извлечения и детализацией происхождения. +Может быть проще реализовать с использованием структурированных методов извлечения, чем с использованием LLM для извлечения в свободной форме. + +<<<<<<< HEAD +Это обозначено как перспективное направление - сначала следует реализовать базовое отслеживание происхождения на уровне фрагментов, а отслеживание подфрагментов следует рассматривать как улучшение в будущем, если это будет возможно. + +### Двухуровневая модель хранения + +Граф происхождения строится постепенно по мере прохождения документов через конвейер: + +| Хранилище | Что хранится | Назначение | +|-------|---------------|---------| +| Библиотекарь | Содержимое документа + ссылки "родитель-потомок" | Извлечение содержимого, каскадное удаление | +| Граф знаний | Ребра "родитель-потомок" + метаданные | Запросы происхождения, атрибуция фактов | + +Оба хранилища поддерживают одну и ту же структуру графа. Библиотекарь хранит содержимое, а граф хранит отношения и обеспечивает возможности запросов для обхода. +======= +Это обозначено как перспективное направление - сначала следует реализовать базовое отслеживание происхождения на уровне фрагментов, а отслеживание подфрагментов следует рассматривать как улучшение в будущем, если это возможно. + +### Двухуровневая модель хранения + +Граф происхождения строится постепенно по мере прохождения документов по конвейеру: + +| Хранилище | Что хранится | Назначение | +|-------|---------------|---------| +| Библиотекарь | Содержимое документа + ссылки родитель-потомок | Извлечение содержимого, каскадное удаление | +| Граф знаний | Ребра родитель-потомок + метаданные | Запросы происхождения, атрибуция фактов | + +Оба хранилища поддерживают одну и ту же структуру графа. Библиотекарь хранит содержимое, а граф хранит отношения и обеспечивает возможность выполнения запросов для обхода графа. +>>>>>>> 82edf2d (New md files from RunPod) + +### Основные принципы проектирования + +1. **Идентификатор документа как единица потока данных** - Процессоры передают идентификаторы, а не содержимое. Содержимое извлекается из библиотеки, когда это необходимо. + +<<<<<<< HEAD +2. **Отправка данных только в исходной точке** - Метаданные записываются в граф только один раз при начале обработки, а не повторяются далее по цепочке. +======= +2. **Однократная отправка данных в источнике** - Метаданные записываются в граф один раз при начале обработки, а не повторяются далее по цепочке. +>>>>>>> 82edf2d (New md files from RunPod) + +3. **Единый шаблон для процессоров** - Каждый процессор следует одному и тому же шаблону: прием/извлечение/создание/сохранение/отправка/передача. + +4. **Постепенное построение графа** - Каждый процессор добавляет свой уровень в граф. Полная цепочка происхождения строится постепенно. + +5. **Оптимизация после разбиения на фрагменты** - После разбиения на фрагменты сообщения содержат как идентификатор, так и содержимое. Фрагменты небольшие (2-4 КБ), поэтому включение содержимого позволяет избежать ненужных обращений к библиотеке, сохраняя при этом происхождение с помощью идентификатора. + +## Задачи реализации + +### Изменения в библиотеке + +#### Текущее состояние + +Инициирует обработку документа, отправляя идентификатор документа первому процессору. +Нет подключения к хранилищу тройных данных - метаданные добавляются к результатам извлечения. +<<<<<<< HEAD +`add-child-document` создает одноуровневые ссылки "родитель-потомок". +======= +`add-child-document` создает одноуровневые ссылки родитель-потомок. +>>>>>>> 82edf2d (New md files from RunPod) +`list-children` возвращает только непосредственные потомки. + +#### Необходимые изменения + +**1. Новый интерфейс: Подключение к хранилищу тройных данных** + +Библиотекарь должен напрямую отправлять ребра метаданных документа в граф знаний при начале обработки. +Добавить клиент/публикатор хранилища тройных данных в сервис библиотеки. +При инициации обработки: отправлять метаданные корневого документа в виде ребер графа (один раз). + +**2. Словарь типов документов** + +<<<<<<< HEAD +Стандартизировать значения `document_type` для дочерних документов: +======= +Стандартизировать значения `document_type` для документов-потомков: +>>>>>>> 82edf2d (New md files from RunPod) +`source` - исходный загруженный документ. +`page` - страница, извлеченная из источника (PDF и т.д.). +`chunk` - текстовый фрагмент, полученный из страницы или источника. + +#### Краткое описание изменений интерфейса + +| Интерфейс | Изменение | +|-----------|--------| +| Хранилище тройных данных | Новый исходящий канал - отправка ребер метаданных документа | +| Инициация обработки | Отправка метаданных в граф перед передачей идентификатора документа | + +<<<<<<< HEAD +### Изменения в извлечении данных из PDF +======= +### Изменения в извлечении PDF +>>>>>>> 82edf2d (New md files from RunPod) + +#### Текущее состояние + +Получает содержимое документа (или потоковую передачу больших документов). +Извлекает текст из страниц PDF. +Передает содержимое страницы в компоновщик. +Не взаимодействует с библиотекой или хранилищем тройных данных. + +#### Необходимые изменения + +**1. Новый интерфейс: Клиент библиотеки** + +<<<<<<< HEAD +Извлечение данных из PDF должно сохранять каждую страницу как дочерний документ в библиотеке. +Добавить клиент библиотеки в сервис извлечения данных из PDF. +======= +Извлечение PDF должно сохранять каждую страницу как документ-потомок в библиотеке. +Добавить клиент библиотеки в сервис извлечения PDF. +>>>>>>> 82edf2d (New md files from RunPod) +Для каждой страницы: вызвать `add-child-document` с parent = идентификатор корневого документа. + +**2. Новый интерфейс: Подключение к хранилищу тройных данных** + +<<<<<<< HEAD +Извлечение данных из PDF должно отправлять ребра "родитель-потомок" в граф знаний. +======= +Извлечение PDF должно отправлять ребра родитель-потомок в граф знаний. +>>>>>>> 82edf2d (New md files from RunPod) +Добавить клиент/публикатор хранилища тройных данных. +Для каждой страницы: отправлять ребро, связывающее документ страницы с родительским документом. + +**3. Изменить формат вывода** + +Вместо прямой передачи содержимого страницы, передавайте идентификатор документа страницы. +Chunker будет извлекать содержимое из хранилища, используя идентификатор. + +#### Краткое описание изменений интерфейса + +| Интерфейс | Изменение | +|-----------|--------| +| Хранилище | Новый исходящий поток - сохранение дочерних документов | +| Тройной магазин | Новый исходящий поток - генерация связей родитель-потомок | +| Сообщение вывода | Изменение с содержимого на идентификатор документа | + +<<<<<<< HEAD +### Изменения Chunker +======= +### Изменения в Chunker +>>>>>>> 82edf2d (New md files from RunPod) + +#### Текущее состояние + +Получает содержимое страницы/текста +Разбивает на фрагменты +Передает содержимое фрагмента обработчикам на последующих этапах +Не взаимодействует с хранилищем или тройным магазином + +#### Необходимые изменения + +**1. Изменение обработки входных данных** + +Вместо содержимого получайте идентификатор документа, извлекайте из хранилища. +Добавьте клиент хранилища в сервис Chunker +Извлекайте содержимое страницы, используя идентификатор документа + +**2. Новый интерфейс: Клиент хранилища (запись)** + +Сохраняйте каждый фрагмент как дочерний документ в хранилище. +Для каждого фрагмента: вызывайте `add-child-document` с parent = идентификатор документа страницы + +**3. Новый интерфейс: Подключение к тройному магазину** + +Генерируйте связи родитель-потомок для графа знаний. +Добавьте клиент/публикатор тройного магазина +Для каждого фрагмента: генерируйте связь, связывающую документ фрагмента с документом страницы + +**4. Изменение формата вывода** + +Передавайте как идентификатор документа фрагмента, так и содержимое фрагмента (оптимизация после обработки фрагмента). +Обработчики на последующих этапах получают идентификатор для отслеживания происхождения + содержимое для работы + +#### Краткое описание изменений интерфейса + +| Интерфейс | Изменение | +|-----------|--------| +| Сообщение ввода | Изменение с содержимого на идентификатор документа | +| Хранилище | Новый исходящий поток (чтение + запись) - извлечение содержимого, сохранение дочерних документов | +| Тройной магазин | Новый исходящий поток - генерация связей родитель-потомок | +| Сообщение вывода | Изменение с содержимого только на идентификатор + содержимое | + +<<<<<<< HEAD +### Изменения Knowledge Extractor +======= +### Изменения в Knowledge Extractor +>>>>>>> 82edf2d (New md files from RunPod) + +#### Текущее состояние + +Получает содержимое фрагмента +Извлекает тройки и вложения +<<<<<<< HEAD +Передает в тройной магазин и хранилище вложений +======= +Отправляет в тройной магазин и хранилище вложений +>>>>>>> 82edf2d (New md files from RunPod) +`subjectOf` отношение указывает на верхний уровень документа (а не на фрагмент) + +#### Необходимые изменения + +**1. Изменение обработки входных данных** + +<<<<<<< HEAD +Получайте идентификатор фрагмента вместе с содержимым. +======= +Получайте идентификатор документа фрагмента вместе с содержимым. +>>>>>>> 82edf2d (New md files from RunPod) +Используйте идентификатор фрагмента для отслеживания происхождения (содержимое уже включено в соответствии с оптимизацией) + +**2. Обновление отслеживания происхождения тройками** + +Связывайте извлеченные тройки с фрагментом (а не с верхним уровнем документа). +Используйте реификацию для создания связи, указывающей на связь +`subjectOf` отношение: тройка → идентификатор документа фрагмента +Первое использование существующей поддержки реификации + +**3. Обновление отслеживания происхождения вложениями** + +Связывайте идентификаторы сущностей вложений с фрагментом. +Генерируйте связь: идентификатор сущности вложения → идентификатор документа фрагмента + +#### Краткое описание изменений интерфейса + +| Интерфейс | Изменение | +|-----------|--------| +| Сообщение ввода | Ожидается идентификатор фрагмента + содержимое (а не только содержимое) | +| Тройной магазин | Используйте реификацию для отслеживания происхождения тройки → фрагмент | +<<<<<<< HEAD +| Отслеживание происхождения вложениями | Свяжите идентификатор сущности → идентификатор фрагмента | +======= +| Отслеживание происхождения вложений | Свяжите идентификатор сущности → идентификатор фрагмента | +>>>>>>> 82edf2d (New md files from RunPod) + +## Ссылки + +Отслеживание происхождения во время запроса: `docs/tech-specs/query-time-provenance.md` +Стандарт PROV-O для моделирования происхождения +Существующие метаданные источника в графе знаний (требуется аудит) diff --git a/docs/tech-specs/extraction-time-provenance.sw.md b/docs/tech-specs/extraction-time-provenance.sw.md new file mode 100644 index 00000000..dddc32a5 --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.sw.md @@ -0,0 +1,935 @@ +--- +layout: default +title: "Asili ya Data Wakati wa Utoaji: Safu ya Chanzo" +parent: "Swahili (Beta)" +--- + +<<<<<<< HEAD +# Asili ya Data Wakati wa Utoaji: Safu ya Chanzo + +> **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 ina rekodi za maelezo kuhusu asili ya data wakati wa utoaji kwa ajili ya kazi ya maelezo ya baadaye. Asili ya data wakati wa utoaji inarejelea "safu ya chanzo" - ambako data ilitoka awali, jinsi ilivyochukuliwa na kubadilishwa. + +Hii ni tofauti na asili ya data wakati wa kuulizia (angalia `query-time-provenance.md`) ambayo inarejelea utaratibu wa akili wa mhusika. + +## Tatizo + +### Utendaji wa Sasa + +Hivi sasa, asili ya data inafanya kazi kama ifuatavyo: +Meta-data ya hati huhifadhiwa kama triple za RDF katika grafu ya maarifa. +Kitambulisho cha hati huunganisha meta-data na hati, hivyo hati inaonekana kama node katika grafu. +Wakati uhusiano (maelezo/ukweli) unachukuliwa kutoka kwa hati, uhusiano wa `subjectOf` huunganisha uhusiano uliochukuliwa na hati ya chanzo. + +### Matatizo ya Mbinu ya Sasa + +1. **Upakiaji wa meta-data unaorudia:** Meta-data ya hati huunganishwa na kupakiwa mara kwa mara na kila kundi la triple zilizochukuliwa kutoka kwa hati hiyo. Hii ni matumizi ya rasilimali na kurudia - meta-data sawa husafiri kama mizigo na kila pato la utoaji. + +2. **Asili ya data ya juu:** Uhusiano wa `subjectOf` wa sasa huunganisha tu ukweli moja kwa moja na hati ya juu. Hakuna uonevu katika mnyororo wa mabadiliko - ukweli huo ulichukuliwa kutoka kwa ukurasa gani, sehemu gani, mbinu gani ya utoaji iliyotumika. + +### Hali Inayotakikana + +1. **Pakia meta-data mara moja:** Meta-data ya hati inapaswa kupakiwa mara moja na kuunganishwa na node ya juu ya hati, sio kurudiwa na kila kundi la triple. + +2. **Grafu ya asili ya data iliyo na maelezo:** Rekodi mnyororo kamili wa mabadiliko kutoka kwa hati ya chanzo hadi kwa vitu vyote vya kati hadi kwa ukweli uliopatikana. Kwa mfano, mabadiliko ya hati ya PDF: +======= +# Asili ya Data Wakati wa Uvunaji: Safu ya Chanzo + +## Muhtasari + +Hati hii ina rekodi za maelezo kuhusu asili ya data wakati wa uvunaji kwa ajili ya kazi zijazo za kubuni. Asili ya data wakati wa uvunaji inarejelea "safu ya chanzo" - ambako data ilitoka awali, jinsi ilivyovunwa na kubadilishwa. + +Hii ni tofauti na asili ya data wakati wa utafutaji (angalia `query-time-provenance.md`) ambayo inarejelea hoja za msimuizi. + +## Tatizo + +### Utendaji Sasa + +Hivi sasa, asili ya data inafanya kazi kama ifuatavyo: +Meta-data ya hati inahifadhiwa kama triple za RDF katika grafu ya maarifa. +Kitambulisho cha hati (document ID) huunganisha meta-data na hati, hivyo hati inaonekana kama nodi katika grafu. +Wakati uhusiano (relationships/facts) unavyovunwa kutoka kwa hati, uhusiano wa `subjectOf` huunganisha uhusiano uliovunwa na hati ya asili. + +### Matatizo ya Mbinu Hali + +1. **Upakiaji wa meta-data unaorudia-rudia:** Meta-data ya hati huunganishwa na kupakiwa mara kwa mara na kila kundi la triple zinazovunwa kutoka kwa hati hiyo. Hii ni matumizi ya rasilimali na kurudia - meta-data sawa husafiri kama mizigo na kila matokeo ya uvunaji. + +2. **Asili ya data ya kawaida:** Uhusiano wa `subjectOf` unaoonekana sasa huunganisha tu ukweli moja kwa moja na hati ya juu. Hakuna uwazi kuhusu mnyororo wa mabadiliko - ukurasa gani ukweli ulikuja, kipande gani, njia gani ya uvunaji iliyotumika. + +### Hali Inayotakikana + +1. **Pakia meta-data mara moja:** Meta-data ya hati inapaswa kupakiwa mara moja na kuunganishwa na nodi ya hati ya juu, sio kurudiwa na kila kundi la triple. + +2. **Grafu ya asili ya data yenye maelezo:** Rekodi mnyororo kamili wa mabadiliko kutoka kwa hati ya asili kupitia kwa vitu vyote vya kati hadi kwa ukweli uliovunwa. Kwa mfano, mabadiliko ya hati ya PDF: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +3. **Hifadhi iliyounganishwa:** Mfumo wa uhusiano wa asili (provenance DAG) huhifadhiwa katika mfumo sawa wa maarifa kama maarifa yaliyopatikana. Hii inaruhusu uhusiano wa asili kuchunguzwa kwa njia ile ile kama maarifa - kufuata miundo kurudi nyuma kutoka kwa ukweli wowote hadi mahali pake halisi. + +4. **Kitambulisho cha kudumu:** Kila kitu (artifact) cha kati (ukurasa, sehemu) kina kitambulisho cha kudumu kama node katika mfumo. + +<<<<<<< HEAD +5. **Uunganisho wa mzazi-mtoto:** Hati zilizoundwa zinaunganishwa na wazazi wao hadi kwenye hati ya asili ya juu kwa kutumia aina za uhusiano sawa. + +6. **Uhusiano sahihi wa ukweli:** Uhusiano wa `subjectOf` kwenye miundo iliyopatikana unaelekeza kwenye mzazi wa karibu (sehemu), sio kwenye hati ya juu. Uhusiano wa asili kamili hupatikana kwa kutembea juu ya DAG. +======= +5. **Uunganisho wa mzazi-mtoto:** Hati zilizoundwa zinaunganishwa na wazazi wao hadi hati ya asili ya juu zaidi kwa kutumia aina za uhusiano sawa. + +6. **Uhusiano sahihi wa ukweli:** Uhusiano wa `subjectOf` kwenye miundo iliyopatikana unaelekeza kwa mzazi wa karibu (sehemu), sio hati ya juu. Uhusiano wa asili kamili hupatikana kwa kutembea juu ya DAG. +>>>>>>> 82edf2d (New md files from RunPod) + +## Matumizi + +### UC1: Uhusiano wa Chanzo katika Majibu ya GraphRAG + +**Hali:** Mtumiaji hufanya swali la GraphRAG na kupokea jibu kutoka kwa programu (agent). + +**Mchakato:** +1. Mtumiaji huwasilisha swali kwa programu ya GraphRAG. +2. Programu inapata ukweli unaohusiana kutoka kwa mfumo wa maarifa ili kuunda jibu. +3. Kulingana na vipimo vya uhusiano wa asili wakati wa swali, programu huripoti ukweli ambao ulichangia jibu. +4. Kila ukweli unaunganishwa na sehemu yake ya asili kupitia mfumo wa uhusiano wa asili. +5. Sehemu zinaunganishwa na kurasa, kurasa zinaunganishwa na hati za asili. + +**Matokeo ya Uzoefu wa Mtumiaji (UX):** Kiolesura huonyesha jibu la LLM pamoja na uhusiano wa chanzo. Mtumiaji anaweza: +Kuona ukweli ambao uliunga mkono jibu. +Kuchunguza kutoka kwa ukweli → sehemu → kurasa → hati. +Kusoma hati za asili ili kuthibitisha madai. +Kuelewa hasa wapi katika hati (ukurasa gani, sehemu gani) ukweli ulitoka. + +**Faida:** Watumiaji wanaweza kuthibitisha majibu yaliyozalishwa na AI dhidi ya vyanzo vya msingi, kuunda uaminifu na kuwezesha ukaguzi wa ukweli. + +### UC2: Kurekebisha Ubora wa Upatikanaji + +<<<<<<< HEAD +Ukweli unaonekana kuwa mbaya. Tembelea kurudi nyuma kupitia sehemu → ukurasa → hati ili kuona maandishi ya asili. Je, ilikuwa upatikanaji mbaya, au chanzo kilikuwa kibaya? + +### UC3: Upatikanaji wa Kurekebishwa + +Hati ya asili inasasishwa. Ni sehemu/ukweli gani uliotokana nayo? Ghairi na uundue tena tu zile, badala ya kuchakata kila kitu. + +### UC4: Ufutilishaji wa Data / Haki ya Kusahau + +Hati ya asili lazima iondolewe (GDPR, kisheria, n.k.). Tembelea DAG ili kupata na kuondoa ukweli wote uliotokana. + +### UC5: Suluhisho la Mzozo + +Ushawishi mbili unapingana. Tembelea zote kurudi kwenye vyanzo vyao ili kuelewa kwa nini na uamue ni ipi ya kuamini (chanzo cha mamlaka zaidi, cha hivi karibuni, n.k.). + +### UC6: Uzito wa Uamuzi wa Chanzo + +Vyanzo vingine ni vya mamlaka kuliko vingine. Ushawishi unaweza kupimwa au kuchujwa kulingana na uamuzi/ubora wa hati zao za asili. +======= +Ukweli unaonekana kuwa mbaya. Rudi nyuma kupitia sehemu → ukurasa → hati ili kuona maandishi ya asili. Je, ilikuwa upatikanaji mbaya, au chanzo kilikuwa kibaya? + +### UC3: Upatikanaji wa Kurekebishwa + +Hati ya asili inasasishwa. Ni sehemu/ukweli zipi zilizotokana nayo? Ghairi na uundue tena zile tu, badala ya kuchakata kila kitu. + +### UC4: Ufutilishaji wa Data / Haki ya Kusahau + +Hati ya asili lazima iondolewe (GDPR, kisheria, n.k.). Tembea kwenye DAG ili kupata na kuondoa ukweli wote uliotokana. + +### UC5: Suluhisho la Mzozo + +Ushawishi mbili unapingana. Rudi nyuma kwa vyanzo vyake ili kuelewa kwa nini na uamue ni ipi ya kuamini (chanzo cha mamlaka zaidi, cha hivi karibuni, n.k.). + +### UC6: Uzito wa Mamlaka ya Chanzo + +Vyanzo vingine ni vya mamlaka kuliko vingine. Ushawishi unaweza kupimwa au kuchujwa kulingana na mamlaka/ubora wa hati zake za asili. +>>>>>>> 82edf2d (New md files from RunPod) + +### UC7: Ulinganisho wa Mfumo wa Upatikanaji + +Linganisha matokeo kutoka kwa mbinu/matoleo tofauti ya upatikanaji. Mfumo wa upatikanaji upi uliunda ukweli bora kutoka kwa chanzo kimoja? + +## Maeneo ya Uunganisho + +### Msimamizi wa Maktaba + +<<<<<<< HEAD +Kifaa cha msimamizi wa maktaba hutoa tayari uhifadhi wa hati na kitambulisho cha kipekee cha hati. Mfumo wa asili unajumuishwa na miundombinu hii iliyopo. + +#### Uwezo Ulioopo (tayari umetekelezwa) + +**Uunganisho wa Hati ya Mzazi-Mtoto:** +======= +Kifaa cha msimamizi wa maktaba tayari hutoa uhifadhi wa hati pamoja na kitambulisho cha kipekee cha hati. Mfumo wa asili unajumuishwa na miundombinu hii iliyopo. + +#### Uwezo Ulioopo (tayari umetekelezwa) + +**Uunganisho wa Hati za Mzazi na Mtoto:** +>>>>>>> 82edf2d (New md files from RunPod) +`parent_id` field katika `DocumentMetadata` - huunganisha hati ya mtoto na hati ya mzazi +`document_type` field - maadili: `"source"` (asili) au `"extracted"` (iliyotokana) +`add-child-document` API - huunda hati ya mtoto na `document_type = "extracted"` moja kwa moja +`list-children` API - hurudisha hati zote za watoto za hati ya mzazi +Ufutilishaji wa mfuatano - kuondoa hati ya mzazi huondoa moja kwa moja hati zote za watoto + +**Kitambulisho cha Hati:** +Kitambulisho cha hati huamuliwa na mteja (hayajaumbwa kiotomatiki) +Hati zimepangwa kwa `(user, document_id)` iliyounganishwa katika Cassandra +Kitambulisho cha kitu (UUIDs) huundwa ndani kwa uhifadhi wa blob + +**Usaidizi wa MetaData:** +`metadata: list[Triple]` field - triples za RDF kwa metaData iliyopangwa +`title`, `comments`, `tags` - metaData ya msingi ya hati +`time` - wakati, `kind` - aina ya MIME + +**Muundo wa Uhifadhi:** +MetaData huhifadhiwa katika Cassandra (`librarian` keyspace, `document` meza) +Yaliyomo huhifadhiwa katika uhifadhi wa blob wa MinIO/S3 (`library` ndoo) +<<<<<<< HEAD +Uwasilishaji mahiri wa yaliyomo: hati < 2MB zimejumuishwa, hati kubwa zaidi hutiririshwa +======= +Utoaji wa yaliyomo mahiri: hati < 2MB zimejumuishwa, hati kubwa zaidi hutiririshwa +>>>>>>> 82edf2d (New md files from RunPod) + +#### Faili Muhimu + +`trustgraph-flow/trustgraph/librarian/librarian.py` - Operesheni muhimu za msimamizi wa maktaba +`trustgraph-flow/trustgraph/librarian/service.py` - Mchakato wa huduma, upakaji hati +`trustgraph-flow/trustgraph/tables/library.py` - Duka la meza ya Cassandra +`trustgraph-base/trustgraph/schema/services/library.py` - Ufafanuzi wa mpango + +<<<<<<< HEAD +#### Mapungufu Yanayohitaji Kusuluhishwa + +Msimamizi wa maktaba una vipengele muhimu lakini kwa sasa: +1. Uunganisho wa mzazi-mtoto ni safu moja tu - hakuna msaada wa utambuzi wa DAG wa ngazi nyingi +2. Hakuna hesabu ya kawaida ya aina ya uhusiano (e.g., `derivedFrom`, `extractedFrom`) +3. MetaData ya asili (mbinu ya uondoaji, uaminifu, nafasi ya kipande) hayajaainishwa +4. Hakuna API ya kuuliza ili kutambua mnyororo kamili wa asili kutoka kwa ukweli hadi chanzo + +## Muundo wa Mtiririko wa Utoaji hadi Utoaji + +Kila mchakato katika mstari huu unafuata mfumo unaoendana: +Kupokea kitambulisho cha hati kutoka kwa chanzo +======= +#### Mapungufu Yanayohitaji Kushughulikiwa + +Msimamizi wa maktaba una vipengele muhimu lakini kwa sasa: +1. Uunganisho wa mzazi-mtoto ni safu moja tu - hakuna msaada wa uvukaji wa DAG wa ngazi nyingi +2. Hakuna hesabu ya kawaida ya aina ya uhusiano (e.g., `derivedFrom`, `extractedFrom`) +3. MetaData ya asili (njia ya uondoaji, uaminifu, nafasi ya kipande) hayajawekwa kikao +4. Hakuna API ya kuuliza ili kuvuka mnyororo kamili wa asili kutoka kwa ukweli hadi chanzo + +## Muundo wa Mtiririko wa Kila Hatua + +Kila mchakato katika mstari huu unafuata mfumo unaoendana: +Kupokea kitambulisho cha hati kutoka kwa mfumo wa juu +>>>>>>> 82edf2d (New md files from RunPod) +Kuchukua yaliyomo kutoka kwa msimamizi wa maktaba +Kutoa vifaa vya watoto +Kwa kila mtoto: kuhifadhi kwenye msimamizi wa maktaba, kutuma upau kwenye grafu, kusonga kitambulisho mbele + +### Mitiririko ya Uendeshaji + +Kuna mitiririko miwili kulingana na aina ya hati: + +#### Mtiririko wa Hati ya PDF + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### Mtiririko wa Nyaraka za Nakshata + +<<<<<<< HEAD +Nyaraka za nakshata huenda moja kwa moja kwenye sehemu ya "chunker" na hazitumii programu ya kutenganisha faili za PDF: +======= +Nyaraka za nakshata huenda moja kwa moja kwenye sehemu ya "chunker" na hazitumii programu ya kutolea maelezo kutoka kwa faili za PDF: +>>>>>>> 82edf2d (New md files from RunPod) + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +<<<<<<< HEAD +DAG iliyotokea ni ya kiwango kimoja chini: +======= +Matokeo ya DAG (Grafu ya Kuelekea Mbele) ni ngazi moja chini: +>>>>>>> 82edf2d (New md files from RunPod) + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +<<<<<<< HEAD +Ubunifu unaoendana na matumizi ya aina zote, kwa sababu mfumo wa kugawanya (chunker) hutumia data yake ya pembejeo kwa njia ya jumla - hutumia kitambulisho chochote cha hati kinachopokelewa kama mzazi, bila kujali kama hiyo ni hati ya asili au ukurasa. +======= +Ubunifu unaoendana na matumizi ya aina zote, kwa sababu mfumo wa kugawanya (chunker) hutumia data yake ya pembeni kwa njia ya jumla - hutumia kitambulisho chochote cha hati kinachopokelewa kama mzazi, bila kujali kama hiyo ni hati ya asili au ukurasa. +>>>>>>> 82edf2d (New md files from RunPod) + +### Mpango wa Meta-data (PROV-O) + +Meta-data ya asili hutumia ontolojia ya W3C PROV-O. Hii hutoa msamiati wa kawaida na inawezesha usaini/uthibitishaji wa matokeo ya utoaji katika siku zijazo. + +### Dhana Zikuu za PROV-O + +| Aina ya PROV-O | Matumizi katika TrustGraph | +|-------------|------------------| +| `prov:Entity` | Hati, Ukurasa, Sehemu, Triple, Uingizwaji | +<<<<<<< HEAD +| `prov:Activity` | Mifano ya operesheni za utoaji | +======= +| `prov:Activity` | Mifano ya shughuli za utoaji | +>>>>>>> 82edf2d (New md files from RunPod) +| `prov:Agent` | Vipengele vya TG (mfumo wa utoaji wa PDF, mfumo wa kugawanya, n.k.) pamoja na matoleo | + +### Mahusiano ya PROV-O + +<<<<<<< HEAD +| Kifurushi | Maana | Mfano | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | Kitu kinachotokana na kitu kingine | Ukurasa ulikuwa umetokana na Hati | +| `prov:wasGeneratedBy` | Kitu kilichoundwa na shughuli | Ukurasa ulikuwa umelindwa na Shughuli ya Utoaji wa PDF | +======= +| Kifurushi | Maana | Kifaa | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | Kitu kinachotokana na kitu kingine | Ukurasa ulitokana na Hati | +| `prov:wasGeneratedBy` | Kitu kilichoanzishwa na shughuli | Ukurasa ulianzishwa na Shughuli ya Utoaji wa PDF | +>>>>>>> 82edf2d (New md files from RunPod) +| `prov:used` | Shughuli ilitumia kitu kama pembejeo | Shughuli ya Utoaji wa PDF ilitumia Hati | +| `prov:wasAssociatedWith` | Shughuli ilifanywa na wakala | Shughuli ya Utoaji wa PDF ilihusishwa na tg:PDFExtractor | + +### Meta-data katika Kila Ngazi + +<<<<<<< HEAD +**Hati ya Asili (inatoolewa na Librarian):** +======= +**Hati ya Asili (inatoa Librarian):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +**Ukurasa (uliochukuliwa na programu ya kuchambua faili za PDF):** +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +<<<<<<< HEAD +**Sehemu (imetolewa na Chunker):** +======= +**Sehemu (inatoolewa na Chunker):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**Tatu (imetolewa na Mvumbuzi wa Maarifa):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**Uingizwaji (hifadhiwa katika hifadhi ya vekta, sio hifadhi ya triple):** + +Uingizwaji huhifadhiwa katika hifadhi ya vekta pamoja na metadata, sio kama triple za RDF. Kila rekodi ya uingizwaji ina: + +<<<<<<< HEAD +| Nguvu | Maelezo | Mfano | +|-------|-------------|---------| +| vekta | Vektali ya uingizwaji | [0.123, -0.456, ...] | +| kitu | URI ya node ambayo uingizwaji unawakilisha | `entity:JohnSmith` | +| kitambulisho_cha_sehemu | Sehemu ya asili (asili) | `chunk:123-1-1` | +| mfumo | Mfumo wa uingizwaji uliotumika | `text-embedding-ada-002` | +| toleo_la_komponenti | Toleo la programu ya uingizwaji | `1.0.0` | + +Nguvu ya `entity` huunganisha uingizwaji na grafu ya maarifa (URI ya node). Nguvu ya `chunk_id` hutoa asili kurudi kwa sehemu ya asili, na kuwezesha ufuatiliaji hadi kwenye hati asili. + +#### Miondoko ya Jina ya TrustGraph + +Maneno maalum chini ya nafasi ya `tg:` kwa metadata maalum ya uondoaji: + +| Neno | Doman | Maelezo | +|-----------|--------|-------------| +| `tg:contains` | Subgraph | Inaashiria triple iliyo ndani ya subgraph hii ya uondoaji | +| `tg:pageCount` | Hati | Idadi jumla ya kurasa katika hati ya asili | +| `tg:mimeType` | Hati | Aina ya MIME ya hati ya asili | +| `tg:pageNumber` | Ukurasa | Namba ya ukurasa katika hati ya asili | +| `tg:chunkIndex` | Sehemu | Index ya sehemu ndani ya sehemu ya wazazi | +| `tg:charOffset` | Sehemu | Marekebisho ya herufi katika maandishi ya wazazi | +| `tg:charLength` | Sehemu | Urefu wa sehemu katika herufi | +| `tg:chunkSize` | Shughuli | Ukubwa uliopangwa wa sehemu | +| `tg:chunkOverlap` | Shughuli | Ulinganishi kati ya sehemu | +| `tg:componentVersion` | Shughuli | Toleo la komponenti ya TG | +| `tg:llmModel` | Shughuli | LLM iliyotumika kwa uondoaji | +| `tg:ontology` | Shughuli | Ontology iliyotumika kuongoza uondoaji | +| `tg:embeddingModel` | Shughuli | Mfumo uliotumika kwa uingizwaji | +| `tg:sourceText` | Tamko | Nakala kamili kutoka ambayo triple iliondolewa | +| `tg:sourceCharOffset` | Tamko | Marekebisho ya herufi ndani ya sehemu ambapo nakala ya asili huanza | +| `tg:sourceCharLength` | Tamko | Urefu wa nakala ya asili katika herufi | + +#### Uanzishaji wa Dhana (Kwa Mkusanyiko Kila Kila) + +Grafu ya maarifa ni ya aina ya ontology na inaanzishwa kuwa tupu. Wakati wa kuandika data ya asili ya PROV-O kwa mkusanyiko kwa mara ya kwanza, dhana lazima ianzishwe na lebo za RDF kwa madarasa na maneno yote. Hii inahakikisha onyesho linalosoma kwa binadamu katika maswali na UI. +======= +| Shamba | Maelezo | Mfano | +|-------|-------------|---------| +| vekta | Vakta ya uingizwaji | [0.123, -0.456, ...] | +| kitu | URI ya node ambayo uingizwaji unawakilisha | `entity:JohnSmith` | +| kitambulisho_cha_sehemu | Sehemu ya asili (asili) | `chunk:123-1-1` | +| mfumo | Mfumo wa uingizwaji uliotumika | `text-embedding-ada-002` | +| toleo_la_komponenti | Toleo la mfumo wa uingizwaji wa TG | `1.0.0` | + +Shamba la `entity` huunganisha uingizwaji na grafu ya maarifa (URI ya node). Shamba la `chunk_id` hutoa asili kurudi kwa sehemu ya asili, na hivyo kuruhusu ufuatiliaji hadi kwenye hati asili. + +#### Miongozo ya Upanuzi wa Nafasi ya TrustGraph + +Maneno maalum chini ya nafasi ya `tg:` kwa metadata maalum ya utoaji: + +| Dhana | Eneo | Maelezo | +|-----------|--------|-------------| +| `tg:contains` | Subgraph | Inaashiria triple iliyo ndani ya subgraph hii. | +| `tg:pageCount` | Document | Idadi jumla ya kurasa katika hati ya asili. | +| `tg:mimeType` | Document | Aina ya MIME ya hati ya asili. | +| `tg:pageNumber` | Page | Namba ya ukurasa katika hati ya asili. | +| `tg:chunkIndex` | Chunk | Indexi ya chunk ndani ya mzazi. | +| `tg:charOffset` | Chunk | Marekebisho ya herufi katika maandishi ya mzazi. | +| `tg:charLength` | Chunk | Urefu wa chunk katika herufi. | +| `tg:chunkSize` | Activity | Ukubwa wa chunk uliopangwa. | +| `tg:chunkOverlap` | Activity | Uwianifu uliopangwa kati ya chunks. | +| `tg:componentVersion` | Activity | Toleo la kipengele cha TG. | +| `tg:llmModel` | Activity | LLM iliyotumika kwa uondoaji. | +| `tg:ontology` | Activity | URI ya ontology iliyotumika kuongoza uondoaji. | +| `tg:embeddingModel` | Activity | Mfumo uliotumika kwa embeddings. | +| `tg:sourceText` | Statement | Nakala kamili kutoka ambayo triple iliondolewa. | +| `tg:sourceCharOffset` | Statement | Marekebisho ya herufi ndani ya chunk ambapo nakala ya chanzo huanza. | +| `tg:sourceCharLength` | Statement | Urefu wa nakala ya chanzo katika herufi. | + +#### Uanzishaji wa Dhana (Kwa Kundi Kila Kimoja) + +Grafu ya maarifa ni ya kawaida na huanzishwa kuwa tupu. Wakati wa kuandika data ya asili ya PROV-O kwenye mkusanyiko kwa mara ya kwanza, dhana lazima ianzishwe kwa lebo za RDF kwa madarasa na dhana zote. Hii inahakikisha onyesho linalosoma na binadamu katika maswali na UI. +>>>>>>> 82edf2d (New md files from RunPod) + +**Madarasa ya PROV-O:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**Predikati za PROV-O:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +<<<<<<< HEAD +**Predikatendi za TrustGraph:** +======= +**Maneno ya TrustGraph:** +>>>>>>> 82edf2d (New md files from RunPod) +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**Kumbukumbu kuhusu utekelezaji:** Kamusi hii ya kuanzia inapaswa kuwa ya aina ambayo inaweza kuendeshwa mara nyingi bila kuunda nakala. Inaweza kuanzishwa wakati wa usindikaji wa hati ya kwanza katika mkusanyiko, au kama hatua tofauti ya uanzishaji wa mkusanyiko. + +#### Asili ya Sehemu Ndogo (Lengo) + +Kwa asili ya kina zaidi, itakuwa muhimu kurekodi hasa katika sehemu gani ya kipande ambapo triple ilitokana. Hii inaruhusu: + +Kuonyesha maandishi ya asili hasa katika kiolesura (UI) +Kuthibitisha usahihi wa uondoaji dhidi ya asili +Kuchunguza ubora wa uondoaji katika kiwango cha sentensi +======= +**Kumbuka kuhusu utekelezaji:** Msamiati huu wa kuanzia inapaswa kuwa sawa - salama kuendeshwa mara nyingi bila kuunda nakala. Inaweza kuanzishwa wakati wa usindikaji wa hati ya kwanza katika mkusanyiko, au kama hatua tofauti ya uanzishaji wa mkusanyiko. + +#### Asili ya Sehemu Ndogo (Lengo) + +Kwa asili ya kina zaidi, itakuwa muhimu kurekodi haswa katika sehemu gani ndani ya kipande ambapo triple ilitokana. Hii inawezesha: + +Kuonyesha maandishi ya asili haswa katika kiolesura (UI) +Kuangalia usahihi wa utoaji kulingana na asili +Kuchunguza ubora wa utoaji katika kiwango cha sentensi +>>>>>>> 82edf2d (New md files from RunPod) + +**Mfano na ufuatiliaji wa nafasi:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**Mfano na sehemu ya maandishi (badala):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**Mazingatio ya utekelezaji:** + +Utaratibu wa kutolea maelezo unaotegemea modeli ya lugha (LLM) huenda usitoe nafasi za herufi kwa kawaida. +Inaweza kuwezekana kuomba LLM irudishe sentensi/maneno ya asili pamoja na vitu vilivyotolewa. +<<<<<<< HEAD +Badala yake, inaweza kufanywa urekebishaji wa ziada ili kulinganisha vitu vilivyotolewa na maandishi ya asili. +Kuna mtego kati ya utata wa utoleaji wa maelezo na kiwango cha uhakikisho. +Inaweza kuwa rahisi kufanikisha kwa kutumia mbinu zilizopangwa kuliko utoleaji wa maelezo wa aina huru unaotegemea LLM. + +Hii imewekwa kama lengo la baadaye - uhakikisho wa kimsingi wa kiwango cha sehemu unapaswa kutekelezwa kwanza, na kufuatilia kwa sehemu ndogo kama uboreshaji wa baadaye ikiwa inawezekana. + +### Mfumo wa Uhifadhi Mkubwa + +Mfumo wa uhakikisho unajengwa hatua kwa hatua wakati hati zinapopitia katika mchakato: + +| Hifadhi | Kile kinachohifadhiwa | Madhumuni | +|-------|---------------|---------| +| Msimamizi | Yaliyomo ya hati + viungo vya mzazi-mtoto | Kupata yaliyomo, kufuta kwa mfuatano | +| Grafu ya Maarifa | Miunganisho ya mzazi-mtoto + metadata | Maswali ya uhakikisho, utambuzi wa ukweli | + +Hifadhi zote mbili zinahifadhi muundo sawa wa DAG. Msimamizi huhifadhi yaliyomo; grafu huhifadhi uhusiano na inaruhusu maswali ya utaftaji. + +### Kanuni Muhimu za Ubunifu + +1. **Kitambulisho cha hati kama kitengo cha mchakato** - Wasindikaji hupitisha vitambulisho, sio yaliyomo. Yaliyomo hupatikana kutoka kwa msimamizi wakati inahitajika. + +2. **Tolea mara moja katika chanzo** - Metadata imeandikwa kwenye grafu mara moja wakati wa mchakato unaanza, sio kurudiwa baadaye. + +3. **Mfumo sawa wa wasindikaji** - Kila wasindikaji hufuata muundo sawa wa kupokea/kupata/kutoa/kuokoa/kutoa/kusonga. + +4. **Ujenzi wa hatua kwa hatua wa DAG** - Kila wasindikaji huongeza kiwango chake kwenye DAG. Mnyororo kamili wa uhakikisho unajengwa hatua kwa hatua. + +5. **Uboreshaji baada ya kugawanyika** - Baada ya kugawanyika, ujumbe unaambatana na kitambulisho na yaliyomo. Sehemu ndogo (2-4KB), kwa hivyo kuingiza yaliyomo inazuia safari zisizo za lazima za msimamizi wakati inahifadhi uhakikisho kupitia kitambulisho. + +## Majukumu ya Utekelezaji + +### Marekebisho ya Msimamizi +======= +Au, inaweza kufanywa urekebishaji wa ziada ili kulinganisha vitu vilivyotolewa na maandishi ya asili. +Kuna mtego kati ya utata wa utoleaji wa maelezo na uwazi wa asili. +Inaweza kuwa rahisi kufanikisha kwa kutumia mbinu zilizopangwa kuliko utoleaji wa maelezo wa bure unaotegemea LLM. + +Hii imewekwa kama lengo la baadaye - utaratibu wa msingi wa utoleaji wa maelezo wa kiwango cha sehemu unapaswa kutekelezwa kwanza, na kufuatilia kwa sehemu ndogo kama uboreshaji wa baadaye ikiwa inawezekana. + +### Mfumo wa Uhifadhi Mkubwa + +Mfumo wa DAG wa utoleaji wa maelezo huundwa hatua kwa hatua wakati hati zinapopitia katika mchakato: + +| Hifadhi | Kitu Kinachohifadhiwa | Lengo | +|-------|---------------|---------| +| Mkumbaji | Yaliyomo ya hati + viungo vya mzazi-mtoto | Upatikanaji wa yaliyomo, kufuta kwa mfuatano | +| Grafu ya Maarifa | Aina za mzazi-mtoto + metadata | Maswali ya utoleaji wa maelezo, uhusishaji wa ukweli | + +Hifadhi zote mbili zinahifadhi muundo sawa wa DAG. Mkumbaji huhifadhi yaliyomo; grafu huhifadhi uhusiano na inaruhusu maswali ya utaftaji. + +### Kanuni Muhimu za Ubunifu + +1. **Kitambulisho cha hati kama kitengo cha mtiririko** - Wasindikaji hutuma kitambulisho, sio yaliyomo. Yaliyomo hupatikana kutoka kwa mkumbaji wakati inahitajika. + +2. **Tolea mara moja katika chanzo** - Metadata imeandikwa kwenye grafu mara moja wakati wa mchakato unaanza, sio kurudiwa baadaye. + +3. **Muundo sawa wa wasindikaji** - Kila wasindikaji hufuata muundo sawa wa kupokea/kupata/kutoa/kuokoa/kutoa/kusonga. + +4. **Uundaji wa hatua kwa hatua wa DAG** - Kila wasindikaji huongeza kiwango chake kwenye DAG. Mnyororo kamili wa utoleaji wa maelezo huundwa hatua kwa hatua. + +5. **Uboreshaji baada ya kugawanyika** - Baada ya kugawanyika, ujumbe unaambatana na kitambulisho na yaliyomo. Sehemu ndogo (2-4KB), kwa hivyo kujumuisha yaliyomo inazuia safari zisizo za lazima za mkumbaji wakati inahifadhi utoleaji wa maelezo kupitia kitambulisho. + +## Majukumu ya Utendaji + +### Marekebisho ya Mkumbaji +>>>>>>> 82edf2d (New md files from RunPod) + +#### Hali ya Sasa + +Inaanzisha mchakato wa hati kwa kutuma kitambulisho cha hati kwa wasindikaji wa kwanza. +<<<<<<< HEAD +Hakuna muunganisho na duka la vitriple - metadata huunganishwa na matokeo ya utoleaji. +======= +Hakuna muunganisho na duka la vitri - metadata huunganishwa na matokeo ya utoleaji. +>>>>>>> 82edf2d (New md files from RunPod) +`add-child-document` huunda viungo vya mzazi-mtoto vya kiwango kimoja. +`list-children` hurudisha watoto wa karibu tu. + +#### Marekebisho Yanayohitajika + +<<<<<<< HEAD +**1. Kiolesura kipya: Muunganisho wa duka la vitriple** + +Msimamizi anahitaji kutoa kingo za metadata ya hati moja kwa moja kwenye grafu ya maarifa wakati wa kuanzisha mchakato. +Ongeza mteja/mpublisher wa duka la vitriple kwenye huduma ya msimamizi. +Wakati wa kuanzisha mchakato: toa metadata ya hati ya mizizi kama kingo za grafu (mara moja). + +**2. Hesabu ya aina ya hati** +======= +**1. Kiolesura kipya: Muunganisho wa duka la vitri** + +Mkumbaji anahitaji kutoa kingo za metadata ya hati moja kwa moja kwenye grafu ya maarifa wakati wa kuanzisha mchakato. +Ongeza mteja/mpublisher wa duka la vitri kwenye huduma ya mkumbaji. +Wakati wa kuanzisha mchakato: toa metadata ya hati ya mizizi kama kingo za grafu (mara moja). + +**2. Msamiati wa aina ya hati** +>>>>>>> 82edf2d (New md files from RunPod) + +Sanidi maadili ya `document_type` kwa watoto wa hati: +`source` - hati iliyopakiwa asili. +`page` - ukurasa uliotolewa kutoka chanzo (PDF, n.k.). +`chunk` - sehemu ya maandishi iliyotokana na ukurasa au chanzo. + +#### Muhtasari wa Marekebisho ya Kiolesura + +<<<<<<< HEAD +| Kiolesura | Marekebisho | +|-----------|--------| +| Duka la vitriple | Muunganisho mpya wa kutoka nje - toa kingo za metadata ya hati | +======= +| Kiolesura | Mabadiliko | +|-----------|--------| +| Duka la vitri | Muunganisho mpya wa kutoka nje - toa kingo za metadata ya hati | +>>>>>>> 82edf2d (New md files from RunPod) +| Kuanzisha mchakato | Toa metadata kwenye grafu kabla ya kusonga kitambulisho cha hati | + +### Marekebisho ya Mtoa Hati ya PDF + +#### Hali ya Sasa + +Hupokea yaliyomo ya hati (au mitiririko ya hati kubwa). +Hutolea maandishi kutoka kwa kurasa za PDF. +Hupeleka yaliyomo ya ukurasa kwa mtoa sehemu. +<<<<<<< HEAD +Hakuna mwingiliano na msimamizi au duka la vitriple. + +#### Marekebisho Yanayohitajika + +**1. Kiolesura kipya: Mteja wa msimamizi** + +Mtoa hati ya PDF anahitaji kuhifadhi kila ukurasa kama hati ya mtoto katika msimamizi. +Ongeza mteja wa msimamizi kwenye huduma ya mtoa hati ya PDF. +Kwa kila ukurasa: piga `add-child-document` na mzazi = kitambulisho cha hati ya mizizi. + +**2. Kiolesura kipya: Muunganisho wa duka la vitriple** + +Mtoa hati ya PDF anahitaji kutoa kingo za mzazi-mtoto kwenye grafu ya maarifa. +Ongeza mteja/mpublisher wa duka la vitriple. +Kwa kila ukurasa: toa kingo inayounganisha hati ya ukurasa na hati ya mzazi. +======= +Hakuna mwingiliano na mkumbaji au duka la vitri. + +#### Marekebisho Yanayohitajika + +**1. Kiolesura kipya: Mteja wa mkumbaji** + +Mtoa hati ya PDF anahitaji kuhifadhi kila ukurasa kama hati ya mtoto katika mkumbaji. +Ongeza mteja wa mkumbaji kwenye huduma ya mtoa hati ya PDF. +Kwa kila ukurasa: piga `add-child-document` na mzazi = kitambulisho cha hati ya mizizi. + +**2. Kiolesura kipya: Muunganisho wa duka la vitri** + +Mtoa hati ya PDF anahitaji kutoa aina za mzazi-mtoto kwenye grafu ya maarifa. +Ongeza mteja/mpublisher wa duka la vitri. +Kwa kila ukurasa: toa aina inayounganisha ukurasa wa hati na hati ya mzazi. +>>>>>>> 82edf2d (New md files from RunPod) + +**3. Badilisha muundo wa matokeo** + +Badala ya kusambaza yaliyomo ya ukurasa moja kwa moja, sambaza kitambulisho cha hati ya ukurasa. +<<<<<<< HEAD +Chunker itapata yaliyomo kutoka kwa 'librarian' kwa kutumia kitambulisho. +======= +Chunker itapakua yaliyomo kutoka kwa 'librarian' kwa kutumia kitambulisho. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Muhtasari wa Mabadiliko ya Kiolesura + +| Kiolesura | Mabadiliko | +|-----------|--------| +| Librarian | Mabadiliko mapya ya kutoka - hifadhi hati za watoto | +<<<<<<< HEAD +| Hifadhi tatu | Mabadiliko mapya ya kutoka - toka miunganisho ya mzazi-mtoto | +======= +| Hifadhi tatu | Mabadiliko mapya ya kutoka - toa miunganisho ya mzazi-mtoto | +>>>>>>> 82edf2d (New md files from RunPod) +| Ujumbe wa pato | Mabadiliko kutoka yaliyomo hadi kitambulisho cha hati | + +### Mabadiliko ya Chunker + +#### Hali ya Sasa + +Yanapokea yaliyomo ya ukurasa/maandishi +<<<<<<< HEAD +Yanagawanyika katika sehemu ndogo +Yanatuma yaliyomo ya sehemu ndogo kwa wasindikaji wa baadaye +======= +Yanagawanywa katika sehemu +Yanatuma yaliyomo ya sehemu kwa wasindikaji wa baadaye +>>>>>>> 82edf2d (New md files from RunPod) +Hakuna mwingiliano na 'librarian' au hifadhi tatu + +#### Mabadiliko Yanayohitajika + +**1. Badilisha utunzaji wa ingizo** + +<<<<<<< HEAD +Pokea kitambulisho cha hati badala ya yaliyomo, pata kutoka kwa 'librarian'. +Ongeza mteja wa 'librarian' kwenye huduma ya chunker +Pata yaliyomo ya ukurasa kwa kutumia kitambulisho cha hati + +**2. Kiolesura kipya: Mteja wa 'Librarian' (kuandika)** + +Hifadhi kila sehemu ndogo kama hati ya mtoto katika 'librarian'. +Kwa kila sehemu ndogo: piga simu `add-child-document` na mzazi = kitambulisho cha hati ya ukurasa +======= +Pokea kitambulisho cha hati badala ya yaliyomo, upakue kutoka kwa 'librarian'. +Ongeza mteja wa 'librarian' kwenye huduma ya chunker +Pakua yaliyomo ya ukurasa kwa kutumia kitambulisho cha hati + +**2. Kiolesura kipya: Mteja wa 'Librarian' (kuandika)** + +Hifadhi kila sehemu kama hati ya mtoto katika 'librarian'. +Kwa kila sehemu: piga simu `add-child-document` na mzazi = kitambulisho cha hati ya ukurasa +>>>>>>> 82edf2d (New md files from RunPod) + +**3. Kiolesura kipya: Muunganisho wa hifadhi tatu** + +Toa miunganisho ya mzazi-mtoto kwa grafu ya maarifa. +Ongeza mteja/mpublisher wa hifadhi tatu +<<<<<<< HEAD +Kwa kila sehemu ndogo: toa muunganiko unaounganisha hati ya sehemu ndogo na hati ya ukurasa + +**4. Badilisha muundo wa pato** + +Sambaza kitambulisho cha hati ya sehemu ndogo na yaliyomo ya sehemu ndogo (uboreshaji wa baada ya chunker). +======= +Kwa kila sehemu: toa muunganisho unaounganisha hati ya sehemu na hati ya ukurasa + +**4. Badilisha muundo wa pato** + +Sambaza kitambulisho cha hati ya sehemu na yaliyomo ya sehemu (uboreshaji wa baada ya chunker). +>>>>>>> 82edf2d (New md files from RunPod) +Wasindikaji wa baadaye hupokea kitambulisho kwa ajili ya asili + yaliyomo ili kufanya kazi nayo + +#### Muhtasari wa Mabadiliko ya Kiolesura + +| Kiolesura | Mabadiliko | +|-----------|--------| +| Ujumbe wa ingizo | Mabadiliko kutoka yaliyomo hadi kitambulisho cha hati | +<<<<<<< HEAD +| Librarian | Mabadiliko mapya ya kutoka (kusoma + kuandika) - pata yaliyomo, hifadhi hati za watoto | +======= +| Librarian | Mabadiliko mapya ya kutoka (kusoma + kuandika) - pakua yaliyomo, hifadhi hati za watoto | +>>>>>>> 82edf2d (New md files from RunPod) +| Hifadhi tatu | Mabadiliko mapya ya kutoka - toa miunganisho ya mzazi-mtoto | +| Ujumbe wa pato | Mabadiliko kutoka yaliyomo-tu hadi kitambulisho + yaliyomo | + +### Mabadiliko ya Mvumbuzi wa Maarifa + +#### Hali ya Sasa + +<<<<<<< HEAD +Yanapokea yaliyomo ya sehemu ndogo +Yanatoa triples na embeddings +Yanatoa kwa hifadhi ya triples na hifadhi ya embeddings +`subjectOf` uhusiano unaelekeza kwenye hati ya juu (si sehemu ndogo) +======= +Yanapokea yaliyomo ya sehemu +Yanatoa triples na embeddings +Yanatuma kwa hifadhi ya triples na hifadhi ya embeddings +`subjectOf` uhusiano unaelekeza kwenye hati ya juu (si sehemu) +>>>>>>> 82edf2d (New md files from RunPod) + +#### Mabadiliko Yanayohitajika + +**1. Badilisha utunzaji wa ingizo** + +<<<<<<< HEAD +Pokea kitambulisho cha hati ya sehemu ndogo pamoja na yaliyomo. +Tumia kitambulisho cha sehemu ndogo kwa ulinganisho (yaliyomo tayari yamejumuishwa kwa uboreshaji) + +**2. Sasisha asili ya triples** + +Unganisha triples zilizotolewa na sehemu ndogo (si hati ya juu). +Tumia reification ili kuunda muunganiko unaoelekeza kwenye muunganiko +`subjectOf` uhusiano: triple → kitambulisho cha hati ya sehemu ndogo +======= +Pokea kitambulisho cha hati ya sehemu pamoja na yaliyomo. +Tumia kitambulisho cha sehemu kwa ulinganisho (yaliyomo tayari yamejumuishwa kwa uboreshaji) + +**2. Sasisha asili ya triples** + +Unganisha triples zilizotolewa na sehemu (si hati ya juu). +Tumia reification ili kuunda muunganisho unaoelekeza kwenye muunganisho +`subjectOf` uhusiano: triple → kitambulisho cha hati ya sehemu +>>>>>>> 82edf2d (New md files from RunPod) +Matumizi ya kwanza ya msaada uliopo wa reification + +**3. Sasisha asili ya embeddings** + +<<<<<<< HEAD +Unganisha kitambulisho cha entiti ya embedding na sehemu ndogo. +Toa muunganiko: kitambulisho cha entiti ya embedding → kitambulisho cha hati ya sehemu ndogo +======= +Unganisha kitambulisho cha entiti ya embedding na sehemu. +Toa muunganisho: kitambulisho cha entiti ya embedding → kitambulisho cha hati ya sehemu +>>>>>>> 82edf2d (New md files from RunPod) + +#### Muhtasari wa Mabadiliko ya Kiolesura + +| Kiolesura | Mabadiliko | +|-----------|--------| +<<<<<<< HEAD +| Ujumbe wa ingizo | Inatarajia kitambulisho cha sehemu ndogo + yaliyomo (si yaliyomo tu) | +| Hifadhi tatu | Tumia reification kwa asili ya triple → sehemu | +| Asili ya embedding | Unganisha kitambulisho cha entiti → kitambulisho cha sehemu | +======= +| Ujumbe wa ingizo | Inatarajia kitambulisho cha sehemu + yaliyomo (si yaliyomo tu) | +| Hifadhi ya triples | Tumia reification kwa asili ya triple → sehemu | +| Asili ya embeddings | Unganisha kitambulisho cha entiti → kitambulisho cha sehemu | +>>>>>>> 82edf2d (New md files from RunPod) + +## Marejeleo + +Asili ya wakati wa swali: `docs/tech-specs/query-time-provenance.md` +Kiwango cha PROV-O kwa uundaji wa asili +Meta-data ya chanzo iliyopo katika grafu ya maarifa (inahitaji ukaguzi) diff --git a/docs/tech-specs/extraction-time-provenance.tr.md b/docs/tech-specs/extraction-time-provenance.tr.md new file mode 100644 index 00000000..6f710760 --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.tr.md @@ -0,0 +1,797 @@ +--- +layout: default +title: "Çıkarma Zamanı Köken Bilgisi: Kaynak Katmanı" +parent: "Turkish (Beta)" +--- + +# Çıkarma Zamanı Köken Bilgisi: Kaynak Katmanı + +> **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ış + +<<<<<<< HEAD +Bu belge, gelecekteki özelliklendirme çalışmaları için çıkarma zamanı köken bilgisi üzerine notları içermektedir. Çıkarma zamanı köken bilgisi kayıtları, verilerin başlangıçta nereden geldiğini, nasıl çıkarıldığını ve dönüştürüldüğünü gösteren "kaynak katmanını" kaydeder. + +Bu, ajan muhakemesini kaydeden sorgu zamanı köken bilgisinden (bkz. `query-time-provenance.md`) farklıdır. +======= +Bu belge, gelecekteki özellik tanımlama çalışmaları için çıkarma zamanı köken bilgisi üzerine notları içermektedir. Çıkarma zamanı köken bilgisi kayıtları, verilerin başlangıçta nereden geldiğini, nasıl çıkarıldığını ve dönüştürüldüğünü gösteren "kaynak katmanını" kaydeder. + +Bu, ajan muhakemesini kaydeden sorgu zamanı köken bilgisinden (`query-time-provenance.md`'a bakın) farklıdır. +>>>>>>> 82edf2d (New md files from RunPod) + +## Problem Tanımı + +### Mevcut Uygulama + +Şu anda köken bilgisi aşağıdaki şekilde çalışmaktadır: +Belge meta verileri, bilgi grafiğinde RDF üçlüleri olarak saklanır. +Bir belge kimliği, meta verileri belgeyle ilişkilendirir, böylece belge grafikte bir düğüm olarak görünür. +Belgelerden kenarlar (ilişkiler/gerçekler) çıkarıldığında, çıkarılan kenarı kaynak belgeye bağlayan bir `subjectOf` ilişkisi bulunur. + +### Mevcut Yaklaşımla İlgili Sorunlar + +<<<<<<< HEAD +1. **Tekrarlayan meta veri yüklemesi:** Belge meta verileri, o belgeden çıkarılan her üçlü grubuyla birlikte tekrar tekrar paketlenir ve yüklenir. Bu, israf ve gereksizdir - aynı meta veriler her çıkarma çıktısıyla birlikte yük taşımacılığı yapar. + +2. **Yüzeysel köken bilgisi:** Mevcut `subjectOf` ilişkisi yalnızca gerçekleri doğrudan en üst düzey belgeyle ilişkilendirir. Dönüşüm zinciri hakkında hiçbir görünürlük yoktur - gerçek hangi sayfadan geldi, hangi parçadan, hangi çıkarma yöntemi kullanıldı. +======= +1. **Tekrarlayan meta veri yüklemesi:** Belge meta verileri, o belgeden çıkarılan her üçlü grubuyla birlikte tekrar tekrar paketlenir ve yüklenir. Bu, israf ve gereksizdir - aynı meta veriler, her çıkarma çıktısıyla birlikte yük olarak taşınır. + +2. **Yüzeysel köken bilgisi:** Mevcut `subjectOf` ilişkisi yalnızca gerçekleri doğrudan en üst düzey belgeyle ilişkilendirir. Dönüşüm zinciri hakkında hiçbir görünürlük yoktur - gerçek hangi sayfadan, hangi bölümden geldi, hangi çıkarma yöntemi kullanıldı. +>>>>>>> 82edf2d (New md files from RunPod) + +### İstediğimiz Durum + +1. **Meta verileri yalnızca bir kez yükleyin:** Belge meta verileri, her üçlü grubuyla tekrarlanmak yerine, yalnızca bir kez yüklenmeli ve en üst düzey belge düğümüne eklenmelidir. + +<<<<<<< HEAD +2. **Zengin köken bilgisi DAG'ı:** Kaynak belgeden başlayarak tüm ara öğeler aracılığıyla çıkarılan gerçeklere kadar olan tüm dönüşüm zincirini yakalayın. Örneğin, bir PDF belgesi dönüşümü: +======= +2. **Zengin köken bilgisi DAG'ı:** Kaynak belgeden başlayarak, tüm ara öğeler aracılığıyla çıkarılan gerçeklere kadar olan tüm dönüşüm zincirini yakalayın. Örneğin, bir PDF belgesi dönüşümü: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +3. **Birleşik depolama:** Kaynak bilgisi DAG'ı, çıkarılan bilgiyle aynı bilgi grafiğinde saklanır. Bu, kaynak bilgisinin, herhangi bir gerçeğin tam kaynak konumuna doğru zincir boyunca geri izlenerek, bilgi gibi aynı şekilde sorgulanabilmesini sağlar. + +4. **Sabit Kimlikler:** Her ara öğe (sayfa, parça) grafikte bir düğüm olarak sabit bir kimliğe sahiptir. + +5. **Ebeveyn-çocuk bağlantısı:** Türetilmiş belgeler, tutarlı ilişki türleri kullanılarak, en üst düzey kaynak belgeye kadar ebeveynlerine bağlanır. + +6. **Hassas gerçek ataması:** Çıkarılan kenarlardaki `subjectOf` ilişkisi, doğrudan ebeveyne (parçaya), en üst düzey belgeye değil, işaret eder. Tam kaynak bilgisi, DAG boyunca yukarı doğru gezilerek elde edilir. + +## Kullanım Senaryoları + +### KS1: GraphRAG Yanıtlarında Kaynak Ataması + +**Senaryo:** Bir kullanıcı bir GraphRAG sorgusu çalıştırır ve ajandan bir yanıt alır. + +**Süreç:** +<<<<<<< HEAD +1. Kullanıcı, GraphRAG ajanıyla bir sorgu gönderir. +2. Ajan, bir yanıt oluşturmak için ilgili gerçekleri bilgi grafiğinden alır. +3. Sorgu zamanı kaynak bilgisi spesifikasyonuna göre, ajan yanıtı oluşturan gerçekleri bildirir. +======= +1. Kullanıcı, GraphRAG ajanına bir sorgu gönderir. +2. Ajan, bir yanıt oluşturmak için bilgi grafiğinden ilgili gerçekleri alır. +3. Sorgu zamanı kaynak bilgisi spesifikasyonuna göre, ajan, yanıta hangi gerçeklerin katkıda bulunduğunu bildirir. +>>>>>>> 82edf2d (New md files from RunPod) +4. Her gerçek, kaynak bilgisi DAG'ı aracılığıyla kaynak parçasına bağlanır. +5. Parçalar, sayfalara bağlanır, sayfalar kaynak belgelere bağlanır. + +**Kullanıcı Deneyimi Sonucu:** Arayüz, LLM yanıtını kaynak atamasıyla birlikte gösterir. Kullanıcı şunları yapabilir: +Yanıtı destekleyen gerçekleri görebilir. +Gerçeklerden → parçalara → sayfalara → belgelere kadar ayrıntılara inebilir. +İddiaları doğrulamak için orijinal kaynak belgelerine göz atabilir. +<<<<<<< HEAD +Bir gerçekin tam olarak bir belgenin (hangi sayfa, hangi bölüm) neresinden geldiğini anlayabilir. + +**Değer:** Kullanıcılar, yapay zeka tarafından oluşturulan yanıtlara birincil kaynaklara göre doğrulama yaparak güven oluşturabilir ve doğrulama yapabilir. +======= +Bir gerçekin bir belgenin neresinden (hangi sayfa, hangi bölüm) geldiğini tam olarak anlayabilir. + +**Değer:** Kullanıcılar, yapay zeka tarafından oluşturulan yanıtlara birincil kaynaklara karşı doğrulama yaparak güven oluşturabilir ve doğruluk kontrolünü sağlayabilir. +>>>>>>> 82edf2d (New md files from RunPod) + +### KS2: Çıkarma Kalitesinin Hata Ayıklaması + +Bir gerçek yanlış görünüyor. Orijinal metni görmek için parça → sayfa → belge yoluyla geriye doğru izleyin. Bu kötü bir çıkarma mıydı, yoksa kaynak mı yanlıştı? + +### KS3: Artımlı Yeniden Çıkarma + +<<<<<<< HEAD +Kaynak belge güncellendi. Bu belgeden hangi parçalar/gerçekler türetildi? Sadece bunları geçersiz kılın ve yeniden oluşturun, her şeyi yeniden işlemek yerine. + +### KS4: Veri Silme / Bilinme Hakkı + +Bir kaynak belge kaldırılmalıdır (GDPR, yasal, vb.). Türetilmiş tüm gerçekleri bulmak ve kaldırmak için DAG'ı izleyin. +======= +Kaynak belge güncellenir. Bu belgeden hangi parçalar/gerçekler türetildi? Sadece bunları geçersiz kılın ve yeniden oluşturun, her şeyi yeniden işlemek yerine. + +### KS4: Veri Silme / Bilinme Hakkı + +Bir kaynak belge kaldırılmalıdır (GDPR, yasal, vb.). Tüm türetilmiş gerçekleri bulmak ve kaldırmak için DAG'ı geçin. +>>>>>>> 82edf2d (New md files from RunPod) + +### KS5: Çatışma Çözümü + +İki gerçek birbiriyle çelişiyor. Nedenini anlamak ve hangisine güveneceğe karar vermek için her ikisini de kaynaklarına kadar izleyin (daha yetkili kaynak, daha yeni, vb.). + +### KS6: Kaynak Yetki Ağırlığı + +Bazı kaynaklar diğerlerinden daha yetkilidir. Gerçekler, kaynak belgelerinin yetki/kalitesine göre ağırlıklandırılabilir veya filtrelenebilir. + +### KS7: Çıkarma Boru Hattı Karşılaştırması + +<<<<<<< HEAD +Farklı çıkarma yöntemlerinin/sürümlerinin çıktılarını karşılaştırın. Aynı kaynaktan daha iyi gerçekler üreten hangi çıkarıcıydı? +======= +Farklı çıkarma yöntemlerinin/sürümlerinin çıktılarını karşılaştırın. Aynı kaynaktan hangi çıkarıcı daha iyi gerçekler üretti? +>>>>>>> 82edf2d (New md files from RunPod) + +## Entegrasyon Noktaları + +### Kütüphaneci + +<<<<<<< HEAD +Kütüphaneci bileşeni, zaten benzersiz belge kimlikleriyle belge depolama imkanı sunmaktadır. Kaynak sistemi, bu mevcut altyapıyla entegre olmaktadır. +======= +Kütüphaneci bileşeni, zaten benzersiz belge kimlikleriyle belge depolama imkanı sunmaktadır. Kaynak sistemi, bu mevcut altyapıyla entegre edilmektedir. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Mevcut Yetenekler (zaten uygulanan) + +**Ebeveyn-Çocuk Belge Bağlantısı:** +`parent_id` alanı - `DocumentMetadata` içinde - çocuk belgeyi ebeveyn belgeye bağlar +`document_type` alanı - değerler: `"source"` (orijinal) veya `"extracted"` (türetilmiş) +`add-child-document` API'si - otomatik `document_type = "extracted"` ile çocuk belge oluşturur +`list-children` API'si - bir ebeveyn belgenin tüm çocuklarını alır +Zincirleme silme - bir ebeveynin silinmesi, otomatik olarak tüm çocuk belgelerin silinmesine neden olur + +**Belge Tanımlama:** +Belge kimlikleri, istemci tarafından belirtilir (otomatik olarak oluşturulmaz) +Belgeler, Cassandra'da bileşik `(user, document_id)` ile indekslenir +Nesne kimlikleri (UUID'ler), blob depolama için dahili olarak oluşturulur + +**Meta Veri Desteği:** +`metadata: list[Triple]` alanı - yapılandırılmış meta veriler için RDF üçlüleri +`title`, `comments`, `tags` - temel belge meta verileri +`time` - zaman damgası, `kind` - MIME türü + +**Depolama Mimarisi:** +<<<<<<< HEAD +Meta veriler, Cassandra'da saklanır (`librarian` anahtar alanı, `document` tablo) +İçerik, MinIO/S3 blob depolamasında saklanır (`library` bucket) +======= +Meta veriler, Cassandra'da depolanır (`librarian` anahtar alanı, `document` tablo) +İçerik, MinIO/S3 blob depolamada depolanır (`library` bucket) +>>>>>>> 82edf2d (New md files from RunPod) +Akıllı içerik dağıtımı: 2 MB'den küçük belgeler yerleştirilir, daha büyük belgeler akışla iletilir + +#### Önemli Dosyalar + +`trustgraph-flow/trustgraph/librarian/librarian.py` - Temel kütüphaneci işlemleri +`trustgraph-flow/trustgraph/librarian/service.py` - Hizmet işlemcisi, belge yükleme +`trustgraph-flow/trustgraph/tables/library.py` - Cassandra tablo deposu +`trustgraph-base/trustgraph/schema/services/library.py` - Şema tanımları + +#### Giderilmesi Gereken Eksiklikler + +Kütüphaneci, temel yapı taşlarına sahip olmasına rağmen şu anda: +1. Ebeveyn-çocuk bağlantısı tek düzeylidir - çok düzeyli DAG (Yönlendirilmiş Döngüsel Grafik) gezinme yardımcıları yoktur +2. Standart bir ilişki türü sözlüğü yoktur (örneğin, `derivedFrom`, `extractedFrom`) +3. Kaynak meta verileri (çıkarma yöntemi, güven, parça konumu) standartlaştırılmamıştır +<<<<<<< HEAD +4. Bir gerçeğe geri dönen kaynaklara kadar tüm kaynak zincirini izlemek için bir sorgu API'si yoktur +======= +4. Bir gerçeğe geri dönen tam kaynak zincirini izlemek için bir sorgu API'si yoktur +>>>>>>> 82edf2d (New md files from RunPod) + +## Uçtan Uca Akış Tasarımı + +Boru hattındaki her işlemci, tutarlı bir kalıbı izler: +<<<<<<< HEAD +Yukarı akıştan belge kimliğini alır +Kütüphaneciden içeriği alır +Çocuk öğeler oluşturur +Her çocuk için: kütüphaneciye kaydeder, grafiğe bir kenar yollar, kimliği aşağı akışa iletir +======= +Yukarıdan bir belge kimliği alınır +İçerik, kütüphaneciden alınır +Çocuk öğeler oluşturulur +Her çocuk için: kütüphaneciye kaydedilir, grafiğe bir kenar yollanır, kimlik aşağı akışa iletilir +>>>>>>> 82edf2d (New md files from RunPod) + +### İşlem Akışları + +Belge türüne bağlı olarak iki akış vardır: + +#### PDF Belge Akışı + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### Metin Belgesi Akışı + +Metin belgeleri, PDF ayıklayıcıyı atlayarak doğrudan parçalayıcıya (chunker) gider: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +Elde edilen DAG, bir seviye daha kısadır: + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +<<<<<<< HEAD +Tasarım, her iki durumu da destekler çünkü parçalayıcı (chunker), girdisini genel olarak işler; aldığı belge kimliği, kaynak belge mi yoksa bir sayfa mı olduğunu dikkate almadan, bunu üst belge olarak kullanır. + +### Metaveri Şeması (PROV-O) + +Kaynak metaverileri, W3C PROV-O ontolojisini kullanır. Bu, standart bir sözlük sağlar ve çıkarılan verilerin gelecekteki imzalanmasını/doğrulanmasını mümkün kılar. +======= +Tasarım, her iki durumu da destekler çünkü parçalayıcı (chunker), girdisini genel olarak işler; aldığı belge kimliğini, bunun kaynak belge olup olmadığını veya bir sayfa olup olmadığını dikkate almadan, üst belge olarak kullanır. + +### Metaveri Şeması (PROV-O) + +Kaynak metaverileri, W3C PROV-O ontolojisini kullanır. Bu, standart bir kelime dağarcığı sağlar ve çıkarılan verilerin gelecekteki imzalama/kimlik doğrulamasını mümkün kılar. +>>>>>>> 82edf2d (New md files from RunPod) + +#### PROV-O Temel Kavramları + +| PROV-O Tipi | TrustGraph Kullanımı | +|-------------|------------------| +| `prov:Entity` | Belge, Sayfa, Parça, Üçlü, Gömme | +| `prov:Activity` | Çıkarma işlemlerinin örnekleri | +| `prov:Agent` | TG bileşenleri (PDF ayıklayıcı, parçalayıcı, vb.) ve versiyonları | + +#### PROV-O İlişkileri + +| Özne | Anlamı | Örnek | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | Başka bir varlıktan türetilen varlık | Sayfa, Belgeden Türetildi | +| `prov:wasGeneratedBy` | Bir etkinlik tarafından oluşturulan varlık | Sayfa, PDFÇıkarmaEtkinliği Tarafından Oluşturuldu | +| `prov:used` | Bir etkinliğin bir varlığı girdi olarak kullandığı | PDFÇıkarmaEtkinliği, Belgeyi Kullandı | +| `prov:wasAssociatedWith` | Bir etkinliğin bir ajan tarafından gerçekleştirildiği | PDFÇıkarmaEtkinliği, tg:PDFÇıkarıcı ile İlişkiliydi | + +#### Her Seviyedeki Metaveriler + +**Kaynak Belge (Librarian tarafından oluşturulan):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +<<<<<<< HEAD +**Sayfa (PDF Çıkarıcı tarafından oluşturulmuştur):** +======= +**Sayfa (PDF Çıkarma Aracı tarafından oluşturulmuştur):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +**Parça (Chunker tarafından üretilen):** +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +<<<<<<< HEAD +**Üçlü (Knowledge Extractor tarafından üretildi):** +======= +**Üçlü (Bilgi Çıkarıcı tarafından üretildi):** +>>>>>>> 82edf2d (New md files from RunPod) +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +<<<<<<< HEAD +**Gömme (vektör deposunda saklanır, üçlü depolamada değil):** + +Gömme verileri, RDF üçlüleri olarak değil, meta verilerle birlikte vektör deposunda saklanır. Her gömme kaydı şunları içerir: +======= +**Gömme (vektör depolama alanında saklanır, üçlü depolama alanında değil):** + +Gömme verileri, RDF üçlüleri olarak değil, meta verilerle birlikte vektör depolama alanında saklanır. Her gömme kaydı şunları içerir: +>>>>>>> 82edf2d (New md files from RunPod) + +| Alan | Açıklama | Örnek | +|-------|-------------|---------| +| vektör | Gömme vektörü | [0.123, -0.456, ...] | +| varlık | Gömmenin temsil ettiği düğüm URI'si | `entity:JohnSmith` | +| chunk_id | Kaynak parça (kaynak) | `chunk:123-1-1` | +| model | Kullanılan gömme modeli | `text-embedding-ada-002` | +| component_version | TG gömme sürümü | `1.0.0` | + +<<<<<<< HEAD +`entity` alanı, gömmeyi bilgi grafiğine (düğüm URI'si) bağlar. `chunk_id` alanı, orijinal belgeye kadar DAG üzerinde izlemeyi sağlayarak, kaynak parçaya ilişkin bilgileri sağlar. + +#### TrustGraph İsim Alanı Genişletmeleri + +Çıkarma ile ilgili meta veriler için `tg:` isim alanı altındaki özel önekler: + +| Önek | Alan | Açıklama | +|-----------|--------|-------------| +| `tg:contains` | Alt Grafik | Bu çıkarma alt grafiğindeki bir üçlüye işaret eder | +======= +`entity` alanı, gömmeyi bilgi grafiğine (düğüm URI'si) bağlar. `chunk_id` alanı, orijinal belgeye kadar DAG üzerinde gezinmeyi sağlayan, kaynak parçaya ilişkin bilgileri sağlar. + +#### TrustGraph Ad Alanı Genişletmeleri + +Çıkarma ile ilgili meta veriler için `tg:` ad alanının altındaki özel önekler: + +| Önek | Alan | Açıklama | +|-----------|--------|-------------| +| `tg:contains` | Alt Grafik | Bu çıkarma alt grafiğinde bulunan bir üçlüye işaret eder | +>>>>>>> 82edf2d (New md files from RunPod) +| `tg:pageCount` | Belge | Kaynak belgedeki toplam sayfa sayısı | +| `tg:mimeType` | Belge | Kaynak belgenin MIME türü | +| `tg:pageNumber` | Sayfa | Kaynak belgedeki sayfa numarası | +| `tg:chunkIndex` | Parça | Ebeveyn içindeki parçanın indeksi | +| `tg:charOffset` | Parça | Ebeveyn metnindeki karakter ofseti | +| `tg:charLength` | Parça | Parçanın karakter cinsinden uzunluğu | +| `tg:chunkSize` | Etkinlik | Yapılandırılmış parça boyutu | +| `tg:chunkOverlap` | Etkinlik | Parçalar arasındaki yapılandırılmış örtüşme | +| `tg:componentVersion` | Etkinlik | TG bileşeninin sürümü | +| `tg:llmModel` | Etkinlik | Çıkarma için kullanılan LLM | +| `tg:ontology` | Etkinlik | Çıkarma için kullanılan ontoloji URI'si | +| `tg:embeddingModel` | Etkinlik | Gömme için kullanılan model | +| `tg:sourceText` | İfade | Bir üçlünün çıkarıldığı tam metin | +| `tg:sourceCharOffset` | İfade | Kaynak metnin başladığı parça içindeki karakter ofseti | +| `tg:sourceCharLength` | İfade | Kaynak metnin karakter cinsinden uzunluğu | + +#### Sözlük Başlatma (Her Koleksiyon İçin) + +<<<<<<< HEAD +Bilgi grafiği, ontolojiye bağımlı olmayan ve başlangıçta boş olan bir yapıdır. Bir koleksiyona PROV-O kaynak verilerini ilk kez yazarken, tüm sınıflar ve önekler için RDF etiketleriyle sözlük başlatılmalıdır. Bu, sorgularda ve kullanıcı arayüzünde okunabilir bir görüntüleme sağlar. +======= +Bilgi grafiği, ontolojiye bağımlı olmayan ve başlangıçta boş durumdadır. Bir koleksiyona PROV-O kaynak verilerini ilk kez yazarken, tüm sınıflar ve önekler için RDF etiketleriyle sözlük başlatılmalıdır. Bu, sorgularda ve kullanıcı arayüzünde okunabilir bir görüntüleme sağlar. +>>>>>>> 82edf2d (New md files from RunPod) + +**PROV-O Sınıfları:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +**PROV-O Yüklemleri:** +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**TrustGraph Önermeleri:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**Uygulama notu:** Bu sözlük başlatma işleminin idempotent olması gerekir - yani, çoğaltmalar oluşturmadan birden çok kez çalıştırılabilir. Bu işlem, bir koleksiyondaki ilk belge işleme sırasında veya ayrı bir koleksiyon başlatma adımı olarak tetiklenebilir. +======= +**Uygulama notu:** Bu sözlük başlatma işleminin idempotent olması gerekir - yani, çoğaltmalar oluşturmadan birden çok kez çalıştırılabilir. Koleksiyon içindeki ilk belge işleme sırasında veya ayrı bir koleksiyon başlatma adımı olarak tetiklenebilir. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Alt Parça Kaynağı (İdeal) + +Daha ayrıntılı bir kaynak bilgisi için, bir üçlemenin bir parça içinde tam olarak nereden çıkarıldığı kaydedilmesi değerli olacaktır. Bu, şunları sağlar: + +Kullanıcı arayüzünde (UI) tam kaynak metninin vurgulanması +Çıkarma doğruluğunun kaynağa göre doğrulanması +Çıkarma kalitesinin cümle düzeyinde hata ayıklanması + +**Konum takibi ile örnek:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**Metin aralığı içeren örnek (alternatif):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +**Uygulama hususları:** + +LLM tabanlı çıkarma, doğal olarak karakter konumlarını sağlamayabilir. +LLM'den çıkarılan üçlülerin yanı sıra kaynak cümleyi/ifadeyi de döndürmesi istenebilir. +Alternatif olarak, çıkarılan varlıkları kaynak metne geri eşleştirmek için bir işlem sonrası adımı uygulanabilir. +Çıkarma karmaşıklığı ile kaynak doğruluğu arasındaki denge. +<<<<<<< HEAD +Yapılandırılmış çıkarma yöntemleriyle serbest biçimli LLM çıkarma yöntemlerinden daha kolay uygulanabilir olabilir. +======= +Serbest biçimli LLM çıkarma yöntemlerine kıyasla yapılandırılmış çıkarma yöntemleriyle elde edilmesi daha kolay olabilir. +>>>>>>> 82edf2d (New md files from RunPod) + +Bu, iddialı bir hedef olarak işaretlenmiştir - temel parça düzeyindeki kaynak bilgisi öncelikle uygulanmalı, alt parça takibi ise uygulanabilirse gelecekteki bir iyileştirme olarak düşünülmelidir. + +### Çift Depolama Modeli + +Kaynak bilgisi DAG'ı, belgeler boru hattından geçerken kademeli olarak oluşturulur: + +<<<<<<< HEAD +| Depo | Neler Saklanır | Amaç | +|-------|---------------|---------| +| Kütüphaneci | Belge içeriği + ebeveyn-çocuk bağlantıları | İçerik alma, kaskad silme | +| Bilgi Grafiği | Ebeveyn-çocuk kenarları + meta veri | Kaynak bilgisi sorguları, gerçek ataması | + +Her iki depo da aynı DAG yapısını korur. Kütüphaneci içeriği saklar; grafik ilişkileri saklar ve gezinme sorgularını sağlar. + +### Temel Tasarım Prensipleri +======= +| Depolama | Neler Depolanır | Amaç | +|-------|---------------|---------| +| Kütüphaneci | Belge içeriği + ebeveyn-çocuk bağlantıları | İçerik alma, zincirleme silme | +| Bilgi Grafiği | Ebeveyn-çocuk kenarları + meta veri | Kaynak bilgisi sorguları, gerçek ataması | + +Her iki depolama birimi de aynı DAG yapısını korur. Kütüphaneci içeriği tutarken, grafik ilişkileri tutar ve gezinme sorgularını sağlar. + +### Temel Tasarım İlkeleri +>>>>>>> 82edf2d (New md files from RunPod) + +1. **Belge Kimliği akış birimi olarak** - İşleyiciler içeriği değil, kimlikleri iletir. İçerik gerektiğinde kütüphaneciden alınır. + +2. **Kaynakta bir kez yayınla** - Meta veri, işleme başladığında grafiğe bir kez yazılır, aşağı akışta tekrarlanmaz. + +3. **Tutarlı işlemci kalıbı** - Her işlemci aynı alım/alma/üretme/kaydetme/yayınlama/ileri gönderme kalıbını izler. + +<<<<<<< HEAD +4. **Kademeli DAG oluşturma** - Her işlemci DAG'a kendi seviyesini ekler. Tam kaynak bilgisi zinciri kademeli olarak oluşturulur. + +5. **Parça sonrasındaki optimizasyon** - Parçalama işleminden sonra, mesajlar hem kimliği hem de içeriği taşır. Parçalar küçüktür (2-4KB), bu nedenle içeriği dahil etmek, kütüphaneciye yapılan gereksiz geri dönüşleri önlerken kimlik yoluyla kaynak bilgisini korur. +======= +4. **Kademeli DAG oluşturma** - Her işlemci, DAG'a kendi seviyesini ekler. Tam kaynak bilgisi zinciri kademeli olarak oluşturulur. + +5. **Parça sonrasındaki optimizasyon** - Parçalama işleminden sonra, mesajlar hem kimliği hem de içeriği taşır. Parçalar küçüktür (2-4KB), bu nedenle içeriği dahil etmek, kütüphaneci ile gereksiz geri dönüşleri önlerken, kimlik aracılığıyla kaynak bilgisini korur. +>>>>>>> 82edf2d (New md files from RunPod) + +## Uygulama Görevleri + +### Kütüphaneci Değişiklikleri + +#### Mevcut Durum + +Belge işleme işlemini başlatarak belge kimliğini ilk işlemciye gönderir. +<<<<<<< HEAD +Üçlü depoyla bağlantı yok - meta veri, çıkarma çıktılarıyla birlikte paketlenir. +`add-child-document` tek seviyeli ebeveyn-çocuk bağlantıları oluşturur. +======= +Üçlü depolamaya bağlantı yok - meta veri, çıkarma çıktılarıyla birlikte paketlenir. +`add-child-document` tek düzeyli ebeveyn-çocuk bağlantıları oluşturur. +>>>>>>> 82edf2d (New md files from RunPod) +`list-children` yalnızca hemen alt öğeleri döndürür. + +#### Gerekli Değişiklikler + +<<<<<<< HEAD +**1. Yeni arayüz: Üçlü depo bağlantısı** + +Kütüphaneci, işleme başlatıldığında belge meta veri kenarlarını doğrudan bilgi grafiğine yayınlamalıdır. +Kütüphaneci hizmetine üçlü depo istemci/yayınlayıcısı ekleyin. +======= +**1. Yeni arayüz: Üçlü depolama bağlantısı** + +Kütüphaneci, işleme başlatıldığında belge meta veri kenarlarını doğrudan bilgi grafiğine yayınlamalıdır. +Kütüphaneci hizmetine üçlü depolama istemci/yayınlayıcısı ekleyin. +>>>>>>> 82edf2d (New md files from RunPod) +İşleme başlatıldığında: kök belge meta verilerini grafik kenarları olarak (tek seferlik) yayınlayın. + +**2. Belge türü sözlüğü** + +<<<<<<< HEAD +Alt belgeler için `document_type` değerlerini standartlaştırın: +======= +Çocuk belgeler için `document_type` değerlerini standartlaştırın: +>>>>>>> 82edf2d (New md files from RunPod) +`source` - orijinal olarak yüklenen belge +`page` - kaynaktan (PDF, vb.) çıkarılan sayfa +`chunk` - sayfadan veya kaynaktan türetilen metin parçası + +#### Arayüz Değişiklikleri Özeti + +| Arayüz | Değişiklik | +|-----------|--------| +<<<<<<< HEAD +| Üçlü depo | Yeni dışa dönük bağlantı - belge meta veri kenarlarını yayınlayın | +| İşleme başlatma | Meta veriyi grafiğe yayınlayın, belge kimliğini iletmeden önce | +======= +| Üçlü depolama | Yeni dışa dönük bağlantı - belge meta veri kenarlarını yayınlayın | +| İşleme başlatma | Meta veriyi grafiğe yayınlayın, belge kimliğini iletmeye devam etmeden önce | +>>>>>>> 82edf2d (New md files from RunPod) + +### PDF Çıkarma Değişiklikleri + +#### Mevcut Durum + +<<<<<<< HEAD +Belge içeriğini alır (veya büyük belgeleri akış halinde alır) +PDF sayfalarından metin çıkarır +Sayfa içeriğini parçalayıcıya iletir +Kütüphaneci veya üçlü depo ile etkileşimde bulunmaz +======= +Belge içeriğini alır (veya büyük belgeleri akış halinde alır). +PDF sayfalarından metin çıkarır. +Sayfa içeriğini parçalayıcıya iletir. +Kütüphaneci veya üçlü depolamayla etkileşimde bulunmaz. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Gerekli Değişiklikler + +**1. Yeni arayüz: Kütüphaneci istemcisi** + +<<<<<<< HEAD +PDF çıkarıcı, her sayfayı kütüphanecide bir alt belge olarak kaydetmelidir. +PDF çıkarıcı hizmetine kütüphaneci istemcisi ekleyin +Her sayfa için: ebeveyn = kök belge kimliği ile `add-child-document`'yi çağırın + +**2. Yeni arayüz: Üçlü depo bağlantısı** + +PDF çıkarıcı, ebeveyn-çocuk kenarlarını bilgi grafiğine yayınlamalıdır. +Üçlü depo istemci/yayınlayıcısı ekleyin +Her sayfa için: sayfa belgesini ebeveyn belgeyle ilişkilendiren bir kenar yayınlayın +======= +PDF çıkarıcı, her sayfayı kütüphanecide bir çocuk belge olarak kaydetmelidir. +PDF çıkarıcı hizmetine kütüphaneci istemcisi ekleyin. +Her sayfa için: `add-child-document`'ı ebeveyn = kök belge kimliği ile çağırın. + +**2. Yeni arayüz: Üçlü depolama bağlantısı** + +PDF çıkarıcı, ebeveyn-çocuk kenarlarını bilgi grafiğine yayınlamalıdır. +Üçlü depolama istemci/yayınlayıcısı ekleyin. +Her sayfa için: sayfa belgesini ebeveyn belgeye bağlayan bir kenar yayınlayın. +>>>>>>> 82edf2d (New md files from RunPod) + +**3. Çıktı biçimini değiştirin** + +Sayfa içeriğini doğrudan iletmek yerine, sayfa belge kimliğini iletin. +Chunker, içeriği kütüphaneden kimliği kullanarak alacaktır. + +#### Arayüz Değişiklikleri Özeti + +| Arayüz | Değişiklik | +|-----------|--------| +| Kütüphane | Yeni dışa aktarma - alt belgeleri kaydet | +| Üçlü depolama | Yeni dışa aktarma - ebeveyn-çocuk kenarlarını yayınla | +| Çıkış mesajı | İçerikten belge kimliğine geçiş | + +### Chunker Değişiklikleri + +#### Mevcut Durum + +Sayfa/metin içeriğini alır +Parçalara böler +Parça içeriğini sonraki işleme birimlerine iletir +Kütüphane veya üçlü depolamayla etkileşimde bulunmaz + +#### Gerekli Değişiklikler + +**1. Giriş işleme şeklini değiştirin** + +İçerik yerine belge kimliğini alın, kütüphaneden alın. +Chunker hizmetine kütüphane istemcisini ekleyin +Belge kimliğini kullanarak sayfa içeriğini alın + +**2. Yeni arayüz: Kütüphane istemcisi (yazma)** + +Her parçayı kütüphanede bir alt belge olarak kaydedin. +Her parça için: ebeveyn = sayfa belge kimliği ile `add-child-document`'ı çağırın + +**3. Yeni arayüz: Üçlü depolama bağlantısı** + +Ebeveyn-çocuk kenarlarını bilgi grafiğine yayınlayın. +Üçlü depolama istemcisini/yayınlayıcısını ekleyin +Her parça için: parça belgesini sayfa belgesine bağlayan kenarı yayınlayın + +**4. Çıkış biçimini değiştirin** + +Hem parça belge kimliğini hem de parça içeriğini iletin (parça işleminden sonraki optimizasyon). +Sonraki işleme birimleri, köken bilgisi için kimliği ve çalışmak için içeriği alır + +#### Arayüz Değişiklikleri Özeti + +| Arayüz | Değişiklik | +|-----------|--------| +| Giriş mesajı | İçerikten belge kimliğine geçiş | +| Kütüphane | Yeni dışa aktarma (okuma + yazma) - içeriği alın, alt belgeleri kaydedin | +| Üçlü depolama | Yeni dışa aktarma - ebeveyn-çocuk kenarlarını yayınla | +| Çıkış mesajı | İçerikten kimliğe + içeriğe geçiş | + +### Bilgi Çıkarıcı Değişiklikleri + +#### Mevcut Durum + +Parça içeriğini alır +Üçlüleri ve gömme değerlerini çıkarır +Üçlü depolamaya ve gömme depolamaya yayınlar +`subjectOf` ilişkisi, en üst düzey belgeye (parçaya değil) işaret eder + +#### Gerekli Değişiklikler + +**1. Giriş işleme şeklini değiştirin** + +<<<<<<< HEAD +Parça belge kimliğini içeriğin yanında alın. +Köken bağlama için parça kimliğini kullanın (içerik zaten optimizasyon kapsamında dahil edilmiştir) + +**2. Üçlü kökeni güncelleyin** +======= +Parça belge kimliğini içeriğin yanı sıra alın. +Köken bağlantısı için parça kimliğini kullanın (içerik zaten optimizasyon kapsamında dahil edilmiştir) + +**2. Üçlü kökenini güncelleyin** +>>>>>>> 82edf2d (New md files from RunPod) + +Çıkarılan üçlüleri parçaya (en üst düzey belgeye değil) bağlayın. +Kenara işaret eden bir kenar oluşturmak için yeniden tanımlama kullanın +`subjectOf` ilişkisi: üçlü → parça belge kimliği +Mevcut yeniden tanımlama desteğinin ilk kullanımı + +**3. Gömme kökenini güncelleyin** + +Gömme varlık kimliklerini parçaya bağlayın. +Kenar yayınlayın: gömme varlık kimliği → parça belge kimliği + +#### Arayüz Değişiklikleri Özeti + +| Arayüz | Değişiklik | +|-----------|--------| +| Giriş mesajı | Parça kimliğini + içeriği bekleyin (sadece içeriği değil) | +| Üçlü depolama | Üçlü → parça kökeni için yeniden tanımlamayı kullanın | +| Gömme kökeni | Varlık kimliğini → parça kimliğine bağlayın | + +## Referanslar + +Sorgu zamanı kökeni: `docs/tech-specs/query-time-provenance.md` +Köken modellemesi için PROV-O standardı +Bilgi grafiğindeki mevcut kaynak meta verileri (denetlenmesi gerekir) diff --git a/docs/tech-specs/extraction-time-provenance.zh-cn.md b/docs/tech-specs/extraction-time-provenance.zh-cn.md new file mode 100644 index 00000000..4c8ceba5 --- /dev/null +++ b/docs/tech-specs/extraction-time-provenance.zh-cn.md @@ -0,0 +1,837 @@ +--- +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. + +## 概述 + +本文档记录了关于提取时数据来源的笔记,用于未来的规范工作。提取时的数据来源记录了数据的“源层”,即数据最初来自哪里,以及它是如何提取和转换的。 + +这与查询时的数据来源(参见 `query-time-provenance.md`)不同,后者记录的是代理推理过程。 + +## 问题陈述 + +### 当前实现 + +<<<<<<< HEAD +目前,数据来源的工作方式如下: +======= +当前的数据来源工作方式如下: +>>>>>>> 82edf2d (New md files from RunPod) +文档元数据以 RDF 三元组的形式存储在知识图谱中。 +文档 ID 将元数据与文档关联起来,因此文档在图中显示为节点。 +当从文档中提取出边(关系/事实)时,一个 `subjectOf` 关系将提取出的边链接回原始文档。 + +### 当前方法的缺点 + +<<<<<<< HEAD +1. **重复加载元数据:** 文档元数据会被打包并重复加载,每次从该文档中提取一批三元组时都会重复。这既浪费又冗余,相同的元数据会作为“货物”随每次提取输出一起传输。 +======= +1. **重复加载元数据:** 文档元数据被打包并重复加载,每次从该文档中提取一批三元组时都会重复。这既浪费又冗余,相同的元数据会作为“货物”随每次提取输出一起传输。 +>>>>>>> 82edf2d (New md files from RunPod) + +2. **浅层数据来源:** 当前的 `subjectOf` 关系仅将事实直接链接到顶级文档。无法了解转换链,例如,该事实来自哪个页面,哪个块,使用了哪种提取方法。 + +### 期望状态 + +1. **一次加载元数据:** 文档元数据应该只加载一次,并附加到顶级文档节点,而不是重复包含在每个三元组批次中。 + +<<<<<<< HEAD +2. **丰富的数据来源 DAG:** 捕获从原始文档到所有中间工件,再到提取出的事实的完整转换链。例如,一个 PDF 文档的转换过程: +======= +2. **丰富的数据来源 DAG:** 捕获从原始文档到所有中间工件再到提取事实的完整转换链。例如,一个 PDF 文档的转换过程: +>>>>>>> 82edf2d (New md files from RunPod) + + ``` + PDF file (source document with metadata) + → Page 1 (decoded text) + → Chunk 1 + → Extracted edge/fact (via subjectOf) + → Extracted edge/fact + → Chunk 2 + → Extracted edge/fact + → Page 2 + → Chunk 3 + → ... + ``` + +<<<<<<< HEAD +3. **统一存储:** 提取的知识及其来源信息(provenance)都存储在同一个知识图谱中。这使得对来源信息的查询方式与对知识的查询方式相同,即可以从任何事实出发,沿着链条追溯到其确切的来源位置。 + +4. **稳定的ID:** 每个中间产物(页面、段落)都具有一个稳定的ID,该ID在图中表示为一个节点。 + +5. **父子链接:** 从派生文档到其父文档,一直链接到顶层源文档,使用一致的关系类型。 +======= +3. **统一存储:** 提取的知识及其来源信息(provenance)都存储在同一个知识图谱中。这使得对来源信息的查询方式与对知识的查询方式相同——可以从任何事实出发,沿着链条追溯到其确切的来源位置。 + +4. **稳定的ID:** 每个中间产物(页面、段落)都有一个稳定的ID,作为图谱中的一个节点。 + +5. **父子链接:** 从派生文档到其父文档,一直链接到顶层原始文档,使用一致的关系类型。 +>>>>>>> 82edf2d (New md files from RunPod) + +6. **精确的事实归属:** 提取的边上的 `subjectOf` 关系指向直接的父节点(段落),而不是顶层文档。可以通过遍历DAG来恢复完整的来源信息。 + +## 用例 + +### UC1:GraphRAG响应中的来源归属 + +**场景:** 用户运行GraphRAG查询,并从代理接收到响应。 + +**流程:** +1. 用户向GraphRAG代理提交查询。 +2. 代理从知识图谱中检索相关的事实,以构建响应。 +3. 根据查询时期的来源信息规范,代理报告哪些事实对响应做出了贡献。 +<<<<<<< HEAD +4. 每个事实通过来源信息DAG链接到其源段落。 +5. 段落链接到页面,页面链接到源文档。 +======= +4. 每个事实通过来源信息DAG链接到其来源段落。 +5. 段落链接到页面,页面链接到原始文档。 +>>>>>>> 82edf2d (New md files from RunPod) + +**用户体验结果:** 界面会显示LLM响应以及来源归属信息。用户可以: +查看哪些事实支持了响应。 +从事实 → 段落 → 页面 → 文档进行深入了解。 +<<<<<<< HEAD +浏览原始的源文档以验证声明。 +======= +浏览原始来源文档以验证声明。 +>>>>>>> 82edf2d (New md files from RunPod) +准确了解事实的来源(哪个页面,哪个部分)。 + +**价值:** 用户可以根据原始来源验证AI生成的响应,从而建立信任并实现事实核查。 + +### UC2:调试提取质量 + +<<<<<<< HEAD +某个事实看起来不正确。追溯到段落 → 页面 → 文档,查看原始文本。是提取出现问题,还是原始来源本身就是错误的? + +### UC3:增量重提取 + +源文档已更新。哪些段落/事实是从它派生的?仅使这些段落/事实失效并重新生成,而不是重新处理所有内容。 + +### UC4:数据删除/被遗忘的权利 + +必须删除一个源文档(GDPR、法律等)。遍历DAG以查找并删除所有派生的事实。 + +### UC5:冲突解决 + +两个事实相互矛盾。追溯到它们的来源,以了解原因并决定应该信任哪个(更权威的来源、更新的来源等)。 +======= +某个事实看起来不正确。追溯到段落 → 页面 → 文档,查看原始文本。是提取过程出现问题,还是原始来源本身就是错误的? + +### UC3:增量重提取 + +原始文档被更新。哪些段落/事实是从它派生的?仅使这些段落/事实失效并重新生成,而不是重新处理所有内容。 + +### UC4:数据删除/被遗忘的权利 + +必须删除一个原始文档(GDPR、法律等)。遍历DAG以查找并删除所有派生的事实。 + +### UC5:冲突解决 + +两个事实相互矛盾。追溯到它们的来源,以了解原因,并决定应该信任哪个(更权威的来源、更新的来源等)。 +>>>>>>> 82edf2d (New md files from RunPod) + +### UC6:来源权威性加权 + +某些来源比其他来源更具权威性。可以根据其原始文档的权威性/质量对事实进行加权或过滤。 + +### UC7:提取管道比较 + +<<<<<<< HEAD +比较来自不同提取方法/版本的输出。哪个提取器从相同的来源生成了更好的事实? +======= +比较不同提取方法/版本的输出。哪个提取器从相同的来源生成了更好的事实? +>>>>>>> 82edf2d (New md files from RunPod) + +## 集成点 + +### Librarian + +librarian组件已经提供了文档存储,并具有唯一的文档ID。来源信息系统与此现有的基础设施集成。 + +#### 现有功能(已实现) + +**父子文档链接:** +<<<<<<< HEAD +`parent_id` 字段在 `DocumentMetadata` 中 - 将子文档链接到父文档。 +`document_type` 字段 - 值:`"source"`(原始)或 `"extracted"`(派生)。 +`add-child-document` API - 创建具有自动 `document_type = "extracted"` 的子文档。 +`list-children` API - 检索父文档的所有子文档。 +级联删除 - 删除父文档会自动删除所有子文档。 + +**文档识别:** +文档ID由客户端指定(不是自动生成)。 +文档按复合 `(user, document_id)` 在Cassandra中键入。 +对象ID(UUID)在内部生成,用于blob存储。 + +**元数据支持:** +`metadata: list[Triple]` 字段 - RDF三元组用于结构化元数据。 +`title`、`comments`、`tags` - 基本文档元数据。 +`time` - 时间戳,`kind` - MIME类型。 + +**存储架构:** +元数据存储在Cassandra中(`librarian` 键空间,`document` 表)。 +内容存储在MinIO/S3 blob存储中(`library` 存储桶)。 +智能内容交付:小于 2MB 的文档嵌入,较大的文档流式传输。 + +#### 关键文件 + +`trustgraph-flow/trustgraph/librarian/librarian.py` - 核心 librarian 操作。 +`trustgraph-flow/trustgraph/librarian/service.py` - 服务处理器,文档加载。 +`trustgraph-flow/trustgraph/tables/library.py` - Cassandra 表存储。 +`trustgraph-base/trustgraph/schema/services/library.py` - 模式定义。 + +#### 需要解决的问题 + +librarian 具有构建块,但目前: +1. 父子链接仅限于一级深度 - 没有多级DAG遍历辅助功能。 +2. 没有标准的关系类型词汇表(例如,`derivedFrom`、`extractedFrom`)。 +3. 来源信息元数据(提取方法、置信度、段落位置)尚未标准化。 +4. 没有查询API来遍历从事实到源的全程来源信息链。 +======= +`parent_id` 字段在 `DocumentMetadata` 中 - 将子文档链接到父文档 +`document_type` 字段 - 值:`"source"`(原始)或 `"extracted"`(派生) +`add-child-document` API - 创建具有自动 `document_type = "extracted"` 的子文档 +`list-children` API - 检索父文档的所有子文档 +级联删除 - 删除父文档会自动删除所有子文档 + +**文档识别:** +文档ID由客户端指定(不是自动生成) +文档按复合 `(user, document_id)` 在Cassandra中键入 +对象ID(UUID)在内部生成,用于blob存储 + +**元数据支持:** +`metadata: list[Triple]` 字段 - RDF三元组用于结构化元数据 +`title`、`comments`、`tags` - 基本文档元数据 +`time` - 时间戳,`kind` - MIME类型 + +**存储架构:** +元数据存储在Cassandra中(`librarian` keyspace,`document` table) +内容存储在MinIO/S3 blob存储中(`library` bucket) +智能内容交付:小于 2MB 的文档嵌入,较大的文档流式传输 + +#### 关键文件 + +`trustgraph-flow/trustgraph/librarian/librarian.py` - 核心 librarian 操作 +`trustgraph-flow/trustgraph/librarian/service.py` - 服务处理器,文档加载 +`trustgraph-flow/trustgraph/tables/library.py` - Cassandra 表存储 +`trustgraph-base/trustgraph/schema/services/library.py` - 模式定义 + +#### 需要解决的关键问题 + +librarian 具有构建块,但目前: +1. 父子链接仅限于一级深度 - 没有多级DAG遍历辅助功能 +2. 没有标准的关系类型词汇表(例如,`derivedFrom`、`extractedFrom`) +3. 来源信息元数据(提取方法、置信度、段落位置)尚未标准化 +4. 没有查询API来遍历从事实到原始来源的完整来源信息链 +>>>>>>> 82edf2d (New md files from RunPod) + +## 端到端流程设计 + +管道中的每个处理器都遵循一致的模式: +<<<<<<< HEAD +从上游接收文档ID。 +从librarian中获取内容。 +生成子产物。 +对于每个子产物:保存到librarian,向图发出边,将ID转发到下游。 + +### 处理流程 + +有两个流程,具体取决于文档类型: +======= +从上游接收文档ID +从librarian中获取内容 +生成子产物 +对于每个子产物:保存到librarian,向图发出边,向下游传递ID + +### 处理流程 + +根据文档类型,有两种流程: +>>>>>>> 82edf2d (New md files from RunPod) + +#### PDF文档流程 + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID to PDF extractor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ PDF Extractor (per page) │ +│ 1. Fetch PDF content from librarian using document ID │ +│ 2. Extract pages as text │ +│ 3. For each page: │ +│ a. Save page as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send page document ID to chunker │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch page content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = page) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + Post-chunker optimization: messages carry both + chunk ID (for provenance) and content (to avoid + librarian round-trip). Chunks are small (2-4KB). + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor (per chunk) │ +│ 1. Receive chunk ID + content directly (no librarian fetch needed) │ +│ 2. Extract facts/triples and embeddings from chunk content │ +│ 3. For each triple: │ +│ a. Emit triple to knowledge graph │ +│ b. Emit reified edge linking triple → chunk ID (edge pointing │ +│ to edge - first use of reification support) │ +│ 4. For each embedding: │ +│ a. Emit embedding with its entity ID │ +│ b. Link entity ID → chunk ID in knowledge graph │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### 文本文档流程 + +文本文档会跳过 PDF 提取器,直接进入分块处理: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Librarian (initiate processing) │ +│ 1. Emit root document metadata to knowledge graph (once) │ +│ 2. Send root document ID directly to chunker (skip PDF extractor) │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Chunker (per chunk) │ +│ 1. Fetch text content from librarian using document ID │ +│ 2. Split text into chunks │ +│ 3. For each chunk: │ +│ a. Save chunk as child document in librarian (parent = root doc) │ +│ b. Emit parent-child edge to knowledge graph │ +│ c. Send chunk document ID + chunk content to next processor │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Knowledge Extractor │ +│ (same as PDF flow) │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +结果生成的有向无环图(DAG)的层数减少了一层: + +``` +PDF: Document → Pages → Chunks → Triples/Embeddings +Text: Document → Chunks → Triples/Embeddings +``` + +该设计同时适用于这两种情况,因为分块器以通用方式处理其输入 - 它使用接收到的任何文档 ID 作为父级,无论该 ID 是源文档还是页面。 + +### 元数据模式 (PROV-O) + +溯源元数据使用 W3C PROV-O 本体。这提供了一个标准词汇表,并为未来提取输出的签名/身份验证提供了支持。 + +#### PROV-O 核心概念 + +| PROV-O 类型 | TrustGraph 用法 | +|-------------|------------------| +| `prov:Entity` | 文档、页面、块、三元组、嵌入 | +| `prov:Activity` | 提取操作的实例 | +| `prov:Agent` | TG 组件(PDF 提取器、分块器等)及其版本 | + +#### PROV-O 关系 + +| 谓词 | 含义 | 示例 | +|-----------|---------|---------| +| `prov:wasDerivedFrom` | 一个实体源自另一个实体 | 页面 wasDerivedFrom 文档 | +| `prov:wasGeneratedBy` | 一个实体由一个活动生成 | 页面 wasGeneratedBy PDFExtractionActivity | +| `prov:used` | 一个活动使用一个实体作为输入 | PDFExtractionActivity used Document | +| `prov:wasAssociatedWith` | 一个活动由一个代理执行 | PDFExtractionActivity wasAssociatedWith tg:PDFExtractor | + +#### 每个级别的元数据 + +**源文档(由 Librarian 产生):** +``` +doc:123 a prov:Entity . +doc:123 dc:title "Research Paper" . +doc:123 dc:source . +doc:123 dc:date "2024-01-15" . +doc:123 dc:creator "Author Name" . +doc:123 tg:pageCount 42 . +doc:123 tg:mimeType "application/pdf" . +``` + +**页面 (由 PDF 提取器生成):** +``` +page:123-1 a prov:Entity . +page:123-1 prov:wasDerivedFrom doc:123 . +page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . +page:123-1 tg:pageNumber 1 . + +activity:pdf-extract-456 a prov:Activity . +activity:pdf-extract-456 prov:used doc:123 . +activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . +activity:pdf-extract-456 tg:componentVersion "1.2.3" . +activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . +``` + +**块 (由分块器发出):** +``` +chunk:123-1-1 a prov:Entity . +chunk:123-1-1 prov:wasDerivedFrom page:123-1 . +chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . +chunk:123-1-1 tg:chunkIndex 1 . +chunk:123-1-1 tg:charOffset 0 . +chunk:123-1-1 tg:charLength 2048 . + +activity:chunk-789 a prov:Activity . +activity:chunk-789 prov:used page:123-1 . +activity:chunk-789 prov:wasAssociatedWith tg:Chunker . +activity:chunk-789 tg:componentVersion "1.0.0" . +activity:chunk-789 tg:chunkSize 2048 . +activity:chunk-789 tg:chunkOverlap 200 . +``` + +**强调 (由知识提取器发出):** +``` +# The extracted triple (edge) +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph containing the extracted triples +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 prov:wasGeneratedBy activity:extract-999 . + +activity:extract-999 a prov:Activity . +activity:extract-999 prov:used chunk:123-1-1 . +activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . +activity:extract-999 tg:componentVersion "2.1.0" . +activity:extract-999 tg:llmModel "claude-3" . +activity:extract-999 tg:ontology . +``` + +**嵌入 (存储在向量存储中,而不是三元组存储中):** + +嵌入存储在向量存储中,包含元数据,而不是作为 RDF 三元组。每个嵌入记录包含: + +| 字段 | 描述 | 示例 | +|-------|-------------|---------| +| vector | 嵌入向量 | [0.123, -0.456, ...] | +| entity | 嵌入所代表的节点 URI | `entity:JohnSmith` | +| chunk_id | 源块 (来源) | `chunk:123-1-1` | +| model | 使用的嵌入模型 | `text-embedding-ada-002` | +| component_version | TG 嵌入器版本 | `1.0.0` | + +`entity` 字段将嵌入链接到知识图谱 (节点 URI)。 `chunk_id` 字段提供回溯到源块的来源信息,从而可以向上遍历 DAG,到达原始文档。 + +#### TrustGraph 命名空间扩展 + +在 `tg:` 命名空间下,定义了用于提取特定元数据的自定义谓词: + +| 谓词 | 域 | 描述 | +|-----------|--------|-------------| +| `tg:contains` | Subgraph | 指向此提取子图中包含的三元组 | +| `tg:pageCount` | Document | 源文档中的总页数 | +| `tg:mimeType` | Document | 源文档的 MIME 类型 | +| `tg:pageNumber` | Page | 源文档中的页码 | +| `tg:chunkIndex` | Chunk | 父级中的块索引 | +| `tg:charOffset` | Chunk | 父级文本中的字符偏移量 | +| `tg:charLength` | Chunk | 块的字符长度 | +| `tg:chunkSize` | Activity | 配置的块大小 | +| `tg:chunkOverlap` | Activity | 配置的块之间的重叠 | +| `tg:componentVersion` | Activity | TG 组件的版本 | +| `tg:llmModel` | Activity | 用于提取的 LLM | +| `tg:ontology` | Activity | 用于指导提取的本体 URI | +| `tg:embeddingModel` | Activity | 用于嵌入的模型 | +| `tg:sourceText` | Statement | 从提取的三元组的精确文本 | +| `tg:sourceCharOffset` | Statement | 源文本在块中的字符偏移量 | +| `tg:sourceCharLength` | Statement | 源文本的字符长度 | + +#### 词汇引导 (每个集合) + +<<<<<<< HEAD +知识图谱是本体无关的,并且初始化为空。 当首次将 PROV-O provenance 数据写入集合时,必须使用 RDF 标签引导所有类和谓词的词汇。 这可确保在查询和 UI 中提供人类可读的显示。 +======= +知识图谱是本体无关的,并且初始化为空。当首次将 PROV-O provenance 数据写入集合时,必须使用 RDF 标签引导所有类和谓词的词汇。这可确保在查询和 UI 中提供人类可读的显示。 +>>>>>>> 82edf2d (New md files from RunPod) + +**PROV-O 类:** +``` +prov:Entity rdfs:label "Entity" . +prov:Activity rdfs:label "Activity" . +prov:Agent rdfs:label "Agent" . +``` + +<<<<<<< HEAD +**PROV-O谓词:** +======= +**PROV-O 谓词:** +>>>>>>> 82edf2d (New md files from RunPod) +``` +prov:wasDerivedFrom rdfs:label "was derived from" . +prov:wasGeneratedBy rdfs:label "was generated by" . +prov:used rdfs:label "used" . +prov:wasAssociatedWith rdfs:label "was associated with" . +prov:startedAtTime rdfs:label "started at" . +``` + +**TrustGraph谓词:** +``` +tg:contains rdfs:label "contains" . +tg:pageCount rdfs:label "page count" . +tg:mimeType rdfs:label "MIME type" . +tg:pageNumber rdfs:label "page number" . +tg:chunkIndex rdfs:label "chunk index" . +tg:charOffset rdfs:label "character offset" . +tg:charLength rdfs:label "character length" . +tg:chunkSize rdfs:label "chunk size" . +tg:chunkOverlap rdfs:label "chunk overlap" . +tg:componentVersion rdfs:label "component version" . +tg:llmModel rdfs:label "LLM model" . +tg:ontology rdfs:label "ontology" . +tg:embeddingModel rdfs:label "embedding model" . +tg:sourceText rdfs:label "source text" . +tg:sourceCharOffset rdfs:label "source character offset" . +tg:sourceCharLength rdfs:label "source character length" . +``` + +<<<<<<< HEAD +**实施说明:** 这个词汇库初始化应该具有幂等性,即可以多次运行而不会创建重复项。 它可以触发在集合中的第一个文档处理过程中,或者作为单独的集合初始化步骤。 + +#### 子块来源信息(期望) + +为了获得更细粒度的来源信息,记录三元组是从块中的哪个位置提取出来的将非常有用。 这可以实现: +======= +**实施说明:** 此词汇引导过程应具有幂等性,即可以多次运行而不会创建重复项。 可以在集合中的首次文档处理过程中触发,也可以作为单独的集合初始化步骤。 + +#### 子块来源信息(期望) + +为了获得更精细的来源信息,记录三元组是从块中的哪个位置提取出来的将非常有用。 这可以实现: +>>>>>>> 82edf2d (New md files from RunPod) + +在用户界面中突出显示确切的原始文本 +验证提取的准确性与原始文本 +在句子级别调试提取质量 + +**带有位置跟踪的示例:** +``` +# The extracted triple +entity:JohnSmith rel:worksAt entity:AcmeCorp . + +# Subgraph with sub-chunk provenance +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +subgraph:001 tg:sourceCharOffset 1547 . +subgraph:001 tg:sourceCharLength 46 . +``` + +**带有文本范围的示例(备选方案):** +``` +subgraph:001 tg:contains <> . +subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . +subgraph:001 tg:sourceRange "1547-1593" . +subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . +``` + +<<<<<<< HEAD +**实现注意事项:** + +基于 LLM 的提取可能无法自然地提供字符位置。 +可以提示 LLM 在提取的三元组旁边返回原始句子/短语。 +或者,可以进行后处理,将提取的实体模糊匹配回原始文本。 +提取复杂度和溯源粒度之间的权衡。 +使用结构化提取方法可能更容易实现,而不是使用自由形式的 LLM 提取。 + +这被标记为期望目标 - 首先应实现基本的块级溯源,如果可行,子块跟踪可以作为未来的增强功能。 +======= +**实现注意事项:** + +基于 LLM 的提取可能无法自然地提供字符位置 +可以提示 LLM 同时返回提取的三元组以及原始句子/短语 +或者,可以进行后处理,将提取的实体模糊匹配回原始文本 +提取复杂度和溯源粒度之间的权衡 +使用结构化提取方法可能更容易实现,而不是使用自由形式的 LLM 提取 + +这被标记为期望目标 - 首先应该实现基本的块级溯源,如果可行,子块跟踪可以作为未来的增强功能。 +>>>>>>> 82edf2d (New md files from RunPod) + +### 双重存储模型 + +溯源 DAG 是随着文档在流水线中流动而逐步构建的: + +| 存储 | 存储内容 | 目的 | +|-------|---------------|---------| +| Librarian | 文档内容 + 父子链接 | 内容检索、级联删除 | +| Knowledge Graph | 父子边 + 元数据 | 溯源查询、事实归属 | + +<<<<<<< HEAD +两个存储都维护相同的 DAG 结构。 Librarian 存储内容;Graph 存储关系,并支持遍历查询。 +======= +两个存储都维护相同的 DAG 结构。 Librarian 存储内容;Knowledge Graph 存储关系,并支持遍历查询。 +>>>>>>> 82edf2d (New md files from RunPod) + +### 关键设计原则 + +1. **文档 ID 作为流动的单位** - 处理程序传递 ID,而不是内容。 需要时从 Librarian 检索内容。 + +<<<<<<< HEAD +2. **在源头一次发出** - 元数据在处理开始时写入到 Graph 中,而不是在下游重复。 + +3. **一致的处理程序模式** - 每个处理程序都遵循相同的接收/检索/生成/保存/发出/转发模式。 + +4. **渐进的 DAG 构建** - 每个处理程序添加其级别到 DAG 中。 完整的溯源链是逐步构建的。 + +5. **分块后优化** - 在分块之后,消息同时携带 ID 和内容。 块很小(2-4KB),因此包含内容可以避免不必要的 Librarian 往返,同时通过 ID 保持溯源。 +======= +2. **在源头一次发出** - 元数据在处理开始时写入 Knowledge Graph 一次,而不是在下游重复。 + +3. **一致的处理程序模式** - 每个处理程序都遵循相同的接收/检索/生成/保存/发出/转发模式。 + +4. **渐进式 DAG 构建** - 每个处理程序添加其级别到 DAG。 完整的溯源链是逐步构建的。 + +5. **分块后优化** - 在分块之后,消息同时携带 ID 和内容。 块很小(2-4KB),因此包含内容可以避免不必要的 Librarian 交互,同时通过 ID 保持溯源。 +>>>>>>> 82edf2d (New md files from RunPod) + +## 实现任务 + +### Librarian 更改 + +#### 当前状态 + +<<<<<<< HEAD +通过将文档 ID 发送到第一个处理程序来启动文档处理。 +没有连接到三元存储 - 元数据与提取输出一起打包。 +`add-child-document` 创建一级父子链接。 +`list-children` 仅返回直接子节点。 +======= +通过将文档 ID 发送到第一个处理程序来启动文档处理 +没有连接到三元存储 - 元数据与提取输出一起打包 +`add-child-document` 创建一级父子链接 +`list-children` 仅返回直接子节点 +>>>>>>> 82edf2d (New md files from RunPod) + +#### 需要的更改 + +**1. 新接口:三元存储连接** + +<<<<<<< HEAD +Librarian 需要直接将文档元数据边发射到知识图谱,以在启动处理时进行操作。 +向 Librarian 服务添加三元存储客户端/发布器。 +在处理启动时:以图谱边的方式(一次)发射根文档元数据。 +======= +Librarian 需要直接将文档元数据边发射到 Knowledge Graph,以在启动处理时。 +向 Librarian 服务添加三元存储客户端/发布器 +在处理启动时:以图边形式(一次)发射根文档元数据 +>>>>>>> 82edf2d (New md files from RunPod) + +**2. 文档类型词汇表** + +标准化子文档的 `document_type` 值: +<<<<<<< HEAD +`source` - 原始上传的文档。 +`page` - 从源头提取的页面(PDF 等)。 +`chunk` - 从页面或源头派生的文本块。 +======= +`source` - 原始上传的文档 +`page` - 从源文件(PDF 等)提取的页面 +`chunk` - 从页面或源文件派生的文本块 +>>>>>>> 82edf2d (New md files from RunPod) + +#### 接口更改摘要 + +| 接口 | 更改 | +|-----------|--------| +<<<<<<< HEAD +| 三元存储 | 新的出站连接 - 发射文档元数据边 | +| 处理启动 | 在转发文档 ID 之前,向图谱发射元数据 | +======= +| 三元存储 | 新的外部连接 - 发射文档元数据边 | +| 处理启动 | 在转发文档 ID 之前,向图发射元数据 | +>>>>>>> 82edf2d (New md files from RunPod) + +### PDF 提取器更改 + +#### 当前状态 + +<<<<<<< HEAD +接收文档内容(或流式传输大型文档)。 +从 PDF 页面提取文本。 +将页面内容转发到分块器。 +没有与 Librarian 或三元存储交互。 +======= +接收文档内容(或流式传输大型文档) +从 PDF 页面提取文本 +将页面内容转发到分块器 +没有与 Librarian 或三元存储交互 +>>>>>>> 82edf2d (New md files from RunPod) + +#### 需要的更改 + +**1. 新接口:Librarian 客户端** + +PDF 提取器需要将每个页面作为子文档保存到 Librarian 中。 +<<<<<<< HEAD +向 PDF 提取器服务添加 Librarian 客户端。 +对于每个页面:使用父文档 ID 调用 `add-child-document`。 + +**2. 新接口:三元存储连接** + +PDF 提取器需要将父子边发射到知识图谱。 +添加三元存储客户端/发布器。 +对于每个页面:发射一个链接页面文档到父文档的边。 +======= +向 PDF 提取器服务添加 Librarian 客户端 +对于每个页面:使用父文档 ID 调用 `add-child-document` + +**2. 新接口:三元存储连接** + +PDF 提取器需要将父子边发射到 Knowledge Graph。 +添加三元存储客户端/发布器 +对于每个页面:发射将页面文档链接到父文档的边 +>>>>>>> 82edf2d (New md files from RunPod) + +**3. 更改输出格式** + +而是直接转发页面内容,而是转发页面文档 ID。 +Chunker 将使用 ID 从 librarian 获取内容 + +#### 接口变更摘要 + +| 接口 | 变更 | +|-----------|--------| +| Librarian | 新的输出 - 保存子文档 | +| Triple store | 新的输出 - 发射父子边 | +| 输出消息 | 从内容更改为文档 ID | + +### Chunker 变更 + +#### 当前状态 + +接收页面/文本内容 +分割成块 +将块内容转发到下游处理器 +不与 librarian 或 triple store 交互 + +#### 必需的变更 + +**1. 更改输入处理** + +接收文档 ID 而不是内容,从 librarian 获取。 +向 chunker 服务添加 librarian 客户端 +使用文档 ID 获取页面内容 + +<<<<<<< HEAD +**2. 新接口:Librarian 客户端(写入)** +======= +**2. 新接口:Librarian 客户端 (写入)** +>>>>>>> 82edf2d (New md files from RunPod) + +将每个块保存为 librarian 中的子文档。 +对于每个块:使用 parent = 页面文档 ID 调用 `add-child-document` + +**3. 新接口:Triple store 连接** + +向知识图谱发射父子边。 +添加 triple store 客户端/发布器 +对于每个块:发射链接块文档到页面文档的边 + +**4. 更改输出格式** + +同时转发块文档 ID 和块内容(块处理后的优化)。 +下游处理器接收 ID 用于溯源 + 用于处理的内容 + +#### 接口变更摘要 + +| 接口 | 变更 | +|-----------|--------| +| 输入消息 | 从内容更改为文档 ID | +<<<<<<< HEAD +| Librarian | 新的输出(读取 + 写入)- 获取内容,保存子文档 | +======= +| Librarian | 新的输出 (读取 + 写入) - 获取内容,保存子文档 | +>>>>>>> 82edf2d (New md files from RunPod) +| Triple store | 新的输出 - 发射父子边 | +| 输出消息 | 从仅包含内容更改为 ID + 内容 | + +### Knowledge Extractor 变更 + +#### 当前状态 + +接收块内容 +提取三元组和嵌入 +发送到 triple store 和 embedding store +<<<<<<< HEAD +`subjectOf` 关系指向顶级文档(不是块) +======= +`subjectOf` 关系指向顶级文档 (而不是块) +>>>>>>> 82edf2d (New md files from RunPod) + +#### 必需的变更 + +**1. 更改输入处理** + +接收块文档 ID 以及内容。 +<<<<<<< HEAD +使用块 ID 用于溯源链接(内容已包含在优化中) + +**2. 更新三元组溯源** + +将提取的三元组链接到块(而不是顶级文档)。 +======= +使用块 ID 用于溯源链接 (内容已包含在优化中) + +**2. 更新三元组溯源** + +将提取的三元组链接到块 (而不是顶级文档)。 +>>>>>>> 82edf2d (New md files from RunPod) +使用重构来创建指向边的边 +`subjectOf` 关系:三元组 → 块文档 ID +首次使用现有的重构支持 + +**3. 更新嵌入溯源** + +将嵌入实体 ID 链接到块。 +发射边:嵌入实体 ID → 块文档 ID + +#### 接口变更摘要 + +| 接口 | 变更 | +|-----------|--------| +<<<<<<< HEAD +| 输入消息 | 期望块 ID + 内容(不是仅包含内容) | +======= +| 输入消息 | 期望块 ID + 内容 (而不是仅包含内容) | +>>>>>>> 82edf2d (New md files from RunPod) +| Triple store | 使用重构进行三元组 → 块溯源 | +| 嵌入溯源 | 将实体 ID 链接到块 ID | + +## 引用 + +查询时溯源:`docs/tech-specs/query-time-provenance.md` +PROV-O 标准用于溯源建模 +<<<<<<< HEAD +知识图谱中现有的源元数据(需要审计) +======= +知识图谱中现有的源元数据 (需要审计) +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/flow-class-definition.ar.md b/docs/tech-specs/flow-class-definition.ar.md new file mode 100644 index 00000000..108c86bb --- /dev/null +++ b/docs/tech-specs/flow-class-definition.ar.md @@ -0,0 +1,311 @@ +--- +layout: default +title: "مواصفات تعريف مخطط التدفق" +parent: "Arabic (Beta)" +--- + +<<<<<<< HEAD +# مواصفات تعريف مخطط التدفق + +> **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. +======= +# تعريف مواصفات مخطط التدفق +>>>>>>> 82edf2d (New md files from RunPod) + +## نظرة عامة + +يحدد مخطط التدفق قالبًا كاملاً لنمط تدفق البيانات في نظام TrustGraph. عند تنفيذه، فإنه ينشئ شبكة مترابطة من المعالجات التي تتعامل مع استيعاب البيانات ومعالجتها وتخزينها والاستعلام عنها كنظام موحد. + +## الهيكل + +يتكون تعريف مخطط التدفق من خمسة أقسام رئيسية: + +### 1. قسم الفئة +يحدد معالجات الخدمات المشتركة التي يتم إنشاؤها مرة واحدة لكل مخطط تدفق. تتعامل هذه المعالجات مع الطلبات من جميع مثيلات التدفق لهذه الفئة. + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**الخصائص:** +مشتركة عبر جميع مثيلات التدفق من نفس الفئة. +عادةً ما تكون خدمات مكلفة أو غير تعتمد على الحالة (نماذج لغوية كبيرة، نماذج تضمين). +استخدم متغير القالب `{class}` لتسمية قائمة الانتظار. +يمكن أن تكون الإعدادات قيمًا ثابتة أو مُعَلمة باستخدام صيغة `{parameter-name}`. +أمثلة: `embeddings:{class}`، `text-completion:{class}`، `graph-rag:{class}`. + +### 2. قسم التدفق +يحدد المعالجات الخاصة بالتدفق والتي يتم إنشاؤها لكل مثيل تدفق فردي. يحصل كل تدفق على مجموعة معزولة خاصة به من هذه المعالجات. + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**الخصائص:** +نسخة فريدة لكل تدفق. +التعامل مع البيانات والحالة الخاصة بالتدفق. +استخدام متغير القالب `{id}` لأسماء قوائم الانتظار. +يمكن أن تكون الإعدادات قيمًا ثابتة أو مُعَلمة باستخدام صيغة `{parameter-name}`. +أمثلة: `chunker:{id}`، `pdf-decoder:{id}`، `kg-extract-relationships:{id}`. + +### القسم 3: الواجهات +يحدد نقاط الدخول وعقود التفاعل للتدفق. تشكل هذه الواجهة البرمجية (API) للأنظمة الخارجية وتواصل المكونات الداخلية. + +يمكن أن تتخذ الواجهات شكلين: + +**نمط الإرسال والإهمال** (قائمة انتظار واحدة): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**نمط الطلب/الاستجابة** (كائن يحتوي على حقول الطلب/الاستجابة): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**أنواع الواجهات:** +**نقاط الدخول:** الأماكن التي تقوم الأنظمة الخارجية بإدخال البيانات (`document-load`، `agent`) +**واجهات الخدمات:** أنماط الطلب/الاستجابة للخدمات (`embeddings`، `text-completion`) +**واجهات البيانات:** نقاط اتصال تدفق البيانات من نوع "أرسل وانتهى" (`triples-store`، `entity-contexts-load`) + +### القسم الرابع: معلمات +يربط أسماء المعلمات الخاصة بالتدفق بتعريفات المعلمات المخزنة مركزيًا: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**الخصائص:** +المفاتيح هي أسماء المعلمات المستخدمة في إعدادات المعالج (مثل: `{model}`) +القيم تشير إلى تعريفات المعلمات المخزنة في schema/config +يتيح إعادة استخدام تعريفات المعلمات الشائعة عبر التدفقات. +يقلل من تكرار مخططات المعلمات. + +### 5. البيانات الوصفية +معلومات إضافية حول مخطط التدفق: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## متغيرات القالب + +### متغيرات النظام + +#### {id} +يتم استبدالها بمعرّف مثيل التدفق الفريد. +<<<<<<< HEAD +تقوم بإنشاء موارد معزولة لكل تدفق. +======= +تنشئ موارد معزولة لكل تدفق. +>>>>>>> 82edf2d (New md files from RunPod) +مثال: `flow-123`، `customer-A-flow` + +#### {class} +يتم استبدالها باسم مخطط التدفق. +<<<<<<< HEAD +تقوم بإنشاء موارد مشتركة عبر التدفقات من نفس الفئة. +======= +تنشئ موارد مشتركة عبر التدفقات من نفس الفئة. +>>>>>>> 82edf2d (New md files from RunPod) +مثال: `standard-rag`، `enterprise-rag` + +### متغيرات المعلمات + +#### {parameter-name} +معلمات مخصصة يتم تعريفها في وقت بدء التدفق. +تتطابق أسماء المعلمات مع المفاتيح الموجودة في قسم `parameters` الخاص بالتدفق. +تُستخدم في إعدادات المعالج لتخصيص السلوك. +أمثلة: `{model}`، `{temp}`، `{chunk}` +يتم استبدالها بالقيم المقدمة عند بدء التدفق. +يتم التحقق من صحتها مقابل تعريفات المعلمات المخزنة مركزيًا. + +## إعدادات المعالج + +توفر الإعدادات قيم التكوين للمعالجات في وقت الإنشاء. يمكن أن تكون: + +### إعدادات ثابتة +قيم مباشرة لا تتغير: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### الإعدادات ذات المعلمات +القيم التي تستخدم معلمات يتم توفيرها عند بدء تشغيل التدفق: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +تتوافق أسماء المعلمات في الإعدادات مع المفاتيح في قسم `parameters` الخاص بالتدفق. + +### أمثلة للإعدادات + +**معالج نماذج اللغة الكبيرة مع المعلمات:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**تقسيم النص بإعدادات ثابتة ومعلمات:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +<<<<<<< HEAD +## أنماط قائمة الانتظار (بالمسر) + +تستخدم مخططات التدفق Apache Pulsar للرسائل. تتبع أسماء قوائم الانتظار تنسيق بالمسر: +======= +## أنماط قائمة الانتظار (بالمار) + +تستخدم مخططات التدفق Apache Pulsar للرسائل. تتبع أسماء قوائم الانتظار تنسيق بالمار: +>>>>>>> 82edf2d (New md files from RunPod) +``` +://// +``` + +### المكونات: +**الاستمرارية**: `persistent` أو `non-persistent` (وضع استمرارية Pulsar) +**المستأجر**: `tg` لتعريفات مخطط التدفق المقدمة من TrustGraph +**مساحة الاسم**: تشير إلى نمط الرسائل + `flow`: خدمات الإرسال والاستقبال + `request`: الجزء الطلب من خدمات الطلب/الاستجابة + `response`: الجزء الاستجابة من خدمات الطلب/الاستجابة +**الموضوع**: اسم قائمة الانتظار/الموضوع المحدد مع متغيرات القالب + +### قوائم الانتظار الدائمة +النمط: `persistent://tg/flow/:{id}` +تستخدم لخدمات الإرسال والاستقبال وتدفق البيانات المتينة +تظل البيانات في تخزين Pulsar عبر عمليات إعادة التشغيل +مثال: `persistent://tg/flow/chunk-load:{id}` + +### قوائم الانتظار غير الدائمة +النمط: `non-persistent://tg/request/:{class}` أو `non-persistent://tg/response/:{class}` +تستخدم لأنماط الرسائل الطلب/الاستجابة +مؤقتة، ولا يتم حفظها على القرص بواسطة Pulsar +زمن انتقال أقل، ومناسبة للاتصالات على غرار RPC +مثال: `non-persistent://tg/request/embeddings:{class}` + +## بنية تدفق البيانات + +ينشئ مخطط التدفق تدفق بيانات موحد حيث: + +1. **مسار معالجة المستندات**: يبدأ من الاستيعاب ويمر بالتحويل إلى التخزين +2. **خدمات الاستعلام**: معالجات مدمجة تستعلم عن نفس مخازن البيانات والخدمات +3. **الخدمات المشتركة**: معالجات مركزية يمكن لجميع التدفقات استخدامها +4. **كتابة التخزين**: تحفظ البيانات المعالجة في المخازن المناسبة + +<<<<<<< HEAD +تعمل جميع المعالجات (سواء `{id}` و `{class}`) معًا كرسوم بيانية لتدفق بيانات متماسك، وليس كأنظمة منفصلة. +======= +تعمل جميع المعالجات (سواء `{id}` و `{class}`) معًا كرسوم بيانية لتدفق البيانات المتكاملة، وليس كأنظمة منفصلة. +>>>>>>> 82edf2d (New md files from RunPod) + +## مثال على إنشاء التدفق + +المعطيات: +معرف مثيل التدفق: `customer-A-flow` +مخطط التدفق: `standard-rag` +تعيينات معلمات التدفق: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +المعلمات المقدمة من المستخدم: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +<<<<<<< HEAD +التوسعات القالبية: +======= +توسعات القالب: +>>>>>>> 82edf2d (New md files from RunPod) +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +هذا ينشئ: +مسار معالجة مستندات معزول لـ `customer-A-flow` +خدمة تضمين مشتركة لجميع تدفقات `standard-rag` +تدفق بيانات كامل من استيعاب المستندات إلى الاستعلام +المعالجات مُكوَّنة بقيم المعلمات المقدمة + +## المزايا + +1. **كفاءة الموارد**: يتم مشاركة الخدمات المكلفة عبر التدفقات +2. **عزل التدفق**: يحتوي كل تدفق على مسار معالجة بيانات خاص به +3. **قابلية التوسع**: يمكن إنشاء مثيلات متعددة من نفس القالب +4. **النمطية**: فصل واضح بين المكونات المشتركة والمكونات الخاصة بالتدفق +5. **بنية موحدة**: الاستعلام والمعالجة جزء من تدفق البيانات نفسه diff --git a/docs/tech-specs/flow-class-definition.es.md b/docs/tech-specs/flow-class-definition.es.md new file mode 100644 index 00000000..5132ded1 --- /dev/null +++ b/docs/tech-specs/flow-class-definition.es.md @@ -0,0 +1,304 @@ +--- +layout: default +title: "Especificación de la Definición del Esquema de Flujo" +parent: "Spanish (Beta)" +--- + +<<<<<<< HEAD +# Especificación de la Definición del Esquema de Flujo + +> **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 + +Un esquema de flujo define una plantilla de patrón de flujo de datos completo en el sistema TrustGraph. Cuando se instancia, crea una red interconectada de procesadores que manejan la ingesta de datos, el procesamiento, el almacenamiento y la consulta como un sistema unificado. + +## Estructura + +Una definición de esquema de flujo consta de cinco secciones principales: + +### 1. Sección de Clase +Define procesadores de servicios compartidos que se instancian una vez por esquema de flujo. Estos procesadores manejan las solicitudes de todas las instancias de flujo de esta clase. +======= +# Especificación de la Definición de la Hoja de Flujo + +## Resumen + +Una hoja de flujo define una plantilla de patrón de flujo de datos completo en el sistema TrustGraph. Cuando se instancia, crea una red interconectada de procesadores que manejan la ingesta de datos, el procesamiento, el almacenamiento y la consulta como un sistema unificado. + +## Estructura + +Una definición de hoja de flujo consta de cinco secciones principales: + +### 1. Sección de Clase +Define procesadores de servicios compartidos que se instancian una vez por hoja de flujo. Estos procesadores manejan las solicitudes de todas las instancias de flujo de esta clase. +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Características:** +Compartidas entre todas las instancias de flujo de la misma clase. +Típicamente servicios costosos o sin estado (modelos de lenguaje grandes, modelos de embedding). +Utilice la variable de plantilla `{class}` para el nombre de la cola. +Los ajustes pueden ser valores fijos o parametrizados con la sintaxis `{parameter-name}`. +Ejemplos: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}`. + +### 2. Sección de Flujo +Define los procesadores específicos del flujo que se instancian para cada instancia de flujo individual. Cada flujo obtiene su propio conjunto aislado de estos procesadores. + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Características:** +Instancia única por flujo +Maneja datos y estado específicos del flujo +Utilice la variable de plantilla `{id}` para el nombre de la cola +Los ajustes pueden ser valores fijos o parametrizados con la sintaxis `{parameter-name}` +Ejemplos: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. Sección de Interfaces +Define los puntos de entrada y los contratos de interacción para el flujo. Estos forman la superficie de la API para sistemas externos y comunicación entre componentes internos. + +Las interfaces pueden adoptar dos formas: + +**Patrón de "Enviar y Olvidar"** (cola única): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**Patrón de solicitud/respuesta** (objeto con campos de solicitud/respuesta): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**Tipos de Interfaces:** +**Puntos de Entrada**: Lugares donde los sistemas externos inyectan datos (`document-load`, `agent`) +**Interfaces de Servicio**: Patrones de solicitud/respuesta para servicios (`embeddings`, `text-completion`) +**Interfaces de Datos**: Puntos de conexión de flujo de datos "dispara y olvida" (`triples-store`, `entity-contexts-load`) + +### 4. Sección de Parámetros +Mapea los nombres de parámetros específicos del flujo a definiciones de parámetros almacenadas centralmente: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**Características:** +Las claves son nombres de parámetros utilizados en la configuración del procesador (por ejemplo, `{model}`) +Los valores hacen referencia a definiciones de parámetros almacenadas en schema/config +Permite la reutilización de definiciones de parámetros comunes en diferentes flujos +Reduce la duplicación de esquemas de parámetros + +### 5. Metadatos +Información adicional sobre el plano del flujo: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## Variables de Plantilla + +### Variables del Sistema + +#### {id} +Reemplazado con el identificador único de la instancia del flujo. +Crea recursos aislados para cada flujo. +Ejemplo: `flow-123`, `customer-A-flow` + +#### {class} +Reemplazado con el nombre de la plantilla del flujo. +Crea recursos compartidos entre flujos de la misma clase. +Ejemplo: `standard-rag`, `enterprise-rag` + +### Variables de Parámetro + +#### {parameter-name} +Parámetros personalizados definidos en el momento de la ejecución del flujo. +Los nombres de los parámetros coinciden con las claves en la sección `parameters` del flujo. +Se utilizan en la configuración de los procesadores para personalizar el comportamiento. +Ejemplos: `{model}`, `{temp}`, `{chunk}` +Reemplazado con los valores proporcionados al iniciar el flujo. +Validados contra definiciones de parámetros almacenadas centralmente. + +## Configuración de Procesadores + +La configuración proporciona valores de configuración a los procesadores en el momento de la creación. Pueden ser: + +### Configuración Fija +Valores directos que no cambian: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### Configuración parametrizada +Valores que utilizan parámetros proporcionados al iniciar el flujo: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +Los nombres de los parámetros en la configuración corresponden a las claves en la sección `parameters` del flujo. + +### Ejemplos de configuración + +**Procesador LLM con parámetros:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**Chunker con Configuraciones Fijas y Parametrizadas:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## Patrones de Colas (Pulsar) + +Los planos de flujo utilizan Apache Pulsar para el envío de mensajes. Los nombres de las colas siguen el formato de Pulsar: +``` +://// +``` + +### Componentes: +**persistencia**: `persistent` or `non-persistent` (Modo de persistencia de Pulsar) +**inquilino**: `tg` para definiciones de planos de flujo proporcionados por TrustGraph +**espacio de nombres**: Indica el patrón de mensajería + `flow`: Servicios de envío y olvido + `request`: Parte de solicitud de servicios de solicitud/respuesta + `response`: Parte de respuesta de servicios de solicitud/respuesta +**tema**: El nombre específico de la cola/tema con variables de plantilla + +### Colas Persistentes +Patrón: `persistent://tg/flow/:{id}` +Utilizado para servicios de envío y olvido y flujo de datos duradero +Los datos persisten en el almacenamiento de Pulsar a través de reinicios +Ejemplo: `persistent://tg/flow/chunk-load:{id}` + +### Colas No Persistentes +Patrón: `non-persistent://tg/request/:{class}` or `non-persistent://tg/response/:{class}` +Utilizado para patrones de mensajería de solicitud/respuesta +Efímero, no se persiste en disco por Pulsar +Menor latencia, adecuado para comunicación estilo RPC +Ejemplo: `non-persistent://tg/request/embeddings:{class}` + +## Arquitectura del Flujo de Datos + +El plano de flujo crea un flujo de datos unificado donde: + +1. **Pipeline de Procesamiento de Documentos**: Fluye desde la ingesta hasta la transformación y el almacenamiento +<<<<<<< HEAD +2. **Servicios de Consulta**: Procesadores integrados que consultan las mismas bases de datos y servicios +======= +2. **Servicios de Consulta**: Procesadores integrados que consultan las mismas fuentes de datos y servicios +>>>>>>> 82edf2d (New md files from RunPod) +3. **Servicios Compartidos**: Procesadores centralizados que todos los flujos pueden utilizar +4. **Escritores de Almacenamiento**: Persisten los datos procesados en los almacenes apropiados + +Todos los procesadores (tanto `{id}` como `{class}`) trabajan juntos como un gráfico de flujo de datos cohesivo, no como sistemas separados. + +## Ejemplo de Instanciación de Flujo + +Dado: +ID de instancia de flujo: `customer-A-flow` +Plano de flujo: `standard-rag` +Mapeos de parámetros de flujo: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +Parámetros proporcionados por el usuario: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +Expansiones de plantilla: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +Esto crea: +Pipeline de procesamiento de documentos aislado para `customer-A-flow` +Servicio de incrustación compartido para todos los flujos `standard-rag` +Flujo de datos completo desde la ingesta de documentos hasta la consulta +Procesadores configurados con los valores de parámetro proporcionados + +## Beneficios + +1. **Eficiencia de Recursos**: Los servicios costosos se comparten entre los flujos +2. **Aislamiento de Flujos**: Cada flujo tiene su propio pipeline de procesamiento de datos +3. **Escalabilidad**: Se pueden instanciar múltiples flujos desde la misma plantilla +4. **Modularidad**: Clara separación entre componentes compartidos y específicos del flujo +5. **Arquitectura Unificada**: La consulta y el procesamiento son parte del mismo flujo de datos diff --git a/docs/tech-specs/flow-class-definition.he.md b/docs/tech-specs/flow-class-definition.he.md new file mode 100644 index 00000000..44d33ffe --- /dev/null +++ b/docs/tech-specs/flow-class-definition.he.md @@ -0,0 +1,328 @@ +--- +layout: default +title: "הגדרת מפרט תוכנית זרימה" +parent: "Hebrew (Beta)" +--- + +<<<<<<< HEAD +# הגדרת מפרט תוכנית זרימה + +> **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. +======= +# מפרט הגדרת תוכנית זרימה +>>>>>>> 82edf2d (New md files from RunPod) + +## סקירה כללית + +תוכנית זרימה מגדירה תבנית מלאה של דפוסי זרימת נתונים במערכת TrustGraph. כאשר היא מופעלת, היא יוצרת רשת מקושרת של מעבדים המטפלים בקליטת נתונים, עיבוד, אחסון ושליפה כחלק ממערכת מאוחדת. + +## מבנה + +הגדרת תוכנית זרימה מורכבת מחמש קטעים עיקריים: + +### 1. קטע מחלקה +<<<<<<< HEAD +מגדיר מעבדי שירות משותפים המופעלים פעם אחת לכל תוכנית זרימה. מעבדים אלה מטפלים בבקשות מכל מופעי הזרימה של מחלקה זו. +======= +מגדיר מעבדים משותפים המופעלים פעם אחת לכל תוכנית זרימה. מעבדים אלה מטפלים בבקשות מכל מופעי הזרימה של מחלקה זו. +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**מאפיינים:** +משותפים לכל מופעי זרימה מאותו סוג. +בדרך כלל שירותים יקרים או חסרי מצב (מודלים של שפה גדולים, מודלים להטמעה). +השתמשו במשתנה תבנית `{class}` עבור שמות תורים. +הגדרות יכולות להיות ערכים קבועים או פרמטריות באמצעות תחביר `{parameter-name}`. +דוגמאות: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}` + +### 2. סעיף זרימה +<<<<<<< HEAD +מגדיר מעבדים ספציפיים לזרימה, אשר מופעלים עבור כל מופע זרימה בודד. לכל זרימה יש סט נפרד משלה של מעבדים אלה. +======= +מגדיר מעבדים ספציפיים לזרימה אשר מופעלים עבור כל מופע זרימה בודד. לכל זרימה יש סט נפרד משלה של מעבדים אלה. +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**מאפיינים:** +מופע ייחודי לכל זרימה +טיפול בנתונים ובמצב ספציפיים לזרימה +שימוש במשתנה תבנית `{id}` עבור שמות תורים +הגדרות יכולות להיות ערכים קבועים או פרמטריות באמצעות תחביר `{parameter-name}` +דוגמאות: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. סעיף ממשקים +מגדיר את נקודות הכניסה ואת חוזי האינטראקציה עבור הזרימה. אלה מהווים את ממשק ה-API עבור מערכות חיצוניות ותקשורת בין רכיבים פנימיים. + +ממשקים יכולים לקבל שתי צורות: + +<<<<<<< HEAD +**תבנית "שלח ושכח"** (תור יחיד): +======= +**תבנית "שלח והשכח"** (תור יחיד): +>>>>>>> 82edf2d (New md files from RunPod) +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**תבנית בקשה/תגובה** (אובייקט עם שדות בקשה/תגובה): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**סוגי ממשקים:** +<<<<<<< HEAD +**נקודות כניסה:** נקודות שבהן מערכות חיצוניות מזריקות נתונים (`document-load`, `agent`) +**ממשקי שירות:** תבניות בקשה/תגובה עבור שירותים (`embeddings`, `text-completion`) +**ממשקי נתונים:** נקודות חיבור לזרימת נתונים מסוג "שלח וסגור" (`triples-store`, `entity-contexts-load`) +======= +**נקודות כניסה:** נקודות בהן מערכות חיצוניות מזריקות נתונים (`document-load`, `agent`) +**ממשקי שירות:** תבניות בקשה/תגובה עבור שירותים (`embeddings`, `text-completion`) +**ממשקי נתונים:** נקודות חיבור לזרימת נתונים מסוג "שלח ושים" (`triples-store`, `entity-contexts-load`) +>>>>>>> 82edf2d (New md files from RunPod) + +### 4. סעיף פרמטרים +ממפה שמות פרמטרים ספציפיים לזרימה להגדרות פרמטרים המאוחסנות באופן מרכזי: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**מאפיינים:** +המפתחות הם שמות הפרמטרים המשמשים בהגדרות המעבד (לדוגמה, `{model}`) +הערכים מפנים להגדרות הפרמטרים המאוחסנות ב-schema/config +מאפשר שימוש חוזר בהגדרות פרמטרים נפוצות בין זרימות +מפחית כפילויות של סכימות פרמטרים + +### 5. מטא-נתונים +מידע נוסף על תוכנית הזרימה: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## משתנים בתבנית + +### משתנים של המערכת + +#### {id} +מוחלף במזהה הייחודי של מופע ה-flow +יוצר משאבים מבודדים עבור כל flow +דוגמה: `flow-123`, `customer-A-flow` + +#### {class} +מוחלף בשם התבנית של ה-flow +יוצר משאבים משותפים בין flows של אותה תבנית +דוגמה: `standard-rag`, `enterprise-rag` + +### משתנים של פרמטרים + +#### {parameter-name} +פרמטרים מותאמים אישית המוגדרים בזמן הפעלת ה-flow +שמות הפרמטרים תואמים למפתחות במקטע `parameters` של ה-flow +משמש בהגדרות של מעבדים כדי להתאים אישית את ההתנהגות +דוגמאות: `{model}`, `{temp}`, `{chunk}` +מוחלף בערכים המסופקים בעת הפעלת ה-flow +<<<<<<< HEAD +מאומתים מול הגדרות פרמטרים המאוחסנות באופן מרכזי +======= +מאומתים מול הגדרות פרמטרים המאוחסנות במרכז +>>>>>>> 82edf2d (New md files from RunPod) + +## הגדרות מעבד + +הגדרות מספקות ערכי תצורה למעבדים בזמן יצירתם. ניתן להגדיר אותן כ: + +### הגדרות קבועות +ערכים ישירים שאינם משתנים: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### הגדרות מותאמות אישית +ערכים המשתמשים בפרמטרים המסופקים בעת הפעלת ה-flow: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +שמות הפרמטרים בהגדרות תואמים למפתחות במקטע `parameters` של ה-flow. + +### דוגמאות להגדרות + +**מעבד LLM עם פרמטרים:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**חלוקה למקטעים עם הגדרות קבועות וניתנות לשינוי:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## תבניות תורים (פולסר) + +תבניות זרימה משתמשות ב-Apache Pulsar עבור העברת הודעות. שמות התורים עוקבים אחר הפורמט של פולסר: +``` +://// +``` + +### רכיבים: +**persistence**: `persistent` או `non-persistent` (מצב אחסון של Pulsar) +**tenant**: `tg` עבור הגדרות תבניות זרימה המסופקות על ידי TrustGraph +**namespace**: מציין את דפוס העברת ההודעות + `flow`: שירותים מסוג "שלח וגע" (fire-and-forget) +<<<<<<< HEAD + `request`: החלק של הבקשה בשירותי בקשה/תגובה (request/response) + `response`: החלק של התגובה בשירותי בקשה/תגובה (request/response) +======= + `request`: החלק של הבקשה בשירותי "בקשה/תגובה" (request/response) + `response`: החלק של התגובה בשירותי "בקשה/תגובה" (request/response) +>>>>>>> 82edf2d (New md files from RunPod) +**topic**: שם התור/נושא הספציפי עם משתני תבנית + +### תורים קבועים (Persistent Queues) +דפוס: `persistent://tg/flow/:{id}` +משמש עבור שירותים מסוג "שלח וגע" וזרימת נתונים עמידה +<<<<<<< HEAD +הנתונים נשמרים באחסון של Pulsar בין הפעלות מחדש +======= +הנתונים נשמרים באחסון של Pulsar גם לאחר אתחולים מחדש +>>>>>>> 82edf2d (New md files from RunPod) +דוגמה: `persistent://tg/flow/chunk-load:{id}` + +### תורים לא קבועים (Non-Persistent Queues) +דפוס: `non-persistent://tg/request/:{class}` או `non-persistent://tg/response/:{class}` +<<<<<<< HEAD +משמש עבור דפוסי העברת הודעות מסוג בקשה/תגובה +======= +משמש עבור דפוסי העברת הודעות מסוג "בקשה/תגובה" +>>>>>>> 82edf2d (New md files from RunPod) +זמני, אינו נשמר בדיסק על ידי Pulsar +השהיה נמוכה יותר, מתאים לתקשורת בסגנון RPC +דוגמה: `non-persistent://tg/request/embeddings:{class}` + +## ארכיטקטורת זרימת נתונים + +תבנית זרימת הנתונים יוצרת זרימה מאוחדת שבה: + +1. **צינור עיבוד מסמכים**: זרימה מאיסוף דרך טרנספורמציה לאחסון +2. **שירותי שאילתות**: מעבדים משולבים השואלים את אותם מאגרי נתונים ושירותים +3. **שירותים משותפים**: מעבדים מרכזיים שכל הזרימות יכולות להשתמש בהם +4. **כותבי אחסון**: שומרים נתונים מעובדים לאחסונים המתאימים + +כל המעבדים (גם `{id}` וגם `{class}`) עובדים יחד כגרף זרימת נתונים מגובש, ולא כמערכות נפרדות. + +## דוגמה להפעלה של זרימה + +בהינתן: +מזהה מופע של זרימה: `customer-A-flow` +תבנית זרימה: `standard-rag` +מיפוי פרמטרים של זרימה: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +פרמטרים שסופקו על ידי המשתמש: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +הרחבות תבניות: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +זה יוצר: +<<<<<<< HEAD +צינור עיבוד מסמכים נפרד עבור `customer-A-flow` +======= +צינור עיבוד מסמכים מבודד עבור `customer-A-flow` +>>>>>>> 82edf2d (New md files from RunPod) +שירות הטמעה משותף עבור כל זרימות `standard-rag` +זרימת נתונים שלמה מאיסוף מסמכים דרך שאילתות +מעבדים מוגדרים עם ערכי הפרמטרים שסופקו + +## יתרונות + +1. **יעילות משאבים**: שירותים יקרים משותפים בין זרימות +2. **בידוד זרימות**: לכל זרימה יש את צינור עיבוד הנתונים שלה +3. **מדרגיות**: ניתן להפעיל מספר זרימות מאותה תבנית +4. **מודולריות**: הפרדה ברורה בין רכיבים משותפים ורכיבים ספציפיים לזרימה +5. **ארכיטקטורה מאוחדת**: שאילתות ועיבוד הם חלק מאותה זרימת נתונים diff --git a/docs/tech-specs/flow-class-definition.hi.md b/docs/tech-specs/flow-class-definition.hi.md new file mode 100644 index 00000000..d54c4772 --- /dev/null +++ b/docs/tech-specs/flow-class-definition.hi.md @@ -0,0 +1,328 @@ +--- +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. क्लास अनुभाग +<<<<<<< HEAD +यह साझा सेवा प्रोसेसर को परिभाषित करता है जिन्हें प्रत्येक फ्लो ब्लूप्रिंट के लिए एक बार इंस्टेंट किया जाता है। ये प्रोसेसर इस क्लास के सभी फ्लो उदाहरणों से अनुरोधों को संभालते हैं। +======= +साझा सेवा प्रोसेसर को परिभाषित करता है जिन्हें प्रत्येक फ्लो ब्लूप्रिंट के लिए एक बार इंस्टेंट किया जाता है। ये प्रोसेसर इस क्लास के सभी फ्लो उदाहरणों से अनुरोधों को संभालते हैं। +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**विशेषताएं:** +समान वर्ग के सभी फ्लो उदाहरणों में साझा किया जाता है। +आमतौर पर महंगी या स्टेटलेस सेवाएं (एलएलएम, एम्बेडिंग मॉडल)। +<<<<<<< HEAD +कतार नामकरण के लिए `{class}` टेम्पलेट वेरिएबल का उपयोग करें। +======= +क्यू नामकरण के लिए `{class}` टेम्पलेट वेरिएबल का उपयोग करें। +>>>>>>> 82edf2d (New md files from RunPod) +सेटिंग्स निश्चित मान हो सकती हैं या `{parameter-name}` सिंटैक्स के साथ पैरामीटराइज़ की जा सकती हैं। +उदाहरण: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}` + +### 2. फ्लो सेक्शन +फ्लो-विशिष्ट प्रोसेसर को परिभाषित करता है जिन्हें प्रत्येक व्यक्तिगत फ्लो उदाहरण के लिए इंस्टेंट किया जाता है। प्रत्येक फ्लो को इन प्रोसेसर का अपना अलग सेट मिलता है। + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**विशेषताएं:** +प्रत्येक प्रवाह के लिए अद्वितीय उदाहरण। +प्रवाह-विशिष्ट डेटा और स्थिति को संभालें। +कतार नामकरण के लिए `{id}` टेम्पलेट चर का उपयोग करें। +सेटिंग्स या तो निश्चित मान हो सकती हैं या `{parameter-name}` सिंटैक्स के साथ पैरामीटराइज़ की जा सकती हैं। +उदाहरण: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. इंटरफेस अनुभाग +<<<<<<< HEAD +यह प्रवाह के लिए प्रवेश बिंदुओं और इंटरैक्शन अनुबंधों को परिभाषित करता है। ये बाहरी प्रणालियों और आंतरिक घटक संचार के लिए एपीआई सतह बनाते हैं। +======= +यह प्रवाह के लिए प्रवेश बिंदु और इंटरैक्शन अनुबंधों को परिभाषित करता है। ये बाहरी प्रणालियों और आंतरिक घटक संचार के लिए एपीआई सतह बनाते हैं। +>>>>>>> 82edf2d (New md files from RunPod) + +इंटरफेस दो रूप ले सकते हैं: + +**फायर-एंड-फॉरगेट पैटर्न** (एक कतार): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**अनुरोध/प्रतिक्रिया पैटर्न** (अनुरोध/प्रतिक्रिया फ़ील्ड वाले ऑब्जेक्ट): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**इंटरफेस के प्रकार:** +**एंट्री पॉइंट:** वे स्थान जहाँ बाहरी सिस्टम डेटा इंजेक्ट करते हैं (`document-load`, `agent`) +**सर्विस इंटरफेस:** सेवाओं के लिए अनुरोध/प्रतिक्रिया पैटर्न (`embeddings`, `text-completion`) +**डेटा इंटरफेस:** फायर-एंड-फॉरगेट डेटा प्रवाह कनेक्शन बिंदु (`triples-store`, `entity-contexts-load`) + +### 4. पैरामीटर अनुभाग +यह प्रवाह-विशिष्ट पैरामीटर नामों को केंद्रीय रूप से संग्रहीत पैरामीटर परिभाषाओं से जोड़ता है: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**विशेषताएं:** +कुंजियाँ प्रोसेसर सेटिंग्स में उपयोग किए जाने वाले पैरामीटर नामों को संदर्भित करती हैं (उदाहरण के लिए, `{model}`) +मान स्कीमा/कॉन्फ़िगरेशन में संग्रहीत पैरामीटर परिभाषाओं को संदर्भित करते हैं। +यह सामान्य पैरामीटर परिभाषाओं को विभिन्न फ्लो में पुन: उपयोग करने की अनुमति देता है। +पैरामीटर स्कीमा की डुप्लिकेसी को कम करता है। + +### 5. मेटाडेटा +फ्लो ब्लूप्रिंट के बारे में अतिरिक्त जानकारी: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## टेम्पलेट वेरिएबल + +### सिस्टम वेरिएबल + +#### {id} +यह अद्वितीय फ्लो इंस्टेंस पहचानकर्ता से प्रतिस्थापित किया जाता है। +यह प्रत्येक फ्लो के लिए अलग-अलग संसाधन बनाता है। +उदाहरण: `flow-123`, `customer-A-flow` + +#### {class} +यह फ्लो ब्लूप्रिंट नाम से प्रतिस्थापित किया जाता है। +यह समान क्लास के फ्लो में साझा संसाधनों का निर्माण करता है। +उदाहरण: `standard-rag`, `enterprise-rag` + +### पैरामीटर वेरिएबल + +#### {पैरामीटर-नाम} +फ्लो लॉन्च करते समय परिभाषित कस्टम पैरामीटर। +पैरामीटर नाम फ्लो के `parameters` अनुभाग में कुंजियों से मेल खाते हैं। +प्रोसेसर सेटिंग्स में व्यवहार को अनुकूलित करने के लिए उपयोग किया जाता है। +उदाहरण: `{model}`, `{temp}`, `{chunk}` +फ्लो लॉन्च करते समय प्रदान किए गए मानों से प्रतिस्थापित किया जाता है। +केंद्रीय रूप से संग्रहीत पैरामीटर परिभाषाओं के विरुद्ध मान्य किया जाता है। + +## प्रोसेसर सेटिंग्स + +सेटिंग्स, इंस्टैंशिएशन के समय प्रोसेसरों को कॉन्फ़िगरेशन मान प्रदान करती हैं। वे निम्न हो सकते हैं: + +### फिक्स्ड सेटिंग्स +सीधे मान जो नहीं बदलते: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### पैरामीटराइज़्ड सेटिंग्स +<<<<<<< HEAD +वे मान जो प्रवाह शुरू करते समय प्रदान किए गए पैरामीटर का उपयोग करते हैं: +======= +वे मान जो फ्लो शुरू करते समय प्रदान किए गए पैरामीटर का उपयोग करते हैं: +>>>>>>> 82edf2d (New md files from RunPod) +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +सेटिंग्स में पैरामीटर नाम, प्रवाह के `parameters` अनुभाग में कुंजियों से मेल खाते हैं। + +### सेटिंग्स के उदाहरण + +**पैरामीटर के साथ एलएलएम प्रोसेसर:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**निश्चित और पैरामीटराइज़्ड सेटिंग्स के साथ चंकर:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## क्यू पैटर्न (पल्सर) + +फ्लो ब्लूप्रिंट्स संदेश भेजने के लिए अपाचे पल्सर का उपयोग करते हैं। क्यू नामों का प्रारूप पल्सर प्रारूप का अनुसरण करता है: +``` +://// +``` + +### घटक: +**स्थायित्व**: `persistent` या `non-persistent` (पल्सर स्थायित्व मोड) +<<<<<<< HEAD +**किरायेदार**: ट्रस्टग्राफ द्वारा प्रदान किए गए प्रवाह ब्लूप्रिंट परिभाषाओं के लिए `tg` +======= +**किरायेदार**: ट्रस्टग्राफ द्वारा प्रदान किए गए फ़्लो ब्लूप्रिंट परिभाषाओं के लिए `tg` +>>>>>>> 82edf2d (New md files from RunPod) +**नामस्थान**: यह संदेश पैटर्न को इंगित करता है + `flow`: फायर-एंड-फॉरगेट सेवाएं + `request`: अनुरोध/प्रतिक्रिया सेवाओं का अनुरोध भाग + `response`: अनुरोध/प्रतिक्रिया सेवाओं का प्रतिक्रिया भाग +**विषय**: टेम्पलेट चर के साथ विशिष्ट कतार/विषय नाम + +### स्थायी कतारें +पैटर्न: `persistent://tg/flow/:{id}` +फायर-एंड-फॉरगेट सेवाओं और टिकाऊ डेटा प्रवाह के लिए उपयोग किया जाता है +डेटा पल्सर स्टोरेज में पुनरारंभों में बना रहता है +उदाहरण: `persistent://tg/flow/chunk-load:{id}` + +### गैर-स्थायी कतारें +पैटर्न: `non-persistent://tg/request/:{class}` या `non-persistent://tg/response/:{class}` +अनुरोध/प्रतिक्रिया संदेश पैटर्न के लिए उपयोग किया जाता है +अस्थिर, पल्सर द्वारा डिस्क पर संग्रहीत नहीं है +कम विलंबता, RPC-शैली संचार के लिए उपयुक्त +उदाहरण: `non-persistent://tg/request/embeddings:{class}` + +## डेटाफ्लो आर्किटेक्चर + +<<<<<<< HEAD +प्रवाह ब्लूप्रिंट एक एकीकृत डेटाफ्लो बनाता है जहां: +======= +फ़्लो ब्लूप्रिंट एक एकीकृत डेटाफ्लो बनाता है जहां: +>>>>>>> 82edf2d (New md files from RunPod) + +1. **दस्तावेज़ प्रसंस्करण पाइपलाइन**: अंतर्ग्रहण से लेकर परिवर्तन और भंडारण तक का प्रवाह +2. **क्वेरी सेवाएं**: एकीकृत प्रोसेसर जो समान डेटा स्टोर और सेवाओं को क्वेरी करते हैं +3. **साझा सेवाएं**: केंद्रीय प्रोसेसर जिनका उपयोग सभी प्रवाह कर सकते हैं +<<<<<<< HEAD +4. **भंडारण लेखक**: संसाधित डेटा को उपयुक्त स्टोर में सहेजें + +सभी प्रोसेसर (दोनों `{id}` और `{class}`) एक सुसंगत डेटाफ्लो ग्राफ के रूप में एक साथ काम करते हैं, अलग-अलग सिस्टम के रूप में नहीं। + +## उदाहरण प्रवाह कार्यान्वयन + +दिया गया: +प्रवाह उदाहरण आईडी: `customer-A-flow` +प्रवाह ब्लूप्रिंट: `standard-rag` +प्रवाह पैरामीटर मैपिंग: +======= +4. **भंडारण लेखक**: संसाधित डेटा को उपयुक्त स्टोर में संग्रहीत करते हैं + +सभी प्रोसेसर (दोनों `{id}` और `{class}`) एक सुसंगत डेटाफ्लो ग्राफ के रूप में एक साथ काम करते हैं, अलग-अलग सिस्टम के रूप में नहीं। + +## उदाहरण फ़्लो इंस्टेंशिएशन + +दिया गया: +फ़्लो इंस्टेंस आईडी: `customer-A-flow` +फ़्लो ब्लूप्रिंट: `standard-rag` +फ़्लो पैरामीटर मैपिंग: +>>>>>>> 82edf2d (New md files from RunPod) + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +उपयोगकर्ता-प्रदत्त पैरामीटर: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +टेम्पलेट विस्तार: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +यह बनाता है: +`customer-A-flow` के लिए अलग दस्तावेज़ प्रसंस्करण पाइपलाइन +सभी `standard-rag` प्रवाह के लिए साझा एम्बेडिंग सेवा +दस्तावेज़ अंतर्ग्रहण से लेकर क्वेरी तक का पूर्ण डेटाफ्लो +प्रोसेसर प्रदान किए गए पैरामीटर मानों के साथ कॉन्फ़िगर किए गए + +## लाभ + +1. **संसाधन दक्षता**: महंगी सेवाओं को प्रवाह में साझा किया जाता है +<<<<<<< HEAD +2. **प्रवाह अलगाव**: प्रत्येक प्रवाह का अपना डेटा प्रसंस्करण पाइपलाइन होता है +3. **मापनीयता**: एक ही टेम्पलेट से कई प्रवाहों को कार्यान्वित किया जा सकता है +4. **मॉड्यूलरिटी**: साझा और प्रवाह-विशिष्ट घटकों के बीच स्पष्ट अलगाव +======= +2. **फ़्लो अलगाव**: प्रत्येक फ़्लो का अपना डेटा प्रसंस्करण पाइपलाइन होता है +3. **मापनीयता**: एक ही टेम्पलेट से कई फ़्लो को इंस्टेंशिएट किया जा सकता है +4. **मॉड्यूलरिटी**: साझा और फ़्लो-विशिष्ट घटकों के बीच स्पष्ट अलगाव +>>>>>>> 82edf2d (New md files from RunPod) +5. **एकीकृत आर्किटेक्चर**: क्वेरी और प्रसंस्करण एक ही डेटाफ्लो का हिस्सा हैं diff --git a/docs/tech-specs/flow-class-definition.md b/docs/tech-specs/flow-class-definition.md index 9e7ed66b..94229b72 100644 --- a/docs/tech-specs/flow-class-definition.md +++ b/docs/tech-specs/flow-class-definition.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Flow Blueprint Definition Specification" +parent: "Tech Specs" +--- + # Flow Blueprint Definition Specification ## Overview @@ -274,4 +280,4 @@ This creates: 2. **Flow Isolation**: Each flow has its own data processing pipeline 3. **Scalability**: Can instantiate multiple flows from the same template 4. **Modularity**: Clear separation between shared and flow-specific components -5. **Unified Architecture**: Query and processing are part of the same dataflow \ No newline at end of file +5. **Unified Architecture**: Query and processing are part of the same dataflow diff --git a/docs/tech-specs/flow-class-definition.pt.md b/docs/tech-specs/flow-class-definition.pt.md new file mode 100644 index 00000000..4d2fc487 --- /dev/null +++ b/docs/tech-specs/flow-class-definition.pt.md @@ -0,0 +1,317 @@ +--- +layout: default +title: "Especificação da Definição do Modelo de Fluxo" +parent: "Portuguese (Beta)" +--- + +# Especificação da Definição do Modelo de Fluxo + +> **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 + +Um modelo de fluxo define um modelo de padrão de fluxo de dados completo no sistema TrustGraph. Quando instanciado, ele cria uma rede interconectada de processadores que lidam com a ingestão, o processamento, o armazenamento e a consulta de dados como um sistema unificado. + +## Estrutura + +Uma definição de modelo de fluxo consiste em cinco seções principais: + +### 1. Seção de Classe +Define processadores de serviço compartilhados que são instanciados uma vez por modelo de fluxo. Esses processadores lidam com solicitações de todas as instâncias de fluxo desta classe. + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Características:** +Compartilhadas entre todas as instâncias de fluxo da mesma classe. +<<<<<<< HEAD +Normalmente, serviços caros ou sem estado (LLMs, modelos de embedding). +======= +Normalmente, serviços com alto custo ou sem estado (LLMs, modelos de embedding). +>>>>>>> 82edf2d (New md files from RunPod) +Use a variável de modelo `{class}` para o nome da fila. +As configurações podem ser valores fixos ou parametrizadas com a sintaxe `{parameter-name}`. +Exemplos: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}`. + +### 2. Seção de Fluxo +Define processadores específicos do fluxo que são instanciados para cada instância de fluxo individual. Cada fluxo recebe seu próprio conjunto isolado desses processadores. + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Características:** +Instância única por fluxo +Gerenciar dados e estado específicos do fluxo +<<<<<<< HEAD +Usar variável de modelo `{id}` para nomeação de filas +As configurações podem ser valores fixos ou parametrizados com a sintaxe `{parameter-name}` +Exemplos: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. Seção de Interfaces +Define os pontos de entrada e os contratos de interação para o fluxo. Estes formam a superfície da API para sistemas externos e comunicação entre componentes internos. +======= +Usar variável de modelo `{id}` para nomeação de fila +As configurações podem ser valores fixos ou parametrizadas com a sintaxe `{parameter-name}` +Exemplos: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. Seção de Interfaces +Define os pontos de entrada e os contratos de interação para o fluxo. Estes formam a superfície da API para sistemas externos e comunicação de componentes internos. +>>>>>>> 82edf2d (New md files from RunPod) + +As interfaces podem assumir duas formas: + +**Padrão Fire-and-Forget** (uma única fila): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**Padrão de Requisição/Resposta** (objeto com campos de requisição/resposta): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**Tipos de Interfaces:** +**Pontos de Entrada**: Onde sistemas externos injetam dados (`document-load`, `agent`) +**Interfaces de Serviço**: Padrões de solicitação/resposta para serviços (`embeddings`, `text-completion`) +**Interfaces de Dados**: Pontos de conexão de fluxo de dados do tipo "enviar e esquecer" (`triples-store`, `entity-contexts-load`) + +### 4. Seção de Parâmetros +Mapeia nomes de parâmetros específicos do fluxo para definições de parâmetros armazenadas centralmente: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**Características:** +As chaves são nomes de parâmetros usados nas configurações do processador (por exemplo, `{model}`) +Os valores referenciam as definições de parâmetros armazenadas em schema/config +Permite a reutilização de definições de parâmetros comuns em diferentes fluxos +Reduz a duplicação de esquemas de parâmetros + +### 5. Metadados +Informações adicionais sobre o blueprint do fluxo: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## Variáveis de Modelo + +### Variáveis do Sistema + +#### {id} +<<<<<<< HEAD +Substituído pelo identificador de instância de fluxo único. +======= +Substituído pelo identificador único da instância do fluxo. +>>>>>>> 82edf2d (New md files from RunPod) +Cria recursos isolados para cada fluxo. +Exemplo: `flow-123`, `customer-A-flow` + +#### {class} +Substituído pelo nome do blueprint do fluxo. +Cria recursos compartilhados entre fluxos da mesma classe. +Exemplo: `standard-rag`, `enterprise-rag` + +### Variáveis de Parâmetro + +#### {parameter-name} +Parâmetros personalizados definidos no momento da execução do fluxo. +Os nomes dos parâmetros correspondem às chaves na seção `parameters` do fluxo. +Usados em configurações do processador para personalizar o comportamento. +Exemplos: `{model}`, `{temp}`, `{chunk}` +Substituído pelos valores fornecidos ao iniciar o fluxo. +Validado em relação às definições de parâmetros armazenadas centralmente. + +## Configurações do Processador + +As configurações fornecem valores de configuração aos processadores no momento da instanciação. Elas podem ser: + +### Configurações Fixas +Valores diretos que não mudam: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### Configurações Parametrizadas +Valores que utilizam parâmetros fornecidos no lançamento do fluxo: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +Os nomes dos parâmetros nas configurações correspondem às chaves na seção `parameters` do fluxo. + +### Exemplos de Configurações + +**Processador LLM com Parâmetros:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**Chunker com Configurações Fixas e Parametrizadas:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## Padrões de Filas (Pulsar) + +Os modelos de fluxo utilizam o Apache Pulsar para mensagens. Os nomes das filas seguem o formato do Pulsar: +``` +://// +``` + +### Componentes: +**persistência**: `persistent` ou `non-persistent` (modo de persistência do Pulsar) +<<<<<<< HEAD +**inquilino**: `tg` para definições de blueprint de fluxo fornecidas pelo TrustGraph +======= +**inquilino**: `tg` para definições de blueprint de fluxo fornecidas pela TrustGraph +>>>>>>> 82edf2d (New md files from RunPod) +**namespace**: Indica o padrão de mensagens + `flow`: Serviços de envio e esquecimento + `request`: Parte de solicitação de serviços de solicitação/resposta + `response`: Parte de resposta de serviços de solicitação/resposta +**tópico**: O nome específico da fila/tópico com variáveis de modelo + +### Filas Persistentes +Padrão: `persistent://tg/flow/:{id}` +Usado para serviços de envio e esquecimento e fluxo de dados durável +Os dados persistem no armazenamento do Pulsar durante as reinicializações +Exemplo: `persistent://tg/flow/chunk-load:{id}` + +### Filas Não Persistentes +Padrão: `non-persistent://tg/request/:{class}` ou `non-persistent://tg/response/:{class}` +Usado para padrões de mensagens de solicitação/resposta +Efêmeras, não persistidas em disco pelo Pulsar +Menor latência, adequado para comunicação no estilo RPC +Exemplo: `non-persistent://tg/request/embeddings:{class}` + +## Arquitetura do Fluxo de Dados + +O blueprint do fluxo cria um fluxo de dados unificado onde: + +<<<<<<< HEAD +1. **Pipeline de Processamento de Documentos**: Fluxo da ingestão ao processamento e armazenamento +2. **Serviços de Consulta**: Processadores integrados que consultam os mesmos armazenamentos de dados e serviços +3. **Serviços Compartilhados**: Processadores centralizados que todos os fluxos podem utilizar +4. **Escritores de Armazenamento**: Persistem os dados processados em armazenamentos apropriados +======= +1. **Pipeline de Processamento de Documentos**: Fluxo da ingestão ao armazenamento, passando pela transformação +2. **Serviços de Consulta**: Processadores integrados que consultam os mesmos armazenamentos de dados e serviços +3. **Serviços Compartilhados**: Processadores centralizados que todos os fluxos podem utilizar +4. **Escritores de Armazenamento**: Persistem os dados processados nos armazenamentos apropriados +>>>>>>> 82edf2d (New md files from RunPod) + +Todos os processadores (tanto `{id}` quanto `{class}`) trabalham juntos como um grafo de fluxo de dados coeso, e não como sistemas separados. + +## Exemplo de Instanciação de Fluxo + +Dado: +ID da Instância do Fluxo: `customer-A-flow` +Blueprint do Fluxo: `standard-rag` +Mapeamentos de parâmetros do fluxo: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +Parâmetros fornecidos pelo usuário: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +Expansões de modelo: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +Isso cria: +Pipeline de processamento de documentos isolado para `customer-A-flow` +Serviço de incorporação compartilhado para todos os fluxos `standard-rag` +<<<<<<< HEAD +Fluxo de dados completo da ingestão de documentos à consulta +======= +Fluxo de dados completo da ingestão do documento à consulta +>>>>>>> 82edf2d (New md files from RunPod) +Processadores configurados com os valores de parâmetro fornecidos + +## Benefícios + +1. **Eficiência de Recursos**: Serviços caros são compartilhados entre os fluxos +2. **Isolamento de Fluxo**: Cada fluxo tem seu próprio pipeline de processamento de dados +3. **Escalabilidade**: É possível instanciar vários fluxos do mesmo modelo +4. **Modularidade**: Separação clara entre componentes compartilhados e específicos do fluxo +5. **Arquitetura Unificada**: Consulta e processamento fazem parte do mesmo fluxo de dados diff --git a/docs/tech-specs/flow-class-definition.ru.md b/docs/tech-specs/flow-class-definition.ru.md new file mode 100644 index 00000000..822e97ee --- /dev/null +++ b/docs/tech-specs/flow-class-definition.ru.md @@ -0,0 +1,313 @@ +--- +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. Раздел классов +Определяет общие сервисные процессоры, которые инстанцируются один раз для каждого шаблона потока. Эти процессоры обрабатывают запросы от всех экземпляров потока этого класса. + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Характеристики:** +<<<<<<< HEAD +Общие для всех экземпляров потока одного класса. +Обычно это дорогие или безсостояниевые сервисы (LLM, модели эмбеддингов). +Используйте переменную шаблона `{class}` для именования очереди. +Настройки могут быть фиксированными значениями или параметризованы с использованием синтаксиса `{parameter-name}`. +======= +Распространяются на все экземпляры потока одного и того же класса. +Обычно это дорогие или не имеющие состояния сервисы (LLM, модели эмбеддингов). +Используйте переменную шаблона `{class}` для именования очереди. +Параметры могут быть фиксированными значениями или параметризованы с использованием синтаксиса `{parameter-name}`. +>>>>>>> 82edf2d (New md files from RunPod) +Примеры: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}`. + +### 2. Раздел потока +Определяет процессоры, специфичные для потока, которые создаются для каждого отдельного экземпляра потока. Каждый поток получает свой собственный изолированный набор этих процессоров. + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Характеристики:** +Уникальный экземпляр для каждого потока. +Обработка данных и состояния, специфичных для потока. +Использование переменной шаблона `{id}` для именования очереди. +Настройки могут быть фиксированными значениями или параметризованы с использованием синтаксиса `{parameter-name}`. +Примеры: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}`. + +### Раздел "Интерфейсы" +Определяет точки входа и контракты взаимодействия для потока. Они формируют API для внешних систем и взаимодействия между внутренними компонентами. + +Интерфейсы могут иметь две формы: + +**Модель "Отправь и забудь"** (одна очередь): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**Шаблон "Запрос/Ответ"** (объект с полями запроса/ответа): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**Типы интерфейсов:** +**Точки входа:** Места, куда внешние системы вводят данные (`document-load`, `agent`) +**Интерфейсы сервисов:** Схемы запросов/ответов для сервисов (`embeddings`, `text-completion`) +**Интерфейсы данных:** Точки подключения для потоковой передачи данных (`triples-store`, `entity-contexts-load`) + +### 4. Раздел параметров +Отображает имена параметров, специфичные для потока, на централизованно хранящиеся определения параметров: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**Характеристики:** +Ключи являются именами параметров, используемыми в настройках процессора (например, `{model}`) +Значения ссылаются на определения параметров, хранящиеся в schema/config +<<<<<<< HEAD +Обеспечивает повторное использование общих определений параметров в различных потоках. +======= +Позволяет повторно использовать общие определения параметров в различных потоках. +>>>>>>> 82edf2d (New md files from RunPod) +Уменьшает дублирование схем параметров. + +### 5. Метаданные +Дополнительная информация о шаблоне потока: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## Переменные шаблона + +### Системные переменные + +#### {id} +Заменяется уникальным идентификатором экземпляра потока. +Создает изолированные ресурсы для каждого потока. +Пример: `flow-123`, `customer-A-flow` + +#### {class} +Заменяется именем шаблона потока. +Создает общие ресурсы для потоков одного и того же класса. +Пример: `standard-rag`, `enterprise-rag` + +### Переменные параметров + +#### {parameter-name} +Пользовательские параметры, определенные во время запуска потока. +Имена параметров соответствуют ключам в разделе `parameters` потока. +Используются в настройках процессоров для настройки поведения. +Примеры: `{model}`, `{temp}`, `{chunk}` +Заменяются значениями, предоставленными при запуске потока. +Проверяются на соответствие централизованным определениям параметров. + +## Настройки процессоров + +Настройки предоставляют значения конфигурации процессорам во время их создания. Они могут быть: + +### Фиксированные настройки +Прямые значения, которые не изменяются: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### Параметрические настройки +Значения, использующие параметры, предоставленные при запуске потока: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +Имена параметров в настройках соответствуют ключам в разделе `parameters` потока. + +### Примеры настроек + +**Обработчик LLM с параметрами:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**Разбиение на части с фиксированными и параметризованными настройками:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## Паттерны очередей (Pulsar) + +Схемы потоков используют Apache Pulsar для обмена сообщениями. Имена очередей соответствуют формату Pulsar: +``` +://// +``` + +### Компоненты: +**постоянство**: `persistent` или `non-persistent` (режим постоянства Pulsar) +**арендатор**: `tg` для определений шаблонов потоков, предоставляемых TrustGraph +**пространство имен**: Указывает шаблон обмена сообщениями + `flow`: Сервисы "отправь и забудь" +<<<<<<< HEAD + `request`: Запрос в сервисах "запрос/ответ" + `response`: Ответ в сервисах "запрос/ответ" +======= + `request`: Запрос в сервисах "запрос-ответ" + `response`: Ответ в сервисах "запрос-ответ" +>>>>>>> 82edf2d (New md files from RunPod) +**тема**: Конкретное имя очереди/темы с переменными шаблона + +### Постоянные очереди +Шаблон: `persistent://tg/flow/:{id}` +Используется для сервисов "отправь и забудь" и потоков данных с гарантированной доставкой +<<<<<<< HEAD +Данные сохраняются в хранилище Pulsar после перезагрузок +======= +Данные сохраняются в хранилище Pulsar при перезапусках +>>>>>>> 82edf2d (New md files from RunPod) +Пример: `persistent://tg/flow/chunk-load:{id}` + +### Непостоянные очереди +Шаблон: `non-persistent://tg/request/:{class}` или `non-persistent://tg/response/:{class}` +<<<<<<< HEAD +Используется для шаблонов обмена сообщениями "запрос/ответ" +======= +Используется для шаблонов обмена сообщениями "запрос-ответ" +>>>>>>> 82edf2d (New md files from RunPod) +Непостоянные, не сохраняются на диск Pulsar +Меньшая задержка, подходит для коммуникации в стиле RPC +Пример: `non-persistent://tg/request/embeddings:{class}` + +## Архитектура потока данных + +Шаблон потока данных создает унифицированный поток, где: + +1. **Конвейер обработки документов**: Поток от получения данных до преобразования и хранения +2. **Сервисы запросов**: Интегрированные процессоры, которые запрашивают одни и те же хранилища данных и сервисы +3. **Общие сервисы**: Централизованные процессоры, которые могут использоваться всеми потоками +4. **Модули записи данных**: Сохраняют обработанные данные в соответствующие хранилища + +Все процессоры (как `{id}`, так и `{class}`) работают вместе как единый граф потока данных, а не как отдельные системы. + +<<<<<<< HEAD +## Пример инстанцирования потока +======= +## Пример инстанциирования потока +>>>>>>> 82edf2d (New md files from RunPod) + +Дано: +Идентификатор экземпляра потока: `customer-A-flow` +Шаблон потока: `standard-rag` +Отображения параметров потока: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +Параметры, предоставленные пользователем: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +Расширение шаблонов: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +Это создает: +Изолированный конвейер обработки документов для `customer-A-flow` +Общий сервис внедрения для всех потоков `standard-rag` +Полный поток данных от получения документов до запросов +Процессоры, настроенные с предоставленными значениями параметров + +## Преимущества + +1. **Эффективность использования ресурсов**: Дорогие сервисы используются совместно несколькими потоками +2. **Изоляция потоков**: Каждый поток имеет свой собственный конвейер обработки данных +3. **Масштабируемость**: Можно создавать несколько экземпляров потоков из одного шаблона +4. **Модульность**: Четкое разделение между общими и специфичными для потока компонентами +5. **Унифицированная архитектура**: Запросы и обработка являются частью одного потока данных diff --git a/docs/tech-specs/flow-class-definition.sw.md b/docs/tech-specs/flow-class-definition.sw.md new file mode 100644 index 00000000..8d63f6ae --- /dev/null +++ b/docs/tech-specs/flow-class-definition.sw.md @@ -0,0 +1,399 @@ +--- +layout: default +title: "Maelezo ya Ufafanuzi wa Mfumo wa Mtiririko" +parent: "Swahili (Beta)" +--- + +# Maelezo ya Ufafanuzi wa Mfumo wa Mtiririko + +> **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 + +<<<<<<< HEAD +Mfumo wa mtiririko unafafanua kiolezo kamili cha mtiririko wa data katika mfumo wa TrustGraph. Unapoongezwa, huunda mtandao unaounganishwa wa vichakata ambavyo hushughulikia uingizaji wa data, uchakataji, uhifadhi, na kuulizia kama mfumo mmoja. +======= +Mfumo wa mtiririko unafafanua mfumo kamili wa mtiririko wa data katika mfumo wa TrustGraph. Unapoongezwa, huunda mtandao unaounganishwa wa vichakata ambavyo hushughulikia uingizaji wa data, uchakataji, uhifadhi, na kuulizia kama mfumo mmoja. +>>>>>>> 82edf2d (New md files from RunPod) + +## Muundo + +Ufafanuzi wa mfumo wa mtiririko una sehemu tano kuu: + +### 1. Sehemu ya Darasa +<<<<<<< HEAD +Inafafanua vichakata vya huduma ambavyo huanzishwa mara moja kwa kila mfumo wa mtiririko. Vichakata hivi hushughulikia ombi kutoka kwa visasisho vyote vya mfumo wa mtiririko vya darasa hili. +======= +Inafafanua vichakata vya huduma ambavyo huanzishwa mara moja kwa kila mfumo wa mtiririko. Vichakata hivi hushughulikia ombi kutoka kwa visasisho vyote vya mfumo wa mtiririko wa darasa hili. +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Sifa:** +Zinashirikiwa katika visasisho vyote vya aina moja. +Hutoa huduma za kawaida au zisizo na hali (LLMs, modeli za uingizaji). +<<<<<<< HEAD +Tumia jina la kigezo cha `{class}` kwa ajili ya kujina kwa folyo. +======= +Tumia jina la kigezo `{class}` kwa ajili ya kujina kwa folyo. +>>>>>>> 82edf2d (New md files from RunPod) +Mipangilio inaweza kuwa maadili thabiti au kupangwa kwa kutumia sintaksia ya `{parameter-name}`. +Mifano: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}` + +### 2. Sehemu ya Folyo +Inafafanua vichakataji maalum ya folyo ambavyo huanzishwa kwa kila visa maalum la folyo. Kila folyo hupata seti yake mwenyewe ya vichakataji hivi. + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Sifa:** +Mfano pekee kwa kila mtiririko. +Hushughulikia data na hali maalum ya mtiririko. +Tumia kigezo cha `{id}` kwa ajili ya kujina kwa folyo. +Mipangilio inaweza kuwa maadili thabiti au kupangishwa kwa kutumia sintaksia ya `{parameter-name}`. +Mifano: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}`. + +<<<<<<< HEAD +### 3. Sehemu ya Vifaa +Inaelezea pointi za kuingilia na mikataba ya mwingiliano kwa mtiririko. Haya huunda safu ya API kwa mifumo ya nje na mawasiliano ya vipengele vya ndani. + +Vifaa vinaweza kuwa na aina mbili: +======= +### Sura ya 3. Sehemu ya Vifaa vya Kuunganisha +Inaelezea pointi za kuingilia na mikataba ya kuingiliana kwa mtiririko. Hizi huunda safu ya API kwa mifumo ya nje na mawasiliano ya vipengele vya ndani. + +Vifaa vya kuunganisha vinaweza kuwa na aina mbili: +>>>>>>> 82edf2d (New md files from RunPod) + +**Mfumo wa "Tuma na Usahau"** (folyo moja): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +<<<<<<< HEAD +**Muundo wa Ombi/Jibu** (kitu chenye sehemu za ombi/jibu): +======= +**Muundo wa Ombi/Jibu** (objekti yenye sehemu za ombi/jibu): +>>>>>>> 82edf2d (New md files from RunPod) +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +<<<<<<< HEAD +**Aina za Mfumo:** +**Vituo vya Kuingia**: Maeneo ambapo mifumo ya nje huingiza data (`document-load`, `agent`) +**Mifumo ya Huduma**: Mfumo wa ombi/jibu kwa huduma (`embeddings`, `text-completion`) +**Mifumo ya Data**: Vituo vya muunganisho wa mtiririko wa data (`triples-store`, `entity-contexts-load`) + +### 4. Sehemu ya Vigezo +Huunganisha majina ya vigezo maalum ya mtiririko na ufafanuzi wa vigezo unaohifadhiwa katika eneo moja: +======= +**Aina za Vifaa vya Kuunganisha:** +**Vifaa vya Kuanzia:** Maeneo ambapo mifumo ya nje huingiza data (`document-load`, `agent`) +**Vifaa vya Huduma:** Mfumo wa ombi/jibu kwa huduma (`embeddings`, `text-completion`) +**Vifaa vya Data:** Vifaa vya kuunganisha mtiririko wa data (`triples-store`, `entity-contexts-load`) + +### 4. Sehemu ya Vigezo +Huunganisha majina ya vigezo maalum ya mtiririko na ufafanuzi wa vigezo unaohifadhiwa katika eneo la kati: +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**Sifa:** +<<<<<<< HEAD +Nenosiri ni majina ya vigezo yanayotumika katika mipangilio ya kichakata (k.m., `{model}`) +======= +Funguo ni majina ya vigezo yanayotumika katika mipangilio ya kichakata (k.m., `{model}`) +>>>>>>> 82edf2d (New md files from RunPod) +Maelezo yanaashiria ufafanuzi wa vigezo uliohifadhiwa katika schema/config +Inaruhusu matumizi ya mara kwa mara ya ufafanuzi wa kawaida wa vigezo katika michakato. +Hupunguza marudio ya schemas za vigezo. + +### 5. Meta Data +<<<<<<< HEAD +Taarifa za ziada kuhusu mpango wa mtiririko: +======= +Habari ya ziada kuhusu mpango wa mtiririko: +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## Vigezo vya Kiolele + +### Vigezo vya Mfumo + +#### {id} +<<<<<<< HEAD +Huibwa na kitambulisho kipekee cha kila mfumo. +Huunda rasilimali zilizotengwa kwa kila mfumo. +Mifano: `flow-123`, `customer-A-flow` + +#### {class} +Huibwa na jina la mpango wa mfumo. +Huunda rasilimali zilizoshirikiwa katika mifumo ya aina moja. +Mifano: `standard-rag`, `enterprise-rag` +======= +Huibadilishwa na kitambulisho kipekee cha kila mtiririko. +Huunda rasilimali zilizojitenga kwa kila mtiririko. +Mfano: `flow-123`, `customer-A-flow` + +#### {class} +Huibadilishwa na jina la mpango wa mtiririko. +Huunda rasilimali zilizoshirikiwa katika mitiririko ya aina moja. +Mfano: `standard-rag`, `enterprise-rag` +>>>>>>> 82edf2d (New md files from RunPod) + +### Vigezo vya Parameta + +#### {parameter-name} +<<<<<<< HEAD +Parameta maalum zilizobainishwa wakati wa kuanzisha mfumo. +Majina ya parameta yanalingana na funguo katika sehemu ya `parameters` ya mfumo. +Hutumiwa katika mipangilio ya kichakuzi ili kuboresha tabia. +Mifano: `{model}`, `{temp}`, `{chunk}` +Huibwa na maadili yaliyotolewa wakati wa kuanzisha mfumo. +Yanathibitishwa kulingana na ufafanuzi wa parameta uliohifadhiwa katika mfumo. + +## Mpangilio wa Kichakuzi + +Mpangilio hutoa maadili ya usanidi kwa vichakuzi wakati wa uundaji. Inaweza kuwa: + +### Mpangilio Thabiti +======= +Parameta maalum zilizobainishwa wakati wa kuanzisha mtiririko. +Majina ya parametri yanalingana na funguo katika sehemu ya `parameters` ya mtiririko. +Hutumiwa katika mipangilio ya kichakataji ili kuboresha tabia. +Mifano: `{model}`, `{temp}`, `{chunk}` +Huibadilishwa na maadili yaliyotolewa wakati wa kuanzisha mtiririko. +Yanathibitishwa kulingana na ufafanuzi wa parametri uliohifadhiwa katika mfumo. + +## Mipangilio ya Kichakataji + +Mipangilio hutoa maadili ya usanidi kwa vichakataji wakati wa uundaji. Inaweza kuwa: + +### Mipangilio Thabiti +>>>>>>> 82edf2d (New md files from RunPod) +Maadili ya moja kwa moja ambayo hayubadiliki: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +<<<<<<< HEAD +### Mipangilio Iliyobadilishwa +======= +### Parameta za Mpangilio +>>>>>>> 82edf2d (New md files from RunPod) +Maelezo ambayo hutumia vigezo vilivyotolewa wakati wa kuanzisha mtiririko: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +Majina ya vigezo katika mipangilio yanalingana na funguo katika sehemu ya `parameters` ya mtiririko. + +### Mifano ya Mipangilio + +**Mchakato wa LLM na Vigezo:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +<<<<<<< HEAD +**Kifurushi cha Mpangilio wa Kurekebisha na Unaoweza Kubadilishwa:** +======= +**Sehemu za Kujumuisha Zenye Mipangilio Thabiti na Inayoweza Kubadilishwa:** +>>>>>>> 82edf2d (New md files from RunPod) +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## Mifumo ya Kinyororo (Pulsar) + +<<<<<<< HEAD +Mfumo wa mtiririko hutumia Apache Pulsar kwa ujumbe. Majina ya nyororo yanafuata muundo wa Pulsar: +======= +Mfumo wa mtiririko hutumia Apache Pulsar kwa ajili ya ujumbe. Majina ya nyororo yanafuata muundo wa Pulsar: +>>>>>>> 82edf2d (New md files from RunPod) +``` +://// +``` + +### Vipengele: +<<<<<<< HEAD +**uthibitisho**: `persistent` au `non-persistent` (Njia ya uthibitisho ya Pulsar) +**mwendeshaji**: `tg` kwa maelezo ya muundo wa mtiririko yanayotolewa na TrustGraph +**nafasi**: Inaonyesha muundo wa ujumbe +======= +**uhifadhi**: `persistent` au `non-persistent` (Njia ya uhifadhi ya Pulsar) +**mwendeshaji**: `tg` kwa maelekezo ya muundo wa mtiririko yanayotolewa na TrustGraph +**nafasi**: Inaonyesha mtindo wa ujumbe +>>>>>>> 82edf2d (New md files from RunPod) + `flow`: Huduma za "tumia na usahau" + `request`: Sehemu ya ombi ya huduma za ombi/jibu + `response`: Sehemu ya jibu ya huduma za ombi/jibu +**mada**: Jina maalum la folyo/mada na vigezo vya kiolezo + +### Folyozilizohifadhiwa +<<<<<<< HEAD +Muundo: `persistent://tg/flow/:{id}` +Inatumika kwa huduma za "tumia na usahau" na mtiririko wa data endelevu +Data inabaki katika hifadhi ya Pulsar wakati wa kuanzishwa upya +Mfano: `persistent://tg/flow/chunk-load:{id}` + +### Folyozilizohifadhiwa +Muundo: `non-persistent://tg/request/:{class}` au `non-persistent://tg/response/:{class}` +Inatumika kwa muundo wa ujumbe wa ombi/jibu +Inapotea, haihifadhiwa kwenye diski na Pulsar +Latensi ndogo, inafaa kwa mawasiliano ya aina ya RPC +======= +Mtindo: `persistent://tg/flow/:{id}` +Inatumika kwa huduma za "tumia na usahau" na mtiririko wa data endelevu +Data inahifadhiwa katika hifadhi ya Pulsar katika kuanzishwa upya +Mfano: `persistent://tg/flow/chunk-load:{id}` + +### Folyozilizohifadhiwa +Mtindo: `non-persistent://tg/request/:{class}` au `non-persistent://tg/response/:{class}` +Inatumika kwa mitindo ya ujumbe ya ombi/jibu +Inapotea, haihifadhiwi kwenye diski na Pulsar +Latensi ya chini, inayofaa kwa mawasiliano ya aina ya RPC +>>>>>>> 82edf2d (New md files from RunPod) +Mfano: `non-persistent://tg/request/embeddings:{class}` + +## Usanifu wa Mtiririko wa Data + +<<<<<<< HEAD +Muundo wa mtiririko huunda mtiririko wa data unaounganishwa ambapo: + +1. **Mchakato wa Kusindika Nyaraka**: Mtiririko kutoka kwa kupokea hadi kubadilisha hadi kuhifadhi +======= +Muundo wa mtiririko huunda mtiririko wa data uliounganishwa ambapo: + +1. **Mchakato wa Kusindika Nyaraka**: Mtiririko kutoka kwa kupokea kupitia mabadiliko hadi kuhifadhi +>>>>>>> 82edf2d (New md files from RunPod) +2. **Huduma za Uchunguzi**: Wasindikaji waliojumuishwa ambao huchunguza hifadhi na huduma sawa za data +3. **Huduma Zilizoshirikiwa**: Wasindikaji wa kati ambao mtiririko wote unaweza kutumia +4. **Waandikaji wa Hifadhi**: Kuhifadhi data iliyosindikwa kwenye hifadhi husika + +<<<<<<< HEAD +Wasindikaji wote (wote `{id}` na `{class}`) hufanya kazi pamoja kama grafu moja ya mtiririko wa data, sio mifumo tofauti. +======= +Wasindikaji wote (wote `{id}` na `{class}`) hufanya kazi pamoja kama grafu ya mtiririko wa data iliyounganishwa, sio mifumo tofauti. +>>>>>>> 82edf2d (New md files from RunPod) + +## Uanzishaji wa Mfano wa Mtiririko + +Imepewa: +Kitambulisho cha Mfano wa Mtiririko: `customer-A-flow` +Muundo wa Mtiririko: `standard-rag` +Ramani za vigezo vya mtiririko: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +Vigezo vilivyotolewa na mtumiaji: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +Upanuzi wa kiolezo: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +Hii huunda: +Mchakato wa kusindika nyaraka uliotengwa kwa `customer-A-flow` +<<<<<<< HEAD +Huduma ya pamoja ya uingizaji kwa mtiririko wote wa `standard-rag` +Mtiririko kamili kutoka kwa kupokea nyaraka hadi uchunguzi +Wasindikaji walioelekezwa na maadili ya vigezo vilivyotolewa +======= +Huduma ya pamoja ya uingishaji kwa mtiririko wote wa `standard-rag` +Mtiririko kamili kutoka kwa kupokea nyaraka hadi uchunguzi +Wasindikaji uliopangwa na maadili ya vigezo vilivyotolewa +>>>>>>> 82edf2d (New md files from RunPod) + +## Faida + +1. **Ufanisi wa Rasilimali**: Huduma ghali hushirikiwa katika mitiririko +2. **Kutengwa kwa Mtiririko**: Kila mtiririko una mchakato wake wa kusindika data +3. **Uwezo wa Kupanuka**: Inaweza kuanzisha mitiririko mingi kutoka kwa kiolezo kimoja +4. **Uunganishaji**: Tofauti wazi kati ya vipengele vilivyoshirikiwa na vilivyohusiana na mtiririko +5. **Usanifu Uliounganishwa**: Uchunguzi na usindikaji ni sehemu ya mtiririko mmoja wa data diff --git a/docs/tech-specs/flow-class-definition.tr.md b/docs/tech-specs/flow-class-definition.tr.md new file mode 100644 index 00000000..7f321f65 --- /dev/null +++ b/docs/tech-specs/flow-class-definition.tr.md @@ -0,0 +1,326 @@ +--- +layout: default +title: "Akış Şeması Tanım Özellikleri" +parent: "Turkish (Beta)" +--- + +# Akış Şeması Tanım Ö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ış + +<<<<<<< HEAD +Bir akış şeması, TrustGraph sisteminde eksiksiz bir veri akışı kalıbı şablonunu tanımlar. Örneklenildiğinde, verilerin alınması, işlenmesi, depolanması ve sorgulanması işlemlerini tek bir sistem olarak ele alan, birbirine bağlı bir işlemci ağı oluşturur. +======= +Bir akış şeması, TrustGraph sisteminde eksiksiz bir veri akışı kalıbı şablonunu tanımlar. Örneklenildiğinde, veri alımı, işleme, depolama ve sorgulamayı birleşik bir sistem olarak ele alan birbirine bağlı işlemci ağları oluşturur. +>>>>>>> 82edf2d (New md files from RunPod) + +## Yapı + +Bir akış şeması tanımı, beş ana bölümden oluşur: + +### 1. Sınıf Bölümü +Her akış şeması için yalnızca bir kez örneklendirilen, paylaşılan hizmet işlemcilerini tanımlar. Bu işlemciler, bu sınıfın tüm akış örneklerinden gelen istekleri işler. + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Özellikler:** +Aynı sınıftaki tüm akış örnekleri arasında paylaşılır. +Genellikle maliyetli veya durumsuz hizmetlerdir (LLM'ler, gömme modelleri). +Kuyruk adlandırması için `{class}` şablon değişkenini kullanın. +Ayarlar, sabit değerler olabilir veya `{parameter-name}` sözdizimi ile parametrelendirilebilir. +Örnekler: `embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}` + +### 2. Akış Bölümü +Her bir bireysel akış örneği için örneklenen, akışa özgü işlemcileri tanımlar. Her akışın kendi izole edilmiş işlemci kümesi vardır. + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**Özellikler:** +Her akış için benzersiz bir örnek +Akışa özgü verileri ve durumu yönetir +<<<<<<< HEAD +Kuyruğu adlandırmak için `{id}` şablon değişkenini kullanın +======= +Kuyruğa adlandırma için `{id}` şablon değişkenini kullanın +>>>>>>> 82edf2d (New md files from RunPod) +Ayarlar, sabit değerler olabilir veya `{parameter-name}` sözdizimi ile parametrelendirilebilir +Örnekler: `chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. Arayüzler Bölümü +Akış için giriş noktalarını ve etkileşim sözleşmelerini tanımlar. Bunlar, harici sistemler ve dahili bileşen iletişimi için API yüzeyini oluşturur. + +Arayüzler iki formda olabilir: + +**Ateşle ve Unut (Fire-and-Forget) Modeli** (tek kuyruk): +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**İstek/Yanıt Modeli** (istek/yanıt alanlarına sahip nesne): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**Arayüz Türleri:** +**Giriş Noktaları:** Dış sistemlerin veri enjekte ettiği yerler (`document-load`, `agent`) +<<<<<<< HEAD +**Servis Arayüzleri:** Servisler için istek/yanıt kalıpları (`embeddings`, `text-completion`) +======= +**Hizmet Arayüzleri:** Hizmetler için istek/yanıt kalıpları (`embeddings`, `text-completion`) +>>>>>>> 82edf2d (New md files from RunPod) +**Veri Arayüzleri:** Ateşle-ve-unut veri akışı bağlantı noktaları (`triples-store`, `entity-contexts-load`) + +### 4. Parametreler Bölümü +Akışa özgü parametre adlarını, merkezi olarak saklanan parametre tanımlarına eşler: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**Özellikler:** +Anahtarlar, işlemci ayarlarında kullanılan parametre adlarıdır (örneğin, `{model}`). +Değerler, şema/yapılandırmada saklanan parametre tanımlarına referans verir. +Akışlar arasında ortak parametre tanımlarının yeniden kullanılmasını sağlar. +Parametre şemalarının çoğaltılmasını azaltır. + +### 5. Meta Veriler +Akış şeması hakkında ek bilgiler: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## Şablon Değişkenleri + +### Sistem Değişkenleri + +#### {id} +Her akış örneği için benzersiz tanımlayıcı ile değiştirilir. +Her akış için izole kaynaklar oluşturur. +Örnek: `flow-123`, `customer-A-flow` + +#### {class} +Akış şablonu adıyla değiştirilir. +Aynı sınıftaki akışlar arasında paylaşılan kaynaklar oluşturur. +Örnek: `standard-rag`, `enterprise-rag` + +### Parametre Değişkenleri + +#### {parametre-adı} +Akış başlatma zamanında tanımlanan özel parametrelerdir. +Parametre adları, akışın `parameters` bölümündeki anahtarlarla eşleşir. +İşlemci ayarlarında davranışı özelleştirmek için kullanılır. +Örnekler: `{model}`, `{temp}`, `{chunk}` +Akışı başlattığınızda sağlanan değerlerle değiştirilir. +Merkezi olarak saklanan parametre tanımlarına göre doğrulanır. + +## İşlemci Ayarları + +Ayarlar, işlemcilerin başlatma zamanındaki yapılandırma değerlerini sağlar. Bunlar şunlar olabilir: + +### Sabit Ayarlar +Değişmeyen doğrudan değerler: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### Parametreleştirilmiş Ayarlar +Akış başlatılırken sağlanan parametreleri kullanan değerler: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +Ayarlardaki parametre adları, akışın `parameters` bölümündeki anahtarlara karşılık gelir. + +### Ayar Örnekleri + +**Parametrelerle LLM İşlemcisi:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**Sabit ve Parametreize Ayarlara Sahip Parçalayıcı:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## Kuyruk Desenleri (Pulsar) + +Akış şemaları, mesajlaşma için Apache Pulsar'ı kullanır. Kuyruk adları, Pulsar formatını izler: +``` +://// +``` + +### Bileşenler: +**kalıcılık**: `persistent` veya `non-persistent` (Pulsar kalıcılık modu) +**kiracı**: TrustGraph tarafından sağlanan akış tanım şablonları için `tg` +<<<<<<< HEAD +**isim alanı**: Mesajlaşma desenini belirtir +======= +**isim alanı**: Mesajlaşma kalıbını gösterir +>>>>>>> 82edf2d (New md files from RunPod) + `flow`: Ateşle ve unut hizmetleri + `request`: İstek/yanıt hizmetlerinin istek kısmı + `response`: İstek/yanıt hizmetlerinin yanıt kısmı +**konu**: Şablon değişkenleriyle belirli kuyruk/konu adı + +### Kalıcı Kuyruklar +<<<<<<< HEAD +Desen: `persistent://tg/flow/:{id}` +======= +Kalıp: `persistent://tg/flow/:{id}` +>>>>>>> 82edf2d (New md files from RunPod) +Ateşle ve unut hizmetleri ve dayanıklı veri akışı için kullanılır +Veri, yeniden başlatmalarda Pulsar depolama alanında kalıcıdır +Örnek: `persistent://tg/flow/chunk-load:{id}` + +### Kalıcı Olmayan Kuyruklar +<<<<<<< HEAD +Desen: `non-persistent://tg/request/:{class}` veya `non-persistent://tg/response/:{class}` +İstek/yanıt mesajlaşma desenleri için kullanılır +======= +Kalıp: `non-persistent://tg/request/:{class}` veya `non-persistent://tg/response/:{class}` +İstek/yanıt mesajlaşma kalıpları için kullanılır +>>>>>>> 82edf2d (New md files from RunPod) +Pulsar tarafından diske kalıcı hale getirilmez, geçicidir +Daha düşük gecikme süresi, RPC tarzı iletişim için uygundur +Örnek: `non-persistent://tg/request/embeddings:{class}` + +## Veri Akışı Mimarisi + +<<<<<<< HEAD +Akış tanımı, aşağıdaki gibi birleşik bir veri akışı oluşturur: +======= +Akış tanımı, aşağıdaki unsurları içeren birleşik bir veri akışı oluşturur: +>>>>>>> 82edf2d (New md files from RunPod) + +1. **Belge İşleme Hattı**: Alımdan dönüşüme ve depolamaya kadar olan akış +2. **Sorgu Hizmetleri**: Aynı veri depolarını ve hizmetlerini sorgulayan entegre işlemciler +3. **Paylaşımlı Hizmetler**: Tüm akışların kullanabileceği merkezi işlemciler +4. **Depolama Yazıcıları**: İşlenmiş verileri uygun depolama alanlarına kaydeder + +Tüm işlemciler (hem `{id}` hem de `{class}`), ayrı sistemler olarak değil, uyumlu bir veri akışı grafiği olarak birlikte çalışır. + +## Örnek Akış Oluşturma + +Verilenler: +Akış Örneği Kimliği: `customer-A-flow` +Akış Tanımı: `standard-rag` +Akış parametre eşlemeleri: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +Kullanıcı tarafından sağlanan parametreler: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +Şablon genişletmeleri: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +Bu, aşağıdaki öğeleri oluşturur: +`customer-A-flow` için izole edilmiş belge işleme hattı +<<<<<<< HEAD +Tüm `standard-rag` akışları için paylaşımlı gömme hizmeti +Belge alımından sorgulamaya kadar olan eksiksiz veri akışı +İşlemciler, sağlanan parametre değerleriyle yapılandırılmıştır +======= +tüm `standard-rag` akışları için paylaşımlı gömme hizmeti +Belge alımından sorgulamaya kadar olan eksiksiz veri akışı +İşlemcilerin sağlanan parametre değerleriyle yapılandırılması +>>>>>>> 82edf2d (New md files from RunPod) + +## Avantajlar + +1. **Kaynak Verimliliği**: Pahalı hizmetler, akışlar arasında paylaşılır +2. **Akış İzolasyonu**: Her akışın kendi veri işleme hattı vardır +<<<<<<< HEAD +3. **Ölçeklenebilirlik**: Aynı şablondan birden fazla akış oluşturulabilir +4. **Modülerlik**: Paylaşılan ve akışa özgü bileşenler arasında net bir ayrım +5. **Bütünleşik Mimari**: Sorgu ve işleme, aynı veri akışının bir parçasıdır +======= +3. **Ölçeklenebilirlik**: Aynı şablondan çok sayıda akış oluşturulabilir +4. **Modülerlik**: Paylaşılan ve akışa özgü bileşenler arasında net bir ayrım +5. **Birleşik Mimari**: Sorgu ve işleme, aynı veri akışının bir parçasıdır +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/flow-class-definition.zh-cn.md b/docs/tech-specs/flow-class-definition.zh-cn.md new file mode 100644 index 00000000..a514879d --- /dev/null +++ b/docs/tech-specs/flow-class-definition.zh-cn.md @@ -0,0 +1,317 @@ +--- +layout: default +title: "流程蓝图定义规范" +parent: "Chinese (Beta)" +--- + +<<<<<<< HEAD +# 流程蓝图定义规范 + +> **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. 类部分 +定义共享服务处理器,这些处理器每个流程蓝图实例化一次。这些处理器处理来自此类的所有流程实例的请求。 +======= +# 流工作蓝图定义规范 + +## 概述 + +一个流工作蓝图定义了 TrustGraph 系统中完整的数据流模式模板。当实例化时,它会创建一个相互连接的处理单元网络,该网络处理数据摄取、处理、存储和查询,作为一个统一的系统。 + +## 结构 + +一个流工作蓝图定义由五个主要部分组成: + +### 1. 类部分 +定义共享服务处理器,这些处理器每个流工作蓝图实例化一次。这些处理器处理来自此类的所有流实例的请求。 +>>>>>>> 82edf2d (New md files from RunPod) + +```json +"class": { + "service-name:{class}": { + "request": "queue-pattern:{class}", + "response": "queue-pattern:{class}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +<<<<<<< HEAD +**特性:** +======= +**特点:** +>>>>>>> 82edf2d (New md files from RunPod) +在同一类别的所有流程实例中共享。 +通常是昂贵或无状态的服务(例如:大型语言模型、嵌入模型)。 +使用 `{class}` 模板变量进行队列命名。 +设置可以是固定值,也可以使用 `{parameter-name}` 语法进行参数化。 +示例:`embeddings:{class}`, `text-completion:{class}`, `graph-rag:{class}` + +### 2. 流程部分 +定义与流程相关的处理器,这些处理器为每个独立的流程实例进行实例化。 每个流程都拥有自己的一组隔离的处理器。 + +```json +"flow": { + "processor-name:{id}": { + "input": "queue-pattern:{id}", + "output": "queue-pattern:{id}", + "settings": { + "setting-name": "fixed-value", + "parameterized-setting": "{parameter-name}" + } + } +} +``` + +**特性:** +每个流程只有一个实例。 +处理流程特定的数据和状态。 +使用 `{id}` 模板变量进行队列命名。 +设置可以是固定值,也可以使用 `{parameter-name}` 语法进行参数化。 +示例:`chunker:{id}`, `pdf-decoder:{id}`, `kg-extract-relationships:{id}` + +### 3. 接口部分 +定义流程的入口点和交互协议。 这些构成了外部系统和内部组件通信的 API 表面。 + +<<<<<<< HEAD +接口可以有两种形式: + +**即发即弃模式**(单个队列): +======= +接口可以采用两种形式: + +**发布-订阅模式**(单个队列): +>>>>>>> 82edf2d (New md files from RunPod) +```json +"interfaces": { + "document-load": "persistent://tg/flow/document-load:{id}", + "triples-store": "persistent://tg/flow/triples-store:{id}" +} +``` + +**请求/响应模式** (包含请求/响应字段的对象): +```json +"interfaces": { + "embeddings": { + "request": "non-persistent://tg/request/embeddings:{class}", + "response": "non-persistent://tg/response/embeddings:{class}" + } +} +``` + +**接口类型:** +**入口点:** 外部系统注入数据的入口点 (`document-load`, `agent`) +**服务接口:** 服务请求/响应模式 (`embeddings`, `text-completion`) +**数据接口:** 触发/完成式数据流连接点 (`triples-store`, `entity-contexts-load`) + +### 4. 参数部分 +将流程特定的参数名称映射到集中存储的参数定义: + +```json +"parameters": { + "model": "llm-model", + "temp": "temperature", + "chunk": "chunk-size" +} +``` + +**特性:** +键是处理器设置中使用的参数名称(例如,`{model}`) +值引用存储在 schema/config 中的参数定义 +允许在流程之间重用常见的参数定义 +减少参数模式的重复 + +### 5. 元数据 +关于流程蓝图的附加信息: + +```json +"description": "Human-readable description", +"tags": ["capability-1", "capability-2"] +``` + +## 模板变量 + +### 系统变量 + +#### {id} +被替换为唯一的流程实例标识符 +为每个流程创建隔离的资源 +示例:`flow-123`, `customer-A-flow` + +#### {class} +被替换为流程蓝图名称 +为相同类别的流程创建共享资源 +示例:`standard-rag`, `enterprise-rag` + +### 参数变量 + +#### {parameter-name} +在流程启动时定义的自定义参数 +参数名称与流程的 `parameters` 部分中的键匹配 +用于在处理器设置中自定义行为 +示例:`{model}`, `{temp}`, `{chunk}` +被替换为启动流程时提供的值 +验证通过与集中存储的参数定义进行比较 + +## 处理器设置 + +设置在实例化时向处理器提供配置值。 它们可以是: + +### 静态设置 +直接值,不会改变: +```json +"settings": { + "model": "gemma3:12b", + "temperature": 0.7, + "max_retries": 3 +} +``` + +### 参数化设置 +使用在流程启动时提供的参数的值: +```json +"settings": { + "model": "{model}", + "temperature": "{temp}", + "endpoint": "https://{region}.api.example.com" +} +``` + +参数名称在设置中对应于流程的 `parameters` 部分中的键。 + +### 设置示例 + +**带有参数的 LLM 处理器:** +```json +// In parameters section: +"parameters": { + "model": "llm-model", + "temp": "temperature", + "tokens": "max-tokens", + "key": "openai-api-key" +} + +// In processor definition: +"text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "settings": { + "model": "{model}", + "temperature": "{temp}", + "max_tokens": "{tokens}", + "api_key": "{key}" + } +} +``` + +**具有固定和参数化设置的分块器:** +```json +// In parameters section: +"parameters": { + "chunk": "chunk-size" +} + +// In processor definition: +"chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "settings": { + "chunk_size": "{chunk}", + "chunk_overlap": 100, + "encoding": "utf-8" + } +} +``` + +## 队列模式 (Pulsar) + +流程蓝图使用 Apache Pulsar 进行消息传递。队列名称遵循 Pulsar 格式: +``` +://// +``` + +### 组件: +**持久性**: `persistent` 或 `non-persistent` (Pulsar 持久性模式) +**租户**: `tg` 用于 TrustGraph 提供的流程蓝图定义 +**命名空间**: 表示消息模式 + `flow`: 适用于“发送即忘”服务 + `request`: 适用于请求/响应服务的请求部分 + `response`: 适用于请求/响应服务的响应部分 +**主题**: 具有模板变量的特定队列/主题名称 + +### 持久队列 +模式: `persistent://tg/flow/:{id}` +用于“发送即忘”服务和持久数据流 +数据在 Pulsar 存储中持久化,即使在重启后也保留 +示例: `persistent://tg/flow/chunk-load:{id}` + +### 非持久队列 +模式: `non-persistent://tg/request/:{class}` 或 `non-persistent://tg/response/:{class}` +用于请求/响应消息模式 +瞬态的,不由 Pulsar 持久化到磁盘 +延迟较低,适用于 RPC 风格的通信 +示例: `non-persistent://tg/request/embeddings:{class}` + +## 数据流架构 + +流程蓝图创建统一的数据流,其中: + +<<<<<<< HEAD +1. **文档处理管道**: 从摄取到转换再到存储的流程 +2. **查询服务**: 集成的处理器,查询相同的存储和服务 +3. **共享服务**: 所有流程都可以使用的集中式处理器 +4. **存储写入器**: 将处理后的数据持久化到适当的存储中 +======= +1. **文档处理管道**: 从摄取到转换再到存储 +2. **查询服务**: 集成的处理器,查询相同的存储和服务 +3. **共享服务**: 所有流程都可以使用的集中处理器 +4. **存储写入器**: 将处理后的数据持久化到适当的存储 +>>>>>>> 82edf2d (New md files from RunPod) + +所有处理器(包括 `{id}` 和 `{class}`)协同工作,形成一个连贯的数据流图,而不是作为独立的系统。 + +## 流程实例化示例 + +假设: +流程实例 ID: `customer-A-flow` +流程蓝图: `standard-rag` +流程参数映射: + `"model": "llm-model"` + `"temp": "temperature"` + `"chunk": "chunk-size"` +用户提供的参数: + `model`: `gpt-4` + `temp`: `0.5` + `chunk`: `512` + +模板扩展: +`persistent://tg/flow/chunk-load:{id}` → `persistent://tg/flow/chunk-load:customer-A-flow` +`non-persistent://tg/request/embeddings:{class}` → `non-persistent://tg/request/embeddings:standard-rag` +`"model": "{model}"` → `"model": "gpt-4"` +`"temperature": "{temp}"` → `"temperature": "0.5"` +`"chunk_size": "{chunk}"` → `"chunk_size": "512"` + +这会创建: +用于 `customer-A-flow` 的隔离文档处理管道 +用于所有 `standard-rag` 流程的共享嵌入服务 +从文档摄取到查询的完整数据流 +使用提供的参数值配置的处理器 + +## 优点 + +1. **资源效率**: 昂贵的服务在流程之间共享 +2. **流程隔离**: 每个流程都有自己的数据处理管道 +3. **可扩展性**: 可以从相同的模板实例化多个流程 +4. **模块化**: 共享组件和流程特定组件之间有明确的分离 +5. **统一架构**: 查询和处理是相同的数据流的一部分 diff --git a/docs/tech-specs/flow-configurable-parameters.ar.md b/docs/tech-specs/flow-configurable-parameters.ar.md new file mode 100644 index 00000000..074a8822 --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.ar.md @@ -0,0 +1,619 @@ +--- +layout: default +title: "المواصفات الفنية لـ 'خطة سير العمل' (Flow Blueprint) للمعلمات القابلة للتكوين" +parent: "Arabic (Beta)" +--- + +# المواصفات الفنية لـ "خطة سير العمل" (Flow Blueprint) للمعلمات القابلة للتكوين + +> **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. تتيح المعلمات للمستخدمين تخصيص معلمات المعالج في وقت بدء تشغيل سير العمل من خلال توفير قيم تحل محل العناصر النائبة للمعلمات في تعريف "خطة سير العمل". + +تعمل المعلمات من خلال استبدال متغيرات القالب في معلمات المعالج، على غرار كيفية عمل المتغيرات `{id}` و `{class}`، ولكن مع قيم مقدمة من المستخدم. + +يدعم التكامل أربعة حالات استخدام رئيسية: + +1. **اختيار النموذج**: السماح للمستخدمين باختيار نماذج LLM مختلفة (مثل `gemma3:8b`، `gpt-4`، `claude-3`) للمعالجات. +2. **تكوين الموارد**: تعديل معلمات المعالج مثل أحجام الدُفعات، وأحجام الدُفعات، وحدود التزامن. +3. **الضبط الدقيق للسلوك**: تعديل سلوك المعالج من خلال معلمات مثل درجة الحرارة، والحد الأقصى للرموز، أو عتبات الاسترجاع. +4. **معلمات خاصة بالبيئة**: تكوين نقاط النهاية، ومفاتيح API، أو عناوين URL خاصة بالمنطقة لكل عملية نشر. + +## الأهداف + +**تكوين المعالج الديناميكي**: تمكين تكوين معلمات المعالج في وقت التشغيل من خلال استبدال المعلمات. +**التحقق من صحة المعلمات**: توفير التحقق من النوع والتحقق من صحة المعلمات في وقت بدء تشغيل سير العمل. +**القيم الافتراضية**: دعم القيم الافتراضية المعقولة مع السماح بالتجاوزات للمستخدمين المتقدمين. +**استبدال القوالب**: استبدال العناصر النائبة للمعلمات في معلمات المعالج بسلاسة. +**التكامل مع واجهة المستخدم**: تمكين إدخال المعلمات من خلال كل من واجهات برمجة التطبيقات وواجهات المستخدم. +**الأمان من النوع**: التأكد من أن أنواع المعلمات تتطابق مع أنواع معلمات المعالج المتوقعة. +**التوثيق**: مخططات معلمات ذاتية التوثيق داخل تعريفات "خطط سير العمل". +**التوافق مع الإصدارات السابقة**: الحفاظ على التوافق مع "خطط سير العمل" الحالية التي لا تستخدم المعلمات. + +## الخلفية + +تدعم "خطط سير العمل" في TrustGraph الآن معلمات المعالج التي يمكن أن تحتوي إما على قيم ثابتة أو عناصر نائبة للمعلمات. هذا يخلق فرصة للتخصيص في وقت التشغيل. + +تدعم معلمات المعالج الحالية: +القيم الثابتة: `"model": "gemma3:12b"` +العناصر النائبة للمعلمات: `"model": "gemma3:{model-size}"` + +تحدد هذه المواصفة كيفية: +الإعلان عن المعلمات في تعريفات "خطط سير العمل". +التحقق من صحة المعلمات عند بدء تشغيل سير العمل. +استبدال المعلمات في معلمات المعالج. +<<<<<<< HEAD +الكشف عنها من خلال واجهات برمجة التطبيقات وواجهات المستخدم. + +من خلال الاستفادة من معلمات معلمات المعالج، يمكن لـ TrustGraph: +تقليل تكرار "خطط سير العمل" باستخدام المعلمات للتغيرات. +======= +الكشف عن المعلمات من خلال واجهات برمجة التطبيقات وواجهات المستخدم. + +من خلال الاستفادة من معلمات معلمات المعالج، يمكن لـ TrustGraph: +تقليل تكرار "خطط سير العمل" باستخدام المعلمات للتنوعات. +>>>>>>> 82edf2d (New md files from RunPod) +تمكين المستخدمين من ضبط سلوك المعالج دون تعديل التعريفات. +دعم التكوينات الخاصة بالبيئة من خلال قيم المعلمات. +الحفاظ على الأمان من النوع من خلال التحقق من صحة مخططات المعلمات. + +## التصميم الفني + +### البنية + +يتطلب نظام المعلمات القابلة للتكوين المكونات الفنية التالية: + +1. **تعريف مخطط المعلمات** + تعريفات المعلمات المستندة إلى JSON Schema داخل بيانات تعريف "خطة سير العمل". + تعريفات الأنواع بما في ذلك أنواع السلاسل والأرقام والمنطق والقوائم وأنواع الكائنات. + قواعد التحقق من الصحة بما في ذلك القيم الدنيا/القصوى، والأنماط، والحقول المطلوبة. + + الوحدة: trustgraph-flow/trustgraph/flow/definition.py + +2. **محرك حل المعلمات** + التحقق من صحة المعلمات في وقت التشغيل مقابل المخطط. + تطبيق القيم الافتراضية للمعلمات غير المحددة. + حقن المعلمات في سياق تنفيذ سير العمل. + التحويل والتحويل من النوع حسب الحاجة. + + الوحدة: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **تكامل مخزن المعلمات** + استرداد تعريفات المعلمات من نظام المخطط/التكوين. + التخزين المؤقت لتعريفات المعلمات المستخدمة بشكل متكرر. + التحقق من الصحة مقابل المخططات المخزنة مركزيًا. + + الوحدة: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **امتدادات مشغل سير العمل** + امتدادات واجهة برمجة التطبيقات لقبول قيم المعلمات أثناء بدء تشغيل سير العمل. + دقة تعيين المعلمات (أسماء سير العمل إلى أسماء التعريف). + معالجة الأخطاء لمجموعات المعلمات غير الصالحة. + + الوحدة: trustgraph-flow/trustgraph/flow/launcher.py + +5. **نماذج واجهة المستخدم للمعلمات** + إنشاء نماذج ديناميكية من بيانات تعريف معلمات سير العمل. + عرض المعلمات بترتيب باستخدام `order`. + تسميات وصفية للمعلمات باستخدام `description`. + التحقق من صحة الإدخال مقابل تعريفات أنواع المعلمات. + إعدادات مسبقة وقوالب للمعلمات. + + الوحدة: trustgraph-ui/components/flow-parameters/ + +### نماذج البيانات + +#### تعريفات المعلمات (مخزنة في المخطط/التكوين) + +يتم تخزين تعريفات المعلمات مركزيًا في نظام المخطط والتكوين مع النوع "parameter-type": + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### مخطط سير العمل مع مراجع المعلمات + +<<<<<<< HEAD +تحدد مخططات سير العمل بيانات وصفية للمعلمات مع مراجع للأنواع والأوصاف والترتيب: +======= +تحدد مخططات سير العمل بيانات تعريف المعلمات مع مراجع الأنواع والأوصاف والترتيب: +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +<<<<<<< HEAD +القسم `parameters` يربط أسماء المعلمات الخاصة بالتدفق (المفاتيح) بكائنات بيانات تعريف المعلمات التي تحتوي على: +`type`: مرجع إلى تعريف المعلمة المحدد مركزيًا (مثل "llm-model") +`description`: وصف يمكن قراءته بواسطة الإنسان للعرض في واجهة المستخدم +======= +القسم `parameters` يربط أسماء المعلمات الخاصة بالتدفق (المفاتيح) بكائنات بيانات وصفية للمعلمات والتي تحتوي على: +`type`: مرجع إلى تعريف المعلمة المحدد مركزيًا (مثل "llm-model") +`description`: وصف قابل للقراءة بواسطة الإنسان للعرض في واجهة المستخدم +>>>>>>> 82edf2d (New md files from RunPod) +`order`: ترتيب العرض لنماذج المعلمات (تظهر الأرقام الأقل أولاً) +`advanced` (اختياري): علامة منطقية تشير إلى ما إذا كانت هذه معلمة متقدمة (افتراضي: خطأ). عند تعيينها على "صحيح"، قد تخفي واجهة المستخدم هذه المعلمة افتراضيًا أو تضعها في قسم "متقدم" +`controlled-by` (اختياري): اسم معلمة أخرى تتحكم في قيمة هذه المعلمة عند التواجد في الوضع البسيط. عند تحديدها، ترث هذه المعلمة قيمتها من المعلمة المتحكمة ما لم يتم تجاوزها بشكل صريح + +تسمح هذه الطريقة بما يلي: +تعريفات أنواع معلمات قابلة لإعادة الاستخدام عبر قوالب تدفق متعددة +إدارة مركزية لأنواع المعلمات والتحقق من صحتها +<<<<<<< HEAD +أوصاف وترتيب المعلمات الخاصة بالتدفق +======= +أوصاف وترتيب معلمات خاصة بالتدفق +>>>>>>> 82edf2d (New md files from RunPod) +تجربة واجهة مستخدم محسنة مع نماذج معلمات وصفية +التحقق من صحة المعلمات بشكل متسق عبر التدفقات +إضافة سهلة لأنواع معلمات قياسية جديدة +واجهة مستخدم مبسطة مع فصل الوضع الأساسي/المتقدم +وراثة قيمة المعلمة للإعدادات ذات الصلة + +#### طلب بدء تشغيل التدفق + +تقبل واجهة برمجة تطبيقات بدء تشغيل التدفق المعلمات باستخدام أسماء المعلمات الخاصة بالتدفق: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +ملاحظة: في هذا المثال، `llm-rag-model` غير مقدمة بشكل صريح ولكنها سترث القيمة "claude-3" من `llm-model` بسبب علاقتها مع `controlled-by`. وبالمثل، يمكن أن ترث `chunk-overlap` قيمة محسوبة بناءً على `chunk-size`. + +سيقوم النظام بما يلي: +<<<<<<< HEAD +1. استخراج بيانات تعريف المعلمات من تعريف مخطط التدفق +2. مطابقة أسماء معلمات التدفق مع تعريفات أنواعها (على سبيل المثال، `llm-model` → نوع `llm-model`) +3. حل علاقات "يتم التحكم بها" (على سبيل المثال، ترث `llm-rag-model` من `llm-model`) +======= +1. استخراج بيانات وصفية للمعلمات من تعريف مخطط التدفق +2. ربط أسماء معلمات التدفق بتعريفات أنواعها (مثل: `llm-model` → نوع `llm-model`) +3. حل علاقات "التحكم بواسطة" (مثل: `llm-rag-model` ترث من `llm-model`) +>>>>>>> 82edf2d (New md files from RunPod) +4. التحقق من صحة القيم المقدمة من المستخدم والقيم الموروثة مقابل تعريفات أنواع المعلمات +5. استبدال القيم التي تم حلها في معلمات المعالج أثناء إنشاء التدفق + +### تفاصيل التنفيذ + +#### عملية حل المعلمات + +عندما يتم بدء تدفق، يقوم النظام بتنفيذ الخطوات التالية لحل المعلمات: + +<<<<<<< HEAD +1. **تحميل مخطط التدفق**: تحميل تعريف مخطط التدفق واستخراج بيانات تعريف المعلمات +2. **استخراج البيانات الوصفية**: استخراج `type`، `description`، `order`، `advanced`، و `controlled-by` لكل معلمة معرفة في قسم `parameters` الخاص بمخطط التدفق +3. **البحث عن تعريف النوع**: لكل معلمة في مخطط التدفق: + استرجاع تعريف نوع المعلمة من متجر المخطط/التكوين باستخدام حقل `type` +======= +1. **تحميل مخطط التدفق**: تحميل تعريف مخطط التدفق واستخراج بيانات وصفية للمعلمات +2. **استخراج البيانات الوصفية**: استخراج `type`، `description`، `order`، `advanced`، و `controlled-by` لكل معلمة معرفة في قسم `parameters` الخاص بمخطط التدفق +3. **البحث عن تعريف النوع**: لكل معلمة في مخطط التدفق: + استرجاع تعريف نوع المعلمة من متجر المخططات/التكوين باستخدام حقل `type` +>>>>>>> 82edf2d (New md files from RunPod) + يتم تخزين تعريفات الأنواع مع النوع "parameter-type" في نظام التكوين + يحتوي كل تعريف نوع على مخطط المعلمة والقيمة الافتراضية وقواعد التحقق من الصحة +4. **حل القيمة الافتراضية**: + لكل معلمة معرفة في مخطط التدفق: + التحقق مما إذا كان المستخدم قد قدم قيمة لهذه المعلمة + إذا لم يتم تقديم قيمة من قبل المستخدم، استخدم القيمة `default` من تعريف نوع المعلمة +<<<<<<< HEAD + إنشاء خريطة معلمات كاملة تحتوي على كل من القيم المقدمة من قبل المستخدم والقيم الافتراضية +5. **حل إرث المعلمات** (علاقات "يتم التحكم بها"): +======= + إنشاء خريطة كاملة للمعلمات تحتوي على كل من القيم المقدمة من قبل المستخدم والقيم الافتراضية +5. **حل إرث المعلمات** (علاقات "التحكم بواسطة"): +>>>>>>> 82edf2d (New md files from RunPod) + للمعلمات التي تحتوي على حقل `controlled-by`، تحقق مما إذا تم توفير قيمة بشكل صريح + إذا لم يتم توفير قيمة صريحة، فقم بوراثة القيمة من المعلمة المسيطرة + إذا كانت المعلمة المسيطرة أيضًا لا تحتوي على قيمة، فاستخدم القيمة الافتراضية من تعريف النوع + التحقق من عدم وجود تبعيات دائرية في علاقات `controlled-by` +6. **التحقق من الصحة**: التحقق من صحة مجموعة المعلمات الكاملة (القيم المقدمة من قبل المستخدم والقيم الافتراضية والقيم الموروثة) مقابل تعريفات الأنواع +7. **التخزين**: تخزين مجموعة المعلمات التي تم حلها بالكامل مع مثيل التدفق لأغراض التدقيق +<<<<<<< HEAD +8. **الاستبدال القالب**: استبدال عناصر نائب المعلمات في معلمات المعالج بالقيم التي تم حلها +======= +8. **استبدال القوالب**: استبدال عناصر نطق المعلمات في معلمات المعالج بالقيم التي تم حلها +>>>>>>> 82edf2d (New md files from RunPod) +9. **إنشاء المعالجات**: إنشاء معالجات بمعلمات مستبدلة + +**ملاحظات تنفيذ مهمة:** +يجب على خدمة التدفق دمج المعلمات المقدمة من قبل المستخدم مع القيم الافتراضية من تعريفات أنواع المعلمات +يجب تخزين مجموعة المعلمات الكاملة (بما في ذلك القيم الافتراضية المطبقة) مع التدفق لأغراض التتبع +يحدث حل المعلمات في وقت بدء التدفق، وليس في وقت إنشاء المعالج +يجب أن يؤدي عدم وجود معلمات مطلوبة بدون قيم افتراضية إلى فشل بدء التدفق مع رسالة خطأ واضحة + +<<<<<<< HEAD +#### إرث المعلمات مع "يتم التحكم بها" +======= +#### إرث المعلمات مع "التحكم بواسطة" +>>>>>>> 82edf2d (New md files from RunPod) + +يتيح الحقل `controlled-by` وراثة قيمة المعلمة، وهو مفيد بشكل خاص لتبسيط واجهات المستخدم مع الحفاظ على المرونة: + +**سيناريو مثال:** +تتحكم المعلمة `llm-model` في نموذج LLM الأساسي +تحتوي المعلمة `llm-rag-model` على `"controlled-by": "llm-model"` +في الوضع البسيط، يؤدي تعيين `llm-model` إلى "gpt-4" تلقائيًا إلى تعيين `llm-rag-model` إلى "gpt-4" أيضًا +في الوضع المتقدم، يمكن للمستخدمين تجاوز `llm-rag-model` بقيمة مختلفة + +**قواعد الحل:** +1. إذا كانت المعلمة تحتوي على قيمة مقدمة بشكل صريح، فاستخدم تلك القيمة +2. إذا لم تكن هناك قيمة صريحة وتم تعيين `controlled-by`، فاستخدم قيمة المعلمة المسيطرة +3. إذا كانت المعلمة المسيطرة لا تحتوي على قيمة، فارجع إلى القيمة الافتراضية من تعريف النوع +4. تؤدي التبعيات الدائرية في علاقات `controlled-by` إلى خطأ في التحقق من الصحة + +**سلوك واجهة المستخدم:** +في الوضع الأساسي/البسيط: قد تكون المعلمات التي تحتوي على `controlled-by` مخفية أو معروضة كقراءة فقط مع القيمة الموروثة +في الوضع المتقدم: يتم عرض جميع المعلمات ويمكن تكوينها بشكل فردي +عندما تتغير المعلمة المسيطرة، يتم تحديث المعلمات التابعة تلقائيًا ما لم يتم تجاوزها بشكل صريح + +#### تكامل Pulsar + +1. **عملية بدء التدفق** + يجب أن تقبل عملية بدء التدفق في Pulsar حقل `parameters` يحتوي على خريطة لقيم المعلمات + يجب تحديث مخطط طلب بدء التدفق في Pulsar لتضمين الحقل الاختياري `parameters` + مثال للطلب: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **عملية الحصول على التدفق** + يجب تحديث مخطط بولسر لـ "استجابة الحصول على التدفق" ليشمل الحقل `parameters`. + يتيح ذلك للعملاء استرداد قيم المعلمات التي تم استخدامها عند بدء التدفق. + مثال على الاستجابة: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### تنفيذ خدمة التدفق + +تتطلب خدمة تكوين التدفق (`trustgraph-flow/trustgraph/config/service/flow.py`) التحسينات التالية: + +1. **وظيفة حل المعلمات** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + يجب أن تقوم هذه الدالة بما يلي: +<<<<<<< HEAD + استخراج بيانات تعريف المعلمات من قسم `parameters` في مخطط سير العمل. + لكل معلمة، استرداد تعريف النوع الخاص بها من مستودع التكوين. +======= + استخراج بيانات تعريف المعلمات من قسم `parameters` في مخطط التدفق. + لكل معلمة، استرجاع تعريف النوع الخاص بها من مستودع التكوين. +>>>>>>> 82edf2d (New md files from RunPod) + تطبيق القيم الافتراضية لأي معلمات لم يتم توفيرها من قبل المستخدم. + التعامل مع علاقات الوراثة `controlled-by`. + إرجاع المجموعة الكاملة للمعلمات. + +2. **الطريقة المعدلة `handle_start_flow`** +<<<<<<< HEAD + استدعاء `resolve_parameters` بعد تحميل مخطط سير العمل. + استخدام المجموعة الكاملة للمعلمات التي تم حلها للاستبدال في القوالب. + تخزين المجموعة الكاملة للمعلمات (وليس فقط المعلمات التي قدمها المستخدم) مع سير العمل. + التحقق من أن جميع المعلمات المطلوبة لها قيم. + +3. **استرداد أنواع المعلمات** +======= + استدعاء `resolve_parameters` بعد تحميل مخطط التدفق. + استخدام المجموعة الكاملة للمعلمات التي تم حلها للاستبدال في القوالب. + تخزين المجموعة الكاملة للمعلمات (وليس فقط المعلمات التي قدمها المستخدم) مع التدفق. + التحقق من أن جميع المعلمات المطلوبة لها قيم. + +3. **استرجاع أنواع المعلمات** +>>>>>>> 82edf2d (New md files from RunPod) + يتم تخزين تعريفات أنواع المعلمات في التكوين بنوع "parameter-type". + يحتوي كل تعريف نوع على مخطط وقيمة افتراضية وقواعد تحقق. + تخزين أنواع المعلمات المستخدمة بشكل متكرر في ذاكرة التخزين المؤقت لتقليل عمليات البحث في التكوين. + +#### تكامل نظام التكوين + +<<<<<<< HEAD +3. **تخزين كائنات سير العمل** + عندما تتم إضافة سير عمل إلى نظام التكوين بواسطة مكون سير العمل في مدير التكوين، يجب أن تتضمن كائن سير العمل قيم المعلمات التي تم حلها. + يحتاج مدير التكوين إلى تخزين كل من المعلمات التي قدمها المستخدم في الأصل والقيم التي تم حلها (مع تطبيق القيم الافتراضية). + يجب أن تتضمن كائنات سير العمل في نظام التكوين: + `parameters`: القيم النهائية للمعلمات التي تم حلها والتي تم استخدامها لسير العمل. +======= +3. **تخزين كائنات التدفق** + عندما تتم إضافة تدفق إلى نظام التكوين بواسطة مكون التدفق في مدير التكوين، يجب أن تتضمن كائن التدفق قيم المعلمات التي تم حلها. + يحتاج مدير التكوين إلى تخزين كل من المعلمات التي قدمها المستخدم في الأصل والقيم التي تم حلها (مع تطبيق القيم الافتراضية). + يجب أن تتضمن كائنات التدفق في نظام التكوين: + `parameters`: القيم النهائية للمعلمات التي تم حلها والتي تم استخدامها للتدفق. +>>>>>>> 82edf2d (New md files from RunPod) + +#### تكامل واجهة سطر الأوامر + +4. **أوامر واجهة سطر الأوامر الخاصة بالمكتبة** +<<<<<<< HEAD + تحتاج أوامر واجهة سطر الأوامر التي تبدأ سير العمل إلى دعم المعلمات: + قبول قيم المعلمات عبر علامات سطر الأوامر أو ملفات التكوين. + التحقق من صحة المعلمات مقابل تعريفات مخطط سير العمل قبل الإرسال. + دعم إدخال ملف المعلمات (JSON/YAML) لمجموعات المعلمات المعقدة. + + تحتاج أوامر واجهة سطر الأوامر التي تعرض سير العمل إلى عرض معلومات المعلمات: + عرض قيم المعلمات المستخدمة عند بدء سير العمل. + عرض المعلمات المتاحة لمخطط سير عمل. +======= + تحتاج أوامر واجهة سطر الأوامر التي تبدأ التدفقات إلى دعم المعلمات: + قبول قيم المعلمات عبر علامات سطر الأوامر أو ملفات التكوين. + التحقق من صحة المعلمات مقابل تعريفات مخطط التدفق قبل الإرسال. + دعم إدخال ملفات المعلمات (JSON/YAML) لمجموعات المعلمات المعقدة. + + تحتاج أوامر واجهة سطر الأوامر التي تعرض التدفقات إلى عرض معلومات المعلمات: + عرض قيم المعلمات المستخدمة عند بدء التدفق. + عرض المعلمات المتاحة لمخطط تدفق. +>>>>>>> 82edf2d (New md files from RunPod) + عرض مخططات التحقق من صحة المعلمات والقيم الافتراضية. + +#### تكامل الفئة الأساسية للمعالج + +5. **دعم ParameterSpec** +<<<<<<< HEAD + تحتاج الفئات الأساسية للمعالج إلى دعم استبدال المعلمات من خلال آلية ParametersSpec الحالية. + يجب تحسين فئة ParametersSpec (الموجودة في نفس الوحدة النمطية مثل ConsumerSpec و ProducerSpec) إذا لزم الأمر لدعم استبدال القوالب للمعلمات. + يجب أن تكون المعالجات قادرة على استدعاء ParametersSpec لتكوين معامها باستخدام قيم المعلمات التي تم حلها في وقت بدء سير العمل. + يجب أن تقوم تنفيذ ParametersSpec بما يلي: + قبول تكوينات المعلمات التي تحتوي على عناصر نائبة للمعلمات (مثل `{model}`، `{temperature}`). +======= + يجب أن تدعم الفئات الأساسية للمعالج استبدال المعلمات من خلال آلية ParametersSpec الحالية. + يجب تحسين فئة ParametersSpec (الموجودة في نفس الوحدة كما ConsumerSpec و ProducerSpec) إذا لزم الأمر لدعم استبدال القوالب للمعلمات. + يجب أن تكون المعالجات قادرة على استدعاء ParametersSpec لتكوين معامها باستخدام قيم المعلمات التي تم حلها في وقت بدء التدفق. + يجب أن تقوم تنفيذ ParametersSpec بما يلي: + قبول تكوينات المعلمات التي تحتوي على عناصر نائب للمعلمات (مثل `{model}`، `{temperature}`). +>>>>>>> 82edf2d (New md files from RunPod) + دعم استبدال المعلمات في وقت التشغيل عند إنشاء المعالج. + التحقق من أن القيم المستبدلة تتطابق مع الأنواع والقيود المتوقعة. + توفير معالجة الأخطاء للإشارات المفقودة أو غير الصالحة للمعلمات. + +#### قواعد الاستبدال + +تستخدم المعلمات التنسيق `{parameter-name}` في معلمات المعالج. +<<<<<<< HEAD +تتطابق أسماء المعلمات في المعلمات مع المفاتيح في قسم `parameters` في سير العمل. +======= +تتطابق أسماء المعلمات في المعلمات مع المفاتيح في قسم `parameters` في التدفق. +>>>>>>> 82edf2d (New md files from RunPod) +يحدث الاستبدال جنبًا إلى جنب مع استبدال `{id}` و `{class}`. +تؤدي الإشارات غير الصالحة للمعلمات إلى أخطاء في وقت بدء التشغيل. +يحدث التحقق من النوع بناءً على تعريف المعلمة المخزن مركزيًا. +**هام**: يتم تخزين جميع قيم المعلمات وإرسالها كسلاسل. + يتم تحويل الأرقام إلى سلاسل (على سبيل المثال، `0.7` تصبح `"0.7"`). + يتم تحويل القيم المنطقية إلى سلاسل صغيرة (على سبيل المثال، `true` تصبح `"true"`). + هذا مطلوب بواسطة مخطط Pulsar الذي يحدد `parameters = Map(String())`. + +مثال على الحل: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## استراتيجية الاختبار + +اختبارات الوحدة للتحقق من صحة مخططات المعلمات. +اختبارات التكامل لاستبدال المعلمات في معلمات المعالج. +<<<<<<< HEAD +اختبارات شاملة لإطلاق العمليات التدفقية بقيم معلمات مختلفة. +اختبارات واجهة المستخدم لإنشاء النموذج والتحقق من صحة المعلمات. +اختبارات الأداء للعمليات التدفقية التي تحتوي على العديد من المعلمات. +======= +اختبارات شاملة لإطلاق العمليات مع قيم معلمات مختلفة. +اختبارات واجهة المستخدم لإنشاء النموذج والتحقق من صحة المعلمات. +اختبارات الأداء للعمليات التي تحتوي على العديد من المعلمات. +>>>>>>> 82edf2d (New md files from RunPod) +حالات حافة: معلمات مفقودة، وأنواع غير صالحة، وإشارات غير معرفة للمعلمات. + +## خطة الترحيل + +<<<<<<< HEAD +1. يجب أن يستمر النظام في دعم مخططات العمليات التدفقية التي لا تحتوي على معلمات. + معلنة. +2. يجب أن يستمر النظام في دعم العمليات التدفقية التي لا يتم فيها تحديد أي معلمات: + هذا يعمل للعمليات التدفقية التي لا تحتوي على معلمات، وللعمليات التدفقية التي تحتوي على معلمات +======= +1. يجب أن يستمر النظام في دعم نماذج العمليات بدون معلمات + مُعرّفة. +2. يجب أن يستمر النظام في دعم العمليات بدون تحديد معلمات: + هذا يعمل للعمليات التي لا تحتوي على معلمات، وللعمليات التي تحتوي على معلمات +>>>>>>> 82edf2d (New md files from RunPod) + (لديها قيم افتراضية). + +## أسئلة مفتوحة + +<<<<<<< HEAD +س: هل يجب أن تدعم المعلمات كائنات متداخلة معقدة أم يجب الالتزام بأنواع بسيطة؟ +ج: سيتم ترميز قيم المعلمات كسلاسل نصية، لذلك من المحتمل أن نلتزم بالسلاسل النصية. + + +س: هل يجب السماح بوضع عناصر نائب للمعلمات في أسماء قوائم الانتظار أم فقط في + المعلمات؟ +ج: فقط في المعلمات لإزالة عمليات الحقن والحالات الحافة الغريبة. + +س: كيف نتعامل مع التعارضات بين أسماء المعلمات والمتغيرات النظامية مثل + `id` و `class`؟ +ج: من غير المسموح بتحديد المعرف (id) والفئة (class) عند إطلاق عملية تدفقية. + +س: هل يجب أن ندعم المعلمات المحسوبة (المشتقة من معلمات أخرى)؟ +ج: مجرد استبدال السلاسل النصية لإزالة عمليات الحقن والحالات الحافة الغريبة. +======= +س: هل يجب أن تدعم المعلمات كائنات متداخلة معقدة أم تقتصر على الأنواع البسيطة؟ +ج: سيتم ترميز قيم المعلمات كسلاسل نصية، ومن المحتمل أن نلتزم بالسلاسل النصية. + + +س: هل يجب السماح بوضع إشارات المعلمات في أسماء قوائم الانتظار أم فقط في + المعلمات؟ +ج: فقط في المعلمات لإزالة الحقن والحالات الحافة الغريبة. + +س: كيف نتعامل مع التعارضات بين أسماء المعلمات ومتغيرات النظام مثل + `id` و `class`؟ +ج: من غير المسموح بتحديد المعرف (id) والفئة (class) عند إطلاق عملية. + +س: هل يجب أن ندعم المعلمات المحسوبة (المشتقة من معلمات أخرى)؟ +ج: مجرد استبدال السلاسل النصية لإزالة الحقن والحالات الحافة الغريبة. +>>>>>>> 82edf2d (New md files from RunPod) + +## المراجع + +مواصفات مخطط JSON: https://json-schema.org/ +<<<<<<< HEAD +مواصفات تعريف مخطط العمليات التدفقية: docs/tech-specs/flow-class-definition.md +======= +مواصفات تعريف نموذج العملية: docs/tech-specs/flow-class-definition.md +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/flow-configurable-parameters.es.md b/docs/tech-specs/flow-configurable-parameters.es.md new file mode 100644 index 00000000..da07e383 --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.es.md @@ -0,0 +1,644 @@ +--- +layout: default +title: "Especificación Técnica de Parámetros Configurables para Flow Blueprint" +parent: "Spanish (Beta)" +--- + +<<<<<<< HEAD +# Especificación Técnica de Parámetros Configurables para Flow Blueprint + +> **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 la implementación de parámetros configurables para flow blueprints en TrustGraph. Los parámetros permiten a los usuarios personalizar los parámetros del procesador en el momento de la ejecución del flujo, proporcionando valores que reemplazan los marcadores de posición de parámetros en la definición del flow blueprint. + +Los parámetros funcionan a través de la sustitución de variables de plantilla en los parámetros del procesador, de manera similar a cómo funcionan las variables `{id}` y `{class}`, pero con valores proporcionados por el usuario. + +La integración admite cuatro casos de uso principales: + +1. **Selección de Modelo**: Permitir a los usuarios elegir diferentes modelos LLM (por ejemplo, `gemma3:8b`, `gpt-4`, `claude-3`) para los procesadores. +2. **Configuración de Recursos**: Ajustar los parámetros del procesador, como los tamaños de lote, los tamaños de lote y los límites de concurrencia. +======= +# Especificación Técnica de Parámetros Configurables para el Blueprint de Flujo + +## Resumen + +Esta especificación describe la implementación de parámetros configurables para blueprints de flujo en TrustGraph. Los parámetros permiten a los usuarios personalizar los parámetros del procesador en el momento de la ejecución del flujo, proporcionando valores que reemplazan los marcadores de posición de parámetros en la definición del blueprint del flujo. + +Los parámetros funcionan mediante la sustitución de variables de plantilla en los parámetros del procesador, de manera similar a como funcionan las variables `{id}` y `{class}`, pero con valores proporcionados por el usuario. + +La integración admite cuatro casos de uso principales: + +1. **Selección de Modelo**: Permitir a los usuarios elegir diferentes modelos de LLM (por ejemplo, `gemma3:8b`, `gpt-4`, `claude-3`) para los procesadores. +2. **Configuración de Recursos**: Ajustar los parámetros del procesador, como los tamaños de lote, los tamaños de fragmento y los límites de concurrencia. +>>>>>>> 82edf2d (New md files from RunPod) +3. **Ajuste del Comportamiento**: Modificar el comportamiento del procesador a través de parámetros como la temperatura, el número máximo de tokens o los umbrales de recuperación. +4. **Parámetros Específicos del Entorno**: Configurar puntos finales, claves de API o URL específicas de la región para cada implementación. + +## Objetivos + +<<<<<<< HEAD +**Configuración Dinámica del Procesador**: Permitir la configuración en tiempo de ejecución de los parámetros del procesador a través de la sustitución de parámetros. +**Validación de Parámetros**: Proporcionar verificación de tipos y validación para los parámetros en el momento de la ejecución del flujo. +**Valores Predeterminados**: Admitir valores predeterminados sensatos, al tiempo que se permite la sobrescritura para usuarios avanzados. +**Sustitución de Plantillas**: Reemplazar sin problemas los marcadores de posición de parámetros en los parámetros del procesador. +**Integración de la Interfaz de Usuario**: Permitir la entrada de parámetros a través de interfaces de API y de interfaz de usuario. +**Seguridad de Tipos**: Asegurar que los tipos de parámetros coincidan con los tipos de parámetros del procesador esperados. +**Documentación**: Esquemas de parámetros auto-documentados dentro de las definiciones de flow blueprint. +**Compatibilidad con Versiones Anteriores**: Mantener la compatibilidad con los flow blueprints existentes que no utilizan parámetros. + +## Antecedentes + +Los flow blueprints en TrustGraph ahora admiten parámetros de procesador que pueden contener valores fijos o marcadores de posición de parámetros. Esto crea una oportunidad para la personalización en tiempo de ejecución. +======= +**Configuración Dinámica del Procesador**: Permitir la configuración en tiempo de ejecución de los parámetros del procesador mediante la sustitución de parámetros. +**Validación de Parámetros**: Proporcionar verificación de tipos y validación para los parámetros en el momento de la ejecución del flujo. +**Valores Predeterminados**: Admitir valores predeterminados razonables, al tiempo que se permite la sobrescritura para usuarios avanzados. +**Sustitución de Plantillas**: Reemplazar sin problemas los marcadores de posición de parámetros en los parámetros del procesador. +**Integración de la Interfaz de Usuario**: Permitir la entrada de parámetros a través de interfaces de API y de la interfaz de usuario. +**Seguridad de Tipos**: Asegurar que los tipos de parámetros coincidan con los tipos de parámetros del procesador esperados. +**Documentación**: Esquemas de parámetros auto-documentados dentro de las definiciones de blueprints de flujo. +**Compatibilidad con Versiones Anteriores**: Mantener la compatibilidad con los blueprints de flujo existentes que no utilizan parámetros. + +## Antecedentes + +Los blueprints de flujo en TrustGraph ahora admiten parámetros de procesador que pueden contener valores fijos o marcadores de posición de parámetros. Esto crea una oportunidad para la personalización en tiempo de ejecución. +>>>>>>> 82edf2d (New md files from RunPod) + +Los parámetros de procesador actuales admiten: +Valores fijos: `"model": "gemma3:12b"` +Marcadores de posición de parámetros: `"model": "gemma3:{model-size}"` + +Esta especificación define cómo se: +<<<<<<< HEAD +Declaran en las definiciones de flow blueprint. +======= +Declaran en las definiciones de blueprints de flujo. +>>>>>>> 82edf2d (New md files from RunPod) +Validan cuando se ejecutan los flujos. +Sustituyen en los parámetros del procesador. +Exponen a través de las API y la interfaz de usuario. + +Al aprovechar los parámetros de procesador parametrizados, TrustGraph puede: +<<<<<<< HEAD +Reducir la duplicación de flow blueprints mediante el uso de parámetros para las variaciones. +======= +Reducir la duplicación de blueprints de flujo mediante el uso de parámetros para las variaciones. +>>>>>>> 82edf2d (New md files from RunPod) +Permitir a los usuarios ajustar el comportamiento del procesador sin modificar las definiciones. +Admitir configuraciones específicas del entorno a través de los valores de los parámetros. +Mantener la seguridad de tipos a través de la validación del esquema de parámetros. + +## Diseño Técnico + +### Arquitectura + +El sistema de parámetros configurables requiere los siguientes componentes técnicos: + +1. **Definición del Esquema de Parámetros** +<<<<<<< HEAD + Definiciones de parámetros basadas en JSON Schema dentro de los metadatos del flow blueprint. +======= + Definiciones de parámetros basadas en esquemas JSON dentro de los metadatos del blueprint de flujo. +>>>>>>> 82edf2d (New md files from RunPod) + Definiciones de tipos que incluyen cadenas, números, booleanos, enumeraciones y tipos de objetos. + Reglas de validación que incluyen valores mínimos/máximos, patrones y campos obligatorios. + + Módulo: trustgraph-flow/trustgraph/flow/definition.py + +2. **Motor de Resolución de Parámetros** + Validación de parámetros en tiempo de ejecución contra el esquema. + Aplicación de valores predeterminados para los parámetros no especificados. + Inyección de parámetros en el contexto de ejecución del flujo. + Coerción y conversión de tipos según sea necesario. + + Módulo: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **Integración del Almacén de Parámetros** + Recuperación de definiciones de parámetros del almacén de esquemas/configuración. + Almacenamiento en caché de definiciones de parámetros utilizadas con frecuencia. + Validación contra esquemas almacenados centralmente. + + Módulo: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **Extensiones del Lanzador de Flujos** + Extensiones de API para aceptar valores de parámetros durante el lanzamiento del flujo. + Resolución de mapeo de parámetros (nombres de flujo a nombres de definición). + Manejo de errores para combinaciones de parámetros no válidas. + + Módulo: trustgraph-flow/trustgraph/flow/launcher.py + +5. **Formularios de Parámetros de la Interfaz de Usuario** +<<<<<<< HEAD + Generación dinámica de formularios a partir de los metadatos de los parámetros del flujo. + Visualización ordenada de parámetros utilizando el campo `order`. + Etiquetas descriptivas de parámetros utilizando el campo `description`. + Validación de entrada contra las definiciones de tipo de parámetro. +======= + Generación dinámica de formularios a partir de metadatos de parámetros del flujo. + Visualización ordenada de parámetros utilizando el campo `order`. + Etiquetas descriptivas de parámetros utilizando el campo `description`. + Validación de entrada contra definiciones de tipos de parámetros. +>>>>>>> 82edf2d (New md files from RunPod) + Preajustes y plantillas de parámetros. + + Módulo: trustgraph-ui/components/flow-parameters/ + +### Modelos de Datos + +#### Definiciones de Parámetros (Almacenadas en Esquema/Configuración) + +Las definiciones de parámetros se almacenan centralmente en el sistema de esquemas y configuración con el tipo "parameter-type": + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### Diagrama de flujo con referencias de parámetros + +Los diagramas de flujo definen los metadatos de los parámetros con referencias de tipo, descripciones y orden: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +<<<<<<< HEAD +La sección `parameters` mapea los nombres de parámetros específicos del flujo (claves) a objetos de metadatos de parámetros que contienen: +`type`: Referencia a la definición de parámetro definida centralmente (por ejemplo, "llm-model") +`description`: Descripción legible por humanos para su visualización en la interfaz de usuario +`order`: Orden de visualización para los formularios de parámetros (los números más bajos aparecen primero) +`advanced` (opcional): Bandera booleana que indica si este es un parámetro avanzado (por defecto: falso). Cuando se establece en verdadero, la interfaz de usuario puede ocultar este parámetro de forma predeterminada o colocarlo en una sección "Avanzado" +`controlled-by` (opcional): Nombre de otro parámetro que controla el valor de este parámetro cuando está en modo simple. Cuando se especifica, este parámetro hereda su valor del parámetro de control, a menos que se anule explícitamente + +Este enfoque permite: +Definiciones de tipos de parámetros reutilizables en múltiples plantillas de flujo +Gestión y validación centralizadas de tipos de parámetros +Descripciones y orden de parámetros específicos del flujo +Experiencia de interfaz de usuario mejorada con formularios de parámetros descriptivos +Validación de parámetros consistente en todos los flujos +Adición fácil de nuevos tipos de parámetros estándar +Interfaz de usuario simplificada con separación de modo básico/avanzado +Herencia de valores de parámetros para configuraciones relacionadas + +#### Solicitud de inicio de flujo + +La API de inicio de flujo acepta parámetros utilizando los nombres de parámetros del flujo: +======= +La sección `parameters` asigna nombres de parámetros específicos del flujo (claves) a objetos de metadatos de parámetros que contienen: +`type`: Referencia a la definición de parámetro definida centralmente (por ejemplo, "llm-model"). +`description`: Descripción legible por humanos para su visualización en la interfaz de usuario. +`order`: Orden de visualización para los formularios de parámetros (los números más bajos aparecen primero). +`advanced` (opcional): Marcador booleano que indica si este es un parámetro avanzado (por defecto: falso). Cuando se establece en verdadero, la interfaz de usuario puede ocultar este parámetro de forma predeterminada o colocarlo en una sección "Avanzado". +`controlled-by` (opcional): Nombre de otro parámetro que controla el valor de este parámetro cuando está en modo simple. Cuando se especifica, este parámetro hereda su valor del parámetro de control, a menos que se anule explícitamente. + +Este enfoque permite: +Definiciones de tipos de parámetros reutilizables en múltiples plantillas de flujo. +Gestión y validación centralizadas de tipos de parámetros. +Descripciones y orden de parámetros específicos del flujo. +Experiencia de interfaz de usuario mejorada con formularios de parámetros descriptivos. +Validación de parámetros coherente en todos los flujos. +Adición fácil de nuevos tipos de parámetros estándar. +Interfaz de usuario simplificada con separación de modo básico/avanzado. +Herencia de valores de parámetros para configuraciones relacionadas. + +#### Solicitud de inicio del flujo + +La API de inicio del flujo acepta parámetros utilizando los nombres de parámetros del flujo: +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +Nota: En este ejemplo, `llm-rag-model` no se proporciona explícitamente, pero heredará el valor "claude-3" de `llm-model` debido a su relación `controlled-by`. De manera similar, `chunk-overlap` podría heredar un valor calculado basado en `chunk-size`. + +<<<<<<< HEAD +El sistema realizará lo siguiente: +1. Extraer metadatos de parámetros de la definición de la plantilla de flujo. +======= +El sistema realizará las siguientes acciones: +1. Extraer metadatos de parámetros de la definición de la plantilla del flujo. +>>>>>>> 82edf2d (New md files from RunPod) +2. Mapear los nombres de los parámetros del flujo a sus definiciones de tipo (por ejemplo, `llm-model` → tipo `llm-model`). +3. Resolver las relaciones de control (por ejemplo, `llm-rag-model` hereda de `llm-model`). +4. Validar los valores proporcionados por el usuario y los valores heredados en función de las definiciones de tipo de los parámetros. +5. Sustituir los valores resueltos en los parámetros del procesador durante la instanciación del flujo. + +### Detalles de implementación + +#### Proceso de resolución de parámetros + +Cuando se inicia un flujo, el sistema realiza los siguientes pasos de resolución de parámetros: + +1. **Carga de la plantilla del flujo**: Cargar la definición de la plantilla del flujo y extraer los metadatos de los parámetros. +2. **Extracción de metadatos**: Extraer `type`, `description`, `order`, `advanced` y `controlled-by` para cada parámetro definido en la sección `parameters` de la plantilla del flujo. +3. **Búsqueda de la definición de tipo**: Para cada parámetro en la plantilla del flujo: +<<<<<<< HEAD + Recuperar la definición de tipo del parámetro del almacén de esquema/configuración utilizando el campo `type`. +======= + Recuperar la definición de tipo del parámetro del almacén de esquemas/configuración utilizando el campo `type`. +>>>>>>> 82edf2d (New md files from RunPod) + Las definiciones de tipo se almacenan con el tipo "parameter-type" en el sistema de configuración. + Cada definición de tipo contiene el esquema del parámetro, el valor predeterminado y las reglas de validación. +4. **Resolución del valor predeterminado**: + Para cada parámetro definido en la plantilla del flujo: + Comprobar si el usuario ha proporcionado un valor para este parámetro. + Si no se proporciona ningún valor del usuario, utilizar el valor `default` de la definición de tipo del parámetro. + Crear un mapa de parámetros completo que contenga tanto los valores proporcionados por el usuario como los valores predeterminados. +5. **Resolución de la herencia de parámetros** (relaciones de control): + Para los parámetros con el campo `controlled-by`, comprobar si se ha proporcionado un valor explícito. + Si no se proporciona ningún valor explícito, heredar el valor del parámetro de control. + Si el parámetro de control también no tiene valor, utilizar el valor predeterminado de la definición de tipo. + Validar que no existan dependencias circulares en las relaciones `controlled-by`. +6. **Validación**: Validar el conjunto completo de parámetros (proporcionados por el usuario, predeterminados y heredados) en función de las definiciones de tipo. +7. **Almacenamiento**: Almacenar el conjunto completo de parámetros resueltos con la instancia del flujo para su trazabilidad. +8. **Sustitución de plantillas**: Reemplazar los marcadores de posición de parámetros en los parámetros del procesador con los valores resueltos. +9. **Instanciación del procesador**: Crear procesadores con los parámetros sustituidos. + +**Notas importantes de implementación**: +El servicio de flujo DEBE combinar los parámetros proporcionados por el usuario con los valores predeterminados de las definiciones de tipo de parámetros. +El conjunto completo de parámetros (incluidos los valores predeterminados aplicados) DEBE almacenarse con el flujo para su trazabilidad. +La resolución de parámetros se realiza al inicio del flujo, no en el momento de la instanciación del procesador. +Los parámetros obligatorios sin valores predeterminados DEBEN provocar que el inicio del flujo falle con un mensaje de error claro. + +<<<<<<< HEAD +#### Herencia de parámetros con control +======= +#### Herencia de parámetros con "controlled-by" +>>>>>>> 82edf2d (New md files from RunPod) + +El campo `controlled-by` permite la herencia de valores de parámetros, lo que es especialmente útil para simplificar las interfaces de usuario al tiempo que se mantiene la flexibilidad: + +**Escenario de ejemplo**: +El parámetro `llm-model` controla el modelo LLM primario. +El parámetro `llm-rag-model` tiene el valor `"controlled-by": "llm-model"`. +En el modo simple, establecer `llm-model` en "gpt-4" establece automáticamente `llm-rag-model` en "gpt-4" también. +En el modo avanzado, los usuarios pueden anular `llm-rag-model` con un valor diferente. + +**Reglas de resolución**: +1. Si un parámetro tiene un valor proporcionado explícitamente, utilizar ese valor. +2. Si no hay ningún valor explícito y `controlled-by` está establecido, utilizar el valor del parámetro de control. +3. Si el parámetro de control no tiene valor, recurrir al valor predeterminado de la definición de tipo. +4. Las dependencias circulares en las relaciones `controlled-by` dan como resultado un error de validación. + +**Comportamiento de la interfaz de usuario**: +En el modo básico/simple: Los parámetros con `controlled-by` pueden estar ocultos o mostrarse como de solo lectura con el valor heredado. +En el modo avanzado: Se muestran todos los parámetros y se pueden configurar individualmente. +Cuando cambia un parámetro de control, los parámetros dependientes se actualizan automáticamente, a menos que se anulen explícitamente. + +<<<<<<< HEAD +#### Integración de Pulsar +======= +#### Integración con Pulsar +>>>>>>> 82edf2d (New md files from RunPod) + +1. **Operación de inicio de flujo** + La operación de inicio de flujo de Pulsar debe aceptar un campo `parameters` que contenga un mapa de valores de parámetros. + El esquema de Pulsar para la solicitud de inicio de flujo debe actualizarse para incluir el campo opcional `parameters`. + Ejemplo de solicitud: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **Operación Get-Flow** + El esquema de Pulsar para la respuesta de get-flow debe actualizarse para incluir el campo `parameters` + Esto permite a los clientes recuperar los valores de los parámetros que se utilizaron cuando se inició el flujo. + Ejemplo de respuesta: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### Implementación del Servicio de Flujo + +El servicio de configuración de flujo (`trustgraph-flow/trustgraph/config/service/flow.py`) requiere las siguientes mejoras: + +1. **Función de Resolución de Parámetros** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + Esta función debe: + Extraer los metadatos de los parámetros de la sección `parameters` del plano de flujo. +<<<<<<< HEAD + Para cada parámetro, obtener la definición de tipo de la tienda de configuración. +======= + Para cada parámetro, obtener la definición de tipo del almacén de configuración. +>>>>>>> 82edf2d (New md files from RunPod) + Aplicar los valores predeterminados para cualquier parámetro que no sea proporcionado por el usuario. + Manejar las relaciones de herencia de `controlled-by`. + Devolver el conjunto de parámetros completo. + +2. **Método `handle_start_flow` Modificado** + Llamar a `resolve_parameters` después de cargar el plano de flujo. + Utilizar el conjunto de parámetros resuelto completo para la sustitución de plantillas. + Almacenar el conjunto de parámetros completo (no solo los proporcionados por el usuario) con el flujo. + Validar que todos los parámetros requeridos tengan valores. + +3. **Obtención del Tipo de Parámetro** + Las definiciones de tipo de parámetro se almacenan en la configuración con el tipo "parameter-type". +<<<<<<< HEAD + Cada definición de tipo contiene un esquema, un valor predeterminado y reglas de validación. +======= + Cada definición de tipo contiene el esquema, el valor predeterminado y las reglas de validación. +>>>>>>> 82edf2d (New md files from RunPod) + Almacenar en caché los tipos de parámetro utilizados con frecuencia para reducir las búsquedas en la configuración. + +#### Integración del Sistema de Configuración + +3. **Almacenamiento de Objetos de Flujo** +<<<<<<< HEAD + Cuando un flujo se agrega al sistema de configuración por el componente de flujo en el administrador de configuración, el objeto de flujo debe incluir los valores de parámetros resueltos. + El administrador de configuración debe almacenar tanto los parámetros originales proporcionados por el usuario como los valores resueltos (con los valores predeterminados aplicados). + Los objetos de flujo en el sistema de configuración deben incluir: + `parameters`: Los valores de parámetros resueltos finales utilizados para el flujo. +======= + Cuando un flujo se agrega al sistema de configuración por el componente de flujo en el administrador de configuración, el objeto de flujo debe incluir los valores de parámetro resueltos. + El administrador de configuración debe almacenar tanto los parámetros originales proporcionados por el usuario como los valores resueltos (con los valores predeterminados aplicados). + Los objetos de flujo en el sistema de configuración deben incluir: + `parameters`: Los valores de parámetro resueltos finales utilizados para el flujo. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Integración de la CLI + +4. **Comandos de la CLI de la Biblioteca** + Los comandos de la CLI que inician flujos necesitan soporte de parámetros: +<<<<<<< HEAD + Aceptar valores de parámetros a través de indicadores de línea de comandos o archivos de configuración. +======= + Aceptar valores de parámetro a través de indicadores de línea de comandos o archivos de configuración. +>>>>>>> 82edf2d (New md files from RunPod) + Validar los parámetros contra las definiciones del plano de flujo antes de la presentación. + Soporte para la entrada de archivos de parámetros (JSON/YAML) para conjuntos de parámetros complejos. + + Los comandos de la CLI que muestran flujos deben mostrar información de parámetros: +<<<<<<< HEAD + Mostrar los valores de parámetros utilizados cuando se inició el flujo. + Mostrar los parámetros disponibles para un plano de flujo. + Mostrar los esquemas y valores predeterminados de validación de parámetros. +======= + Mostrar los valores de parámetro utilizados cuando se inició el flujo. + Mostrar los parámetros disponibles para un plano de flujo. + Mostrar los esquemas de validación y los valores predeterminados de los parámetros. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Integración de la Clase Base del Procesador + +5. **Soporte de ParameterSpec** + Las clases base del procesador deben admitir la sustitución de parámetros a través del mecanismo ParametersSpec existente. + La clase ParametersSpec (ubicada en el mismo módulo que ConsumerSpec y ProducerSpec) debe mejorarse si es necesario para admitir la sustitución de plantillas de parámetros. +<<<<<<< HEAD + Los procesadores deben poder invocar ParametersSpec para configurar sus parámetros con los valores de parámetros resueltos en el momento del lanzamiento del flujo. + La implementación de ParametersSpec debe: + Aceptar configuraciones de parámetros que contengan marcadores de posición de parámetros (por ejemplo, `{model}`, `{temperature}`). + Admitir la sustitución de parámetros en tiempo de ejecución cuando se instancia el procesador. + Validar que los valores sustituidos coincidan con los tipos y restricciones esperados. + Proporcionar manejo de errores para referencias de parámetros faltantes o no válidos. +======= + Los procesadores deben poder invocar ParametersSpec para configurar sus parámetros con los valores de parámetro resueltos en el momento del inicio del flujo. + La implementación de ParametersSpec debe: + Aceptar configuraciones de parámetros que contengan marcadores de posición de parámetros (por ejemplo, `{model}`, `{temperature}`). + Admitir la sustitución de parámetros en tiempo de ejecución cuando se instancia el procesador. + Validar que los valores sustituidos coincidan con los tipos y las restricciones esperadas. + Proporcionar el manejo de errores para las referencias de parámetros faltantes o no válidas. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Reglas de Sustitución + +Los parámetros utilizan el formato `{parameter-name}` en los parámetros del procesador. +Los nombres de los parámetros en los parámetros coinciden con las claves en la sección `parameters` del flujo. +La sustitución se produce junto con la sustitución de `{id}` y `{class}`. +<<<<<<< HEAD +Las referencias de parámetros no válidas dan como resultado errores en el momento del lanzamiento. +La validación de tipos se basa en la definición de parámetro almacenada de forma centralizada. +**IMPORTANTE**: Todos los valores de parámetros se almacenan y transmiten como cadenas. +======= +Las referencias de parámetros no válidas dan como resultado errores en el momento del inicio. +La validación de tipos se basa en la definición de parámetro almacenada de forma centralizada. +**IMPORTANTE**: Todos los valores de los parámetros se almacenan y transmiten como cadenas. +>>>>>>> 82edf2d (New md files from RunPod) + Los números se convierten a cadenas (por ejemplo, `0.7` se convierte en `"0.7"`). + Los booleanos se convierten a cadenas en minúsculas (por ejemplo, `true` se convierte en `"true"`). + Esto es requerido por el esquema de Pulsar que define `parameters = Map(String())`. + +Ejemplo de resolución: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## Estrategia de Pruebas + +Pruebas unitarias para la validación del esquema de parámetros. +Pruebas de integración para la sustitución de parámetros en los parámetros del procesador. +Pruebas de extremo a extremo para el lanzamiento de flujos con diferentes valores de parámetros. +Pruebas de la interfaz de usuario para la generación y validación de formularios de parámetros. +Pruebas de rendimiento para flujos con muchos parámetros. +<<<<<<< HEAD +Casos extremos: parámetros faltantes, tipos no válidos, referencias de parámetros no definidos. + +## Plan de Migración + +1. El sistema debe seguir soportando planos de flujo sin parámetros + declarados. +2. El sistema debe seguir soportando flujos sin parámetros especificados: +======= +Casos extremos: parámetros faltantes, tipos inválidos, referencias de parámetros no definidos. + +## Plan de Migración + +1. El sistema debe continuar admitiendo planos de flujo sin parámetros + declarados. +2. El sistema debe continuar admitiendo flujos sin parámetros especificados: +>>>>>>> 82edf2d (New md files from RunPod) + Esto funciona para flujos sin parámetros y para flujos con parámetros + (que tienen valores predeterminados). + +## Preguntas Abiertas + +<<<<<<< HEAD +P: ¿Deben los parámetros soportar objetos anidados complejos o limitarse a tipos simples? +======= +P: ¿Deben los parámetros admitir objetos anidados complejos o limitarse a tipos simples? +>>>>>>> 82edf2d (New md files from RunPod) +R: Los valores de los parámetros se codificarán como cadenas, por lo que probablemente + queremos limitarnos a cadenas. + +P: ¿Se deben permitir los marcadores de posición de parámetros en los nombres de las colas o solo en + los parámetros? +R: Solo en los parámetros para evitar inyecciones extrañas y casos límite. + +P: ¿Cómo manejar los conflictos entre los nombres de los parámetros y las variables del sistema como + `id` y `class`? +R: No es válido especificar "id" y "class" al iniciar un flujo. + +<<<<<<< HEAD +P: ¿Debemos soportar parámetros calculados (derivados de otros parámetros)? +======= +P: ¿Debemos admitir parámetros calculados (derivados de otros parámetros)? +>>>>>>> 82edf2d (New md files from RunPod) +R: Solo la sustitución de cadenas para evitar inyecciones extrañas y casos límite. + +## Referencias + +Especificación de JSON Schema: https://json-schema.org/ +<<<<<<< HEAD +Especificación de la Definición del Plano de Flujo: docs/tech-specs/flow-class-definition.md +======= +Especificación de la definición del plano de flujo: docs/tech-specs/flow-class-definition.md +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/flow-configurable-parameters.he.md b/docs/tech-specs/flow-configurable-parameters.he.md new file mode 100644 index 00000000..73884934 --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.he.md @@ -0,0 +1,590 @@ +--- +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. + +## סקירה כללית + +<<<<<<< HEAD +מפרט זה מתאר את יישום הפרמטרים הניתנים להגדרה עבור תבניות זרימה ב-TrustGraph. פרמטרים מאפשרים למשתמשים להתאים אישית את פרמטרי המעבד בזמן הפעלת הזרימה על ידי מתן ערכים המחליפים את מקומות הפרמטרים בהגדרת תבנית הזרימה. +======= +מפרט זה מתאר את יישום הפרמטרים הניתנים להגדרה עבור תבניות זרימה ב-TrustGraph. פרמטרים מאפשרים למשתמשים להתאים אישית את פרמטרי המעבד בזמן הפעלת הזרימה על ידי מתן ערכים שמחליפים את מקומות הפרמטרים בהגדרת תבנית הזרימה. +>>>>>>> 82edf2d (New md files from RunPod) + +פרמטרים פועלים באמצעות החלפת משתנים בתבניות בפרמטרי המעבד, בדומה לאופן שבו משתנים `{id}` ו-`{class}` פועלים, אך עם ערכים שמסופקים על ידי המשתמש. + +האינטגרציה תומכת בארבעה תרחישי שימוש עיקריים: + +1. **בחירת מודל**: לאפשר למשתמשים לבחור מודלים שונים של LLM (לדוגמה, `gemma3:8b`, `gpt-4`, `claude-3`) עבור מעבדים. +2. **תצורת משאבים**: התאמת פרמטרי מעבד כגון גודל חבילות, גודל אצווה ומגבלות מקביליות. +<<<<<<< HEAD +3. **כוונון התנהגות**: שינוי התנהגות המעבד באמצעות פרמטרים כגון טמפרטורה, מקסימום טוקנים או ספי תאחזור. +======= +3. **כוונון התנהגות**: שינוי התנהגות המעבד באמצעות פרמטרים כגון טמפרטורה, מקסימום טוקנים או ספי הצעת מחיר. +>>>>>>> 82edf2d (New md files from RunPod) +4. **פרמטרים ספציפיים לסביבה**: הגדרת נקודות קצה, מפתחות API או כתובות URL ספציפיות לאזור עבור כל פריסה. + +## מטרות + +**תצורת מעבד דינמית**: לאפשר תצורת זמן ריצה של פרמטרי מעבד באמצעות החלפת פרמטרים. +**אימות פרמטרים**: לספק בדיקת סוג ואימות עבור פרמטרים בזמן הפעלת הזרימה. +**ערכי ברירת מחדל**: לתמוך בערכי ברירת מחדל הגיוניים תוך מתן אפשרות לשנות אותם עבור משתמשים מתקדמים. +**החלפת תבניות**: להחליף בצורה חלקה את מקומות הפרמטרים בפרמטרי המעבד. +**אינטגרציה עם ממשק משתמש**: לאפשר הזנת פרמטרים באמצעות ממשקי API וממשקי משתמש. +**בטיחות סוגים**: להבטיח שטיפוסי הפרמטרים תואמים לטיפוסי פרמטרי המעבד הצפויים. +<<<<<<< HEAD +**תיעוד**: סכימות פרמטרים המתועדות באופן עצמי בתוך הגדרות תבניות הזרימה. +======= +**תיעוד**: סכימות פרמטרים המתועדות באופן עצמי בתוך הגדרות תבניות זרימה. +>>>>>>> 82edf2d (New md files from RunPod) +**תאימות לאחור**: לשמור על תאימות לתבניות זרימה קיימות שאינן משתמשות בפרמטרים. + +## רקע + +<<<<<<< HEAD +תבניות זרימה ב-TrustGraph תומכות כעת בפרמטרי מעבד שניתן להכיל ערכים קבועים או מקומות שמירת פרמטרים. זה יוצר הזדמנות להתאמה אישית בזמן ריצה. + +פרמטרי מעבד קיימים תומכים ב: +ערכים קבועים: `"model": "gemma3:12b"` +מקומות שמירת פרמטרים: `"model": "gemma3:{model-size}"` +======= +תבניות זרימה ב-TrustGraph תומכות כעת בפרמטרי מעבד שניתן להכיל ערכים קבועים או מקומות פרמטרים. זה יוצר הזדמנות להתאמה אישית בזמן ריצה. + +פרמטרי מעבד קיימים תומכים ב: +ערכים קבועים: `"model": "gemma3:12b"` +מקומות פרמטרים: `"model": "gemma3:{model-size}"` +>>>>>>> 82edf2d (New md files from RunPod) + +מפרט זה מגדיר כיצד פרמטרים: +מוצהרים בהגדרות תבניות זרימה +מאומתים כאשר זרימות מופעלות +מוכנסים לפרמטרי מעבד +נחשפים באמצעות ממשקי API וממשקי משתמש + +<<<<<<< HEAD +על ידי שימוש בפרמטרי מעבד מוגדרים, TrustGraph יכולה: +======= +על ידי שימוש בפרמטרי מעבד מותאמים אישית, TrustGraph יכולה: +>>>>>>> 82edf2d (New md files from RunPod) +להפחית שכפול של תבניות זרימה על ידי שימוש בפרמטרים עבור וריאציות +לאפשר למשתמשים לכוונן את התנהגות המעבד מבלי לשנות הגדרות +לתמוך בתצורות ספציפיות לסביבה באמצעות ערכי פרמטרים +לשמור על בטיחות סוגים באמצעות אימות סכימת פרמטרים + +## עיצוב טכני + +### ארכיטקטורה + +מערכת הפרמטרים הניתנים להגדרה דורשת את הרכיבים הטכניים הבאים: + +1. **הגדרת סכימת פרמטרים** +<<<<<<< HEAD + הגדרות פרמטרים מבוססות סכימת JSON בתוך מטא-נתונים של תבניות זרימה + הגדרות סוגים כולל מחרוזות, מספרים, בוליאנים, enum ואובייקטים + כללי אימות כולל ערכים מינימליים/מקסימליים, תבניות ושדות חובה +======= + הגדרות פרמטרים המבוססות על סכימת JSON בתוך מטא-נתונים של תבניות זרימה + הגדרות סוגים כולל מחרוזות, מספרים, בוליאנים, enum ואובייקטים + כללי אימות כולל ערכים מינימליים/מקסימליים, תבניות ושדות נדרשים +>>>>>>> 82edf2d (New md files from RunPod) + + מודול: trustgraph-flow/trustgraph/flow/definition.py + +2. **מנוע פתרון פרמטרים** + אימות פרמטרים בזמן ריצה מול סכימה + יישום ערכי ברירת מחדל עבור פרמטרים לא מוגדרים + הכנסת פרמטרים להקשר ביצוע הזרימה + המרה והסבה של סוגים לפי הצורך + + מודול: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **אינטגרציה עם מאגר פרמטרים** + אחזור הגדרות פרמטרים ממערכת סכימות/תצורה + שמירת פרמטרי הגדרה בשימוש תכוף + אימות מול סכימות המאוחסנות באופן מרכזי + + מודול: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **הרחבות משגר זרימה** + הרחבות API לקבלת ערכי פרמטרים במהלך הפעלת זרימה + רזולוציית מיפוי פרמטרים (שמות זרימה לשמות הגדרה) + טיפול בשגיאות עבור שילובים לא חוקיים של פרמטרים + + מודול: trustgraph-flow/trustgraph/flow/launcher.py + +5. **טפסי פרמטרים של ממשק משתמש** + יצירת טפסים דינמיים ממטא-נתוני פרמטרים של זרימה + תצוגה מסודרת של פרמטרים באמצעות שדה `order` + תגיות תיאוריות של פרמטרים באמצעות שדה `description` + אימות קלט מול הגדרות סוג פרמטרים +<<<<<<< HEAD + ערכות מקדימות ותבניות פרמטרים +======= + ערכות חכמות ותבניות פרמטרים +>>>>>>> 82edf2d (New md files from RunPod) + + מודול: trustgraph-ui/components/flow-parameters/ + +### מודלים של נתונים + +#### הגדרות פרמטרים (מאוחסנות בסכימה/תצורה) + +הגדרות פרמטרים מאוחסנות באופן מרכזי במערכת הסכימות והתצורה עם סוג "parameter-type": +<<<<<<< HEAD +פלט חוזה (יש לעקוב בדיוק אחר הפורמט הבא). +======= +פלט חוזה (יש לעקוב אחר הפורמט המדויק). +>>>>>>> 82edf2d (New md files from RunPod) +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### תרשים זרימה עם הפניות לפרמטרים + +תרשימי זרימה מגדירים מטא-נתונים של פרמטרים עם הפניות לסוג, תיאורים וסדר: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +הסעיף `parameters` ממפה שמות פרמטרים ספציפיים לזרימה (מפתחות) לאובייקטי מטא-נתונים של פרמטרים המכילים: +`type`: הפניה להגדרה מרכזית של פרמטר (לדוגמה, "llm-model") +`description`: תיאור קריא לבני אדם לצורך הצגה בממשק המשתמש +`order`: סדר הצגה של טפסי פרמטרים (מספרים נמוכים יותר מופיעים ראשונים) +`advanced` (אופציונלי): דגל בוליאני המציין אם זהו פרמטר מתקדם (ברירת מחדל: false). כאשר מוגדר כ-true, הממשק המשתמש עשוי להסתיר את הפרמטר הזה כברירת מחדל או למקם אותו בסעיף "מתקדם" +`controlled-by` (אופציונלי): שם של פרמטר אחר השולט בערך של הפרמטר הזה במצב פשוט. כאשר מצוין, פרמטר זה יורש את הערך שלו מהפרמטר השולט, אלא אם כן הוא מוגדר במפורש אחרת + +גישה זו מאפשרת: +הגדרות סוג פרמטרים שניתן לעשות בהן שימוש חוזר במספר תבניות זרימה +ניהול ובדיקת תוקף מרכזיים של סוגי פרמטרים +תיאורים וסדר הצגה ספציפיים לזרימה של פרמטרים +חוויית ממשק משתמש משופרת עם טפסי פרמטרים תיאוריים +בדיקת תוקף עקבית של פרמטרים בכל הזרימות +הוספה קלה של סוגי פרמטרים סטנדרטיים חדשים +ממשק משתמש מפושט עם הפרדה בין מצב בסיסי/מתקדם +ירושת ערכי פרמטרים עבור הגדרות קשורות + +#### בקשת הפעלת זרימה + +ממשק ה-API להפעלת זרימה מקבל פרמטרים באמצעות שמות הפרמטרים של הזרימה: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +<<<<<<< HEAD +הערה: בדוגמה זו, `llm-rag-model` אינו מסופק באופן מפורש, אך הוא יירש את הערך "claude-3" מ-`llm-model` בשל הקשר `controlled-by` שלו. באופן דומה, `chunk-overlap` יכול לרשת ערך מחושב המבוסס על `chunk-size`. +======= +הערה: בדוגמה זו, `llm-rag-model` אינו מסופק באופן מפורש, אך הוא יירש את הערך "claude-3" מ-`llm-model` עקב הקשר `controlled-by` שלו. באופן דומה, `chunk-overlap` יכול לרשת ערך מחושב המבוסס על `chunk-size`. +>>>>>>> 82edf2d (New md files from RunPod) + +המערכת תבצע את הפעולות הבאות: +1. חילוץ מטא-נתונים של פרמטרים מהגדרת תבנית זרימה +2. מיפוי שמות פרמטרים של זרימה להגדרות הסוג שלהם (לדוגמה, `llm-model` → סוג `llm-model`) +3. פתרון קשרים "שולט ב" (controlled-by) (לדוגמה, `llm-rag-model` יורש מ-`llm-model`) +4. אימות ערכים שסופקו על ידי המשתמש וערכים שירשו בהתאם להגדרות הסוג של הפרמטרים +<<<<<<< HEAD +5. החלפת ערכים שפתורים לתוך פרמטרים של מעבדים במהלך יצירת זרימה +======= +5. החלפת ערכים פתורים לפרמטרים של מעבדים במהלך יצירת זרימה +>>>>>>> 82edf2d (New md files from RunPod) + +### פרטי יישום + +#### תהליך פתרון פרמטרים + +כאשר זרימה מתחילה, המערכת מבצעת את שלבי פתרון הפרמטרים הבאים: + +1. **טעינת תבנית זרימה**: טעינת הגדרת תבנית זרימה וחילוץ מטא-נתונים של פרמטרים +2. **חילוץ מטא-נתונים**: חילוץ `type`, `description`, `order`, `advanced` ו-`controlled-by` עבור כל פרמטר המוגדר בתבנית הזרימה בסעיף `parameters` +3. **חיפוש הגדרת סוג**: עבור כל פרמטר בתבנית הזרימה: +<<<<<<< HEAD + אחזור הגדרת הסוג של הפרמטר ממחסן הסכימה/התצורה באמצעות השדה `type` + הגדרות הסוג מאוחסנות עם הסוג "parameter-type" במערכת התצורה +======= + אחזור הגדרת הסוג של הפרמטר ממחסן הסכימה/הגדרות באמצעות השדה `type` + הגדרות הסוג מאוחסנות עם הסוג "parameter-type" במערכת ההגדרות +>>>>>>> 82edf2d (New md files from RunPod) + כל הגדרת סוג מכילה את הסכימה של הפרמטר, ערך ברירת מחדל וכללי אימות +4. **פתרון ערך ברירת מחדל**: + עבור כל פרמטר המוגדר בתבנית הזרימה: + בדיקה האם המשתמש סיפק ערך עבור פרמטר זה + אם לא סופק ערך על ידי המשתמש, השתמש בערך `default` מהגדרת סוג הפרמטר +<<<<<<< HEAD + יצירת מפת פרמטרים שלמה המכילה הן ערכים שסופקו על ידי המשתמש והן ערכי ברירת מחדל +5. **פתרון ירושה של פרמטרים** (קשרים "שולט ב"): + עבור פרמטרים עם שדה `controlled-by`, בדוק האם סופק ערך באופן מפורש + אם לא סופק ערך מפורש, יורשים את הערך מהפרמטר השולט + אם גם לפרמטר השולט אין ערך, משתמשים בברירת המחדל מהגדרת הסוג + אימות שאין תלות מעגלית בקשרי `controlled-by` +6. **אימות**: אימות קבוצת הפרמטרים השלמה (ערכים שסופקו על ידי המשתמש, ברירות מחדל וערכים שירשו) בהתאם להגדרות הסוג +7. **אחסון**: אחסון קבוצת הפרמטרים השלמה שפתורה עם מופע הזרימה לצורך ביקורת +8. **החלפת תבניות**: החלפת מקומות שמורות של פרמטרים בפרמטרים של מעבדים עם ערכים שפתורים +======= + יצירת מפת פרמטרים שלמה המכילה גם ערכים שסופקו על ידי המשתמש וגם ערכי ברירת מחדל +5. **פתרון ירושה של פרמטרים** (קשרים "שולט ב"): + עבור פרמטרים עם שדה `controlled-by`, בדוק האם סופק ערך באופן מפורש + אם לא סופק ערך מפורש, ירוש את הערך מהפרמטר השולט + אם גם לפרמטר השולט אין ערך, השתמש בברירת המחדל מהגדרת הסוג + ודא שאין תלות מעגלית בקשרי `controlled-by` +6. **אימות**: אימות קבוצת הפרמטרים השלמה (ערכים שסופקו על ידי המשתמש, ברירות מחדל וערכים שירשו) בהתאם להגדרות הסוג +7. **אחסון**: אחסון קבוצת הפרמטרים הפתורים השלמה עם מופע הזרימה לצורך ביקורת +8. **החלפת תבניות**: החלפת מקומות שמורות של פרמטרים בפרמטרים של מעבדים עם ערכים פתורים +>>>>>>> 82edf2d (New md files from RunPod) +9. **יצירת מעבדים**: יצירת מעבדים עם פרמטרים שהוחלפו + +**הערות חשובות ליישום:** +שירות הזרימה חייב למזג פרמטרים שסופקו על ידי המשתמש עם ברירות מחדל מהגדרות סוג הפרמטרים +קבוצת הפרמטרים השלמה (כולל ברירות המחדל המיושמות) חייבת להיות מאוחסנת עם הזרימה לצורך מעקב +פתרון פרמטרים מתרחש בזמן התחלת הזרימה, ולא בזמן יצירת המעבד +<<<<<<< HEAD +פרמטרים חסרים שנדרשים ללא ברירות מחדל חייבים לגרום לכישלון התחלת הזרימה עם הודעת שגיאה ברורה +======= +פרמטרים חסרים הדורשים ברירות מחדל חייבים לגרום לכישלון התחלת הזרימה עם הודעת שגיאה ברורה +>>>>>>> 82edf2d (New md files from RunPod) + +#### ירושת פרמטרים עם "שולט ב" + +השדה `controlled-by` מאפשר ירושת ערכי פרמטרים, שימושי במיוחד לפשט ממשקי משתמש תוך שמירה על גמישות: + +**תרחיש לדוגמה**: +פרמטר `llm-model` שולט במודל LLM הראשי +פרמטר `llm-rag-model` מכיל `"controlled-by": "llm-model"` +במצב פשוט, הגדרת `llm-model` ל-"gpt-4" מגדירה אוטומטית גם את `llm-rag-model` ל-"gpt-4" +במצב מתקדם, משתמשים יכולים לדרוס את `llm-rag-model` עם ערך שונה + +**כללי פתרון**: +1. אם לפרמטר יש ערך שסופק באופן מפורש, השתמש בערך זה +2. אם אין ערך מפורש ו-`controlled-by` מוגדר, השתמש בערך של הפרמטר השולט +3. אם לפרמטר השולט אין ערך, חזור לברירת המחדל מהגדרת הסוג +4. תלות מעגלית בקשרי `controlled-by` גורמת לשגיאת אימות + +**התנהגות ממשק משתמש**: +במצב בסיסי/פשוט: פרמטרים עם `controlled-by` עשויים להיות מוסתרים או מוצגים כקריאה בלבד עם ערך שירש +במצב מתקדם: מוצגים כל הפרמטרים וניתן להגדיר אותם באופן אינדיבידואלי +<<<<<<< HEAD +כאשר פרמטר שולט משתנה, פרמטרים תלויים מתעדכנים אוטומטית אלא אם כן הם נדחפים באופן מפורש +======= +כאשר פרמטר שולט משתנה, פרמטרים תלויים מתעדכנים אוטומטית אלא אם כן הם דורסים באופן מפורש +>>>>>>> 82edf2d (New md files from RunPod) + +#### אינטגרציה עם Pulsar + +1. **פעולת התחלת זרימה** + פעולת התחלת הזרימה של Pulsar צריכה לקבל שדה `parameters` המכיל מפה של ערכי פרמטרים + הסכימה של בקשת התחלת הזרימה של Pulsar חייבת להיות מעודכנת כדי לכלול את השדה האופציונלי `parameters` + דוגמת בקשה: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **פעולת Get-Flow** + הסכימה של Pulsar עבור תגובת ה-get-flow חייבת להיות מעודכנת כדי לכלול את השדה `parameters` + זה מאפשר ללקוחות לשלוף את ערכי הפרמטרים ששימשו כאשר ה-flow הופעל + דוגמה לתגובה: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### יישום שירות זרימה + +שירות תצורת הזרימה (`trustgraph-flow/trustgraph/config/service/flow.py`) דורש את השיפורים הבאים: + +1. **פונקציית פתרון פרמטרים** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + פונקציה זו צריכה: +<<<<<<< HEAD + לחלץ מטא-נתונים של פרמטרים מתוך סעיף `parameters` של תוכנית העבודה (blueprint). + עבור כל פרמטר, לשלוף את הגדרת הסוג שלו ממאגר התצורה. + להחיל ערכי ברירת מחדל עבור כל פרמטרים שאינם מסופקים על ידי המשתמש. +======= + לחלץ מטא-נתונים של פרמטרים מסעיף `parameters` של תוכנית העבודה (blueprint). + עבור כל פרמטר, לשלוף את הגדרת הסוג שלו ממאגר התצורה. + להחיל ערכי ברירת מחדל עבור כל פרמטרים שלא סופקו על ידי המשתמש. +>>>>>>> 82edf2d (New md files from RunPod) + לטפל ביחסי ירושה `controlled-by`. + להחזיר את קבוצת הפרמטרים השלמה. + +2. **שיטה `handle_start_flow` שעברה שינוי** + לקרוא ל-`resolve_parameters` לאחר טעינת תוכנית העבודה. + להשתמש בקבוצת הפרמטרים המפורטת והפתורה עבור החלפת תבניות. + לשמור את קבוצת הפרמטרים השלמה (ולא רק את אלה שסופקו על ידי המשתמש) יחד עם תוכנית העבודה. + לוודא שכל הפרמטרים הנדרשים מכילים ערכים. + +3. **שליפת סוגי פרמטרים** + הגדרות סוגי פרמטרים מאוחסנות בתצורה עם הסוג "parameter-type". + כל הגדרת סוג מכילה סכימה, ערך ברירת מחדל וכללי אימות. + לשמור סוגי פרמטרים בשימוש נפוץ במטמון כדי להפחית את מספר הפניות לתצורה. + +#### שילוב עם מערכת התצורה + +3. **אחסון אובייקטי זרימה** + כאשר אובייקט זרימה מתווסף למערכת התצורה על ידי רכיב הזרימה בניהול התצורה, אובייקט הזרימה חייב לכלול את ערכי הפרמטרים הפתורים. + מנהל התצורה צריך לאחסן גם את הפרמטרים שסופקו על ידי המשתמש וגם את הערכים הפתורים (עם יישום ברירת המחדל). + אובייקטי זרימה במערכת התצורה צריכים לכלול: + `parameters`: ערכי הפרמטרים הפתורים הסופיים המשמשים עבור הזרימה. + +#### שילוב עם ממשק שורת הפקודה (CLI) + +4. **פקודות CLI של הספריה** + פקודות CLI המתחילות זרימות צריכות לתמוך בפרמטרים: + לקבל ערכי פרמטרים באמצעות דגלי שורת הפקודה או קבצי תצורה. + לאמת פרמטרים מול הגדרות תוכנית העבודה לפני שליחה. + לתמוך בקלט של קובץ פרמטרים (JSON/YAML) עבור קבוצות פרמטרים מורכבות. + + פקודות CLI המציגות זרימות צריכות להציג מידע על פרמטרים: + להציג את ערכי הפרמטרים ששימשו בעת התחלת הזרימה. + להציג את הפרמטרים הזמינים עבור תוכנית עבודה של זרימה. + להציג סכימות אימות של פרמטרים וערכי ברירת מחדל. + +#### שילוב עם מחלקת בסיס של מעבד (Processor) + +5. **תמיכה ב-ParameterSpec** + מחלקות בסיס של מעבדים צריכות לתמוך בהחלפת פרמטרים באמצעות מנגנון ה-ParametersSpec הקיים. + המחלקה ParametersSpec (הנמצאת באותו מודול כמו ConsumerSpec ו-ProducerSpec) צריכה להיות משופרת במידת הצורך כדי לתמוך בהחלפת תבניות של פרמטרים. + מעבדים צריכים להיות מסוגלים להשתמש ב-ParametersSpec כדי להגדיר את הפרמטרים שלהם עם ערכי פרמטרים שפתורים בזמן הפעלת הזרימה. + יישום ה-ParametersSpec צריך: + לקבל תצורות פרמטרים המכילות מקומות שמורות של פרמטרים (לדוגמה, `{model}`, `{temperature}`). + לתמוך בהחלפת פרמטרים בזמן ריצה בעת יצירת המעבד. + לוודא שערכים שהוחלפו תואמים לסוגים ולמגבלות הצפויים. + לספק טיפול בשגיאות עבור הפניות חסרות או לא חוקיות של פרמטרים. + +#### כללי החלפה + +פרמטרים משתמשים בפורמט `{parameter-name}` בפרמטרים של מעבד. +שמות הפרמטרים בפרמטרים תואמים למפתחות בסעיף `parameters` של תוכנית העבודה. +החלפה מתרחשת יחד עם החלפת `{id}` ו-`{class}`. +הפניות לא חוקיות של פרמטרים גורמות לשגיאות בזמן ההפעלה. +אימות סוג מתרחש בהתבסס על הגדרת הפרמטר המאוחסנת במרכז. +**חשוב**: כל ערכי הפרמטרים מאוחסנים ומועברים כרצף תווים. + מספרים מומרים לרצף תווים (לדוגמה, `0.7` הופך ל-`"0.7"`). +<<<<<<< HEAD + ערכים בוליאניים מומרים לרצף תווים קטן (לדוגמה, `true` הופך ל-`"true"`). +======= + בוליאנים מומרים לרצף תווים קטן (לדוגמה, `true` הופך ל-`"true"`). +>>>>>>> 82edf2d (New md files from RunPod) + זה נדרש על ידי הסכימה של Pulsar, אשר מגדירה `parameters = Map(String())`. + +דוגמה לפענוח: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## אסטרטגיית בדיקות + +בדיקות יחידה לאימות סכימת הפרמטרים +בדיקות אינטגרציה להחלפת פרמטרים בפרמטרים של המעבד +בדיקות מקצה לקצה להפעלת זרימות עם ערכי פרמטרים שונים +בדיקות ממשק משתמש ליצירה ואימות של טופס פרמטרים +בדיקות ביצועים עבור זרימות עם פרמטרים רבים +מקרים קצה: פרמטרים חסרים, סוגים לא חוקיים, הפניות לפרמטרים לא מוגדרים + +## תוכנית מעבר + +1. המערכת צריכה להמשיך לתמוך בתבניות זרימה ללא פרמטרים +<<<<<<< HEAD + מוצהרים. +======= + מוגדרים. +>>>>>>> 82edf2d (New md files from RunPod) +2. המערכת צריכה להמשיך לתמוך בזרימות ללא פרמטרים מוגדרים: + זה עובד עבור זרימות ללא פרמטרים, וזרימות עם פרמטרים + (שיש להם ערכי ברירת מחדל). + +## שאלות פתוחות + +<<<<<<< HEAD +ש: האם הפרמטרים צריכים לתמוך באובייקטים מקוננים מורכבים או להישאר בסוגים פשוטים? +======= +ש: האם פרמטרים צריכים לתמוך באובייקטים מקוננים מורכבים או להישאר בסוגים פשוטים? +>>>>>>> 82edf2d (New md files from RunPod) +ת: ערכי הפרמטרים יועברו כרצף תווים, סביר להניח שנרצה + להישאר ברצפים תווים. + +ש: האם מותר להשתמש במחזיקי פרמטרים בשמות תורים או רק ב + פרמטרים? +ת: רק בפרמטרים כדי למנוע הזרקות ותופעות לוואי. + +ש: כיצד לטפל בקונפליקטים בין שמות פרמטרים למשתנים של המערכת כמו +<<<<<<< HEAD + `id` ו- `class`? +ת: לא חוקי לציין id ו-class בעת הפעלת זרימה. + +ש: האם אנו תומכים בפרמטרים מחושבים (נגזרים מפרמטרים אחרים)? +ת: רק החלפת רצפי תווים כדי למנוע הזרקות ותופעות לוואי. +======= + `id` ו-`class`? +ת: לא חוקי לציין id ו-class בעת הפעלת זרימה. + +ש: האם אנו תומכים בפרמטרים מחושבים (נגזרים מפרמטרים אחרים)? +ת: רק החלפת רצפים תווים כדי למנוע הזרקות ותופעות לוואי. +>>>>>>> 82edf2d (New md files from RunPod) + +## הפניות + +מפרט JSON Schema: https://json-schema.org/ +מפרט הגדרת תבנית זרימה: docs/tech-specs/flow-class-definition.md diff --git a/docs/tech-specs/flow-configurable-parameters.hi.md b/docs/tech-specs/flow-configurable-parameters.hi.md new file mode 100644 index 00000000..54306057 --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.hi.md @@ -0,0 +1,598 @@ +--- +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. + +## अवलोकन + +यह विनिर्देश ट्रस्टग्राफ में कॉन्फ़िगर करने योग्य पैरामीटर के कार्यान्वयन का वर्णन करता है। पैरामीटर उपयोगकर्ताओं को फ्लो लॉन्च समय पर प्रोसेसर पैरामीटर को अनुकूलित करने की अनुमति देते हैं, जो फ्लो ब्लूप्रिंट परिभाषा में पैरामीटर प्लेसहोल्डर को बदलने वाले मान प्रदान करते हैं। + +पैरामीटर प्रोसेसर पैरामीटर में टेम्पलेट वेरिएबल प्रतिस्थापन के माध्यम से काम करते हैं, जो `{id}` और `{class}` वेरिएबल्स के काम करने के तरीके के समान है, लेकिन उपयोगकर्ता-प्रदत्त मानों के साथ। + +एकीकरण चार प्राथमिक उपयोग मामलों का समर्थन करता है: + +1. **मॉडल चयन**: उपयोगकर्ताओं को प्रोसेसर के लिए विभिन्न एलएलएम मॉडल (जैसे, `gemma3:8b`, `gpt-4`, `claude-3`) चुनने की अनुमति देना +2. **संसाधन कॉन्फ़िगरेशन**: प्रोसेसर पैरामीटर जैसे कि चंक आकार, बैच आकार और समवर्ती सीमा को समायोजित करना +3. **व्यवहार ट्यूनिंग**: तापमान, अधिकतम-टोकन या पुनर्प्राप्ति थ्रेसहोल्ड जैसे पैरामीटर के माध्यम से प्रोसेसर व्यवहार को संशोधित करना +<<<<<<< HEAD +4. **पर्यावरण-विशिष्ट पैरामीटर**: प्रत्येक परिनियोजन के लिए समापन बिंदु, एपीआई कुंजियाँ या क्षेत्र-विशिष्ट यूआरएल को कॉन्फ़िगर करना +======= +4. **पर्यावरण-विशिष्ट पैरामीटर**: प्रत्येक तैनाती के लिए समापन बिंदु, एपीआई कुंजियाँ या क्षेत्र-विशिष्ट यूआरएल को कॉन्फ़िगर करना +>>>>>>> 82edf2d (New md files from RunPod) + +## लक्ष्य + +**डायनामिक प्रोसेसर कॉन्फ़िगरेशन**: पैरामीटर प्रतिस्थापन के माध्यम से प्रोसेसर पैरामीटर के रनटाइम कॉन्फ़िगरेशन को सक्षम करना +**पैरामीटर सत्यापन**: फ्लो लॉन्च समय पर पैरामीटर के लिए टाइप चेकिंग और सत्यापन प्रदान करना +<<<<<<< HEAD +**डिफ़ॉल्ट मान**: समझदार डिफ़ॉल्ट का समर्थन करना जबकि उन्नत उपयोगकर्ताओं के लिए ओवरराइड की अनुमति देना +======= +**डिफ़ॉल्ट मान**: समझदार डिफ़ॉल्ट मानों का समर्थन करना जबकि उन्नत उपयोगकर्ताओं के लिए ओवरराइड की अनुमति देना +>>>>>>> 82edf2d (New md files from RunPod) +**टेम्पलेट प्रतिस्थापन**: प्रोसेसर पैरामीटर में पैरामीटर प्लेसहोल्डर को निर्बाध रूप से बदलना +**यूआई एकीकरण**: एपीआई और यूआई इंटरफेस दोनों के माध्यम से पैरामीटर इनपुट को सक्षम करना +**टाइप सुरक्षा**: यह सुनिश्चित करना कि पैरामीटर प्रकार अपेक्षित प्रोसेसर पैरामीटर प्रकारों से मेल खाते हैं +**प्रलेखन**: फ्लो ब्लूप्रिंट परिभाषाओं के भीतर स्व-प्रलेखित पैरामीटर स्कीमा +<<<<<<< HEAD +**पिछड़ा संगतता**: मौजूदा फ्लो ब्लूप्रिंट के साथ संगतता बनाए रखना जो पैरामीटर का उपयोग नहीं करते हैं +======= +**पिछला संगतता**: मौजूदा फ्लो ब्लूप्रिंट के साथ संगतता बनाए रखना जो पैरामीटर का उपयोग नहीं करते हैं +>>>>>>> 82edf2d (New md files from RunPod) + +## पृष्ठभूमि + +ट्रस्टग्राफ में फ्लो ब्लूप्रिंट अब प्रोसेसर पैरामीटर का समर्थन करते हैं जिनमें या तो निश्चित मान या पैरामीटर प्लेसहोल्डर हो सकते हैं। यह रनटाइम अनुकूलन के लिए एक अवसर बनाता है। + +वर्तमान प्रोसेसर पैरामीटर का समर्थन: +निश्चित मान: `"model": "gemma3:12b"` +पैरामीटर प्लेसहोल्डर: `"model": "gemma3:{model-size}"` + +यह विनिर्देश परिभाषित करता है कि पैरामीटर कैसे हैं: +फ्लो ब्लूप्रिंट परिभाषाओं में घोषित +जब फ्लो लॉन्च होते हैं तो मान्य +प्रोसेसर पैरामीटर में प्रतिस्थापित +एपीआई और यूआई के माध्यम से उजागर + +पैरामीटराइज़्ड प्रोसेसर पैरामीटर का लाभ उठाकर, ट्रस्टग्राफ: +भिन्नताओं के लिए पैरामीटर का उपयोग करके फ्लो ब्लूप्रिंट डुप्लिकेसन को कम करता है +उपयोगकर्ताओं को परिभाषाओं को संशोधित किए बिना प्रोसेसर व्यवहार को ट्यून करने की अनुमति देता है +पैरामीटर मानों के माध्यम से पर्यावरण-विशिष्ट कॉन्फ़िगरेशन का समर्थन करता है +पैरामीटर स्कीमा सत्यापन के माध्यम से टाइप सुरक्षा बनाए रखता है + +## तकनीकी डिजाइन + +### वास्तुकला + +कॉन्फ़िगर करने योग्य पैरामीटर सिस्टम के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है: + +1. **पैरामीटर स्कीमा परिभाषा** + फ्लो ब्लूप्रिंट मेटाडेटा के भीतर JSON स्कीमा-आधारित पैरामीटर परिभाषाएँ +<<<<<<< HEAD + स्ट्रिंग, नंबर, बूलियन, एनम और ऑब्जेक्ट प्रकार सहित प्रकार परिभाषाएँ +======= + स्ट्रिंग, संख्या, बूलियन, एनम और ऑब्जेक्ट प्रकार सहित प्रकार परिभाषाएँ +>>>>>>> 82edf2d (New md files from RunPod) + न्यूनतम/अधिकतम मान, पैटर्न और आवश्यक फ़ील्ड सहित सत्यापन नियम + + मॉड्यूल: trustgraph-flow/trustgraph/flow/definition.py + +2. **पैरामीटर रिज़ॉल्यूशन इंजन** + स्कीमा के विरुद्ध रनटाइम पैरामीटर सत्यापन + निर्दिष्ट पैरामीटर के लिए डिफ़ॉल्ट मानों का अनुप्रयोग + फ्लो निष्पादन संदर्भ में पैरामीटर इंजेक्शन + आवश्यकतानुसार प्रकार का रूपांतरण और रूपांतरण + + मॉड्यूल: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **पैरामीटर स्टोर एकीकरण** + स्कीमा/कॉन्फ़िग स्टोर से पैरामीटर परिभाषाओं की पुनर्प्राप्ति +<<<<<<< HEAD + अक्सर उपयोग की जाने वाली पैरामीटर परिभाषाओं का कैशिंग +======= + बार-बार उपयोग की जाने वाली पैरामीटर परिभाषाओं का कैशिंग +>>>>>>> 82edf2d (New md files from RunPod) + केंद्रीय रूप से संग्रहीत स्कीमा के विरुद्ध सत्यापन + + मॉड्यूल: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **फ्लो लॉन्चर एक्सटेंशन** + फ्लो लॉन्च के दौरान पैरामीटर मानों को स्वीकार करने के लिए एपीआई एक्सटेंशन + पैरामीटर मैपिंग रिज़ॉल्यूशन (फ्लो नाम से परिभाषा नाम) + अमान्य पैरामीटर संयोजनों के लिए त्रुटि हैंडलिंग + + मॉड्यूल: trustgraph-flow/trustgraph/flow/launcher.py + +5. **यूआई पैरामीटर फॉर्म** + फ्लो पैरामीटर मेटाडेटा से गतिशील रूप से उत्पन्न फॉर्म + `order` फ़ील्ड का उपयोग करके क्रमबद्ध पैरामीटर प्रदर्शन + `description` फ़ील्ड का उपयोग करके वर्णनात्मक पैरामीटर लेबल + पैरामीटर प्रकार परिभाषाओं के विरुद्ध इनपुट सत्यापन + पैरामीटर प्रीसेट और टेम्पलेट + + मॉड्यूल: trustgraph-ui/components/flow-parameters/ + +### डेटा मॉडल + +#### पैरामीटर परिभाषाएँ (स्कीमा/कॉन्फ़िग में संग्रहीत) + +पैरामीटर परिभाषाएँ स्कीमा और कॉन्फ़िग सिस्टम में "पैरामीटर-प्रकार" प्रकार के साथ केंद्रीय रूप से संग्रहीत की जाती हैं: + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### पैरामीटर संदर्भों के साथ फ्लो ब्लूप्रिंट + +फ्लो ब्लूप्रिंट, प्रकार संदर्भों, विवरणों और क्रम के साथ पैरामीटर मेटाडेटा को परिभाषित करते हैं: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +`parameters` अनुभाग प्रवाह-विशिष्ट पैरामीटर नामों (कुंजियों) को पैरामीटर मेटाडेटा ऑब्जेक्ट्स से मैप करता है जिनमें शामिल हैं: +`type`: केंद्रीय रूप से परिभाषित पैरामीटर परिभाषा का संदर्भ (उदाहरण के लिए, "llm-model") +`description`: यूआई प्रदर्शन के लिए मानव-पठनीय विवरण +`order`: पैरामीटर फ़ॉर्म के लिए प्रदर्शन क्रम (छोटे नंबर पहले दिखाई देते हैं) +`advanced` (वैकल्पिक): एक बूलियन ध्वज जो इंगित करता है कि क्या यह एक उन्नत पैरामीटर है (डिफ़ॉल्ट: false)। जब इसे true पर सेट किया जाता है, तो यूआई डिफ़ॉल्ट रूप से इस पैरामीटर को छिपा सकता है या इसे "उन्नत" अनुभाग में रख सकता है +<<<<<<< HEAD +`controlled-by` (वैकल्पिक): एक अन्य पैरामीटर का नाम जो सरल मोड में इस पैरामीटर के मान को नियंत्रित करता है। जब निर्दिष्ट किया जाता है, तो यह पैरामीटर अपने मान को नियंत्रित पैरामीटर से प्राप्त करता है जब तक कि स्पष्ट रूप से ओवरराइड न किया जाए + +यह दृष्टिकोण अनुमति देता है: +कई प्रवाह ब्लूप्रिंट में पुन: प्रयोज्य पैरामीटर प्रकार परिभाषाएँ +======= +`controlled-by` (वैकल्पिक): एक अन्य पैरामीटर का नाम जो सरल मोड में इस पैरामीटर के मान को नियंत्रित करता है। जब निर्दिष्ट किया जाता है, तो यह पैरामीटर अपने मान को नियंत्रित पैरामीटर से विरासत में लेता है जब तक कि स्पष्ट रूप से ओवरराइड न किया जाए + +यह दृष्टिकोण अनुमति देता है: +कई फ़्लो ब्लूप्रिंट में पुन: प्रयोज्य पैरामीटर प्रकार परिभाषाएँ +>>>>>>> 82edf2d (New md files from RunPod) +केंद्रीकृत पैरामीटर प्रकार प्रबंधन और सत्यापन +प्रवाह-विशिष्ट पैरामीटर विवरण और क्रम +वर्णनात्मक पैरामीटर फ़ॉर्म के साथ बेहतर यूआई अनुभव +प्रवाह में सुसंगत पैरामीटर सत्यापन +नए मानक पैरामीटर प्रकारों को आसानी से जोड़ना +बुनियादी/उन्नत मोड अलगाव के साथ सरलीकृत यूआई +संबंधित सेटिंग्स के लिए पैरामीटर मान विरासत + +<<<<<<< HEAD +#### प्रवाह लॉन्च अनुरोध + +प्रवाह लॉन्च एपीआई प्रवाह के पैरामीटर नामों का उपयोग करके पैरामीटर स्वीकार करता है: +======= +#### फ़्लो लॉन्च अनुरोध + +फ़्लो लॉन्च एपीआई प्रवाह के पैरामीटर नामों का उपयोग करके पैरामीटर स्वीकार करता है: +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +<<<<<<< HEAD +ध्यान दें: इस उदाहरण में, `llm-rag-model` स्पष्ट रूप से प्रदान नहीं किया गया है, लेकिन यह `llm-model` से "claude-3" मान को अपने `controlled-by` संबंध के कारण प्राप्त करेगा। इसी तरह, `chunk-overlap` `chunk-size` के आधार पर गणना किए गए मान को प्राप्त कर सकता है। +======= +ध्यान दें: इस उदाहरण में, `llm-rag-model` स्पष्ट रूप से प्रदान नहीं किया गया है, लेकिन यह `llm-model` से "claude-3" मान को अपने `controlled-by` संबंध के कारण प्राप्त करेगा। इसी तरह, `chunk-overlap` `chunk-size` के आधार पर एक गणना किए गए मान को प्राप्त कर सकता है। +>>>>>>> 82edf2d (New md files from RunPod) + +सिस्टम निम्नलिखित कार्य करेगा: +1. फ्लो ब्लूप्रिंट परिभाषा से पैरामीटर मेटाडेटा निकालें +2. फ्लो पैरामीटर नामों को उनके प्रकार परिभाषाओं (जैसे, `llm-model` → `llm-model` प्रकार) में मैप करें +<<<<<<< HEAD +3. नियंत्रित-द्वारा संबंधों को हल करें (जैसे, `llm-rag-model` `llm-model` से प्राप्त होता है) +======= +3. नियंत्रित-द्वारा (controlled-by) संबंधों को हल करें (जैसे, `llm-rag-model` `llm-model` से प्राप्त होता है) +>>>>>>> 82edf2d (New md files from RunPod) +4. पैरामीटर प्रकार परिभाषाओं के विरुद्ध उपयोगकर्ता द्वारा प्रदान किए गए और प्राप्त मूल्यों को मान्य करें +5. फ्लो इंस्टेंशिएशन के दौरान हल किए गए मूल्यों को प्रोसेसर पैरामीटर में प्रतिस्थापित करें + +### कार्यान्वयन विवरण + +#### पैरामीटर रिज़ॉल्यूशन प्रक्रिया + +जब कोई फ्लो शुरू होता है, तो सिस्टम निम्नलिखित पैरामीटर रिज़ॉल्यूशन चरण करता है: + +1. **फ्लो ब्लूप्रिंट लोडिंग**: फ्लो ब्लूप्रिंट परिभाषा लोड करें और पैरामीटर मेटाडेटा निकालें +2. **मेटाडेटा निष्कर्षण**: फ्लो ब्लूप्रिंट के `parameters` अनुभाग में परिभाषित प्रत्येक पैरामीटर के लिए `type`, `description`, `order`, `advanced`, और `controlled-by` निकालें +3. **टाइप परिभाषा लुकअप**: फ्लो ब्लूप्रिंट में प्रत्येक पैरामीटर के लिए: +<<<<<<< HEAD + स्कीमा/कॉन्फ़िग स्टोर से `type` फ़ील्ड का उपयोग करके पैरामीटर प्रकार परिभाषा प्राप्त करें +======= + `type` फ़ील्ड का उपयोग करके स्कीमा/कॉन्फ़िग स्टोर से पैरामीटर प्रकार परिभाषा प्राप्त करें +>>>>>>> 82edf2d (New md files from RunPod) + प्रकार परिभाषाएँ कॉन्फ़िग सिस्टम में "parameter-type" प्रकार के साथ संग्रहीत की जाती हैं + प्रत्येक प्रकार की परिभाषा में पैरामीटर का स्कीमा, डिफ़ॉल्ट मान और सत्यापन नियम होते हैं +4. **डिफ़ॉल्ट मान रिज़ॉल्यूशन**: + फ्लो ब्लूप्रिंट में परिभाषित प्रत्येक पैरामीटर के लिए: + जांचें कि क्या उपयोगकर्ता ने इस पैरामीटर के लिए कोई मान प्रदान किया है + यदि कोई उपयोगकर्ता मान प्रदान नहीं किया गया है, तो पैरामीटर प्रकार परिभाषा से `default` मान का उपयोग करें +<<<<<<< HEAD + उपयोगकर्ता द्वारा प्रदान किए गए और डिफ़ॉल्ट मानों दोनों को शामिल करते हुए एक पूर्ण पैरामीटर मानचित्र बनाएं +======= + उपयोगकर्ता द्वारा प्रदान किए गए और डिफ़ॉल्ट मानों दोनों को शामिल करते हुए एक पूर्ण पैरामीटर मैप बनाएं +>>>>>>> 82edf2d (New md files from RunPod) +5. **पैरामीटर इनहेरिटेंस रिज़ॉल्यूशन** (नियंत्रित-द्वारा संबंध): + `controlled-by` फ़ील्ड वाले पैरामीटर के लिए, जांचें कि क्या कोई मान स्पष्ट रूप से प्रदान किया गया था + यदि कोई स्पष्ट मान प्रदान नहीं किया गया है, तो नियंत्रित पैरामीटर से मान प्राप्त करें + यदि नियंत्रित पैरामीटर में भी कोई मान नहीं है, तो प्रकार परिभाषा से डिफ़ॉल्ट का उपयोग करें + जांचें कि `controlled-by` संबंधों में कोई गोलाकार निर्भरता मौजूद नहीं है +6. **सत्यापन**: प्रकार परिभाषाओं के विरुद्ध पूर्ण पैरामीटर सेट (उपयोगकर्ता द्वारा प्रदान किए गए, डिफ़ॉल्ट और प्राप्त) को मान्य करें +7. **भंडारण**: ऑडिटिंग के लिए फ्लो इंस्टेंस के साथ पूर्ण हल किए गए पैरामीटर सेट को संग्रहीत करें +8. **टेम्प्लेट प्रतिस्थापन**: प्रोसेसर पैरामीटर में पैरामीटर प्लेसहोल्डर को हल किए गए मानों से बदलें +9. **प्रोसेसर इंस्टेंशिएशन**: प्रतिस्थापित पैरामीटर के साथ प्रोसेसर बनाएं + +**महत्वपूर्ण कार्यान्वयन नोट्स:** +<<<<<<< HEAD +फ्लो सर्विस को पैरामीटर प्रकार परिभाषाओं से डिफ़ॉल्ट के साथ उपयोगकर्ता द्वारा प्रदान किए गए पैरामीटर को मर्ज करना होगा +पूर्ण पैरामीटर सेट (लागू डिफ़ॉल्ट सहित) को पता लगाने के लिए फ्लो के साथ संग्रहीत किया जाना चाहिए +पैरामीटर रिज़ॉल्यूशन फ्लो शुरू होने के समय होता है, प्रोसेसर इंस्टेंशिएशन के समय नहीं +======= +फ्लो सेवा को उपयोगकर्ता द्वारा प्रदान किए गए पैरामीटर को पैरामीटर प्रकार परिभाषाओं से डिफ़ॉल्ट के साथ मर्ज करना होगा +पूर्ण पैरामीटर सेट (लागू डिफ़ॉल्ट सहित) को ट्रेसबिलिटी के लिए फ्लो के साथ संग्रहीत किया जाना चाहिए +पैरामीटर रिज़ॉल्यूशन फ्लो शुरू होने के समय होता है, न कि प्रोसेसर इंस्टेंशिएशन के समय +>>>>>>> 82edf2d (New md files from RunPod) +डिफ़ॉल्ट के बिना आवश्यक पैरामीटर गायब होने से फ्लो शुरू होने में विफलता होनी चाहिए, साथ ही एक स्पष्ट त्रुटि संदेश भी + +#### नियंत्रित-द्वारा के साथ पैरामीटर इनहेरिटेंस + +`controlled-by` फ़ील्ड पैरामीटर मान इनहेरिटेंस को सक्षम करता है, जो उपयोगकर्ता इंटरफ़ेस को सरल बनाने के साथ-साथ लचीलापन बनाए रखने के लिए विशेष रूप से उपयोगी है: + +**उदाहरण परिदृश्य**: +`llm-model` पैरामीटर प्राथमिक LLM मॉडल को नियंत्रित करता है +`llm-rag-model` पैरामीटर में `"controlled-by": "llm-model"` होता है +सरल मोड में, `llm-model` को "gpt-4" पर सेट करने से स्वचालित रूप से `llm-rag-model` भी "gpt-4" पर सेट हो जाता है +उन्नत मोड में, उपयोगकर्ता `llm-rag-model` को एक अलग मान के साथ ओवरराइड कर सकते हैं + +**रिज़ॉल्यूशन नियम**: +1. यदि किसी पैरामीटर में एक स्पष्ट रूप से प्रदान किया गया मान है, तो उस मान का उपयोग करें +2. यदि कोई स्पष्ट मान नहीं है और `controlled-by` सेट है, तो नियंत्रित पैरामीटर का मान उपयोग करें +3. यदि नियंत्रित पैरामीटर में कोई मान नहीं है, तो प्रकार परिभाषा से डिफ़ॉल्ट पर वापस जाएं +4. `controlled-by` संबंधों में गोलाकार निर्भरताएँ एक सत्यापन त्रुटि का कारण बनती हैं + +**UI व्यवहार**: +बुनियादी/सरल मोड में: `controlled-by` वाले पैरामीटर छिपे हो सकते हैं या प्राप्त मान के साथ केवल-पढ़ने योग्य के रूप में दिखाए जा सकते हैं +उन्नत मोड में: सभी पैरामीटर दिखाए जाते हैं और उन्हें व्यक्तिगत रूप से कॉन्फ़िगर किया जा सकता है +जब एक नियंत्रित पैरामीटर बदलता है, तो निर्भर पैरामीटर स्वचालित रूप से अपडेट हो जाते हैं जब तक कि उन्हें स्पष्ट रूप से ओवरराइड न किया जाए + +#### पल्सर एकीकरण + +1. **स्टार्ट-फ्लो ऑपरेशन** +<<<<<<< HEAD + पल्सर स्टार्ट-फ्लो ऑपरेशन को एक `parameters` फ़ील्ड स्वीकार करना होगा जिसमें पैरामीटर मानों का एक मानचित्र होता है +======= + पल्सर स्टार्ट-फ्लो ऑपरेशन को एक `parameters` फ़ील्ड स्वीकार करना होगा जिसमें पैरामीटर मानों का एक मैप हो +>>>>>>> 82edf2d (New md files from RunPod) + स्टार्ट-फ्लो अनुरोध के लिए पल्सर स्कीमा को वैकल्पिक `parameters` फ़ील्ड को शामिल करने के लिए अपडेट किया जाना चाहिए + उदाहरण अनुरोध: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **गेट-फ्लो ऑपरेशन** + गेट-फ्लो प्रतिक्रिया के लिए पल्सर स्कीमा को `parameters` फ़ील्ड को शामिल करने के लिए अपडेट किया जाना चाहिए। + यह ग्राहकों को उन पैरामीटर मानों को पुनः प्राप्त करने की अनुमति देता है जिनका उपयोग फ्लो शुरू करते समय किया गया था। + उदाहरण प्रतिक्रिया: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### फ्लो सर्विस कार्यान्वयन + +फ्लो कॉन्फ़िगरेशन सर्विस (`trustgraph-flow/trustgraph/config/service/flow.py`) को निम्नलिखित सुधारों की आवश्यकता है: + +1. **पैरामीटर रिज़ॉल्यूशन फ़ंक्शन** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + यह फ़ंक्शन को इस प्रकार होना चाहिए: + फ़्लो ब्लूप्रिंट के `parameters` अनुभाग से पैरामीटर मेटाडेटा निकालें + प्रत्येक पैरामीटर के लिए, कॉन्फ़िगरेशन स्टोर से इसके प्रकार की परिभाषा प्राप्त करें + उन सभी पैरामीटर के लिए डिफ़ॉल्ट मान लागू करें जो उपयोगकर्ता द्वारा प्रदान नहीं किए गए हैं + `controlled-by` विरासत संबंधों को संभालें +<<<<<<< HEAD + संपूर्ण पैरामीटर सेट लौटाएं + +2. **संशोधित `handle_start_flow` विधि** + फ़्लो ब्लूप्रिंट लोड करने के बाद `resolve_parameters` को कॉल करें + टेम्पलेट प्रतिस्थापन के लिए पूरे हल किए गए पैरामीटर सेट का उपयोग करें + पूरे पैरामीटर सेट को (केवल उपयोगकर्ता द्वारा प्रदान किए गए नहीं) फ़्लो के साथ संग्रहीत करें +======= + पूर्ण पैरामीटर सेट लौटाएं + +2. **संशोधित `handle_start_flow` विधि** + फ़्लो ब्लूप्रिंट लोड करने के बाद `resolve_parameters` को कॉल करें + टेम्पलेट प्रतिस्थापन के लिए पूर्ण हल किए गए पैरामीटर सेट का उपयोग करें + पूर्ण पैरामीटर सेट (केवल उपयोगकर्ता द्वारा प्रदान किए गए नहीं) को फ़्लो के साथ संग्रहीत करें +>>>>>>> 82edf2d (New md files from RunPod) + सत्यापित करें कि सभी आवश्यक पैरामीटर में मान हैं + +3. **पैरामीटर प्रकार प्राप्त करना** + पैरामीटर प्रकार की परिभाषाएँ "parameter-type" प्रकार के साथ कॉन्फ़िगर में संग्रहीत हैं + प्रत्येक प्रकार की परिभाषा में स्कीमा, डिफ़ॉल्ट मान और सत्यापन नियम होते हैं + अक्सर उपयोग किए जाने वाले पैरामीटर प्रकारों को कैश करें ताकि कॉन्फ़िगर लुकअप कम हो सकें + +#### कॉन्फ़िगर सिस्टम एकीकरण + +3. **फ़्लो ऑब्जेक्ट स्टोरेज** + जब कोई फ़्लो घटक कॉन्फ़िगर प्रबंधक में कॉन्फ़िगर सिस्टम में जोड़ा जाता है, तो फ़्लो ऑब्जेक्ट में हल किए गए पैरामीटर मान शामिल होने चाहिए +<<<<<<< HEAD + कॉन्फ़िगर प्रबंधक को मूल उपयोगकर्ता-प्रदान किए गए पैरामीटर और हल किए गए मान दोनों (डिफ़ॉल्ट लागू किए गए) को संग्रहीत करने की आवश्यकता होती है + कॉन्फ़िगर सिस्टम में फ़्लो ऑब्जेक्ट में शामिल होना चाहिए: +======= + कॉन्फ़िगर प्रबंधक को मूल उपयोगकर्ता-प्रदान किए गए पैरामीटर और हल किए गए मान (डिफ़ॉल्ट लागू होने के साथ) दोनों को संग्रहीत करने की आवश्यकता है + कॉन्फ़िगर सिस्टम में फ़्लो ऑब्जेक्ट में निम्नलिखित शामिल होने चाहिए: +>>>>>>> 82edf2d (New md files from RunPod) + `parameters`: फ़्लो के लिए उपयोग किए गए अंतिम हल किए गए पैरामीटर मान + +#### CLI एकीकरण + +4. **लाइब्रेरी CLI कमांड** + फ़्लो शुरू करने वाले CLI कमांड में पैरामीटर समर्थन होना चाहिए: + कमांड-लाइन फ़्लैग या कॉन्फ़िगरेशन फ़ाइलों के माध्यम से पैरामीटर मान स्वीकार करें + सबमिशन से पहले फ़्लो ब्लूप्रिंट परिभाषाओं के विरुद्ध पैरामीटर को मान्य करें + जटिल पैरामीटर सेट के लिए पैरामीटर फ़ाइल इनपुट (JSON/YAML) का समर्थन करें + + फ़्लो दिखाने वाले CLI कमांड में पैरामीटर जानकारी प्रदर्शित करने की आवश्यकता होती है: + उस समय प्रदर्शित करें जब फ़्लो शुरू किया गया था, तो उपयोग किए गए पैरामीटर मान + एक फ़्लो ब्लूप्रिंट के लिए उपलब्ध पैरामीटर प्रदर्शित करें + पैरामीटर सत्यापन स्कीमा और डिफ़ॉल्ट प्रदर्शित करें + +#### प्रोसेसर बेस क्लास एकीकरण + +5. **पैरामीटरस्पेक समर्थन** + प्रोसेसर बेस क्लास को मौजूदा पैरामीटर्सस्पेक तंत्र के माध्यम से पैरामीटर प्रतिस्थापन का समर्थन करने की आवश्यकता है + पैरामीटर्सस्पेक क्लास (उपभोक्तास्पेक और प्रोड्यूसरस्पेक के समान मॉड्यूल में स्थित) को पैरामीटर टेम्पलेट प्रतिस्थापन का समर्थन करने के लिए आवश्यक होने पर बढ़ाया जाना चाहिए +<<<<<<< HEAD + प्रोसेसर को अपने पैरामीटर को कॉन्फ़िगर करने के लिए पैरामीटर्सस्पेक को कॉल करने में सक्षम होना चाहिए, जिसमें फ़्लो लॉन्च समय पर हल किए गए पैरामीटर मान शामिल हैं +======= + प्रोसेसर को अपने पैरामीटर को कॉन्फ़िगर करने के लिए पैरामीटर्सस्पेक को लागू करने में सक्षम होना चाहिए, जिसमें फ़्लो लॉन्च समय पर हल किए गए पैरामीटर मान शामिल हैं +>>>>>>> 82edf2d (New md files from RunPod) + पैरामीटर्सस्पेक कार्यान्वयन को: + पैरामीटर कॉन्फ़िगरेशन स्वीकार करें जिसमें पैरामीटर प्लेसहोल्डर शामिल हैं (जैसे, `{model}`, `{temperature}`) + प्रोसेसर के इंस्टेंट होने पर रनटाइम पैरामीटर प्रतिस्थापन का समर्थन करें + सत्यापित करें कि प्रतिस्थापित मान अपेक्षित प्रकार और बाधाओं से मेल खाते हैं + गुम या अमान्य पैरामीटर संदर्भों के लिए त्रुटि हैंडलिंग प्रदान करें + +#### प्रतिस्थापन नियम + +<<<<<<< HEAD +प्रोसेसर पैरामीटर में पैरामीटर `{parameter-name}` प्रारूप का उपयोग करते हैं +======= +पैरामीटर प्रोसेसर पैरामीटर में `{parameter-name}` प्रारूप का उपयोग करते हैं +>>>>>>> 82edf2d (New md files from RunPod) +पैरामीटर में पैरामीटर नाम फ़्लो के `parameters` अनुभाग में कुंजियों से मेल खाते हैं +प्रतिस्थापन `{id}` और `{class}` प्रतिस्थापन के साथ-साथ होता है +अमान्य पैरामीटर संदर्भ लॉन्च-टाइम त्रुटियों का परिणाम देते हैं +केंद्रीय रूप से संग्रहीत पैरामीटर परिभाषा के आधार पर प्रकार सत्यापन होता है +**महत्वपूर्ण**: सभी पैरामीटर मान स्ट्रिंग के रूप में संग्रहीत और प्रसारित किए जाते हैं + संख्याओं को स्ट्रिंग में परिवर्तित किया जाता है (जैसे, `0.7` `"0.7"` बन जाता है) + बूलियन को लोअरकेस स्ट्रिंग में परिवर्तित किया जाता है (जैसे, `true` `"true"` बन जाता है) +<<<<<<< HEAD + यह पल्सर स्कीमा की आवश्यकता है जो `parameters = Map(String())` को परिभाषित करती है +======= + यह पल्सर स्कीमा द्वारा आवश्यक है जो `parameters = Map(String())` को परिभाषित करता है +>>>>>>> 82edf2d (New md files from RunPod) + +उदाहरण समाधान: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## परीक्षण रणनीति + +पैरामीटर स्कीमा सत्यापन के लिए यूनिट परीक्षण +प्रोसेसर पैरामीटर में पैरामीटर प्रतिस्थापन के लिए एकीकरण परीक्षण +विभिन्न पैरामीटर मानों के साथ फ्लो लॉन्च करने के लिए एंड-टू-एंड परीक्षण +पैरामीटर फॉर्म पीढ़ी और सत्यापन के लिए यूआई परीक्षण +कई पैरामीटर वाले फ्लो के लिए प्रदर्शन परीक्षण +किनारे के मामले: गुम पैरामीटर, अमान्य प्रकार, अपरिभाषित पैरामीटर संदर्भ + +## माइग्रेशन योजना + +1. सिस्टम को बिना पैरामीटर वाले फ्लो ब्लूप्रिंट का समर्थन करना जारी रखना चाहिए। + घोषित। +2. सिस्टम को बिना पैरामीटर वाले फ्लो का समर्थन करना जारी रखना चाहिए: +<<<<<<< HEAD + यह बिना पैरामीटर वाले फ्लो और पैरामीटर वाले फ्लो दोनों के लिए काम करता है (उनके पास डिफ़ॉल्ट होते हैं)। +======= + यह बिना पैरामीटर वाले फ्लो और पैरामीटर वाले फ्लो दोनों के लिए काम करता है (उनके पास डिफ़ॉल्ट मान होते हैं)। +>>>>>>> 82edf2d (New md files from RunPod) + +## खुले प्रश्न + + +<<<<<<< HEAD +प्रश्न: क्या पैरामीटर जटिल, नेस्टेड ऑब्जेक्ट्स का समर्थन करेंगे, या केवल साधारण प्रकारों तक सीमित रहेंगे? +उत्तर: पैरामीटर मान स्ट्रिंग के रूप में एन्कोड किए जाएंगे, इसलिए शायद हमें + केवल स्ट्रिंग तक ही सीमित रहना चाहिए। + +प्रश्न: क्या पैरामीटर प्लेसहोल्डर को कतार के नामों में अनुमति दी जानी चाहिए, या केवल + पैरामीटर में? +उत्तर: केवल पैरामीटर में, ताकि अजीब इंजेक्शन और असामान्य स्थितियों से बचा जा सके। + +प्रश्न: पैरामीटर नामों और सिस्टम वेरिएबल्स के बीच टकराव को कैसे संभालें, जैसे कि + `id` और `class`? +अ: यह सही नहीं है कि फ्लो शुरू करते समय आईडी और क्लास दोनों निर्दिष्ट किए जाएं। + +प्रश्न: क्या हमें गणना किए गए पैरामीटर (अन्य पैरामीटर से प्राप्त) का समर्थन करना चाहिए? +======= +प्रश्न: क्या पैरामीटर जटिल, नेस्टेड ऑब्जेक्ट्स का समर्थन करेंगे, या केवल सरल प्रकारों तक सीमित रहेंगे? +उत्तर: पैरामीटर मान स्ट्रिंग के रूप में एन्कोड किए जाएंगे, इसलिए हम शायद केवल स्ट्रिंग तक ही सीमित रहना चाहेंगे। + + +प्रश्न: क्या पैरामीटर प्लेसहोल्डर को कतार के नामों में अनुमति दी जानी चाहिए, या केवल पैरामीटर में? + उत्तर: केवल पैरामीटर में, ताकि अजीब इंजेक्शन और असामान्य स्थितियों से बचा जा सके। + + +प्रश्न: पैरामीटर नामों और सिस्टम वेरिएबल्स के बीच टकराव को कैसे संभालें, जैसे कि + `id` और `class`? +अ: यह सही नहीं है कि फ्लो शुरू करते समय आईडी और क्लास दोनों को निर्दिष्ट किया जाए। + +प्रश्न: क्या हमें गणना किए गए मापदंडों (अन्य मापदंडों से प्राप्त) का समर्थन करना चाहिए? +>>>>>>> 82edf2d (New md files from RunPod) +उत्तर: केवल स्ट्रिंग प्रतिस्थापन का उपयोग करके अजीब इंजेक्शन और विशेष मामलों को हटाना। + +## संदर्भ + +JSON स्कीमा विनिर्देश: https://json-schema.org/ +फ्लो ब्लूप्रिंट परिभाषा विनिर्देश: docs/tech-specs/flow-class-definition.md diff --git a/docs/tech-specs/flow-configurable-parameters.md b/docs/tech-specs/flow-configurable-parameters.md index a605c114..cb9e64dd 100644 --- a/docs/tech-specs/flow-configurable-parameters.md +++ b/docs/tech-specs/flow-configurable-parameters.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Flow Blueprint Configurable Parameters Technical Specification" +parent: "Tech Specs" +--- + # Flow Blueprint Configurable Parameters Technical Specification ## Overview diff --git a/docs/tech-specs/flow-configurable-parameters.pt.md b/docs/tech-specs/flow-configurable-parameters.pt.md new file mode 100644 index 00000000..39cc63ec --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.pt.md @@ -0,0 +1,596 @@ +--- +layout: default +title: "Especificação Técnica de Parâmetros Configuráveis para Flow Blueprint" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Parâmetros Configuráveis para Flow Blueprint + +> **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 a implementação de parâmetros configuráveis para flow blueprints no TrustGraph. Os parâmetros permitem que os usuários personalizem os parâmetros do processador no momento da execução do fluxo, fornecendo valores que substituem os espaços reservados de parâmetros na definição do flow blueprint. + +Os parâmetros funcionam por meio da substituição de variáveis de modelo nos parâmetros do processador, de forma semelhante a como as variáveis `{id}` e `{class}` funcionam, mas com valores fornecidos pelo usuário. + +A integração suporta quatro casos de uso principais: + +1. **Seleção de Modelo**: Permitindo que os usuários escolham diferentes modelos LLM (por exemplo, `gemma3:8b`, `gpt-4`, `claude-3`) para processadores. +2. **Configuração de Recursos**: Ajustando parâmetros do processador, como tamanhos de lote, tamanhos de lote e limites de concorrência. +3. **Ajuste de Comportamento**: Modificando o comportamento do processador por meio de parâmetros como temperatura, max-tokens ou limites de recuperação. +4. **Parâmetros Específicos do Ambiente**: Configurando endpoints, chaves de API ou URLs específicas da região para cada implantação. + +## Objetivos + +**Configuração Dinâmica do Processador**: Permitir a configuração em tempo de execução dos parâmetros do processador por meio da substituição de parâmetros. +**Validação de Parâmetros**: Fornecer verificação de tipo e validação para parâmetros no momento da execução do fluxo. +**Valores Padrão**: Suportar valores padrão sensatos, permitindo a substituição para usuários avançados. +**Substituição de Modelo**: Substituir perfeitamente os espaços reservados de parâmetros nos parâmetros do processador. +**Integração com a Interface do Usuário**: Permitir a entrada de parâmetros por meio de interfaces de API e de interface do usuário. +**Segurança de Tipo**: Garantir que os tipos de parâmetros correspondam aos tipos de parâmetros do processador esperados. +**Documentação**: Esquemas de parâmetros autoexplicativos dentro das definições do flow blueprint. +**Compatibilidade com Versões Anteriores**: Manter a compatibilidade com flow blueprints existentes que não usam parâmetros. + +## Contexto + +Flow blueprints no TrustGraph agora suportam parâmetros de processador que podem conter valores fixos ou espaços reservados de parâmetros. Isso cria uma oportunidade para personalização em tempo de execução. + +Os parâmetros de processador atuais suportam: +Valores fixos: `"model": "gemma3:12b"` +Espaços reservados de parâmetros: `"model": "gemma3:{model-size}"` + +Esta especificação define como os parâmetros são: +Declarados em definições de flow blueprint. +Validados quando os fluxos são iniciados. +Substituídos em parâmetros do processador. +Expostos por meio de APIs e da interface do usuário. + +Ao aproveitar os parâmetros de processador parametrizados, o TrustGraph pode: +Reduzir a duplicação de flow blueprints, usando parâmetros para variações. +Permitir que os usuários ajustem o comportamento do processador sem modificar as definições. +Suportar configurações específicas do ambiente por meio de valores de parâmetro. +Manter a segurança de tipo por meio da validação do esquema de parâmetro. + +## Design Técnico + +### Arquitetura + +O sistema de parâmetros configuráveis requer os seguintes componentes técnicos: + +1. **Definição de Esquema de Parâmetro** + Definições de parâmetros baseadas em JSON Schema dentro dos metadados do flow blueprint. + Definições de tipo, incluindo string, número, booleano, enum e tipos de objeto. + Regras de validação, incluindo valores mínimo/máximo, padrões e campos obrigatórios. + + Módulo: trustgraph-flow/trustgraph/flow/definition.py + +2. **Motor de Resolução de Parâmetros** + Validação de parâmetros em tempo de execução contra o esquema. + Aplicação de valores padrão para parâmetros não especificados. + Injeção de parâmetros no contexto de execução do fluxo. + Coerção e conversão de tipo, conforme necessário. + + Módulo: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **Integração com o Armazenamento de Parâmetros** + Recuperação de definições de parâmetros do armazenamento de esquema/configuração. + Cache de definições de parâmetros frequentemente usadas. + Validação contra esquemas armazenados centralmente. + + Módulo: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **Extensões do Lançador de Fluxo** + Extensões de API para aceitar valores de parâmetro durante o lançamento do fluxo. + Resolução de mapeamento de parâmetros (nomes de fluxo para nomes de definição). + Tratamento de erros para combinações de parâmetros inválidas. + + Módulo: trustgraph-flow/trustgraph/flow/launcher.py + +<<<<<<< HEAD +5. **Formulários de Parâmetro da Interface do Usuário** + Geração dinâmica de formulários a partir de metadados de parâmetros do fluxo. + Exibição ordenada de parâmetros usando o campo `order`. + Rótulos de parâmetros descritivos usando o campo `description`. +======= +5. **Formulários de Parâmetros da Interface do Usuário** + Geração dinâmica de formulários a partir de metadados de parâmetros do fluxo. + Exibição ordenada de parâmetros usando o campo `order`. + Rótulos descritivos de parâmetros usando o campo `description`. +>>>>>>> 82edf2d (New md files from RunPod) + Validação de entrada contra as definições de tipo de parâmetro. + Predefinições e modelos de parâmetros. + + Módulo: trustgraph-ui/components/flow-parameters/ + +### Modelos de Dados + +#### Definições de Parâmetro (Armazenadas no Esquema/Configuração) + +As definições de parâmetros são armazenadas centralmente no sistema de esquema e configuração com o tipo "parameter-type": + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### Diagrama de fluxo com referências de parâmetros + +Os diagramas de fluxo definem metadados de parâmetros com referências de tipo, descrições e ordem: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +A seção `parameters` mapeia nomes de parâmetros específicos do fluxo (chaves) para objetos de metadados de parâmetros que contêm: +`type`: Referência à definição de parâmetro definida centralmente (por exemplo, "llm-model") +`description`: Descrição legível por humanos para exibição na interface do usuário +`order`: Ordem de exibição para formulários de parâmetros (números menores aparecem primeiro) +`advanced` (opcional): Sinalizador booleano que indica se este é um parâmetro avançado (padrão: falso). Quando definido como verdadeiro, a interface do usuário pode ocultar este parâmetro por padrão ou colocá-lo em uma seção "Avançado" +`controlled-by` (opcional): Nome de outro parâmetro que controla o valor deste parâmetro quando no modo simples. Quando especificado, este parâmetro herda seu valor do parâmetro de controle, a menos que seja explicitamente substituído + +Esta abordagem permite: +Definições de tipos de parâmetros reutilizáveis em vários modelos de fluxo +Gerenciamento e validação centralizados de tipos de parâmetros +Descrições e ordenação de parâmetros específicos do fluxo +Experiência de interface do usuário aprimorada com formulários de parâmetros descritivos +Validação consistente de parâmetros em todos os fluxos +Adição fácil de novos tipos de parâmetros padrão +Interface do usuário simplificada com separação de modo básico/avançado +Herança de valores de parâmetros para configurações relacionadas + +#### Solicitação de Inicialização do Fluxo + +A API de inicialização do fluxo aceita parâmetros usando os nomes de parâmetros do fluxo: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +Nota: Neste exemplo, `llm-rag-model` não é fornecido explicitamente, mas herdará o valor "claude-3" de `llm-model` devido à sua relação `controlled-by`. Da mesma forma, `chunk-overlap` pode herdar um valor calculado com base em `chunk-size`. + +O sistema irá: +<<<<<<< HEAD +1. Extrair metadados de parâmetros da definição do blueprint do fluxo +2. Mapear os nomes dos parâmetros do fluxo para suas definições de tipo (por exemplo, `llm-model` → `llm-model` tipo) +3. Resolver as relações "controlado por" (por exemplo, `llm-rag-model` herda de `llm-model`) +4. Validar os valores fornecidos pelo usuário e os valores herdados em relação às definições de tipo dos parâmetros +5. Substituir os valores resolvidos nos parâmetros do processador durante a instanciação do fluxo +======= +1. Extrair metadados de parâmetros da definição do fluxo. +2. Mapear os nomes dos parâmetros do fluxo para suas definições de tipo (por exemplo, `llm-model` → `llm-model` tipo). +3. Resolver relações de dependência (por exemplo, `llm-rag-model` herda de `llm-model`). +4. Validar os valores fornecidos pelo usuário e os valores herdados em relação às definições de tipo dos parâmetros. +5. Substituir os valores resolvidos nos parâmetros do processador durante a instanciação do fluxo. +>>>>>>> 82edf2d (New md files from RunPod) + +### Detalhes da Implementação + +#### Processo de Resolução de Parâmetros + +Quando um fluxo é iniciado, o sistema executa as seguintes etapas de resolução de parâmetros: + +<<<<<<< HEAD +1. **Carregamento do Blueprint do Fluxo**: Carregar a definição do blueprint do fluxo e extrair os metadados dos parâmetros +2. **Extração de Metadados**: Extrair `type`, `description`, `order`, `advanced` e `controlled-by` para cada parâmetro definido na seção `parameters` do blueprint do fluxo +3. **Consulta da Definição de Tipo**: Para cada parâmetro no blueprint do fluxo: + Recuperar a definição de tipo do parâmetro do armazenamento de esquema/configuração usando o campo `type` + As definições de tipo são armazenadas com o tipo "parameter-type" no sistema de configuração + Cada definição de tipo contém o esquema do parâmetro, o valor padrão e as regras de validação +4. **Resolução do Valor Padrão**: + Para cada parâmetro definido no blueprint do fluxo: + Verificar se o usuário forneceu um valor para este parâmetro + Se nenhum valor do usuário for fornecido, usar o valor `default` da definição de tipo do parâmetro + Criar um mapa de parâmetros completo contendo tanto os valores fornecidos pelo usuário quanto os valores padrão +5. **Resolução de Herança de Parâmetros** (relações "controlado por"): + Para parâmetros com o campo `controlled-by`, verificar se um valor foi fornecido explicitamente + Se nenhum valor explícito for fornecido, herdar o valor do parâmetro de controle + Se o parâmetro de controle também não tiver valor, usar o padrão da definição de tipo + Validar que não existam dependências circulares nas relações `controlled-by` +6. **Validação**: Validar o conjunto completo de parâmetros (fornecidos pelo usuário, padrões e herdados) em relação às definições de tipo +7. **Armazenamento**: Armazenar o conjunto completo de parâmetros resolvidos com a instância do fluxo para auditoria +8. **Substituição de Modelos**: Substituir os espaços reservados de parâmetros nos parâmetros do processador com os valores resolvidos +9. **Instanciação do Processador**: Criar processadores com os parâmetros substituídos + +**Notas Importantes de Implementação:** +O serviço de fluxo DEVE mesclar os parâmetros fornecidos pelo usuário com os padrões das definições de tipo de parâmetro +O conjunto completo de parâmetros (incluindo os padrões aplicados) DEVE ser armazenado com o fluxo para rastreabilidade +A resolução de parâmetros ocorre no início do fluxo, não no momento da instanciação do processador +Parâmetros obrigatórios sem padrões DEVE causar a falha no início do fluxo com uma mensagem de erro clara + +#### Herança de Parâmetros com "controlado-por" + +O campo `controlled-by` permite a herança de valores de parâmetros, o que é particularmente útil para simplificar as interfaces do usuário, mantendo a flexibilidade: + +**Cenário de Exemplo**: +O parâmetro `llm-model` controla o modelo LLM primário +O parâmetro `llm-rag-model` tem `"controlled-by": "llm-model"` +No modo simples, definir `llm-model` para "gpt-4" define automaticamente `llm-rag-model` para "gpt-4" também +No modo avançado, os usuários podem substituir `llm-rag-model` com um valor diferente + +**Regras de Resolução**: +1. Se um parâmetro tiver um valor fornecido explicitamente, use esse valor +2. Se não houver valor explícito e `controlled-by` estiver definido, use o valor do parâmetro de controle +3. Se o parâmetro de controle não tiver valor, use o padrão da definição de tipo +4. Dependências circulares nas relações `controlled-by` resultam em um erro de validação + +**Comportamento da IU**: +No modo básico/simples: Parâmetros com `controlled-by` podem ser ocultos ou exibidos como somente leitura com valor herdado +No modo avançado: Todos os parâmetros são exibidos e podem ser configurados individualmente +Quando um parâmetro de controle é alterado, os parâmetros dependentes são atualizados automaticamente, a menos que sejam explicitamente substituídos +======= +1. **Carregamento da Definição do Fluxo**: Carregar a definição do fluxo e extrair os metadados dos parâmetros. +2. **Extração de Metadados**: Extrair `type`, `description`, `order`, `advanced` e `controlled-by` para cada parâmetro definido na seção `parameters` da definição do fluxo. +3. **Consulta da Definição de Tipo**: Para cada parâmetro na definição do fluxo: + Recuperar a definição de tipo do parâmetro do armazenamento de esquema/configuração usando o campo `type`. + As definições de tipo são armazenadas com o tipo "parameter-type" no sistema de configuração. + Cada definição de tipo contém o esquema do parâmetro, o valor padrão e as regras de validação. +4. **Resolução do Valor Padrão**: + Para cada parâmetro definido na definição do fluxo: + Verificar se o usuário forneceu um valor para este parâmetro. + Se nenhum valor do usuário for fornecido, usar o valor `default` da definição de tipo do parâmetro. + Criar um mapa de parâmetros completo contendo tanto os valores fornecidos pelo usuário quanto os valores padrão. +5. **Resolução de Herança de Parâmetros** (relações de dependência): + Para parâmetros com o campo `controlled-by`, verificar se um valor foi fornecido explicitamente. + Se nenhum valor explícito for fornecido, herdar o valor do parâmetro de controle. + Se o parâmetro de controle também não tiver valor, usar o padrão da definição de tipo. + Validar que não existam dependências circulares nas relações `controlled-by`. +6. **Validação**: Validar o conjunto completo de parâmetros (fornecidos pelo usuário, padrões e herdados) em relação às definições de tipo. +7. **Armazenamento**: Armazenar o conjunto completo de parâmetros resolvidos com a instância do fluxo para auditoria. +8. **Substituição de Marcadores**: Substituir os marcadores de parâmetros nos parâmetros do processador pelos valores resolvidos. +9. **Instanciação do Processador**: Criar processadores com os parâmetros substituídos. + +**Notas Importantes de Implementação:** +O serviço de fluxo DEVE mesclar os parâmetros fornecidos pelo usuário com os padrões das definições de tipo de parâmetro. +O conjunto completo de parâmetros (incluindo os padrões aplicados) DEVE ser armazenado com o fluxo para rastreabilidade. +A resolução de parâmetros ocorre no início do fluxo, não no momento da instanciação do processador. +Parâmetros obrigatórios sem padrões DEVE causar a falha no início do fluxo com uma mensagem de erro clara. + +#### Herança de Parâmetros com dependência + +O campo `controlled-by` permite a herança de valores de parâmetros, o que é particularmente útil para simplificar interfaces de usuário, mantendo a flexibilidade: + +**Cenário de Exemplo**: +O parâmetro `llm-model` controla o modelo LLM primário. +O parâmetro `llm-rag-model` tem o valor `"controlled-by": "llm-model"`. +No modo simples, definir `llm-model` para "gpt-4" define automaticamente `llm-rag-model` para "gpt-4" também. +No modo avançado, os usuários podem substituir `llm-rag-model` com um valor diferente. + +**Regras de Resolução**: +1. Se um parâmetro tiver um valor fornecido explicitamente, use esse valor. +2. Se não houver valor explícito e `controlled-by` estiver definido, use o valor do parâmetro de controle. +3. Se o parâmetro de controle não tiver valor, use o padrão da definição de tipo. +4. Dependências circulares nas relações `controlled-by` resultam em um erro de validação. + +**Comportamento da Interface do Usuário**: +No modo básico/simples: Parâmetros com `controlled-by` podem ser ocultos ou exibidos como somente leitura com valor herdado. +No modo avançado: Todos os parâmetros são exibidos e podem ser configurados individualmente. +Quando um parâmetro de controle é alterado, os parâmetros dependentes são atualizados automaticamente, a menos que sejam explicitamente substituídos. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Integração com Pulsar + +1. **Operação Start-Flow** +<<<<<<< HEAD + A operação start-flow do Pulsar precisa aceitar um campo `parameters` contendo um mapa de valores de parâmetros + O esquema do Pulsar para a solicitação start-flow deve ser atualizado para incluir o campo opcional `parameters` +======= + A operação start-flow do Pulsar precisa aceitar um campo `parameters` contendo um mapa de valores de parâmetros. + O esquema do Pulsar para a solicitação start-flow deve ser atualizado para incluir o campo opcional `parameters`. +>>>>>>> 82edf2d (New md files from RunPod) + Exemplo de solicitação: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **Operação Get-Flow** + O esquema Pulsar para a resposta do get-flow deve ser atualizado para incluir o campo `parameters` + Isso permite que os clientes recuperem os valores dos parâmetros que foram usados quando o fluxo foi iniciado. + Exemplo de resposta: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### Implementação do Serviço de Fluxo + +O serviço de configuração de fluxo (`trustgraph-flow/trustgraph/config/service/flow.py`) requer as seguintes melhorias: + +1. **Função de Resolução de Parâmetros** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + Esta função deve: + Extrair metadados de parâmetros da seção `parameters` do blueprint do fluxo + Para cada parâmetro, buscar a definição de tipo no armazenamento de configuração + Aplicar valores padrão para quaisquer parâmetros não fornecidos pelo usuário + Lidar com relacionamentos de herança `controlled-by` + Retornar o conjunto completo de parâmetros + +2. **Método `handle_start_flow` Modificado** + Chamar `resolve_parameters` após carregar o blueprint do fluxo +<<<<<<< HEAD + Usar o conjunto completo de parâmetros resolvidos para substituição de modelo +======= + Usar o conjunto completo de parâmetros resolvidos para a substituição de modelo +>>>>>>> 82edf2d (New md files from RunPod) + Armazenar o conjunto completo de parâmetros (não apenas os fornecidos pelo usuário) com o fluxo + Validar que todos os parâmetros obrigatórios tenham valores + +3. **Busca de Tipo de Parâmetro** + As definições de tipo de parâmetro são armazenadas na configuração com o tipo "parameter-type" + Cada definição de tipo contém esquema, valor padrão e regras de validação + Armazenar em cache os tipos de parâmetro frequentemente usados para reduzir as consultas à configuração + +#### Integração com o Sistema de Configuração + +3. **Armazenamento de Objetos de Fluxo** + Quando um fluxo é adicionado ao sistema de configuração pelo componente de fluxo no gerenciador de configuração, o objeto de fluxo deve incluir os valores de parâmetros resolvidos + O gerenciador de configuração precisa armazenar tanto os parâmetros originais fornecidos pelo usuário quanto os valores resolvidos (com os padrões aplicados) + Os objetos de fluxo no sistema de configuração devem incluir: +<<<<<<< HEAD + `parameters`: Os valores finais de parâmetros resolvidos usados para o fluxo +======= + `parameters`: Os valores de parâmetros resolvidos finais usados para o fluxo +>>>>>>> 82edf2d (New md files from RunPod) + +#### Integração com a CLI + +4. **Comandos da CLI da Biblioteca** + Os comandos da CLI que iniciam fluxos precisam de suporte a parâmetros: + Aceitar valores de parâmetros por meio de flags de linha de comando ou arquivos de configuração +<<<<<<< HEAD + Validar parâmetros em relação às definições do blueprint do fluxo antes da submissão +======= + Validar os parâmetros em relação às definições do blueprint do fluxo antes da submissão +>>>>>>> 82edf2d (New md files from RunPod) + Suportar a entrada de arquivos de parâmetros (JSON/YAML) para conjuntos de parâmetros complexos + + Os comandos da CLI que mostram fluxos precisam exibir informações de parâmetros: + Mostrar os valores de parâmetros usados quando o fluxo foi iniciado + Exibir os parâmetros disponíveis para um blueprint de fluxo + Mostrar os esquemas e padrões de validação de parâmetros + +#### Integração com a Classe Base do Processador + +5. **Suporte a ParameterSpec** +<<<<<<< HEAD + As classes base do processador precisam suportar a substituição de parâmetros por meio do mecanismo existente ParametersSpec +======= + As classes base do processador precisam suportar a substituição de parâmetros por meio do mecanismo ParametersSpec existente +>>>>>>> 82edf2d (New md files from RunPod) + A classe ParametersSpec (localizada no mesmo módulo que ConsumerSpec e ProducerSpec) deve ser aprimorada, se necessário, para suportar a substituição de modelos de parâmetros + Os processadores devem ser capazes de invocar ParametersSpec para configurar seus parâmetros com valores de parâmetros resolvidos no momento da inicialização do fluxo + A implementação de ParametersSpec precisa: + Aceitar configurações de parâmetros que contenham espaços reservados de parâmetros (por exemplo, `{model}`, `{temperature}`) + Suportar a substituição de parâmetros em tempo de execução quando o processador é instanciado + Validar que os valores substituídos correspondam aos tipos e restrições esperados + Fornecer tratamento de erros para referências de parâmetros ausentes ou inválidos + +#### Regras de Substituição + +Os parâmetros usam o formato `{parameter-name}` nos parâmetros do processador +Os nomes dos parâmetros nos parâmetros correspondem às chaves na seção `parameters` do fluxo +A substituição ocorre juntamente com a substituição de `{id}` e `{class}` +Referências de parâmetros inválidas resultam em erros no momento da inicialização +A validação de tipo ocorre com base na definição de parâmetro armazenada centralmente +**IMPORTANTE**: Todos os valores de parâmetros são armazenados e transmitidos como strings + Os números são convertidos em strings (por exemplo, `0.7` se torna `"0.7"`) + Os booleanos são convertidos em strings em letras minúsculas (por exemplo, `true` se torna `"true"`) + Isso é necessário pelo esquema do Pulsar que define `parameters = Map(String())` + +Exemplo de resolução: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## Estratégia de Testes + +<<<<<<< HEAD +Testes unitários para validação do esquema de parâmetros +Testes de integração para substituição de parâmetros nos parâmetros do processador +Testes de ponta a ponta para iniciar fluxos com diferentes valores de parâmetros +Testes de interface do usuário para geração e validação de formulários de parâmetros +Testes de desempenho para fluxos com muitos parâmetros +Casos extremos: parâmetros ausentes, tipos inválidos, referências de parâmetros indefinidos +======= +Testes unitários para validação do esquema de parâmetros. +Testes de integração para substituição de parâmetros nos parâmetros do processador. +Testes de ponta a ponta para iniciar fluxos com diferentes valores de parâmetros. +Testes de interface do usuário para geração e validação de formulários de parâmetros. +Testes de desempenho para fluxos com muitos parâmetros. +Casos de borda: parâmetros ausentes, tipos inválidos, referências de parâmetros indefinidos. +>>>>>>> 82edf2d (New md files from RunPod) + +## Plano de Migração + +1. O sistema deve continuar a suportar modelos de fluxo sem parâmetros + declarados. +2. O sistema deve continuar a suportar fluxos sem parâmetros especificados: + Isso funciona para fluxos sem parâmetros e para fluxos com parâmetros + (eles têm valores padrão). + +## Perguntas Abertas + +P: Os parâmetros devem suportar objetos aninhados complexos ou devem se limitar a tipos simples? +R: Os valores dos parâmetros serão codificados como strings, provavelmente queremos + restringir a strings. + +P: Os espaços reservados de parâmetros devem ser permitidos em nomes de filas ou apenas em + parâmetros? +<<<<<<< HEAD +R: Apenas em parâmetros para evitar injeções estranhas e casos extremos. +======= +R: Apenas em parâmetros para remover injeções estranhas e casos de borda. +>>>>>>> 82edf2d (New md files from RunPod) + +P: Como lidar com conflitos entre nomes de parâmetros e variáveis do sistema, como + `id` e `class`? +R: Não é válido especificar "id" e "class" ao iniciar um fluxo. + +P: Devemos suportar parâmetros calculados (derivados de outros parâmetros)? +<<<<<<< HEAD +R: Apenas substituição de strings para evitar injeções estranhas e casos extremos. +======= +R: Apenas substituição de strings para remover injeções estranhas e casos de borda. +>>>>>>> 82edf2d (New md files from RunPod) + +## Referências + +Especificação do Esquema JSON: https://json-schema.org/ +Especificação da Definição do Modelo de Fluxo: docs/tech-specs/flow-class-definition.md diff --git a/docs/tech-specs/flow-configurable-parameters.ru.md b/docs/tech-specs/flow-configurable-parameters.ru.md new file mode 100644 index 00000000..d9a14bf4 --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.ru.md @@ -0,0 +1,613 @@ +--- +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. Параметры позволяют пользователям настраивать параметры процессоров при запуске потока, предоставляя значения, которые заменяют заполнители параметров в определении шаблона потока. + +Параметры работают путем подстановки переменных в шаблонах в параметрах процессоров, аналогично тому, как работают переменные `{id}` и `{class}`, но со значениями, предоставленными пользователем. + +Интеграция поддерживает четыре основных сценария использования: + +1. **Выбор модели**: Предоставление пользователям возможности выбора различных моделей LLM (например, `gemma3:8b`, `gpt-4`, `claude-3`) для процессоров. +2. **Конфигурация ресурсов**: Настройка параметров процессоров, таких как размеры пакетов, размеры партий и лимиты параллельности. +3. **Настройка поведения**: Изменение поведения процессоров с помощью параметров, таких как температура, максимальное количество токенов или пороги извлечения. +4. **Параметры, специфичные для среды**: Настройка конечных точек, ключей API или URL-адресов, специфичных для региона, для каждого развертывания. + +## Цели + +**Динамическая конфигурация процессоров**: Обеспечение возможности динамической конфигурации параметров процессоров путем подстановки параметров. +**Проверка параметров**: Предоставление проверки типов и валидации параметров при запуске потока. +**Значения по умолчанию**: Поддержка разумных значений по умолчанию, позволяя при этом переопределять их для продвинутых пользователей. +**Подстановка шаблонов**: Бесшовная замена заполнителей параметров в параметрах процессоров. +**Интеграция с пользовательским интерфейсом**: Обеспечение ввода параметров как через API, так и через пользовательский интерфейс. +**Безопасность типов**: Обеспечение соответствия типов параметров ожидаемым типам параметров процессора. +**Документация**: Самодокументированные схемы параметров в определениях шаблонов потоков. +**Обратная совместимость**: Поддержка обратной совместимости с существующими шаблонами потоков, которые не используют параметры. + +## Предыстория + +В шаблонах потоков в TrustGraph теперь поддерживаются параметры процессоров, которые могут содержать либо фиксированные значения, либо заполнители параметров. Это создает возможность для динамической настройки. + +Текущие параметры процессоров поддерживают: +Фиксированные значения: `"model": "gemma3:12b"` +Заполнители параметров: `"model": "gemma3:{model-size}"` + +Эта спецификация определяет, как параметры: +Объявляются в определениях шаблонов потоков. +Проверяются при запуске потоков. +Подставляются в параметры процессоров. +Предоставляются через API и пользовательский интерфейс. + +Используя параметризованные параметры процессоров, TrustGraph может: +Уменьшить дублирование шаблонов потоков, используя параметры для вариаций. +Позволить пользователям настраивать поведение процессоров без изменения определений. +Поддерживать конфигурации, специфичные для среды, с помощью значений параметров. +Обеспечивать безопасность типов с помощью проверки схемы параметров. + +## Технический дизайн + +### Архитектура + +Система конфигурируемых параметров требует следующих технических компонентов: + +1. **Определение схемы параметров** + Определения параметров на основе JSON-схемы в метаданных шаблона потока. + Определения типов, включая типы string, number, boolean, enum и object. + Правила валидации, включая минимальные/максимальные значения, шаблоны и обязательные поля. + + Модуль: trustgraph-flow/trustgraph/flow/definition.py + +<<<<<<< HEAD +2. **Механизм разрешения параметров** + Проверка параметров на соответствие схеме во время выполнения. + Применение значений по умолчанию для не указанных параметров. + Внедрение параметров в контекст выполнения потока. + Преобразование типов и приведение типов при необходимости. +======= +2. **Движок разрешения параметров** + Проверка параметров на соответствие схеме во время выполнения. + Применение значений по умолчанию для не указанных параметров. + Внедрение параметров в контекст выполнения потока. + Приведение типов и преобразование при необходимости. +>>>>>>> 82edf2d (New md files from RunPod) + + Модуль: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **Интеграция с хранилищем параметров** + Получение определений параметров из хранилища схем/конфигураций. + Кэширование часто используемых определений параметров. + Проверка на соответствие централизованным схемам. + + Модуль: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **Расширения для запуска потоков** + Расширения API для приема значений параметров при запуске потока. +<<<<<<< HEAD + Разрешение отображения (имена потоков на имена определений). +======= + Разрешение сопоставления параметров (имена потоков к именам определений). +>>>>>>> 82edf2d (New md files from RunPod) + Обработка ошибок для недействительных комбинаций параметров. + + Модуль: trustgraph-flow/trustgraph/flow/launcher.py + +5. **Формы параметров пользовательского интерфейса** + Динамическая генерация форм из метаданных параметров потока. +<<<<<<< HEAD + Отображение параметров в упорядоченном виде с использованием поля `order`. +======= + Отображение параметров в отсортированном порядке с использованием поля `order`. +>>>>>>> 82edf2d (New md files from RunPod) + Описательные метки параметров с использованием поля `description`. + Проверка ввода в соответствии с определениями типов параметров. + Предустановки и шаблоны параметров. + + Модуль: trustgraph-ui/components/flow-parameters/ + +### Модели данных + +#### Определения параметров (хранятся в схеме/конфигурации) + +Определения параметров хранятся централизованно в системе схем и конфигураций с типом "parameter-type": + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### Схема потока с ссылками на параметры + +Схемы потока определяют метаданные параметров со ссылками на типы, описаниями и порядком: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +Раздел `parameters` сопоставляет имена параметров, специфичные для потока (ключи), с объектами метаданных параметров, содержащими: +<<<<<<< HEAD +`type`: Ссылка на централизованно определенное определение параметра (например, "llm-model") +`description`: Описание, понятное человеку, для отображения в пользовательском интерфейсе +======= +`type`: Ссылка на центрально определенное определение параметра (например, "llm-model") +`description`: Описание, понятное для человека, для отображения в пользовательском интерфейсе +>>>>>>> 82edf2d (New md files from RunPod) +`order`: Порядок отображения параметров в формах (меньшие числа отображаются первыми) +`advanced` (необязательно): Булевский флаг, указывающий, является ли этот параметр расширенным (по умолчанию: false). Если установлено значение true, пользовательский интерфейс может скрывать этот параметр по умолчанию или помещать его в раздел "Расширенные" +`controlled-by` (необязательно): Имя другого параметра, который управляет значением этого параметра в простом режиме. Если указано, этот параметр наследует свое значение от управляющего параметра, если явно не переопределен + +Этот подход позволяет: +Повторное использование определений типов параметров в нескольких шаблонах потоков +Централизованное управление и проверка типов параметров +Описания и порядок параметров, специфичные для потока +Улучшенный пользовательский интерфейс с описательными формами параметров +Последовательная проверка параметров во всех потоках +Легкое добавление новых стандартных типов параметров +Упрощенный пользовательский интерфейс с разделением на режимы "базовый/расширенный" +Наследование значений параметров для связанных настроек + +#### Запрос запуска потока + +API запуска потока принимает параметры, используя имена параметров, специфичные для потока: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +<<<<<<< HEAD +Примечание: В этом примере, `llm-rag-model` явно не указан, но он унаследует значение "claude-3" из `llm-model` из-за его `controlled-by` связи. Аналогично, `chunk-overlap` может унаследовать вычисленное значение на основе `chunk-size`. + +Система будет: +1. Извлекать метаданные параметров из определения схемы потока +2. Сопоставлять имена параметров потока с их определениями типов (например, `llm-model` → `llm-model` тип) +3. Разрешать отношения "контролируется" (например, `llm-rag-model` наследуется от `llm-model`) +======= +Примечание: В этом примере `llm-rag-model` явно не указано, но оно наследует значение "claude-3" из `llm-model` из-за своей `controlled-by` связи. Аналогично, `chunk-overlap` может наследовать вычисленное значение на основе `chunk-size`. + +Система будет: +1. Извлекать метаданные параметров из определения шаблона потока +2. Сопоставлять имена параметров потока с их определениями типов (например, `llm-model` → тип `llm-model`) +3. Разрешать зависимости (например, `llm-rag-model` наследует от `llm-model`) +>>>>>>> 82edf2d (New md files from RunPod) +4. Проверять предоставленные пользователем и унаследованные значения на соответствие определениям типов параметров +5. Подставлять разрешенные значения в параметры процессоров во время создания экземпляра потока + +### Детали реализации + +#### Процесс разрешения параметров + +При запуске потока система выполняет следующие шаги разрешения параметров: + +<<<<<<< HEAD +1. **Загрузка схемы потока**: Загрузить определение схемы потока и извлечь метаданные параметров +2. **Извлечение метаданных**: Извлечь `type`, `description`, `order`, `advanced` и `controlled-by` для каждого параметра, определенного в разделе `parameters` схемы потока +3. **Поиск определения типа**: Для каждого параметра в схеме потока: + Получить определение типа параметра из хранилища схем/конфигураций, используя поле `type` + Определения типов хранятся с типом "parameter-type" в системе конфигураций + Каждое определение типа содержит схему параметра, значение по умолчанию и правила проверки +4. **Разрешение значения по умолчанию**: + Для каждого параметра, определенного в схеме потока: + Проверить, предоставлено ли пользователем значение для этого параметра + Если пользовательское значение не предоставлено, использовать значение `default` из определения типа параметра + Создать полную карту параметров, содержащую как предоставленные пользователем, так и значения по умолчанию +5. **Разрешение наследования параметров** (отношения "контролируется"): + Для параметров с полем `controlled-by`, проверить, было ли предоставлено явное значение + Если явное значение не предоставлено, унаследовать значение от контролируемого параметра + Если контролируемый параметр также не имеет значения, использовать значение по умолчанию из определения типа + Проверить отсутствие циклических зависимостей в отношениях `controlled-by` +6. **Проверка**: Проверить полный набор параметров (предоставленные пользователем, значения по умолчанию и унаследованные) на соответствие определениям типов +7. **Хранение**: Сохранить полный разрешенный набор параметров с экземпляром потока для обеспечения возможности аудита +8. **Подстановка шаблонов**: Заменить заполнители параметров в параметрах процессоров разрешенными значениями +9. **Создание экземпляров процессоров**: Создать процессоры с подставленными параметрами +======= +1. **Загрузка шаблона потока**: Загрузить определение шаблона потока и извлечь метаданные параметров +2. **Извлечение метаданных**: Извлечь `type`, `description`, `order`, `advanced` и `controlled-by` для каждого параметра, определенного в разделе `parameters` шаблона потока +3. **Поиск определения типа**: Для каждого параметра в шаблоне потока: + Получить определение типа параметра из хранилища схемы/конфигурации, используя поле `type` + Определения типов хранятся с типом "parameter-type" в системе конфигурации + Каждое определение типа содержит схему параметра, значение по умолчанию и правила проверки +4. **Разрешение значения по умолчанию**: + Для каждого параметра, определенного в шаблоне потока: + Проверить, предоставлено ли пользователем значение для этого параметра + Если значение не предоставлено пользователем, использовать значение `default` из определения типа параметра + Создать полную карту параметров, содержащую как предоставленные пользователем, так и значения по умолчанию +5. **Разрешение наследования параметров** (зависимости): + Для параметров с полем `controlled-by`, проверить, было ли предоставлено явное значение + Если явное значение не предоставлено, унаследовать значение от управляющего параметра + Если управляющий параметр также не имеет значения, использовать значение по умолчанию из определения типа + Убедиться в отсутствии циклических зависимостей в отношениях `controlled-by` +6. **Проверка**: Проверить полный набор параметров (предоставленные пользователем, значения по умолчанию и унаследованные) на соответствие определениям типов +7. **Хранение**: Сохранить полный набор разрешенных параметров с экземпляром потока для обеспечения возможности аудита +8. **Подстановка шаблонов**: Заменить заполнители параметров в параметрах процессоров разрешенными значениями +9. **Создание процессоров**: Создать процессоры с подставленными параметрами +>>>>>>> 82edf2d (New md files from RunPod) + +**Важные замечания по реализации**: +Сервис потока ДОЛЖЕН объединять параметры, предоставленные пользователем, со значениями по умолчанию из определений типов параметров +Полный набор параметров (включая примененные значения по умолчанию) ДОЛЖЕН храниться с потоком для обеспечения отслеживаемости +Разрешение параметров происходит при запуске потока, а не при создании экземпляра процессора +Отсутствующие обязательные параметры без значений по умолчанию ДОЛЖНЫ приводить к сбою запуска потока с четким сообщением об ошибке + +<<<<<<< HEAD +#### Наследование параметров с помощью "контролируется" +======= +#### Наследование параметров с помощью controlled-by +>>>>>>> 82edf2d (New md files from RunPod) + +Поле `controlled-by` обеспечивает наследование значений параметров, что особенно полезно для упрощения пользовательских интерфейсов, сохраняя при этом гибкость: + +**Пример сценария**: +<<<<<<< HEAD +Параметр `llm-model` контролирует основную модель LLM +Параметр `llm-rag-model` имеет значение `"controlled-by": "llm-model"` +В простом режиме установка `llm-model` в "gpt-4" автоматически устанавливает `llm-rag-model` в "gpt-4" +В расширенном режиме пользователи могут переопределить `llm-rag-model` другим значением + +**Правила разрешения**: +1. Если параметр имеет явно предоставленное значение, используйте это значение +2. Если нет явного значения и `controlled-by` установлено, используйте значение контролируемого параметра +3. Если контролируемый параметр не имеет значения, используйте значение по умолчанию из определения типа +4. Циклические зависимости в отношениях `controlled-by` приводят к ошибке проверки + +**Поведение пользовательского интерфейса**: +В базовом/простом режиме: Параметры с `controlled-by` могут быть скрыты или показаны как доступные только для чтения со значением, полученным по наследству +В расширенном режиме: Все параметры отображаются и могут быть настроены индивидуально +При изменении контролируемого параметра зависимые параметры автоматически обновляются, если они не были явно переопределены +======= +Параметр `llm-model` управляет основной моделью LLM +Параметр `llm-rag-model` имеет значение `"controlled-by": "llm-model"` +В простом режиме установка `llm-model` в "gpt-4" автоматически устанавливает `llm-rag-model` в "gpt-4" +В расширенном режиме пользователи могут перезаписать `llm-rag-model` другим значением + +**Правила разрешения**: +1. Если параметр имеет явно предоставленное значение, используйте это значение +2. Если нет явного значения и `controlled-by` установлено, используйте значение управляющего параметра +3. Если управляющий параметр не имеет значения, используйте значение по умолчанию из определения типа +4. Циклические зависимости в отношениях `controlled-by` приводят к ошибке проверки + +**Поведение пользовательского интерфейса**: +В режимах "базовый/простой": Параметры с `controlled-by` могут быть скрыты или показаны как доступные только для чтения со унаследованным значением +В расширенном режиме: Все параметры отображаются и могут быть настроены индивидуально +При изменении управляющего параметра зависимые параметры автоматически обновляются, если они не перезаписаны +>>>>>>> 82edf2d (New md files from RunPod) + +#### Интеграция с Pulsar + +1. **Операция Start-Flow** +<<<<<<< HEAD + Операция start-flow в Pulsar должна принимать поле `parameters`, содержащее карту значений параметров + Схема запроса start-flow в Pulsar должна быть обновлена для включения необязательного поля `parameters` +======= + Операция Pulsar start-flow должна принимать поле `parameters`, содержащее карту значений параметров + Схема Pulsar для запроса start-flow должна быть обновлена для включения необязательного поля `parameters` +>>>>>>> 82edf2d (New md files from RunPod) + Пример запроса: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **Операция Get-Flow** + Схему Pulsar для ответа get-flow необходимо обновить, чтобы включить поле `parameters`. + Это позволяет клиентам получать значения параметров, которые были использованы при запуске потока. + Пример ответа: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### Реализация сервиса потоков + +Сервис конфигурации потоков (`trustgraph-flow/trustgraph/config/service/flow.py`) требует следующих улучшений: + +1. **Функция разрешения параметров** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + Эта функция должна: + Извлекать метаданные параметров из раздела `parameters` схемы потока. + Для каждого параметра получать определение его типа из хранилища конфигурации. +<<<<<<< HEAD + Применять значения по умолчанию для любых параметров, которые не предоставлены пользователем. +======= + Применять значения по умолчанию для любых параметров, не предоставленных пользователем. +>>>>>>> 82edf2d (New md files from RunPod) + Обрабатывать отношения наследования `controlled-by`. + Возвращать полный набор параметров. + +2. **Измененный метод `handle_start_flow`** + Вызывать `resolve_parameters` после загрузки схемы потока. + Использовать полный набор разрешенных параметров для подстановки в шаблоне. + Сохранять полный набор параметров (а не только предоставленные пользователем) вместе с потоком. + Проверять, что все необходимые параметры имеют значения. + +3. **Получение типа параметра** + Определения типов параметров хранятся в конфигурации с типом "parameter-type". + Каждое определение типа содержит схему, значение по умолчанию и правила проверки. + Кэшировать часто используемые типы параметров для уменьшения количества обращений к конфигурации. + +#### Интеграция с системой конфигурации + +3. **Хранение объектов потока** + Когда поток добавляется в систему конфигурации компонентом потока в менеджере конфигурации, объект потока должен включать разрешенные значения параметров. + Менеджер конфигурации должен хранить как исходные параметры, предоставленные пользователем, так и разрешенные значения (с применением значений по умолчанию). + Объекты потока в системе конфигурации должны включать: +<<<<<<< HEAD + `parameters`: Конечные разрешенные значения параметров, используемые для потока. +======= + `parameters`: Окончательные разрешенные значения параметров, используемые для потока. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Интеграция с CLI + +4. **Команды CLI для библиотеки** + Команды CLI, которые запускают потоки, должны поддерживать параметры: + Принимать значения параметров через флаги командной строки или файлы конфигурации. + Проверять параметры на соответствие определениям схемы потока перед отправкой. + Поддерживать ввод файлов параметров (JSON/YAML) для сложных наборов параметров. + + Команды CLI, которые отображают потоки, должны отображать информацию о параметрах: + Отображать значения параметров, использованные при запуске потока. + Отображать доступные параметры для схемы потока. + Отображать схемы проверки параметров и значения по умолчанию. + +#### Интеграция с базовым классом процессора + +5. **Поддержка ParameterSpec** + Базовые классы процессоров должны поддерживать подстановку параметров с помощью существующего механизма ParametersSpec. + Класс ParametersSpec (расположенный в том же модуле, что и ConsumerSpec и ProducerSpec) должен быть расширен, если это необходимо, для поддержки подстановки параметров в шаблонах. + Процессоры должны иметь возможность вызывать ParametersSpec для настройки своих параметров со значениями параметров, разрешенными во время запуска потока. + Реализация ParametersSpec должна: + Принимать конфигурации параметров, содержащие заполнители параметров (например, `{model}`, `{temperature}`). + Поддерживать подстановку параметров во время выполнения при создании экземпляра процессора. +<<<<<<< HEAD + Проверять, соответствуют ли подставленные значения ожидаемым типам и ограничениям. +======= + Проверять, что подставленные значения соответствуют ожидаемым типам и ограничениям. +>>>>>>> 82edf2d (New md files from RunPod) + Предоставлять обработку ошибок для отсутствующих или недействительных ссылок на параметры. + +#### Правила подстановки + +Параметры используют формат `{parameter-name}` в параметрах процессора. +Имена параметров в параметрах соответствуют ключам в разделе `parameters` схемы потока. +Подстановка происходит наряду с заменой `{id}` и `{class}`. +Недействительные ссылки на параметры приводят к ошибкам во время запуска. +Проверка типов происходит на основе централизованно хранящегося определения параметра. +**ВАЖНО**: Все значения параметров хранятся и передаются в виде строк. + Числа преобразуются в строки (например, `0.7` становится `"0.7"`). + Булевы значения преобразуются в строчные буквы (например, `true` становится `"true"`). + Это требуется схемой Pulsar, которая определяет `parameters = Map(String())`. + +Пример разрешения: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## Стратегия тестирования + +Юнит-тесты для проверки схемы параметров +Интеграционные тесты для проверки подстановки параметров в параметры процессора +Комплексные тесты для запуска потоков с разными значениями параметров +UI-тесты для генерации и проверки форм параметров +Тесты производительности для потоков со многими параметрами +<<<<<<< HEAD +Пограничные случаи: отсутствующие параметры, неверные типы, неопределенные ссылки на параметры +======= +Краевые случаи: отсутствующие параметры, неверные типы, неопределенные ссылки на параметры +>>>>>>> 82edf2d (New md files from RunPod) + +## План миграции + +1. Система должна продолжать поддерживать шаблоны потоков без объявленных параметров. + 2. Система должна продолжать поддерживать потоки без указанных параметров: +<<<<<<< HEAD +Это работает для потоков без параметров и для потоков с параметрами (у которых есть значения по умолчанию). + + (имеют значения по умолчанию). + +## Открытые вопросы + +В: Должны ли параметры поддерживать сложные вложенные объекты или ограничиваться простыми типами? +О: Значения параметров будут закодированы в виде строки, поэтому, вероятно, нам стоит + ограничиваться строками. + +В: Должны ли быть разрешены заполнители параметров в именах очередей или только в + параметрах? +О: Только в параметрах, чтобы избежать странных инъекций и пограничных случаев. +======= +Это работает для потоков без параметров и для потоков с параметрами + (у них есть значения по умолчанию). + +## Открытые вопросы + + +В: Должны ли параметры поддерживать сложные вложенные объекты или ограничиваться простыми типами? +О: Значения параметров будут закодированы в виде строки, поэтому, вероятно, нам стоит + придерживаться строк. + +В: Должны ли быть разрешены заполнители параметров в именах очередей или только в + параметрах? +О: Только в параметрах, чтобы избежать странных внедрений и пограничных случаев. +>>>>>>> 82edf2d (New md files from RunPod) + +В: Как обрабатывать конфликты между именами параметров и системными переменными, такими как + `id` и `class`? +О: Недопустимо указывать id и class при запуске потока. + +В: Должны ли мы поддерживать вычисляемые параметры (выводимые из других параметров)? +<<<<<<< HEAD +О: Только простая подстановка строк, чтобы избежать странных инъекций и пограничных случаев. +======= +О: Только простая замена строк, чтобы избежать странных внедрений и пограничных случаев. +>>>>>>> 82edf2d (New md files from RunPod) + +## Ссылки + +Спецификация JSON Schema: https://json-schema.org/ +<<<<<<< HEAD +Спецификация определения шаблона потока: docs/tech-specs/flow-class-definition.md +======= +Спецификация определения схемы потока: docs/tech-specs/flow-class-definition.md +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/flow-configurable-parameters.sw.md b/docs/tech-specs/flow-configurable-parameters.sw.md new file mode 100644 index 00000000..61dbcbca --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.sw.md @@ -0,0 +1,712 @@ +--- +layout: default +title: "Mfumo wa Uwekaji Njia (Flow Blueprint) - Vigezo Vinavyoweza Kubadilishwa - Maelezo ya Kiufundi" +parent: "Swahili (Beta)" +--- + +# Mfumo wa Uwekaji Njia (Flow Blueprint) - Vigezo Vinavyoweza Kubadilishwa - Maelezo ya Kiufundi + +> **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. + +## Maelezo + +Maelezo haya yanaeleza utekelezaji wa vigezo vinavyoweza kubadilishwa kwa mifumo ya uwekaji njia (flow blueprints) katika TrustGraph. Vigezo huruhusu watumiaji kubadilisha vigezo vya kichakato (processor) wakati wa kuanzisha mfumo wa uwekaji njia kwa kutoa maadili ambayo hubadilisha nafasi za vigezo katika ufafanuzi wa mfumo wa uwekaji njia. + +<<<<<<< HEAD +Vigezo hufanya kazi kupitia ubadilishaji wa vigezo vya kishabaha katika vigezo vya kichakato, sawa na jinsi vigezo vya `{id}` na `{class}` hufanya kazi, lakini kwa maadili ambayo hutolewa na mtumiaji. +======= +Vigezo hufanya kazi kupitia ubadilishaji wa vigezo vya kishabaha katika vigezo vya kichakato, sawa na jinsi vigezo `{id}` na `{class}` hufanya kazi, lakini kwa maadili ambayo hutolewa na mtumiaji. +>>>>>>> 82edf2d (New md files from RunPod) + +Uunganishaji huu unaunga mkono matumizi manne makuu: + +1. **Uchaguzi wa Mfumo**: Kuruhusu watumiaji kuchagua mifumo tofauti ya LLM (e.g., `gemma3:8b`, `gpt-4`, `claude-3`) kwa vichakato. +2. **Uwekaji Njia wa Rasilimali**: Kurekebisha vigezo vya kichakato kama vile saizi za sehemu, saizi za kundi, na mipaka ya utendaji. +3. **Urekebishaji wa Tabia**: Kubadilisha tabia ya kichakato kupitia vigezo kama vile halijoto, max-tokens, au viwango vya urejesho. +4. **Vigezo Maalum ya Mazingira**: Kusanidi sehemu za mwisho, funguo za API, au anwani za mtandao (URLs) maalum kwa eneo kwa kila uwekaji. + +## Lengo + +**Uwekaji Njia wa Kichakato Unaoweza Kubadilishwa**: Kuruhusu uwekaji njia wa vigezo vya kichakato wakati wa utendaji kupitia ubadilishaji wa vigezo. +**Uthibitisho wa Vigezo**: Kutoa ukaguzi wa aina na uthibitisho wa vigezo wakati wa kuanzisha mfumo wa uwekaji njia. +**Maadili ya Msingi**: Kusaidia maadili ya msingi ambayo yanafaa lakini kuruhusu ubadilishaji kwa watumiaji wa hali ya juu. +**Ubadilishaji wa Kishabaha**: Kubadilisha nafasi za vigezo katika vigezo vya kichakato kwa urahisi. +<<<<<<< HEAD +**Uunganishaji wa UI**: Kuruhusu uingizaji wa vigezo kupitia interfaces za API na UI. +======= +**Uunganisho wa UI**: Kuruhusu uingizaji wa vigezo kupitia interfaces za API na UI. +>>>>>>> 82edf2d (New md files from RunPod) +**Usalama wa Aina**: Kuhakikisha kwamba aina za vigezo zinafanana na aina zilizotarajiwa za vigezo vya kichakato. +**Ufafanuzi**: Mifumo ya vigezo inayojieleza yenyewe ndani ya ufafanuzi wa mifumo ya uwekaji njia. +**Ulinganifu na Mifumo ya Zamani**: Kuhifadhi ulinganifu na mifumo ya uwekaji njia iliyopo ambayo haitumii vigezo. + +## Asili + +<<<<<<< HEAD +Mifumo ya uwekaji njia katika TrustGraph sasa inaunga mkono vigezo vya kichakato ambavyo yanaweza kuwa na maadili thabiti au nafasi za vigezo. Hii huunda fursa ya urekebishaji wakati wa utendaji. +======= +Mifumo ya uwekaji njia katika TrustGraph sasa inasaidia vigezo vya kichakato ambavyo yanaweza kuwa na maadili thabiti au nafasi za vigezo. Hii huunda fursa ya urekebishaji wakati wa utendaji. +>>>>>>> 82edf2d (New md files from RunPod) + +Vigezo vya kichakato vya sasa vinaunga mkono: +Maadili thabiti: `"model": "gemma3:12b"` +Nafasi za vigezo: `"model": "gemma3:{model-size}"` + +Maelezo haya yanaeleza jinsi vigezo: +Yanavyoonyeshwa katika ufafanuzi wa mifumo ya uwekaji njia +Yanavyothibitishwa wakati wa kuanzisha mifumo ya uwekaji njia +Yanavyobadilishwa katika vigezo vya kichakato +Yanavyoonyeshwa kupitia API na UI + +Kwa kutumia vigezo vya kichakato, TrustGraph inaweza: +Kupunguza uduzi wa mifumo ya uwekaji njia kwa kutumia vigezo kwa tofauti +Kuruhusu watumiaji kurekebisha tabia ya kichakato bila kubadilisha ufafanuzi +Kusaidia usanidi maalum wa mazingira kupitia maadili ya vigezo +Kuhifadhi usalama wa aina kupitia uthibitisho wa shabaha ya vigezo + +<<<<<<< HEAD +## Ubunifu wa Kiufundi + +### Muundo + +Mfumo wa vigezo vinavyoweza kubadilishwa unahitaji vipengele vifuatavyo vya kiufundi: + +1. **Ufafanuzi wa Shabaha ya Vigezo** + Ufafanuzi wa vigezo unaotegemea shabaha ya JSON ndani ya metadata ya mfumo wa uwekaji njia. +======= +## Muundo wa Kiufundi + +### Usanifu + +Mfumo wa vigezo unaoweza kubadilishwa unahitaji vipengele vifuatavyo vya kiufundi: + +1. **Ufafanuzi wa Shabaha ya Vigezo** + Ufafanuzi wa vigezo unaotegemea kwenye JSON Schema ndani ya metadata ya mfumo wa uwekaji njia. +>>>>>>> 82edf2d (New md files from RunPod) + Ufafanuzi wa aina ikiwa ni pamoja na aina ya maandishi, nambari, ya kweli, enum, na aina ya kitu. + Kanuni za uthibitisho ikiwa ni pamoja na maadili ya chini/juu, mifumo, na mashamba yanayohitajika. + + Moduli: trustgraph-flow/trustgraph/flow/definition.py + +<<<<<<< HEAD +2. **Injini ya Ufumbuzi wa Vigezo** + Uthibitisho wa vigezo wakati wa utendaji dhidi ya shabaha. + Matumizi ya maadili ya msingi kwa vigezo ambavyo havijatolewa. + Uingizaji wa vigezo katika muktadha wa utendaji wa mfumo wa uwekaji njia. +======= +2. **Injini ya Urekebishaji wa Vigezo** + Uthibitisho wa vigezo wakati wa utendaji dhidi ya shabaha. + Matumizi ya maadili ya msingi kwa vigezo ambavyo havijatolewa. + Uingizaji wa vigezo katika muktadha wa utekelezaji wa mfumo wa uwekaji njia. +>>>>>>> 82edf2d (New md files from RunPod) + Marekebisho na ubadilishaji wa aina kama inavyohitajika. + + Moduli: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +<<<<<<< HEAD +3. **Uunganishaji wa Hifadhi ya Vigezo** +======= +3. **Uunganisho wa Hifadhi ya Vigezo** +>>>>>>> 82edf2d (New md files from RunPod) + Kupata ufafanuzi wa vigezo kutoka kwa duka la shabaha/usanidi. + Kuhifadhi ufafanuzi wa vigezo unaotumika mara kwa mara. + Uthibitisho dhidi ya shabaha zilizohifadhiwa katikati. + + Moduli: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **Viendelezi vya Kuanzisha Mfumo wa Uwekaji Njia** + Viendelezi vya API kukubali maadili ya vigezo wakati wa kuanzisha mfumo wa uwekaji njia. +<<<<<<< HEAD + Ufumbuzi wa ramani ya vigezo (majina ya mifumo ya uwekaji njia hadi majina ya ufafanuzi). +======= + Urekebishaji wa ramani ya vigezo (majina ya mifumo kwa majina ya ufafanuzi). +>>>>>>> 82edf2d (New md files from RunPod) + Usimamizi wa makosa kwa mchanganyiko usiofaa wa vigezo. + + Moduli: trustgraph-flow/trustgraph/flow/launcher.py + +5. **Fomu za Vigezo za UI** +<<<<<<< HEAD + Uundaji wa fomu ya kiotomatiki kutoka kwa metadata ya vigezo ya mfumo wa uwekaji njia. + Kuonyesha vigezo kwa utaratibu kwa kutumia `order`. + Laha za vigezo za maelezo kwa kutumia `description`. + Uthibitisho wa ingizo dhidi ya ufafanuzi wa aina ya vigezo. + Vigezo vilivyosanidiwa na vipuli. +======= + Uzalishaji wa fomu ya kiotomatiki kutoka kwa metadata ya vigezo ya mfumo wa uwekaji njia. + Kuonyesha vigezo kwa utaratibu kwa kutumia `order`. + Laha za vigezo za maelezo kwa kutumia `description`. + Uthibitisho wa uingizaji dhidi ya ufafanuzi wa aina ya vigezo. + Vipangilio na vipuli vya vigezo. +>>>>>>> 82edf2d (New md files from RunPod) + + Moduli: trustgraph-ui/components/flow-parameters/ + +### Mifano ya Data + +#### Ufafanuzi wa Vigezo (Imehifadhiwa katika Shabaha/Usanidi) +<<<<<<< HEAD +Ufafanuzi wa vigezo unaotegemea shabaha ya JSON ndani ya metadata ya mfumo wa uwekaji njia. +Ufafanuzi wa aina ikiwa ni pamoja na aina ya maandishi, nambari, ya kweli, enum, na aina ya kitu. +Kanuni za uthibitisho ikiwa ni pamoja na maadili ya chini/juu, mifumo, na mashamba yanayohitajika. +======= + +Ufafanuzi wa vigezo umehifadhiwa ndani ya duka la shabaha/usanidi. + +>>>>>>> 82edf2d (New md files from RunPod) +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### Mpango wa Mchakato na Marejeleo ya Vigezo + +Mipango ya mchakato inaelezea metadata ya vigezo pamoja na marejeleo ya aina, maelezo, na mpangilio: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +<<<<<<< HEAD +Sehemu ya `parameters` inaeleza jina la kila parameter (funguo) inayohusiana na mtiririko, na inaunganisha na vitu vya metadata ya parameter ambavyo vina: +`type`: Rejea kwa ufafanuzi wa parameter uliotolewa kwa njia ya kati (k.m., "llm-model") +`description`: Maelezo ambayo yanaweza kusomwa na binadamu kwa ajili ya kuonyeshwa kwenye kiolesura (UI) +`order`: Mpangilio wa kuonyeshwa wa parameter katika fomu (nambari ndogo huonyeshwa kwanza) +`advanced` (hiari): Bendera ya boolean inayoelezea ikiwa hii ni parameter ya hali ya juu (ya kawaida: false). Ikiwa imewekwa kuwa "true", kiolesura kinaweza kuficha parameter hii kwa chagu ku, au kuiweka katika sehemu ya "Advanced" +`controlled-by` (hiari): Jina la parameter nyingine ambayo inadhibiti thamani ya parameter hii wakati katika hali rahisi. Ikiwa imeingizwa, parameter hii inaruhusu thamani yake kutoka kwa parameter inayodhibiti, isipokuwa ikiwa imebadilishwa wazi. + +Mbinu hii inaruhusu: +Ufafanuzi wa aina ya parameter unaoweza kutumika tena katika mipangilio mingi. +Usimamizi na uthibitishaji wa aina ya parameter katika eneo moja. +Maelezo na mpangilio wa parameter unaohusiana na kila mtiririko. +Uzoefu bora wa kiolesura (UI) kwa kutumia fomu za parameter zenye maelezo. +Uthibitishaji thabiti wa parameter katika mitiririko yote. +======= +Sehemu ya `parameters` inaeleza jina la parameter (funguo) inayohusiana na mtiririko, na inaunganisha na vitu vya metadata ya parameter ambavyo vina: +`type`: Rejea kwa ufafanuzi wa parameter uliotolewa kwa njia ya kati (k.m., "llm-model") +`description`: Maelezo ambayo yanaweza kusomwa na binadamu kwa ajili ya kuonyeshwa kwenye kiolesura (UI) +`order`: Mfululizo wa kuonyeshwa kwa fomu za parameter (nambari ndogo huonyeshwa kwanza) +`advanced` (hiari): Bendera ya Boolean inayoelezea ikiwa hii ni parameter ya hali ya juu (ya kawaida: false). Ikiwa imewekwa kuwa "true", kiolesura kinaweza kuficha parameter hii kwa chaguльку au kuiweka katika sehemu ya "Advanced" +`controlled-by` (hiari): Jina la parameter nyingine ambayo inadhibiti thamani ya parameter hii wakati katika hali rahisi. Ikiwa imeingizwa, parameter hii inaruhusu thamani yake kutoka kwa parameter inayodhibiti, isipokuwa ikiwa imebadilishwa wazi. + +Mbinu hii inaruhusu: +Ufafanuzi wa aina ya parameter unaoweza kutumika tena katika mipangilio mingi ya mtiririko. +Usimamizi na uthibitishaji wa aina ya parameter unaozingatia. +Maelezo na mpangilio wa parameter unaozingatia mtiririko. +Uzoefu bora wa kiolesura (UI) na fomu za parameter zenye maelezo. +Uthibitishaji thabiti wa parameter katika mitiririko. +>>>>>>> 82edf2d (New md files from RunPod) +Kuongeza kwa urahisi aina mpya za parameter za kawaida. +Kiolesura kilichorahisishwa na mgawanyiko wa hali ya msingi/ya hali ya juu. +Urithi wa thamani ya parameter kwa mipangilio inayohusiana. + +#### Ombi la Uzinduzi wa Mtiririko + +API ya uzinduzi wa mtiririko inakubali parameter kwa kutumia majina ya parameter ya mtiririko: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +Kumbuka: Katika mfano huu, `llm-rag-model` haitoa maelezo wazi lakini itapokea thamani "claude-3" kutoka kwa `llm-model` kutokana na uhusiano wake wa `controlled-by`. Vile vile, `chunk-overlap` inaweza kupokea thamani iliyohitajiwa kulingana na `chunk-size`. + +Mfumo utafanya: +1. Kuchukua metadata ya vigezo kutoka ufafanuzi wa mpango (blueprint). +2. Kuunganisha majina ya vigezo vya mpango na ufafanuzi wao wa aina (e.g., `llm-model` → `llm-model` aina). +3. Kutatua uhusiano wa "controlled-by" (e.g., `llm-rag-model` inarithi kutoka kwa `llm-model`). +<<<<<<< HEAD +4. Kuthibitisha maadili yaliyotolewa na mtumiaji na yaliyorithiwa dhidi ya ufafanuzi wa aina ya vigezo. +======= +4. Kuthibitisha maadili yaliyotolewa na mtumiaji na yaliyorithishwa dhidi ya ufafanuzi wa aina ya vigezo. +>>>>>>> 82edf2d (New md files from RunPod) +5. Kubadilisha maadili yaliyotatuliwa katika vigezo vya kichakataji (processor) wakati wa kuunda mpango. + +### Maelezo ya Utendaji + +#### Mchakato wa Kutatua Vigezo + +Wakati mpango unaanza, mfumo hufanya hatua zifuatazo za kutatua vigezo: + +1. **Kupakia Mpango (Flow Blueprint)**: Pakia ufafanuzi wa mpango na uchukue metadata ya vigezo. +<<<<<<< HEAD +2. **Kuchukua Metadata**: Chukua `type`, `description`, `order`, `advanced`, na `controlled-by` kwa kila kiparamu kilichoainishwa katika sehemu ya `parameters` ya ufafanuzi wa mpango. +3. **Kutafuta Ufafanuzi wa Aina**: Kwa kila kiparamu katika ufafanuzi wa mpango: + Pata ufafanuzi wa aina ya kiparamu kutoka kwa duka la schema/config kwa kutumia sehemu ya `type`. + Ufafanuzi wa aina huhifadhiwa na aina "parameter-type" katika mfumo wa config. + Kila ufafanuzi wa aina una schema ya kiparamu, thamani ya chaguo-msingi, na sheria za uthibitishaji. +4. **Kutatua Thamani ya Chaguo-msingi**: + Kwa kila kiparamu kilichoainishwa katika ufafanuzi wa mpango: + Angalia ikiwa mtumiaji ametoa thamani kwa kiparamu hiki. + Ikiwa hakuna thamani iliyotolewa na mtumiaji, tumia thamani ya `default` kutoka kwa ufafanuzi wa aina ya kiparamu. + Unda ramani kamili ya vigezo inayojumuisha maadili yaliyotolewa na mtumiaji na maadili chaguo-msingi. +5. **Kutatua Ufuataji wa Vigezo** (uhusiano wa "controlled-by"): + Kwa vigezo vyenye sehemu ya `controlled-by`, angalia ikiwa thamani ilitolewa wazi. + Ikiwa hakuna thamani iliyotolewa wazi, arithia thamani kutoka kwa kiparamu kinachodhibiti. + Ikiwa kiparamu kinachodhibiti pia hakina thamani, tumia chaguo-msingi kutoka kwa ufafanuzi wa aina. + Hakikisha kuwa hakuna utegemezi wa mzunguko katika uhusiano wa `controlled-by`. +6. **Uthibitishaji**: Thibitisha seti kamili ya vigezo (vile vilivyotolewa na mtumiaji, chaguo-msingi, na vile vilivyorithiwa) dhidi ya ufafanuzi wa aina. +======= +2. **Kuchukua Metadata**: Chukua `type`, `description`, `order`, `advanced`, na `controlled-by` kwa kila kigezo kilichoainishwa katika sehemu ya `parameters` ya ufafanuzi wa mpango. +3. **Kutafuta Ufafanuzi wa Aina**: Kwa kila kigezo katika ufafanuzi wa mpango: + Pata ufafanuzi wa aina ya kigezo kutoka kwa duka la schema/config kwa kutumia sehemu ya `type`. + Ufafanuzi wa aina huhifadhiwa na aina "parameter-type" katika mfumo wa config. + Kila ufafanuzi wa aina una schema ya kigezo, thamani ya chaguo-msingi, na sheria za uthibitishaji. +4. **Kutatua Thamani ya Chaguo-msingi**: + Kwa kila kigezo kilichoainishwa katika ufafanuzi wa mpango: + Angalia ikiwa mtumiaji ametoa thamani kwa kigezo hiki. + Ikiwa hakuna thamani iliyotolewa na mtumiaji, tumia thamani ya `default` kutoka kwa ufafanuzi wa aina ya kigezo. + Unda ramani kamili ya vigezo inayojumuisha maadili yaliyotolewa na mtumiaji na maadili chaguo-msingi. +5. **Kutatua Ufuasi wa Vigezo** (uhusiano wa "controlled-by"): + Kwa vigezo vyenye sehemu ya `controlled-by`, angalia ikiwa thamani ilitolewa wazi. + Ikiwa hakuna thamani iliyotolewa wazi, arithia thamani kutoka kwa kigezo kinachodhibiti. + Ikiwa kigezo kinachodhibiti pia hakina thamani, tumia chaguo-msingi kutoka kwa ufafanuzi wa aina. + Hakikisha kuwa hakuna utegemezi wa mzunguko katika uhusiano wa `controlled-by`. +6. **Uthibitishaji**: Thibitisha seti kamili ya vigezo (vile vilivyotolewa na mtumiaji, chaguo-msingi, na vile vilivyorithishwa) dhidi ya ufafanuzi wa aina. +>>>>>>> 82edf2d (New md files from RunPod) +7. **Uhifadhi**: Hifadhi seti kamili ya vigezo yaliyotatuliwa pamoja na mfano wa mpango kwa ajili ya uhakiki. +8. **Ubadilishaji wa Kigezo**: Badilisha nafasi za kigezo katika vigezo vya kichakataji na maadili yaliyotatuliwa. +9. **Uundaji wa Kichakataji**: Unda vichakataji na vigezo vilivyobadilishwa. + +**Maelezo Muhimu ya Utendaji:** +<<<<<<< HEAD +Huduma ya mpango INAVYOHITAJI kuchanganya vigezo vilivyotolewa na mtumiaji na chaguo-msingi kutoka kwa ufafanuzi wa aina ya kiparamu. +Seti kamili ya vigezo (ikiwa ni pamoja na chaguo-msingi zilizotumiwa) INAVYOHITAJI kuhifadhiwa na mpango kwa ajili ya ufuatiliaji. +Kutatua vigezo hufanyika wakati wa kuanza kwa mpango, sio wakati wa kuunda kichakataji. +Vigezo muhimu ambavyo havina chaguo-msingi HAVIHUITAJI kusababisha kuanza kwa mpango kushindwa na ujumbe wa kosa wazi. + +#### Ufuataji wa Vigezo na "controlled-by" + +Sehemu ya `controlled-by` inaruhusu urithi wa thamani ya kiparamu, ambayo ni muhimu sana kwa kurahisisha mazingira ya mtumiaji huku ikiendelea kudumisha uwezekano: + +**Mfano wa Matukio:** +Kiparamu cha `llm-model` kinadhibiti mfumo mkuu wa LLM. +Kiparamu cha `llm-rag-model` kina `"controlled-by": "llm-model"`. +Katika hali rahisi, kuweka `llm-model` kwa "gpt-4" huanzisha kiotomatiki `llm-rag-model` kwa "gpt-4" pia. +Katika hali ya juu, watumiaji wanaweza kubadilisha `llm-rag-model` na thamani tofauti. + +**Sheria za Kutatua:** +1. Ikiwa kiparamu kina thamani iliyotolewa wazi, tumia thamani hiyo. +2. Ikiwa hakuna thamani iliyotolewa wazi na `controlled-by` imewekwa, tumia thamani ya kiparamu kinachodhibiti. +3. Ikiwa kiparamu kinachodhibiti hakina thamani, rudi kwenye chaguo-msingi kutoka kwa ufafanuzi wa aina. +4. Utendaji wa mzunguko katika uhusiano wa `controlled-by` husababisha kosa la uthibitishaji. + +**Tabia ya UI:** +Katika hali ya msingi/rahisi: Vigezo vyenye `controlled-by` vinaweza kufichwa au kuonyeshwa kama visivyo na uwezo wa kubadilishwa na thamani iliyoarithi. +Katika hali ya juu: Vigezo vyote huonyeshwa na vinaweza kusanidiwa kivyake. +Wakati kiparamu kinachodhibiti kinapobadilika, vigezo vinavyotegemea hupatikana kiotomatiki isipokuwa zimebadilishwa wazi. + +#### Uunganisho wa Pulsar +======= +Huduma ya mpango INAVYOKWENDA kuchanganya vigezo vilivyotolewa na mtumiaji na chaguo-msingi kutoka kwa ufafanuzi wa aina ya kigezo. +Seti kamili ya vigezo (ikiwa ni pamoja na chaguo-msingi zilizotumiwa) INAVYOKWENDA kuhifadhiwa na mpango kwa ajili ya ufuatiliaji. +Kutatua vigezo hufanyika wakati wa kuanza kwa mpango, sio wakati wa kuunda kichakataji. +Vigezo muhimu ambavyo havina chaguo-msingi HAVI kukatisha kuanza kwa mpango na kuonyesha ujumbe wa kosa wazi. + +#### Ufuasi wa Vigezo na "controlled-by" + +Sehemu ya `controlled-by` inaruhusu urithi wa thamani ya kigezo, ambayo ni muhimu sana kwa kurahisisha mazingira ya mtumiaji huku ikiendelea kuwezesha utendaji: + +**Mfano wa Matukio:** +Kigezo cha `llm-model` kinadhibiti mfumo mkuu wa LLM. +Kigezo cha `llm-rag-model` kina `"controlled-by": "llm-model"`. +Katika hali rahisi, kuweka `llm-model` kwa "gpt-4" hufanya `llm-rag-model` pia iwe "gpt-4" kiotomatiki. +Katika hali ya juu, watumiaji wanaweza kubadilisha `llm-rag-model` na thamani tofauti. + +**Sheria za Kutatua:** +1. Ikiwa kigezo kina thamani iliyotolewa wazi, tumia thamani hiyo. +2. Ikiwa hakuna thamani iliyotolewa na `controlled-by` imewekwa, tumia thamani ya kigezo kinachodhibiti. +3. Ikiwa kigezo kinachodhibiti hakina thamani, rudi kwenye chaguo-msingi kutoka kwa ufafanuzi wa aina. +4. Utendaji wa mzunguko katika uhusiano wa `controlled-by` husababisha kosa la uthibitishaji. + +**Tabia ya UI:** +Katika hali ya msingi/rahisi: Vigezo vyenye `controlled-by` vinaweza kufichwa au kuonyeshwa kama visivyo na uwezo (read-only) na thamani iliyoorithishwa. +Katika hali ya juu: Vigezo vyote huonyeshwa na vinaweza kusanidiwa kivyake. +Wakati kigezo kinachodhibiti kinapobadilika, vigezo vinavyotegemea hupatikana kiotomatiki isipokuwa ikiwa vimewekwa kuwa visivyo na uwezo. + +#### Ujumuishaji wa Pulsar +>>>>>>> 82edf2d (New md files from RunPod) + +1. **Operesheni ya Kuanza-Mpango** + Operesheni ya kuanza-mpango ya Pulsar inahitaji kukubali sehemu ya `parameters` inayojumuisha ramani ya maadili ya vigezo. + Schema ya ombi la kuanza-mpango ya Pulsar inapaswa kusasishwa ili kujumuisha sehemu ya `parameters` ya hiari. + Mfano wa ombi: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +<<<<<<< HEAD +2. **Operesheni ya Kupata Mtiririko** + Mfumo wa Pulsar wa jibu la "get-flow" lazima ubadilishwe ili kujumuisha sehemu ya `parameters` + Hii inaruhusu wateja kupata maadili ya vigezo ambayo yalitumiwa wakati mtiririko ulipoanzishwa. + Jibu la mfano: +======= +2. **Operesheni ya Kupata Mtiririko (Get-Flow)** + Mfumo wa Pulsar wa jibu la operesheni ya kupata mtiririko lazima ubadilishwe ili kujumuisha sehemu `parameters` + Hii inaruhusu wateja kupata maadili ya vigezo ambayo yalitumiwa wakati mtiririko ulipoanzishwa. + Mfano wa jibu: +>>>>>>> 82edf2d (New md files from RunPod) + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### Utendaji wa Huduma ya Mchakato + +Huduma ya usanidi wa mchakato (`trustgraph-flow/trustgraph/config/service/flow.py`) inahitaji maboresho yafuatayo: + +1. **Kitendaji cha Ufafanuzi wa Vigezo** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + Kazi hii inapaswa: +<<<<<<< HEAD + Kuchukua metadata ya vigezo kutoka sehemu ya `parameters` ya mpango wa mtiririko + Kwa kila vigezo, pata ufafanuzi wa aina kutoka kwa hifadhi ya usanidi + Tumia maadili chaguu kwa vigezo vyovyote ambavyo havijatolewa na mtumiaji + Kushughulikia uhusiano wa urithi wa `controlled-by` + Kurudisha seti kamili ya vigezo + +2. **Njia Iliyorekebishwa ya `handle_start_flow`** + Piga `resolve_parameters` baada ya kupakua mpango wa mtiririko + Tumia seti kamili ya vigezo vilivyomalizika kwa kubadilisha kigezo + Hifadhi seti kamili ya vigezo (sio tu zile zilizotolewa na mtumiaji) pamoja na mtiririko + Thibitisha kwamba vigezo vyote muhimu vina maadili + +3. **Uchukuzi wa Aina ya Vigezo** + Ufafanuzi wa aina ya vigezo huhifadhiwa katika usanidi na aina "parameter-type" + Kila ufafanuzi wa aina una schema, thamani chaguo, na sheria za uthibitishaji + Hifadhi aina za vigezo zinazotumika mara kwa mara ili kupunguza utafutaji wa usanidi +======= + Kuchukua metadata ya vigezo kutoka sehemu ya `parameters` ya mpango wa mtiririko. + Kwa kila vigezo, pata ufafanuzi wa aina yake kutoka kwa hifadhi ya usanidi. + Tumia maadili chaguu kwa vigezo vyovyote ambavyo havijatolewa na mtumiaji. + Kushughulikia uhusiano wa urithi wa `controlled-by`. + Kurudisha seti kamili ya vigezo. + +2. **Njia Iliyorekebishwa ya `handle_start_flow`** + Piga `resolve_parameters` baada ya kupakua mpango wa mtiririko. + Tumia seti kamili ya vigezo vilivyofafanuliwa kwa badiliko la kiolezo. + Hifadhi seti kamili ya vigezo (si tu ile iliyotolewa na mtumiaji) pamoja na mtiririko. + Thibitisha kuwa vigezo vyote muhimu vina maadili. + +3. **Uchukuzi wa Aina ya Vigezo** + Ufafanuzi wa aina ya vigezo huhifadhiwa katika usanidi na aina "parameter-type". + Kila ufafanuzi wa aina una schema, thamani chaguo, na sheria za uthibitishaji. + Hifadhi aina za vigezo zinazotumika mara kwa mara ili kupunguza utafutaji wa usanidi. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Ujumuishaji wa Mfumo wa Usanidi + +3. **Uhifadhi wa Kitu cha Mtiririko** +<<<<<<< HEAD + Wakati mtiririko unaongezwa kwenye mfumo wa usanidi na kipengele cha mtiririko katika meneja wa usanidi, kitu cha mtiririko lazima kiwe na maadili yaliyomalizika ya vigezo + Meneja wa usanidi lazima ahifadhi vigezo vyote vilivyotolewa na mtumiaji na maadili yaliyomalizika (pamoja na maadili chaguo) + Vitu vya mtiririko katika mfumo wa usanidi vinapaswa kujumuisha: + `parameters`: Maadili ya vigezo yaliyomalizika ambayo hutumiwa kwa mtiririko +======= + Wakati mtiririko unaongezwa kwenye mfumo wa usanidi na kipengele cha mtiririko katika meneja wa usanidi, kitu cha mtiririko lazima kiwe na maadili yaliyofafanuliwa ya vigezo. + Meneja wa usanidi lazima ahifadhi vigezo vyote vilivyotolewa na mtumiaji na maadili yaliyofafanuliwa (pamoja na maadili chaguo). + Vitu vya mtiririko katika mfumo wa usanidi vinapaswa kujumuisha: + `parameters`: Maadili yaliyofafanuliwa ya vigezo ambayo hutumiwa kwa mtiririko. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Ujumuishaji wa CLI + +4. **Amani za CLI za Maktaba** + Amani za CLI ambazo huanzisha mitiririko zinahitaji usaidizi wa vigezo: +<<<<<<< HEAD + Kukubali maadili ya vigezo kupitia bendera za mstari wa amri au faili za usanidi + Thibitisha vigezo dhidi ya ufafanuzi wa mpango wa mtiririko kabla ya kuwasilisha + Usaidizi wa uingizaji wa faili ya vigezo (JSON/YAML) kwa seti ngumu ya vigezo + + Amani za CLI ambazo zinaonyesha mitiririko zinahitaji kuonyesha habari ya vigezo: + Onyesha maadili ya vigezo ambayo yalitumiwa wakati mtiririko ulipoanzishwa + Onyesha vigezo vinavyopatikana kwa mpango wa mtiririko + Onyesha schema na maadili chaguo ya vigezo +======= + Kukubali maadili ya vigezo kupitia bendera za mstari wa amri au faili za usanidi. + Thibitisha vigezo dhidi ya ufafanuzi wa mpango wa mtiririko kabla ya kuwasilisha. + Usaidizi wa uingizaji wa faili ya vigezo (JSON/YAML) kwa seti ngumu ya vigezo. + + Amani za CLI ambazo zinaonyesha mitiririko zinahitaji kuonyesha taarifa za vigezo: + Onyesha maadili ya vigezo ambayo yalitumiwa wakati mtiririko ulipoanzishwa. + Onyesha vigezo vinavyopatikana kwa mpango wa mtiririko. + Onyesha schema na maadili chaguo ya vigezo. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Ujumuishaji wa Darasa la Msingi la Processor + +5. **Usaidizi wa ParameterSpec** +<<<<<<< HEAD + Darasa za msingi za processor zinahitaji kusaidia kubadilisha vigezo kupitia utaratibu uliopo wa ParametersSpec + Darasa la ParametersSpec (lililopo katika moduli sawa na ConsumerSpec na ProducerSpec) linapaswa kuimarishwa ikiwa ni lazima ili kusaidia kubadilisha kigezo + Wasindikaji wanapaswa kuwa na uwezo wa kuita ParametersSpec ili kusanidi vigezo vyao na maadili ya vigezo ambayo yamefafanuliwa wakati wa kuzindua mtiririko + Utaratibu wa utekelezaji wa ParametersSpec lazima: + Kukubali usanidi wa vigezo ambao una nafasi za vigezo (k.m., `{model}`, `{temperature}`) + Kusaidia kubadilisha vigezo wakati wa uendeshaji wa wasindikaji + Thibitisha kwamba maadili yaliyobadilishwa yanalingana na aina na vikwazo vilivyotarajiwa + Kutoa ushughulikiaji wa makosa kwa marejeleo yaliyopotea au yasiyo halali ya vigezo + +#### Kanuni za Kubadilisha + +Vigezo hutumia muundo wa `{parameter-name}` katika vigezo vya wasindikaji +Majina ya vigezo katika vigezo yanalingana na funguo katika sehemu ya `parameters` ya mtiririko +Kubadilisha hufanyika pamoja na `{id}` na `{class}` +Marejeleo yasiyo halali ya vigezo husababisha makosa wakati wa kuzindua +Uthibitisho wa aina hutokea kulingana na ufafanuzi wa vigezo uliohifadhiwa katikati +**MUHIMU**: Maadili yote ya vigezo huhifadhiwa na hutumwa kama maandishi + Nambari hubadilishwa kuwa maandishi (k.m., `0.7` inakuwa `"0.7"`) + Booleans hubadilishwa kuwa maandishi ya chini (k.m., `true` inakuwa `"true"`) + Hii inahitajika na schema ya Pulsar ambayo ina `parameters = Map(String())` +======= + Darasa za msingi za processor zinahitaji kusaidia badiliko la vigezo kupitia utaratibu uliopo wa ParametersSpec. + Darasa la ParametersSpec (lililopo katika moduli sawa na ConsumerSpec na ProducerSpec) linapaswa kuimarishwa ikiwa ni lazima ili kusaidia badiliko la kiolezo la vigezo. + Wasindikaji wanapaswa kuwa na uwezo wa kutumia ParametersSpec ili kusanidi vigezo vyao na maadili ya vigezo ambayo yamefafanuliwa wakati wa kuzindua mtiririko. + Utaratibu wa utekelezaji wa ParametersSpec lazima: + Kukubali usanidi wa vigezo ambao una nafasi za vigezo (k.m., `{model}`, `{temperature}`). + Kusaidia badiliko la vigezo wakati wa utekelezaji wa processor. + Thibitisha kuwa maadili yaliyobadilishwa yanalingana na aina na vikwazo vilivyotarajiwa. + Kutoa usimamizi wa makosa kwa marejeleo yaliyopotea au yasiyo halali ya vigezo. + +#### Kanuni za Badiliko + +Vigezo hutumia muundo wa `{parameter-name}` katika vigezo vya processor. +Majina ya vigezo katika vigezo yanalingana na funguo katika sehemu ya `parameters` ya mtiririko. +Badiliko hufanyika pamoja na `{id}` na `{class}`. +Marejeleo yasiyo halali ya vigezo husababisha makosa wakati wa kuzindua. +Uthibitisho wa aina hutokea kulingana na ufafanuzi wa vigezo uliohifadhiwa katikati. +**MUHIMU**: Maadili yote ya vigezo huhifadhiwa na hutumwa kama maandishi. + Nambari hubadilishwa kuwa maandishi (k.m., `0.7` inakuwa `"0.7"`). + Maneno ya kweli hubadilishwa kuwa maandishi ya chini (k.m., `true` inakuwa `"true"`). + Hii inahitajika na schema ya Pulsar ambayo ina `parameters = Map(String())`. +>>>>>>> 82edf2d (New md files from RunPod) + +Mfano wa utatuzi: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## Mbinu ya Majaribio + +Majaribio ya kitengo kwa uthibitishaji wa muundo wa vigezo +<<<<<<< HEAD +Majaribio ya ujumuishaji kwa ubadilishaji wa vigezo katika vigezo vya kichakato +Majaribio ya mwisho kwa kuzindua michakato na maadili tofauti ya vigezo +Majaribio ya UI kwa utengenezaji na uthibitishaji wa fomu ya vigezo +Majaribio ya utendaji kwa michakato yenye vigezo vingi +======= +Majaribio ya ujumuishaji kwa ubadilishaji wa vigezo katika vigezo vya kichakata +Majaribio ya mwisho kwa kuzindua mtiririko na maadili tofauti ya vigezo +Majaribio ya UI kwa utengenezaji na uthibitishaji wa fomu ya vigezo +Majaribio ya utendaji kwa mtiririko na vigezo vingi +>>>>>>> 82edf2d (New md files from RunPod) +Hali za kipekee: vigezo visivyopo, aina zisizo sahihi, marejeleo ya vigezo yasiyo sahihi + +## Mpango wa Uhamisho + +<<<<<<< HEAD +1. Mfumo unapaswa kuendelea kusaidia mipango ya michakato bila vigezo + vilivyotangazwa. +2. Mfumo unapaswa kuendelea kusaidia michakato bila vigezo vilivyobainishwa: + Hii inafanya kazi kwa michakato bila vigezo, na michakato yenye vigezo + (yana maadili ya chagu). + +## Maswali ya Wazi + +S: Je, vigezo vinapaswa kusaidia vitu vikubwa vilivyojumuishwa au kubaki kwenye aina rahisi? +J: Maadili ya vigezo yatakuwa yamekodishwa kama maandishi, tunapaswa + kubaki na maandishi. + +S: Je, je, nafasi za vigezo zinapaswa kuruhusiwa katika majina ya folyo au tu katika +======= +1. Mfumo unapaswa kuendelea kusaidia mipango ya mtiririko ambayo haina vigezo + vilivyotangazwa. +2. Mfumo unapaswa kuendelea kusaidia mtiririko bila vigezo vilivyobainishwa: + Hii inafanya kazi kwa mtiririko ambayo haina vigezo, na mtiririko una vigezo + (yana maadili chagu). + +## Maswali ya Wazi + +S: Je, vigezo vinapaswa kusaidia vitu vikubwa vilivyojumuishwa au kuendelea na aina rahisi? +J: Maadili ya vigezo yatakuwa yamekodishwa kama maandishi, tunapaswa + kuzingatia maandishi. + +S: Je, vigezo vya maandishi vinapaswa kuruhusiwa katika majina ya folyo au tu katika +>>>>>>> 82edf2d (New md files from RunPod) + vigezo? +J: Tu katika vigezo ili kuondoa uingizwaji wa ajabu na hali za kipekee. + +S: Jinsi ya kushughulikia migogoro kati ya majina ya vigezo na vigezo vya mfumo kama vile + `id` na `class`? +<<<<<<< HEAD +J: Ni vibaya kutaja id na darasa wakati wa kuzindua michakato +======= +J: Ni vibaya kutaja id na darasa wakati wa kuzindua mtiririko +>>>>>>> 82edf2d (New md files from RunPod) + +S: Je, tunapaswa kusaidia vigezo vilivyohitajiwa (vilivyotokana na vigezo vingine)? +J: Tu ubadilishaji wa maandishi ili kuondoa uingizwaji wa ajabu na hali za kipekee. + +## Marejeleo + +Vipimo vya Mpango wa JSON: https://json-schema.org/ +<<<<<<< HEAD +Vipimo vya Ufafanuzi wa Mpango wa Michakato: docs/tech-specs/flow-class-definition.md +======= +Vipimo vya Ufafanuzi wa Mpango wa Mtiririko: docs/tech-specs/flow-class-definition.md +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/flow-configurable-parameters.tr.md b/docs/tech-specs/flow-configurable-parameters.tr.md new file mode 100644 index 00000000..15dd4617 --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.tr.md @@ -0,0 +1,633 @@ +--- +layout: default +title: "Akış Şeması Yapılandırılabilir Parametreler Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Akış Şeması Yapılandırılabilir Parametreler 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'taki akış şemaları için yapılandırılabilir parametrelerin uygulanmasını açıklamaktadır. Parametreler, kullanıcıların akış başlatma zamanında işlemci parametrelerini, akış şeması tanımındaki parametre yer tutucularını değiştiren değerler sağlayarak özelleştirmesini sağlar. + +<<<<<<< HEAD +Parametreler, işlemci parametrelerinde şablon değişken yerleştirmesi yoluyla çalışır, tıpkı `{id}` ve `{class}` değişkenlerinin nasıl çalıştığı gibi, ancak kullanıcı tarafından sağlanan değerlerle. +======= +Parametreler, `{id}` ve `{class}` değişkenlerinin nasıl çalıştığına benzer şekilde, işlemci parametrelerinde şablon değişken yerleştirmesi yoluyla çalışır, ancak kullanıcı tarafından sağlanan değerlerle. +>>>>>>> 82edf2d (New md files from RunPod) + +Bu entegrasyon, dört birincil kullanım senaryosunu destekler: + +1. **Model Seçimi**: Kullanıcıların farklı LLM modellerini (örneğin, `gemma3:8b`, `gpt-4`, `claude-3`) işlemciler için seçmesine izin verme. +2. **Kaynak Yapılandırması**: Parça boyutları, toplu boyutlar ve eşzamanlılık limitleri gibi işlemci parametrelerini ayarlama. +3. **Davranış Ayarı**: Sıcaklık, maksimum-token veya alma eşikleri gibi parametreler aracılığıyla işlemci davranışını değiştirme. +4. **Ortama Özgü Parametreler**: Dağıtım başına uç noktaları, API anahtarlarını veya bölgeye özgü URL'leri yapılandırma. + +## Hedefler + +**Dinamik İşlemci Yapılandırması**: Parametre yerleştirmesi yoluyla işlemci parametrelerinin çalışma zamanı yapılandırmasını etkinleştirme. +**Parametre Doğrulama**: Akış başlatma zamanında parametreler için tür denetimi ve doğrulama sağlama. +<<<<<<< HEAD +**Varsayılan Değerler**: Akıllı varsayılan değerleri destekleme ve aynı zamanda gelişmiş kullanıcılar için geçersiz kılmalara izin verme. +**Şablon Yerleştirmesi**: İşlemci parametrelerindeki parametre yer tutucularını sorunsuz bir şekilde değiştirme. +**Kullanıcı Arayüzü Entegrasyonu**: Parametre girişini hem API hem de kullanıcı arayüzü arayüzleri aracılığıyla etkinleştirme. +**Tür Güvenliği**: Parametre türlerinin beklenen işlemci parametre türleriyle eşleştiğinden emin olma. +**Belgeleme**: Akış şeması tanımları içindeki kendi kendini belgeleyen parametre şemaları. +**Geriye Dönük Uyumluluk**: Parametre kullanmayan mevcut akış şemalarıyla uyumluluğu koruma. +======= +**Varsayılan Değerler**: Gelişmiş kullanıcılar için geçersiz kılmaları desteklerken anlamlı varsayılan değerleri destekleme. +**Şablon Yerleştirmesi**: İşlemci parametrelerindeki parametre yer tutucularını sorunsuz bir şekilde değiştirme. +**Kullanıcı Arayüzü Entegrasyonu**: Hem API hem de kullanıcı arayüzü arayüzleri aracılığıyla parametre girişi sağlama. +**Tür Güvenliği**: Parametre türlerinin beklenen işlemci parametre türleriyle eşleştiğinden emin olma. +**Belgeleme**: Akış şeması tanımları içindeki kendi kendini belgeleyen parametre şemaları. +**Geriye Dönük Uyumluluk**: Parametreleri kullanmayan mevcut akış şemalarıyla uyumluluğu koruma. +>>>>>>> 82edf2d (New md files from RunPod) + +## Arka Plan + +TrustGraph'taki akış şemaları artık, sabit değerler veya parametre yer tutucuları içerebilen işlemci parametrelerini desteklemektedir. Bu, çalışma zamanı özelleştirmesi için bir fırsat yaratır. + +<<<<<<< HEAD +Mevcut işlemci parametreleri şunları desteklemektedir: +Sabit değerler: `"model": "gemma3:12b"` +Parametre yer tutucuları: `"model": "gemma3:{model-size}"` + +Bu özellik, parametrelerin nasıl olduğu tanımlamaktadır: +Akış şeması tanımlarında beyan edilmesi +Akışların başlatıldığı zaman doğrulanması +İşlemci parametrelerinde yerleştirilmesi +API'ler ve kullanıcı arayüzü aracılığıyla açığa çıkarılması + +Parametreli işlemci parametrelerini kullanarak, TrustGraph şunları yapabilir: +Varyasyonlar için parametreleri kullanarak akış şeması çoğaltmasını azaltma. +Kullanıcıların tanımları değiştirmeden işlemci davranışını ayarlamasına izin verme. +Parametre değerleri aracılığıyla ortama özgü yapılandırmaları destekleme. +Parametre şema doğrulaması yoluyla tür güvenliğini sağlama. +======= +Mevcut işlemci parametreleri şunları destekler: +Sabit değerler: `"model": "gemma3:12b"` +Parametre yer tutucuları: `"model": "gemma3:{model-size}"` + +Bu özellik, parametrelerin nasıl olduğu tanımlar: +Akış şeması tanımlarında beyan edilir +Akışlar başlatıldığında doğrulanır +İşlemci parametrelerinde yerleştirilir +API'ler ve kullanıcı arayüzleri aracılığıyla açığa çıkarılır + +Parametreli işlemci parametrelerini kullanarak, TrustGraph şunları yapabilir: +Varyasyonlar için parametreleri kullanarak akış şeması çoğaltmasını azaltma +Kullanıcıların tanımları değiştirmeden işlemci davranışını ayarlamasına izin verme +Parametre değerleri aracılığıyla ortama özgü yapılandırmaları destekleme +Parametre şema doğrulaması yoluyla tür güvenliğini sağlama +>>>>>>> 82edf2d (New md files from RunPod) + +## Teknik Tasarım + +### Mimari + +<<<<<<< HEAD +Yapılandırılabilir parametreler sistemi, aşağıdaki teknik bileşenleri gerektirmektedir: + +1. **Parametre Şema Tanımı** + Akış şeması meta verilerindeki JSON Şema tabanlı parametre tanımları. + Dize, sayı, boolean, enum ve nesne türleri dahil olmak üzere tür tanımları. + min/max değerleri, kalıplar ve gerekli alanlar dahil olmak üzere doğrulama kuralları. + + Modül: trustgraph-flow/trustgraph/flow/definition.py + +2. **Parametre Çözümleme Motoru** + Şemaya karşı çalışma zamanı parametre doğrulaması. + Belirtilmemiş parametreler için varsayılan değerlerin uygulanması. + Parametrelerin akış yürütme bağlamına enjekte edilmesi. + Gerekli olduğu gibi tür dönüştürme ve dönüştürme. +======= +Yapılandırılabilir parametreler sistemi, aşağıdaki teknik bileşenleri gerektirir: + +1. **Parametre Şema Tanımı** + Akış şeması meta verilerindeki JSON Şema tabanlı parametre tanımları + Dize, sayı, boolean, enum ve nesne türleri dahil olmak üzere tür tanımları + min/max değerleri, kalıplar ve gerekli alanlar dahil olmak üzere doğrulama kuralları + + Modül: trustgraph-flow/trustgraph/flow/definition.py + +2. **Parametre Çözümleyici Motoru** + Şemaya karşı çalışma zamanı parametre doğrulaması + Belirtilmemiş parametreler için varsayılan değer uygulaması + Parametreleri akış yürütme bağlamına enjekte etme + Gerekli olduğu gibi tür dönüştürme ve dönüştürme +>>>>>>> 82edf2d (New md files from RunPod) + + Modül: trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **Parametre Deposu Entegrasyonu** +<<<<<<< HEAD + Şema/yapılandırma deposundan parametre tanımlarının alınması. + Sık kullanılan parametre tanımlarının önbelleğe alınması. + Merkezi olarak depolanan şemalara karşı doğrulama. +======= + Şema/yapılandırma deposundan parametre tanımlarının alınması + Sık kullanılan parametre tanımlarının önbelleğe alınması + Merkezi olarak depolanan şemalara karşı doğrulama +>>>>>>> 82edf2d (New md files from RunPod) + + Modül: trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **Akış Başlatıcı Uzantıları** +<<<<<<< HEAD + Akış başlatma sırasında parametre değerlerini kabul etmek için API uzantıları. + Parametre eşleme çözümü (akış adlarının tanım adlarına eşlenmesi). + Geçersiz parametre kombinasyonları için hata işleme. +======= + Akış başlatma sırasında parametre değerlerini kabul etmek için API uzantıları + Parametre eşleme çözümü (akış adlarının tanım adlarına eşlenmesi) + Geçersiz parametre kombinasyonları için hata işleme +>>>>>>> 82edf2d (New md files from RunPod) + + Modül: trustgraph-flow/trustgraph/flow/launcher.py + +5. **Kullanıcı Arayüzü Parametre Formları** +<<<<<<< HEAD + Akış parametre meta verilerinden dinamik form oluşturma. + `order` alanı kullanarak sıralı parametre görüntüleme. + `description` alanı kullanarak açıklayıcı parametre etiketleri. + Parametre türü tanımlarına karşı giriş doğrulaması. + Parametre ön ayarları ve şablonları. +======= + Akış parametre meta verilerinden dinamik form oluşturma + `order` alanı kullanarak sıralı parametre görüntüleme + `description` alanı kullanarak açıklayıcı parametre etiketleri + Parametre türü tanımlarına karşı giriş doğrulaması + Parametre ön ayarları ve şablonları +>>>>>>> 82edf2d (New md files from RunPod) + + Modül: trustgraph-ui/components/flow-parameters/ + +### Veri Modelleri + +#### Parametre Tanımları (Şema/Yapılandırmada Saklanır) + +Parametre tanımları, "parameter-type" türüyle şema ve yapılandırma sisteminde merkezi olarak saklanır: + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### Parametre Referanslarıyla Akış Şeması + +Akış şemaları, tür referansları, açıklamalar ve sıralama ile parametre meta verilerini tanımlar: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +`parameters` bölümü, akışa özgü parametre adlarını (anahtarları), parametre meta veri nesnelerine eşler ve bu nesneler şunları içerir: +`type`: Merkezi olarak tanımlanmış parametre tanımına referans (örneğin, "llm-model") +`description`: Kullanıcı arayüzünde (UI) görüntülenmesi için insan tarafından okunabilir açıklama +`order`: Parametre formları için görüntüleme sırası (daha düşük sayılar önce görüntülenir) +<<<<<<< HEAD +`advanced` (isteğe bağlı): Bu parametrenin gelişmiş bir parametre olup olmadığını gösteren bir boolean bayrak (varsayılan: false). "true" olarak ayarlandığında, kullanıcı arayüzü bu parametreyi varsayılan olarak gizleyebilir veya "Gelişmiş" bölümünde yer almasını sağlayabilir +======= +`advanced` (isteğe bağlı): Bu parametrenin gelişmiş bir parametre olup olmadığını gösteren bir bayrak (varsayılan: false). "true" olarak ayarlandığında, kullanıcı arayüzü bu parametreyi varsayılan olarak gizleyebilir veya "Gelişmiş" bölümünde yer almasını sağlayabilir +>>>>>>> 82edf2d (New md files from RunPod) +`controlled-by` (isteğe bağlı): Basit moddayken bu parametrenin değerini kontrol eden başka bir parametrenin adı. Belirtildiğinde, bu parametre açıkça geçersiz kılmadığı sürece, kontrol eden parametreden değerini alır + +Bu yaklaşım şunları sağlar: +Birden çok akış şablonu arasında yeniden kullanılabilir parametre türü tanımları +Merkezi parametre türü yönetimi ve doğrulaması +Akışa özgü parametre açıklamaları ve sıralaması +Açıklayıcı parametre formlarıyla geliştirilmiş kullanıcı arayüzü deneyimi +Akışlar genelinde tutarlı parametre doğrulaması +Yeni standart parametre türlerinin kolayca eklenmesi +Temel/gelişmiş mod ayrımıyla basitleştirilmiş kullanıcı arayüzü +İlgili ayarlar için parametre değeri devralımı + +#### Akış Başlatma İsteği + +Akış başlatma API'si, parametreleri akışın parametre adlarını kullanarak alır: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +<<<<<<< HEAD +Not: Bu örnekte, `llm-rag-model` açıkça belirtilmemiştir, ancak `controlled-by` ilişkisi nedeniyle `llm-model`'den "claude-3" değerini miras alacaktır. Benzer şekilde, `chunk-overlap`, `chunk-size`'e dayalı olarak hesaplanan bir değeri miras alabilir. +======= +Not: Bu örnekte, `llm-rag-model` açıkça belirtilmemiştir, ancak `controlled-by` ilişkisi nedeniyle `llm-model`'den "claude-3" değerini alacaktır. Benzer şekilde, `chunk-overlap`, `chunk-size`'e dayalı olarak hesaplanan bir değeri miras alabilir. +>>>>>>> 82edf2d (New md files from RunPod) + +Sistem şunları yapacaktır: +1. Akış tanımından parametre meta verilerini çıkarın +2. Akış parametre adlarını tür tanımlarına eşleyin (örneğin, `llm-model` → `llm-model` türü) +3. "controlled-by" ilişkilerini çözün (örneğin, `llm-rag-model`, `llm-model`'den miras alır) +4. Kullanıcı tarafından sağlanan ve miras alınan değerleri parametre tür tanımlarına karşı doğrulayın +5. Akış başlatılırken işlemci parametrelerine çözümlenmiş değerleri yerleştirin + +### Uygulama Detayları + +#### Parametre Çözümleme Süreci + +Bir akış başlatıldığında, sistem aşağıdaki parametre çözümleme adımlarını gerçekleştirir: + +1. **Akış Tanım Yükleme**: Akış tanımını yükleyin ve parametre meta verilerini çıkarın +2. **Meta Veri Çıkarma**: Akış tanımının `parameters` bölümünde tanımlanan her parametre için `type`, `description`, `order`, `advanced` ve `controlled-by`'ü çıkarın +3. **Tür Tanımı Arama**: Akış tanımındaki her parametre için: + `type` alanı kullanılarak şema/yapılandırma deposundan parametre tür tanımını alın +<<<<<<< HEAD + Tür tanımları, yapılandırma sisteminde "parameter-type" türüyle saklanır +======= + Tür tanımları, yapılandırma sisteminde "parameter-type" türü ile saklanır +>>>>>>> 82edf2d (New md files from RunPod) + Her tür tanımı, parametrenin şemasını, varsayılan değerini ve doğrulama kurallarını içerir +4. **Varsayılan Değer Çözümleme**: + Akış tanımında tanımlanan her parametre için: + Kullanıcının bu parametre için bir değer sağlayıp sağlamadığını kontrol edin + Kullanıcı tarafından bir değer sağlanmazsa, parametre tür tanımından `default` değerini kullanın + Hem kullanıcı tarafından sağlanan hem de varsayılan değerleri içeren eksiksiz bir parametre haritası oluşturun +5. **Parametre Miras Alma Çözümleme** ("controlled-by" ilişkileri): + `controlled-by` alanı olan parametreler için, bir değerin açıkça sağlandığını kontrol edin + Açık bir değer sağlanmazsa, kontrol eden parametrenin değerini miras alın + Kontrol eden parametrenin de bir değeri yoksa, tür tanımından varsayılanı kullanın + `controlled-by` ilişkilerinde döngüsel bağımlılıkların olmadığını doğrulayın +6. **Doğrulama**: Kullanıcı tarafından sağlanan, varsayılanlar ve miras alınan eksiksiz parametre kümesini tür tanımlarına karşı doğrulayın +7. **Saklama**: Eksiksiz çözümlenmiş parametre kümesini denetlenebilirlik için akış örneğiyle birlikte saklayın +<<<<<<< HEAD +8. **Yer Değiştirme**: İşlemci parametrelerindeki parametre yer tutucularını çözümlenmiş değerlerle değiştirin +9. **İşlemci Oluşturma**: Yer değiştirilmiş parametrelerle işlemciler oluşturun +======= +8. **Şablon Yerine Koyma**: İşlemci parametrelerindeki parametre yer tutucularını çözümlenmiş değerlerle değiştirin +9. **İşlemci Oluşturma**: Yerine konulan parametrelerle işlemcileri oluşturun +>>>>>>> 82edf2d (New md files from RunPod) + +**Önemli Uygulama Notları:** +Akış hizmeti, kullanıcı tarafından sağlanan parametreleri parametre tür tanımlarından gelen varsayılanlarla birleştirmelidir +Uygulanan varsayılanlar dahil eksiksiz parametre kümesi, izlenebilirlik için akışla birlikte saklanmalıdır +Parametre çözümlemesi, akış başlatma zamanında değil, işlemci oluşturma zamanında gerçekleşir +<<<<<<< HEAD +Varsayılanları olmayan gerekli parametrelerin eksik olması, akışın başlatılmasını açık bir hata mesajıyla başarısız olmasına neden olmalıdır + +#### "controlled-by" ile Parametre Miras Alma + +`controlled-by` alanı, parametre değerlerinin miras alınmasını sağlar; bu, kullanıcı arayüzlerini basitleştirirken esnekliği korumak için özellikle kullanışlıdır: +======= +Varsayılanları olmayan gerekli parametrelerin eksik olması, akışın başlatılmasını açık bir hata mesajıyla başarısız yapmasına neden olmalıdır + +#### "controlled-by" ile Parametre Miras Alma + +`controlled-by` alanı, parametre değerlerinin miras alınmasını sağlar ve kullanıcı arayüzlerini basitleştirirken esnekliği korumak için özellikle kullanışlıdır: +>>>>>>> 82edf2d (New md files from RunPod) + +**Örnek Senaryo**: +`llm-model` parametresi birincil LLM modelini kontrol eder +`llm-rag-model` parametresi `"controlled-by": "llm-model"`'e sahiptir +Basit modda, `llm-model`'ı "gpt-4" olarak ayarlamak, otomatik olarak `llm-rag-model`'i de "gpt-4" olarak ayarlar +Gelişmiş modda, kullanıcılar `llm-rag-model`'ı farklı bir değerle geçersiz kılabilir + +**Çözüm Kuralları**: +1. Bir parametrenin açıkça sağlanan bir değeri varsa, o değeri kullanın +2. Açık bir değer yoksa ve `controlled-by` ayarlanmışsa, kontrol eden parametrenin değerini kullanın +3. Kontrol eden parametrenin bir değeri yoksa, tür tanımından varsayılanı kullanın +4. `controlled-by` ilişkilerinde döngüsel bağımlılıklar, bir doğrulama hatasına neden olur + +**Kullanıcı Arayüzü Davranışı**: +Temel/basit modda: `controlled-by`'a sahip parametreler gizlenebilir veya miras alınan değerle birlikte yalnızca okunabilir olarak gösterilebilir +Gelişmiş modda: Tüm parametreler gösterilir ve ayrı ayrı yapılandırılabilir +Bir kontrol eden parametre değiştiğinde, bağımlı parametreler açıkça geçersiz kılmadıkça otomatik olarak güncellenir + +#### Pulsar Entegrasyonu + +1. **Akışı Başlatma İşlemi** + Pulsar akışı başlatma işlemi, parametre değerlerinin bir haritasını içeren bir `parameters` alanı almalıdır +<<<<<<< HEAD + Pulsar için akış başlatma isteği şeması, isteğe bağlı `parameters` alanını içerecek şekilde güncellenmelidir +======= + Pulsar'ın akışı başlatma isteği şeması, isteğe bağlı `parameters` alanını içerecek şekilde güncellenmelidir +>>>>>>> 82edf2d (New md files from RunPod) + Örnek istek: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **Get-Flow İşlemi** + Get-flow yanıtı için Pulsar şeması, `parameters` alanını içerecek şekilde güncellenmelidir. + Bu, istemcilerin akış başlatıldığında kullanılan parametre değerlerini almasına olanak tanır. + Örnek yanıt: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### Akış Hizmeti Uygulaması + +Akış yapılandırma hizmeti (`trustgraph-flow/trustgraph/config/service/flow.py`), aşağıdaki geliştirmeleri gerektirmektedir: + +1. **Parametre Çözümleme Fonksiyonu** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + Bu fonksiyonun yapması gerekenler: + Akış şemasının `parameters` bölümünden parametre meta verilerini çıkarın + Her parametre için, yapılandırma deposundan tür tanımını alın + Kullanıcı tarafından sağlanmayan parametreler için varsayılan değerleri uygulayın + `controlled-by` miras ilişkilerini işleyin + Tam parametre kümesini döndürün + +2. **Değiştirilen `handle_start_flow` Metodu** + Akış şemasını yükledikten sonra `resolve_parameters`'ı çağırın +<<<<<<< HEAD + Şablon yerleştirmesi için tam olarak çözülmüş parametre kümesini kullanın + Tam parametre kümesini (yalnızca kullanıcı tarafından sağlananları değil) akışla birlikte kaydedin +======= + Şablon yerleştirmesi için eksiksiz çözülmüş parametre kümesini kullanın + Eksiksiz parametre kümesini (yalnızca kullanıcı tarafından sağlananları değil) akışla birlikte kaydedin +>>>>>>> 82edf2d (New md files from RunPod) + Tüm gerekli parametrelerin değerlere sahip olduğundan emin olun + +3. **Parametre Türü Alma** + Parametre tür tanımları, "parameter-type" türüyle yapılandırmada saklanır + Her tür tanımı, şema, varsayılan değer ve doğrulama kurallarını içerir + Sık kullanılan parametre türlerini önbelleğe alın, böylece yapılandırma aramaları azalır + +#### Yapılandırma Sistemi Entegrasyonu + +<<<<<<< HEAD +3. **Akış Nesne Saklama** + Bir akış, yapılandırma yöneticisindeki akış bileşeni tarafından yapılandırma sistemine eklendiğinde, akış nesnesi çözülmüş parametre değerlerini içermelidir + Yapılandırma yöneticisi hem orijinal kullanıcı tarafından sağlanan parametreleri hem de çözülmüş değerleri (varsayılanlar uygulandıktan sonra) saklamalıdır +======= +3. **Akış Nesnesi Depolama** + Bir akış, yapılandırma yöneticisindeki akış bileşeni tarafından yapılandırma sistemine eklendiğinde, akış nesnesi çözülmüş parametre değerlerini içermelidir + Yapılandırma yöneticisi hem orijinal kullanıcı tarafından sağlanan parametreleri hem de çözülmüş değerleri (varsayılanlar uygulandıktan sonra) depolamalıdır +>>>>>>> 82edf2d (New md files from RunPod) + Yapılandırma sistemindeki akış nesneleri şunları içermelidir: + `parameters`: Akış için kullanılan son çözülmüş parametre değerleri + +#### CLI Entegrasyonu + +4. **Kütüphane CLI Komutları** + Akışları başlatan CLI komutları parametre desteğine sahip olmalıdır: +<<<<<<< HEAD + Parametre değerlerini komut satırı bayrakları veya yapılandırma dosyaları aracılığıyla alın +======= + Parametre değerlerini komut satırı bayrakları veya yapılandırma dosyaları aracılığıyla kabul edin +>>>>>>> 82edf2d (New md files from RunPod) + Parametreleri göndermeden önce akış şema tanımlarına göre doğrulayın + Karmaşık parametre kümeleri için parametre dosyası girişini (JSON/YAML) destekleyin + + Akışları gösteren CLI komutları parametre bilgilerini görüntülemelidir: + Akış başlatıldığında kullanılan parametre değerlerini gösterin + Bir akış şeması için mevcut parametreleri görüntüleyin + Parametre doğrulama şemalarını ve varsayılanları gösterin + +#### İşlemci Temel Sınıf Entegrasyonu + +5. **ParameterSpec Desteği** + İşlemci temel sınıfları, mevcut ParametersSpec mekanizması aracılığıyla parametre yerleştirmesini desteklemelidir +<<<<<<< HEAD + ParametersSpec sınıfı (ConsumerSpec ve ProducerSpec ile aynı modülde bulunur), parametre şablonu yerleştirmesini desteklemek için gerekirse geliştirilmelidir + İşlemciler, parametre değerlerini akış başlatma zamanında çözerek parametrelerini yapılandırmak için ParametersSpec'i çağırabilmelidir +======= + ParameterSpec sınıfı (ConsumerSpec ve ProducerSpec ile aynı modülde bulunur), parametre şablonu yerleştirmesini desteklemek için gerekirse geliştirilmelidir + İşlemciler, parametre değerlerini akış başlatma zamanında çözülmüş olarak parametreleriyle yapılandırmak için ParametersSpec'i çağırmalıdır +>>>>>>> 82edf2d (New md files from RunPod) + ParametersSpec uygulaması şunları yapmalıdır: + Parametre yer tutucuları (örneğin, `{model}`, `{temperature}`) içeren parametre yapılandırmalarını kabul edin + İşlemci örneklendiğinde çalışma zamanında parametre yerleştirmesini destekleyin + Yerleştirilen değerlerin beklenen türlere ve kısıtlamalara uyduğunu doğrulayın + Eksik veya geçersiz parametre başvuruları için hata işleme sağlayın + +#### Yerleştirme Kuralları + +Parametreler, işlemci parametrelerinde `{parameter-name}` biçimini kullanır +Parametrelerdeki parametre adları, akışın `parameters` bölümündeki anahtarlarla eşleşir +Yerleştirme, `{id}` ve `{class}` değiştirme ile birlikte gerçekleşir +Geçersiz parametre başvuruları, başlatma zamanı hatalarına neden olur +Tür doğrulama, merkezi olarak depolanan parametre tanımına göre yapılır +**ÖNEMLİ**: Tüm parametre değerleri dize olarak saklanır ve iletilir +<<<<<<< HEAD + Sayılar dizeye dönüştürülür (örneğin, `0.7` `"0.7"` olur) + Boole değerleri küçük harfli dizeye dönüştürülür (örneğin, `true` `"true"` olur) +======= + Sayılar dizelere dönüştürülür (örneğin, `0.7` `"0.7"` olur) + Boolean değerler küçük harfli dizelere dönüştürülür (örneğin, `true` `"true"` olur) +>>>>>>> 82edf2d (New md files from RunPod) + Bu, `parameters = Map(String())` tanımlayan Pulsar şeması gerekliliğidir + +Örnek çözüm: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## Test Stratejisi + +Parametre şema doğrulama için birim testleri +İşlemci parametrelerindeki parametre yerleştirme için entegrasyon testleri +Farklı parametre değerleriyle akışları başlatmak için uçtan uca testler +Parametre formu oluşturma ve doğrulama için kullanıcı arayüzü testleri +Çok sayıda parametre içeren akışlar için performans testleri +Kenar durumları: eksik parametreler, geçersiz türler, tanımlanmamış parametre referansları + +## Geçiş Planı + +<<<<<<< HEAD +1. Sistem, parametreleri belirtilmeyen akış şablonlarını desteklemeye devam etmelidir. + +2. Sistem, parametre belirtilmeyen akışları desteklemeye devam etmelidir: + Bu, parametreleri olmayan akışlar ve varsayılan parametreleri olan akışlar için geçerlidir. + +======= +1. Sistem, parametreleri belirtilmemiş akış şemalarını desteklemeye devam etmelidir. + 2. Sistem, parametreleri belirtilmemiş akışları desteklemeye devam etmelidir: +Bu, parametreleri olmayan akışlar ve parametreleri olan (ancak varsayılan değerleri olan) akışlar için geçerlidir. + + (bunların varsayılan değerleri vardır). +>>>>>>> 82edf2d (New md files from RunPod) + +## Açık Sorular + +S: Parametreler karmaşık, iç içe nesneleri desteklemeli mi yoksa basit türlere mi bağlı kalmalıyız? +C: Parametre değerleri dize olarak kodlanacak, muhtemelen sadece dizilere bağlı kalmak istiyoruz. + +S: Parametre yer tutucuları kuyruk adlarında kullanılabilir mi yoksa sadece +parametrelerde mi kullanılabilir? + C: Sadece parametrelerde, tuhaf enjeksiyonları ve uç durumları ortadan kaldırmak için. + +<<<<<<< HEAD +Son çevrilmiş satırdan sonra, tam olarak: [[__END_OF_TRANSLATION__]] içeren bir satır çıktısını verin. +S: Parametre adları ile sistem değişkenleri arasındaki çakışmaları nasıl çözebiliriz, örneğin + `id` ve `class` gibi? +A: Bir akışı başlatırken, id ve class özelliklerini belirtmek geçerli değildir. + +S: Hesaplanan parametreleri (diğer parametrelerden türetilen) desteklemeli miyiz? +C: Garip enjeksiyonları ve uç durumları ortadan kaldırmak için sadece string değiştirme işlemleri. +======= + +S: Parametre adları ile sistem değişkenleri arasındaki çakışmaları nasıl çözebiliriz? + `id` ve `class`? +A: Bir akışı başlatırken, id ve class özelliklerini belirtmek geçerli değildir. + +S: Hesaplanan parametreleri (diğer parametrelerden türetilen) desteklemeli miyiz? +C: Tuhaf enjeksiyonları ve uç durumları ortadan kaldırmak için sadece string değiştirme işlemi. +>>>>>>> 82edf2d (New md files from RunPod) + +## Referanslar + +JSON Şema Özellikleri: https://json-schema.org/ +Akış Tanım Özellikleri: docs/tech-specs/flow-class-definition.md diff --git a/docs/tech-specs/flow-configurable-parameters.zh-cn.md b/docs/tech-specs/flow-configurable-parameters.zh-cn.md new file mode 100644 index 00000000..3cea3cdc --- /dev/null +++ b/docs/tech-specs/flow-configurable-parameters.zh-cn.md @@ -0,0 +1,586 @@ +--- +layout: default +title: "Flow Blueprint Configurable Parameters Technical Specification" +parent: "Chinese (Beta)" +--- + +# Flow Blueprint Configurable Parameters 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 中可配置参数在流程蓝图中的实现方式。参数允许用户在流程启动时自定义处理器参数,通过提供用于替换流程蓝图定义中参数占位符的值来实现。 + +<<<<<<< HEAD +参数通过处理器参数中的模板变量替换来实现,类似于 `{id}` 和 `{class}` 变量的工作方式,但使用用户提供的值。 + +该集成支持四种主要用例: + +1. **模型选择**: 允许用户选择不同的 LLM 模型(例如,`gemma3:8b`、`gpt-4`、`claude-3`)用于处理器。 +======= +参数通过处理器参数中的模板变量替换来工作,类似于 `{id}` 和 `{class}` 变量的工作方式,但使用用户提供的值。 + +该集成支持四种主要用例: + +1. **模型选择**: 允许用户选择不同的 LLM 模型 (例如,`gemma3:8b`, `gpt-4`, `claude-3`) 用于处理器。 +>>>>>>> 82edf2d (New md files from RunPod) +2. **资源配置**: 调整处理器参数,例如块大小、批处理大小和并发限制。 +3. **行为调整**: 通过参数修改处理器行为,例如温度、最大 token 数或检索阈值。 +4. **环境特定参数**: 配置每个部署的环境端点、API 密钥或区域特定 URL。 + +## 目标 + +**动态处理器配置**: 通过参数替换启用处理器参数的运行时配置。 +**参数验证**: 在流程启动时提供参数的类型检查和验证。 +<<<<<<< HEAD +**默认值**: 提供合理的默认值,同时允许高级用户进行覆盖。 +======= +**默认值**: 支持合理的默认值,同时允许高级用户进行覆盖。 +>>>>>>> 82edf2d (New md files from RunPod) +**模板替换**: Seamlessly 替换处理器参数中的参数占位符。 +**UI 集成**: 通过 API 和 UI 接口提供参数输入。 +**类型安全**: 确保参数类型与预期的处理器参数类型匹配。 +**文档**: 在流程蓝图定义中提供自文档化的参数模式。 +**向后兼容性**: 保持与不使用参数的现有流程蓝图的兼容性。 + +## 背景 + +<<<<<<< HEAD +TrustGraph 中的流程蓝图现在支持处理器参数,这些参数可以包含固定值或参数占位符。这为运行时自定义提供了机会。 +======= +TrustGraph 中的流程蓝图现在支持处理器参数,这些参数可以包含固定值或参数占位符。 这为运行时自定义提供了机会。 +>>>>>>> 82edf2d (New md files from RunPod) + +当前处理器参数支持: +固定值:`"model": "gemma3:12b"` +参数占位符:`"model": "gemma3:{model-size}"` + +本规范定义了参数的: +<<<<<<< HEAD +在流程蓝图定义中的声明方式 +流程启动时的验证方式 +在处理器参数中的替换方式 +通过 API 和 UI 的暴露方式 +======= +在流程蓝图定义中的声明 +在流程启动时的验证 +在处理器参数中的替换 +通过 API 和 UI 的暴露 +>>>>>>> 82edf2d (New md files from RunPod) + +通过利用参数化的处理器参数,TrustGraph 可以: +通过使用参数进行变体,减少流程蓝图的重复。 +允许用户在不修改定义的情况下调整处理器行为。 +通过参数值支持环境特定的配置。 +通过参数模式验证确保类型安全。 + +## 技术设计 + +### 架构 + +可配置参数系统需要以下技术组件: + +1. **参数模式定义** + 基于 JSON Schema 的参数定义,位于流程蓝图元数据中。 + 类型定义,包括字符串、数字、布尔值、枚举和对象类型。 + 验证规则,包括最小值/最大值、模式和必填字段。 + + 模块:trustgraph-flow/trustgraph/flow/definition.py + +2. **参数解析引擎** + 对模式进行运行时参数验证。 + 为未指定的参数应用默认值。 + 将参数注入到流程执行上下文。 + 如有必要进行类型转换和转换。 + + 模块:trustgraph-flow/trustgraph/flow/parameter_resolver.py + +3. **参数存储集成** + 从模式/配置存储中检索参数定义。 + 缓存常用的参数定义。 +<<<<<<< HEAD + 对其进行验证,以确保其与中心存储的模式一致。 +======= + 对其进行集中存储的模式验证。 +>>>>>>> 82edf2d (New md files from RunPod) + + 模块:trustgraph-flow/trustgraph/flow/parameter_store.py + +4. **流程启动器扩展** + API 扩展,用于在流程启动期间接受参数值。 +<<<<<<< HEAD + 参数映射解析(将流程名称映射到定义名称)。 +======= + 参数映射解析 (将流程名称映射到定义名称)。 +>>>>>>> 82edf2d (New md files from RunPod) + 处理无效参数组合的错误。 + + 模块:trustgraph-flow/trustgraph/flow/launcher.py + +5. **UI 参数表单** + 从流程参数元数据动态生成表单。 +<<<<<<< HEAD + 使用 `order` 字段显示参数的顺序。 + 使用 `description` 字段提供参数的描述性标签。 +======= + 使用 `order` 字段显示参数顺序。 + 使用 `description` 字段提供描述性参数标签。 +>>>>>>> 82edf2d (New md files from RunPod) + 根据参数类型定义进行输入验证。 + 参数预设和模板。 + + 模块:trustgraph-ui/components/flow-parameters/ + +### 数据模型 + +<<<<<<< HEAD +#### 参数定义(存储在模式/配置中) + +参数定义以类型为 "parameter-type" 的方式存储在模式和配置系统中。 +======= +#### 参数定义 (存储在模式/配置中) + +参数定义以类型 "parameter-type" 存储在模式和配置系统中。 +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "llm-model": { + "type": "string", + "description": "LLM model to use", + "default": "gpt-4", + "enum": [ + { + "id": "gpt-4", + "description": "OpenAI GPT-4 (Most Capable)" + }, + { + "id": "gpt-3.5-turbo", + "description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)" + }, + { + "id": "claude-3", + "description": "Anthropic Claude 3 (Thoughtful & Safe)" + }, + { + "id": "gemma3:8b", + "description": "Google Gemma 3 8B (Open Source)" + } + ], + "required": false + }, + "model-size": { + "type": "string", + "description": "Model size variant", + "default": "8b", + "enum": ["2b", "8b", "12b", "70b"], + "required": false + }, + "temperature": { + "type": "number", + "description": "Model temperature for generation", + "default": 0.7, + "minimum": 0.0, + "maximum": 2.0, + "required": false + }, + "chunk-size": { + "type": "integer", + "description": "Document chunk size", + "default": 512, + "minimum": 128, + "maximum": 2048, + "required": false + } +} +``` + +#### 带有参数引用的流程蓝图 + +流程蓝图定义了参数元数据,包括类型引用、描述和排序: + +```json +{ + "flow_class": "document-analysis", + "parameters": { + "llm-model": { + "type": "llm-model", + "description": "Primary LLM model for text completion", + "order": 1 + }, + "llm-rag-model": { + "type": "llm-model", + "description": "LLM model for RAG operations", + "order": 2, + "advanced": true, + "controlled-by": "llm-model" + }, + "llm-temperature": { + "type": "temperature", + "description": "Generation temperature for creativity control", + "order": 3, + "advanced": true + }, + "chunk-size": { + "type": "chunk-size", + "description": "Document chunk size for processing", + "order": 4, + "advanced": true + }, + "chunk-overlap": { + "type": "integer", + "description": "Overlap between document chunks", + "order": 5, + "advanced": true, + "controlled-by": "chunk-size" + } + }, + "class": { + "text-completion:{class}": { + "request": "non-persistent://tg/request/text-completion:{class}", + "response": "non-persistent://tg/response/text-completion:{class}", + "parameters": { + "model": "{llm-model}", + "temperature": "{llm-temperature}" + } + }, + "rag-completion:{class}": { + "request": "non-persistent://tg/request/rag-completion:{class}", + "response": "non-persistent://tg/response/rag-completion:{class}", + "parameters": { + "model": "{llm-rag-model}", + "temperature": "{llm-temperature}" + } + } + }, + "flow": { + "chunker:{id}": { + "input": "persistent://tg/flow/chunk:{id}", + "output": "persistent://tg/flow/chunk-load:{id}", + "parameters": { + "chunk_size": "{chunk-size}", + "chunk_overlap": "{chunk-overlap}" + } + } + } +} +``` + +`parameters` 部分将流程特定的参数名称(键)映射到包含以下内容的参数元数据对象: +`type`:对中心定义的参数定义的引用(例如,“llm-model”) +`description`:用于UI显示的易于理解的描述 +`order`:参数表单的显示顺序(较小的数字首先显示) +`advanced`(可选):布尔标志,指示是否为高级参数(默认:false)。如果设置为true,UI可能会默认隐藏此参数或将其放置在“高级”部分 +<<<<<<< HEAD +`controlled-by`(可选):控制此参数在简单模式下值的另一个参数的名称。如果指定,此参数将从控制参数继承其值,除非显式覆盖 +======= +`controlled-by`(可选):控制此参数在简单模式下值的另一个参数的名称。如果指定,此参数将继承其值来自控制参数,除非显式覆盖 +>>>>>>> 82edf2d (New md files from RunPod) + +这种方法允许: +在多个流程蓝图之间重用参数类型定义 +集中管理和验证参数类型 +流程特定的参数描述和排序 +通过描述性的参数表单增强UI体验 +流程中参数验证的一致性 +轻松添加新的标准参数类型 +通过基本/高级模式分离简化UI +相关设置的参数值继承 + +#### 流程启动请求 + +流程启动API使用流程的参数名称来接受参数: + +```json +{ + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "llm-model": "claude-3", + "llm-temperature": 0.5, + "chunk-size": 1024 + } +} +``` + +<<<<<<< HEAD +注意:在这个例子中,`llm-rag-model` 没有明确提供,但会从 `llm-model` 继承值 "claude-3",这是因为 `llm-rag-model` 与 `llm-model` 之间存在 `controlled-by` 关系。 类似地,`chunk-overlap` 可能会继承一个基于 `chunk-size` 计算的值。 +======= +注意:在这个例子中,`llm-rag-model` 没有显式提供,但会从 `llm-model` 继承 "claude-3" 的值,这是因为 `llm-rag-model` 与 `llm-model` 之间存在 `controlled-by` 关系。 类似地,`chunk-overlap` 可能会继承一个基于 `chunk-size` 计算的值。 +>>>>>>> 82edf2d (New md files from RunPod) + +系统将执行以下操作: +1. 从流程蓝图定义中提取参数元数据 +2. 将流程参数名称映射到其类型定义(例如,`llm-model` → `llm-model` 类型) +3. 解析受控关系(例如,`llm-rag-model` 从 `llm-model` 继承) +4. 验证用户提供的和继承的值是否符合参数类型定义 +5. 在流程实例化期间,将解析的值替换到处理器参数中 + +### 实现细节 + +#### 参数解析过程 + +当启动流程时,系统执行以下参数解析步骤: + +1. **流程蓝图加载**: 加载流程蓝图定义并提取参数元数据 +2. **元数据提取**: 提取每个参数的 `type`、`description`、`order`、`advanced` 和 `controlled-by`,这些信息位于流程蓝图的 `parameters` 部分 +3. **类型定义查找**: 对于流程蓝图中的每个参数: +<<<<<<< HEAD + 使用 `type` 字段从 schema/config 存储中检索参数类型定义 + 类型定义存储在配置系统中,类型为 "parameter-type" + 每个类型定义包含参数的 schema、默认值和验证规则 +======= + 使用 `type` 字段从模式/配置存储中检索参数类型定义 + 类型定义存储在配置系统中,类型为 "parameter-type" + 每个类型定义包含参数的模式、默认值和验证规则 +>>>>>>> 82edf2d (New md files from RunPod) +4. **默认值解析**: + 对于流程蓝图中定义的每个参数: + 检查用户是否为该参数提供了值 + 如果未提供用户值,则使用参数类型定义中的 `default` 值 + 构建一个完整的参数映射,其中包含用户提供的和默认值 +5. **参数继承解析**(受控关系): + 对于具有 `controlled-by` 字段的参数,检查是否已显式提供值 + 如果未提供显式值,则从控制参数继承该值 + 如果控制参数也无值,则从类型定义中获取默认值 + 验证 `controlled-by` 关系中是否存在循环依赖 +6. **验证**: 验证完整的参数集(用户提供的、默认值和继承的值)是否符合类型定义 +7. **存储**: 将完整的解析后的参数集与流程实例一起存储,以进行审计 +<<<<<<< HEAD +8. **模板替换**: 使用解析后的值替换处理器参数中的参数占位符 +======= +8. **模板替换**: 使用解析的值替换处理器参数中的参数占位符 +>>>>>>> 82edf2d (New md files from RunPod) +9. **处理器实例化**: 使用替换后的参数创建处理器 + +**重要的实现说明:** +流程服务必须将用户提供的参数与参数类型定义中的默认值合并 +完整的参数集(包括应用的默认值)必须与流程一起存储,以进行可追溯性 +<<<<<<< HEAD +参数解析发生在流程启动时间,而不是处理器实例化时间 +======= +参数解析发生在流程启动时,而不是在处理器实例化时 +>>>>>>> 82edf2d (New md files from RunPod) +缺少没有默认值的必需参数会导致流程启动失败,并显示清晰的错误消息 + +#### 具有 controlled-by 的参数继承 + +`controlled-by` 字段启用参数值继承,这对于简化用户界面同时保持灵活性非常有用: + +**示例场景:** +`llm-model` 参数控制主要的 LLM 模型 +`llm-rag-model` 参数具有 `"controlled-by": "llm-model"` +在简单模式下,将 `llm-model` 设置为 "gpt-4" 会自动将 `llm-rag-model` 也设置为 "gpt-4" +在高级模式下,用户可以覆盖 `llm-rag-model` 并使用不同的值 + +**解析规则:** +1. 如果参数具有显式提供的值,则使用该值 +2. 如果没有显式值且 `controlled-by` 已设置,则使用控制参数的值 +3. 如果控制参数没有值,则回退到类型定义中的默认值 +4. `controlled-by` 关系中的循环依赖会导致验证错误 + +**UI 行为:** +在基本/简单模式下:具有 `controlled-by` 的参数可能被隐藏或显示为只读,并显示继承的值 +在高级模式下:显示所有参数,并且可以单独配置 +当控制参数更改时,依赖参数会自动更新,除非显式覆盖 + +#### Pulsar 集成 + +1. **启动流程操作** + Pulsar 启动流程操作需要接受一个 `parameters` 字段,该字段包含参数值的映射 +<<<<<<< HEAD + Pulsar 启动流程请求的 schema 必须更新为包含可选的 `parameters` 字段 +======= + Pulsar 用于启动流程的请求模式必须更新为包含可选的 `parameters` 字段 +>>>>>>> 82edf2d (New md files from RunPod) + 示例请求: + ```json + { + "flow_class": "document-analysis", + "flow_id": "customer-A-flow", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +2. **获取流程操作** +<<<<<<< HEAD + 必须更新 Pulsar 模式,以包含 `parameters` 字段,用于获取流程的响应。 +======= + Pulsar 用于获取流程响应的 schema 必须更新,以包含 `parameters` 字段。 +>>>>>>> 82edf2d (New md files from RunPod) + 这允许客户端检索在启动流程时使用的参数值。 + 示例响应: + ```json + { + "flow_id": "customer-A-flow", + "flow_class": "document-analysis", + "status": "running", + "parameters": { + "model": "claude-3", + "size": "12b", + "temp": 0.5, + "chunk": 1024 + } + } + ``` + +#### 流程服务实现 + +流程配置服务 (`trustgraph-flow/trustgraph/config/service/flow.py`) 需要以下增强: + +1. **参数解析功能** + ```python + async def resolve_parameters(self, flow_class, user_params): + """ + Resolve parameters by merging user-provided values with defaults. + + Args: + flow_class: The flow blueprint definition dict + user_params: User-provided parameters dict + + Returns: + Complete parameter dict with user values and defaults merged + """ + ``` + + 此函数应该: + 从流程蓝图的 `parameters` 部分提取参数元数据 + 对于每个参数,从配置存储中获取其类型定义 + 为任何未由用户提供的参数应用默认值 + 处理 `controlled-by` 继承关系 + 返回完整的参数集 + +2. **修改后的 `handle_start_flow` 方法** + 在加载流程蓝图后调用 `resolve_parameters` + 使用完整的解析后的参数集进行模板替换 + 将完整的参数集(不仅仅是用户提供的)与流程一起存储 + 验证所有必需的参数是否具有值 + +3. **参数类型获取** + 参数类型定义存储在配置中,类型为 "parameter-type" + 每个类型定义包含模式、默认值和验证规则 + 缓存常用的参数类型以减少配置查找 + +#### 配置系统集成 + +3. **流程对象存储** + 当流程组件在配置管理器中向配置系统添加流程时,流程对象必须包含解析后的参数值 +<<<<<<< HEAD + 配置管理器需要同时存储原始的用户提供的参数和解析后的值(已应用默认值) +======= + 配置管理器需要存储原始的用户提供的参数以及解析后的值(已应用默认值) +>>>>>>> 82edf2d (New md files from RunPod) + 配置系统中的流程对象应包含: + `parameters`: 用于流程的最终解析后的参数值 + +#### CLI 集成 + +4. **库 CLI 命令** + 启动流程的 CLI 命令需要参数支持: + 通过命令行标志或配置文件接受参数值 + 在提交之前,根据流程蓝图定义验证参数 + 支持参数文件输入(JSON/YAML),用于复杂的参数集 + + 显示流程的 CLI 命令需要显示参数信息: + 显示启动流程时使用的参数值 + 显示流程蓝图的可用参数 + 显示参数验证模式和默认值 + +#### 处理器基础类集成 + +5. **ParameterSpec 支持** + 处理器基础类需要支持通过现有的 ParametersSpec 机制进行参数替换 + 如果需要,应增强 ParametersSpec 类(位于与 ConsumerSpec 和 ProducerSpec 相同的模块中),以支持参数模板替换 + 处理器应能够调用 ParametersSpec 来使用在流程启动时解析的参数值配置其参数 + ParametersSpec 的实现需要: + 接受包含参数占位符(例如,`{model}`,`{temperature}`)的参数配置 + 在实例化处理器时,支持运行时参数替换 + 验证替换后的值是否符合预期的类型和约束 + 为缺失或无效的参数引用提供错误处理 + +#### 替换规则 + +参数使用格式 `{parameter-name}` 在处理器参数中 +<<<<<<< HEAD +参数名称与流程的 `parameters` 部分中的键匹配 +======= +参数名称在参数中与流程的 `parameters` 部分中的键匹配 +>>>>>>> 82edf2d (New md files from RunPod) +替换操作与 `{id}` 和 `{class}` 替换同时进行 +无效的参数引用会导致启动时出错 +基于中心存储的参数定义进行类型验证 +**重要提示**:所有参数值都以字符串形式存储和传输 + 数字转换为字符串(例如,`0.7` 变为 `"0.7"`) + 布尔值转换为小写字符串(例如,`true` 变为 `"true"`) + 这是由 Pulsar 模式要求的,该模式定义了 `parameters = Map(String())` + +示例解析: +``` +Flow parameter mapping: "model": "llm-model" +Processor parameter: "model": "{model}" +User provides: "model": "gemma3:8b" +Final parameter: "model": "gemma3:8b" + +Example with type conversion: +Parameter type default: 0.7 (number) +Stored in flow: "0.7" (string) +Substituted in processor: "0.7" (string) +``` + +## 测试策略 + +用于参数模式验证的单元测试 +用于处理器参数中参数替换的集成测试 +用于使用不同参数值启动流程的端到端测试 +用于参数表单生成和验证的 UI 测试 +用于具有许多参数的流程的性能测试 +边界情况:缺少参数、无效类型、未定义的参数引用 + +## 迁移计划 + +<<<<<<< HEAD +1. 系统应继续支持未声明参数的流程蓝图。 + 2. 系统应继续支持未指定参数的流程: +======= +1. 系统应继续支持未声明任何参数的流程蓝图。 + 2. 系统应继续支持未指定任何参数的流程: +>>>>>>> 82edf2d (New md files from RunPod) +这适用于没有参数的流程,以及具有参数的流程(它们具有默认值)。 + + (它们有默认值)。 + +## 开放问题 + +问:参数是否应该支持复杂的嵌套对象,还是仅限于简单类型? +答:参数值将被字符串编码,我们可能更倾向于 + 使用字符串。 + +<<<<<<< HEAD +问:是否允许在队列名称中使用参数占位符,还是仅在 +======= +问:是否允许在队列名称中使用参数占位符,或者仅在 +>>>>>>> 82edf2d (New md files from RunPod) + 参数中使用? +答:仅在参数中使用,以避免奇怪的注入和边缘情况。 + +问:如何处理参数名称与系统变量(如 + `id` 和 `class`)之间的冲突? +答:在启动流程时,指定 id 和 class 是无效的。 + +问:我们是否应该支持计算参数(从其他参数派生)? +答:仅进行字符串替换,以避免奇怪的注入和边缘情况。 + +<<<<<<< HEAD +## 引用 +======= +## 参考文献 +>>>>>>> 82edf2d (New md files from RunPod) + +JSON Schema 规范:https://json-schema.org/ +流程蓝图定义规范:docs/tech-specs/flow-class-definition.md diff --git a/docs/tech-specs/graph-contexts.ar.md b/docs/tech-specs/graph-contexts.ar.md new file mode 100644 index 00000000..db7ca47d --- /dev/null +++ b/docs/tech-specs/graph-contexts.ar.md @@ -0,0 +1,344 @@ +--- +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 لمواءمتها مع RDF 1.2 ولتقديم دعم كامل لسمات مجموعة بيانات RDF. هذا تغيير جذري لإصدار 2.x. + +### إصدارات + +- **2.0**: إصدار للمستخدمين الأوائل. تتوفر الميزات الأساسية، وقد لا تكون جاهزة تمامًا للإنتاج. +- **2.1 / 2.2**: إصدار جاهز للإنتاج. الاستقرار والشمولية تم التحقق منهما. + +إن توفير مرونة بشأن مستوى النضج هو مقصود - يمكن للمستخدمين الأوائل الوصول إلى إمكانيات جديدة قبل أن تصبح جميع الميزات جاهزة للإنتاج. + +## الأهداف + +الأهداف الرئيسية لهذا العمل هي تمكين البيانات الوصفية حول الحقائق/البيانات: + +- **المعلومات الزمنية**: ربط الحقائق ببيانات وصفية تتعلق بالوقت + - متى اعتبرت حقيقة صحيحة + - متى أصبحت حقيقة صحيحة + - متى اكتشف أن حقيقة غير صحيحة + +- **الأصل/المصادر**: تتبع المصادر التي تدعم حقيقة ما + - "هذه الحقيقة مدعومة من المصدر X" + - ربط الحقائق بوثائقها الأصلية + +- **الموثوقية/الثقة**: تسجيل التأكيدات حول الحقيقة + - "الشخص P أعلن أن هذا صحيح" + - "الشخص Q يدعي أن هذا غير صحيح" + - تمكين تسجيل النقاط والتحقق من التعارض + +**الفرضية**: Reification (RDF-star / quoted triples) هي الآلية الرئيسية لتحقيق هذه النتائج، حيث تتطلب جميعها إجراء بيانات حول البيانات. + +## الخلفية + +للتعبير عن "تم اكتشاف حقيقة (تعرف أليس بوب) في 2024-01-15" أو "يدعم المصدر X الادعاء (يسبب Y Z)"، تحتاج إلى الرجوع إلى حافة كشيء يمكنك إجراء بيانات حوله. لا تدعم الثلاثيات القياسية هذا. + +### القيود الحالية + +يمكن للفئة `Value` الحالية في `trustgraph-base/trustgraph/schema/core/primitives.py` أن تمثل: +- عقد URI (`is_uri=True`) +- قيم حرفية (`is_uri=False`) + +يوجد الحقل `type` ولكنه لا يستخدم لتمثيل أنواع بيانات XSD. + +## التصميم التقني + +### ميزات RDF المدعومة + +#### الميزات الأساسية (المرتبطة بأهداف إعادة التعريف) + +ترتبط هذه الميزات بشكل مباشر بالأهداف الزمنية والأصل والموثوقية: + +1. **RDF 1.2 Quoted Triples (RDF-star)** + - حواف تشير إلى حواف أخرى + - يمكن أن تظهر الثلاثية كـ subject أو object في ثلاثية أخرى + - تمكن البيانات حول البيانات (reification) + - الآلية الأساسية لتعليق الحقائق الفردية + +2. **RDF Dataset / Named Graphs** + - دعم رسوم بيانية مسماة متعددة داخل مجموعة بيانات + - يتم تحديد كل رسم بياني بواسطة IRI + - الانتقال من ثلاثيات (s, p, o) إلى أرباع (s, p, o, g) + - يتضمن الرسم البياني الافتراضي بالإضافة إلى رسم بياني مسمى واحد أو أكثر + - يمكن أن يكون IRI الرسم البياني subject في البيانات، على سبيل المثال: + ``` + "2024-01-15" + "high" + ``` + - ملاحظة: الرسوم البيانية المسماة ميزة منفصلة عن إعادة التعريف. لها استخدامات تتجاوز تعليق البيانات (التقسيم، التحكم في الوصول، تنظيم مجموعة البيانات) ويجب اعتبارها قدرة متميزة. + +3. **Blank Nodes** (دعم محدود) + - عقد مجهولة الهوية بدون URI عالمي + - مدعوم من أجل التوافق عند تحميل بيانات RDF خارجية + - **حالة محدودة**: لا توجد ضمانات بشأن الهوية المستقرة بعد التحميل + - ابحث عنها عبر استعلامات wildcard (تطابق عن طريق الاتصالات، وليس عن طريق المعرف) + - ليست ميزة أساسية - لا تعتمد على معالجة دقيقة لعقد فارغة + +#### إصلاحات فرعية (تغيير جذري للإصدار 2.0) + +هذه الميزات ليست مرتبطة بشكل مباشر بأهداف إعادة التعريف ولكنها تحسينات قيمة يجب تضمينها أثناء إجراء تغييرات جذرية: + +4. **Literal Datatypes** + - استخدام الحقل `type` بشكل صحيح لأنواع بيانات XSD + - أمثلة: xsd:string, xsd:integer, xsd:dateTime، إلخ. + - يحل مشكلة حالية: لا يمكن تمثيل التواريخ أو الأعداد الصحيحة بشكل صحيح + +5. **Language Tags** + - دعم سمات اللغة على الحرفيات (`@en`, `@fr`, إلخ) + - ملاحظة: تحتوي الحرفية على إما علامة لغة أو نوع بيانات، وليس كلاهما (باستثناء `rdf:langString`) + - مهم لحالات الاستخدام المتعلقة بالذكاء الاصطناعي/اللغات المتعددة + +### نماذج البيانات + +#### Term (تغيير من Value) + +سيتم إعادة تسمية الفئة `Value` إلى `Term` لتعكس بشكل أفضل المصطلحات الخاصة بـ RDF. تخدم عملية إعادة التسمية هذه غرضين: +1. توافق التسمية مع مفاهيم RDF (يمكن أن يكون "Term" IRI أو عقدة فارغة أو حرفية أو ثلاثية مقتبسة - وليس مجرد "value") +2. إجبار مراجعة التعليمات البرمجية عند واجهة التغيير الجذري - أي تعليمات برمجية لا تزال تشير إلى `Value` ستظهر بشكل واضح أنها معطلة وتحتاج إلى التحديث + +يمكن أن يمثل Term: + +- **IRI/URI** - عقدة/مورد مسماة +- **Blank Node** - عقدة مجهولة الهوية ذات نطاق محلي +- **Literal** - قيمة بيانات مع إما: + - نوع بيانات (XSD type)، أو + - علامة لغة +- **Quoted Triple** - ثلاثية تستخدم كـ term (RDF 1.2) + +##### النهج المختار: فئة واحدة مع مُميز نوع + +تحدد متطلبات التسلسل الهيكل - هناك حاجة إلى مُميز نوع في التنسيق السلكي بغض النظر عن التمثيل في Python. الفئة الواحدة ذات نوع التمييز هي الأنسب وتتوافق مع نمط `Value` الحالي. + +توفر رموز النوع أحادية الحرف تسلسلًا مضغوطًا: + +```python +from dataclasses import dataclass + +# ثوابت أنواع Term +IRI = "i" # عقدة URI +BLANK = "b" # عقدة فارغة +LITERAL = "l" # قيمة حرفية +TRIPLE = "t" # ثلاثية مقتبسة (RDF 1.2) + +@dataclass +class Term: + type: str = "" # واحد من: IRI, BLANK, LITERAL, TRIPLE + + # لـ مصطلحات IRI (type == IRI) + iri: str = "" + + # لـ عقد فارغة (type == BLANK) + id: str = "" + + # لـ الحرفيات (type == LITERAL) + value: str = "" + datatype: str = "" # URI لنوع بيانات XSD (مستبعدة مع اللغة) + language: str = "" # علامة لغة (مستبعدة مع نوع البيانات) + + # لـ ثلاثيات مقتبسة (type == TRIPLE) + triple: "Triple | None" = None +``` + +أمثلة على الاستخدام: + +```python +# مصطلح IRI +node = Term(type=IRI, iri="http://example.org/Alice") + +# حرفية مع نوع بيانات +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# حرفية مع علامة لغة +label = Term(type=LITERAL, value="Hello", language="en") + +# عقدة فارغة +anon = Term(type=BLANK, id="_:b1") + +# ثلاثية مقتبسة (بيانات حول بيانات) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +#### البدائل التي تم أخذها في الاعتبار + +**الخيار B: اتحاد الفئات المتخصصة** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- مرفوض: لا يزال التسلسل يحتاج إلى مُميز نوع، مما يضيف تعقيدًا + +**الخيار C: فئة أساسية مع فئات فرعية** +- مرفوض: نفس مشكلة التسلسل، بالإضافة إلى تعقيدات وراثة dataclass + +#### Triple / Quad + +تكتسب الفئة `Triple` حقل اختياري للرسم البياني ليصبح أربعة: + +```python +@dataclass +class Triple: + s: Term | None = None # Subject + p: Term | None = None # Predicate + o: Term | None = None # Object + g: str | None = None # اسم الرسم البياني (IRI)، None = الرسم البياني الافتراضي +``` + +قرارات التصميم: +- **اسم الحقل**: `g` لضمان الاتساق مع `s`, `p`, `o` +- **اختياري**: `None` يعني الرسم البياني الافتراضي (غير المسمى) +- **النوع**: سلسلة عادية (IRI) بدلاً من Term + - أسماء الرسم البياني هي دائمًا IRIs + - تم استبعاد العقد الفارغة كأسماء للرسوم البيانية (مربكة جدًا) + - لا حاجة إلى آليات Term الكاملة + +لاحظ أن اسم الفئة يظل `Triple` حتى لو كانت ثلاثية الآن. هذا يتجنب التغييرات الجذرية و "triple" هي لا تزال المصطلحات الشائعة. السياق البياني هو بيانات وصفية حول مكان وجود الثلاثية. + +### أنماط استعلام مرشحة + +يقبل محرك الاستعلام الحالي مجموعات من مصطلحات S, P, O. مع ثلاثيات مقتبسة، تصبح الثلاثية نفسها مصطلحًا صالحًا في هذه المواضع. فيما يلي أنماط استعلام مرشحة تدعم الأهداف الأصلية. + +#### معاني معلمات الرسم البياني + +باتباع اصطلاحات SPARQL للتوافق مع الإصدارات السابقة: + +- **تم حذف `g` / None**: استعلام للرسم البياني الافتراضي فقط +- **`g` = IRI محدد**: استعلام لهذا الرسم البياني المسمى فقط +- **`g` = حرف جاموسي / `*`**: استعلام عبر جميع الرسوم البيانية (مكافئ لـ SPARQL + `GRAPH ?g { ... }`) + +هذا يحافظ على بساطة الاستعلامات البسيطة ويجعل استعلامات الرسم البياني المسماة اختيارية. + +تدعم الاستعلامات عبر الرسوم البيانية (g=حرف جاموسي). يحتوي مخطط Cassandra على جداول مخصصة (SPOG, POSG, OSPG) حيث g هو عمود تجميع بدلاً من مفتاح التقسيم، مما يتيح استعلامات فعالة عبر جميع الرسوم البيانية. + +#### استعلامات زمنية + +**ابحث عن جميع الحقائق التي تم اكتشافها بعد تاريخ معين:** +``` +S: ? # أي ثلاثية مقتبسة +P: +O: > "2024-01-15"^^xsd:date # مقارنة التاريخ +``` + +**ابحث عن الوقت الذي اعتبرت فيه حقيقة صحيحة:** +``` +S: << >> # ثلاثية مقتبسة كـ subject +P: +O: ? # يعيد التاريخ +``` + +**ابحث عن الحقائق التي تبين أنها خاطئة:** +``` +S: ? # أي ثلاثية مقتبسة +P: +O: ? # له أي قيمة (موجود) +``` + +#### استعلامات الأصل + +**ابحث عن جميع الحقائق التي يدعمها مصدر معين:** +``` +S: ? # أي ثلاثية مقتبسة +P: +O: +``` + +**ابحث عن المصادر التي تدعم حقيقة معينة:** +``` +S: << >> # ثلاثية مقتبسة كـ subject +P: +O: ? # يعيد IRIs المصدر +``` + +#### استعلامات الموثوقية + +**ابحث عن التأكيدات التي أعلن شخص ما أنها صحيحة:** +``` +S: ? # أي ثلاثية مقتبسة +P: +O: +``` + +**ابحث عن التأكيدات المتعارضة (نفس الحقيقة، موثوقية مختلفة):** +``` +# الاستعلام الأول: الحقائق التي أعلنت صحتها +S: ? +P: +O: ? + +# الاستعلام الثاني: الحقائق التي أعلنت أنها خاطئة +S: ? +P: +O: ? + +# منطق التطبيق: ابحث عن تقاطع الـ subjects +``` + +**ابحث عن الحقائق التي تقل فيها درجة الثقة عن حد معين:** +``` +S: ? +P: +O: [threshold] +``` + +### حد تخزين المتجهات + +تستخدم مخازن المتجهات دائمًا IRIs فقط: +- لا توجد حواف (ثلاثيات مقتبسة) +- لا توجد قيم حرفية +- لا توجد عقد فارغة + +هذا يبقي تخزين المتجهات بسيطًا - يتعامل مع التشابه الدلالي للكائنات المسماة. يتعامل هيكل الرسم البياني مع العلاقات وإعادة التعريف والبيانات الوصفية. لا تعقد الثلاثيات المقتبسة والرسوم البيانية المسماة عمليات المتجهات. + +## اعتبارات الأمان + +الرسوم البيانية المسماة ليست ميزة أمان. تظل المستخدمون والمجموعات هي حدود الأمان. الرسوم البيانية المسماة مخصصة لتنظيم البيانات فقط وليست لإعادة التعريف. + +## اعتبارات الأداء + +- يمكن أن تضيف الثلاثيات المقتبسة عمق التداخل - قد تؤثر على أداء الاستعلام +- هناك حاجة إلى استراتيجيات فهرسة الرسم البياني المسماة للاستعلامات الفعالة الموجهة للرسم البياني +- يجب أن يستوعب تصميم مخطط Cassandra تخزين الأربعة بكفاءة + +### واجهة مستخدم مخزن المتجهات + +دائمًا ما تشير مخازن المتجهات إلى IRIs فقط: +- لا توجد حواف (ثلاثيات مقتبسة) +- لا توجد قيم حرفية +- لا توجد عقد فارغة + +هذا يبقي مخزن المتجهات بسيطًا - يتعامل مع التشابه الدلالي للكائنات المسماة. يتعامل هيكل الرسم البياني مع العلاقات وإعادة التعريف والبيانات الوصفية. لا تعقد الثلاثيات المقتبسة والرسوم البيانية المسماة عمليات المتجهات. + +## استراتيجية الاختبار + +استخدم استراتيجية الاختبار الحالية. نظرًا لأن هذا تغيير جذري، ركز بشكل كبير على مجموعة الاختبار الشاملة للتحقق من أن الهياكل الجديدة تعمل بشكل صحيح عبر جميع المكونات. + +## خطة الترحيل + +- 2.0 هو إصدار جذري؛ لا توجد توافقية مع الإصدارات السابقة مطلوبة +- قد تتطلب البيانات الحالية ترحيلًا إلى مخطط جديد (سيتم تحديده بناءً على التصميم النهائي) +- ضع في اعتبارك أدوات الترحيل لتحويل الثلاثيات الموجودة + +## أسئلة مفتوحة + +- **العقد الفارغة**: تم تأكيد الدعم المحدود. قد تحتاج إلى تحديد استراتيجية skolemization (إنشاء IRIs عند التحميل أو الحفاظ على معرفات العقد الفارغة). +- **بناء جملة الاستعلام**: ما هي البنية النحوية الملموسة لتحديد الثلاثيات المقتبسة في الاستعلامات؟ تحتاج إلى تعريف واجهة برمجة تطبيقات الاستعلام. +- ~~**مفردات السمة**~~: تم الحل. أي عناصر من المفردات RDF الصالحة مسموح بها، بما في ذلك العناصر المخصصة التي يحددها المستخدم. افتراضات قليلة جدًا عن صلاحية RDF. +- ~~**تأثير مستودع المتجهات**~~: تم الحل. تشير مستودعات المتجهات دائمًا إلى IRIs فقط - لا توجد حواف أو قيم حرفية أو عقد فارغة. لا تؤثر الثلاثيات المقتبسة وإعادة التعريف على مستودع المتجهات. +- ~~**دلالات الرسم البياني المسماة**~~: تم الحل. الاستعلامات افتراضيًا هي الرسم البياني الافتراضي (تتوافق مع سلوك SPARQL، متوافقة مع الإصدارات السابقة). مطلوب معلمة رسم بياني صريحة للاستعلام عن الرسوم البيانية المسماة أو جميع الرسوم البيانية. + +## المراجع + +- [RDF 1.2 Concepts](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-star and SPARQL-star](https://w3c.github.io/rdf-star/) +- [RDF Dataset](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.es.md b/docs/tech-specs/graph-contexts.es.md new file mode 100644 index 00000000..df30cb3a --- /dev/null +++ b/docs/tech-specs/graph-contexts.es.md @@ -0,0 +1,394 @@ +--- +layout: default +title: "Especificación Técnica de Contextos de Grafos" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Contextos de Grafos + +> **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 los cambios en los primitivos de grafos centrales de TrustGraph para +alinearse con RDF 1.2 y admitir la semántica completa del conjunto de datos RDF. Este es un +cambio importante para la serie de versiones 2.x. + +### Versionamiento + +- **2.0**: Lanzamiento para adoptantes tempranos. Características principales disponibles, + puede que no esté completamente lista para producción. +- **2.1 / 2.2**: Lanzamiento de producción. Estabilidad y completitud validadas. + +La flexibilidad en cuanto a la madurez es intencional: los adoptantes tempranos pueden acceder a nuevas +capacidades antes de que todas las funciones estén listas para producción. + +## Objetivos + +Los objetivos principales de este trabajo son habilitar metadatos sobre hechos/afirmaciones: + +- **Información temporal**: Asociar hechos con metadatos de tiempo + - Cuándo se creyó que un hecho era verdadero + - Cuándo un hecho se volvió verdadero + - Cuándo se descubrió que un hecho era falso + +- **Origen/Fuentes**: Realizar un seguimiento de las fuentes que respaldan un hecho + - "Este hecho fue respaldado por la fuente X" + - Enlazar los hechos con sus documentos de origen + +- **Veracidad/Confianza**: Registrar afirmaciones sobre la verdad + - "La persona P afirmó que esto era cierto" + - "La persona Q afirma que esto es falso" + - Habilitar la puntuación de confianza y la detección de conflictos + +**Hipótesis**: La reificación (RDF-star / triples con comillas) es el mecanismo clave +para lograr estos resultados, ya que todos requieren hacer afirmaciones sobre afirmaciones. + +## Antecedentes + +Para expresar "el hecho (Alice conoce a Bob) se descubrió el 2024-01-15" o +"la fuente X respalda la afirmación (Y causa Z)", necesita referenciar un borde +como algo sobre lo cual se pueden hacer afirmaciones. Los triples estándar no admiten esto. + +### Limitaciones actuales + +La clase `Value` actual en `trustgraph-base/trustgraph/schema/core/primitives.py` +puede representar: +- Nodos URI (`is_uri=True`) +- Valores literales (`is_uri=False`) + +El campo `type` existe, pero no se utiliza para representar los tipos de datos XSD. + +## Diseño técnico + +### Características de RDF a admitir + +#### Características principales (relacionadas con los objetivos de reificación) + +Estas características están directamente relacionadas con los objetivos temporales, de origen y de veracidad: + +1. **RDF 1.2 Triples con comillas (RDF-star)** + - Bordes que apuntan a otros bordes + - Un triple puede aparecer como sujeto u objeto de otro triple + - Permite hacer afirmaciones sobre afirmaciones (reificación) + - Mecanismo central para anotar hechos individuales + +2. **Conjunto de datos RDF / Grafos con nombre** + - Soporte para múltiples grafos con nombre dentro de un conjunto de datos + - Cada grafo identificado por un IRI + - Pasa de triples (s, p, o) a cuads (s, p, o, g) + - Incluye un grafo predeterminado más cero o más grafos con nombre + - El IRI del grafo puede ser un sujeto en las afirmaciones, por ejemplo: + ``` + "2024-01-15" + "high" + ``` + - Nota: Los grafos con nombre son una característica separada de la reificación. Tienen + usos más allá de la anotación de afirmaciones (particionamiento, control de acceso, organización del conjunto de datos) + y deben tratarse como una capacidad distinta. + +3. **Nodos vacíos** (Soporte limitado) + - Nodos anónimos sin un URI global + - Compatible al cargar datos RDF externos + - **Estado limitado**: No hay garantías sobre la identidad estable después de la carga + - Encontrarlos a través de consultas comodín (coincidencia por conexiones, no por ID) + - No es una característica de primera clase: no confíe en el manejo preciso de nodos vacíos. + +#### Correcciones oportunistas (cambio importante de la versión 2.0) + +Estas características no están directamente relacionadas con los objetivos de la reificación, pero son +mejoras valiosas a incluir al realizar cambios importantes: + +4. **Tipos de literales** + - Utilice correctamente el campo `type` para los tipos de datos XSD + - Ejemplos: xsd:string, xsd:integer, xsd:dateTime, etc. + - Corrige la limitación actual: no se pueden representar fechas o enteros correctamente. + +5. **Etiquetas de idioma** + - Soporte para atributos de idioma en literales (por ejemplo, @en, @fr) + - Nota: un literal tiene una etiqueta de idioma O un tipo de datos, no ambos + (excepto para rdf:langString) + - Importante para casos de uso de IA/multilingües. + +### Modelos de datos + +#### Término (cambiar de Value) + +La clase `Value` se renombrará a `Term` para reflejar mejor la terminología de RDF. +Este cambio de nombre tiene dos propósitos: +1. Alinea la nomenclatura con los conceptos de RDF (un "Término" puede ser un IRI, literal, nodo vacío o triple con comillas, + no solo un "valor") +2. Fuerza la revisión del código en la interfaz de cambio importante: cualquier código que aún haga referencia a `Value` + se considera roto y debe actualizarse. + +Un Término puede representar: + +- **IRI/URI**: un nodo/recurso con nombre +- **Nodo vacío**: un nodo anónimo con alcance local +- **Literal**: un valor de datos con: + - Un tipo de datos (tipo XSD), O + - Una etiqueta de idioma +- **Triple con comillas**: un triple utilizado como término (RDF 1.2) + +##### Enfoque elegido: Clase única con discriminador de tipo + +Los requisitos de serialización impulsan la estructura: se necesita un discriminador de tipo en el formato de cable +independientemente de la representación de Python. Una clase única con un campo de tipo es la opción natural y se alinea con la +patrón `Value` actual. + +Los códigos de tipo de un solo carácter proporcionan una serialización compacta: + +```python +from dataclasses import dataclass + +# Constantes de tipo de término +IRI = "i" # Nodo IRI/URI +BLANK = "b" # Nodo vacío +LITERAL = "l" # Valor literal +TRIPLE = "t" # Triple con comillas (RDF 1.2) + +@dataclass +class Term: + type: str = "" # Uno de: IRI, BLANK, LITERAL, TRIPLE + + # Para términos IRI (type == IRI) + iri: str = "" + + # Para nodos vacíos (type == BLANK) + id: str = "" + + # Para literales (type == LITERAL) + value: str = "" + datatype: str = "" # URI de tipo de datos XSD (mutuamente excluyente con el idioma) + language: str = "" # Etiqueta de idioma (mutuamente excluyente con el tipo de datos) + + # Para triples con comillas (type == TRIPLE) + triple: "Triple | None" = None +``` + +Ejemplos de uso: + +```python +# Término IRI +node = Term(type=IRI, iri="http://example.org/Alice") + +# Literal con tipo de datos +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# Literal con etiqueta de idioma +label = Term(type=LITERAL, value="Hello", language="en") + +# Nodo vacío +anon = Term(type=BLANK, id="_:b1") + +# Triple con comillas (afirmación sobre una afirmación) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### Alternativas consideradas + +**Opción B: Unión de clases especializadas** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- Rechazada: La serialización aún necesitaría un discriminador de tipo, lo que agregaría complejidad. + +**Opción C: Clase base con subclases** +- Rechazada: El mismo problema de serialización, además de peculiaridades de la herencia de dataclass. + +#### Triple / Cuad + +La clase `Triple` gana un campo de grafo opcional para convertirse en un cuad: + +```python +@dataclass +class Triple: + s: Term | None = None # Sujeto + p: Term | None = None # Predicado + o: Term | None = None # Objeto + g: str | None = None # Nombre del grafo (IRI), None = grafo predeterminado +``` + +Decisiones de diseño: +- **Nombre del campo**: `g` para la coherencia con `s`, `p`, `o` +- **Opcional**: `None` significa el grafo predeterminado (sin nombre) +- **Tipo**: Cadena simple (IRI) en lugar de Term + - Los nombres de los grafos siempre son IRIs + - Los nodos vacíos como nombres de grafos se descartaron (demasiado confusos) + - No es necesario el conjunto completo de mecanismos de Term + +Nota: El nombre de la clase permanece `Triple` incluso si técnicamente es un cuad ahora. +Esto evita la alteración y la terminología "triple" todavía es la terminología común. El contexto del grafo es +metadatos sobre dónde vive el triple. + +### Patrones de consulta candidatos + +El motor de consulta actual acepta combinaciones de términos S, P, O. Con los triples con comillas, +un triple en sí mismo se convierte en un término válido en esas posiciones. A continuación, se presentan patrones de consulta +candidatos que admiten los objetivos originales. + +#### Semántica de parámetros de grafo + +Siguiendo las convenciones de SPARQL para la compatibilidad hacia atrás: + +- **`g` omitido / None**: Consulta solo el grafo predeterminado +- **`g` = IRI específico**: Consulta solo ese grafo con nombre +- **`g` = comodín / `*`**: Consulta en todos los grafos (equivalente a `GRAPH ?g { ... }` de SPARQL) + +Esto mantiene las consultas simples simples y hace que las consultas de grafos con nombre sean opcionales. + +Las consultas entre grafos (g=comodín) se admiten completamente. El esquema de Cassandra incluye tablas dedicadas (SPOG, POSG, OSPG) +donde g es una columna de agrupación, en lugar de una clave de partición, lo que permite consultas eficientes en todos los grafos. + +#### Consultas temporales + +**Encontrar todos los hechos descubiertos después de una fecha determinada:** +``` +S: ? # cualquier triple con comillas +P: +O: > "2024-01-15"^^xsd:date # comparación de fecha +``` + +**Encontrar cuándo se creyó que un hecho era verdadero:** +``` +S: << >> # triple con comillas como sujeto +P: +O: ? # devuelve la fecha +``` + +**Encontrar los hechos que se descubrió que eran falsos:** +``` +S: ? # cualquier triple con comillas +P: +O: ? # tiene cualquier valor (existe) +``` + +#### Consultas de origen + +**Encontrar todos los hechos respaldados por una fuente específica:** +``` +S: ? # cualquier triple con comillas +P: +O: +``` + +**Encontrar qué fuentes respaldan un hecho específico:** +``` +S: << >> # triple con comillas como sujeto +P: +O: ? # devuelve las IRIs de la fuente +``` + +#### Consultas de veracidad + +**Encontrar las afirmaciones que una persona marcó como verdaderas:** +``` +S: ? # cualquier triple con comillas +P: +O: +``` + +**Encontrar las afirmaciones conflictivas (el mismo hecho, diferente veracidad):** +``` +# Primera consulta: hechos afirmados como verdaderos +S: ? +P: +O: ? + +# Segunda consulta: hechos afirmados como falsos +S: ? +P: +O: ? + +# Lógica de la aplicación: encontrar la intersección de los sujetos +``` + +**Encontrar los hechos con una puntuación de confianza por debajo del umbral:** +``` +S: ? # cualquier triple con comillas +P: +O: < 0.5 # comparación numérica +``` + +### Arquitectura + +Se requieren cambios significativos en varios componentes: + +#### Este repositorio (trustgraph) + +- **Primitivos del esquema** (`trustgraph-base/trustgraph/schema/core/primitives.py`) + - `Value` → `Term` cambio de nombre + - Nueva estructura de `Term` con discriminador de tipo + - `Triple` gana el campo `g` para el contexto del grafo + +- **Traductores de mensajes** (`trustgraph-base/trustgraph/messaging/translators/`) + - Actualizaciones para las nuevas estructuras de `Term` y `Triple` + +- **Componentes de puerta de enlace** + - Manejar nuevas estructuras de `Term` y cuádruple + +- **Núcleos de conocimiento** + - ... + +- **Pruebas** + - ... + +Esto se deja para futuras implementaciones. + +- **Vector store boundary** + - ... + +Esto se deja para futuras implementaciones. + +## Consideraciones de seguridad + +Los grafos con nombre no son una característica de seguridad. Los usuarios y las colecciones siguen siendo los límites de seguridad. +Los grafos con nombre son puramente para la organización de datos y el soporte de la reificación. + +## Consideraciones de rendimiento + +- Los triples con comillas agregan profundidad de anidamiento; esto puede afectar el rendimiento de las consultas. +- Se necesitan estrategias de indexación para consultas con ámbito de grafo. +- El diseño del esquema de Cassandra deberá acomodar el almacenamiento de cuádruples de forma eficiente. + +### Límite del almacén vectorial + +Los almacenes vectoriales siempre hacen referencia a IRIs: +- Nunca bordes (triples con comillas) +- Nunca valores literales +- Nunca nodos vacíos + +Esto mantiene el almacén vectorial simple; se encarga de la similitud semántica de las entidades con nombre. La estructura del grafo maneja las relaciones, la reificación y los metadatos. Los triples con comillas y los grafos con nombre no complican las operaciones vectoriales. + +## Estrategia de pruebas + +Utilice la estrategia de prueba existente. Dado que esta es una versión importante, se prestará especial atención al +conjunto de pruebas de extremo a extremo para validar que las nuevas estructuras funcionan correctamente en todos los componentes. + +## Plan de migración + +- La versión 2.0 es una versión importante; no se requiere compatibilidad con versiones anteriores +- Los datos existentes pueden necesitar migrarse al nuevo esquema (por determinarse según el diseño final) +- Considere herramientas de migración para convertir triples existentes + +## Preguntas abiertas + +- **Nodos vacíos**: Soporte limitado confirmado. Es posible que deba decidirse sobre una estrategia de skolemización (generar IRIs + al cargar o preservar los ID de nodos vacíos). +- **Sintaxis de consulta**: ¿Cuál es la sintaxis concreta para especificar triples con comillas en las consultas? Debe definirse + la API de consulta. +- ~~**Vocabulario de predicados**~~: Resuelto. Se permiten todos los predicados RDF válidos, incluidos los personalizados definidos por el usuario. + Supuestos mínimos sobre la validez de RDF. Muy pocos valores bloqueados (por ejemplo, `rdfs:label` se utiliza en algunos lugares). + Estrategia: evite bloquear cualquier cosa a menos que sea absolutamente necesario. +- ~~**Impacto del almacén vectorial**~~: Resuelto. Los almacenes vectoriales siempre apuntan a IRIs. + solo; nunca bordes, literales o nodos vacíos. Los triples con comillas y la reificación no afectan al almacén vectorial. +- ~~**Semántica del grafo con nombre**~~: Resuelta. Las consultas predeterminadas son para el grafo predeterminado (coincide con el comportamiento de SPARQL, + compatible con versiones anteriores). Se requiere un parámetro de grafo explícito para consultar grafos con nombre o todos los grafos. + +## Referencias + +- [Conceptos RDF 1.2](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-star y SPARQL-star](https://w3c.github.io/rdf-star/) +- [Conjunto de datos RDF](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.he.md b/docs/tech-specs/graph-contexts.he.md new file mode 100644 index 00000000..929d8c34 --- /dev/null +++ b/docs/tech-specs/graph-contexts.he.md @@ -0,0 +1,324 @@ +--- +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, +כדי להתאים ל-RDF 1.2 ולתמוך בסמנטיקה מלאה של סט נתונים RDF. +זוהי שינוי משמעותי עבור סדרת השחרורים 2.x. + +### גרסאות + +- **2.0**: גרסה למתקדמים. תכונות ליבה זמינות, ייתכן שאינן + מוכנות לחלוטין לשימוש בייצור. +- **2.1 / 2.2**: גרסת ייצור. יציבות ושלמות אומתו. + +הגמישות בנוגע לבשלות היא מכוונת - משתמשים מתקדמים יכולים לגשת +ליכולות חדשות לפני שכל התכונות מוכנות לשימוש בייצור. + +## מטרות + +המטרות העיקריות של עבודה זו הן לאפשר מטא-נתונים על עובדות/הצהרות: + +- **מידע זמני**: קשר עובדות עם מטא-נתונים של זמן + - מתי עובדה נחשבה לנכונה + - מתי עובדה הפכה לנכונה + - מתי עובדה התגלתה כלא נכונה + +- **מקורות/מקורות**: מעקב אחר מקורות התומכים בעובדה + - "עובדה זו נתמכה על ידי המקור X" + - קישור עובדות למסמכי המקור שלהן + +- **נכונות/אמינות**: תיעוד הצהרות על אמת + - "האדם P טען שזה נכון" + - "האדם Q טוען שזה לא נכון" + - אפשרות לחישוב ציון אמינות וגילוי סתירות + +**השערה**: Reification (RDF-star / משולשות מצוטטות) הוא המנגנון העיקרי +לשם השגת תוצאות אלה, מכיוון שכולן דורשות הצהרות על הצהרות. + +## רקע + +כדי להביע "העובדה (אליס יודעת את בוב) התגלתה ב-2024-01-15" או +"מקור X תומך בטענה (Y גורם ל-Z)", אתה צריך להתייחס לקצה +כאל דבר שאפשר להצהיר עליו. משולשות סטנדרטיים אינם תומכים בכך. + +### מגבלות נוכחיות + +המחלקת `Value` הנוכחית ב-`trustgraph-base/trustgraph/schema/core/primitives.py` +יכולה לייצג: +- צומתי URI (`is_uri=True`) +- ערכים מילוליים (`is_uri=False`) + +השדה `type` קיים אך אינו משמש לייצוג טיפוסי נתונים של XSD. + +## עיצוב טכני + +### תכונות RDF לתמיכה + +#### תכונות ליבה (קשור למטרות ה-Reification) + +תכונות אלו קשורות ישירות למטרות הזמן, המקור והנכונות: + +1. **משולשות מצוטטות של RDF 1.2 (RDF-star)** + - קצוות המצביעים על קצוות אחרים + - משולש יכול להופיע כנושא או כאובייקט של משולש אחר + - מאפשר הצהרות על הצהרות (reification) + - מנגנון ליבה לסימון עובדות בודדות + +2. **סט נתונים RDF / גרפים בעלי שם** + - תמיכה במספר גרפים בעלי שם בתוך סט נתונים + - כל גרף מזוהה על ידי IRI + - מעבר משלשות (s, p, o) לארבעיות (s, p, o, g) + - כולל גרף ברירת מחדל ואחד או יותר גרפים בעלי שם + - ניתן להשתמש ב-IRI של הגרף כנושא בהצהרות, לדוגמה: + ``` + "2024-01-15" + "high" + ``` + - הערה: גרפים בעלי שם הם תכונה נפרדת מ-reification. יש להם + שימושים מעבר לסימון הצהרות (מחיצה, בקרת גישה, ארגון סט נתונים) + ועליהם להתייחס אליהם כלי יכולת נפרדת. + +3. **צמתים ריקים** (תמיכה מוגבלת) + - צמתים אנונימיים ללא URI גלובלי + - נתמך לצורך תאימות בעת טעינת נתוני RDF חיצוניים + - **סטטוס מוגבל**: אין ערובות לזהות יציבה לאחר הטעינה + - ניתן למצוא אותם באמצעות שאילתות wildcard (התאמה לפי חיבורים, לא לפי מזהה) + - לא תכונה ראשית - אין להסתמך על טיפול מדויק בצמתים ריקים + +#### תיקונים הזדמנותיים (שינוי שבירה 2.0) + +תכונות אלה אינן קשורות ישירות למטרות ה-reification, אך הן שיפורים +חשובים שצריך לכלול בעת ביצוע שינויים שבירים: + +4. **טיפוסי מילוליים** + - שימוש נכון בשדה `type` עבור טיפוסי נתונים של XSD + - דוגמאות: xsd:string, xsd:integer, xsd:dateTime וכו' + - פותר מגבלה קיימת: לא ניתן לייצג תאריכים או מספרים שלמים כראוי + +5. **תגיות שפה** + - תמיכה בתכונות שפה על מילוליים (en, fr וכו') + - הערה: למילול יש תגית שפה או טיפוס נתונים, לא את שניהם + (מלבד rdf:langString) + - חשוב עבור מקרי שימוש בבינה מלאכותית/רב-לשוניים + +### מודלים של נתונים + +#### Term (שינוי שם מ-Value) + +המחלקת `Value` תשנה את שמה ל-`Term` כדי לשקף טוב יותר את המונחים של RDF. +שינוי שם זה משרת שני מטרות: +1. מיישר את שמות עם מושגים של RDF (ה- "Term" יכול להיות IRI, מילול, צומת ריק או משולש מצוטט - ולא רק "ערך") +2. גורם לסקירת קוד בממשק לשינוי השבירה - כל קוד שעדיין מתייחס ל-`Value` + נראה שבור באופן גלוי ויש לעדכן אותו + +Term יכול לייצג: + +- **IRI/URI** - צומת/משאב בעל שם +- **צומת ריק** - צומת אנונימי עם תחום מקומי +- **מילול** - ערך נתונים עם: + - טיפוס נתונים (טיפוס XSD), או + - תגית שפה +- **משולש מצוטט** - משולש המשמש כ-term (RDF 1.2) + +##### גישה שנבחרה: מחלקה אחת עם מפריד טיפוס + +דרישות הסתרה חשובות למבנה - מפריד טיפוס נחוץ +בפורמט ה-wire ללא קשר לייצוג ה-Python. מחלקה אחת עם שדה טיפוס היא +ההתאמה הטבעית ותואמת לדפוס ה-`Value` הנוכחי. + +קודים חד-תווים של טיפוסים מספקים הסתרה קומפקטית: + +```python +from dataclasses import dataclass + +# קבועים של סוג Term +IRI = "i" # צומת IRI/URI +BLANK = "b" # צומת ריק +LITERAL = "l" # ערך מילולי +TRIPLE = "t" # משולש מצוטט (RDF-star) + +@dataclass +class Term: + type: str = "" # אחד מ: IRI, BLANK, LITERAL, TRIPLE + + # עבור מונחי IRI (type == IRI) + iri: str = "" + + # עבור צמתים ריקים (type == BLANK) + id: str = "" + + # עבור מילויים (type == LITERAL) + value: str = "" + datatype: str = "" # טיפוס URI של XSD (בלעדי ל-language) + language: str = "" # תגית שפה (בלעדי ל-datatype) + + # עבור משולשות מצוטטות (type == TRIPLE) + triple: "Triple | None" = None +``` + +דוגמאות שימוש: + +```python +# מונח IRI +node = Term(type=IRI, iri="http://example.org/Alice") + +# מילול עם טיפוס נתונים +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# מילול עם תגית שפה +label = Term(type=LITERAL, value="Hello", language="en") + +# צומת ריק +anon = Term(type=BLANK, id="_:b1") + +# משולש מצוטט (הצהרה על הצהרה) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### אלטרנטיבות שנשקלו + +**אפשרות B: איחוד של מחלקות מיוחדות** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- נדחה: הסתרה עדיין תצטרך מפריד טיפוס, מה שמוסיף מורכבות + +**אפשרות C: מחלקה בסיסית עם תת-מחלקה** +- נדחה: אותה בעיית הסתרה, בנוסף לבעיות ירושה של dataclass + +#### משולש / ארבעייה + +המחלקת `Triple` רוכשת שדה גרף אופציונלי כדי להפוך לארבעייה: + +```python +@dataclass +class Triple: + s: Term | None = None # נושא + p: Term | None = None # תכונה + o: Term | None = None # אובייקט + g: str | None = None # שם גרף (IRI), None = גרף ברירת מחדל +``` + +החלטות עיצוב: +- **שם שדה**: `g` לעקביות עם `s`, `p`, `o` +- **אופציונלי**: `None` פירושו הגרף כברירת מחדל (חסר שם) +- **סוג**: מחרוזת פשוטה (IRI) ולא Term + - שמות גרפים הם תמיד IRIs + - צמתים ריקים כשמות גרפים נשללו (מבלבלים) + - אין צורך במכניקת ה-Term המלאה + +שים לב: שם המחלקה נשאר `Triple` גם אם היא טכנית ארבעייה. +זה מונע שינויים ו"משולש" הוא עדיין המונח הנפוץ. הקונטקסט של הגרף +הוא מטא-נתונים לגבי היכן שוכנת השלישייה. + +### תבניות שאילתות מועמדות + +מנוע השאילתות הנוכחי מקבל שילובים של מונחי S, P, O. עם משולשות מצוטטות, +משולש בעצמו הופך ל-term חוקי בעמדות אלה. להלן תבניות שאילתות מועמדות +התומכות במטרות המקוריות. + +#### סמנטיקת פרמטר גרף + +בהתאם לקונבנציות SPARQL עבור תאימות לאחור: + +- **`g` מושמט / None**: שאילתא רק את הגרף כברירת מחדל +- **`g` = IRI ספציפי**: שאילתא רק את הגרף בעל השם הזה +- **`g` = wildcard / `*`**: שאילתא על פני כל הגרפים (שווה ערך ל-SPARQL + `GRAPH ?g { ... }`) + +זה שומר על שאילתות פשוטות כפשוטות ומאפשר שאילתות על גרפים בעלי +שמות כבחירה. + +שאילתות חוצות גרפים (g=wildcard) נתמכות במלואן. סכימת Cassandra +כוללת טבלאות ייעודיות (SPOG, POSG, OSPG) כאשר g הוא עמודת clustering +ולא מפתח מחיצה, המאפשר שאילתות יעילות על פני כל הגרפים. + +#### שאילתות זמניות + +**מצא את כל העובדות שהתגלו בתאריך 2024-01-15:** +``` +SELECT * FROM triples WHERE ?s p1 ?o1 . +``` + +#### שיקולי ביצועים + +- משולשות מצוטטות מוסיפות עומק קינון - עשויות להשפיע על ביצועי השאילתות +- אסטרטגיות אינדוקס לגרפים בעלי שם נחוצות עבור שאילתות יעילות מבוססות גרפים +- עיצוב סכימת Cassandra יצטרך להתאים אחסון ארבעיות ביעילות + +### גבולת מאגר וקטורי + +מאגרי וקטורים תמיד מתייחסים ל-IRIs בלבד: +- לעולם לא קצוות (משולשות מצוטטות) +- לעולם לא ערכים מילוליים +- לעולם לא צמתים ריקים + +זה שומר על מאגר הווקטורים פשוט - הוא מטפל בדמיון סמנטי של ישויות בעלות שם. +המבנה של הגרף מטפל ביחסים, reification ומטא-נתונים. משולשות מצוטטות +וגרפים בעלי שם אינם מסבכים פעולות וקטוריות. + +## שיקולי אבטחה + +גרפים בעלי שם אינם תכונה של אבטחה. משתמשים ואוספים הם גבולות האבטחה. +גרפים בעלי שם הם אך ורק עבור ארגון נתונים ו-reification תמיכה. + +## שיקולי ביצועים + +- משולשות מצוטטות מוסיפות עומק קינון - עשויות להשפיע על ביצועי השאילתות +- אסטרטגיות אינדוקס לגרפים בעלי שם נחוצות עבור שאילתות יעילות מבוססות גרפים +- עיצוב סכימת Cassandra יצטרך להתאים אחסון ארבעיות ביעילות + +### גבולת מאגר וקטורי + +מאגרי וקטורים תמיד מתייחסים ל-IRIs בלבד: +- לעולם לא קצוות (משולשות מצוטטות) +- לעולם לא ערכים מילוליים +- לעולם לא צמתים ריקים + +זה שומר על מאגר הווקטורים פשוט - הוא מטפל בדמיון סמנטי של ישויות בעלות שם. +המבנה של הגרף מטפל ביחסים, reification ומטא-נתונים. משולשות מצוטטות +וגרפים בעלי שם אינם מסבכים פעולות וקטוריות. + +## אסטרטגיית בדיקה + +השתמש באסטרטגיית הבדיקה הקיימת. מכיוון שזוהי גרסה שבירה, יש להתמקד +בבדיקות הקצה כדי לוודא שהמבנים החדשים עובדים כראוי בכל הרכיבים. + +## תוכנית העברה + +- 2.0 היא גרסה שבירה; אין צורך בתאימות לאחור +- ייתכן שיהיה צורך להעביר נתונים קיימים לסכימה חדשה (בהתאם לעיצוב הסופי) +- שקול כלי העברה להמרת משולשות קיימות + +## שאלות פתוחות + +- **צמתים ריקים**: תמיכה מוגבלת אושרה. ייתכן שיהיה צורך להחליט על + אסטרטגיית skolemization (ליצור IRIs בעת הטעינה, או לשמר מזהי צמתים ריקים). +- **תחביר שאילתא**: מהו התחביר הקונקרטי לציין משולשות מצוטטות + בשאלות? יש להגדיר את ממשק ה-API של השאילתא. +- ~~**אוצר מילים של תכונות**~~: נפתר. כל תכונות RDF חוקיות מותרות, + כולל מילים מוגדרות על ידי משתמש. הנחות מינימליות לגבי תוקף RDF. + אסטרטגיה: הימנע מנעילה אלא אם הכרחי לחלוטין. +- ~~**השפעה על מאגר הווקטורים**~~: נפתר. מאגרי וקטורים תמיד מצביעים על + IRIs בלבד - לעולם לא קצוות, מילויים או צמתים ריקים. משולשות מצוטטות + וגרפים בעלי שם אינם משפיעים על מאגר הווקטורים. +- ~~**סמנטיקת גרפים בעלי שם**~~: נפתר. שאילתות כברירת מחדל לגרף + כברירת מחדל (מתאים להתנהגות SPARQL, תואם לאחור). פרמטר גרף ספציפי + נדרש לשאילתא על גרפים בעלי שם או כל הגרפים. + +## הפניות + +- [מושגים של RDF 1.2](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-star ו-SPARQL-star](https://w3c.github.io/rdf-star/) +- [סט נתונים RDF](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.hi.md b/docs/tech-specs/graph-contexts.hi.md new file mode 100644 index 00000000..9a13893c --- /dev/null +++ b/docs/tech-specs/graph-contexts.hi.md @@ -0,0 +1,376 @@ +--- +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. + +## अवलोकन + +यह विनिर्देश ट्रस्टग्राफ के मुख्य ग्राफ प्रिमिटिव में किए गए परिवर्तनों का वर्णन करता है ताकि +यह RDF 1.2 के अनुरूप हो और RDF डेटासेट के पूर्ण अर्थों का समर्थन कर सके। यह 2.x रिलीज़ श्रृंखला के लिए एक महत्वपूर्ण बदलाव है। + +### संस्करण + +- **2.0**: प्रारंभिक अपनाने वाला रिलीज़। मुख्य विशेषताएं उपलब्ध हैं, लेकिन यह पूरी तरह से + उत्पादन के लिए तैयार नहीं हो सकता है। +- **2.1 / 2.2**: उत्पादन रिलीज़। स्थिरता और पूर्णता की पुष्टि की गई है। + +परिपक्वता में लचीलापन जानबूझकर रखा गया है - प्रारंभिक अपनाने वाले नई +क्षमताओं तक पहुंच सकते हैं, भले ही सभी विशेषताएं उत्पादन के लिए पूरी तरह से तैयार न हों। + +## लक्ष्य + +इस कार्य के प्राथमिक लक्ष्य तथ्यों/कथनों के बारे में मेटाडेटा को सक्षम करना हैं: + +- **टेम्पोरल जानकारी**: तथ्यों को समय मेटाडेटा से जोड़ना + - जब किसी तथ्य को सत्य माना गया था + - जब कोई तथ्य सत्य हो गया + - जब किसी तथ्य को गलत साबित किया गया + +- **उत्पत्ति/स्रोत**: यह ट्रैक करना कि कौन से स्रोत किसी तथ्य का समर्थन करते हैं + - "यह तथ्य स्रोत X द्वारा समर्थित था" + - तथ्यों को उनके मूल दस्तावेजों से जोड़ना + +- **सत्यता/विश्वसनीयता**: सत्य के बारे में दावे रिकॉर्ड करना + - "व्यक्ति P ने कहा कि यह सत्य था" + - "व्यक्ति Q का दावा है कि यह गलत है" + - विश्वास स्कोरिंग और संघर्ष का पता लगाने को सक्षम करना + +**परिकल्पना**: पुन:पुनर्बलन (RDF-स्टार / उद्धृत ट्रिपल) वह प्रमुख तंत्र है +इन परिणामों को प्राप्त करने के लिए, क्योंकि सभी को कथनों के बारे में कथन करने की आवश्यकता होती है। + +## पृष्ठभूमि + +"यह तथ्य (एलिस बॉब को जानती है) 15 जनवरी, 2024 को खोजा गया था" या +"स्रोत X दावे (Y कारण Z है) का समर्थन करता है" को व्यक्त करने के लिए, आपको एक किनारे +का संदर्भ देना होगा जिसे आप कथनों के बारे में बात कर सकते हैं। मानक ट्रिपल इसका समर्थन नहीं करते हैं। + +### वर्तमान सीमाएं + +`trustgraph-base/trustgraph/schema/core/primitives.py` में वर्तमान `Value` वर्ग: +- URI नोड (`is_uri=True`) +- शाब्दिक मान (`is_uri=False`) + +`type` फ़ील्ड मौजूद है, लेकिन इसका उपयोग XSD डेटा प्रकारों को दर्शाने के लिए नहीं किया जाता है। + +## तकनीकी डिज़ाइन + +### समर्थित RDF विशेषताएं + +#### मुख्य विशेषताएं (पुन:पुनर्बलन लक्ष्यों से संबंधित) + +ये विशेषताएं अस्थायी, उत्पत्ति और सत्यता लक्ष्यों से सीधे संबंधित हैं: + +1. **RDF 1.2 उद्धृत ट्रिपल (RDF-स्टार)** + - किनारे जो अन्य किनारों की ओर इशारा करते हैं + - एक ट्रिपल एक ट्रिपल के विषय या वस्तु दोनों के रूप में दिखाई दे सकता है + - कथनों के बारे में कथन सक्षम करें (पुन:पुनर्बलन) + - व्यक्तिगत तथ्यों को एनोटेट करने का मुख्य तंत्र + +2. **RDF डेटासेट / नामित ग्राफ** + - एक डेटासेट के भीतर कई नामित ग्राफ का समर्थन + - प्रत्येक ग्राफ को एक IRI द्वारा पहचाना जाता है + - ट्रिपल (s, p, o) से क्वाड (s, p, o, g) में बदलाव + - एक डिफ़ॉल्ट ग्राफ प्लस शून्य या अधिक नामित ग्राफ शामिल हैं + - ग्राफ IRI कथनों में एक विषय हो सकता है, उदाहरण के लिए: + ``` + "2024-01-15" + "उच्च" + ``` + - ध्यान दें: नामित ग्राफ पुन:पुनर्बलन से अलग विशेषता है। उनके + कथन एनोटेशन (विभाजन, एक्सेस नियंत्रण, डेटासेट संगठन) से परे उपयोग हैं + और इसे एक अलग क्षमता के रूप में माना जाना चाहिए। + +3. **रिक्त नोड** (सीमित समर्थन) + - वैश्विक URI के बिना अनाम नोड + - बाहरी RDF डेटा लोड करते समय संगतता के लिए समर्थित + - **सीमित स्थिति**: लोडिंग के बाद स्थिर पहचान की कोई गारंटी नहीं + - वाइल्डकार्ड प्रश्नों के माध्यम से उनका पता लगाएं (कनेक्शन से मिलान करें, आईडी से नहीं) + - यह पहली श्रेणी की विशेषता नहीं है - सटीक रिक्त नोड हैंडलिंग पर भरोसा न करें। + +#### अवसरवादी सुधार (2.0 ब्रेकिंग परिवर्तन) + +ये विशेषताएं पुन:पुनर्बलन लक्ष्यों से सीधे संबंधित नहीं हैं, लेकिन +महत्वपूर्ण सुधार हैं जिन्हें ब्रेकिंग परिवर्तनों के दौरान शामिल किया जाना चाहिए: + +4. **शाब्दिक डेटा प्रकार** + - XSD डेटा प्रकारों के लिए `type` फ़ील्ड का ठीक से उपयोग करें + - उदाहरण: xsd:string, xsd:integer, xsd:dateTime, आदि। + - वर्तमान सीमा को ठीक करता है: तिथियों या पूर्णांकों को ठीक से दर्शाया नहीं जा सकता है। + +5. **भाषा टैग** + - स्ट्रिंग शाब्दिक पर भाषा विशेषताओं का समर्थन + - ध्यान दें: एक शाब्दिक में या तो एक भाषा टैग होता है या एक डेटा प्रकार, दोनों नहीं + (rdf:langString को छोड़कर) + - AI/बहुभाषी उपयोग के मामलों के लिए महत्वपूर्ण। + +### डेटा मॉडल + +#### टर्म (नाम बदलकर वैल्यू) + +`Value` वर्ग को बेहतर ढंग से RDF शब्दावली को दर्शाने के लिए `Term` में बदल दिया जाएगा। +इस नामकरण का दो उद्देश्य हैं: +1. यह नामकरण RDF अवधारणाओं के साथ संरेखित होता है (एक "टर्म" एक IRI, शाब्दिक, + रिक्त नोड या उद्धृत ट्रिपल हो सकता है - केवल एक "मान" नहीं)। +2. यह ब्रेकिंग परिवर्तन इंटरफ़ेस पर कोड समीक्षा को मजबूर करता है - कोई भी कोड जो अभी भी + `Value` को संदर्भित करता है, वह स्पष्ट रूप से टूटा हुआ है और इसे अपडेट करने की आवश्यकता है। + +एक टर्म का प्रतिनिधित्व किया जा सकता है: + +- **IRI/URI**: एक नामित नोड/संसाधन +- **रिक्त नोड**: स्थानीय दायरे वाला एक अनाम नोड +- **शाब्दिक**: एक डेटा मान जिसमें या तो: + - एक डेटा प्रकार (XSD प्रकार), या + - एक भाषा टैग +- **उद्धृत ट्रिपल**: एक ट्रिपल का उपयोग एक टर्म के रूप में किया जाता है (RDF 1.2) + +##### चुनी गई दृष्टिकोण: एकल वर्ग जिसमें प्रकार विभेदक है + +सीरियलाइज़ेशन आवश्यकताएं संरचना को चलाती हैं - वायर प्रारूप में एक प्रकार विभेदक की आवश्यकता होती है +चाहे पायथन प्रतिनिधित्व कुछ भी हो। एक एकल वर्ग जिसमें एक प्रकार फ़ील्ड प्राकृतिक है +और वर्तमान `Value` पैटर्न के साथ संरेखित है। + +एकल-अक्षर प्रकार कोड कॉम्पैक्ट सीरियलाइज़ेशन प्रदान करते हैं: + +```python +from dataclasses import dataclass + +# टर्म प्रकार स्थिरांक +IRI = "i" # IRI/URI नोड +BLANK = "b" # रिक्त नोड +LITERAL = "l" # शाब्दिक मान +TRIPLE = "t" # उद्धृत ट्रिपल (RDF-स्टार) + +@dataclass +class Term: + type: str = "" # इनमें से एक: IRI, BLANK, LITERAL, TRIPLE + + # IRI टर्म के लिए (type == IRI) + iri: str = "" + + # रिक्त नोड के लिए (type == BLANK) + id: str = "" + + # शाब्दिक के लिए (type == LITERAL) + value: str = "" + datatype: str = "" # XSD डेटा प्रकार URI (भाषा के साथ परस्पर अनन्य) + language: str = "" # भाषा टैग (डेटा प्रकार के साथ परस्पर अनन्य) + + # उद्धृत ट्रिपल के लिए (type == TRIPLE) + triple: "Triple | None" = None +``` + +उपयोग के उदाहरण: + +```python +# IRI टर्म +node = Term(type=IRI, iri="http://example.org/Alice") + +# डेटा प्रकार के साथ शाब्दिक +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# भाषा टैग के साथ शाब्दिक +label = Term(type=LITERAL, value="नमस्ते", language="en") + +# रिक्त नोड +anon = Term(type=BLANK, id="_:b1") + +# उद्धृत ट्रिपल (कथन के बारे में कथन) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### विचार किए गए विकल्प + +**विकल्प B: विशिष्ट वर्गों का संघ** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- अस्वीकृत: सीरियलाइज़ेशन को अभी भी एक प्रकार विभेदक की आवश्यकता होगी, जो जटिलता जोड़ता है। + +**विकल्प C: बेस क्लास जिसमें सबक्लासेस हैं** +- अस्वीकृत: समान सीरियलाइज़ेशन समस्या, साथ ही डेटा क्लास इनहेरिटेंस की जटिलताएं। + +#### ट्रिपल / क्वाड + +`Triple` वर्ग में एक वैकल्पिक ग्राफ फ़ील्ड है ताकि यह क्वाड बन जाए: + +```python +@dataclass +class Triple: + s: Term | None = None # विषय + p: Term | None = None # विधेय + o: Term | None = None # वस्तु + g: str | None = None # ग्राफ नाम (IRI), None = डिफ़ॉल्ट ग्राफ +``` + +डिज़ाइन निर्णय: +- **फ़ील्ड नाम**: स्थिरता के लिए `g` को `s`, `p`, `o` के साथ +- **वैकल्पिक**: `None` का मतलब डिफ़ॉल्ट ग्राफ (अनटैग) +- **प्रकार**: पूर्ण `Term` तंत्र की आवश्यकता नहीं होने के कारण, केवल एक स्ट्रिंग (IRI) + - ग्राफ नाम हमेशा IRI होते हैं + - ग्राफ नाम के रूप में रिक्त नोड को खारिज कर दिया गया (बहुत भ्रमित करने वाला) + +ध्यान दें: `Triple` वर्ग का नाम `Quad` होने पर भी `Triple` रहता है। +यह अपव्यय से बचाता है और "ट्रिपल" अभी भी सामान्य शब्दावली है। ग्राफ संदर्भ +यह दर्शाता है कि ट्रिपल कहाँ स्थित है। + +### उम्मीदवार क्वेरी पैटर्न + +वर्तमान क्वेरी इंजन S, P, O टर्म के संयोजनों को स्वीकार करता है। उद्धृत +ट्रिपल के साथ, एक ट्रिपल स्वयं उन स्थितियों में एक मान्य टर्म बन जाता है। नीचे +उम्मीदवार क्वेरी पैटर्न दिए गए हैं जो मूल लक्ष्यों का समर्थन करते हैं। + +#### ग्राफ पैरामीटर अर्थशास्त्र + +पिछड़ी संगतता के लिए SPARQL सम्मेलनों का पालन करना: + +- **`g` छोड़ा गया / None**: केवल डिफ़ॉल्ट ग्राफ क्वेरी करें +- **`g` = विशिष्ट IRI**: केवल उस नामित ग्राफ को क्वेरी करें +- **`g` = वाइल्डकार्ड / `*`**: सभी ग्राफों में क्वेरी करें (SPARQL के बराबर + `GRAPH ?g { ... }`) + +यह सरल क्वेरी को सरल रखता है और नामित ग्राफ क्वेरी को वैकल्पिक बनाता है। + +क्रॉस-ग्राफ क्वेरी (g=वाइल्डकार्ड) पूरी तरह से समर्थित हैं। Cassandra स्कीमा +समर्पित तालिकाओं को शामिल करता है (SPOG, POSG, OSPG) जहां g एक क्लस्टरिंग कॉलम है +विभिन्न ग्राफों में कुशल क्वेरी सक्षम करने के लिए पार्टीशन कुंजी नहीं है। + +#### टेम्पोरल क्वेरी + +**एक निश्चित तिथि के बाद खोजे गए सभी तथ्यों का पता लगाएं:** +``` +S: ? # कोई भी उद्धृत ट्रिपल +P: +O: > "2024-01-15"^^xsd:date # तिथि तुलना +``` + +**पता लगाएं कि किसी विशिष्ट तथ्य को कब सत्य माना गया था:** +``` +S: << <एलिस> <जानता है> <बॉब> >> # विषय के रूप में उद्धृत ट्रिपल +P: +O: ? # तिथि लौटाता है +``` + +**उन तथ्यों का पता लगाएं जिन्हें गलत माना गया था:** +``` +S: ? # कोई भी उद्धृत ट्रिपल +P: +O: ? # कोई भी मान (अस्तित्व) +``` + +#### उत्पत्ति क्वेरी + +**किसी विशिष्ट स्रोत द्वारा समर्थित सभी तथ्यों का पता लगाएं:** +``` +S: ? # कोई भी उद्धृत ट्रिपल +P: +O: +``` + +**पता करें कि कौन से स्रोत किसी विशिष्ट तथ्य का समर्थन करते हैं:** +``` +S: << <ड्रगए> <उपचार करता है> <बीमारीबी> >> # विषय के रूप में उद्धृत ट्रिपल +P: +O: ? # स्रोत IRI लौटाता है +``` + +#### सत्यता क्वेरी + +**उन दावों का पता लगाएं जिन्हें किसी व्यक्ति ने सत्य के रूप में चिह्नित किया था:** +``` +S: ? # कोई भी उद्धृत ट्रिपल +P: +O: +``` + +**विरोधाभासी दावों का पता लगाएं (एक ही तथ्य, अलग-अलग सत्यता):** +``` +# पहली क्वेरी: सत्य माने गए तथ्य +S: ? +P: +O: ? + +# दूसरी क्वेरी: झूठे माने गए तथ्य +S: ? +P: +O: ? + +# एप्लिकेशन तर्क: विषयों के चौराहे का पता लगाएं +``` + +**उस विश्वास स्कोर का पता लगाएं जो थ्रेसहोल्ड से नीचे है:** +``` +S: ? # कोई भी उद्धृत ट्रिपल +P: +O: < 0.5 # संख्यात्मक तुलना +``` + +### आर्किटेक्चर + +कई घटकों में महत्वपूर्ण परिवर्तन आवश्यक हैं: + +#### यह भंडार (trustgraph) + +- **स्कीमा प्रिमिटिव** (`trustgraph-base/trustgraph/schema/core/primitives.py`) + - वैल्यू → टर्म का नाम बदलें + - नए टर्म संरचना में प्रकार विभेदक + - ग्राफ संदर्भ के लिए ट्रिपल में `g` +- **नाम बदलें**: `Value` क्लास का नाम बदलकर `Term` कर दिया जाएगा। यह + ~78 फ़ाइलों को कोडबेस में प्रभावित करता है। नामकरण एक मजबूर करने वाला कारक के रूप में कार्य करता है: + `Value` का उपयोग करने वाला कोई भी कोड तुरंत पहचानने योग्य है और इसे 2.0 + संगतता के लिए समीक्षा/अपडेट करने की आवश्यकता है। + +सुरक्षा विचार +नामित ग्राफ एक सुरक्षा सुविधा नहीं हैं। उपयोगकर्ता और संग्रह सुरक्षा सीमाएँ हैं। +नामित ग्राफ डेटा संगठन और पुन:पुनर्बलन समर्थन के लिए पूरी तरह से हैं। + +प्रदर्शन विचार +- उद्धृत ट्रिपल नेस्टिंग गहराई जोड़ते हैं - यह क्वेरी प्रदर्शन को प्रभावित कर सकता है +- कुशल ग्राफ-स्कोप वाली क्वेरी के लिए नामित ग्राफ इंडेक्सिंग रणनीतियाँ आवश्यक हैं +- क्वाड स्टोरेज को कुशलतापूर्वक समायोजित करने के लिए Cassandra स्कीमा डिज़ाइन + आवश्यक होगा। + +वेक्टर स्टोर सीमा +वेक्टर स्टोर हमेशा केवल IRIs को संदर्भित करते हैं: +- कभी भी किनारे (उद्धृत ट्रिपल) +- कभी भी शाब्दिक मान +- कभी भी रिक्त नोड +यह वेक्टर स्टोर को सरल रखता है - यह नामित संस्थाओं की सिमेंटिक समानता को संभालता है। +ग्राफ संरचना, पुन:पुनर्बलन और मेटाडेटा संबंध को संभालता है। उद्धृत ट्रिपल और +नामित ग्राफ वेक्टर संचालन को जटिल नहीं बनाते हैं। + +परीक्षण रणनीति +मौजूदा परीक्षण रणनीति का उपयोग करें। चूंकि यह एक ब्रेकिंग रिलीज़ है, इसलिए नए +संरचनाओं का परीक्षण करने के लिए एंड-टू-एंड परीक्षण सूट पर ध्यान केंद्रित करें ताकि यह सत्यापित किया जा सके कि +वे सभी घटकों में सही ढंग से काम करते हैं। + +प्रवासन योजना +- 2.0 एक ब्रेकिंग रिलीज़ है; कोई पिछड़ा संगतता की आवश्यकता नहीं है +- मौजूदा डेटा को नए स्कीमा में माइग्रेट करने की आवश्यकता हो सकती है (अंतिम डिज़ाइन के आधार पर TBD) +- मौजूदा ट्रिपल को बदलने के लिए माइग्रेशन टूल पर विचार करें + +खुले प्रश्न +- **रिक्त नोड**: सीमित समर्थन की पुष्टि की गई है। एक स्कोलेम रणनीति पर निर्णय लेने + हो सकता है (लोडिंग पर IRI उत्पन्न करें, या रिक्त नोड ID को संरक्षित करें)। +- **क्वेरी सिंटैक्स**: उद्धृत ट्रिपल को क्वेरी में निर्दिष्ट करने के लिए ठोस सिंटैक्स क्या है? + क्वेरी API को परिभाषित करने की आवश्यकता है। +- ~~**विधेय शब्दावली**~~: हल किया गया। किसी भी वैध RDF विधेय की अनुमति है, + जिसमें कस्टम उपयोगकर्ता-परिभाषित भी शामिल हैं। RDF वैधता के बारे में बहुत कम धारणाएं। + रणनीति: जब तक बिल्कुल आवश्यक न हो, कुछ भी लॉक न करें। +- ~~**वेक्टर स्टोर प्रभाव**~~: हल किया गया। वेक्टर स्टोर हमेशा केवल IRIs को संदर्भित करते हैं + - कभी भी किनारे, शाब्दिक, या रिक्त नोड। उद्धृत ट्रिपल और + पुन:पुनर्बलन वेक्टर स्टोर को प्रभावित नहीं करते हैं। +- ~~**नामित ग्राफ अर्थशास्त्र**~~: हल किया गया। क्वेरी डिफ़ॉल्ट में डिफ़ॉल्ट ग्राफ + (पिछड़ी संगत SPARQL व्यवहार)। नामित ग्राफ या सभी ग्राफों को क्वेरी करने के लिए + एक स्पष्ट ग्राफ पैरामीटर की आवश्यकता होती है। + +संदर्भ +- [RDF 1.2 अवधारणाएँ](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-स्टार और SPARQL-स्टार](https://w3c.github.io/rdf-star/) +- [RDF डेटासेट](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.md b/docs/tech-specs/graph-contexts.md index 54737012..cbb9ada6 100644 --- a/docs/tech-specs/graph-contexts.md +++ b/docs/tech-specs/graph-contexts.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Graph Contexts Technical Specification" +parent: "Tech Specs" +--- + # Graph Contexts Technical Specification ## Overview diff --git a/docs/tech-specs/graph-contexts.pt.md b/docs/tech-specs/graph-contexts.pt.md new file mode 100644 index 00000000..9bbd9c79 --- /dev/null +++ b/docs/tech-specs/graph-contexts.pt.md @@ -0,0 +1,678 @@ +--- +layout: default +title: "Especificação Técnica dos Contextos de Grafos" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica dos Contextos de Grafos + +> **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 alterações nos primitivos de grafo principais do TrustGraph para +estar em conformidade com o RDF 1.2 e suportar a semântica completa do Conjunto de Dados RDF. Esta é uma +alteração que causa incompatibilidade para a série de lançamento 2.x. + +### Versionamento + +**2.0**: Lançamento para usuários iniciais. Recursos principais disponíveis, mas pode não estar totalmente + pronto para produção. +**2.1 / 2.2**: Lançamento para produção. Estabilidade e completude validadas. + +A flexibilidade em relação à maturidade é intencional - os usuários iniciais podem acessar novos +recursos antes que todos os recursos sejam aprimorados para produção. + +## Objetivos + +Os principais objetivos deste trabalho são permitir metadados sobre fatos/declarações: + +**Informações temporais**: Associar fatos a metadados de tempo + Quando um fato foi considerado verdadeiro + Quando um fato se tornou verdadeiro + Quando um fato foi descoberto como falso + +**Proveniência/Fontes**: Rastrear quais fontes suportam um fato + "Este fato foi suportado pela fonte X" +<<<<<<< HEAD + Vincular fatos aos documentos de origem +======= + Vincular fatos aos seus documentos de origem +>>>>>>> 82edf2d (New md files from RunPod) + +**Veracidade/Confiança**: Registrar afirmações sobre a verdade + "A pessoa P afirmou que isso era verdade" + "A pessoa Q afirma que isso é falso" + Permitir pontuação de confiança e detecção de conflitos + +**Hipótese**: A reificação (triplas RDF-star / citadas) é o mecanismo chave +para alcançar esses resultados, pois todos exigem fazer declarações sobre declarações. + +## Contexto + +Para expressar "o fato (Alice conhece Bob) foi descoberto em 2024-01-15" ou +"a fonte X suporta a afirmação (Y causa Z)", você precisa referenciar uma aresta +como algo sobre o qual você pode fazer declarações. Triplas padrão não suportam isso. + +### Limitações Atuais + +<<<<<<< HEAD +A classe `Value` atual em `trustgraph-base/trustgraph/schema/core/primitives.py` +======= +A classe `Value` em `trustgraph-base/trustgraph/schema/core/primitives.py` +>>>>>>> 82edf2d (New md files from RunPod) +pode representar: +Nós URI (`is_uri=True`) +Valores literais (`is_uri=False`) + +O campo `type` existe, mas não é usado para representar tipos de dados XSD. + +## Design Técnico + +### Recursos RDF a serem Suportados + +#### Recursos Principais (Relacionados aos Objetivos de Reificação) + +Esses recursos estão diretamente relacionados aos objetivos de tempo, proveniência e veracidade: + +1. **Triplas Citadas RDF 1.2 (RDF-star)** +Arestas que apontam para outras arestas +<<<<<<< HEAD + Uma Tripla pode aparecer como o sujeito ou objeto de outra Tripla +======= + Uma Tripla pode aparecer como o sujeito ou o objeto de outra Tripla +>>>>>>> 82edf2d (New md files from RunPod) + Permite declarações sobre declarações (reificação) + Mecanismo principal para anotar fatos individuais + +2. **Conjunto de Dados RDF / Grafos Nomeados** +Suporte para vários grafos nomeados dentro de um conjunto de dados + Cada grafo identificado por um IRI + Passa de triplas (s, p, o) para quads (s, p, o, g) + Inclui um grafo padrão, mais zero ou mais grafos nomeados + O IRI do grafo pode ser um sujeito em declarações, por exemplo: + O IRI do grafo pode ser o sujeito em declarações, por exemplo: + ``` + "2024-01-15" + "high" + ``` + Nota: Os grafos nomeados são uma funcionalidade separada da reificação. Eles têm + usos além da anotação de declarações (particionamento, controle de acesso, organização de conjuntos de dados) + e devem ser tratados como uma capacidade distinta. + +3. **Nós Anônimos** (Suporte Limitado) + Nós anônimos sem um URI global + Suportados para compatibilidade ao carregar dados RDF externos + **Status limitado**: Sem garantias sobre a identidade estável após o carregamento + Encontre-os por meio de consultas curinga (correspondência por conexões, não por ID) + Não é uma funcionalidade de primeira classe - não dependa de um tratamento preciso de nós anônimos + +#### Correções Oportunas (Mudança Incompatível 2.0) + +Esses recursos não estão diretamente relacionados aos objetivos da reificação, mas são +melhorias valiosas a serem incluídas ao mesmo tempo em que são feitas alterações incompatíveis: + +4. **Tipos de Dados Literais** + Use corretamente o campo `type` para tipos de dados XSD + Exemplos: xsd:string, xsd:integer, xsd:dateTime, etc. + Corrige a limitação atual: não é possível representar datas ou inteiros corretamente + +5. **Tags de Idioma** + Suporte para atributos de idioma em literais de string (@en, @fr, etc.) + Nota: Um literal tem uma tag de idioma OU um tipo de dados, não ambos + (exceto para rdf:langString) + Importante para casos de uso de IA/multilíngues + +### Modelos de Dados + +#### Termo (renomeado de Valor) + +A classe `Value` será renomeada para `Term` para melhor refletir a terminologia RDF. +Esta renomeação tem dois propósitos: +1. Alinha a nomenclatura com os conceitos RDF (um "Termo" pode ser um IRI, literal ou nó anônimo. + nó, ou tripla entre aspas - não apenas um "valor"). +2. Exige revisão de código na interface de alteração significativa - qualquer código que ainda + faça referência a `Value` estará visivelmente quebrado e precisará ser atualizado. + +Um Termo pode representar: + +**IRI/URI** - Um nó/recurso nomeado. +**Nó Anônimo** - Um nó anônimo com escopo local. +**Literal** - Um valor de dados com um dos seguintes: + Um tipo de dados (tipo XSD), OU + Uma etiqueta de idioma. +**Tripla Citada** - Uma tripla usada como um termo (RDF 1.2). + +##### Abordagem Escolhida: Classe Única com Discriminador de Tipo + +Os requisitos de serialização determinam a estrutura - um discriminador de tipo é necessário +<<<<<<< HEAD +no formato de transmissão, independentemente da representação em Python. Uma classe única com +======= +no formato de transmissão, independentemente da representação em Python. Uma única classe com +>>>>>>> 82edf2d (New md files from RunPod) +um campo de tipo é a opção mais adequada e está alinhada com o padrão atual `Value`. + +Códigos de tipo de caractere único fornecem serialização compacta: + +```python +from dataclasses import dataclass + +# Term type constants +IRI = "i" # IRI/URI node +BLANK = "b" # Blank node +LITERAL = "l" # Literal value +TRIPLE = "t" # Quoted triple (RDF-star) + +@dataclass +class Term: + type: str = "" # One of: IRI, BLANK, LITERAL, TRIPLE + + # For IRI terms (type == IRI) + iri: str = "" + + # For blank nodes (type == BLANK) + id: str = "" + + # For literals (type == LITERAL) + value: str = "" + datatype: str = "" # XSD datatype URI (mutually exclusive with language) + language: str = "" # Language tag (mutually exclusive with datatype) + + # For quoted triples (type == TRIPLE) + triple: "Triple | None" = None +``` + +Exemplos de uso: + +```python +# IRI term +node = Term(type=IRI, iri="http://example.org/Alice") + +# Literal with datatype +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# Literal with language tag +label = Term(type=LITERAL, value="Hello", language="en") + +# Blank node +anon = Term(type=BLANK, id="_:b1") + +# Quoted triple (statement about a statement) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### Alternativas Consideradas + +**Opção B: União de classes especializadas** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +Rejeitada: A serialização ainda precisaria de um discriminador de tipo, adicionando complexidade. + +**Opção C: Classe base com subclasses** +Rejeitada: Mesmo problema de serialização, além de peculiaridades da herança de dataclasses. + +#### Tripla / Quádrupla + +A classe `Triple` ganha um campo de grafo opcional para se tornar uma quádrupla: + +```python +@dataclass +class Triple: + s: Term | None = None # Subject + p: Term | None = None # Predicate + o: Term | None = None # Object + g: str | None = None # Graph name (IRI), None = default graph +``` + +Decisões de design: +**Nome do campo**: `g` para consistência com `s`, `p`, `o` +**Opcional**: `None` significa o grafo padrão (sem nome) +**Tipo**: String simples (IRI) em vez de Termo + Os nomes dos grafos são sempre IRIs + Nodos vazios como nomes de grafos são descartados (muito confusos) + Não há necessidade da totalidade do mecanismo de Termos + +Nota: O nome da classe permanece `Triple` mesmo que tecnicamente seja um quad agora. +Isso evita mudanças e "tripla" ainda é a terminologia comum para a parte s/p/o. +O contexto do grafo é metadado sobre onde a tripla reside. + +### Padrões de Consulta Candidatos + +<<<<<<< HEAD +O mecanismo de consulta atual aceita combinações de termos S, P, O. Com triplas +entre aspas, uma tripla em si se torna um termo válido nessas posições. Abaixo estão +padrões de consulta candidatos que suportam os objetivos originais. +======= +O mecanismo de consulta atual aceita combinações de termos S, P, O. Com triplas entre aspas, +uma tripla se torna um termo válido nessas posições. Abaixo estão os padrões de consulta +candidatos que suportam os objetivos originais. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Semântica do Parâmetro do Grafo + +Seguindo as convenções do SPARQL para compatibilidade com versões anteriores: + +**`g` omitido / Nenhum**: Consulta apenas o grafo padrão +**`g` = IRI específico**: Consulta apenas aquele grafo nomeado +**`g` = curinga / `*`**: Consulta em todos os grafos (equivalente ao SPARQL + `GRAPH ?g { ... }`) + +Isso mantém as consultas simples simples e torna as consultas de grafos nomeados opcionais. + +Consultas entre grafos (g=curinga) são totalmente suportadas. O esquema do Cassandra +inclui tabelas dedicadas (SPOG, POSG, OSPG) onde g é uma coluna de agrupamento +em vez de uma chave de partição, permitindo consultas eficientes em todos os grafos. + +#### Consultas Temporais + +**Encontre todos os fatos descobertos após uma determinada data:** +``` +S: ? # any quoted triple +P: +O: > "2024-01-15"^^xsd:date # date comparison +``` + +**Descubra quando um fato específico foi considerado verdadeiro:** +``` +S: << >> # quoted triple as subject +P: +O: ? # returns the date +``` + +**Encontre fatos que se tornaram falsos:** +``` +S: ? # any quoted triple +P: +O: ? # has any value (exists) +``` + +#### Consultas de Proveniência + +**Encontre todos os fatos suportados por uma fonte específica:** +``` +S: ? # any quoted triple +P: +O: +``` + +**Descubra quais fontes sustentam um fato específico:** +``` +S: << >> # quoted triple as subject +P: +O: ? # returns source IRIs +``` + +#### Consultas de Veracidade + +**Encontre as afirmações que uma pessoa marcou como verdadeiras:** +``` +S: ? # any quoted triple +P: +O: +``` + +**Encontre asserções conflitantes (mesmo fato, diferentes níveis de veracidade):** +``` +# First query: facts asserted true +S: ? +P: +O: ? + +# Second query: facts asserted false +S: ? +P: +O: ? + +# Application logic: find intersection of subjects +``` + +**Encontre fatos com uma pontuação de confiança abaixo do limite:** +``` +S: ? # any quoted triple +P: +O: < 0.5 # numeric comparison +``` + +### Arquitetura + +Mudanças significativas necessárias em vários componentes: + +#### Este Repositório (trustgraph) + +**Primitivos de esquema** (`trustgraph-base/trustgraph/schema/core/primitives.py`) + Renomeação de Value → Term + Nova estrutura de Term com discriminador de tipo + Triple ganha campo `g` para contexto do grafo + +**Tradutores de mensagens** (`trustgraph-base/trustgraph/messaging/translators/`) + Atualização para novas estruturas de Term/Triple + Serialização/desserialização para novos campos + +**Componentes de gateway** + Lidar com novas estruturas de Term e quad + +**Núcleos de conhecimento** + Mudanças no núcleo para suportar quads e reificação + +**Gerenciador de conhecimento** + Mudanças de esquema se propagam aqui + +**Camadas de armazenamento** + Cassandra: Redesenho do esquema (veja Detalhes de Implementação) + Outros backends: Adiado para fases posteriores + +**Utilitários de linha de comando** + Atualização para novas estruturas de dados + +**Documentação da API REST** + Atualizações da especificação OpenAPI + +#### Repositórios Externos + +**API Python** (este repositório) + Atualizações da biblioteca cliente para novas estruturas + +**APIs TypeScript** (repositório separado) + Atualizações da biblioteca cliente + +**Workbench** (repositório separado) + Mudanças significativas no gerenciamento de estado + +### APIs + +#### API REST + +Documentado na especificação OpenAPI +Será necessário atualizar para novas estruturas de Term/Triple +Novos endpoints podem ser necessários para operações de contexto do grafo + +#### API Python (este repositório) + +Mudanças na biblioteca cliente para corresponder a novos primitivos +Mudanças significativas em Term (era Value) e Triple + +#### API TypeScript (repositório separado) + +Mudanças paralelas à API Python +Coordenação de lançamento separada + +#### Workbench (repositório separado) + +Mudanças significativas no gerenciamento de estado +Atualizações da interface do usuário para recursos de contexto do grafo + +### Detalhes de Implementação + +#### Implementação de Armazenamento em Fases + +Existem vários backends de armazenamento de grafos (Cassandra, Neo4j, etc.). A implementação +seguirá em fases: + +1. **Fase 1: Cassandra** + Começar com o armazenamento Cassandra próprio +<<<<<<< HEAD + O controle total sobre a camada de armazenamento permite iteração rápida +======= + Controle total sobre a camada de armazenamento permite iteração rápida +>>>>>>> 82edf2d (New md files from RunPod) + O esquema será redesenhado do zero para quads + reificação + Validar o modelo de dados e os padrões de consulta em relação a casos de uso reais + +#### Design de Esquema do Cassandra + +O Cassandra requer múltiplas tabelas para suportar diferentes padrões de acesso a consultas +(cada tabela consulta de forma eficiente pela sua chave de partição + colunas de agrupamento). + +##### Padrões de Consulta + +<<<<<<< HEAD +Com quads (g, s, p, o), cada posição pode ser especificada ou curinga, dando +======= +Com tuplas (g, s, p, o), cada posição pode ser especificada ou curinga, dando +>>>>>>> 82edf2d (New md files from RunPod) +16 padrões de consulta possíveis: + +| # | g | s | p | o | Descrição | +|---|---|---|---|---|-------------| +<<<<<<< HEAD +| 1 | ? | ? | ? | ? | Todos os quads | +======= +| 1 | ? | ? | ? | ? | Todas as tuplas | +>>>>>>> 82edf2d (New md files from RunPod) +| 2 | ? | ? | ? | o | Por objeto | +| 3 | ? | ? | p | ? | Por predicado | +| 4 | ? | ? | p | o | Por predicado + objeto | +| 5 | ? | s | ? | ? | Por sujeito | +| 6 | ? | s | ? | o | Por sujeito + objeto | +| 7 | ? | s | p | ? | Por sujeito + predicado | +| 8 | ? | s | p | o | Tripla completa (quais grafos?) | +| 9 | g | ? | ? | ? | Por grafo | +| 10 | g | ? | ? | o | Por grafo + objeto | +| 11 | g | ? | p | ? | Por grafo + predicado | +| 12 | g | ? | p | o | Por grafo + predicado + objeto | +| 13 | g | s | ? | ? | Por grafo + sujeito | +| 14 | g | s | ? | o | Por grafo + sujeito + objeto | +| 15 | g | s | p | ? | Por grafo + sujeito + predicado | +<<<<<<< HEAD +| 16 | g | s | p | o | Quad exato | + +##### Design de Tabela + +Restrição do Cassandra: Você só pode consultar de forma eficiente pela chave de partição e, em seguida, +filtrar nas colunas de agrupamento da esquerda para a direita. Para consultas com curinga "g", "g" deve ser +uma coluna de agrupamento. Para consultas com "g" especificado, "g" na chave de partição é mais +======= +| 16 | g | s | p | o | Tupla exata | + +##### Design da Tabela + +Restrição do Cassandra: Você só pode consultar de forma eficiente pela chave de partição e, em seguida, +filtrar nas colunas de agrupamento da esquerda para a direita. Para consultas com curinga "g", "g" deve estar +em uma coluna de agrupamento. Para consultas com "g" especificado, "g" na chave de partição é mais +>>>>>>> 82edf2d (New md files from RunPod) +eficiente. + +**Duas famílias de tabelas necessárias:** + +<<<<<<< HEAD +**Família A: consultas com curinga "g"** (g em colunas de agrupamento) +======= +**Família A: Consultas com curinga "g"** (g em colunas de agrupamento) +>>>>>>> 82edf2d (New md files from RunPod) + +| Tabela | Partição | Agrupamento | Suporta padrões | +|-------|-----------|------------|-------------------| +| SPOG | (user, collection, s) | p, o, g | 5, 7, 8 | +| POSG | (user, collection, p) | o, s, g | 3, 4 | +| OSPG | (user, collection, o) | s, p, g | 2, 6 | + +<<<<<<< HEAD +**Família B: consultas com "g" especificado** (g na chave de partição) +======= +**Família B: Consultas com "g" especificado** (g na chave de partição) +>>>>>>> 82edf2d (New md files from RunPod) + +| Tabela | Partição | Agrupamento | Suporta padrões | +|-------|-----------|------------|-------------------| +| GSPO | (user, collection, g, s) | p, o | 9, 13, 15, 16 | +| GPOS | (user, collection, g, p) | o, s | 11, 12 | +| GOSP | (user, collection, g, o) | s, p | 10, 14 | + +**Tabela de coleção** (para iteração e exclusão em massa) + +| Tabela | Partição | Agrupamento | Propósito | +|-------|-----------|------------|---------| +<<<<<<< HEAD +| COLL | (user, collection) | g, s, p, o | Enumerar todos os quads na coleção | +======= +| COLL | (user, collection) | g, s, p, o | Enumerar todas as tuplas na coleção | +>>>>>>> 82edf2d (New md files from RunPod) + +##### Caminhos de Escrita e Exclusão + +**Caminho de escrita**: Inserir em todas as 7 tabelas. + +**Caminho de exclusão da coleção**: +1. Iterar na tabela COLL para `(user, collection)` +<<<<<<< HEAD +2. Para cada quad, excluir de todas as 6 tabelas de consulta +3. Excluir da tabela COLL (ou exclusão por intervalo) + +**Caminho de exclusão de um único quad**: Excluir diretamente de todas as 7 tabelas. + +##### Custo de Armazenamento + +Cada quad é armazenado 7 vezes. Este é o custo da consulta flexível combinada +com exclusão eficiente da coleção. + +##### Triplas Citadas no Armazenamento + +O sujeito ou o objeto podem ser uma tripla em si. Opções: +======= +2. Para cada tupla, excluir de todas as 6 tabelas de consulta +3. Excluir da tabela COLL (ou exclusão por intervalo) + +**Caminho de exclusão de uma única tupla**: Excluir diretamente de todas as 7 tabelas. + +##### Custo de Armazenamento + +Cada tupla é armazenada 7 vezes. Este é o custo da consulta flexível +combinado com a exclusão eficiente da coleção. + +##### Triplas Citadas no Armazenamento + +Sujeito ou objeto podem ser uma tripla em si. Opções: +>>>>>>> 82edf2d (New md files from RunPod) + +**Opção A: Serializar triplas citadas para string canônica** +``` +S: "<>" +P: http://ex/discoveredOn +O: "2024-01-15" +G: null +``` +Armazenar a tripla citada como uma string serializada nas colunas S ou O. +Consultar por correspondência exata na forma serializada. +Prós: Simples, se encaixa em padrões de índice existentes. +Contras: Não é possível consultar "encontrar triplas onde o predicado do sujeito citado é X". + +**Opção B: IDs / Hashes de Triplas** +``` +Triple table: + id: hash(s,p,o,g) + s, p, o, g: ... + +Metadata table: + subject_triple_id: + p: http://ex/discoveredOn + o: "2024-01-15" +``` +Atribua a cada tripla um ID (hash dos componentes) +As referências de metadados de reificação referenciam as triplas por ID +Prós: Separação limpa, pode indexar os IDs das triplas +Contras: Requer o cálculo/gerenciamento da identidade da tripla, pesquisas em duas fases + +**Recomendação**: Comece com a Opção A (strings serializadas) para simplificar. +A Opção B pode ser necessária se forem necessários padrões de consulta avançados sobre triplas com aspas +componentes. + +2. **Fase 2+: Outros Backends** + Neo4j e outros armazenamentos implementados em estágios subsequentes + As lições aprendidas com o Cassandra informam essas implementações + +Esta abordagem reduz os riscos do projeto, validando em um backend totalmente controlado +antes de implementar em todos os armazenamentos. + +<<<<<<< HEAD +#### Renomear Classe de Valor → Termo +======= +#### Renomeação de Valor → Termo +>>>>>>> 82edf2d (New md files from RunPod) + +A classe `Value` será renomeada para `Term`. Isso afeta aproximadamente 78 arquivos em +todo o código-fonte. A renomeação funciona como um fator de força: qualquer código que ainda use +`Value` pode ser identificado imediatamente como precisando de revisão/atualização para compatibilidade com a versão 2.0 + + +## Considerações de Segurança + +Os grafos nomeados não são um recurso de segurança. Usuários e coleções permanecem +como os limites de segurança. Os grafos nomeados são puramente para organização de dados e +suporte de reificação. + +## Considerações de Desempenho + +Triplas com aspas adicionam profundidade de aninhamento - podem afetar o desempenho da consulta +Estratégias de indexação de grafos nomeados necessárias para consultas eficientes com escopo de grafo +O design do esquema do Cassandra precisará acomodar o armazenamento de quads de forma eficiente + +### Limite do Armazenamento Vetorial + +Os armazenamentos vetoriais sempre referenciam apenas IRIs: +Nunca arestas (triplas com aspas) +Nunca valores literais +Nunca nós vazios + +<<<<<<< HEAD +Isso mantém o armazenamento vetorial simples - ele lida com a similaridade semântica de entidades nomeadas. A estrutura do grafo lida com relacionamentos, reificação e metadados. +======= +Isso mantém o armazenamento vetorial simples - ele lida com a similaridade semântica de entidades nomeadas. +A estrutura do grafo lida com relacionamentos, reificação e metadados. +>>>>>>> 82edf2d (New md files from RunPod) +Triplas com aspas e grafos nomeados não complicam as operações vetoriais. + +## Estratégia de Teste + +Use a estratégia de teste existente. Como esta é uma alteração disruptiva, concentre-se extensivamente no +conjunto de testes de ponta a ponta para validar que as novas estruturas funcionam corretamente em +todos os componentes. + +<<<<<<< HEAD + +======= +>>>>>>> 82edf2d (New md files from RunPod) +## Plano de Migração + +A versão 2.0 é uma versão disruptiva; nenhuma compatibilidade com versões anteriores é necessária +Os dados existentes podem precisar ser migrados para um novo esquema (a ser definido com base no design final) +Considere ferramentas de migração para converter triplas existentes + +## Perguntas Abertas + +**Nós vazios**: Suporte limitado confirmado. Pode ser necessário decidir sobre +<<<<<<< HEAD + estratégia de skolemização (gerar IRIs na carga, ou preservar os IDs dos nós vazios). +======= + estratégia de skolemização (gerar IRIs na carga ou preservar os IDs dos nós vazios). +>>>>>>> 82edf2d (New md files from RunPod) +**Sintaxe de consulta**: Qual é a sintaxe concreta para especificar triplas com aspas + em consultas? É necessário definir a API de consulta. +~~**Vocabulário de predicados**~~: Resolvido. Qualquer predicado RDF válido é permitido, + incluindo vocabulários personalizados do usuário. Mínimas suposições sobre a validade do RDF. + Pouquíssimos valores fixos (por exemplo, `rdfs:label` usado em alguns lugares). +<<<<<<< HEAD + Estratégia: evite fixar qualquer coisa, a menos que seja absolutamente necessário. +~~**Impacto no armazenamento vetorial**~~: Resolvido. Os armazenamentos vetoriais sempre apontam para IRIs + apenas - nunca arestas, literais ou nós vazios. Triplas com aspas e + a reificação não afetam o armazenamento vetorial. +~~**Semântica do grafo nomeado**~~: Resolvido. As consultas padrão + para o grafo padrão (corresponde ao comportamento do SPARQL, compatível com versões anteriores). Parâmetro de grafo explícito +======= + Estratégia: evitar fixar qualquer coisa, a menos que seja absolutamente necessário. +~~**Impacto no armazenamento vetorial**~~: Resolvido. Os armazenamentos vetoriais sempre apontam para IRIs + apenas - nunca arestas, literais ou nós vazios. Triplas com aspas e + a reificação não afetam o armazenamento vetorial. +~~**Semântica do grafo nomeado**~~: Resolvido. As consultas usam o grafo padrão + (corresponde ao comportamento do SPARQL, compatível com versões anteriores). Parâmetro de grafo explícito +>>>>>>> 82edf2d (New md files from RunPod) + necessário para consultar grafos nomeados ou todos os grafos. + +## Referências + +[Conceitos RDF 1.2](https://www.w3.org/TR/rdf12-concepts/) +[RDF-star e SPARQL-star](https://w3c.github.io/rdf-star/) +[Conjunto de dados RDF](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.ru.md b/docs/tech-specs/graph-contexts.ru.md new file mode 100644 index 00000000..814ad5a3 --- /dev/null +++ b/docs/tech-specs/graph-contexts.ru.md @@ -0,0 +1,415 @@ +--- +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 для +соответствия RDF 1.2 и поддержки полной семантики набора данных RDF. Это +радикальное изменение для серии выпусков 2.x. + +### Версионирование + +- **2.0**: Ранний выпуск для тестирования. Основные функции доступны, но + возможно, еще не полностью готовы к производственному использованию. +- **2.1 / 2.2**: Промышленный выпуск. Стабильность и полнота проверены. + +Гибкость в отношении зрелости намеренна - ранние пользователи могут получить +доступ к новым возможностям, прежде чем все функции будут полностью +проверены. + +## Цели + +Основные цели этой работы - обеспечить возможность добавления метаданных к +фактам/утверждениям: + +- **Временная информация**: Связывание фактов со временными метаданными + - Когда факт считался истинным + - Когда факт стал истинным + - Когда факт был признан ложным + +- **Происхождение/Источники**: Отслеживание источников, подтверждающих факт + - "Этот факт подтверждается источником X" + - Связывание фактов с исходными документами + +- **Достоверность/Надежность**: Запись утверждений об истинности + - "Пользователь P заявил, что это было правдой" + - "Пользователь Q утверждает, что это неправда" + - Обеспечение оценки надежности и обнаружения конфликтов + +**Гипотеза**: Реификация (RDF-star / цитируемые тройки) является ключевым +механизмом для достижения этих результатов, поскольку все они требуют +создания утверждений об утверждениях. + +## Предыстория + +Чтобы выразить фразу "факт (Алиса знает Боба) был обнаружен 15 января 2024 года" +или "источник X поддерживает утверждение (Y вызывает Z)", необходимо +обращаться к ребру как к чему-то, о чем можно делать утверждения. Стандартные +тройки не поддерживают это. + +### Текущие ограничения + +Текущий класс `Value` в `trustgraph-base/trustgraph/schema/core/primitives.py` +может представлять: +- URI-узлы (`is_uri=True`) +- Литеральные значения (`is_uri=False`) + +Поле `type` существует, но не используется для представления типов данных XSD. + +## Технический дизайн + +### Функции RDF для поддержки + +#### Основные функции (связанные с целями реификации) + +Эти функции напрямую связаны с целями временной информации, происхождения и +достоверности: + +1. **Цитируемые тройки RDF 1.2 (RDF-star)** + - Ребра, указывающие на другие ребра + - Тройка может быть субъектом или объектом другой тройки + - Позволяет делать утверждения об утверждениях (реификация) + - Основной механизм для аннотирования отдельных фактов + +2. **Набор данных RDF / Именованные графы** + - Поддержка нескольких именованных графов внутри набора данных + - Каждый граф идентифицируется IRI + - Переход от троек (s, p, o) к квадам (s, p, o, g) + - Включает граф по умолчанию и ноль или более именованных графов + - IRI графа может быть субъектом в утверждениях, например: + ``` + "2024-01-15" + "high" + ``` + - Обратите внимание: Именованные графы - это отдельная функция от + реификации. Они имеют другие применения (разделение, контроль доступа, + организация набора данных) и должны рассматриваться как отдельная + возможность. + +3. **Анонимные узлы** (Ограниченная поддержка) + - Анонимные узлы без глобального URI + - Поддерживаются для совместимости при загрузке внешних данных RDF + - **Ограниченный статус**: Без гарантий стабильной идентичности после + загрузки + - Находите их с помощью запросов по подстановочным знакам (сопоставляйте по + связям, а не по ID) + - Не являются основной функцией - не полагайтесь на точную обработку + анонимных узлов + +#### Временные исправления (радикальное изменение в 2.0) + +Эти функции не связаны напрямую с целями реификации, но являются ценными +улучшениями, которые следует включить при внесении радикальных изменений: + +4. **Типы литералов** + - Правильное использование поля `type` для типов данных XSD + - Примеры: xsd:string, xsd:integer, xsd:dateTime и т.д. + - Исправляет текущее ограничение: невозможно правильно представлять даты + или целые числа + +5. **Языковые теги** + - Поддержка языковых атрибутов для строковых литералов (@en, @fr и т.д.) + - Обратите внимание: у литерала либо языковой тег, ЛИБО тип данных, но не + оба (за исключением rdf:langString) + - Важно для сценариев использования ИИ/многоязычности + +### Модели данных + +#### Термин (переименование из Value) + +Класс `Value` будет переименован в `Term`, чтобы лучше отражать терминологию +RDF. Это переименование имеет две цели: +1. Согласование наименований с концепциями RDF ( "Term" может быть IRI, + литералом, анонимным узлом или цитируемой тройкой - а не просто + "значением") +2. Вызывает проверку кода на интерфейсе радикальных изменений - любой код, + который все еще ссылается на `Value`, явно не работает и требует + обновления + +Термин может представлять: + +- **IRI/URI** - Именованный узел/ресурс +- **Анонимный узел** - Анонимный узел с локальной областью +- **Литерал** - Значение данных с одним из следующих: + - Тип данных (тип XSD) ИЛИ + - Языковой тег +- **Цитируемая тройка** - Тройка, используемая в качестве термина (RDF 1.2) + +##### Выбранный подход: Одиночный класс с дискриминатором типа + +Структура определяется требованиями сериализации - в формате передачи данных +необходим дискриминатор типа, независимо от представления на Python. +Одиночный класс с полем типа - это естественный выбор и соответствует +текущему шаблону `Value`. + +Односимвольный код типа обеспечивает компактную сериализацию: + +```python +from dataclasses import dataclass + +# Константы типа Term +IRI = "i" # IRI/URI узел +BLANK = "b" # Анонимный узел +LITERAL = "l" # Литеральное значение +TRIPLE = "t" # Цитируемая тройка (RDF 1.2) + +@dataclass +class Term: + type: str = "" # Один из: IRI, BLANK, LITERAL, TRIPLE + + # Для терминов IRI (type == IRI) + iri: str = "" + + # Для анонимных узлов (type == BLANK) + id: str = "" + + # Для литералов (type == LITERAL) + value: str = "" + datatype: str = "" # URI типа данных XSD (взаимно исключающееся с language) + language: str = "" # Языковой тег (взаимно исключающееся с datatype) + + # Для цитируемых троек (type == TRIPLE) + triple: "Triple | None" = None +``` + +Примеры использования: + +```python +# Термин IRI +node = Term(type=IRI, iri="http://example.org/Alice") + +# Литерал с типом данных +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# Литерал с языковым тегом +label = Term(type=LITERAL, value="Hello", language="en") + +# Анонимный узел +anon = Term(type=BLANK, id="_:b1") + +# Цитируемая тройка (утверждение об утверждении) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### Рассмотренные альтернативы + +**Вариант B: Объединение специализированных классов** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- Отклонено: Сериализация все равно потребует дискриминатора типа, что + увеличивает сложность + +**Вариант C: Базовый класс с подклассами** +- Отклонено: Та же проблема с сериализацией, а также особенности + наследования dataclass + +#### Тройка / Квад + +Класс `Triple` получает необязательное поле графа, чтобы стать квадом: + +```python +@dataclass +class Triple: + s: Term | None = None # Subject + p: Term | None = None # Predicate + o: Term | None = None # Object + g: str | None = None # Имя графа (IRI), None = граф по умолчанию +``` + +Решения в дизайне: +- **Имя поля**: `g` для согласованности с `s`, `p`, `o` +- **Необязательно**: `None` означает граф по умолчанию (неименованный) +- **Тип**: Обычная строка (IRI) вместо Term + - Имена графов всегда являются IRI + - Анонимные узлы в качестве имен графов не допускаются (слишком + путано) + - Нет необходимости в полной машинерии Term + +Обратите внимание: Имя класса остается `Triple`, даже если технически это +квад. Это позволяет избежать изменений и "тройка" по-прежнему является +общепринятым термином. Контекст графа является метаданными о том, где +находится тройка. + +### Шаблоны запросов + +Текущий движок запросов принимает комбинации терминов S, P, O. С цитируемыми +тройками сама тройка может быть допустимым термином в этих позициях. Ниже +приведены примеры шаблонов запросов, поддерживающих исходные цели. + +#### Семантика параметров графа + +В соответствии с соглашениями SPARQL для обратной совместимости: + +- **`g` опущено / None**: Запрос только к графу по умолчанию +- **`g` = конкретный IRI**: Запрос только к этому именованному графу +- **`g` = подстановочный знак / `*`**: Запрос по всем графам (эквивалентно + SPARQL `GRAPH ?g { ... }`) + +Это позволяет выполнять простые запросы простыми и делает запросы именованных +графов опциональными. + +Запросы между графами (g=подстановочный знак) полностью поддерживаются. +Схема Cassandra включает специализированные таблицы (SPOG, POSG, OSPG), где g +является столбцом кластеризации, а не ключом раздела, что обеспечивает +эффективные запросы по всем графам. + +#### Временные запросы + +**Найти все факты, обнаруженные после определенной даты:** +``` +S: ? # любая цитируемая тройка +P: +O: > "2024-01-15"^^xsd:date # сравнение даты +``` + +**Найти, когда определенный факт считался истинным:** +``` +S: << >> # цитируемая тройка как субъект +P: +O: ? # возвращает дату +``` + +**Найти факты, которые были признаны ложными:** +``` +S: ? # любая цитируемая тройка +P: +O: ? # имеет любое значение (существует) +``` + +#### Запросы происхождения + +**Найти все факты, подтвержденные определенным источником:** +``` +S: ? # любая цитируемая тройка +P: +O: +``` + +**Найти, какие источники подтверждают определенный факт:** +``` +S: << >> # цитируемая тройка как субъект +P: +O: ? # возвращает IRI источника +``` + +#### Запросы достоверности + +**Найти утверждения, которые пользователь отметил как истинные:** +``` +S: ? # любая цитируемая тройка +P: +O: +``` + +**Найти конфликтующие утверждения (один и тот же факт, разная достоверность):** +``` +# Первый запрос: факты, отмеченные как истинные +S: ? +P: +O: ? + +# Второй запрос: факты, отмеченные как ложные +S: ? +P: +O: ? + +# Логика приложения: найти пересечение субъектов +``` + +**Найти факты со значением надежности ниже определенного значения:** +- **Vector store impact** +``` +S: ? +P: +O: +``` + +### Граница хранилища векторов + +Хранилища векторов всегда ссылаются только на IRI: +- Никогда на ребра (цитируемые тройки) +- Никогда на литеральные значения +- Никогда на анонимные узлы + +Это упрощает хранилище векторов - оно обрабатывает семантическое сходство +именованных сущностей. Структура графа обрабатывает отношения, +реификацию и метаданные. Цитируемые тройки и именованные графы не +усложняют операции с векторами. + +## Соображения безопасности + +Именованные графы не являются функцией безопасности. Пользователи и +коллекции остаются границами безопасности. Именованные графы предназначены +исключительно для организации данных и поддержки реификации. + +## Соображения производительности + +- Цитируемые тройки добавляют глубину вложенности - могут повлиять на + производительность запросов +- Необходимы стратегии индексирования именованных графов для эффективных + запросов, охватывающих графы +- Проект схемы Cassandra должен учитывать эффективное хранение квадов. + +### Vector store boundary + +Vector stores always reference IRIs only: +- Never edges (quoted triples) +- Never literal values +- Never blank nodes + +This keeps the vector store simple - it handles semantic similarity of named +entities. The graph structure handles relationships, reification, and metadata. +Quoted triples and named graphs don't complicate vector operations. + +## Стратегия тестирования + +Используйте существующую стратегию тестирования. Поскольку это радикальное +изменение, особое внимание уделяется комплексному набору тестов для +проверки правильности работы новых структур во всех компонентах. + +## План миграции + +- 2.0 - это радикальное изменение; обратная совместимость не требуется +- Существующие данные могут потребовать миграции на новую схему (будет + определено на основе окончательного проекта) +- Рассмотрите возможность использования инструментов миграции для преобразования + существующих троек + +## Открытые вопросы + +- **Анонимные узлы**: Подтверждена ограниченная поддержка. Возможно, потребуется + определить стратегию сколемизации (генерировать IRI при загрузке или + сохранять идентификаторы анонимных узлов). +- **Синтаксис запросов**: Какой конкретный синтаксис используется для + указания цитируемых троек в запросах? Необходимо определить API запросов. +- ~~**Словарь предикатов**~~: Решено. Допускаются любые допустимые + предикаты RDF, включая пользовательские. Минимальные предположения о + валидности RDF. Очень мало жестко заданных значений (например, + `rdfs:label` используется в некоторых местах). Стратегия: избегать + фиксирования чего-либо, если это абсолютно необходимо. +- ~~**Влияние на хранилище векторов**~~: Решено. Хранилища векторов + всегда указывают только на IRI - никогда на ребра, литеральные значения или + анонимные узлы. Цитируемые тройки и реификация не влияют на хранилище + векторов. +- ~~**Семантика именованных графов**~~: Решено. Запросы по умолчанию + выполняются к графу по умолчанию (соответствует поведению SPARQL, + обратная совместимость). Требуется явный параметр графа для запросов к + именованным графам или ко всем графам. + +## Ссылки + +- [Концепции RDF 1.2](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-star и SPARQL-star](https://w3c.github.io/rdf-star/) +- [Набор данных RDF](https://www.w3.org/TR/rdf11-concepts/#section-dataset) +``` diff --git a/docs/tech-specs/graph-contexts.sw.md b/docs/tech-specs/graph-contexts.sw.md new file mode 100644 index 00000000..71266a23 --- /dev/null +++ b/docs/tech-specs/graph-contexts.sw.md @@ -0,0 +1,359 @@ +--- +layout: default +title: "Tahadhari za Kiufundi za Mazingira ya Picha (Graph Contexts)" +parent: "Swahili (Beta)" +--- + +# Tahadhari za Kiufundi za Mazingira ya Picha (Graph Contexts) + +> **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 + +Maelezo haya yanataja mabadiliko kwenye vitu vya msingi (primitives) vya TrustGraph ili +kuendana na RDF 1.2 na kusaidia maana kamili ya RDF Dataset. Hii ni +mabadiliko ambayo yanaweza kusababisha utosoni (breaking change) kwa toleo la 2.x. + +### Matoleo + +- **2.0**: Toleo la kwanza kwa watumiaji. Vitu muhimu vipo, lakini vinaweza + kusiletelewa kikamilifu kwa matumizi ya uzalishaji. +- **2.1 / 2.2**: Toleo la uzalishaji. Uthabiti na ukamilifu umehakikishwa. + +Uhusika wa uthabiti ni wa kujua - watumiaji wa kwanza wanaweza kupata +uwezo mpya kabla ya sifa zote kuwa zimekamilishwa. + +## Lengo + +Lengo kuu la kazi hii ni kuruhusu metadata kuhusu ukweli/taarifa: + +- **Habari za muda (Temporal information)**: Kuunganisha ukweli na metadata ya wakati + - Wakati ambapo ukweli ulikuwa unaaminika kuwa ni kweli + - Wakati ambapo ukweli ulipoanza kuwa kweli + - Wakati ambapo ukweli ulipoonekana kuwa bandia + +- **Chanzo/Asili (Provenance/Sources)**: Kufuatilia vyanzo ambavyo vinaunga mkono ukweli + - "Ukweli huu ulikuwa unaungwa mkono na chanzo X" + - Kuunganisha ukweli na hati zao za asili + +- **Ukweli/Amani (Veracity/Trust)**: Kurekodi maelezo kuhusu ukweli + - "Mtu P amesema kwamba hii ni kweli" + - "Mtu Q anadai kwamba hii ni bandia" + - Kuruhusu upimaji wa uaminifu na ugunduzi wa migogoro + +**Nadharia**: Ufufunzaji (reification) (RDF-star / triples zilizotiwa nukuu) ni +mfumo muhimu wa kufanikisha matokeo haya, kwani yote yanahitaji kufanya +maelezo kuhusu maelezo. + +## Msingi + +Ili kueleza "ukweli kwamba (Alice anajua Bob) uligunduliwa tarehe 2024-01-15" au +"chanzo X kinaunga mkono dai kwamba (Y husababisha Z)", unahitaji +kurejelea ukingo kama kitu ambacho unaweza kufanya maelezo. Triples +za kawaida hazisaidii hii. + +### Vikwazo vya Sasa + +Darasa la `Value` linalopo `trustgraph-base/trustgraph/schema/core/primitives.py` +linaweza kuwakilisha: +- Nodi za URI (`is_uri=True`) +- Maadili ya kawaida (`is_uri=False`) + +Nguvu ya `type` ipo lakini haitumiki kuwakilisha aina za XSD. + +## Muundo wa Kiufundi + +### Sifa za RDF za Kusaidiwa + +#### Sifa za Msingi (Zilizohusiana na Lengo la Ufufunzaji) + +Sifa hizi zinahusiana moja kwa moja na malengo ya muda, chanzo, na ukweli: + +1. **Triples Zilizotiwa Nukuu za RDF 1.2 (RDF-star)** + - Ukingo ambao unaelekea kwenye ukingo mwingine + - Triple inaweza kuonekana kama mada au kitu cha Triple nyingine + - Inaruhusu maelezo kuhusu maelezo (ufufunzaji) + - Mfumo muhimu wa kuongeza maelezo kwa ukweli binafsi + +2. **RDF Dataset / Picha Zilizojulikana (Named Graphs)** + - Usaidizi wa picha nyingi zilizojulikana ndani ya dataset + - Kila picha huainishwa na IRI + - Mabadiliko kutoka kwa triples (s, p, o) hadi quads (s, p, o, g) + - Inajumuisha picha ya chaguo-msingi pamoja na picha za majina + - IRI ya picha inaweza kuwa mada katika maelezo, kwa mfano: + ``` + "2024-01-15" + "high" + ``` + - Kumbuka: Picha zilizojulikana ni kipengele tofauti kutoka kwa ufufunzaji. + Zina matumizi mengine yakiwa nje ya kuongeza maelezo (kugawanya, udhibiti + wa ufikiaji, shirika la dataset) na zinapaswa kuchukuliwa kama + uwezo tofauti. + +3. **Nodi Tupu (Limited Support)** + - Nodi bila URI ya kimataifa + - Inasaidiwa kwa utangamano wakati wa kupakua data ya RDF ya nje + - **Hali mdogo**: Hakuna ahadi kuhusu utambulisho wa imara baada ya kupakia + - Zipate kupitia maswali ya wildcard (pangilia kwa muunganisho, sio kwa ID) + - Sio kipengele cha kwanza - usitegemee usimamizi sahihi wa nodi tupu + +#### Marekebisho ya Nafasi (2.0 Breaking Change) + +Sifa hizi hazihusiani moja kwa moja na malengo ya ufufunzaji lakini ni +mafanikio muhimu ya kuingiza wakati wa kufanya mabadiliko ambayo yanaweza +kusababisha utosoni: + +4. **Aina za Literal** + - Tumia vizuri nguvu ya `type` kwa aina za XSD + - Mifano: xsd:string, xsd:integer, xsd:dateTime, n.k. + - Huondoa kikwazo cha sasa: haiwezi kuwakilisha tarehe au nambari + kwa usahihi + +5. **Lebo za Lugha** + - Usaidizi wa sifa za lugha kwenye maadili ya kawaida (@en, @fr, n.k.) + - Kumbuka: Literal inaweza kuwa na lebo ya lugha AU aina, sio zote + (isipokuwa rdf:langString) + - Muhimu kwa matumizi ya AI/mbalimbali za lugha + +### Miundo ya Data + +#### Nguvu (kutoka Value) + +Darasa la `Value` litabadilishwa na `Term` ili kuakisi vizuri dhana za RDF. +Mabadiliko haya yafanywa kwa sababu mbili: +1. Inaakisi majina na dhana za RDF (nguvu inaweza kuwa IRI, literal, + nodi tupu, au triple iliyotiwa nukuu - sio tu "maadili") +2. Inalazimisha ukaguzi wa msimbo kwenye interface ya mabadiliko ambayo + yanaweza kusababisha utosoni - msimbo wowote unaoendelea kurejelea `Value` + unaonyeshwa kuwa umevunjika na unahitaji kusasishwa. + +Nguvu inaweza kuwakilisha: + +- **IRI/URI** - Nodi/rasilimali iliyojulikana +- **Nodi Tupu** - Nodi isiyo na jina yenye upeo wa ndani +- **Literal** - Maadili ya data ambayo ina: + - Aina ya data (aina ya XSD), AU + - Lebo ya lugha +- **Triple Iliyotiwa Nukuu** - Triple inayotumika kama nguvu (RDF 1.2) + +##### Mbinu Iliyo Chaguliwa: Darasa Moja na Kichunguzi Aina + +Mahitaji ya utayarishaji yanaendesha muundo - kichunguzi aina inahitajika +katika muundo wa waya bila kujali uwakilishi wa Python. Darasa moja na +aina ni inayofaa na inaakibiana na mtindo wa `Value` wa sasa. + +Msimbo wa aina ya herufi moja hutoa utayarishaji kompakt: + +```python +from dataclasses import dataclass + +# Mara ya aina ya Nguvu +IRI = "i" # Nodi ya IRI/URI +BLANK = "b" # Nodi tupu +LITERAL = "l" # Maadili +TRIPLE = "t" # Triple iliyotiwa nukuu (RDF 1.2) + +@dataclass +class Term: + type: str = "" # Moja ya: IRI, BLANK, LITERAL, TRIPLE + + # Kwa masharti ya IRI (aina == IRI) + iri: str = "" + + # Kwa nodi tupu (aina == BLANK) + id: str = "" + + # Kwa maadili (aina == LITERAL) + value: str = "" + datatype: str = "" # URI ya aina ya XSD (inatenganishwa) + language: str = "" # Lebo ya lugha (inatenganishwa) + + # Kwa triples zilizotiwa nukuu (aina == TRIPLE) + triple: "Triple | None" = None +``` + +Mifano ya matumizi: + +```python +# Nguvu ya IRI +node = Term(type=IRI, iri="http://example.org/Alice") + +# Maadili na aina +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# Maadili na lebo ya lugha +label = Term(type=LITERAL, value="Hello", language="en") + +# Nodi tupu +anon = Term(type=BLANK, id="_:b1") + +# Triple iliyotiwa nukuu (taarifa kuhusu taarifa) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### Mbinu Zingine Zilizozingatiwa + +**Njia B: Muungano wa madarasa maalum** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- Ilikataliwa: Utayarishaji bado unahitaji kichunguzi aina, na kuongeza + ugumu. + +**Njia C: Darasa la msingi na madarasa ya ndoto** +- Ilikataliwa: Tatizo lile lile la utayarishaji, pamoja na utata wa + urithi wa dataclass + +#### Triple / Quad + +Darasa la `Triple` hupata nguvu ya hiari kuwa quad: + +```python +@dataclass +class Triple: + s: Term | None = None # Mada + p: Term | None = None # Kieleuzo + o: Term | None = None # Kitu + g: str | None = None # Jina la picha (IRI), None = picha ya + # chaguo-msingi +``` + +Maamuzi ya muundo: +- **Jina la nguvu**: `g` kwa utangamano na `s`, `p`, `o` +- **Hiari**: `None` inamaanisha picha ya chaguo-msingi (isiyo na jina) +- **Aina**: Kamba (IRI) badala ya Nguvu + - Majina ya picha daima ni IRIs + - Nodi tupu kama majina ya picha zilikataliwa (zinaweza kusababisha + uchanganyifu) + - Hakuna haja ya utaratibu kamili wa Nguvu + +Kumbuka: Jina la darasa linaendelea kuwa `Triple` licha ya kuwa quad sasa. +Hii inazuia mabadiliko na "triple" bado ni terminolojia ya kawaida. +Mazingira ya picha ni metadata kuhusu mahali ambapo triple inakaa. + +### Mfano wa Maswali Yanayowezekana + +Msimu wa maswali unaokubaliwa hivi sasa unachanganya masharti ya S, P, O. +Katika quoted triples, triple yenyewe inakuwa nguvu halali katika +maeneo hayo. Hapa chini kuna mifano ya maswali yanayodumisha malengo +yaliyoelezwa. + +#### Semantika ya Paramu ya Picha + +Kufuata makubaliano ya SPARQL kwa utangamano wa kurudi nyuma: + +- **`g` imepunguzwa / None**: Huuliza picha ya chaguo-msingi pekee +- **`g` = IRI maalum**: Huuliza picha hiyo maalum pekee +- **`g` = wildcard / `*`**: Huuliza katika picha zote (inalingana na + SPARQL `GRAPH ?g { ... }`) + +Hii inaendelea na maswali rahisi rahisi na inafanya maswali ya picha +kuwa ya hiari. + +Maswali ya picha (g=wildcard) yanasaidiwa kikamilifu. Cassandra schema +inajumuisha jedwali maalum (SPOG, POSG, OSPG) ambapo g ni nguzo ya +kugandana badala ya nguzo ya sehemu, na inaruhusu maswali ya ufanisi +katika picha zote. + +#### Maswali ya Muda + +**Kutafuta ukweli wote ambao uligunduliwa baada ya tarehe fulani:** +``` +S: ? # triple yoyote iliyotiwa nukuu +P: +O: > "2024-01-15"^^xsd:date +G: null +``` +**Kumbuka:** `^^xsd:date` inahitajika ili kuonyesha kuwa `2024-01-15` ni +tarehe, si kamba. + +**Kumbuka:** Huwezi kuuliza "tafuta triples ambapo kieleuzo cha mada ya +triple iliyotiwa nukuu ni X" + +#### Maswala ya Chanzo/Asili + +```python +# Tafuta ukweli ambao umeungwa mkono na chanzo X +# Tafuta taarifa ambapo chanzo ni X +# Tafuta masharti ambapo chanzo ni X +``` + +#### Maswala ya Ukweli/Amani + +```python +# Tafuta maelezo ambayo yamesemwa kuwa ni kweli +# Tafuta masharti ambapo ukweli ni kweli +# Tafuta maelezo ambayo yamesemwa kuwa ni kweli +``` + +Vitu vyote vyote vya RDF vinaruhusiwa, ikiwa ni pamoja na maneno ya +mtumiaji. Mkakati: epuka kuweka kitu chochote kilichofungwa isipokuwa +linapohitajika. + +## Masuala ya Usalama + +Picha hazina kipengele cha usalama. Watumiaji na makusudi ndio mipaka +ya usalama. Picha ni tu kwa shirika la data na usaidizi wa ufufunzaji. + +## Masuala ya Utendaji + +- Triples zilizotiwa nukuu zinaongeza kina cha kuziba - zinaweza kuathiri + utendaji wa maswali +- Mikakati ya ufuataji wa picha inahitajika kwa maswali ya picha +- Muundo wa schema ya Cassandra utahitaji kuweka nafasi kwa uhifadhi + wa quad kwa ufanisi + +### Kikomo cha Hifadhi ya Vector + +Hifadhi za vector daima zinaunga mkono IRIs pekee: +- Kamwe ukingo (triples zilizotiwa nukuu) +- Kamwe maadili +- Kamwe nodi tupu + +Hii inahifadhi hifadhi ya vector kuwa rahisi - inashughulikia utangamano +wa kimaana wa vitu vilivyoainishwa. Muundo wa grafu hushughulikia +mahusiano, ufufunzaji, na metadata. Triples zilizotiwa nukuu na picha +hazichanganyishi shughuli za vector. + +## Mkakati wa Majaribio + +Tumia mkakati wa sasa wa majaribio. Kwa kuwa hii ni mabadiliko ambayo +yanaweza kusababisha utosoni, zingatia sana seti ya majaribio ya mwisho +ku hakikisha kwamba miundo mipya inafanya kazi vizuri katika vipengele +vyote. + +## Mpango wa Uhamishaji + +- 2.0 ni toleo ambalo linaweza kusababisha utosoni; hakuna utangamano + wa kurudi nyuma unaohitajika +- Data iliyopo inaweza kuhitaji uhamishaji kwenye schema mpya (itaamuliwa + kulingana na muundo wa mwisho) +- Tafadhali fikiria zana za uhamishaji kwa ajili ya kubadilisha triples + zilizo zilizopo. + +## Masuala yaliyowazi + +- **Nodi tupu**: Usaidizi mdogo umeanzishwa. Inaweza kuhitaji uamuzi wa + mkakati wa skolemization (kuunda IRIs wakati wa kupakua, au kudumisha + vitambulisho vya nodi tupu). +- **Mbinu ya maswali**: Mbinu halisi ya kutaja triples zilizotiwa nukuu + katika maswali ni nini? Tafadhali define API ya swali. +- ~~**Sanaa ya kieleuzo**~~: Limeelekezwa. Maneno yoyote ya RDF yanaruhusiwa, + pamoja na maneno ya mtumiaji. Vipengele vichache tu vya kufungwa (k.m., + rdfs:label inatumiwa katika baadhi ya maeneo). + Mkakati: epuka kufunga kitu chochote isipokuwa kinapohitajika. +- ~~**Athari ya hifadhi ya vector**~~: Limeelekezwa. Hifadhi za vector + daima zinarejelea IRIs pekee - kamwe ukingo, maadili, au nodi tupu. + Triples zilizotiwa nukuu na ufufunzaji hazisababishi hifadhi ya vector. +- ~~**Semantika ya picha**~~: Limeelekezwa. Maswali huanguka chaguo-msingi + kwenye picha ya chaguo-msingi (inalingana na tabia ya SPARQL, inafaa + kurudi nyuma). Paramu halisi ya picha inahitajika kuuliza picha + zilizoainishwa au picha zote. + +## Marejeo + +- [Mawazo ya RDF 1.2](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-star na SPARQL-star](https://w3c.github.io/rdf-star/) +- [RDF Dataset](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.tr.md b/docs/tech-specs/graph-contexts.tr.md new file mode 100644 index 00000000..622c7f9a --- /dev/null +++ b/docs/tech-specs/graph-contexts.tr.md @@ -0,0 +1,775 @@ +--- +layout: default +title: "Graph Contexts Technical Specification" +parent: "Turkish (Beta)" +--- + +<<<<<<< HEAD +# Graph Contexts 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 + +Bu özellik, TrustGraph'ın temel grafik yapılarına yapılan değişiklikleri tanımlar ve +RDF 1.2 ile uyumlu olacak ve tam RDF Dataset semantiğini destekleyecek şekilde tasarlanmıştır. Bu, 2.x yayın serisi için önemli bir değişikliktir. + + +### Versioning +======= +# Graph Contexts Teknik Özellikler + +## Genel Bakış + +Bu özellik, TrustGraph'ın temel grafik öğelerindeki değişiklikleri, +RDF 1.2 ile uyumlu olacak ve tam RDF Dataset semantiğini destekleyecek şekilde tanımlar. Bu, 2.x sürüm serisi için önemli bir değişikliktir. + + +### Sürümleme +>>>>>>> 82edf2d (New md files from RunPod) + +**2.0**: Erken benimseyen sürüm. Temel özellikler mevcut, ancak henüz tamamen + üretim ortamına hazır olmayabilir. +**2.1 / 2.2**: Üretim sürümü. Kararlılık ve eksiksizlik doğrulandı. + +Olgunluk konusundaki esneklik kasıtlıdır; erken benimseyenler, tüm özellikler +üretim ortamına hazır hale gelmeden önce yeni yeteneklere erişebilir. + +<<<<<<< HEAD +## Goals +======= +## Hedefler +>>>>>>> 82edf2d (New md files from RunPod) + +Bu çalışmanın temel hedefleri, gerçekler/ifadeler hakkında meta veri sağlamaktır: + +**Zaman bilgisi**: Gerçekleri zamanla ilgili bilgilerle ilişkilendirme +<<<<<<< HEAD + Bir gerçeğin doğru olduğu düşünüldüğü zaman + Bir gerçeğin doğru hale geldiği zaman + Bir gerçeğin yanlış olduğu tespit edildiği zaman + +**Kaynak/Köken**: Bir gerçeği destekleyen kaynakları izleme + "Bu gerçek, X kaynağı tarafından desteklenmektedir" + Gerçekleri, köken belgelerine bağlama + +**Doğruluk/Güven**: Gerçekler hakkındaki iddiaları kaydetme + "Kişi P, bunun doğru olduğunu iddia etti" + "Kişi Q, bunun yanlış olduğunu iddia ediyor" + Güven puanlamasını ve çakışma tespitini etkinleştirme + +**Hipotez**: Yeniden tanımlama (RDF-star / tırnak işaretli üçlüler), bu sonuçları +elde etmek için temel mekanizmadır, çünkü bunların hepsi ifadeler hakkında ifadeler yapmayı gerektirir. + +## Background + +"Alice'in Bob'u tanıdığı" gerçeğinin "2024-01-15" tarihinde keşfedildiğini veya +"X kaynağının (Y'nin Z'ye neden olduğu) iddiasını desteklediğini" ifade etmek için, +bir kenara bir şey olarak başvurmanız ve bu kenar hakkında ifadeler yapabilmeniz gerekir. Standart üçlüler bunu desteklemez. + +### Current Limitations + +Mevcut `Value` sınıfı `trustgraph-base/trustgraph/schema/core/primitives.py` içinde +======= + Bir gerçeğin doğru olduğuna inanıldığı zaman + Bir gerçeğin doğru hale geldiği zaman + Bir gerçeğin yanlış olduğu keşfedildiğinde + +**Kaynak/Köken**: Bir gerçeği destekleyen kaynakları izleme + "Bu gerçek, kaynak X tarafından destekleniyordu" + Gerçekleri, köken belgelerine bağlama + +**Doğruluk/Güvenilirlik**: Doğrulukla ilgili ifadeleri kaydetme + "Kişi P, bunun doğru olduğunu iddia etti" + "Kişi Q, bunun yanlış olduğunu iddia ediyor" + Güvenilirlik puanlaması ve çakışma tespitini etkinleştirme + +**Hipotez**: Yeniden tanımlama (RDF-star / tırnaklı üçlüler), bu sonuçları elde etmenin temel mekanizmasıdır, çünkü bunların hepsi ifadeler hakkında ifadeler yapmayı gerektirir. + + +## Arka Plan + +"Alice'nin Bob'u bildiği gerçeği 2024-01-15'te keşfedildi" veya "kaynak X, (Y'nin Z'ye neden olduğu) iddiasını destekliyor" gibi ifadeleri belirtmek için, +bir kenarı, hakkında ifadeler yapılabilecek bir şey olarak referans göstermeniz gerekir. Standart üçlüler bunu desteklemez. + +### Mevcut Sınırlamalar + + +Mevcut `Value` sınıfı `trustgraph-base/trustgraph/schema/core/primitives.py` içinde: +>>>>>>> 82edf2d (New md files from RunPod) +şunları temsil edebilir: +URI düğümleri (`is_uri=True`) +Literal değerler (`is_uri=False`) + +<<<<<<< HEAD +`type` alanı mevcuttur, ancak XSD veri türlerini temsil etmek için kullanılmaz. + +## Technical Design + +### RDF Features to Support + +#### Core Features (Related to Reification Goals) + +Bu özellikler, zaman, kaynak ve doğruluk hedefleriyle doğrudan ilgilidir: + +1. **RDF 1.2 Quoted Triples (RDF-star)** +Diğer kenarlara işaret eden kenarlar + Bir Üçlü, başka bir Üçlünün konusu veya nesnesi olabilir + İfadeler hakkında ifadeler yapmayı sağlar (yeniden tanımlama) + Bireysel gerçekleri açıklamak için temel mekanizma + +2. **RDF Dataset / Named Graphs** +Bir veri kümesi içindeki birden fazla adlandırılmış grafik için destek + Her grafik bir IRI ile tanımlanır + Üçlülerden (s, p, o) dörtlülere (s, p, o, g) geçiş + Bir varsayılan grafik ve sıfır veya daha fazla adlandırılmış grafik içerir + Grafik IRI'si, ifadelerin konusu olabilir, örneğin: + Grafik IRI'si, ifadelerde bir özne olabilir, örneğin: +======= +`type` alanı mevcut, ancak XSD veri tiplerini temsil etmek için kullanılmıyor. + +## Teknik Tasarım + +### Desteklenecek RDF Özellikleri + +#### Temel Özellikler (Somutlaştırma Hedefleriyle İlgili) + +Bu özellikler, zamansallık, köken ve doğruluk +hedefleriyle doğrudan ilişkilidir: + +1. **RDF 1.2 Tırnak İşaretli Üçlüler (RDF-star)** + Diğer kenarlara işaret eden kenarlar + Bir Üçlü, başka bir Üçlünün öznesi veya nesnesi olabilir + Üçlüler hakkında ifadeler oluşturmayı sağlar (somutlaştırma) + Bireysel gerçekleri açıklamak için temel mekanizma + +2. **RDF Veri Kümesi / Adlandırılmış Grafikler** + Bir veri kümesi içinde birden fazla adlandırılmış grafik desteği + Her grafik bir IRI ile tanımlanır + Üçlülerden (s, p, o) dörtlülere (s, p, o, g) geçiş + Bir varsayılan grafik ve sıfır veya daha fazla adlandırılmış grafik içerir + Grafik IRI'si, ifadelerin bir öznesi olabilir, örneğin: +>>>>>>> 82edf2d (New md files from RunPod) + ``` + "2024-01-15" + "high" + ``` + Not: Adlandırılmış grafikler, somutlaştırmadan ayrı bir özelliktir. Bunlar, + yalnızca ifade açıklamasının ötesinde kullanımlara sahiptir (bölümleme, erişim kontrolü, veri kümesi +<<<<<<< HEAD + organizasyonu) ve ayrı bir yetenek olarak ele alınmalıdır. +======= + düzeni) ve ayrı bir yetenek olarak ele alınmalıdır. +>>>>>>> 82edf2d (New md files from RunPod) + +3. **Anonim Düğümler** (Sınırlı Destek) + Küresel bir URI'ye sahip olmayan anonim düğümler + Dış RDF verilerini yüklerken uyumluluk için desteklenir +<<<<<<< HEAD + **Sınırlı durum:** Yükleme işleminden sonra kararlı bir kimlik konusunda hiçbir garanti yoktur + Bunları jokerli sorgular aracılığıyla bulun (bağlantılara göre, kimliğe göre değil) +======= + **Sınırlı durum**: Yükleme işleminden sonra kararlı bir kimlik konusunda garanti yoktur + Bunları jokerli sorgularla bulun (bağlantılara göre, kimliğe göre değil) +>>>>>>> 82edf2d (New md files from RunPod) + Birincil bir özellik değildir - kesin anonim düğüm işleme özelliğine güvenmeyin + +#### Fırsatçı Düzeltmeler (2.0'ın Kırıcı Değişikliği) + +Bu özellikler, somutlaştırma hedefleriyle doğrudan ilişkili değildir, ancak +kırıcı değişiklikler yaparken dahil edilmesi değerli olan iyileştirmelerdir: + +4. **Literal Veri Tipleri** + XSD veri tipleri için `type` alanını doğru şekilde kullanın + Örnekler: xsd:string, xsd:integer, xsd:dateTime, vb. +<<<<<<< HEAD + Mevcut sınırlamayı düzeltir: tarihleri veya tamsayıları düzgün bir şekilde temsil edilemez +======= + Mevcut sınırlamayı düzeltir: tarihleri veya tamsayıları doğru şekilde temsil edilemez +>>>>>>> 82edf2d (New md files from RunPod) + +5. **Dil Etiketleri** + Dize literal değerleri üzerinde dil öznitelikleri desteği (@en, @fr, vb.) + Not: Bir literal değerin ya bir dil etiketi YA da bir veri tipi vardır, ikisi birden değil + (rdf:langString hariç) +<<<<<<< HEAD + Yapay zeka/çok dilli kullanım senaryoları için önemlidir +======= + Yapay zeka/çok dilli kullanım durumları için önemlidir +>>>>>>> 82edf2d (New md files from RunPod) + +### Veri Modelleri + +#### Terim (Value adından değiştirildi) + +`Value` sınıfı, RDF terminolojisini daha iyi yansıtmak için `Term` olarak yeniden adlandırılacaktır. +<<<<<<< HEAD +Bu yeniden adlandırma iki amaca hizmet etmektedir: +1. İsimlendirmeyi RDF kavramlarıyla uyumlu hale getirmek (bir "Terim", bir IRI, literal, boş + düğüm veya tırnak içindeki üçlü olabilir - sadece bir "değer" değildir). +2. Değişikliklere neden olan arayüzde kod incelemesini zorlamak - hala + `Value`'a referans veren herhangi bir kod, açıkça hatalıdır ve güncellenmesi gerekir. +======= +Bu yeniden adlandırmanın iki amacı vardır: +1. İsimlendirmeyi RDF kavramlarıyla uyumlu hale getirmek (bir "Terim", bir IRI, literal, boş + düğüm veya tırnak içindeki üçlü olabilir - sadece bir "değer" değildir). +2. Kod incelemesini, önemli değişikliklerin yapıldığı arayüzde zorunlu kılmak - hala + `Value`'a referans veren herhangi bir kod, açıkça hatalı olacaktır ve güncellenmesi gerekecektir. +>>>>>>> 82edf2d (New md files from RunPod) + +Bir Terim şunları temsil edebilir: + +**IRI/URI** - Adlandırılmış bir düğüm/kaynak +**Boş Düğüm** - Yerel kapsamı olan anonim bir düğüm +**Literal (Değer)** - Ya bir veri türü (XSD türü) veya + Bir dil etiketi + **Tırnak İçine Alınmış Üçlü** - Bir terim olarak kullanılan bir üçlü (RDF 1.2) + + +##### Seçilen Yaklaşım: Tip Ayırıcısı Olan Tek Sınıf + +<<<<<<< HEAD +Serileştirme gereksinimleri yapıyı belirler - bir tür ayrımcısına ihtiyaç vardır. +Python gösteriminden bağımsız olarak, kablo formatında bir tür ayrımcısına ihtiyaç vardır. +======= +Serileştirme gereksinimleri yapıyı belirler - bir tür belirleyiciye ihtiyaç vardır. +Python gösteriminden bağımsız olarak, kablo formatında bir tür belirleyiciye ihtiyaç vardır. +>>>>>>> 82edf2d (New md files from RunPod) +Tek bir sınıf ve bir tür alanı, doğal bir çözümdür ve mevcut `Value` kalıbıyla uyumludur. + +Tek karakterli tür kodları, kompakt serileştirme sağlar: + +```python +from dataclasses import dataclass + +# Term type constants +IRI = "i" # IRI/URI node +BLANK = "b" # Blank node +LITERAL = "l" # Literal value +TRIPLE = "t" # Quoted triple (RDF-star) + +@dataclass +class Term: + type: str = "" # One of: IRI, BLANK, LITERAL, TRIPLE + + # For IRI terms (type == IRI) + iri: str = "" + + # For blank nodes (type == BLANK) + id: str = "" + + # For literals (type == LITERAL) + value: str = "" + datatype: str = "" # XSD datatype URI (mutually exclusive with language) + language: str = "" # Language tag (mutually exclusive with datatype) + + # For quoted triples (type == TRIPLE) + triple: "Triple | None" = None +``` + +Kullanım örnekleri: + +```python +# IRI term +node = Term(type=IRI, iri="http://example.org/Alice") + +# Literal with datatype +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# Literal with language tag +label = Term(type=LITERAL, value="Hello", language="en") + +# Blank node +anon = Term(type=BLANK, id="_:b1") + +# Quoted triple (statement about a statement) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### Alternatifler + +**B Seçeneği: Özel sınıfların birleşimi** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +Reddedildi: Seri hale getirme işlemi hala bir tür belirleyici gerektirecek, bu da karmaşıklığı artıracaktır. + +**C Seçeneği: Alt sınıflara sahip temel sınıf** +Reddedildi: Aynı seri hale getirme sorunu, ayrıca dataclass miras özellikleriyle ilgili sorunlar. + +#### Üçlü / Dörtlü + +`Triple` sınıfı, isteğe bağlı bir grafik alanı kazanarak dörtlü bir yapıya dönüşebilir: + +```python +@dataclass +class Triple: + s: Term | None = None # Subject + p: Term | None = None # Predicate + o: Term | None = None # Object + g: str | None = None # Graph name (IRI), None = default graph +``` + +Tasarım kararları: +**Alan adı**: `g`, `s`, `p` ve `o` ile tutarlılık için. +**İsteğe bağlı**: `None`, varsayılan grafiği (isim belirtilmemiş) ifade eder. +**Tip**: Terim yerine düz bir dize (IRI). + Grafik adları her zaman IRI'lerdir. + Boş düğümlerin grafik adı olarak kullanılması reddedildi (çok kafa karıştırıcı). + Tam Terim mekanizmasına ihtiyaç yok. + +Not: Sınıf adı teknik olarak bir dörtlü olsa bile `Triple` olarak kalır. +Bu, karmaşayı önler ve "üçlü" terimi hala s/p/o kısmı için yaygın olarak kullanılan bir terimdir. Grafik bağlamı, üçlünün nerede bulunduğu hakkında meta veridir. + + +### Olası Sorgu Desenleri + +Mevcut sorgu motoru, S, P, O terimlerinin kombinasyonlarını kabul eder. Tırnak içinde belirtilen +üçlüler, bir üçlünün kendisi bu konumlarda geçerli bir terim haline gelir. Aşağıda, +orijinal hedefleri destekleyen olası sorgu desenleri bulunmaktadır. + +<<<<<<< HEAD +#### Grafik Parametre Anlamları +======= +#### Grafik Parametre Anlamı +>>>>>>> 82edf2d (New md files from RunPod) + +Geriye dönük uyumluluk için SPARQL kurallarına uygun olarak: + +**`g` belirtilmemiş / Yok**: Yalnızca varsayılan grafiği sorgula. +**`g` = belirli bir IRI**: Yalnızca o adlandırılmış grafiği sorgula. +**`g` = joker karakter / `*`**: Tüm grafikler arasında sorgu yap (SPARQL ile eşdeğer + `GRAPH ?g { ... }`). + +Bu, basit sorguları basit tutar ve adlandırılmış grafik sorgularını isteğe bağlı hale getirir. + +<<<<<<< HEAD +Grafik arası sorgular (g=joker karakter), tamamen desteklenir. Cassandra şeması, +g'nin bir kümeleme sütunu olduğu (bölüm anahtarı olmadığı) özel tabloları içerir (SPOG, POSG, OSPG), +======= +Grafikler arası sorgular (g=joker karakter) tamamen desteklenir. Cassandra şeması, +g'nin bir kümeleme sütunu olduğu (bölüm anahtarı değil) özel tabloları içerir (SPOG, POSG, OSPG), +>>>>>>> 82edf2d (New md files from RunPod) +bu da tüm grafikler arasında verimli sorgular yapmayı sağlar. + +#### Zamansal Sorgular + +**Belirli bir tarihten sonra keşfedilen tüm bilgileri bul:** +``` +S: ? # any quoted triple +P: +O: > "2024-01-15"^^xsd:date # date comparison +``` + +**Belirli bir bilginin ne zaman doğru olduğuna inanıldığı bulun:** +``` +S: << >> # quoted triple as subject +P: +O: ? # returns the date +``` + +**Yanlış hale gelen bilgileri bulun:** +``` +S: ? # any quoted triple +P: +O: ? # has any value (exists) +``` + +#### Kaynak Sorguları + +**Belirli bir kaynağa dayanan tüm bilgileri bulun:** +``` +S: ? # any quoted triple +P: +O: +``` + +**Belirli bir gerçeği destekleyen kaynakları bulun:** +``` +S: << >> # quoted triple as subject +P: +O: ? # returns source IRIs +``` + +#### Doğruluk Sorguları + +**Bir kişinin doğru olarak işaretlediği ifadeleri bulun:** +``` +S: ? # any quoted triple +P: +O: +``` + +**Çelişkili ifadeleri bulun (aynı gerçek, farklı doğruluk):** +``` +# First query: facts asserted true +S: ? +P: +O: ? + +# Second query: facts asserted false +S: ? +P: +O: ? + +# Application logic: find intersection of subjects +``` + +**Güvenilirlik puanı eşik değerinin altında olan bilgileri bulun:** +``` +S: ? # any quoted triple +P: +O: < 0.5 # numeric comparison +``` + +### Mimari + +<<<<<<< HEAD +Birden çok bileşende önemli değişiklikler gereklidir: +======= +Birden fazla bileşende önemli değişiklikler gereklidir: +>>>>>>> 82edf2d (New md files from RunPod) + +#### Bu Depo (trustgraph) + +**Şema ilkel öğeleri** (`trustgraph-base/trustgraph/schema/core/primitives.py`) + Değer → Terim yeniden adlandırması +<<<<<<< HEAD + Tip ayrımcısına sahip yeni Terim yapısı +======= + Tip ayrımcısı ile yeni Terim yapısı +>>>>>>> 82edf2d (New md files from RunPod) + Üçlü, grafik bağlamı için `g` alanı kazanır + +**Mesaj çeviricileri** (`trustgraph-base/trustgraph/messaging/translators/`) + Yeni Terim/Üçlü yapıları için güncelleme + Yeni alanlar için serileştirme/deserileştirme + +**Geçit bileşenleri** + Yeni Terim ve dörtlü yapılarını işleyin + +**Bilgi çekirdekleri** + Dörtlüleri ve yeniden tanımlamayı desteklemek için çekirdek değişiklikleri + +**Bilgi yöneticisi** + Şema değişiklikleri burada yayılır + +**Depolama katmanları** + Cassandra: Şema yeniden tasarımı (Ayrıntılar için Uygulama Ayrıntılarına bakın) + Diğer arka uçlar: Daha sonraki aşamalara ertelenmiştir + +**Komut satırı araçları** + Yeni veri yapıları için güncelleme + +**REST API dokümantasyonu** + OpenAPI spesifikasyonunda güncellemeler + +#### Harici Depolar + +**Python API'si** (bu depo) + Yeni yapılar için istemci kitaplığı güncellemeleri + +**TypeScript API'leri** (ayrı depo) + İstemci kitaplığı güncellemeleri + +**Çalışma alanı** (ayrı depo) + Önemli durum yönetimi değişiklikleri + +### API'ler + +#### REST API + +OpenAPI spesifikasyonunda belgelenmiştir +Yeni Terim/Üçlü yapıları için güncellenmesi gerekecektir +Grafik bağlamı işlemleri için yeni uç noktaları gerekebilir + +#### Python API'si (bu depo) + +Yeni ilkel öğelerle eşleşen istemci kitaplığı değişiklikleri +Terim (önceden Değer) ve Üçlü için bozucu değişiklikler + +#### TypeScript API'si (ayrı depo) + +Python API'sine paralel değişiklikler +Ayrı sürüm koordinasyonu + +#### Çalışma alanı (ayrı depo) + +Önemli durum yönetimi değişiklikleri +<<<<<<< HEAD +Grafik bağlamı özellikleriyle ilgili kullanıcı arayüzü güncellemeleri +======= +Grafik bağlamı özelliklerini destekleyen UI güncellemeleri +>>>>>>> 82edf2d (New md files from RunPod) + +### Uygulama Ayrıntıları + +#### Aşamalı Depolama Uygulaması + +<<<<<<< HEAD +Birden çok grafik depolama arka ucu (Cassandra, Neo4j, vb.) vardır. Uygulama +aşağıdaki aşamalarda gerçekleştirilecektir: + +1. **1. Aşama: Cassandra** + Yerel Cassandra deposuyla başlayın + Depolama katmanı üzerinde tam kontrol, hızlı yinelemeyi sağlar + Şema, dörtlüler + yeniden tanımlama için sıfırdan yeniden tasarlanacaktır +======= +Birden fazla grafik depolama arka ucu (Cassandra, Neo4j, vb.) bulunmaktadır. Uygulama, +aşağıdaki aşamalarda gerçekleştirilecektir: + +1. **1. Aşama: Cassandra** + Kendi geliştirdiğimiz Cassandra deposuyla başlayın + Depolama katmanı üzerinde tam kontrole sahip olmak, hızlı yinelemeyi sağlar + Şema, dörtlüler ve yeniden tanımlama için sıfırdan yeniden tasarlanacaktır +>>>>>>> 82edf2d (New md files from RunPod) + Veri modelini ve sorgu kalıplarını gerçek kullanım durumlarına göre doğrulayın + +#### Cassandra Şema Tasarımı + +Cassandra, farklı sorgu erişim modellerini desteklemek için birden fazla tablo gerektirir +(her tablo, bölüm anahtarı + kümeleme sütunları aracılığıyla verimli bir şekilde sorgulanır). + +##### Sorgu Modelleri + +"quads" (g, s, p, o) ile, her konum belirtilebilir veya joker karakter olabilir ve bu da +16 olası sorgu modeli oluşturur: + +| # | g | s | p | o | Açıklama | +|---|---|---|---|---|-------------| +| 1 | ? | ? | ? | ? | Tüm "quads" | +| 2 | ? | ? | ? | o | Nesneye göre | +| 3 | ? | ? | p | ? | Özneye göre | +| 4 | ? | ? | p | o | Özne + nesneye göre | +| 5 | ? | s | ? | ? | Konuya göre | +| 6 | ? | s | ? | o | Konu + nesneye göre | +<<<<<<< HEAD +| 7 | ? | s | p | ? | Konu + öneye göre | +| 8 | ? | s | p | o | Tam üçlü (hangi grafikler?) | +| 9 | g | ? | ? | ? | Grafiğe göre | +| 10 | g | ? | ? | o | Grafik + nesneye göre | +| 11 | g | ? | p | ? | Grafik + öneye göre | +| 12 | g | ? | p | o | Grafik + öne + nesneye göre | +| 13 | g | s | ? | ? | Grafik + konuya göre | +| 14 | g | s | ? | o | Grafik + konu + nesneye göre | +| 15 | g | s | p | ? | Grafik + konu + öneye göre | +======= +| 7 | ? | s | p | ? | Konu + özneliğe göre | +| 8 | ? | s | p | o | Tam üçlü (hangi grafikler?) | +| 9 | g | ? | ? | ? | Grafiğe göre | +| 10 | g | ? | ? | o | Grafik + nesneye göre | +| 11 | g | ? | p | ? | Grafik + özneliğe göre | +| 12 | g | ? | p | o | Grafik + özneliği + nesneye göre | +| 13 | g | s | ? | ? | Grafik + konuya göre | +| 14 | g | s | ? | o | Grafik + konu + nesneye göre | +| 15 | g | s | p | ? | Grafik + konu + özneliğe göre | +>>>>>>> 82edf2d (New md files from RunPod) +| 16 | g | s | p | o | Tam "quad" | + +##### Tablo Tasarımı + +<<<<<<< HEAD +Cassandra kısıtlaması: Yalnızca bölüm anahtarına göre verimli bir şekilde sorgulayabilirsiniz, ardından +======= +Cassandra kısıtlaması: Yalnızca bölüm anahtarına göre verimli bir şekilde sorgu yapabilirsiniz, ardından +>>>>>>> 82edf2d (New md files from RunPod) +kümeleme sütunları üzerinde soldan sağa filtreleme yapabilirsiniz. "g" joker karakterli sorgular için, "g" bir +kümeleme sütunu olmalıdır. "g" belirtilmiş sorgular için, bölüm anahtarında bulunan "g" daha +verimlidir. + +**İki tablo ailesi gereklidir:** + +**A Ailesi: "g" joker karakterli sorgular** ("g" kümeleme sütunlarında) + +| Tablo | Bölüm | Kümeleme | Desteklenen modeller | +|-------|-----------|------------|-------------------| +| SPOG | (kullanıcı, koleksiyon, s) | p, o, g | 5, 7, 8 | +| POSG | (kullanıcı, koleksiyon, p) | o, s, g | 3, 4 | +| OSPG | (kullanıcı, koleksiyon, o) | s, p, g | 2, 6 | + +**B Ailesi: "g" belirtilmiş sorgular** ("g" bölüm anahtarında) + +| Tablo | Bölüm | Kümeleme | Desteklenen modeller | +|-------|-----------|------------|-------------------| +| GSPO | (kullanıcı, koleksiyon, g, s) | p, o | 9, 13, 15, 16 | +| GPOS | (kullanıcı, koleksiyon, g, p) | o, s | 11, 12 | +| GOSP | (kullanıcı, koleksiyon, g, o) | s, p | 10, 14 | + +**Koleksiyon tablosu** (döngüleme ve toplu silme için) + +| Tablo | Bölüm | Kümeleme | Amaç | +|-------|-----------|------------|---------| +| COLL | (kullanıcı, koleksiyon) | g, s, p, o | Koleksiyondaki tüm "quad"ları numaralandır | + +##### Yazma ve Silme Yolları + +**Yazma yolu**: Tüm 7 tabloya ekleyin. + +**Koleksiyon silme yolu**: +1. `(user, collection)` için COLL tablosunu yineleyin +2. Her "quad" için, tüm 6 sorgu tablosundan silin +3. COLL tablosundan silin (veya aralık silme) + +**Tek bir "quad" silme yolu**: Tüm 7 tabloya doğrudan silin. + +##### Depolama Maliyeti + +Her "quad" 7 kez depolanır. Bu, esnek sorgulama ile +verimli koleksiyon silme birleşiminin maliyetidir. + +##### Depolamada Alıntılanmış Üçlüler + +Konu veya nesne kendisi bir üçlü olabilir. Seçenekler: + +**A Seçeneği: Alıntılanmış üçlüleri standart bir dizeye seri hale getirin** +``` +S: "<>" +P: http://ex/discoveredOn +O: "2024-01-15" +G: null +``` +Tırnak içinde belirtilen üçlüleri, seri hale getirilmiş bir dize olarak S veya O sütunlarında saklayın. +<<<<<<< HEAD +Seri hale getirilmiş forma göre tam eşleşme ile sorgulayın. +Artı: Basit, mevcut indeks kalıplarına uyuyor. +Eksileri: "Tırnak içinde belirtilen öznenin yüklemesinin X olduğu üçlüleri bul" gibi sorguları yapmak mümkün değil. +======= +Seri hale getirilmiş forma göre tam eşleşme sorgusu yapın. +Artı: Basit, mevcut indeks kalıplarına uyuyor. +Eksileri: "Tırnak içinde belirtilen öznenin yüklemesinin X olduğu üçlüleri bul" gibi sorgular yapılamaz. +>>>>>>> 82edf2d (New md files from RunPod) + +**B Seçeneği: Üçlü Kimlikleri / Hash'leri** +``` +Triple table: + id: hash(s,p,o,g) + s, p, o, g: ... + +Metadata table: + subject_triple_id: + p: http://ex/discoveredOn + o: "2024-01-15" +``` +Her üçlüye bir kimlik (bileşenlerin karma değeri) atayın. +<<<<<<< HEAD +Örnek meta veri referansları, kimlik numarasıyla üçlüleri belirtir. +Artı: Temiz bir ayrım, üçlü kimlik numaralarının indekslenmesini sağlar. +Eksileri: Üçlü kimliğinin hesaplanmasını/yönetilmesini gerektirir, iki aşamalı aramalar. + +**Öneri**: Basitlik için A seçeneğiyle (serileştirilmiş dizeler) başlayın. +B seçeneği, tırnak içinde belirtilen üçlü bileşenleri üzerinde gelişmiş sorgu desenleri gerekiyorsa gerekebilir. + +ÇIKTI SÖZLEŞMESİ (tam olarak aşağıdaki formatı takip etmelidir): +2. **2. Aşama+: Diğer Altyapılar** + Neo4j ve diğer depolama sistemleri, sonraki aşamalarda uygulanmıştır. + Cassandra'dan edinilen deneyimler, bu uygulamaları etkilemiştir. + +Bu yaklaşım, tamamen kontrol altında olan bir altyapıda doğrulama yaparak tasarım riskini azaltır. +======= +Somutlaştırma meta veri referansları, kimlik numarasıyla üçlülere başvurur. +Artı: Temiz bir ayrım, üçlü kimlik numaralarını indekslemek mümkündür. +Eksileri: Üçlü kimliğini hesaplamayı/yönetmeyi gerektirir, iki aşamalı aramalar. + +**Öneri**: Basitlik için A seçeneğiyle (serileştirilmiş dizeler) başlayın. +B seçeneği, tırnak içinde belirtilen üçlü +bileşenleri üzerinde gelişmiş sorgu desenleri gerekiyorsa gerekebilir. + +2. **Faz 2+: Diğer Altyapılar** + Neo4j ve diğer depolama sistemleri, sonraki aşamalarda uygulanmıştır. + Cassandra'dan edinilen deneyimler, bu uygulamaları etkilemiştir. + +Bu yaklaşım, tamamen kontrol altında olan bir altyapıda doğrulama yaparak tasarım risklerini azaltır. +>>>>>>> 82edf2d (New md files from RunPod) +Tüm depolama sistemlerine yönelik uygulamalara başlamadan önce bu doğrulama yapılır. + +#### Değer → Terim Yeniden Adlandırma + +`Value` sınıfı, `Term` olarak yeniden adlandırılacaktır. Bu, kod tabanındaki yaklaşık 78 dosyayı etkilemektedir. +Yeniden adlandırma, bir zorlama işlevi olarak görev görmektedir: hala ⟦CODE_0⟧'ı kullanan herhangi bir kod... +`Value`, 2.0 ile uyumluluk açısından gözden geçirilmesi/güncellenmesi gereken bir alan olarak hemen belirlenebilir. + + +## Güvenlik Hususları + +Adlandırılmış grafikler bir güvenlik özelliği değildir. Kullanıcılar ve koleksiyonlar, +<<<<<<< HEAD +güvenlik sınırlarıdır. Adlandırılmış grafikler tamamen veri organizasyonu ve +======= +güvenlik sınırlarıdır. Adlandırılmış grafikler tamamen veri düzenlemesi ve +>>>>>>> 82edf2d (New md files from RunPod) +somutlaştırma desteği içindir. + +## Performans Hususları + +Tırnak işaretli üçlüler, iç içe derinliğini artırır - sorgu performansını etkileyebilir. +<<<<<<< HEAD +Verimli grafik kapsamlı sorgular için adlandırılmış grafik indeksleme stratejilerine ihtiyaç vardır. +======= +Verimli grafik kapsamlı sorgular için adlandırılmış grafik indeksleme stratejileri gereklidir. +>>>>>>> 82edf2d (New md files from RunPod) +Cassandra şema tasarımı, dörtlü depolamayı verimli bir şekilde karşılayacak şekilde tasarlanmalıdır. + +### Vektör Depolama Sınırı + +Vektör depoları her zaman yalnızca IRI'lere başvurur: +Asla kenarlar (tırnak işaretli üçlüler) +Asla literal değerler +Asla boş düğümler + +Bu, vektör deposunu basit tutar; adlandırılmış varlıkların semantik benzerliğini işler. Grafik yapısı, ilişkileri, somutlaştırmayı ve meta verileri yönetir. +Tırnak içinde belirtilen üçlüler ve adlandırılmış grafikler, vektör işlemlerini karmaşıklaştırmaz. + +## Test Stratejisi + +Mevcut test stratejisini kullanın. Bu, önemli bir değişiklik olduğundan, yeni yapıların tüm bileşenlerde doğru şekilde çalıştığını doğrulamak için uçtan uca test paketine kapsamlı bir şekilde odaklanılmalıdır. + +## Geçiş Planı + +2.0, önemli bir değişiklik içeren bir sürümdür; geriye dönük uyumluluk gerekmemektedir. +Mevcut verilerin, yeni şemaya aktarılması gerekebilir (son tasarım bazında belirlenecektir). +Mevcut üçlüleri dönüştürmek için geçiş araçlarını göz önünde bulundurun. + +## Açık Sorular + + +## Açık Sorular + +<<<<<<< HEAD +**Boş düğümler**: Sınırlı destek doğrulandı. Boş düğümler için bir skolemleştirme stratejisi belirlemek gerekebilir (yükleme sırasında IRI'lar oluşturmak veya boş düğüm kimliklerini korumak). + **Sorgu sözdizimi**: Alıntılanmış üçlüleri sorgularda belirtmek için somut sözdizimi nedir? Sorgu API'sini tanımlamak gerekiyor. +~~**Önerme sözlüğü**~~: Çözüldü. Herhangi bir geçerli RDF önermesi izin verilir, kullanıcı tanımlı olanlar dahil. RDF geçerliliği hakkında minimum varsayımlar. + Çok az sabit değer (örneğin, bazı yerlerde kullanılan ⟦CODE_0⟧). +~~**Önerme sözlüğü**:~~ Çözüldü. Herhangi bir geçerli RDF özneli kabul edilebilir, + kullanıcı tarafından tanımlanmış özel özneler de dahil. RDF geçerliliği hakkında çok az varsayım. + Çok az sabit değer (örneğin, bazı yerlerde kullanılan `rdfs:label`). + Strateji: Mümkün olduğunca hiçbir şeyi kilitlememeye özen gösterin. +~~**Vektör depolama etkisi**~~: Çözüldü. Vektör depoları her zaman IRI'lere işaret eder. + sadece - asla kenarlara, literal değerlere veya boş düğümlere işaret etmez. Tırnak işaretli üçlüler ve + yeniden tanımlama, vektör deposunu etkilemez. +~~**Adlandırılmış grafik semantiği**~~: Çözüldü. Sorgular varsayılan olarak + grafiğe yöneliktir (SPARQL davranışıyla eşleşir, geriye dönük uyumlu). Adlandırılmış grafiklere veya tüm + grafiklere sorgu yapmak için açık bir grafik parametresi gereklidir. +======= +**Boş düğümler**: Sınırlı destek doğrulandı. Boş düğümler için bir skolemleştirme stratejisi belirlemek gerekebilir (yükleme sırasında IRİ'ler oluşturmak veya boş düğüm kimliklerini korumak). + **Sorgu sözdizimi**: Alıntılanmış üçlüleri sorgularda belirtmek için somut sözdizimi nedir? Sorgu API'sini tanımlamak gerekiyor. +~~**Önerme sözlüğü**~~: Çözüldü. Herhangi bir geçerli RDF önermesi izin verilir, kullanıcı tanımlı olanlar da dahil. RDF geçerliliği hakkında minimum varsayımlar. + Çok az sabit değer (örneğin, bazı yerlerde kullanılan ⟦CODE_0⟧). +~~**Önerme sözlüğü**:~~ Çözüldü. Herhangi bir geçerli RDF özneli kabul edilir, + kullanıcı tarafından tanımlanmış özel özneler de dahil. RDF geçerliliği hakkında çok az varsayım yapılır. + Çok az sabit değer (örneğin, bazı yerlerde kullanılan `rdfs:label`). + Strateji: Mümkün olduğunca hiçbir şeyi kilitlememeye özen gösterin. +~~**Vektör depolama etkisi**~~: Çözüldü. Vektör depoları her zaman IRI'lara işaret eder. + sadece - asla kenarlara, literal değerlere veya boş düğümlere işaret etmez. Tırnak işaretli üçlüler ve + yeniden tanımlama, vektör deposunu etkilemez. +~~**Adlandırılmış grafik semantiği**~~: Çözüldü. Sorgular, varsayılan + grafiğe varsayılan olarak yöneliktir (SPARQL davranışıyla eşleşir, geriye dönük uyumlu). Açık bir grafik + parametresi, adlandırılmış grafiklere veya tüm grafiklere sorgu yapmak için gereklidir. +>>>>>>> 82edf2d (New md files from RunPod) + +## Referanslar + +[RDF 1.2 Kavramları](https://www.w3.org/TR/rdf12-concepts/) +[RDF-star ve SPARQL-star](https://w3c.github.io/rdf-star/) +[RDF Veri Kümesi](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graph-contexts.zh-cn.md b/docs/tech-specs/graph-contexts.zh-cn.md new file mode 100644 index 00000000..b54b1b27 --- /dev/null +++ b/docs/tech-specs/graph-contexts.zh-cn.md @@ -0,0 +1,425 @@ +--- +layout: default +title: "Graph Contexts 技术规范" +parent: "Chinese (Beta)" +--- + +# Graph Contexts 技术规范 + +> **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 核心图结构体的变更,以符合 RDF 1.2 标准并支持完整的 RDF 数据集语义。 这对 2.x 版本系列是一个破坏性变更。 + +### 版本控制 + +- **2.0**: 早期采用版本。核心功能可用,可能尚未完全达到生产级别。 +- **2.1 / 2.2**: 生产版本。稳定性和完整性已验证。 + +关于成熟度的灵活性是故意的 - 早期采用者可以访问新的功能,而所有功能尚未经过生产环境的验证。 + +## 目标 + +本次工作的首要目标是启用关于事实/声明的元数据: + +- **时间信息**: 将事实与时间元数据关联 + - 确定一个事实何时被认为是正确的。 + - 确定一个事实何时开始成立。 + - 确定一个事实何时被发现是错误的。 + +- **来源/溯源**: 跟踪哪些来源支持一个事实 + - “这个事实由来源 X 支持”。 + - 将事实链接回其原始文档。 + +- **真实性/信任度**: 记录对真实性的断言 + - “Person P 声明这是真的”。 + - “Person Q 声称这是假的”。 + - 启用信任评分和冲突检测。 + +**假设**: 重构(RDF-star / 引用三元组)是实现这些目标的关键机制,因为所有这些都要求对声明进行声明。 + +## 背景 + +为了表达“事实(Alice 知道 Bob)于 2024-01-15 被发现”或“来源 X 支持(Y 导致 Z)的声明”,您需要引用一个边作为可以进行声明的对象。 标准的三元组不支持这种情况。 + +### 当前限制 + +`trustgraph-base/trustgraph/schema/core/primitives.py` 中的当前 `Value` 类可以表示: +- URI 节点 (`is_uri=True`) +- 原始值 (`is_uri=False`) + +`type` 字段存在,但未用于表示 XSD 数据类型。 + +## 技术设计 + +### 需要支持的 RDF 功能 + +#### 核心功能(与重构目标相关) + +这些功能与时间、溯源和真实性目标直接相关: + +1. **RDF 1.2 引用三元组 (RDF-star)** + - 指向其他边的边。 + - 三元组可以作为另一个三元组的主语或宾语。 + - 启用关于声明的声明(重构)。 + - 注释单个事实的核心机制。 + +2. **RDF 数据集 / 命名图** + - 支持数据集中的多个命名图。 + - 每个图由 IRI 标识。 + - 从三元组 (s, p, o) 转换为四元组 (s, p, o, g)。 + - 包含一个默认图以及零个或多个命名图。 + - 图 IRI 可以是语句的主语,例如: + ``` + "2024-01-15" + "high" + ``` + - 注意:命名图是一个与重构分离的功能。 它们除了语句注释之外还有其他用途(分区、访问控制、数据集组织),并且应该被视为一种不同的能力。 + +3. **匿名节点** (有限支持) + - 没有全局 URI 的匿名节点。 + - 用于兼容性,以便加载外部 RDF 数据。 + - **有限状态**: 对加载后身份的稳定性没有保证。 + - 通过通配符查询找到它们(通过连接匹配,而不是通过 ID)。 + - 不是首选功能 - 不要依赖于精确的匿名节点处理。 + +#### 机会性修复 (2.0 破坏性变更) + +这些功能与重构目标没有直接关系,但包含在破坏性变更中是有价值的改进: + +4. **原始数据类型** + - 正确使用 `type` 字段表示 XSD 数据类型。 + - 示例:xsd:string, xsd:integer, xsd:dateTime 等。 + - 修复当前限制:无法正确表示日期或整数。 + +5. **语言标签** + - 支持字符串原始值上的语言属性 (@en, @fr 等)。 + - 注意:一个原始值要么有一个语言标签,要么有一个数据类型,两者不能同时存在(除了 rdf:langString)。 + - 对于 AI/多语言用例非常重要。 + +### 数据模型 + +#### Term (重命名自 Value) + +`Value` 类将被重命名为 `Term`,以更好地反映 RDF 术语。 +此重命名有两个目的: +1. 与 RDF 概念对齐命名(“Term”可以是 IRI、原始值、匿名节点或引用三元组,而不仅仅是“值”)。 +2. 在破坏性变更接口强制代码审查 - 任何仍然引用 `Value` 的代码都会立即显示为已损坏,并且需要更新。 + +一个 Term 可以表示: + +- **IRI/URI** - 命名节点/资源。 +- **匿名节点** - 具有本地作用域的匿名节点。 +- **原始值** - 具有以下之一的数据值: + - 数据类型 (XSD 类型),或 + - 语言标签。 +- **引用三元组** - 用作项的三元组 (RDF 1.2)。 + +##### 选定的方法:具有类型区分器的单个类 + +序列化要求驱动结构 - 无论 Python 表示形式如何,都需要类型区分器。 具有类型字段的单个类是最佳选择,并且与当前的 `Value` 模式一致。 + +单字符类型代码提供紧凑的序列化: + +```python +from dataclasses import dataclass + +# Term 类型常量 +IRI = "i" # IRI/URI 节点 +BLANK = "b" # 匿名节点 +LITERAL = "l" # 原始值 +TRIPLE = "t" # 引用三元组 (RDF-star) + +@dataclass +class Term: + type: str = "" # 之一: IRI, BLANK, LITERAL, TRIPLE + + # 对于 IRI 项 (type == IRI) + iri: str = "" + + # 对于匿名节点 (type == BLANK) + id: str = "" + + # 对于原始值 (type == LITERAL) + value: str = "" + datatype: str = "" # XSD 数据类型 URI (与语言互斥) + language: str = "" # 语言标签 (与数据类型互斥) + + # 对于引用三元组 (type == TRIPLE) + triple: "Triple | None" = None +``` + +用法示例: + +```python +# IRI 项 +node = Term(type=IRI, iri="http://example.org/Alice") + +# 带数据类型的原始值 +age = Term(type=LITERAL, value="42", datatype="xsd:integer") + +# 带语言标签的原始值 +label = Term(type=LITERAL, value="Hello", language="en") + +# 匿名节点 +anon = Term(type=BLANK, id="_:b1") + +# 引用三元组 (关于声明的声明) +inner = Triple( + s=Term(type=IRI, iri="http://example.org/Alice"), + p=Term(type=IRI, iri="http://example.org/knows"), + o=Term(type=IRI, iri="http://example.org/Bob"), +) +reified = Term(type=TRIPLE, triple=inner) +``` + +##### 考虑的替代方案 + +**选项 B:专用类的联合** (`Term = IRI | BlankNode | Literal | QuotedTriple`) +- 拒绝:仍然需要类型区分器进行序列化,增加了复杂性。 + +**选项 C:具有子类的基本类** +- 拒绝:与序列化问题相同,此外还有 dataclass 继承的复杂性。 + +#### Triple / Quad + +`Triple` 类获得一个可选的图字段,以成为四元组: + +```python +@dataclass +class Triple: + s: Term | None = None # 主语 + p: Term | None = None # 谓词 + o: Term | None = None # 宾语 + g: str | None = None # 图名 (IRI),None = 默认图 +``` + +设计决策: +- **字段名称**: `g` 用于与 `s`、`p`、`o` 一致。 +- **可选**: `None` 表示默认图(无命名)。 +- **类型**: 纯字符串 (IRI),而不是 Term + - 图名始终是 IRI。 + - 匿名节点作为图名被排除(过于混乱)。 + - 不需要完整的 Term 机制。 + +注意:类名保持为 `Triple`,即使它现在实际上是一个四元组。 +这避免了变更,并且术语“三元组”仍然是常见的术语。 图上下文是关于三元组存储位置的元数据。 + +### 候选查询模式 + +当前查询引擎接受 S、P、O 项的组合。 使用引用三元组时,一个三元组本身可以成为这些位置上的有效项。 以下是支持原始目标的候选查询模式。 + +#### 图参数语义 + +遵循 SPARQL 的约定以实现向后兼容: + +- **`g` 被省略 / None**: 仅查询默认图。 +- **`g` = 特定 IRI**: 仅查询该命名图。 +- **`g` = 通配符 / `*`**: 查询所有图 (相当于 SPARQL `GRAPH ?g { ... }`) + +这保持简单查询的简单性,并使命名图查询成为可选。 + +完全支持跨图查询 (g=通配符)。 Cassandra 模式包含专门的表,其中 g 是一个聚类列,而不是分区键,从而实现高效的跨所有图的查询。 + +#### 时间查询 + +**查找在特定日期之后发现的所有事实:** +``` +S: ? # 任何引用三元组 +P: +O: > "2024-01-15"^^xsd:date # 日期比较 +``` + +**查找何时认为特定事实成立:** +``` +S: << >> # 引用三元组作为主语 +P: +O: ? # 返回日期 +``` + +**查找被发现为错误的 facts:** +``` +S: ? # 任何引用三元组 +P: +O: ? # 具有任何值 (存在) +``` + +#### 溯源查询 + +**查找由特定来源支持的所有事实:** +``` +S: ? # 任何引用三元组 +P: +O: +``` + +**查找哪些来源支持特定事实:** +``` +S: << >> # 引用三元组作为主语 +P: +O: ? # 返回来源 IRI +``` + +#### 真实性查询 + +**查找 Person 声明为真的断言:** +``` +S: ? # 任何引用三元组 +P: +O: +``` + +**查找冲突的断言 (相同的 facts,不同的真实性):** +``` +# 第一个查询:声明为真的事实 +S: ? +P: +O: ? + +# 第二个查询:声明为假的 fact +S: ? +P: +O: ? + +# 应用程序逻辑:查找主语的交集 +``` + +**查找信任评分低于阈值的 facts:** +``` +S: ? # 任何引用三元组 +P: +O: < 0.5 # 数值比较 +``` + +### 架构 + +需要对多个组件进行重大更改: + +#### 此仓库 (trustgraph) + +- **模式原始数据类型** (`trustgraph-base/trustgraph/schema/core/primitives.py`) + - `Value` → `Term` 重命名。 + - 具有类型区分器的新的 `Term` 结构。 + - `Triple` 获得 `g` 字段以进行图上下文。 + +- **消息翻译器** (`trustgraph-base/trustgraph/messaging/translators/`) + - 更新以适应新的 `Term` 和 `Triple` 结构。 + - 用于新字段的序列化/反序列化。 + +- **网关组件** + - 处理新的 `Term` 和四元组结构。 + +- **知识核心** + - 支持四元组和重构的核心更改。 + +- **知识管理器** + - 模式更改会在此处传播。 + +- **存储层** + - Cassandra: 重新设计模式(参见“实施详细信息”)。 + - 其他后端:推迟到后续阶段。 + +- **命令行工具** + - 更新以适应新的数据结构。 + +- **REST API 文档** + - 更新 OpenAPI 规范。 + +#### 外部仓库 + +- **Python API** (此仓库) + - 更新客户端库以匹配新的结构。 + +- **TypeScript API** (单独仓库) + - 平行于 Python API 的更改。 + - 分离的发布协调。 + +- **Workbench** (单独仓库) + - 状态管理方面的重大更改。 + - 用于图上下文功能的 UI 更新。 + +### API + +#### REST API + +- 在 OpenAPI 规范中记录。 +- 需要更新以适应新的 `Term` 和 `Triple` 结构。 +- 可能需要新的端点来处理图上下文操作。 + +#### Python API (此仓库) + +- 客户端库更改以匹配新的原始数据类型。 +- `Term` (以前是 `Value`) 和 `Triple` 的破坏性更改。 + +#### TypeScript API (单独仓库) + +- 与 Python API 平行的更改。 +- 分离的发布协调。 + +#### Workbench (单独仓库) + +- 状态管理方面的重大更改。 +- 用于图上下文功能的 UI 更新。 + +### 实施细节 + +#### 分阶段的存储实施 + +存在多个图存储后端(Cassandra、Neo4j 等)。 +实施将分阶段进行: + +1. **第一阶段:Cassandra** + - 在完全控制的后端上验证设计,然后再承诺在所有存储系统中的实现。 + +2. **第二阶段+:其他后端** + - 在后续阶段实施 Neo4j 和其他存储系统。 + +此方法通过在所有系统上承诺实现之前,在完全受控的后端上验证设计,从而降低风险。 + +#### `Value` → `Term` 重命名 + +`Value` 类将被重命名为 `Term`。 这会影响代码库中的约 78 个文件。 +重命名充当强制函数:任何仍然使用 `Value` 的代码都将立即显示为需要审查/更新以获得 2.0 兼容性。 + +## 安全注意事项 + +命名图不是安全功能。 用户和集合仍然是安全边界。 命名图纯粹用于数据组织和重构支持。 + +## 性能注意事项 + +- 引用三元组会增加嵌套深度,这可能会影响查询性能。 +- 需要命名图索引策略以实现高效的范围查询。 +- Cassandra 模式设计需要适应四元组存储。 + +### 向量存储边界 + +向量存储始终只引用 IRI: +- 永远不要边(引用三元组)。 +- 永远不要原始值。 +- 永远不要匿名节点。 + +这使向量存储保持简单 - 它处理命名实体语义相似性。 图结构处理关系、重构和元数据。 引用三元组和命名图不会使向量操作复杂化。 + +## 测试策略 + +使用现有的测试策略。 由于这是一个破坏性版本,因此需要重点关注端到端测试套件,以验证新的结构是否在所有组件中都正确工作。 + +## 迁移计划 + +- 2.0 是一个破坏性版本;不需要向后兼容性。 +- 现有数据可能需要迁移到新的模式(基于最终设计的确定)。 +- 考虑迁移工具,用于转换现有三元组。 + +## 开放问题 + +- **匿名节点**: 确认有限支持。 可能需要决定采用 Skolem 化策略(在加载时生成 IRI,或保留匿名节点 ID)。 +- **查询语法**: 引用三元组在查询中的具体语法是什么? 需要定义查询 API。 +- **谓词词汇表**: 已解决。 允许任何有效的 RDF 谓词,包括自定义的用户定义的谓词。 尽量减少对任何事情的锁定(例如,在某些地方使用 `rdfs:label`)。 策略:除非绝对必要,否则避免锁定任何内容。 +- **向量存储影响**: 已解决。 向量存储始终仅指向 IRI - 永远不要边、原始值或匿名节点。 引用三元组和重构不会影响向量存储。 + +## 参考文献 + +- [RDF 1.2 概念](https://www.w3.org/TR/rdf12-concepts/) +- [RDF-star 和 SPARQL-star](https://w3c.github.io/rdf-star/) +- [RDF 数据集](https://www.w3.org/TR/rdf11-concepts/#section-dataset) diff --git a/docs/tech-specs/graphql-query.ar.md b/docs/tech-specs/graphql-query.ar.md new file mode 100644 index 00000000..841fb643 --- /dev/null +++ b/docs/tech-specs/graphql-query.ar.md @@ -0,0 +1,531 @@ +--- +layout: default +title: "GraphQL Query Technical Specification" +parent: "Arabic (Beta)" +--- + +# GraphQL Query 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 + +<<<<<<< HEAD +تصف هذه المواصفات تنفيذ واجهة استعلام GraphQL للبيانات المنظمة المخزنة في Apache Cassandra. بناءً على إمكانات البيانات المنظمة الموضحة في المواصفات الموجودة في structured-data.md، يوضح هذا المستند كيفية تنفيذ استعلامات GraphQL على جداول Cassandra التي تحتوي على كائنات منظمة مستخرجة ومُدخلة. + +سيوفر خدمة استعلام GraphQL واجهة مرنة وآمنة من حيث النوع للاستعلام عن البيانات المنظمة المخزنة في Cassandra. ستتكيف ديناميكيًا مع تغييرات المخطط، وتدعم الاستعلامات المعقدة بما في ذلك العلاقات بين الكائنات، وتتكامل بسلاسة مع بنية TrustGraph الحالية القائمة على الرسائل. + +## الأهداف + +**دعم المخططات الديناميكي**: التكيف تلقائيًا مع تغييرات المخطط في التكوين دون إعادة تشغيل الخدمة. +**الامتثال لمعايير GraphQL**: توفير واجهة GraphQL قياسية متوافقة مع أدوات GraphQL والعملاء الحاليين. +**استعلامات Cassandra فعالة**: ترجمة استعلامات GraphQL إلى استعلامات Cassandra CQL فعالة مع احترام مفاتيح التقسيم والفهارس. +**حل العلاقات**: دعم محللات الحقول GraphQL للعلاقات بين أنواع الكائنات المختلفة. +**الأمان من حيث النوع**: ضمان تنفيذ الاستعلامات وتوليد الاستجابات بطريقة آمنة من حيث النوع بناءً على تعريفات المخطط. +**أداء قابل للتوسع**: التعامل مع الاستعلامات المتزامنة بكفاءة مع تجميع الاتصالات وتحسين الاستعلامات المناسب. +**التكامل مع الطلبات والاستجابات**: الحفاظ على التوافق مع نمط الطلب/الاستجابة القائم على Pulsar في TrustGraph. +**معالجة الأخطاء**: توفير تقارير أخطاء شاملة لمطابقة المخططات وأخطاء الاستعلامات ومشكلات التحقق من صحة البيانات. + +## الخلفية + +تقوم عملية تخزين البيانات المنظمة (trustgraph-flow/trustgraph/storage/objects/cassandra/) بكتابة الكائنات إلى جداول Cassandra بناءً على تعريفات المخطط المخزنة في نظام تكوين TrustGraph. تستخدم هذه الجداول هيكل مفتاح تقسيم مركب مع مفاتيح أولية محددة في المجموعة ومحددة في المخطط، مما يتيح استعلامات فعالة داخل المجموعات. + +القيود الحالية التي تعالجها هذه المواصفات: +لا توجد واجهة استعلام للبيانات المنظمة المخزنة في Cassandra. +عدم القدرة على الاستفادة من إمكانات الاستعلام القوية لـ GraphQL للبيانات المنظمة. +عدم وجود دعم لتتبع العلاقات بين الكائنات ذات الصلة. +عدم وجود لغة استعلام موحدة للوصول إلى البيانات المنظمة. + +ستقوم خدمة استعلام GraphQL بسد هذه الفجوات من خلال: +توفير واجهة GraphQL قياسية للاستعلام عن جداول Cassandra. +توليد مخططات GraphQL ديناميكيًا من تكوين TrustGraph. +ترجمة استعلامات GraphQL بكفاءة إلى Cassandra CQL. +دعم حل العلاقات من خلال محللات الحقول. + +## التصميم الفني + +### البنية + +سيتم تنفيذ خدمة استعلام GraphQL كمعالج TrustGraph جديد باتباع الأنماط الراسخة: + +**الموقع**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**المكونات الرئيسية**: + +1. **معالج خدمة استعلام GraphQL**: + يرث من الفئة الأساسية FlowProcessor. + ينفذ نمط الطلب/الاستجابة المشابه لخدمات الاستعلام الحالية. + يراقب التكوين بحثًا عن تحديثات المخطط. + يحافظ على تزامن مخطط GraphQL مع التكوين. + +2. **مولد المخططات الديناميكي**: + يحول تعريفات TrustGraph RowSchema إلى أنواع GraphQL. + ينشئ أنواع كائنات GraphQL مع تعريفات الحقول المناسبة. + يولد نوع الاستعلام الجذر مع محللات قائمة على المجموعة. + يقوم بتحديث مخطط GraphQL عند حدوث تغييرات في التكوين. + +3. **منفذ الاستعلام**: + يحلل استعلامات GraphQL الواردة باستخدام مكتبة Strawberry. + يتحقق من صحة الاستعلامات مقابل المخطط الحالي. + ينفذ الاستعلامات ويعيد استجابات منظمة. + يتعامل مع الأخطاء بأمان مع رسائل خطأ مفصلة. + +4. **مترجم استعلامات Cassandra**: + يحول عمليات اختيار GraphQL إلى استعلامات CQL. + يحسن الاستعلامات بناءً على الفهارس ومفاتيح التقسيم المتاحة. + يتعامل مع التصفية والتقسيم والترتيب. + يدير تجميع الاتصالات ودورة حياة الجلسة. + +5. **محلل العلاقات**: + ينفذ محللات الحقول للعلاقات بين الكائنات. + يقوم بتحميل دفعات بكفاءة لتجنب استعلامات N+1. + يقوم بتخزين العلاقات التي تم حلها في سياق الطلب. + يدعم كل من تتبع العلاقات الأمامية والعكسية. + +### مراقبة مخطط التكوين + +ستقوم الخدمة بتسجيل معالج تكوين لتلقي تحديثات المخطط: +======= +This specification describes the implementation of a GraphQL query interface for TrustGraph's structured data storage in Apache Cassandra. Building upon the structured data capabilities outlined in the structured-data.md specification, this document details how GraphQL queries will be executed against Cassandra tables containing extracted and ingested structured objects. + +The GraphQL query service will provide a flexible, type-safe interface for querying structured data stored in Cassandra. It will dynamically adapt to schema changes, support complex queries including relationships between objects, and integrate seamlessly with TrustGraph's existing message-based architecture. + +## Goals + +**Dynamic Schema Support**: Automatically adapt to schema changes in configuration without service restarts +**GraphQL Standards Compliance**: Provide a standard GraphQL interface compatible with existing GraphQL tooling and clients +**Efficient Cassandra Queries**: Translate GraphQL queries into efficient Cassandra CQL queries respecting partition keys and indexes +**Relationship Resolution**: Support GraphQL field resolvers for relationships between different object types +**Type Safety**: Ensure type-safe query execution and response generation based on schema definitions +**Scalable Performance**: Handle concurrent queries efficiently with proper connection pooling and query optimization +**Request/Response Integration**: Maintain compatibility with TrustGraph's Pulsar-based request/response pattern +**Error Handling**: Provide comprehensive error reporting for schema mismatches, query errors, and data validation issues + +## Background + +The structured data storage implementation (trustgraph-flow/trustgraph/storage/objects/cassandra/) writes objects to Cassandra tables based on schema definitions stored in TrustGraph's configuration system. These tables use a composite partition key structure with collection and schema-defined primary keys, enabling efficient queries within collections. + +Current limitations that this specification addresses: +No query interface for the structured data stored in Cassandra +Inability to leverage GraphQL's powerful query capabilities for structured data +Missing support for relationship traversal between related objects +Lack of a standardized query language for structured data access + +The GraphQL query service will bridge these gaps by: +Providing a standard GraphQL interface for querying Cassandra tables +Dynamically generating GraphQL schemas from TrustGraph configuration +Efficiently translating GraphQL queries to Cassandra CQL +Supporting relationship resolution through field resolvers + +## Technical Design + +### Architecture + +The GraphQL query service will be implemented as a new TrustGraph flow processor following established patterns: + +**Module Location**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**Key Components**: + +1. **GraphQL Query Service Processor** + Extends base FlowProcessor class + Implements request/response pattern similar to existing query services + Monitors configuration for schema updates + Maintains GraphQL schema synchronized with configuration + +2. **Dynamic Schema Generator** + Converts TrustGraph RowSchema definitions to GraphQL types + Creates GraphQL object types with proper field definitions + Generates root Query type with collection-based resolvers + Updates GraphQL schema when configuration changes + +3. **Query Executor** + Parses incoming GraphQL queries using Strawberry library + Validates queries against current schema + Executes queries and returns structured responses + Handles errors gracefully with detailed error messages + +4. **Cassandra Query Translator** + Converts GraphQL selections to CQL queries + Optimizes queries based on available indexes and partition keys + Handles filtering, pagination, and sorting + Manages connection pooling and session lifecycle + +5. **Relationship Resolver** + Implements field resolvers for object relationships + Performs efficient batch loading to avoid N+1 queries + Caches resolved relationships within request context + Supports both forward and reverse relationship traversal + +### Configuration Schema Monitoring + +The service will register a configuration handler to receive schema updates: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +self.register_config_handler(self.on_schema_config) +``` + +عندما تتغير المخططات: +1. تحليل تعريفات المخططات الجديدة من التكوين. +2. إعادة إنشاء أنواع GraphQL والمحللات. +<<<<<<< HEAD +3. تحديث المخطط القابل للتنفيذ. +======= +3. تحديث المخطط التنفيذي. +>>>>>>> 82edf2d (New md files from RunPod) +4. مسح أي ذاكرة تخزين مؤقت تعتمد على المخطط. + +### توليد مخطط GraphQL + +لكل RowSchema في التكوين، قم بإنشاء: + +1. **نوع كائن GraphQL**: +<<<<<<< HEAD + مطابقة أنواع الحقول (string → String, integer → Int, float → Float, boolean → Boolean). +======= + تعيين أنواع الحقول (string → String, integer → Int, float → Float, boolean → Boolean). +>>>>>>> 82edf2d (New md files from RunPod) + وضع علامة على الحقول المطلوبة على أنها غير قابلة للقيم الفارغة في GraphQL. + إضافة أوصاف الحقول من المخطط. + +2. **حقول الاستعلام الجذرية**: + استعلام المجموعة (مثل `customers`، `transactions`). + وسائط التصفية بناءً على الحقول المفهرسة. + دعم التقسيم (limit, offset). + خيارات الفرز للحقول القابلة للفرز. + +3. **حقول العلاقات**: + تحديد علاقات المفاتيح الخارجية من المخطط. + إنشاء محللات حقول للكائنات ذات الصلة. + دعم كل من علاقات الكائنات الفردية وقوائم الكائنات. + +### تدفق تنفيذ الاستعلام + +1. **استقبال الطلب**: + استقبال ObjectsQueryRequest من Pulsar. + استخراج سلسلة استعلام GraphQL والمتغيرات. + تحديد سياق المستخدم والمجموعة. + +2. **التحقق من صحة الاستعلام**: + تحليل استعلام GraphQL باستخدام Strawberry. + التحقق من الصحة مقابل المخطط الحالي. + التحقق من عمليات اختيار الحقول وأنواع الوسائط. + +3. **توليد CQL**: + تحليل عمليات اختيار GraphQL. + إنشاء استعلام CQL مع عبارات WHERE المناسبة. + تضمين المجموعة في مفتاح التقسيم. + تطبيق عوامل التصفية بناءً على وسائط GraphQL. + +4. **تنفيذ الاستعلام**: + تنفيذ استعلام CQL مقابل Cassandra. +<<<<<<< HEAD + مطابقة النتائج مع هيكل استجابة GraphQL. +======= + تعيين النتائج إلى هيكل استجابة GraphQL. +>>>>>>> 82edf2d (New md files from RunPod) + حل أي حقول علاقات. + تنسيق الاستجابة وفقًا لمواصفات GraphQL. + +5. **تسليم الاستجابة**: + إنشاء ObjectsQueryResponse مع النتائج. + تضمين أي أخطاء في التنفيذ. + إرسال الاستجابة عبر Pulsar بمعرف الارتباط. + +### نماذج البيانات + +<<<<<<< HEAD +> **ملاحظة**: يوجد مخطط StructuredQueryRequest/Response موجود في `trustgraph-base/trustgraph/schema/services/structured_query.py`. ومع ذلك، فإنه يفتقر إلى حقول مهمة (المستخدم، المجموعة) ويستخدم أنواعًا دون المستوى الأمثل. تمثل المخططات أدناه التطور الموصى به، والتي يجب إما أن تحل محل المخططات الحالية أو يتم إنشاؤها كأنواع ObjectsQueryRequest/Response جديدة. +======= +> **ملاحظة**: يوجد مخطط StructuredQueryRequest/Response موجود في `trustgraph-base/trustgraph/schema/services/structured_query.py`. ومع ذلك، فإنه يفتقر إلى حقول مهمة (المستخدم، المجموعة) ويستخدم أنواعًا دون المستوى الأمثل. تمثل المخططات أدناه التطور الموصى به، والتي يجب إما استبدال المخططات الموجودة بها أو إنشاؤها كأنواع ObjectsQueryRequest/Response جديدة. +>>>>>>> 82edf2d (New md files from RunPod) + +#### مخطط الطلب (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +**السبب وراء التغييرات من طلب الاستعلام المنظم الحالي:** +تمت إضافة الحقول `user` و `collection` لمطابقة نمط خدمات الاستعلام الأخرى. +هذه الحقول ضرورية لتحديد مساحة مفاتيح Cassandra والمجموعة. +تظل المتغيرات كـ Map(String()) في الوقت الحالي، ولكن من الأفضل أن تدعم جميع أنواع JSON. + +#### مخطط الاستجابة (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**الأساس المنطقي للتغييرات من الاستجابة المنظمة للاستعلامات الحالية:** +التمييز بين أخطاء النظام (`error`) وأخطاء GraphQL (`errors`). +استخدام كائنات GraphQLError منظمة بدلاً من مصفوفة سلسلة. +إضافة حقل `extensions` للامتثال لمواصفات GraphQL. +الحفاظ على البيانات كسلسلة JSON للتوافق، على الرغم من أن الأنواع الأصلية ستكون مفضلة. + +### تحسين استعلامات Cassandra + +ستقوم الخدمة بتحسين استعلامات Cassandra عن طريق: + +1. **احترام مفاتيح التقسيم:** + تضمين المجموعة دائمًا في الاستعلامات. + استخدام المفاتيح الأساسية المعرفة في المخطط بكفاءة. + تجنب عمليات المسح الكاملة للجدول. + +2. **الاستفادة من الفهارس:** + استخدام الفهارس الثانوية للتصفية. + دمج عوامل التصفية المتعددة كلما أمكن ذلك. +<<<<<<< HEAD + التحذير عندما قد تكون الاستعلامات غير فعالة. + +3. **التحميل الدفعي:** + جمع استعلامات العلاقات. +======= + إصدار تحذير عندما قد تكون الاستعلامات غير فعالة. + +3. **التحميل الدفعي:** + تجميع استعلامات العلاقات. +>>>>>>> 82edf2d (New md files from RunPod) + تنفيذها على دفعات لتقليل عدد الرحلات ذهابًا وإيابًا. + تخزين النتائج مؤقتًا داخل سياق الطلب. + +4. **إدارة الاتصالات:** + الحفاظ على جلسات Cassandra مستمرة. + استخدام تجميع الاتصالات. +<<<<<<< HEAD + التعامل مع إعادة الاتصال في حالة حدوث أخطاء. +======= + التعامل مع إعادة الاتصال في حالة حدوث أعطال. +>>>>>>> 82edf2d (New md files from RunPod) + +### أمثلة لاستعلامات GraphQL + +#### استعلام بسيط للمجموعة +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### استعلام مع العلاقات +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### استعلام مُقسّم إلى صفحات +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### الاعتمادات الخاصة بالتنفيذ + +**Strawberry GraphQL**: لتعريف مخطط GraphQL وتنفيذ الاستعلامات. +**Cassandra Driver**: للاتصال بقاعدة البيانات (يتم استخدامه بالفعل في وحدة التخزين). +**TrustGraph Base**: لـ FlowProcessor وتعريفات المخططات. +**Configuration System**: لمراقبة المخططات وتحديثها. + +### واجهة سطر الأوامر + +سيوفر الخدمة أمر سطر أوامر: `kg-query-objects-graphql-cassandra` + +الوسائط: +`--cassandra-host`: نقطة اتصال مجموعة Cassandra. +`--cassandra-username`: اسم مستخدم المصادقة. +`--cassandra-password`: كلمة مرور المصادقة. +`--config-type`: نوع التكوين للمخططات (افتراضي: "schema"). +وسائط FlowProcessor القياسية (تكوين Pulsar، إلخ). + +## تكامل واجهة برمجة التطبيقات + +### مواضيع Pulsar + +**موضوع الإدخال**: `objects-graphql-query-request` +المخطط: ObjectsQueryRequest +يتلقى استعلامات GraphQL من خدمات البوابة. + +**موضوع الإخراج**: `objects-graphql-query-response` +المخطط: ObjectsQueryResponse +يُرجع نتائج الاستعلام والأخطاء. + +### تكامل البوابة + +ستحتاج البوابة والبوابة العكسية إلى نقاط نهاية لـ: +1. قبول استعلامات GraphQL من العملاء. +2. توجيهها إلى خدمة الاستعلام عبر Pulsar. +3. إرجاع الاستجابات إلى العملاء. +<<<<<<< HEAD +4. دعم استعلامات GraphQL الخاصة بالتحقق من المخطط. +======= +4. دعم استعلامات GraphQL الخاصة بالتحقق (introspection). +>>>>>>> 82edf2d (New md files from RunPod) + +### تكامل أداة الوكيل + +ستتيح فئة أداة وكيل جديدة: +توليد استعلامات GraphQL من اللغة الطبيعية. +تنفيذ استعلامات GraphQL مباشرة. +<<<<<<< HEAD +تفسير وتنسيق النتائج. +التكامل مع مسارات قرار الوكيل. +======= +تفسير النتائج وتنسيقها. +التكامل مع تدفقات قرار الوكيل. +>>>>>>> 82edf2d (New md files from RunPod) + +## اعتبارات الأمان + +**تحديد عمق الاستعلام**: منع الاستعلامات المتداخلة بعمق والتي يمكن أن تسبب مشاكل في الأداء. +<<<<<<< HEAD +**تحليل تعقيد الاستعلام**: الحد من تعقيد الاستعلام لمنع استنفاد الموارد. +**أذونات على مستوى الحقل**: دعم مستقبلي للتحكم في الوصول على مستوى الحقل بناءً على أدوار المستخدم. +**تنظيف الإدخال**: التحقق من صحة وتنظيف جميع مدخلات الاستعلام لمنع هجمات الحقن. +**تحديد المعدل**: تنفيذ تحديد معدل الاستعلام لكل مستخدم/مجموعة. +======= +**تحليل تعقيد الاستعلام**: تحديد تعقيد الاستعلام لمنع استنفاد الموارد. +**أذونات على مستوى الحقل**: دعم مستقبلي للتحكم في الوصول على مستوى الحقل بناءً على أدوار المستخدم. +**تنظيف الإدخال**: التحقق من صحة وتنظيف جميع مدخلات الاستعلام لمنع هجمات الحقن. +**تحديد المعدل**: تطبيق تحديد معدل الاستعلام لكل مستخدم/مجموعة. +>>>>>>> 82edf2d (New md files from RunPod) + +## اعتبارات الأداء + +**تخطيط الاستعلام**: تحليل الاستعلامات قبل التنفيذ لتحسين توليد CQL. +**تخزين النتائج مؤقتًا**: ضع في اعتبارك تخزين البيانات التي يتم الوصول إليها بشكل متكرر مؤقتًا على مستوى محلل الحقل. +<<<<<<< HEAD +**تجميع الاتصالات**: حافظ على مجموعات اتصالات فعالة إلى Cassandra. +======= +**تجميع الاتصالات**: حافظ على تجمعات اتصالات فعالة إلى Cassandra. +>>>>>>> 82edf2d (New md files from RunPod) +**العمليات الدفعية**: اجمع بين استعلامات متعددة كلما أمكن ذلك لتقليل زمن الوصول. +**المراقبة**: تتبع مقاييس أداء الاستعلام لتحسين الأداء. + +## استراتيجية الاختبار + +### اختبارات الوحدة +توليد المخططات من تعريفات RowSchema +تحليل وتدقيق استعلامات GraphQL +منطق توليد استعلامات CQL +تطبيقات محللات الحقول + +### اختبارات العقود +الامتثال لعقد رسائل Pulsar +صلاحية مخطط GraphQL +التحقق من تنسيق الاستجابة +التحقق من صحة هيكل الأخطاء + +### اختبارات التكامل +<<<<<<< HEAD +تنفيذ استعلامات شاملة مقابل نسخة اختبار Cassandra +======= +تنفيذ الاستعلامات من طرف إلى طرف مقابل مثيل Cassandra للاختبار +>>>>>>> 82edf2d (New md files from RunPod) +معالجة تحديثات المخططات +حل العلاقات +الترقيم والتصفية +سيناريوهات الأخطاء + +### اختبارات الأداء +معدل نقل البيانات للاستعلامات تحت الضغط +وقت الاستجابة لتعقيدات الاستعلامات المختلفة +استخدام الذاكرة مع مجموعات نتائج كبيرة +كفاءة مجموعة الاتصالات + +## خطة الترحيل + +لا يلزم إجراء أي ترحيل نظرًا لأن هذا ميزة جديدة. ستقوم الخدمة بما يلي: +1. قراءة المخططات الموجودة من التكوين +2. الاتصال بجداول Cassandra الموجودة التي تم إنشاؤها بواسطة وحدة التخزين +3. البدء في قبول الاستعلامات على الفور عند النشر + +## الجدول الزمني + +الأسبوع 1-2: تنفيذ الخدمة الأساسية وتوليد المخططات +الأسبوع 3: تنفيذ الاستعلامات وترجمة CQL +الأسبوع 4: حل العلاقات والتحسين +الأسبوع 5: الاختبار وضبط الأداء +الأسبوع 6: التكامل مع البوابة والتوثيق + +## أسئلة مفتوحة + +1. **تطور المخططات**: كيف يجب أن تتعامل الخدمة مع الاستعلامات أثناء عمليات انتقال المخططات؟ + خيار: وضع الاستعلامات في قائمة انتظار أثناء تحديثات المخططات + خيار: دعم إصدارات متعددة من المخططات في نفس الوقت + +2. **استراتيجية التخزين المؤقت**: هل يجب تخزين نتائج الاستعلامات مؤقتًا؟ + ضع في اعتبارك: انتهاء الصلاحية بناءً على الوقت + ضع في اعتبارك: الإبطال بناءً على الأحداث + +3. **دعم التجميع**: هل يجب أن تدعم الخدمة تجميع GraphQL لدمجها مع مصادر بيانات أخرى؟ +<<<<<<< HEAD + سيمكن ذلك من إجراء استعلامات موحدة عبر البيانات المهيكلة والبيانات الرسومية +======= + سيمكن ذلك من الاستعلامات الموحدة عبر البيانات المهيكلة والبيانات الرسومية +>>>>>>> 82edf2d (New md files from RunPod) + +4. **دعم الاشتراكات**: هل يجب أن تدعم الخدمة اشتراكات GraphQL للتحديثات في الوقت الفعلي؟ + سيتطلب ذلك دعم WebSocket في البوابة + +<<<<<<< HEAD +5. **أنواع قياسية مخصصة**: هل يجب دعم الأنواع القياسية المخصصة لأنواع البيانات الخاصة بالمجال؟ +======= +5. **الأنواع العددية المخصصة**: هل يجب دعم الأنواع العددية المخصصة لأنواع البيانات الخاصة بالمجال؟ +>>>>>>> 82edf2d (New md files from RunPod) + أمثلة: DateTime، UUID، حقول JSON + +## المراجع + +المواصفات الفنية للبيانات المهيكلة: `docs/tech-specs/structured-data.md` +<<<<<<< HEAD +وثائق GraphQL Strawberry: https://strawberry.rocks/ +======= +وثائق Strawberry GraphQL: https://strawberry.rocks/ +>>>>>>> 82edf2d (New md files from RunPod) +مواصفات GraphQL: https://spec.graphql.org/ +مرجع Apache Cassandra CQL: https://cassandra.apache.org/doc/stable/cassandra/cql/ +وثائق معالج التدفق TrustGraph: وثائق داخلية diff --git a/docs/tech-specs/graphql-query.es.md b/docs/tech-specs/graphql-query.es.md new file mode 100644 index 00000000..0bf36f40 --- /dev/null +++ b/docs/tech-specs/graphql-query.es.md @@ -0,0 +1,467 @@ +--- +layout: default +title: "Especificación Técnica de la Consulta GraphQL" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de la Consulta GraphQL + +> **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 la implementación de una interfaz de consulta GraphQL para el almacenamiento de datos estructurados de TrustGraph en Apache Cassandra. Basándose en las capacidades de datos estructurados descritas en la especificación structured-data.md, este documento detalla cómo se ejecutarán las consultas GraphQL contra las tablas de Cassandra que contienen objetos estructurados extraídos e importados. + +<<<<<<< HEAD +El servicio de consulta GraphQL proporcionará una interfaz flexible y segura para consultar datos estructurados almacenados en Cassandra. Se adaptará dinámicamente a los cambios de esquema, admitirá consultas complejas que incluyan relaciones entre objetos y se integrará perfectamente con la arquitectura existente basada en mensajes de TrustGraph. +======= +El servicio de consulta GraphQL proporcionará una interfaz flexible y segura para consultar datos estructurados almacenados en Cassandra. Se adaptará dinámicamente a los cambios de esquema, admitirá consultas complejas, incluidas las relaciones entre objetos, y se integrará perfectamente con la arquitectura existente basada en mensajes de TrustGraph. +>>>>>>> 82edf2d (New md files from RunPod) + +## Objetivos + +**Soporte de Esquema Dinámico**: Adaptación automática a los cambios de esquema en la configuración sin reiniciar el servicio. +**Cumplimiento de los Estándares GraphQL**: Proporcionar una interfaz GraphQL estándar compatible con las herramientas y clientes GraphQL existentes. +<<<<<<< HEAD +**Consultas Eficientes de Cassandra**: Traducir consultas GraphQL en consultas CQL eficientes de Cassandra, respetando las claves de partición y los índices. +**Resolución de Relaciones**: Soporte para resolutores de campos GraphQL para relaciones entre diferentes tipos de objetos. +**Seguridad de Tipos**: Garantizar la ejecución de consultas y la generación de respuestas seguras, basadas en definiciones de esquema. +**Rendimiento Escalable**: Manejar consultas concurrentes de manera eficiente con un grupo de conexiones y optimización de consultas adecuados. +**Integración de Solicitud/Respuesta**: Mantener la compatibilidad con el patrón de solicitud/respuesta basado en Pulsar de TrustGraph. +**Manejo de Errores**: Proporcionar informes de errores completos para discrepancias de esquema, errores de consulta y problemas de validación de datos. + +## Antecedentes + +La implementación del almacenamiento de datos estructurados (trustgraph-flow/trustgraph/storage/objects/cassandra/) escribe objetos en tablas de Cassandra según las definiciones de esquema almacenadas en el sistema de configuración de TrustGraph. Estas tablas utilizan una estructura de clave de partición compuesta con claves primarias definidas por colección y esquema, lo que permite consultas eficientes dentro de las colecciones. + +Limitaciones actuales que esta especificación aborda: +No hay una interfaz de consulta para los datos estructurados almacenados en Cassandra. +Incapacidad de aprovechar las poderosas capacidades de consulta de GraphQL para datos estructurados. +======= +**Consultas Eficientes de Cassandra**: Traducir las consultas GraphQL en consultas CQL eficientes de Cassandra, respetando las claves de partición y los índices. +**Resolución de Relaciones**: Soporte para los resolvedores de campos GraphQL para las relaciones entre diferentes tipos de objetos. +**Seguridad de Tipos**: Garantizar la ejecución de consultas y la generación de respuestas seguras, basadas en las definiciones del esquema. +**Rendimiento Escalable**: Manejar las consultas concurrentes de manera eficiente con un correcto agrupamiento de conexiones y optimización de consultas. +**Integración de Solicitud/Respuesta**: Mantener la compatibilidad con el patrón de solicitud/respuesta basado en Pulsar de TrustGraph. +**Manejo de Errores**: Proporcionar informes de errores completos para las discrepancias del esquema, los errores de consulta y los problemas de validación de datos. + +## Antecedentes + +La implementación del almacenamiento de datos estructurados (trustgraph-flow/trustgraph/storage/objects/cassandra/) escribe objetos en tablas de Cassandra según las definiciones de esquema almacenadas en el sistema de configuración de TrustGraph. Estas tablas utilizan una estructura de clave de partición compuesta con claves primarias definidas por la colección y el esquema, lo que permite consultas eficientes dentro de las colecciones. + +Limitaciones actuales que esta especificación aborda: +No hay una interfaz de consulta para los datos estructurados almacenados en Cassandra. +Incapacidad de aprovechar las potentes capacidades de consulta de GraphQL para los datos estructurados. +>>>>>>> 82edf2d (New md files from RunPod) +Falta de soporte para la navegación de relaciones entre objetos relacionados. +Falta de un lenguaje de consulta estandarizado para el acceso a datos estructurados. + +El servicio de consulta GraphQL cerrará estas brechas al: +Proporcionar una interfaz GraphQL estándar para consultar tablas de Cassandra. +Generar dinámicamente esquemas GraphQL a partir de la configuración de TrustGraph. +<<<<<<< HEAD +Traducir de manera eficiente las consultas GraphQL a CQL de Cassandra. +Soporte para la resolución de relaciones a través de resolutores de campos. +======= +Traducir de forma eficiente las consultas GraphQL a CQL de Cassandra. +Soporte para la resolución de relaciones a través de resolvedores de campos. +>>>>>>> 82edf2d (New md files from RunPod) + +## Diseño Técnico + +### Arquitectura + +El servicio de consulta GraphQL se implementará como un nuevo procesador de flujo de TrustGraph, siguiendo patrones establecidos: + +**Ubicación del Módulo**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**Componentes Clave**: + +1. **Procesador del Servicio de Consulta GraphQL** + Extiende la clase base FlowProcessor. + Implementa un patrón de solicitud/respuesta similar a los servicios de consulta existentes. + Supervisa la configuración para las actualizaciones del esquema. + Mantiene el esquema GraphQL sincronizado con la configuración. + +2. **Generador de Esquema Dinámico** + Convierte las definiciones de esquema de TrustGraph RowSchema en tipos GraphQL. + Crea tipos de objetos GraphQL con definiciones de campos adecuadas. +<<<<<<< HEAD + Genera el tipo de consulta raíz con resolutores basados en colecciones. +======= + Genera el tipo de consulta raíz con resolvedores basados en colecciones. +>>>>>>> 82edf2d (New md files from RunPod) + Actualiza el esquema GraphQL cuando cambia la configuración. + +3. **Ejecutor de Consultas** + Analiza las consultas GraphQL entrantes utilizando la biblioteca Strawberry. + Valida las consultas contra el esquema actual. + Ejecuta las consultas y devuelve respuestas estructuradas. + Maneja los errores con elegancia con mensajes de error detallados. + +4. **Traductor de Consultas de Cassandra** + Convierte las selecciones GraphQL en consultas CQL. + Optimiza las consultas según los índices y las claves de partición disponibles. + Maneja el filtrado, la paginación y la clasificación. +<<<<<<< HEAD + Administra el grupo de conexiones y el ciclo de vida de la sesión. + +5. **Resolutor de Relaciones** + Implementa resolutores de campos para relaciones de objetos. +======= + Administra el agrupamiento de conexiones y el ciclo de vida de la sesión. + +5. **Resolvedor de Relaciones** + Implementa resolvedores de campos para las relaciones de objetos. +>>>>>>> 82edf2d (New md files from RunPod) + Realiza una carga por lotes eficiente para evitar consultas N+1. + Almacena en caché las relaciones resueltas dentro del contexto de la solicitud. + Admite la navegación de relaciones tanto directa como inversa. + +### Monitoreo del Esquema de Configuración + +<<<<<<< HEAD +El servicio se registrará con un controlador de configuración para recibir actualizaciones de esquema: +======= +El servicio se registrará con un controlador de configuración para recibir actualizaciones del esquema: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +self.register_config_handler(self.on_schema_config) +``` + +Cuando los esquemas cambian: +1. Analizar las nuevas definiciones de esquema desde la configuración. +2. Regenerar los tipos y resolutores de GraphQL. +3. Actualizar el esquema ejecutable. +4. Limpiar cualquier caché dependiente del esquema. + +### Generación de Esquema GraphQL + +Para cada RowSchema en la configuración, generar: + +1. **Tipo de Objeto GraphQL**: + Mapear tipos de campo (string → String, integer → Int, float → Float, boolean → Boolean). + Marcar los campos obligatorios como no anulables en GraphQL. + Agregar descripciones de campo desde el esquema. + +2. **Campos de Consulta de Nivel Superior**: + Consulta de colección (por ejemplo, `customers`, `transactions`). + Argumentos de filtrado basados en campos indexados. + Soporte de paginación (límite, desplazamiento). + Opciones de ordenamiento para campos ordenables. + +3. **Campos de Relación**: + Identificar relaciones de clave externa desde el esquema. + Crear resolutores de campo para objetos relacionados. + Soporte tanto para relaciones de objeto único como para listas. + +### Flujo de Ejecución de Consulta + +1. **Recepción de Solicitud**: + Recibir ObjectsQueryRequest de Pulsar. + Extraer la cadena de consulta GraphQL y las variables. + Identificar el contexto de usuario y colección. + +2. **Validación de Consulta**: + Analizar la consulta GraphQL utilizando Strawberry. + Validar contra el esquema actual. + Comprobar las selecciones de campo y los tipos de argumentos. + +3. **Generación de CQL**: + Analizar las selecciones de GraphQL. + Construir la consulta CQL con las cláusulas WHERE adecuadas. + Incluir la colección en la clave de partición. + Aplicar filtros basados en los argumentos de GraphQL. + +4. **Ejecución de Consulta**: + Ejecutar la consulta CQL contra Cassandra. + Mapear los resultados a la estructura de respuesta de GraphQL. + Resolver cualquier campo de relación. + Formatear la respuesta de acuerdo con la especificación de GraphQL. + +5. **Entrega de Respuesta**: + Crear una respuesta ObjectsQueryResponse con los resultados. + Incluir cualquier error de ejecución. + Enviar la respuesta a través de Pulsar con el ID de correlación. + +### Modelos de Datos + +<<<<<<< HEAD +> **Nota**: Existe un esquema existente de StructuredQueryRequest/Response en `trustgraph-base/trustgraph/schema/services/structured_query.py`. Sin embargo, le faltan campos críticos (usuario, colección) y utiliza tipos subóptimos. Los esquemas a continuación representan la evolución recomendada, que debe reemplazar los esquemas existentes o crearse como nuevos tipos de ObjectsQueryRequest/Response. +======= +> **Nota**: Existe un esquema existente de StructuredQueryRequest/Response en `trustgraph-base/trustgraph/schema/services/structured_query.py`. Sin embargo, carece de campos críticos (usuario, colección) y utiliza tipos subóptimos. Los esquemas a continuación representan la evolución recomendada, que debe reemplazar los esquemas existentes o crearse como nuevos tipos de ObjectsQueryRequest/Response. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Esquema de Solicitud (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +<<<<<<< HEAD +**Justificación de los cambios desde la solicitud de consulta estructurada existente:** +======= +**Justificación de los cambios con respecto a la solicitud de consulta estructurada existente:** +>>>>>>> 82edf2d (New md files from RunPod) +Se agregaron los campos `user` y `collection` para que coincidan con el patrón de otros servicios de consulta. +Estos campos son esenciales para identificar el espacio de claves de Cassandra y la colección. +Las variables permanecen como Map(String()) por ahora, pero idealmente deberían admitir todos los tipos JSON. + +#### Esquema de respuesta (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**Justificación de los cambios desde StructuredQueryResponse existente:** +Distingue entre errores del sistema (`error`) y errores de GraphQL (`errors`) +Utiliza objetos GraphQLError estructurados en lugar de un array de cadenas +Agrega el campo `extensions` para el cumplimiento de la especificación de GraphQL +Mantiene los datos como una cadena JSON para la compatibilidad, aunque los tipos nativos serían preferibles + +### Optimización de consultas de Cassandra + +El servicio optimizará las consultas de Cassandra mediante: + +1. **Respetando las claves de partición:** + Siempre incluir la colección en las consultas + Utilizar eficientemente las claves primarias definidas en el esquema + Evitar escaneos completos de la tabla + +2. **Aprovechando los índices:** + Utilizar índices secundarios para filtrar + Combinar múltiples filtros siempre que sea posible +<<<<<<< HEAD + Emitir una advertencia cuando las consultas puedan ser ineficientes +======= + Advertir cuando las consultas puedan ser ineficientes +>>>>>>> 82edf2d (New md files from RunPod) + +3. **Carga por lotes:** + Recopilar consultas de relaciones + Ejecutar en lotes para reducir los viajes de ida y vuelta + Almacenar en caché los resultados dentro del contexto de la solicitud + +4. **Administración de conexiones:** + Mantener sesiones de Cassandra persistentes + Utilizar un grupo de conexiones + Manejar la reconexión en caso de fallos + +### Ejemplos de consultas GraphQL + +#### Consulta simple de colección +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### Consulta con Relaciones +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### Consulta paginada +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### Dependencias de Implementación + +**Strawberry GraphQL**: Para la definición del esquema GraphQL y la ejecución de consultas. +**Cassandra Driver**: Para la conectividad con la base de datos (ya utilizado en el módulo de almacenamiento). +**TrustGraph Base**: Para FlowProcessor y definiciones de esquema. +**Sistema de Configuración**: Para la supervisión y las actualizaciones del esquema. + +### Interfaz de Línea de Comandos + +El servicio proporcionará un comando de la CLI: `kg-query-objects-graphql-cassandra` + +Argumentos: +`--cassandra-host`: Punto de contacto del clúster de Cassandra. +`--cassandra-username`: Nombre de usuario de autenticación. +`--cassandra-password`: Contraseña de autenticación. +`--config-type`: Tipo de configuración para los esquemas (por defecto: "schema"). +Argumentos estándar de FlowProcessor (configuración de Pulsar, etc.). + +## Integración de la API + +### Temas de Pulsar + +**Tema de entrada**: `objects-graphql-query-request` +Esquema: ObjectsQueryRequest +<<<<<<< HEAD +Recibe consultas GraphQL de los servicios de puerta de enlace. +======= +Recibe consultas GraphQL de los servicios de la puerta de enlace. +>>>>>>> 82edf2d (New md files from RunPod) + +**Tema de salida**: `objects-graphql-query-response` +Esquema: ObjectsQueryResponse +Devuelve los resultados de la consulta y los errores. + +### Integración de la puerta de enlace + +La puerta de enlace y la puerta de enlace inversa necesitarán puntos finales para: +1. Aceptar consultas GraphQL de los clientes. +2. Enviar a través de Pulsar al servicio de consulta. +<<<<<<< HEAD +3. Devolver respuestas a los clientes. +4. Compatibilidad con consultas de introspección de GraphQL. +======= +3. Devolver las respuestas a los clientes. +4. Compatibilidad con las consultas de introspección de GraphQL. +>>>>>>> 82edf2d (New md files from RunPod) + +### Integración de la herramienta de agente + +Una nueva clase de herramienta de agente permitirá: +Generación de consultas GraphQL a partir de lenguaje natural. +Ejecución directa de consultas GraphQL. +Interpretación y formato de resultados. +<<<<<<< HEAD +Integración con flujos de decisión de agentes. +======= +Integración con los flujos de decisión del agente. +>>>>>>> 82edf2d (New md files from RunPod) + +## Consideraciones de seguridad + +**Limitación de la profundidad de la consulta**: Prevenir consultas profundamente anidadas que puedan causar problemas de rendimiento. +**Análisis de la complejidad de la consulta**: Limitar la complejidad de la consulta para evitar el agotamiento de recursos. +**Permisos a nivel de campo**: Futuro soporte para el control de acceso a nivel de campo basado en los roles de usuario. +**Saneamiento de entrada**: Validar y limpiar todas las entradas de la consulta para prevenir ataques de inyección. +**Limitación de velocidad**: Implementar la limitación de velocidad de las consultas por usuario/colección. + +## Consideraciones de rendimiento + +**Planificación de consultas**: Analizar las consultas antes de la ejecución para optimizar la generación de CQL. +<<<<<<< HEAD +**Caché de resultados**: Considerar el almacenamiento en caché de datos accedidos con frecuencia a nivel del resolutor de campos. +**Creación de grupos de conexiones**: Mantener grupos de conexiones eficientes a Cassandra. +**Operaciones por lotes**: Combinar múltiples consultas cuando sea posible para reducir la latencia. +======= +**Caché de resultados**: Considerar el almacenamiento en caché de los datos accedidos con frecuencia a nivel del resolutor de campos. +**Creación de grupos de conexiones**: Mantener grupos de conexiones eficientes a Cassandra. +**Operaciones por lotes**: Combinar múltiples consultas siempre que sea posible para reducir la latencia. +>>>>>>> 82edf2d (New md files from RunPod) +**Supervisión**: Supervisar las métricas de rendimiento de las consultas para la optimización. + +## Estrategia de pruebas + +### Pruebas Unitarias +Generación de esquemas a partir de definiciones de RowSchema +Análisis y validación de consultas GraphQL +Lógica de generación de consultas CQL +Implementaciones de resolutores de campos + +### Pruebas de Contrato +Cumplimiento del contrato de mensajes Pulsar +Validez del esquema GraphQL +Verificación del formato de respuesta +Validación de la estructura de errores + +### Pruebas de Integración +Ejecución de consultas de extremo a extremo contra una instancia de prueba de Cassandra +Manejo de actualizaciones de esquema +Resolución de relaciones +Paginación y filtrado +Escenarios de error + +### Pruebas de Rendimiento +Rendimiento de consultas bajo carga +Tiempo de respuesta para diversas complejidades de consulta +Uso de memoria con conjuntos de resultados grandes +Eficiencia del pool de conexiones + +## Plan de Migración + +No se requiere migración, ya que se trata de una nueva funcionalidad. El servicio: +1. Leerá los esquemas existentes desde la configuración +2. Se conectará a las tablas de Cassandra existentes creadas por el módulo de almacenamiento +3. Comenzará a aceptar consultas inmediatamente después de la implementación + +## Cronograma + +Semana 1-2: Implementación del servicio principal y generación de esquemas +Semana 3: Ejecución de consultas y traducción de CQL +Semana 4: Resolución de relaciones y optimización +Semana 5: Pruebas y ajuste de rendimiento +Semana 6: Integración con la puerta de enlace y documentación + +## Preguntas Abiertas + +1. **Evolución del Esquema**: ¿Cómo debe el servicio manejar las consultas durante las transiciones de esquema? + Opción: Encolar consultas durante las actualizaciones de esquema + Opción: Compatibilidad con múltiples versiones de esquema simultáneamente + +2. **Estrategia de Caché**: ¿Deben almacenarse en caché los resultados de las consultas? + Considerar: Expiración basada en el tiempo + Considerar: Invalidación basada en eventos + +3. **Soporte de Federación**: ¿Debe el servicio admitir la federación de GraphQL para combinarlo con otras fuentes de datos? + Permitiría consultas unificadas a través de datos estructurados y de grafos + +4. **Soporte de Suscripciones**: ¿Debe el servicio admitir suscripciones de GraphQL para actualizaciones en tiempo real? + Requeriría soporte de WebSocket en la puerta de enlace + +5. **Escalares Personalizados**: ¿Se deben admitir tipos de datos escalares personalizados para tipos de datos específicos del dominio? + Ejemplos: DateTime, UUID, campos JSON + +## Referencias + +Especificación Técnica de Datos Estructurados: `docs/tech-specs/structured-data.md` +Documentación de Strawberry GraphQL: https://strawberry.rocks/ +Especificación de GraphQL: https://spec.graphql.org/ +<<<<<<< HEAD +Referencia de CQL de Apache Cassandra: https://cassandra.apache.org/doc/stable/cassandra/cql/ +======= +Referencia CQL de Apache Cassandra: https://cassandra.apache.org/doc/stable/cassandra/cql/ +>>>>>>> 82edf2d (New md files from RunPod) +Documentación del Procesador de Flujo de TrustGraph: Documentación interna diff --git a/docs/tech-specs/graphql-query.he.md b/docs/tech-specs/graphql-query.he.md new file mode 100644 index 00000000..728a9627 --- /dev/null +++ b/docs/tech-specs/graphql-query.he.md @@ -0,0 +1,465 @@ +--- +layout: default +title: "GraphQL Query Technical Specification" +parent: "Hebrew (Beta)" +--- + +# GraphQL Query 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 + +<<<<<<< HEAD +מפרט זה מתאר את יישום ממשק שאילתות GraphQL עבור אחסון נתונים מובנים של TrustGraph ב-Apache Cassandra. בהתבסס על יכולות הנתונים המובנים המתוארות במפרט structured-data.md, מסמך זה מפרט כיצד שאילתות GraphQL יבוצעו כנגד טבלאות Cassandra המכילות אובייקטים מובנים שחולצו והועברו. +======= +מפרט זה מתאר את יישום ממשק שאילתות GraphQL עבור אחסון נתונים מובנים של TrustGraph ב-Apache Cassandra. בהתבסס על יכולות הנתונים המובנים המתוארות במפרט structured-data.md, מסמך זה מפרט כיצד שאילתות GraphQL יבוצעו כנגד טבלאות Cassandra המכילות אובייקטים מובנים שחולצו ויועברו. +>>>>>>> 82edf2d (New md files from RunPod) + +שירות שאילתות GraphQL יספק ממשק גמיש ובטוח טיפוסית לשאילתות נתונים מובנים המאוחסנים ב-Cassandra. הוא יסתגל באופן דינמי לשינויים בסכימה, יתמוך בשאילתות מורכבות כולל קשרים בין אובייקטים, וישתלב בצורה חלקה עם ארכיטקטורת העברת הודעות הקיימת של TrustGraph. + +## Goals + +**תמיכה דינמית בסכימה**: הסתגלות אוטומטית לשינויים בסכימה בתצורה ללא אתחולים מחדש של השירות +<<<<<<< HEAD +**עמידה בתקני GraphQL**: מתן ממשק GraphQL סטנדרטי התואם לכלי לקוחות GraphQL קיימים +**שאילתות Cassandra יעילות**: המרת שאילתות GraphQL לשאילתות CQL יעילות של Cassandra תוך כיבוד מפתחות מחיצה ואינדקסים +**פתרון קשרים**: תמיכה במאפייני פותרים עבור קשרים בין סוגי אובייקטים שונים +**בטיחות טיפוסים**: הבטחת ביצוע שאילתות ובניית תגובות בצורה בטוחה טיפוסית בהתבסס על הגדרות סכימה +**ביצועים ניתנים להרחבה**: טיפול יעיל בשאילתות מקבילות עם ניהול חיבורים מתאים ואופטימיזציה של שאילתות +======= +**עמידה בתקני GraphQL**: מתן ממשק GraphQL סטנדרטי התואם לכלי ולקוחות GraphQL קיימים +**שאילתות Cassandra יעילות**: המרת שאילתות GraphQL לשאילתות CQL יעילות של Cassandra תוך כיבוד מפתחות מחיצה ואינדקסים +**פתרון קשרים**: תמיכה בפתרוני שדות עבור קשרים בין סוגי אובייקטים שונים +**בטיחות טיפוסים**: הבטחת ביצוע שאילתות ובניית תגובות בצורה בטוחה טיפוסית בהתבסס על הגדרות סכימה +**ביצועים ניתנים להרחבה**: טיפול יעיל בשאילתות מקבילות עם ניהול בריכת חיבורים ואופטימיזציה של שאילתות +>>>>>>> 82edf2d (New md files from RunPod) +**אינטגרציה של בקשות/תגובות**: שמירה על תאימות לדפוס בקשות/תגובות המבוסס על Pulsar של TrustGraph +**טיפול בשגיאות**: מתן דיווח מקיף על שגיאות עבור חוסר התאמה בסכימה, שגיאות שאילתות ובעיות אימות נתונים + +## Background + +<<<<<<< HEAD +יישום אחסון הנתונים המובנים (trustgraph-flow/trustgraph/storage/objects/cassandra/) כותב אובייקטים לטבלאות Cassandra בהתבסס על הגדרות סכימה המאוחסנות במערכת התצורה של TrustGraph. טבלאות אלה משתמשות במבנה מפתח מחיצה מורכב עם אוספים ומפתחות ראשיים המוגדרים בסכימה, המאפשרות שאילתות יעילות בתוך אוספים. + +מגבלות קיימות שספציפיקציה זו מתייחסת אליהן: +======= +יישום אחסון הנתונים המובנים (trustgraph-flow/trustgraph/storage/objects/cassandra/) כותב אובייקטים לטבלאות Cassandra בהתבסס על הגדרות סכימה המאוחסנות במערכת התצורה של TrustGraph. טבלאות אלה משתמשות במבנה מפתח מחיצה מורכב עם אוספים ומפתחות ראשיים המוגדרים בסכימה, המאפשרים שאילתות יעילות בתוך אוספים. + +מגבלות נוכחיות שמתפרט זה מטפל בהן: +>>>>>>> 82edf2d (New md files from RunPod) +אין ממשק שאילתות עבור הנתונים המובנים המאוחסנים ב-Cassandra +חוסר יכולת לנצל את יכולות השאילתות החזקות של GraphQL עבור נתונים מובנים +חוסר תמיכה במעבר על קשרים בין אובייקטים קשורים +היעדר שפה סטנדרטית לגישה לנתונים מובנים + +שירות שאילתות GraphQL יסגור את הפערים הללו על ידי: +מתן ממשק GraphQL סטנדרטי לשאילתות של טבלאות Cassandra +יצירת סכימות GraphQL באופן דינמי מתצורה של TrustGraph +המרת יעילה של שאילתות GraphQL לשאילתות CQL של Cassandra +<<<<<<< HEAD +תמיכה בפתרון קשרים באמצעות פותרים של שדות +======= +תמיכה בפתרון קשרים באמצעות פתרוני שדות +>>>>>>> 82edf2d (New md files from RunPod) + +## Technical Design + +### Architecture + +שירות שאילתות GraphQL ייושם כמעבד זרימה חדש של TrustGraph תוך שימוש בדפוסים מבוססים: + +**מיקום מודול**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**רכיבים מרכזיים**: + +1. **מעבד שירות שאילתות GraphQL** + מרחיב את מחלקת FlowProcessor הבסיסית + מיישם דפוס בקשה/תגובה הדומה לשירותי שאילתות קיימים + מנטר את התצורה עבור עדכוני סכימה + שומר על סכימת GraphQL מסונכרנת עם התצורה + +<<<<<<< HEAD +2. **מחולל סכימה דינמי** + ממיר הגדרות RowSchema של TrustGraph לטיפוסי GraphQL + יוצר טיפוסי אובייקטים של GraphQL עם הגדרות שדות מתאימות + מייצר טיפוס שורש Query עם פותרים מבוססי אוספים +======= +2. **מחולל סכימה דינמית** + ממיר הגדרות RowSchema של TrustGraph לסוגי GraphQL + יוצר סוגי אובייקטים של GraphQL עם הגדרות שדות מתאימות + מייצר סוג שאילתא ראשי עם פותרים מבוססי אוספים +>>>>>>> 82edf2d (New md files from RunPod) + מעדכן את סכימת GraphQL כאשר התצורה משתנה + +3. **מבצע שאילתות** + מנתח שאילתות GraphQL נכנס באמצעות ספריית Strawberry + מאמת שאילתות כנגד הסכימה הנוכחית + מבצע שאילתות ומחזיר תגובות מובנות + מטפל בשגיאות בצורה אלגנטית עם הודעות שגיאה מפורטות + +4. **מתרגם שאילתות Cassandra** + ממיר בחירות GraphQL לשאילתות CQL + מייעל שאילתות בהתבסס על אינדקסים ומפתחות מחיצה זמינים + מטפל בסינון, דפוס ומיון +<<<<<<< HEAD + מנהל ניהול חיבורים ומחזור חיים של סשן + +5. **פותר קשרים** + מיישם פותרים של שדות עבור קשרים בין אובייקטים +======= + מנהל ניהול בריכת חיבורים ומחזור חיים של סשן + +5. **פתרון קשרים** + מיישם פתרוני שדות עבור קשרים בין אובייקטים +>>>>>>> 82edf2d (New md files from RunPod) + מבצע טעינה באצווה יעילה כדי למנוע שאילתות N+1 + שומר על קשרים פתורים בהקשר הבקשה + תומך במעבר קשרים קדימה ואחורה + +### ניטור סכימת תצורה + +השירות יירשם למטפל תצורה כדי לקבל עדכוני סכימה: + +```python +self.register_config_handler(self.on_schema_config) +``` + +כאשר סכימות משתנות: +1. ניתוח הגדרות סכימה חדשות מקובץ התצורה +2. יצירת סוגי GraphQL ופתרונות (resolvers) מחדש +3. עדכון הסכימה הביצועית +4. ניקוי מטמון כלשהו התלוי בסכימה + +### יצירת סכימת GraphQL + +עבור כל RowSchema בתצורה, יוצרים: + +1. **סוג אובייקט GraphQL**: + מיפוי סוגי שדות (string → String, integer → Int, float → Float, boolean → Boolean) + סימון שדות חובה כלא-nullable ב-GraphQL + הוספת תיאורי שדות מהסכימה + +2. **שדות שאילתה ראשיים**: + שאילתת אוסף (לדוגמה, `customers`, `transactions`) + ארגומנטים לסינון המבוססים על שדות עם אינדקס + תמיכה בדפוס של "paginate" (limit, offset) + אפשרויות מיון עבור שדות הניתנים למיון + +3. **שדות יחסים**: + זיהוי יחסי מפתח זר מהסכימה + יצירת פתרונות (resolvers) עבור אובייקטים קשורים + תמיכה הן ביחסי אובייקט בודד והן ביחסי רשימה + +### זרימת ביצוע שאילתות + +1. **קבלת בקשה**: + קבלת ObjectsQueryRequest מ-Pulsar + חילוץ מחרוזת שאילתת GraphQL ומשתנים + זיהוי משתמש והקשר של אוסף + +2. **אימות שאילתה**: + ניתוח שאילתת GraphQL באמצעות Strawberry + אימות מול הסכימה הנוכחית + בדיקת בחירות שדות וסוגי ארגומנטים + +3. **יצירת CQL**: + ניתוח בחירות GraphQL + בניית שאילתת CQL עם סעיפי WHERE מתאימים + הכללת האוסף במפתח מחיצה + החלת פילטרים המבוססים על ארגומנטים של GraphQL + +4. **ביצוע שאילתה**: + ביצוע שאילתת CQL נגד Cassandra + מיפוי תוצאות למבנה תגובת GraphQL + פתרון כל שדות היחסים + עיצוב התגובה בהתאם למפרט של GraphQL + +5. **העברת תגובה**: + יצירת ObjectsQueryResponse עם תוצאות + הכללת כל שגיאות הביצוע + שליחת תגובה דרך Pulsar עם מזהה מתאם + +### מודלים של נתונים + +<<<<<<< HEAD +> **הערה**: קיימת סכימת StructuredQueryRequest/Response קיימת ב-`trustgraph-base/trustgraph/schema/services/structured_query.py`. עם זאת, היא חסרה שדות קריטיים (משתמש, אוסף) ומשתמשת בסוגים לא אופטימליים. הסכימות שלהלן מייצגות את ההתפתחות המומלצת, שעליה להחליף את הסכימות הקיימות או ליצור סוגי ObjectsQueryRequest/Response חדשים. +======= +> **הערה**: קיימת סכימת StructuredQueryRequest/Response קיימת ב-`trustgraph-base/trustgraph/schema/services/structured_query.py`. עם זאת, היא חסרה שדות קריטיים (משתמש, אוסף) ומשתמשת בסוגים לא אופטימליים. הסכימות שלהלן מייצגות את ההתפתחות המומלצת, שעשויה להחליף את הסכימות הקיימות או ליצור סוגי ObjectsQueryRequest/Response חדשים. +>>>>>>> 82edf2d (New md files from RunPod) + +#### סכימת בקשה (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +<<<<<<< HEAD +**ההצדקה לשינויים מתוך בקשת StructuredQueryRequest קיימת:** +הוספת השדות `user` ו-`collection` כדי להתאים לדפוס של שירותי שאילתות אחרים. +שדות אלה חיוניים לזיהוי ה-keyspace והקולקציה של Cassandra. +המשתנים נשארים מסוג Map(String()) כרגע, אך באופן אידיאלי צריכים לתמוך בכל סוגי ה-JSON. + +#### סכימת תגובה (ObjectsQueryResponse) +======= +**ההצדקה לשינויים מהבקשה המובנית הקיימת (StructuredQueryRequest):** +הוספת השדות `user` ו-`collection` כדי להתאים לדפוס של שירותי שאילתות אחרים. +שדות אלה חיוניים לזיהוי מרחב המפתחות (keyspace) והאוסף (collection) של Cassandra. +המשתנים נשארים מסוג Map(String()) כרגע, אך באופן אידיאלי צריכים לתמוך בכל סוגי ה-JSON. + +#### סכימת התגובה (ObjectsQueryResponse) +>>>>>>> 82edf2d (New md files from RunPod) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**ההצדקה לשינויים מ-StructuredQueryResponse הקיים:** +מבחינה בין שגיאות מערכת (`error`) ושגיאות GraphQL (`errors`) +משתמשת באובייקטי GraphQLError מובנים במקום מערך מחרוזות +מוסיפה שדה `extensions` לצורך עמידה במפרט GraphQL +שומרת על הנתונים כמחרוזת JSON לצורך תאימות, למרות שטיפוסים מקוריים היו עדיפים + +### אופטימיזציה של שאילתות Cassandra + +השירות יבצע אופטימיזציה של שאילתות Cassandra על ידי: + +1. **כבוד למפתחות מחיצה:** + תמיד לכלול אוסף בשאילתות + להשתמש ביעילות במפתחות ראשיים המוגדרים בסכימה + להימנע מסריקות טבלה מלאות + +2. **ניצול אינדקסים:** + להשתמש באינדקסים משניים לסינון + לשלב מספר פילטרים במידת האפשר + להזהיר כאשר שאילתות עשויות להיות לא יעילות + +3. **טעינה באצווה:** + לאסוף שאילתות קשר +<<<<<<< HEAD + לבצע אותן באצווה כדי להפחית את מספר הפעמים +======= + לבצע אותן באצווה כדי להפחית מעברים +>>>>>>> 82edf2d (New md files from RunPod) + לשמור תוצאות בהקשר הבקשה + +4. **ניהול חיבורים:** + לשמור על סשנים קבועים של Cassandra + להשתמש בבריכת חיבורים + לטפל בחיבור מחדש במקרה של כשלים + +### דוגמאות לשאילתות GraphQL + +#### שאילתת אוסף פשוטה +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### שאילתה עם קשרים +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### שאילתה מדורגת +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### תלותות יישום + +**Strawberry GraphQL**: להגדרת סכימת GraphQL ולביצוע שאילתות +**Cassandra Driver**: לחיבור למסד הנתונים (בשימוש כבר במודול האחסון) +**TrustGraph Base**: עבור FlowProcessor והגדרות סכימה +<<<<<<< HEAD +**Configuration System**: לניטור ועדכון סכימות +======= +**Configuration System**: עבור ניטור ועדכון סכימות +>>>>>>> 82edf2d (New md files from RunPod) + +### ממשק שורת הפקודה + +השירות יספק פקודת CLI: `kg-query-objects-graphql-cassandra` + +ארגומנטים: +`--cassandra-host`: נקודת מגע של אשכול Cassandra +`--cassandra-username`: שם משתמש לאימות +`--cassandra-password`: סיסמה לאימות +`--config-type`: סוג תצורה עבור סכימות (ברירת מחדל: "schema") +ארגומנטים סטנדרטיים של FlowProcessor (תצורת Pulsar, וכו') + +## אינטגרציה של API + +### נושאים של Pulsar + +**נושא קלט**: `objects-graphql-query-request` +סכימה: ObjectsQueryRequest +מקבל שאילתות GraphQL משירותי שער + +**נושא פלט**: `objects-graphql-query-response` +סכימה: ObjectsQueryResponse +מחזיר תוצאות שאילתות ושגיאות + +### אינטגרציה של שער + +השער ושער הפוך יצטרכו נקודות קצה כדי: +1. לקבל שאילתות GraphQL מלקוחות +2. להעביר לשירות השאילתות דרך Pulsar +3. להחזיר תגובות ללקוחות +4. לתמוך בשאילתות אינטרוספקציה של GraphQL + +### אינטגרציה של כלי סוכן + +מחלקה חדשה של כלי סוכן תאפשר: +יצירת שאילתות GraphQL משפה טבעית +ביצוע ישיר של שאילתות GraphQL +פרשנות ועיצוב תוצאות +שילוב עם זרימות החלטה של סוכן + +## שיקולי אבטחה + +**הגבלת עומק שאילתה**: למנוע שאילתות מקוננות עמוקות שעלולות לגרום לבעיות ביצועים +**ניתוח מורכבות שאילתה**: להגביל את מורכבות השאילתה כדי למנוע מיצוי משאבים +**הרשאות ברמת השדה**: תמיכה עתידית בשליטה על גישה ברמת השדה בהתבסס על תפקידי משתמש +**ניקוי קלט**: לאמת ולנקות את כל קלט השאילתה כדי למנוע התקפות הזרקה +**הגבלת קצב**: ליישם הגבלת קצב שאילתות למשתמש/אוסף + +## שיקולי ביצועים + +**תכנון שאילתות**: לנתח שאילתות לפני ביצוע כדי לייעל יצירת CQL +**מטמון תוצאות**: לשקול שמירת נתונים שנגישים אליהם לעתים קרובות ברמת פותר השדה +**בריכת חיבורים**: לשמור על בריכות חיבורים יעילות ל-Cassandra +**פעולות אצווה**: לשלב מספר שאילתות כאשר אפשר כדי להפחית השהיה +**ניטור**: לעקוב אחר מדדי ביצועי שאילתות לצורך אופטימיזציה + +## אסטרטגיית בדיקה + +### בדיקות יחידה +יצירת סכימה מתוך הגדרות RowSchema +ניתוח ותיקוף שאילתות GraphQL +לוגיקת יצירת שאילתות CQL +יישומים של פותרים (resolvers) של שדות + +### בדיקות חוזה +עמידה בחוזה הודעות Pulsar +תקינות סכימת GraphQL +אימות פורמט תגובה +אימות מבנה שגיאות + +### בדיקות אינטגרציה +ביצוע שאילתות מקצה לקצה מול מופע בדיקת Cassandra +טיפול בעדכוני סכימה +פתרון קשרים +דפוסים של דף אחרי דף וסינון +<<<<<<< HEAD +תרחישי שגיאות +======= +תרחישי שגיאה +>>>>>>> 82edf2d (New md files from RunPod) + +### בדיקות ביצועים +תפוקת שאילתות תחת עומס +זמן תגובה עבור מורכבויות שאילתות שונות +שימוש בזיכרון עם קבוצות תוצאות גדולות +יעילות של מאגר חיבורים + +## תוכנית מעבר + +<<<<<<< HEAD +אין צורך במעבר מכיוון שזו יכולת חדשה. השירות י: +1. יקרא סכימות קיימות מהתצורה +======= +אין צורך במעבר מכיוון שזו יכולת חדשה. השירות יעשה את הפעולות הבאות: +1. יקרא סכימות קיימות מהגדרות +>>>>>>> 82edf2d (New md files from RunPod) +2. יתחבר לטבלאות Cassandra קיימות שנוצרו על ידי מודול האחסון +3. יתחיל לקבל שאילתות מיד עם הפריסה + +## ציר זמן + +שבוע 1-2: יישום ליבת השירות ויצירת סכימה +שבוע 3: ביצוע שאילתות ותרגום CQL +שבוע 4: פתרון קשרים ואופטימיזציה +<<<<<<< HEAD +שבוע 5: בדיקות וכוונון ביצועים +======= +שבוע 5: בדיקות וכיוונון ביצועים +>>>>>>> 82edf2d (New md files from RunPod) +שבוע 6: שילוב עם שער ותיעוד + +## שאלות פתוחות + +1. **אבולוציה של סכימה**: כיצד השירות צריך להתמודד עם שאילתות במהלך מעברי סכימה? + אפשרות: תזמון שאילתות במהלך עדכוני סכימה + אפשרות: תמיכה במספר גרסאות סכימה בו זמנית + +2. **אסטרטגיית אחסון במטמון**: האם יש לאחסן תוצאות שאילתות במטמון? + לשקול: תפוגה מבוססת זמן + לשקול: ביטול תוקף מבוסס אירועים + +3. **תמיכה בפדרציה**: האם השירות צריך לתמוך בפדרציה של GraphQL לשילוב עם מקורות נתונים אחרים? + יאפשר שאילתות מאוחדות על נתונים מובנים וגרפיים + +4. **תמיכה במנויים**: האם השירות צריך לתמוך במנויים של GraphQL לעדכונים בזמן אמת? + ידרוש תמיכה ב-WebSocket בשער + +5. **סקלרים מותאמים אישית**: האם יש לתמוך בסקלרים מותאמים אישית עבור סוגי נתונים ספציפיים לתחום? + דוגמאות: DateTime, UUID, שדות JSON + +## הפניות + +מפרט טכני של נתונים מובנים: `docs/tech-specs/structured-data.md` +תיעוד Strawberry GraphQL: https://strawberry.rocks/ +מפרט GraphQL: https://spec.graphql.org/ +הפניה ל-Apache Cassandra CQL: https://cassandra.apache.org/doc/stable/cassandra/cql/ +<<<<<<< HEAD +תיעוד מעבד זרימת נתונים TrustGraph: תיעוד פנימי +======= +תיעוד מעבד זרימה של TrustGraph: תיעוד פנימי +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/graphql-query.hi.md b/docs/tech-specs/graphql-query.hi.md new file mode 100644 index 00000000..73cc5aa6 --- /dev/null +++ b/docs/tech-specs/graphql-query.hi.md @@ -0,0 +1,533 @@ +--- +layout: default +title: "GraphQL क्वेरी तकनीकी विनिर्देश" +parent: "Hindi (Beta)" +--- + +# GraphQL क्वेरी तकनीकी विनिर्देश + +> **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. + +## अवलोकन + +यह विनिर्देश अपाचे कैसेंड्रा में ट्रस्टग्राफ के संरचित डेटा भंडारण के लिए एक GraphQL क्वेरी इंटरफ़ेस के कार्यान्वयन का वर्णन करता है। संरचित-डेटा.md विनिर्देश में उल्लिखित संरचित डेटा क्षमताओं पर निर्माण करते हुए, यह दस्तावेज़ बताता है कि निकाले गए और संसाधित संरचित ऑब्जेक्ट युक्त कैसेंड्रा तालिकाओं के खिलाफ GraphQL क्वेरी कैसे निष्पादित की जाएंगी। + +<<<<<<< HEAD +GraphQL क्वेरी सेवा कैसेंड्रा में संग्रहीत संरचित डेटा के लिए एक लचीला, टाइप-सुरक्षित इंटरफ़ेस प्रदान करेगी। यह स्कीमा परिवर्तनों के लिए गतिशील रूप से अनुकूल होगा, ऑब्जेक्ट के बीच संबंधों सहित जटिल प्रश्नों का समर्थन करेगा, और ट्रस्टग्राफ के मौजूदा संदेश-आधारित वास्तुकला के साथ सहजता से एकीकृत होगा। + +## लक्ष्य + +**गतिशील स्कीमा समर्थन**: सेवा को पुनरारंभ किए बिना कॉन्फ़िगरेशन में स्कीमा परिवर्तनों के लिए स्वचालित रूप से अनुकूल होना। +======= +GraphQL क्वेरी सेवा कैसेंड्रा में संग्रहीत संरचित डेटा के लिए एक लचीला, टाइप-सुरक्षित इंटरफ़ेस प्रदान करेगी। यह स्कीमा परिवर्तनों के लिए गतिशील रूप से अनुकूल होगा, ऑब्जेक्ट के बीच संबंधों सहित जटिल क्वेरी का समर्थन करेगा, और ट्रस्टग्राफ के मौजूदा संदेश-आधारित आर्किटेक्चर के साथ सहजता से एकीकृत होगा। + +## लक्ष्य + +**डायनामिक स्कीमा समर्थन**: सेवा को पुनरारंभ किए बिना कॉन्फ़िगरेशन में स्कीमा परिवर्तनों के लिए स्वचालित रूप से अनुकूल होना। +>>>>>>> 82edf2d (New md files from RunPod) +**GraphQL मानकों का अनुपालन**: मौजूदा GraphQL टूलिंग और क्लाइंट के साथ संगत एक मानक GraphQL इंटरफ़ेस प्रदान करना। +**कुशल कैसेंड्रा क्वेरी**: GraphQL क्वेरी को कुशल कैसेंड्रा CQL क्वेरी में अनुवाद करना, विभाजन कुंजियों और अनुक्रमणिकाओं का सम्मान करना। +**संबंध संकल्प**: विभिन्न ऑब्जेक्ट प्रकारों के बीच संबंधों के लिए GraphQL फ़ील्ड रिज़ॉल्वर का समर्थन करना। +**टाइप सुरक्षा**: स्कीमा परिभाषाओं के आधार पर टाइप-सुरक्षित क्वेरी निष्पादन और प्रतिक्रिया पीढ़ी सुनिश्चित करना। +<<<<<<< HEAD +**मापनीय प्रदर्शन**: उचित कनेक्शन पूलिंग और क्वेरी अनुकूलन के साथ समवर्ती प्रश्नों को कुशलतापूर्वक संभालना। +======= +**स्केलेबल प्रदर्शन**: उचित कनेक्शन पूलिंग और क्वेरी अनुकूलन के साथ समवर्ती क्वेरी को कुशलतापूर्वक संभालना। +>>>>>>> 82edf2d (New md files from RunPod) +**अनुरोध/प्रतिक्रिया एकीकरण**: ट्रस्टग्राफ के पल्सर-आधारित अनुरोध/प्रतिक्रिया पैटर्न के साथ संगतता बनाए रखना। +**त्रुटि प्रबंधन**: स्कीमा मिसमैच, क्वेरी त्रुटियों और डेटा सत्यापन मुद्दों के लिए व्यापक त्रुटि रिपोर्टिंग प्रदान करना। + +## पृष्ठभूमि + +<<<<<<< HEAD +संरचित डेटा भंडारण कार्यान्वयन (trustgraph-flow/trustgraph/storage/objects/cassandra/) ट्रस्टग्राफ के कॉन्फ़िगरेशन सिस्टम में संग्रहीत स्कीमा परिभाषाओं के आधार पर कैसेंड्रा तालिकाओं में ऑब्जेक्ट लिखता है। ये तालिकाएँ एक समग्र विभाजन कुंजी संरचना का उपयोग करती हैं जिसमें संग्रह और स्कीमा-परिभाषित प्राथमिक कुंजियाँ होती हैं, जो संग्रह के भीतर कुशल प्रश्नों को सक्षम करती हैं। +======= +संरचित डेटा भंडारण कार्यान्वयन (trustgraph-flow/trustgraph/storage/objects/cassandra/) ट्रस्टग्राफ के कॉन्फ़िगरेशन सिस्टम में संग्रहीत स्कीमा परिभाषाओं के आधार पर कैसेंड्रा तालिकाओं में ऑब्जेक्ट लिखता है। ये तालिकाएँ एक समग्र विभाजन कुंजी संरचना का उपयोग करती हैं जिसमें संग्रह और स्कीमा-परिभाषित प्राथमिक कुंजियाँ होती हैं, जो संग्रह के भीतर कुशल क्वेरी को सक्षम करती हैं। +>>>>>>> 82edf2d (New md files from RunPod) + +वर्तमान सीमाएँ जिन्हें इस विनिर्देश द्वारा संबोधित किया गया है: +कैसेंड्रा में संग्रहीत संरचित डेटा के लिए कोई क्वेरी इंटरफ़ेस नहीं। +संरचित डेटा के लिए GraphQL की शक्तिशाली क्वेरी क्षमताओं का लाभ उठाने में असमर्थता। +संबंधित ऑब्जेक्ट के बीच संबंध ट्रैवर्सल के लिए कोई समर्थन नहीं। +<<<<<<< HEAD +संरचित डेटा एक्सेस के लिए एक मानकीकृत क्वेरी भाषा का अभाव। +======= +संरचित डेटा एक्सेस के लिए एक मानकीकृत क्वेरी भाषा की कमी। +>>>>>>> 82edf2d (New md files from RunPod) + +GraphQL क्वेरी सेवा इन कमियों को भरकर: +कैसेंड्रा तालिकाओं के लिए एक मानक GraphQL इंटरफ़ेस प्रदान करना। +ट्रस्टग्राफ कॉन्फ़िगरेशन से गतिशील रूप से GraphQL स्कीमा उत्पन्न करना। +कुशलतापूर्वक GraphQL क्वेरी को कैसेंड्रा CQL में अनुवाद करना। +फ़ील्ड रिज़ॉल्वर के माध्यम से संबंध संकल्प का समर्थन करना। + +## तकनीकी डिजाइन + +<<<<<<< HEAD +### वास्तुकला +======= +### आर्किटेक्चर +>>>>>>> 82edf2d (New md files from RunPod) + +GraphQL क्वेरी सेवा को एक नए ट्रस्टग्राफ फ्लो प्रोसेसर के रूप में लागू किया जाएगा जो स्थापित पैटर्न का पालन करता है: + +**मॉड्यूल स्थान**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**मुख्य घटक**: + +1. **GraphQL क्वेरी सेवा प्रोसेसर** + बेस FlowProcessor क्लास का विस्तार करता है। + मौजूदा क्वेरी सेवाओं के समान अनुरोध/प्रतिक्रिया पैटर्न को लागू करता है। + स्कीमा अपडेट के लिए कॉन्फ़िगरेशन की निगरानी करता है। + कॉन्फ़िगरेशन के साथ GraphQL स्कीमा को सिंक्रनाइज़ रखता है। + +<<<<<<< HEAD +2. **गतिशील स्कीमा जनरेटर** +======= +2. **डायनामिक स्कीमा जनरेटर** +>>>>>>> 82edf2d (New md files from RunPod) + ट्रस्टग्राफ RowSchema परिभाषाओं को GraphQL प्रकारों में परिवर्तित करता है। + उचित फ़ील्ड परिभाषाओं के साथ GraphQL ऑब्जेक्ट प्रकार बनाता है। + संग्रह-आधारित रिज़ॉल्वर के साथ रूट क्वेरी प्रकार उत्पन्न करता है। + जब कॉन्फ़िगरेशन बदलता है तो GraphQL स्कीमा को अपडेट करता है। + +3. **क्वेरी निष्पादक** + Strawberry लाइब्रेरी का उपयोग करके आने वाली GraphQL क्वेरी को पार्स करता है। + वर्तमान स्कीमा के विरुद्ध क्वेरी को मान्य करता है। + क्वेरी निष्पादित करता है और संरचित प्रतिक्रियाएँ लौटाता है। +<<<<<<< HEAD + विस्तृत त्रुटि संदेशों के साथ त्रुटियों को कुशलतापूर्वक संभालता है। + +4. **कैसेंड्रा क्वेरी अनुवादक** +======= + विस्तृत त्रुटि संदेशों के साथ त्रुटियों को सुचारू रूप से संभालता है। + +4. **कैसेंड्रा क्वेरी ट्रांसलेटर** +>>>>>>> 82edf2d (New md files from RunPod) + GraphQL चयन को CQL क्वेरी में परिवर्तित करता है। + उपलब्ध अनुक्रमणिकाओं और विभाजन कुंजियों के आधार पर क्वेरी को अनुकूलित करता है। + फ़िल्टरिंग, पेजिंग और सॉर्टिंग को संभालता है। + कनेक्शन पूलिंग और सत्र जीवनचक्र का प्रबंधन करता है। + +5. **संबंध रिज़ॉल्वर** + ऑब्जेक्ट संबंधों के लिए फ़ील्ड रिज़ॉल्वर को लागू करता है। + N+1 क्वेरी से बचने के लिए कुशल बैच लोडिंग करता है। + अनुरोध संदर्भ के भीतर हल किए गए संबंधों को कैश करता है। + आगे और पीछे दोनों संबंध ट्रैवर्सल का समर्थन करता है। + +### कॉन्फ़िगरेशन स्कीमा निगरानी + +सेवा स्कीमा अपडेट प्राप्त करने के लिए एक कॉन्फ़िगरेशन हैंडलर को पंजीकृत करेगी: + +```python +self.register_config_handler(self.on_schema_config) +``` + +जब स्कीमा बदलते हैं: +1. कॉन्फ़िगरेशन से नए स्कीमा परिभाषाओं को पार्स करें। +2. GraphQL प्रकारों और रिज़ॉल्वरों को फिर से उत्पन्न करें। +3. निष्पादन योग्य स्कीमा को अपडेट करें। +4. किसी भी स्कीमा-निर्भर कैश को साफ़ करें। + +### GraphQL स्कीमा पीढ़ी + +कॉन्फ़िगरेशन में प्रत्येक RowSchema के लिए, निम्नलिखित उत्पन्न करें: + +1. **GraphQL ऑब्जेक्ट टाइप**: + फ़ील्ड प्रकारों को मैप करें (string → String, integer → Int, float → Float, boolean → Boolean)। + आवश्यक फ़ील्ड को GraphQL में गैर-शून्य के रूप में चिह्नित करें। + स्कीमा से फ़ील्ड विवरण जोड़ें। + +2. **रूट क्वेरी फ़ील्ड**: + संग्रह क्वेरी (जैसे, `customers`, `transactions`)। + अनुक्रमित फ़ील्ड के आधार पर फ़िल्टरिंग तर्क। + पेजिंग समर्थन (सीमा, ऑफ़सेट)। + सॉर्ट करने योग्य फ़ील्ड के लिए सॉर्टिंग विकल्प। + +3. **रिलेशनशिप फ़ील्ड**: + स्कीमा से विदेशी कुंजी संबंधों की पहचान करें। + संबंधित ऑब्जेक्ट के लिए फ़ील्ड रिज़ॉल्वर बनाएं। + एकल ऑब्जेक्ट और सूची दोनों संबंधों का समर्थन करें। + +### क्वेरी निष्पादन प्रवाह + +<<<<<<< HEAD +1. **अनुरोध स्वागत**: +======= +1. **अनुरोध रिसेप्शन**: +>>>>>>> 82edf2d (New md files from RunPod) + Pulsar से ObjectsQueryRequest प्राप्त करें। + GraphQL क्वेरी स्ट्रिंग और चर निकालें। + उपयोगकर्ता और संग्रह संदर्भ की पहचान करें। + +2. **क्वेरी सत्यापन**: + Strawberry का उपयोग करके GraphQL क्वेरी को पार्स करें। + वर्तमान स्कीमा के विरुद्ध मान्य करें। + फ़ील्ड चयन और तर्क प्रकारों की जांच करें। + +3. **CQL पीढ़ी**: + GraphQL चयन का विश्लेषण करें। + उचित WHERE खंडों के साथ CQL क्वेरी बनाएं। + विभाजन कुंजी में संग्रह शामिल करें। + GraphQL तर्कों के आधार पर फ़िल्टर लागू करें। + +4. **क्वेरी निष्पादन**: + Cassandra के खिलाफ CQL क्वेरी निष्पादित करें। + परिणामों को GraphQL प्रतिक्रिया संरचना में मैप करें। + किसी भी रिलेशनशिप फ़ील्ड को हल करें। + GraphQL विनिर्देश के अनुसार प्रतिक्रिया को प्रारूपित करें। + +5. **प्रतिक्रिया वितरण**: + परिणामों के साथ ObjectsQueryResponse बनाएं। + किसी भी निष्पादन त्रुटि को शामिल करें। + सहसंबंध आईडी के साथ Pulsar के माध्यम से प्रतिक्रिया भेजें। + +### डेटा मॉडल + +> **ध्यान दें**: `trustgraph-base/trustgraph/schema/services/structured_query.py` में एक मौजूदा StructuredQueryRequest/Response स्कीमा मौजूद है। हालाँकि, इसमें महत्वपूर्ण फ़ील्ड (उपयोगकर्ता, संग्रह) की कमी है और यह उप-इष्टतम प्रकारों का उपयोग करता है। नीचे दिए गए स्कीमा अनुशंसित विकास का प्रतिनिधित्व करते हैं, जिसे या तो मौजूदा स्कीमा को बदलने के लिए या नए ObjectsQueryRequest/Response प्रकारों के रूप में बनाया जाना चाहिए। + +#### अनुरोध स्कीमा (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +<<<<<<< HEAD +**मौजूदा StructuredQueryRequest से परिवर्तनों का तर्क:** +======= +**मौजूदा StructuredQueryRequest से परिवर्तनों का कारण:** +>>>>>>> 82edf2d (New md files from RunPod) +अन्य क्वेरी सेवाओं के पैटर्न से मेल खाने के लिए `user` और `collection` फ़ील्ड जोड़े गए। +ये फ़ील्ड कैसेंड्रा की स्पेस और कलेक्शन की पहचान करने के लिए आवश्यक हैं। +वेरिएबल अभी भी Map(String()) के रूप में हैं, लेकिन आदर्श रूप से सभी JSON प्रकारों का समर्थन करना चाहिए। + +#### प्रतिक्रिया स्कीमा (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**मौजूदा StructuredQueryResponse से परिवर्तनों का कारण:** +सिस्टम त्रुटियों (`error`) और GraphQL त्रुटियों (`errors`) के बीच अंतर करता है। +स्ट्रिंग सरणी के बजाय संरचित GraphQLError ऑब्जेक्ट का उपयोग करता है। +GraphQL विनिर्देश के अनुपालन के लिए `extensions` फ़ील्ड जोड़ता है। +अनुकूलता के लिए डेटा को JSON स्ट्रिंग के रूप में रखता है, हालांकि मूल प्रकार बेहतर होंगे। + +### कैसेंड्रा क्वेरी अनुकूलन + +सेवा कैसेंड्रा क्वेरी को इस प्रकार अनुकूलित करेगी: + +1. **पार्टिशन कुंजियों का सम्मान करना:** + हमेशा क्वेरी में संग्रह शामिल करें। + स्कीमा-परिभाषित प्राथमिक कुंजियों का कुशलतापूर्वक उपयोग करें। + पूर्ण तालिका स्कैन से बचें। + +2. **सूचकांकों का उपयोग करना:** + फ़िल्टरिंग के लिए द्वितीयक सूचकांकों का उपयोग करें। + जब संभव हो, तो कई फ़िल्टरों को मिलाएं। + चेतावनी दें जब क्वेरी अक्षम हो सकती हैं। + +3. **बैच लोडिंग:** + संबंध क्वेरी एकत्र करें। + राउंड ट्रिप को कम करने के लिए बैचों में निष्पादित करें। + अनुरोध संदर्भ के भीतर परिणामों को कैश करें। + +4. **कनेक्शन प्रबंधन:** + लगातार कैसेंड्रा सत्र बनाए रखें। + कनेक्शन पूलिंग का उपयोग करें। + विफलताओं पर पुनः कनेक्शन को संभालें। + +### उदाहरण GraphQL क्वेरी + +#### सरल संग्रह क्वेरी +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### संबंधों के साथ प्रश्न +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### पृष्ठों में विभाजित क्वेरी +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### कार्यान्वयन निर्भरताएँ + +<<<<<<< HEAD +**स्ट्रॉबेरी ग्राफक्यूएल (Strawberry GraphQL)**: ग्राफक्यूएल स्कीमा परिभाषा और क्वेरी निष्पादन के लिए +**कैसेंड्रा ड्राइवर (Cassandra Driver)**: डेटाबेस कनेक्टिविटी के लिए (भंडारण मॉड्यूल में पहले से उपयोग किया गया) +**ट्रस्टग्राफ बेस (TrustGraph Base)**: फ्लोप्रोसेसर और स्कीमा परिभाषाओं के लिए +**कॉन्फ़िगरेशन सिस्टम (Configuration System)**: स्कीमा निगरानी और अपडेट के लिए +======= +**स्ट्रॉबेरी ग्राफक्यूएल**: ग्राफक्यूएल स्कीमा परिभाषा और क्वेरी निष्पादन के लिए +**कैसेंड्रा ड्राइवर**: डेटाबेस कनेक्टिविटी के लिए (भंडारण मॉड्यूल में पहले से उपयोग किया गया) +**ट्रस्टग्राफ बेस**: फ्लोप्रोसेसर और स्कीमा परिभाषाओं के लिए +**कॉन्फ़िगरेशन सिस्टम**: स्कीमा निगरानी और अपडेट के लिए +>>>>>>> 82edf2d (New md files from RunPod) + +### कमांड-लाइन इंटरफ़ेस + +सेवा एक CLI कमांड प्रदान करेगी: `kg-query-objects-graphql-cassandra` + +तर्क: +`--cassandra-host`: कैसेंड्रा क्लस्टर संपर्क बिंदु +`--cassandra-username`: प्रमाणीकरण उपयोगकर्ता नाम +`--cassandra-password`: प्रमाणीकरण पासवर्ड +`--config-type`: स्कीमा के लिए कॉन्फ़िगरेशन प्रकार (डिफ़ॉल्ट: "स्कीमा") +मानक फ्लोप्रोसेसर तर्क (पल्सर कॉन्फ़िगरेशन, आदि) + +## एपीआई एकीकरण + +<<<<<<< HEAD +### पल्सर विषय (Pulsar Topics) + +**इनपुट टॉपिक (Input Topic)**: `objects-graphql-query-request` +स्कीमा: ऑब्जेक्ट्सक्वेरीरिक्वेस्ट (ObjectsQueryRequest) +गेटवे सेवाओं से ग्राफक्यूएल क्वेरी प्राप्त करता है + +**आउटपुट टॉपिक (Output Topic)**: `objects-graphql-query-response` +स्कीमा: ऑब्जेक्ट्सक्वेरीरिस्पांस (ObjectsQueryResponse) +======= +### पल्सर विषय + +**इनपुट टॉपिक**: `objects-graphql-query-request` +स्कीमा: ऑब्जेक्ट्सक्वेरीरिक्वेस्ट +गेटवे सेवाओं से ग्राफक्यूएल क्वेरी प्राप्त करता है + +**आउटपुट टॉपिक**: `objects-graphql-query-response` +स्कीमा: ऑब्जेक्ट्सक्वेरीरिस्पांस +>>>>>>> 82edf2d (New md files from RunPod) +क्वेरी परिणाम और त्रुटियां लौटाता है + +### गेटवे एकीकरण + +गेटवे और रिवर्स-गेटवे को निम्नलिखित के लिए एंडपॉइंट की आवश्यकता होगी: +1. क्लाइंट से ग्राफक्यूएल क्वेरी स्वीकार करें +<<<<<<< HEAD +2. पल्सर के माध्यम से क्वेरी सेवा को आगे बढ़ाएं +3. क्लाइंट को प्रतिक्रियाएं लौटाएं +======= +2. पल्सर के माध्यम से क्वेरी सेवा को भेजें +3. क्लाइंट को प्रतिक्रिया लौटाएं +>>>>>>> 82edf2d (New md files from RunPod) +4. ग्राफक्यूएल इंट्रॉस्पेक्शन क्वेरी का समर्थन करें + +### एजेंट टूल एकीकरण + +<<<<<<< HEAD +एक नया एजेंट टूल क्लास निम्नलिखित को सक्षम करेगा: +======= +एक नई एजेंट टूल क्लास निम्नलिखित को सक्षम करेगी: +>>>>>>> 82edf2d (New md files from RunPod) +प्राकृतिक भाषा से ग्राफक्यूएल क्वेरी पीढ़ी +प्रत्यक्ष ग्राफक्यूएल क्वेरी निष्पादन +परिणाम व्याख्या और स्वरूपण +एजेंट निर्णय प्रवाह के साथ एकीकरण + +## सुरक्षा विचार + +<<<<<<< HEAD +**क्वेरी गहराई सीमित करना (Query Depth Limiting)**: गहराई से नेस्टेड क्वेरी को रोकें जो प्रदर्शन समस्याओं का कारण बन सकती हैं +**क्वेरी जटिलता विश्लेषण (Query Complexity Analysis)**: संसाधन समाप्त होने से रोकने के लिए क्वेरी जटिलता को सीमित करें +**फ़ील्ड-लेवल अनुमतियाँ (Field-Level Permissions)**: उपयोगकर्ता भूमिकाओं के आधार पर फ़ील्ड-लेवल एक्सेस नियंत्रण के लिए भविष्य का समर्थन +**इनपुट सैनिटाइजेशन (Input Sanitization)**: इंजेक्शन हमलों को रोकने के लिए सभी क्वेरी इनपुट को मान्य और सैनिटाइज करें +**दर सीमित करना (Rate Limiting)**: प्रति उपयोगकर्ता/संग्रहण क्वेरी दर सीमित करना लागू करें + +## प्रदर्शन विचार + +**क्वेरी योजना (Query Planning)**: सीक्यूएल पीढ़ी को अनुकूलित करने के लिए निष्पादन से पहले क्वेरी का विश्लेषण करें +**परिणाम कैशिंग (Result Caching)**: फ़ील्ड रिज़ॉल्वर स्तर पर बार-बार एक्सेस किए जाने वाले डेटा को कैश करने पर विचार करें +**कनेक्शन पूलिंग (Connection Pooling)**: कैसेंड्रा के लिए कुशल कनेक्शन पूल बनाए रखें +**बैच ऑपरेशन (Batch Operations)**: जब भी संभव हो, कई क्वेरी को संयोजित करें ताकि विलंबता कम हो सके +**निगरानी (Monitoring)**: अनुकूलन के लिए क्वेरी प्रदर्शन मेट्रिक्स को ट्रैक करें + +## परीक्षण रणनीति + +### यूनिट परीक्षण +रोस्कीमा परिभाषाओं से स्कीमा पीढ़ी +ग्राफक्यूएल क्वेरी पार्सिंग और सत्यापन +सीक्यूएल क्वेरी पीढ़ी तर्क +======= +**क्वेरी गहराई सीमित करना**: ऐसे गहराई से नेस्टेड क्वेरी को रोकें जो प्रदर्शन समस्याओं का कारण बन सकते हैं +**क्वेरी जटिलता विश्लेषण**: संसाधन समाप्त होने से रोकने के लिए क्वेरी जटिलता को सीमित करें +**फ़ील्ड-स्तरीय अनुमतियाँ**: भविष्य में उपयोगकर्ता भूमिकाओं के आधार पर फ़ील्ड-स्तरीय एक्सेस नियंत्रण के लिए समर्थन +**इनपुट सैनिटाइजेशन**: इंजेक्शन हमलों को रोकने के लिए सभी क्वेरी इनपुट को मान्य और सैनिटाइज करें +**दर सीमित करना**: प्रति उपयोगकर्ता/संग्रहण क्वेरी दर सीमित करना लागू करें + +## प्रदर्शन विचार + +**क्वेरी योजना**: CQL पीढ़ी को अनुकूलित करने के लिए निष्पादन से पहले क्वेरी का विश्लेषण करें +**परिणाम कैशिंग**: फ़ील्ड रिज़ॉल्वर स्तर पर बार-बार एक्सेस किए जाने वाले डेटा को कैश करने पर विचार करें +**कनेक्शन पूलिंग**: कैसेंड्रा के लिए कुशल कनेक्शन पूल बनाए रखें +**बैच ऑपरेशन**: जब भी संभव हो, कई क्वेरी को मिलाएं ताकि विलंबता कम हो सके +**निगरानी**: अनुकूलन के लिए क्वेरी प्रदर्शन मेट्रिक्स को ट्रैक करें + +## परीक्षण रणनीति + +### यूनिट टेस्ट +RowSchema परिभाषाओं से स्कीमा पीढ़ी +GraphQL क्वेरी पार्सिंग और सत्यापन +CQL क्वेरी पीढ़ी लॉजिक +>>>>>>> 82edf2d (New md files from RunPod) +फ़ील्ड रिज़ॉल्वर कार्यान्वयन + +### अनुबंध परीक्षण +पल्सर संदेश अनुबंध अनुपालन +<<<<<<< HEAD +ग्राफक्यूएल स्कीमा वैधता +======= +GraphQL स्कीमा वैधता +>>>>>>> 82edf2d (New md files from RunPod) +प्रतिक्रिया प्रारूप सत्यापन +त्रुटि संरचना सत्यापन + +### एकीकरण परीक्षण +<<<<<<< HEAD +परीक्षण कैसेंड्रा उदाहरण के खिलाफ एंड-टू-एंड क्वेरी निष्पादन +स्कीमा अपडेट हैंडलिंग +संबंध संकल्प +======= +परीक्षण कैसेंड्रा इंस्टेंस के खिलाफ एंड-टू-एंड क्वेरी निष्पादन +स्कीमा अपडेट हैंडलिंग +संबंध समाधान +>>>>>>> 82edf2d (New md files from RunPod) +पेजिंग और फ़िल्टरिंग +त्रुटि परिदृश्य + +### प्रदर्शन परीक्षण +लोड के तहत क्वेरी थ्रूपुट +विभिन्न क्वेरी जटिलताओं के लिए प्रतिक्रिया समय +बड़े परिणाम सेट के साथ मेमोरी उपयोग +कनेक्शन पूल दक्षता + +## माइग्रेशन योजना + +<<<<<<< HEAD +इस नई क्षमता के रूप में माइग्रेशन की आवश्यकता नहीं है। सेवा निम्नलिखित करेगी: +1. कॉन्फ़िगरेशन से मौजूदा स्कीमा पढ़ें +2. स्टोरेज मॉड्यूल द्वारा बनाए गए मौजूदा कैसेंड्रा तालिकाओं से कनेक्ट करें +3. तैनाती पर तुरंत क्वेरी स्वीकार करना शुरू करें +======= +चूंकि यह एक नई क्षमता है, इसलिए माइग्रेशन की आवश्यकता नहीं है। सेवा निम्नलिखित कार्य करेगी: +1. कॉन्फ़िगरेशन से मौजूदा स्कीमा पढ़ें +2. स्टोरेज मॉड्यूल द्वारा बनाए गए मौजूदा कैसेंड्रा तालिकाओं से कनेक्ट करें +3. परिनियोजन पर तुरंत क्वेरी स्वीकार करना शुरू करें +>>>>>>> 82edf2d (New md files from RunPod) + +## समयरेखा + +सप्ताह 1-2: कोर सेवा कार्यान्वयन और स्कीमा पीढ़ी +<<<<<<< HEAD +सप्ताह 3: क्वेरी निष्पादन और सीक्यूएल अनुवाद +सप्ताह 4: संबंध संकल्प और अनुकूलन +सप्ताह 5: परीक्षण और प्रदर्शन ट्यूनिंग +सप्ताह 6: गेटवे एकीकरण और प्रलेखन + +## खुले प्रश्न + +1. **स्कीमा विकास (Schema Evolution)**: सेवा स्कीमा संक्रमण के दौरान क्वेरी को कैसे संभालती है? + विकल्प: स्कीमा अपडेट के दौरान क्वेरी को कतार में लगाएं + विकल्प: एक साथ कई स्कीमा संस्करणों का समर्थन करें + +2. **कैशिंग रणनीति (Caching Strategy)**: क्या क्वेरी परिणामों को कैश किया जाना चाहिए? + विचार करें: समय-आधारित समाप्ति + विचार करें: घटना-आधारित अमान्यकरण + +3. **संघटन समर्थन (Federation Support)**: क्या सेवा अन्य डेटा स्रोतों के साथ संयोजन के लिए ग्राफक्यूएल संघटन का समर्थन करना चाहिए? + यह संरचित और ग्राफ डेटा में एकीकृत क्वेरी को सक्षम करेगा + +4. **सदस्यता समर्थन (Subscription Support)**: क्या सेवा वास्तविक समय अपडेट के लिए ग्राफक्यूएल सदस्यता का समर्थन करना चाहिए? + + +5. **कस्टम स्केलर:** क्या डोमेन-विशिष्ट डेटा प्रकारों के लिए कस्टम स्केलर प्रकारों का समर्थन किया जाना चाहिए? +======= +सप्ताह 3: क्वेरी निष्पादन और CQL अनुवाद +सप्ताह 4: संबंध समाधान और अनुकूलन +सप्ताह 5: परीक्षण और प्रदर्शन ट्यूनिंग +सप्ताह 6: गेटवे एकीकरण और दस्तावेज़ीकरण + +## खुले प्रश्न + +1. **स्कीमा विकास**: सेवा को स्कीमा संक्रमण के दौरान क्वेरी को कैसे संभालना चाहिए? + विकल्प: स्कीमा अपडेट के दौरान क्वेरी को कतार में लगाएं + विकल्प: एक साथ कई स्कीमा संस्करणों का समर्थन करें + +2. **कैशिंग रणनीति**: क्या क्वेरी परिणामों को कैश किया जाना चाहिए? + विचार करें: समय-आधारित समाप्ति + विचार करें: घटना-आधारित अमान्यकरण + +3. **संघटन समर्थन**: क्या सेवा को अन्य डेटा स्रोतों के साथ संयोजन के लिए GraphQL संघटन का समर्थन करना चाहिए? + यह संरचित और ग्राफ डेटा में एकीकृत क्वेरी को सक्षम करेगा + +4. **सदस्यता समर्थन**: क्या सेवा को वास्तविक समय अपडेट के लिए GraphQL सदस्यता का समर्थन करना चाहिए? + इसके लिए गेटवे में WebSocket समर्थन की आवश्यकता होगी + +5. **कस्टम स्केलर**: क्या डोमेन-विशिष्ट डेटा प्रकारों के लिए कस्टम स्केलर प्रकारों का समर्थन किया जाना चाहिए? +>>>>>>> 82edf2d (New md files from RunPod) + उदाहरण: DateTime, UUID, JSON फ़ील्ड + +## संदर्भ + +<<<<<<< HEAD +स्ट्रक्चर्ड डेटा तकनीकी विनिर्देश: `docs/tech-specs/structured-data.md` +स्ट्रॉबेरी GraphQL दस्तावेज़: https://strawberry.rocks/ +GraphQL विनिर्देश: https://spec.graphql.org/ +अपाचे कैसेंड्रा CQL संदर्भ: https://cassandra.apache.org/doc/stable/cassandra/cql/ +ट्रस्टग्राफ फ्लो प्रोसेसर दस्तावेज़: आंतरिक दस्तावेज़ +======= +संरचित डेटा तकनीकी विनिर्देश: `docs/tech-specs/structured-data.md` +स्ट्रॉबेरी GraphQL दस्तावेज़ीकरण: https://strawberry.rocks/ +GraphQL विनिर्देश: https://spec.graphql.org/ +Apache Cassandra CQL संदर्भ: https://cassandra.apache.org/doc/stable/cassandra/cql/ +TrustGraph फ्लो प्रोसेसर दस्तावेज़ीकरण: आंतरिक दस्तावेज़ीकरण +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/graphql-query.md b/docs/tech-specs/graphql-query.md index 3d8b8d86..e3dd44f4 100644 --- a/docs/tech-specs/graphql-query.md +++ b/docs/tech-specs/graphql-query.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "GraphQL Query Technical Specification" +parent: "Tech Specs" +--- + # GraphQL Query Technical Specification ## Overview @@ -380,4 +386,4 @@ No migration required as this is a new capability. The service will: - Strawberry GraphQL Documentation: https://strawberry.rocks/ - GraphQL Specification: https://spec.graphql.org/ - Apache Cassandra CQL Reference: https://cassandra.apache.org/doc/stable/cassandra/cql/ -- TrustGraph Flow Processor Documentation: Internal documentation \ No newline at end of file +- TrustGraph Flow Processor Documentation: Internal documentation diff --git a/docs/tech-specs/graphql-query.pt.md b/docs/tech-specs/graphql-query.pt.md new file mode 100644 index 00000000..fc82879e --- /dev/null +++ b/docs/tech-specs/graphql-query.pt.md @@ -0,0 +1,501 @@ +--- +layout: default +title: "Especificação Técnica da Consulta GraphQL" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica da Consulta GraphQL + +> **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 a implementação de uma interface de consulta GraphQL para o armazenamento de dados estruturados do TrustGraph no Apache Cassandra. Baseando-se nas capacidades de dados estruturados descritas na especificação structured-data.md, este documento detalha como as consultas GraphQL serão executadas contra tabelas do Cassandra contendo objetos estruturados extraídos e ingeridos. + +O serviço de consulta GraphQL fornecerá uma interface flexível e segura para consultar dados estruturados armazenados no Cassandra. Ele se adaptará dinamicamente às alterações de esquema, suportará consultas complexas, incluindo relacionamentos entre objetos, e se integrará perfeitamente à arquitetura existente baseada em mensagens do TrustGraph. + +## Objetivos + +**Suporte Dinâmico de Esquema**: Adaptar-se automaticamente às alterações de esquema na configuração sem reinicializações do serviço. +**Conformidade com os Padrões GraphQL**: Fornecer uma interface GraphQL padrão compatível com as ferramentas e clientes GraphQL existentes. +**Consultas Eficientes do Cassandra**: Traduzir consultas GraphQL em consultas CQL eficientes do Cassandra, respeitando as chaves de partição e os índices. +**Resolução de Relacionamentos**: Suportar resolvedores de campos GraphQL para relacionamentos entre diferentes tipos de objetos. +**Segurança de Tipo**: Garantir a execução de consultas e a geração de respostas com segurança de tipo, com base nas definições do esquema. +**Desempenho Escalável**: Lidar com consultas concorrentes de forma eficiente, com um pool de conexões adequado e otimização de consultas. +<<<<<<< HEAD +**Integração de Solicitação/Resposta**: Manter a compatibilidade com o padrão de solicitação/resposta baseado no Pulsar do TrustGraph. +======= +**Integração de Solicitação/Resposta**: Manter a compatibilidade com o padrão de solicitação/resposta baseado em Pulsar do TrustGraph. +>>>>>>> 82edf2d (New md files from RunPod) +**Tratamento de Erros**: Fornecer relatórios de erros abrangentes para incompatibilidades de esquema, erros de consulta e problemas de validação de dados. + +## Contexto + +<<<<<<< HEAD +A implementação do armazenamento de dados estruturados (trustgraph-flow/trustgraph/storage/objects/cassandra/) grava objetos em tabelas do Cassandra com base em definições de esquema armazenadas no sistema de configuração do TrustGraph. Essas tabelas usam uma estrutura de chave de partição composta com chaves primárias definidas por coleção e esquema, permitindo consultas eficientes dentro das coleções. +======= +A implementação de armazenamento de dados estruturados (trustgraph-flow/trustgraph/storage/objects/cassandra/) grava objetos em tabelas do Cassandra com base em definições de esquema armazenadas no sistema de configuração do TrustGraph. Essas tabelas usam uma estrutura de chave de partição composta com chaves primárias definidas por coleção, permitindo consultas eficientes dentro de coleções. +>>>>>>> 82edf2d (New md files from RunPod) + +Limitações atuais que esta especificação aborda: +Não há interface de consulta para os dados estruturados armazenados no Cassandra. +Impossibilidade de aproveitar os poderosos recursos de consulta do GraphQL para dados estruturados. +Falta de suporte para a travessia de relacionamentos entre objetos relacionados. +Falta de uma linguagem de consulta padronizada para acesso a dados estruturados. + +O serviço de consulta GraphQL preencherá essas lacunas fornecendo: +Uma interface GraphQL padrão para consultar tabelas do Cassandra. +Geração dinâmica de esquemas GraphQL a partir da configuração do TrustGraph. +Tradução eficiente de consultas GraphQL para CQL do Cassandra. +Suporte para resolução de relacionamentos por meio de resolvedores de campos. + +## Design Técnico + +### Arquitetura + +O serviço de consulta GraphQL será implementado como um novo processador de fluxo do TrustGraph, seguindo padrões estabelecidos: + +**Localização do Módulo**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**Componentes Principais**: + +<<<<<<< HEAD +1. **Processador do Serviço de Consulta GraphQL** + Estende a classe base FlowProcessor. + Implementa um padrão de solicitação/resposta semelhante aos serviços de consulta existentes. +======= +1. **Processador de Serviço de Consulta GraphQL** + Estende a classe base FlowProcessor. + Implementa um padrão de solicitação/resposta semelhante a outros serviços de consulta existentes. +>>>>>>> 82edf2d (New md files from RunPod) + Monitora a configuração para atualizações de esquema. + Mantém o esquema GraphQL sincronizado com a configuração. + +2. **Gerador de Esquema Dinâmico** + Converte definições de RowSchema do TrustGraph em tipos GraphQL. +<<<<<<< HEAD + Cria tipos de objetos GraphQL com definições de campo adequadas. +======= + Cria tipos de objetos GraphQL com definições de campo apropriadas. +>>>>>>> 82edf2d (New md files from RunPod) + Gera o tipo de consulta raiz com resolvedores baseados em coleções. + Atualiza o esquema GraphQL quando a configuração é alterada. + +3. **Executor de Consulta** + Analisa consultas GraphQL recebidas usando a biblioteca Strawberry. + Valida as consultas em relação ao esquema atual. + Executa as consultas e retorna respostas estruturadas. + Lida com erros de forma elegante com mensagens de erro detalhadas. + +4. **Tradutor de Consulta do Cassandra** + Converte seleções GraphQL em consultas CQL. + Otimiza as consultas com base nos índices e chaves de partição disponíveis. + Lida com filtragem, paginação e classificação. + Gerencia o pool de conexões e o ciclo de vida da sessão. + +5. **Resolvedor de Relacionamentos** + Implementa resolvedores de campos para relacionamentos entre objetos. + Realiza carregamento em lote eficiente para evitar consultas N+1. + Armazena em cache os relacionamentos resolvidos dentro do contexto da solicitação. + Suporta a travessia de relacionamentos tanto para frente quanto para trás. + +### Monitoramento do Esquema de Configuração + +O serviço registrará um manipulador de configuração para receber atualizações de esquema: + +```python +self.register_config_handler(self.on_schema_config) +``` + +Quando os esquemas mudam: +1. Analisar as novas definições de esquema a partir da configuração +2. Regenerar os tipos e resolvedores GraphQL +3. Atualizar o esquema executável +4. Limpar quaisquer caches dependentes do esquema + +### Geração de Esquema GraphQL + +Para cada RowSchema na configuração, gerar: + +1. **Tipo de Objeto GraphQL**: + Mapear tipos de campo (string → String, integer → Int, float → Float, boolean → Boolean) + Marcar campos obrigatórios como não nulos no GraphQL + Adicionar descrições de campo do esquema + +2. **Campos de Consulta Raiz**: + Consulta de coleção (por exemplo, `customers`, `transactions`) + Argumentos de filtragem com base em campos indexados + Suporte de paginação (limite, deslocamento) + Opções de ordenação para campos classificáveis + +3. **Campos de Relacionamento**: + Identificar relacionamentos de chave estrangeira do esquema + Criar resolvedores de campo para objetos relacionados + Suportar relacionamentos de objeto único e de lista + +### Fluxo de Execução da Consulta + +1. **Recepção da Requisição**: + Receber ObjectsQueryRequest do Pulsar + Extrair a string de consulta GraphQL e as variáveis + Identificar o contexto de usuário e coleção + +2. **Validação da Consulta**: + Analisar a consulta GraphQL usando Strawberry + Validar em relação ao esquema atual + Verificar as seleções de campo e os tipos de argumento + +3. **Geração de CQL**: + Analisar as seleções GraphQL + Construir a consulta CQL com as cláusulas WHERE apropriadas + Incluir a coleção na chave de partição + Aplicar filtros com base nos argumentos GraphQL + +4. **Execução da Consulta**: + Executar a consulta CQL contra o Cassandra + Mapear os resultados para a estrutura de resposta GraphQL + Resolver quaisquer campos de relacionamento + Formatar a resposta de acordo com a especificação GraphQL + +5. **Entrega da Resposta**: + Criar uma ObjectsQueryResponse com os resultados + Incluir quaisquer erros de execução + Enviar a resposta via Pulsar com o ID de correlação + +### Modelos de Dados + +<<<<<<< HEAD +> **Nota**: Um esquema StructuredQueryRequest/Response existente existe em `trustgraph-base/trustgraph/schema/services/structured_query.py`. No entanto, ele carece de campos críticos (usuário, coleção) e usa tipos subótimos. Os esquemas abaixo representam a evolução recomendada, que deve substituir os esquemas existentes ou ser criada como novos tipos ObjectsQueryRequest/Response. +======= +> **Observação**: Um esquema StructuredQueryRequest/Response existente existe em `trustgraph-base/trustgraph/schema/services/structured_query.py`. No entanto, ele carece de campos críticos (usuário, coleção) e usa tipos subótimos. Os esquemas abaixo representam a evolução recomendada, que deve substituir os esquemas existentes ou ser criada como novos tipos ObjectsQueryRequest/Response. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Esquema de Requisição (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +**Justificativa para as alterações em relação ao StructuredQueryRequest existente:** +Adicionados os campos `user` e `collection` para corresponder ao padrão de outros serviços de consulta. +Esses campos são essenciais para identificar o keyspace e a coleção do Cassandra. +As variáveis permanecem como Map(String()) por enquanto, mas idealmente deveriam suportar todos os tipos JSON. + +#### Esquema de Resposta (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**Justificativa para as alterações em relação à StructuredQueryResponse existente:** +Distingue entre erros do sistema (`error`) e erros do GraphQL (`errors`) +Utiliza objetos GraphQLError estruturados em vez de um array de strings +Adiciona o campo `extensions` para conformidade com a especificação do GraphQL +Mantém os dados como uma string JSON para compatibilidade, embora os tipos nativos seriam preferíveis + +### Otimização de Consultas Cassandra + +O serviço otimizará as consultas do Cassandra, através de: + +1. **Respeitando as Chaves de Partição:** + Inclua sempre a coleção nas consultas + Utilize as chaves primárias definidas no esquema de forma eficiente + Evite varreduras completas da tabela + +2. **Aproveitando os Índices:** + Utilize índices secundários para filtragem + Combine vários filtros sempre que possível + Avise quando as consultas podem ser ineficientes + +3. **Carregamento em Lote:** + Colete consultas de relacionamento + Execute em lotes para reduzir o número de viagens de ida e volta + Armazene em cache os resultados dentro do contexto da requisição + +4. **Gerenciamento de Conexões:** + Mantenha sessões persistentes do Cassandra + Utilize um pool de conexões + Lide com a reconexão em caso de falhas + +### Exemplos de Consultas GraphQL + +#### Consulta Simples de Coleção +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### Consulta com Relacionamentos +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### Consulta Paginação +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### Dependências de Implementação + +**Strawberry GraphQL**: Para definição de esquema GraphQL e execução de consultas. +**Cassandra Driver**: Para conectividade com o banco de dados (já utilizado no módulo de armazenamento). +**TrustGraph Base**: Para FlowProcessor e definições de esquema. +<<<<<<< HEAD +**Configuration System**: Para monitoramento e atualizações de esquema. + +### Interface de Linha de Comando + +O serviço fornecerá um comando de CLI: `kg-query-objects-graphql-cassandra` +======= +**Sistema de Configuração**: Para monitoramento e atualizações de esquema. + +### Interface de Linha de Comando + +O serviço fornecerá um comando de interface de linha de comando: `kg-query-objects-graphql-cassandra` +>>>>>>> 82edf2d (New md files from RunPod) + +Argumentos: +`--cassandra-host`: Ponto de contato do cluster Cassandra. +`--cassandra-username`: Nome de usuário de autenticação. +`--cassandra-password`: Senha de autenticação. +`--config-type`: Tipo de configuração para esquemas (padrão: "schema"). +Argumentos padrão do FlowProcessor (configuração do Pulsar, etc.). + +## Integração de API + +### Tópicos Pulsar + +**Tópico de Entrada**: `objects-graphql-query-request` +Esquema: ObjectsQueryRequest +Recebe consultas GraphQL de serviços de gateway. + +**Tópico de Saída**: `objects-graphql-query-response` +Esquema: ObjectsQueryResponse +Retorna resultados de consulta e erros. + +### Integração de Gateway + +<<<<<<< HEAD +O gateway e o gateway reverso precisarão de endpoints para: +======= +O gateway e o reverse-gateway precisarão de endpoints para: +>>>>>>> 82edf2d (New md files from RunPod) +1. Aceitar consultas GraphQL de clientes. +2. Encaminhar para o serviço de consulta via Pulsar. +3. Retornar respostas aos clientes. +4. Suportar consultas de introspecção GraphQL. + +### Integração da Ferramenta de Agente + +Uma nova classe de ferramenta de agente permitirá: +Geração de consultas GraphQL a partir de linguagem natural. +Execução direta de consultas GraphQL. +Interpretação e formatação de resultados. +Integração com fluxos de decisão do agente. + +## Considerações de Segurança + +<<<<<<< HEAD +**Limitação de Profundidade da Consulta**: Prevenir consultas profundamente aninhadas que possam causar problemas de desempenho. +**Análise de Complexidade da Consulta**: Limitar a complexidade da consulta para evitar o esgotamento de recursos. +**Permissões de Nível de Campo**: Suporte futuro para controle de acesso baseado em funções de usuário. +**Sanitização de Entrada**: Validar e sanitizar todas as entradas de consulta para prevenir ataques de injeção. +**Limitação de Taxa**: Implementar a limitação de taxa de consulta por usuário/coleção. +======= +**Limitação da Profundidade da Consulta**: Prevenir consultas profundamente aninhadas que possam causar problemas de desempenho. +**Análise de Complexidade da Consulta**: Limitar a complexidade da consulta para evitar o esgotamento de recursos. +**Permissões em Nível de Campo**: Suporte futuro para controle de acesso baseado em funções de usuário. +**Sanitização de Entrada**: Validar e sanitizar todas as entradas de consulta para prevenir ataques de injeção. +**Limitação de Taxa**: Implementar a limitação de taxa de consultas por usuário/coleção. +>>>>>>> 82edf2d (New md files from RunPod) + +## Considerações de Desempenho + +**Planejamento de Consulta**: Analisar consultas antes da execução para otimizar a geração de CQL. +**Cache de Resultados**: Considerar o cache de dados acessados com frequência no nível do resolvedor de campo. +<<<<<<< HEAD +**Pool de Conexões**: Manter pools de conexão eficientes para o Cassandra. +**Operações em Lote**: Combinar várias consultas sempre que possível para reduzir a latência. +**Monitoramento**: Rastrear métricas de desempenho da consulta para otimização. +======= +**Pool de Conexões**: Manter pools de conexões eficientes para o Cassandra. +**Operações em Lote**: Combinar várias consultas sempre que possível para reduzir a latência. +**Monitoramento**: Acompanhar métricas de desempenho de consultas para otimização. +>>>>>>> 82edf2d (New md files from RunPod) + +## Estratégia de Teste + +### Testes Unitários +<<<<<<< HEAD +Geração de esquema a partir de definições de RowSchema. +Análise e validação de consultas GraphQL. +Lógica de geração de consultas CQL. +Implementações de resolvedores de campo. + +### Testes de Contrato +Conformidade do contrato de mensagem Pulsar. +Validade do esquema GraphQL. +Verificação do formato da resposta. +Validação da estrutura de erro. + +### Testes de Integração +Execução de consulta de ponta a ponta contra uma instância de teste do Cassandra. +Tratamento de atualização de esquema. +Resolução de relacionamento. +Paginação e filtragem. +Cenários de erro. + +### Testes de Desempenho +Taxa de transferência de consultas sob carga. +Tempo de resposta para várias complexidades de consulta. +Uso de memória com grandes conjuntos de resultados. +Eficiência do pool de conexões. +======= +Geração de esquema a partir de definições RowSchema +Análise e validação de consultas GraphQL +Lógica de geração de consultas CQL +Implementações de resolvedores de campos + +### Testes de Contrato +Conformidade com o contrato de mensagens Pulsar +Validade do esquema GraphQL +Verificação do formato da resposta +Validação da estrutura de erros + +### Testes de Integração +Execução de consulta ponta a ponta contra uma instância de teste do Cassandra +Tratamento de atualizações de esquema +Resolução de relacionamentos +Paginação e filtragem +Cenários de erro + +### Testes de Desempenho +Taxa de transferência de consultas sob carga +Tempo de resposta para diferentes complexidades de consulta +Uso de memória com grandes conjuntos de resultados +Eficiência do pool de conexões +>>>>>>> 82edf2d (New md files from RunPod) + +## Plano de Migração + +Não é necessária migração, pois esta é uma nova funcionalidade. O serviço irá: +<<<<<<< HEAD +1. Ler esquemas existentes da configuração. +2. Conectar-se às tabelas Cassandra existentes criadas pelo módulo de armazenamento. +3. Começar a aceitar consultas imediatamente após a implantação. +======= +1. Ler esquemas existentes da configuração +2. Conectar-se às tabelas Cassandra existentes criadas pelo módulo de armazenamento +3. Começar a aceitar consultas imediatamente após a implantação + +## Cronograma + +Semana 1-2: Implementação do serviço principal e geração de esquema +Semana 3: Execução de consultas e tradução CQL +Semana 4: Resolução de relacionamentos e otimização +Semana 5: Testes e ajuste de desempenho +Semana 6: Integração com o gateway e documentação +>>>>>>> 82edf2d (New md files from RunPod) + +## Perguntas Abertas + +1. **Evolução do Esquema**: Como o serviço deve lidar com consultas durante as transições de esquema? +<<<<<<< HEAD +Opção: Enfileirar consultas durante as atualizações de esquema. +Opção: Suportar várias versões de esquema simultaneamente. + +2. **Estratégia de Cache**: Os resultados da consulta devem ser armazenados em cache? +Considerar: Expiração baseada em tempo. +Considerar: Invalidação baseada em eventos. + +3. **Suporte à Federação**: O serviço deve suportar a federação GraphQL para combinar com outras fontes de dados? + Permitiria consultas unificadas em dados estruturados e de grafo. + +4. **Suporte a Assinaturas**: O serviço deve suportar assinaturas GraphQL para atualizações em tempo real? +Requereria suporte WebSocket no gateway. + + 5. **Escalares Personalizados**: O serviço deve suportar tipos escalares personalizados para tipos de dados específicos do domínio? +Exemplos: DateTime, UUID, campos JSON. + + ## Referências + +Especificação de Dados Estruturados: ⟦CODE_0⟧ + Documentação do Strawberry GraphQL: ⟦URL_0⟧ +Especificação GraphQL: ⟦URL_0⟧ +Referência CQL do Apache Cassandra: ⟦URL_0⟧ + Documentação do Flow Processor TrustGraph: Documentação interna. +======= + Opção: Enfileirar consultas durante as atualizações de esquema + Opção: Suportar múltiplas versões de esquema simultaneamente + +2. **Estratégia de Cache**: Os resultados das consultas devem ser armazenados em cache? + Considerar: Expiração baseada em tempo + Considerar: Invalidação baseada em eventos + +3. **Suporte à Federação**: O serviço deve suportar a federação GraphQL para combinar com outras fontes de dados? + Permitiria consultas unificadas em dados estruturados e de grafo + +4. **Suporte a Assinaturas**: O serviço deve suportar assinaturas GraphQL para atualizações em tempo real? + Requereria suporte WebSocket no gateway + +5. **Escalares Personalizados**: O serviço deve suportar tipos escalares personalizados para tipos de dados específicos do domínio? + Exemplos: DateTime, UUID, campos JSON +>>>>>>> 82edf2d (New md files from RunPod) + +## Referências + +Especificação Técnica de Dados Estruturados: `docs/tech-specs/structured-data.md` +<<<<<<< HEAD +Documentação do Strawberry GraphQL: https://strawberry.rocks/ +======= +Documentação do GraphQL Strawberry: https://strawberry.rocks/ +>>>>>>> 82edf2d (New md files from RunPod) +Especificação do GraphQL: https://spec.graphql.org/ +Referência CQL do Apache Cassandra: https://cassandra.apache.org/doc/stable/cassandra/cql/ +Documentação do Processador de Fluxo TrustGraph: Documentação interna diff --git a/docs/tech-specs/graphql-query.ru.md b/docs/tech-specs/graphql-query.ru.md new file mode 100644 index 00000000..cc0793bb --- /dev/null +++ b/docs/tech-specs/graphql-query.ru.md @@ -0,0 +1,530 @@ +--- +layout: default +title: "Техническая спецификация запросов GraphQL" +parent: "Russian (Beta)" +--- + +# Техническая спецификация запросов GraphQL + +> **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. + +## Обзор + +Эта спецификация описывает реализацию интерфейса запросов GraphQL для хранения структурированных данных TrustGraph в Apache Cassandra. Основываясь на возможностях структурированных данных, описанных в спецификации structured-data.md, этот документ подробно описывает, как запросы GraphQL будут выполняться к таблицам Cassandra, содержащим извлеченные и импортированные структурированные объекты. + +Сервис запросов GraphQL предоставит гибкий и типобезопасный интерфейс для запроса структурированных данных, хранящихся в Cassandra. Он будет динамически адаптироваться к изменениям схемы, поддерживать сложные запросы, включая отношения между объектами, и беспрепятственно интегрироваться с существующей архитектурой TrustGraph, основанной на обмене сообщениями. + +## Цели + +**Динамическая поддержка схемы**: Автоматическая адаптация к изменениям схемы в конфигурации без перезапуска сервиса. +**Соответствие стандартам GraphQL**: Предоставление стандартного интерфейса GraphQL, совместимого с существующими инструментами и клиентами GraphQL. +<<<<<<< HEAD +**Эффективные запросы к Cassandra**: Преобразование запросов GraphQL в эффективные запросы CQL к Cassandra, учитывающие первичные ключи и индексы. +**Разрешение отношений**: Поддержка решателей полей GraphQL для отношений между различными типами объектов. +**Типобезопасность**: Обеспечение типобезопасного выполнения запросов и генерации ответов на основе определений схемы. +**Масштабируемая производительность**: Эффективная обработка одновременных запросов с использованием правильного пула соединений и оптимизации запросов. +**Интеграция запросов/ответов**: Поддержка существующей архитектуры TrustGraph, основанной на шаблоне запросов/ответов с использованием Pulsar. +======= +**Эффективные запросы к Cassandra**: Преобразование запросов GraphQL в эффективные запросы CQL для Cassandra, учитывающие первичные ключи и индексы. +**Разрешение отношений**: Поддержка решателей полей GraphQL для отношений между различными типами объектов. +**Типобезопасность**: Обеспечение типобезопасного выполнения запросов и генерации ответов на основе определений схемы. +**Масштабируемая производительность**: Эффективная обработка одновременных запросов с использованием правильного пула соединений и оптимизации запросов. +**Интеграция запросов/ответов**: Поддержка существующего шаблона запросов/ответов TrustGraph, основанного на Pulsar. +>>>>>>> 82edf2d (New md files from RunPod) +**Обработка ошибок**: Предоставление подробной отчетности об ошибках для несоответствий схемы, ошибок запросов и проблем проверки данных. + +## Предыстория + +<<<<<<< HEAD +Реализация хранения структурированных данных (trustgraph-flow/trustgraph/storage/objects/cassandra/) записывает объекты в таблицы Cassandra на основе определений схемы, хранящихся в системе конфигурации TrustGraph. Эти таблицы используют структуру составного первичного ключа с коллекциями и первичными ключами, определенными схемой, что обеспечивает эффективные запросы внутри коллекций. +======= +Реализация хранения структурированных данных (trustgraph-flow/trustgraph/storage/objects/cassandra/) записывает объекты в таблицы Cassandra на основе определений схемы, хранящихся в системе конфигурации TrustGraph. Эти таблицы используют структуру составного первичного ключа с коллекциями и первичными ключами, определенными схемой, что обеспечивает эффективные запросы в пределах коллекций. +>>>>>>> 82edf2d (New md files from RunPod) + +Текущие ограничения, которые эта спецификация решает: +Отсутствие интерфейса запросов для структурированных данных, хранящихся в Cassandra. +Невозможность использования мощных возможностей запросов GraphQL для структурированных данных. +Отсутствие поддержки обхода отношений между связанными объектами. +Отсутствие стандартизированного языка запросов для доступа к структурированным данным. + +Сервис запросов GraphQL устранит эти недостатки, предоставив: +Стандартный интерфейс GraphQL для запросов к таблицам Cassandra. +Динамическую генерацию схем GraphQL из конфигурации TrustGraph. +Эффективное преобразование запросов GraphQL в CQL для Cassandra. +Поддержку разрешения отношений с помощью решателей полей. + +## Технический дизайн + +### Архитектура + +Сервис запросов GraphQL будет реализован как новый обработчик потоков TrustGraph, следуя установленным шаблонам: + +<<<<<<< HEAD +**Местоположение модуля**: `trustgraph-flow/trustgraph/query/objects/cassandra/` +======= +**Расположение модуля**: `trustgraph-flow/trustgraph/query/objects/cassandra/` +>>>>>>> 82edf2d (New md files from RunPod) + +**Основные компоненты**: + +1. **Обработчик сервиса запросов GraphQL** + Расширяет базовый класс FlowProcessor. + Реализует шаблон запросов/ответов, аналогичный существующим сервисам запросов. + Отслеживает конфигурацию на предмет обновлений схемы. + Поддерживает синхронизацию схемы GraphQL с конфигурацией. + +2. **Генератор динамической схемы** +<<<<<<< HEAD + Преобразует определения RowSchema TrustGraph в типы GraphQL. + Создает типы объектов GraphQL с соответствующими определениями полей. + Генерирует корневой тип запроса с решателями на основе коллекций. + Обновляет схему GraphQL при изменении конфигурации. + +3. **Исполнитель запросов** + Анализирует входящие запросы GraphQL с использованием библиотеки Strawberry. +======= + Преобразует определения схемы TrustGraph в типы GraphQL. + Создает типы объектов GraphQL с правильными определениями полей. + Генерирует корневой тип Query с решателями на основе коллекций. + Обновляет схему GraphQL при изменении конфигурации. + +3. **Исполнитель запросов** + Разбирает входящие запросы GraphQL с использованием библиотеки Strawberry. +>>>>>>> 82edf2d (New md files from RunPod) + Проверяет запросы на соответствие текущей схеме. + Выполняет запросы и возвращает структурированные ответы. + Обрабатывает ошибки с подробными сообщениями об ошибках. + +4. **Транслятор запросов Cassandra** + Преобразует выборки GraphQL в запросы CQL. + Оптимизирует запросы на основе доступных индексов и первичных ключей. + Обрабатывает фильтрацию, пагинацию и сортировку. + Управляет пулом соединений и жизненным циклом сессии. + +5. **Разрешитель отношений** + Реализует решатели полей для отношений между объектами. + Выполняет эффективную пакетную загрузку для предотвращения запросов N+1. + Кэширует разрешенные отношения в контексте запроса. + Поддерживает как прямой, так и обратный обход отношений. + +### Мониторинг схемы конфигурации + +Сервис зарегистрирует обработчик конфигурации для получения обновлений схемы: + +```python +self.register_config_handler(self.on_schema_config) +``` + +Когда схемы меняются: +1. Разбор новых определений схемы из конфигурации +2. Регенерация типов GraphQL и решателей +3. Обновление исполняемой схемы +4. Очистка любых кэшей, зависящих от схемы + +### Генерация схемы GraphQL + +Для каждой RowSchema в конфигурации, генерируется: + +1. **Тип объекта GraphQL**: + Отображение типов полей (string → String, integer → Int, float → Float, boolean → Boolean) + Отметка обязательных полей как non-nullable в GraphQL + Добавление описаний полей из схемы + +2. **Корневые поля запроса**: + Запрос коллекции (например, `customers`, `transactions`) + Аргументы фильтрации на основе индексированных полей + Поддержка пагинации (limit, offset) + Варианты сортировки для полей, поддерживающих сортировку + +3. **Поля отношений**: + Определение отношений внешнего ключа из схемы + Создание решателей полей для связанных объектов + Поддержка как одиночных объектов, так и списков отношений + +### Поток выполнения запроса + +1. **Прием запроса**: + Получение ObjectsQueryRequest от Pulsar + Извлечение строки запроса GraphQL и переменных + Определение контекста пользователя и коллекции + +2. **Валидация запроса**: + Разбор запроса GraphQL с использованием Strawberry + Проверка на соответствие текущей схеме + Проверка выбранных полей и типов аргументов + +3. **Генерация CQL**: + Анализ выбранных элементов GraphQL +<<<<<<< HEAD + Создание запроса CQL с правильными предложениями WHERE +======= + Построение запроса CQL с правильными предложениями WHERE +>>>>>>> 82edf2d (New md files from RunPod) + Включение коллекции в ключ партиции + Применение фильтров на основе аргументов GraphQL + +4. **Выполнение запроса**: + Выполнение запроса CQL к Cassandra + Отображение результатов в структуру ответа GraphQL + Разрешение любых полей отношений + Форматирование ответа в соответствии со спецификацией GraphQL + +5. **Доставка ответа**: + Создание ObjectsQueryResponse с результатами + Включение любых ошибок выполнения + Отправка ответа через Pulsar с идентификатором корреляции + +### Модели данных + +> **Примечание**: Существует существующая схема StructuredQueryRequest/Response в `trustgraph-base/trustgraph/schema/services/structured_query.py`. Однако, в ней отсутствуют критические поля (user, collection) и используются неоптимальные типы. Схемы ниже представляют собой рекомендуемую эволюцию, которая должна либо заменить существующие схемы, либо быть создана как новые типы ObjectsQueryRequest/Response. + +#### Схема запроса (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +**Обоснование изменений по сравнению с существующим запросом StructuredQueryRequest:** +Добавлены поля `user` и `collection` для соответствия шаблону других сервисов запросов. +Эти поля необходимы для идентификации пространства ключей и коллекции Cassandra. +Переменные пока остаются Map(String()), но в идеале должны поддерживать все типы JSON. + +#### Схема ответа (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**Обоснование изменений по сравнению с существующим StructuredQueryResponse:** +Различает системные ошибки (`error`) и ошибки GraphQL (`errors`) +Использует структурированные объекты GraphQLError вместо массива строк +Добавляет поле `extensions` для соответствия спецификации GraphQL +Сохраняет данные в виде строки JSON для совместимости, хотя нативные типы были бы предпочтительнее + +### Оптимизация запросов Cassandra + +Сервис будет оптимизировать запросы Cassandra следующим образом: + +1. **Соблюдение ключей разделов (Partition Keys):** + Всегда включайте коллекцию в запросы + Эффективно используйте первичные ключи, определенные в схеме + Избегайте полного сканирования таблицы + +2. **Использование индексов:** + Используйте вторичные индексы для фильтрации + Объединяйте несколько фильтров, когда это возможно + Предупреждайте, когда запросы могут быть неэффективными + +3. **Пакетная загрузка:** + Собирайте запросы для получения взаимосвязей + Выполняйте их пакетами для уменьшения количества обращений + Кэшируйте результаты в контексте запроса + +4. **Управление соединениями:** + Поддерживайте постоянные сессии Cassandra + Используйте пули соединений + Обрабатывайте повторное подключение в случае сбоев + +### Примеры запросов GraphQL + +#### Простой запрос коллекции +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### Запрос со связями +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### Разделенная на страницы выборка +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +<<<<<<< HEAD +### Зависимости реализации +======= +### Реализация и зависимости +>>>>>>> 82edf2d (New md files from RunPod) + +**Strawberry GraphQL**: Для определения схемы GraphQL и выполнения запросов. +**Cassandra Driver**: Для подключения к базе данных (уже используется в модуле хранения). +**TrustGraph Base**: Для FlowProcessor и определений схем. +**Configuration System**: Для мониторинга и обновления схем. + +### Интерфейс командной строки + +Сервис предоставит команду интерфейса командной строки: `kg-query-objects-graphql-cassandra` + +Аргументы: +<<<<<<< HEAD +`--cassandra-host`: Точка контакта кластера Cassandra. +======= +`--cassandra-host`: Контактная точка кластера Cassandra. +>>>>>>> 82edf2d (New md files from RunPod) +`--cassandra-username`: Имя пользователя для аутентификации. +`--cassandra-password`: Пароль для аутентификации. +`--config-type`: Тип конфигурации для схем (по умолчанию: "schema"). +Стандартные аргументы FlowProcessor (конфигурация Pulsar и т.д.). + +<<<<<<< HEAD +## Интеграция API +======= +## Интеграция с API +>>>>>>> 82edf2d (New md files from RunPod) + +### Темы Pulsar + +**Входная тема**: `objects-graphql-query-request` +Схема: ObjectsQueryRequest +<<<<<<< HEAD +Получает GraphQL-запросы от шлюзовых сервисов. +======= +Получает запросы GraphQL от шлюзовых сервисов. +>>>>>>> 82edf2d (New md files from RunPod) + +**Выходная тема**: `objects-graphql-query-response` +Схема: ObjectsQueryResponse +Возвращает результаты запросов и ошибки. + +<<<<<<< HEAD +### Интеграция с шлюзом + +Шлюз и обратный шлюз потребуют конечных точек для: +1. Приема GraphQL-запросов от клиентов. +2. Передачи запросов сервису запросов через Pulsar. +3. Возврата ответов клиентам. +4. Поддержки GraphQL-запросов на интроспекцию. +======= +### Интеграция со шлюзом + +Шлюз и обратный шлюз потребуют конечных точек для: +1. Приема запросов GraphQL от клиентов. +2. Передачи запросов сервису запросов через Pulsar. +3. Возврата ответов клиентам. +4. Поддержки запросов introspection GraphQL. +>>>>>>> 82edf2d (New md files from RunPod) + +### Интеграция с инструментом агента + +Новый класс инструмента агента позволит: +<<<<<<< HEAD +Генерировать GraphQL-запросы из естественного языка. +Выполнять GraphQL-запросы напрямую. +Интерпретировать и форматировать результаты. +Интегрироваться с потоками принятия решений агентом. + +## Вопросы безопасности + +**Ограничение глубины запросов**: Предотвращает вложенные запросы, которые могут вызвать проблемы с производительностью. +**Анализ сложности запросов**: Ограничивает сложность запросов для предотвращения исчерпания ресурсов. +**Разрешения на уровне полей**: Будущая поддержка контроля доступа на уровне полей на основе ролей пользователей. +**Санитизация входных данных**: Проверяет и очищает все входные данные запросов для предотвращения атак внедрения. +**Ограничение скорости**: Реализует ограничение скорости запросов на пользователя/коллекцию. + +## Вопросы производительности + +**Планирование запросов**: Анализирует запросы перед выполнением для оптимизации генерации CQL. +======= +Преобразование естественного языка в запросы GraphQL. +Непосредственное выполнение запросов GraphQL. +Интерпретацию и форматирование результатов. +Интеграцию с потоками принятия решений агентом. + +## Вопросы безопасности + +**Ограничение глубины запросов**: Предотвращение глубоко вложенных запросов, которые могут вызвать проблемы с производительностью. +**Анализ сложности запросов**: Ограничение сложности запросов для предотвращения исчерпания ресурсов. +**Разрешения на уровне полей**: Будущая поддержка контроля доступа на уровне полей на основе ролей пользователей. +**Санитарная обработка входных данных**: Проверка и санитарная обработка всех входных данных запросов для предотвращения атак внедрения. +**Ограничение скорости**: Реализация ограничения скорости запросов на пользователя/коллекцию. + +## Вопросы производительности + +**Планирование запросов**: Анализ запросов перед выполнением для оптимизации генерации CQL. +>>>>>>> 82edf2d (New md files from RunPod) +**Кэширование результатов**: Рассмотрите возможность кэширования часто используемых данных на уровне решателя полей. +**Пул соединений**: Поддерживайте эффективные пулы соединений к Cassandra. +**Пакетные операции**: Объединяйте несколько запросов, когда это возможно, для уменьшения задержки. +**Мониторинг**: Отслеживайте метрики производительности запросов для оптимизации. + +## Стратегия тестирования + +<<<<<<< HEAD +### Unit Tests +Генерация схемы на основе определений RowSchema +Разбор и проверка запросов GraphQL +Логика генерации запросов CQL +Реализации решателей полей + +### Contract Tests +Соответствие контракту сообщений Pulsar +Достоверность схемы GraphQL +Проверка формата ответа +Проверка структуры ошибок + +### Integration Tests +Комплексное выполнение запросов к тестовой инстанции Cassandra +Обработка обновлений схемы +Разрешение связей +Пагинация и фильтрация +Сценарии ошибок + +### Performance Tests +Производительность запросов при высокой нагрузке +Время отклика для различных уровней сложности запросов +Использование памяти при работе с большими наборами результатов +Эффективность пула соединений +======= +### Юнит-тесты +Генерация схем из определений RowSchema. +Разбор и проверка запросов GraphQL. +Логика генерации запросов CQL. +Реализации решателей полей. + +### Контрактные тесты +Соответствие контракту сообщений Pulsar. +Достоверность схемы GraphQL. +Проверка формата ответа. +Проверка структуры ошибок. + +### Интеграционные тесты +Комплексное выполнение запросов к тестовой инстанции Cassandra. +Обработка обновления схем. +Разрешение взаимосвязей. +Пагинация и фильтрация. +Сценарии ошибок. + +### Тесты производительности +Пропускная способность запросов при нагрузке. +Время отклика для различных уровней сложности запросов. +Использование памяти с большими наборами результатов. +Эффективность пула соединений. +>>>>>>> 82edf2d (New md files from RunPod) + +## План миграции + +Миграция не требуется, так как это новая функциональность. Сервис будет: +<<<<<<< HEAD +1. Считывать существующие схемы из конфигурации +2. Подключаться к существующим таблицам Cassandra, созданным модулем хранения +3. Начинать принимать запросы сразу после развертывания + +## Сроки + +1-2 неделя: Реализация основного сервиса и генерация схемы +3 неделя: Выполнение запросов и трансляция CQL +4 неделя: Разрешение связей и оптимизация +5 неделя: Тестирование и настройка производительности +6 неделя: Интеграция с шлюзом и документация + +## Открытые вопросы + +1. **Эволюция схемы**: Как сервис должен обрабатывать запросы во время изменений схемы? + Вариант: Помещать запросы в очередь во время обновлений схемы + Вариант: Поддерживать несколько версий схемы одновременно + +2. **Стратегия кэширования**: Следует ли кэшировать результаты запросов? + Рассмотреть: Временное истечение срока действия + Рассмотреть: Инвалидация на основе событий + +3. **Поддержка федерации**: Следует ли сервису поддерживать GraphQL federation для объединения с другими источниками данных? + Это позволит выполнять унифицированные запросы к структурированным и графовым данным + +4. **Поддержка подписок**: Следует ли сервису поддерживать GraphQL subscriptions для получения обновлений в реальном времени? + Это потребует поддержки WebSocket в шлюзе + +5. **Пользовательские скаляры**: Следует ли поддерживать пользовательские скалярные типы для специфических типов данных? + Примеры: DateTime, UUID, JSON-поля +======= +1. Считывать существующие схемы из конфигурации. +Подключаться к существующим таблицам Cassandra, созданным модулем хранения. +3. Начинать принимать запросы сразу после развертывания. + +## Открытые вопросы + +**Эволюция схемы**: Как сервис должен обрабатывать запросы во время переходов схемы? +Вариант: Помещать запросы в очередь во время обновлений схемы. +Вариант: Поддерживать несколько версий схемы одновременно. + +**Стратегия кэширования**: Следует ли кэшировать результаты запросов? +Рассмотреть: Временное истечение срока действия. +Рассмотреть: Инвалидация на основе событий. + +**Поддержка федерации**: Должен ли сервис поддерживать федерацию GraphQL для объединения с другими источниками данных? + Это позволит выполнять унифицированные запросы к структурированным и графовым данным. + +**Поддержка подписок**: Должен ли сервис поддерживать подписки GraphQL для получения обновлений в режиме реального времени? +Это потребует поддержки WebSocket в шлюзе. + + **Пользовательские скаляры**: Должна ли поддерживаться поддержка пользовательских скалярных типов для специфических типов данных? +Примеры: DateTime, UUID, поля JSON. + + ## Ссылки + +Техническая спецификация структурированных данных: ⟦CODE_0⟧ + Документация Strawberry GraphQL: ⟦URL_0⟧ +Спецификация GraphQL: ⟦URL_0⟧ +Документация Cassandra Driver: ⟦URL_0⟧ + Документация Pulsar: ⟦URL_0⟧ +>>>>>>> 82edf2d (New md files from RunPod) + +## Ссылки + +Техническая спецификация структурированных данных: `docs/tech-specs/structured-data.md` +Документация Strawberry GraphQL: https://strawberry.rocks/ +Спецификация GraphQL: https://spec.graphql.org/ +Справочник Apache Cassandra CQL: https://cassandra.apache.org/doc/stable/cassandra/cql/ +<<<<<<< HEAD +Документация TrustGraph Flow Processor: Внутренняя документация +======= +Документация процессора потоков TrustGraph: Внутренняя документация +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/graphql-query.sw.md b/docs/tech-specs/graphql-query.sw.md new file mode 100644 index 00000000..c9a3c68e --- /dev/null +++ b/docs/tech-specs/graphql-query.sw.md @@ -0,0 +1,585 @@ +--- +layout: default +title: "Vipimo vya Kiufundi vya Umasilisho wa GraphQL" +parent: "Swahili (Beta)" +--- + +<<<<<<< HEAD +# Vipimo vya Kiufundi vya Umasilisho wa GraphQL + +> **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 utekelezaji wa kiolesura cha uwasilisho wa GraphQL kwa kuhifadhi data iliyopangwa ya TrustGraph katika Apache Cassandra. Kujenga juu ya uwezo wa data iliyopangwa uliyoainishwa katika maelekezo ya structured-data.md, hati hii inaeleza jinsi maswali ya GraphQL yanavyotekelezwa dhidi ya meza za Cassandra zinazokuza vitu vilivyochukuliwa na vilivyomingwa. + +Huduma ya uwasilisho wa GraphQL itatoa kiolesura kinachobadilika na kinacholingana na aina kwa kuuliza data iliyopangwa iliyohifadhiwa katika Cassandra. Itabadilika moja kwa moja kwa mabadiliko ya mpango, inasaidia maswali tata ikiwa ni pamoja na uhusiano kati ya vitu, na itounganisha kikamilifu na usanifu uliopo wa TrustGraph unaotegemea ujumbe. + +## Lengo + +**Usaidizi wa Mpango Unaobadilika**: Kujifunga kiotomatiki kwa mabadiliko ya mpango bila kuacha huduma +**Uzingatiaji wa Viwango vya GraphQL**: Kutoa kiolesura cha kawaida cha GraphQL kinacholingana na zana na wateja wa GraphQL iliyopo +**Maswali ya Ufanisi ya Cassandra**: Kubadilisha maswali ya GraphQL kuwa maswali ya ufanisi ya Cassandra CQL kwa kuheshimu funguo za sehemu na fahirisi +**Suluhisho la Uhusiano**: Kusaidia suluhu za GraphQL kwa uhusiano kati ya aina tofauti za vitu +**Usalama wa Aina**: Kuhakikisha utekelezaji wa aina-salama wa maswali na utengenezaji wa majibu kulingana na maelezo ya mpango +**Utendaji Unaoweza Kukidhi Mahitaji**: Kushughulikia maswali mengi kwa ufanisi kwa kutumia udhibiti wa muunganisho na uboreshaji wa maswali +**Ujumuishaji wa Ombi/Jibu**: Kuhifadhi utangamano na mtindo wa ombi/jibu wa TrustGraph unaotegemea Pulsar +**Usimamizi wa Makosa**: Kutoa ripoti kamili ya makosa kwa kutofautiana kwa mpango, makosa ya maswali, na masuala ya uthibitisho wa data + +## Asili + +Utekelezaji wa uhifadhi wa data iliyopangwa (trustgraph-flow/trustgraph/storage/objects/cassandra/) huandika vitu kwenye meza za Cassandra kulingana na maelezo ya mpango yaliyohifadhiwa katika mfumo wa usanidi wa TrustGraph. Meza hizi hutumia muundo wa funguo ya sehemu iliyounganishwa na funguo za msingi zilizobainishwa na mpango, na kuwezesha maswali ya ufanisi ndani ya makusanyo. + +Marekebisho ya sasa ambayo maelekezo haya yanaashiria: +Hakuna kiolesura cha kuuliza kwa data iliyopangwa iliyohifadhiwa katika Cassandra +Uwasilishaji usio wa uwezo wa uwezo wa maswali ya GraphQL kwa data iliyopangwa +Usaidizi usio na uhusiano kati ya vitu vinavyohusiana +Ukosefu wa lugha ya kawaida ya kuuliza kwa upataji wa data iliyopangwa + +Huduma ya uwasilisho wa GraphQL itafunga pengo hizi kwa: +Kutoa kiolesura cha kawaida cha GraphQL kwa kuuliza meza za Cassandra +Kujenga schemas za GraphQL kwa moja kwa moja kutoka usanidi wa TrustGraph +Kubadilisha maswali ya GraphQL kwa ufanisi kwa CQL ya Cassandra +Kusaidia suluhisho la uhusiano kupitia suluhu za uwanja + +## Ubunifu wa Kiufundi + +### Usanifu + +Huduma ya uwasilisho wa GraphQL itatekelezwa kama mchakato mpya wa TrustGraph kufuatia mbinu zilizopo: +======= +# Vipimo vya Kiufundi vya Ulinganisho wa GraphQL + +## Muhtasari + +Maelezo haya yanaeleza utekelezaji wa kiolesura cha ulinganisho wa GraphQL kwa kuhifadhi data iliyopangwa ya TrustGraph katika Apache Cassandra. Kujenga juu ya uwezo wa data iliyopangwa uliotajwa katika maelezo ya structured-data.md, hati hii inaeleza jinsi ulinganisho wa GraphQL utakavyotekelezwa dhidi ya meza za Cassandra zinazozingatia vitu vilivyochukuliwa na kuingizwa. + +Huduma ya ulinganisho wa GraphQL itatoa kiolesura kinachobadilika na kinacholingana na aina kwa ulinganisho wa data iliyopangwa iliyohifadhiwa katika Cassandra. Itabadilika moja kwa moja kulingana na mabadiliko ya muundo, itaidhinisha ulinganisho tata ikiwa ni pamoja na uhusiano kati ya vitu, na itounganisha kikamilifu na usanifu uliopo wa TrustGraph unaotegemea ujumbe. + +## Lengo + +**Usaidizi wa Muundo Unaobadilika**: Kujifunga kiotomatiki na mabadiliko ya muundo katika usanidi bila kuacha huduma +**Uzingatiaji wa Viwango vya GraphQL**: Kutoa kiolesura cha kawaida cha GraphQL kinacholingana na zana na wateja wa GraphQL iliyopo +**Ulinganisho wa Ufanisi wa Cassandra**: Kubadilisha ulinganisho wa GraphQL kuwa ulinganisho wa CQL wa Cassandra unaofaa kwa kuheshimu funguo za sehemu na fahirisi +**Suluhisho la Uhusiano**: Kusaidia suluhu za GraphQL kwa uhusiano kati ya aina tofauti za vitu +**Usalama wa Aina**: Kuhakikisha utekelezaji wa ulinganisho salama wa aina na uzalishaji wa majibu kulingana na ufafanuzi wa muundo +**Utendaji Unaoweza Kukidhi Mahitaji**: Kushughulikia ulinganisho wa wakati mmoja kwa ufanisi kwa kutumia udhibiti wa muunganisho na uboreshaji wa ulinganisho +**Ujumuishaji wa Ombi/Jibu**: Kuhifadhi utangamano na mtindo wa ombi/jibu wa TrustGraph unaotegemea Pulsar +**Usimamizi wa Makosa**: Kutoa ripoti kamili ya makosa kwa kutofautiana kwa muundo, makosa ya ulinganisho, na masuala ya uthibitisho wa data + +## Asili + +Utekelezaji wa uhifadhi wa data iliyopangwa (trustgraph-flow/trustgraph/storage/objects/cassandra/) huandika vitu kwenye meza za Cassandra kulingana na ufafanuzi wa muundo uliohifadhiwa katika mfumo wa usanidi wa TrustGraph. Meza hizi hutumia muundo wa funguo ya sehemu iliyounganishwa na funguo za msingi zilizobainishwa na muundo, na kuwezesha ulinganisho wa ufanisi ndani ya mikusanyiko. + +Marekebisho ya sasa ambayo maelezo haya yanaashiria: +Hakuna kiolesura cha ulinganisho kwa data iliyopangwa iliyohifadhiwa katika Cassandra +Uwezekano wa kutumia uwezo wa ulinganisho wa GraphQL kwa data iliyopangwa +Usaidizi usio na uhusiano wa ueleuzi kati ya vitu vinavyohusiana +Ukosefu wa lugha ya kawaida ya ulinganisho kwa ufikiaji wa data iliyopangwa + +Huduma ya ulinganisho wa GraphQL itafunga pengo hizi kwa: +Kutoa kiolesura cha kawaida cha GraphQL kwa ulinganisho wa meza za Cassandra +Kujenga schemas za GraphQL moja kwa moja kutoka kwa usanidi wa TrustGraph +Kubadilisha ulinganisho wa GraphQL kwa CQL ya Cassandra kwa ufanisi +Kusaidia suluhisho la uhusiano kupitia suluhu za uwanja + +## Muundo wa Kiufundi + +### Usanifu + +Huduma ya ulinganisho wa GraphQL itatekelezwa kama mchakato mpya wa TrustGraph kufuatia mbinu zilizopo: +>>>>>>> 82edf2d (New md files from RunPod) + +**Eneo la Moduli**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**Vipengele Muhimu**: + +<<<<<<< HEAD +1. **Mchakato wa Huduma ya Uwasilisho wa GraphQL** + Huendelea na darasa la msingi la FlowProcessor + Inatekeleza mtindo wa ombi/jibu sawa na huduma zingine za kuuliza + Inafuatilia usanidi kwa sasisho za mpango + Inahifadhi mpango wa GraphQL inayosawazishwa na usanidi + +2. **Mjenzi wa Mpango wa Njia Moja Moja** + Inabadilisha maelezo ya TrustGraph RowSchema kuwa aina za GraphQL + Inaunda aina za vitu vya GraphQL na maelezo ya uwanja sahihi + Inazalisha aina ya mizizi ya Ombi na suluhu za msingi za makusanyo + Inasasisha mpango wa GraphQL wakati usanidi unabadilika + +3. **Mtekelezaji wa Maswali** + Inachambua maswali ya GraphQL yanayoingia kwa kutumia maktaba ya Strawberry + Inathibitisha maswali dhidi ya mpango wa sasa + Inatekeleza maswali na inarudisha majibu yaliyopangwa + Inashughulikia makosa kwa utulivu na ujumbe wa makosa wa kina + +4. **Mhubiri wa Maswali ya Cassandra** + Inabadilisha uteuzi wa GraphQL kuwa maswali ya CQL + Inaboresha maswali kulingana na fahirisi na funguo za sehemu zinazopatikana + Inashughulikia kuchujwa, upangishaji, na utaratibu + Inadhibiti udhibiti wa muunganisho na maisha ya kikao + +5. **Suluhu ya Uhusiano** + Inatekeleza suluhu za uwanja kwa uhusiano wa vitu + Inafanya upakiaji wa kundi ili kuepuka maswali ya N+1 + Inahifadhi suluhu za uhusiano ndani ya muktadha wa ombi + Inasaidia utambuzi wa uhusiano wa mbele na nyuma + +### Ufuatiliaji wa Mpango wa Usanidi + +Huduma itasajili mshukiwa wa usanidi ili kupokea sasisho za mpango: +======= +1. **Mchakato wa Huduma ya Ulinganisho wa GraphQL** + Huendelea na darasa la msingi la FlowProcessor + Huendesha mtindo wa ombi/jibu sawa na huduma zingine za ulinganisho + Huangalia usanidi kwa sasisho za muundo + Huendeleza schema ya GraphQL ili kuendana na usanidi + +2. **Mzalishaji wa Muundo wa Njia Moja Moja** + Hubadilisha ufafanuzi wa TrustGraph RowSchema kuwa aina za GraphQL + Huunda aina za vitu vya GraphQL na ufafanuzi sahihi wa uwanja + Huunda aina ya Query ya mizizi na suluhu za msingi za mkusanyiko + Huendeleza schema ya GraphQL wakati usanidi unabadilika + +3. **Mtekelezaji wa Ulinganisho** + Huainisha ulinganisho wa GraphQL unaoingia kwa kutumia maktaba ya Strawberry + Huainisha ulinganisho dhidi ya schema ya sasa + Huendesha ulinganisho na hurudisha majibu yaliyopangwa + Hushughulikia makosa kwa njia nzuri na ujumbe wa makosa wa kina + +4. **Mhubiri wa Ulinganisho wa Cassandra** + Hubadilisha uteuzi wa GraphQL kuwa ulinganisho wa CQL + Huongeza ulinganisho kulingana na fahirisi na funguo za sehemu zinazopatikana + Hushughulikia uchujaji, upangishaji, na utaratibu + Hushughulikia udhibiti wa muunganisho na mzunguko wa kikao + +5. **Suluhu ya Uhusiano** + Huendesha suluhu za uwanja kwa uhusiano wa vitu + Hufanya upakiaji wa kundi ili kuepuka masuala ya N+1 + Huweka suluhu za uhusiano ndani ya muktadha wa ombi + Inasaidia ueleuzi wa uhusiano wa mbele na nyuma + +### Ufuatiliaji wa Muundo wa Usanidi + +Huduma itajisajili kwa mshughuliki wa usanidi ili kupokea sasisho za muundo: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +self.register_config_handler(self.on_schema_config) +``` + +Wakati schemas hubadilika: +1. Changanua maelezo mapya ya schema kutoka kwa usanidi +<<<<<<< HEAD +2. Tengeneza upya aina za GraphQL na suluhu +======= +2. Tengeneza upya aina na suluhu za GraphQL +>>>>>>> 82edf2d (New md files from RunPod) +3. Sasisha schema inayotumika +4. Ondoa kumbukumbu zozote zinazotegemea schema + +### Uzalishaji wa Schema ya GraphQL + +Kwa kila RowSchema katika usanidi, tengeneza: + +1. **Aina ya Kitu cha GraphQL**: + Linganisha aina za sehemu (string → String, integer → Int, float → Float, boolean → Boolean) + Weka sehemu ambazo zinahitajika kama zisizo na thamani null katika GraphQL + Ongeza maelezo ya sehemu kutoka kwa schema + +2. **Sehemu za Uchunguzi Mkuu**: + Uchunguzi wa mkusanyiko (e.g., `customers`, `transactions`) +<<<<<<< HEAD + Vigezo vya kuchujwa kulingana na sehemu zilizo na fahirisi + Usaidizi wa ukurasa (limit, offset) +======= + Majadiliano ya kuchujwa kulingana na sehemu zilizo na index + Usaidizi wa upangaji (limit, offset) +>>>>>>> 82edf2d (New md files from RunPod) + Chaguo za kupanga kwa sehemu ambazo zinaweza kupangwa + +3. **Sehemu za Uhusiano**: + Tambua uhusiano wa ufunguo wa kigeni kutoka kwa schema + Unda suluhu za sehemu kwa vitu vinavyohusiana +<<<<<<< HEAD + Usaidizi wa uhusiano wa kitu kimoja na orodha +======= + Saidia uhusiano wa kitu kimoja na orodha +>>>>>>> 82edf2d (New md files from RunPod) + +### Mtiririko wa Utendaji wa Uchunguzi + +1. **Mapokezi ya Ombi**: + Pokea `ObjectsQueryRequest` kutoka Pulsar. + Toa mfuatano wa GraphQL na vigezo. + Tambua muktadha wa mtumiaji na mkusanyiko. + +2. **Uthibitisho wa Ombi**: + Changanua mfuatano wa GraphQL kwa kutumia Strawberry. + Thibitisha dhidi ya mpango (schema) unaoendelea. + Angalia uteuzi wa sehemu na aina za hoja (argument). + +3. **Uundaji wa Ombi la CQL**: +<<<<<<< HEAD + Jadili uteuzi wa GraphQL. + Unda ombi la CQL na vipengele sahihi vya `WHERE`. +======= + Changanua uteuzi wa GraphQL. + Unda ombi la CQL na vigezo sahihi vya `WHERE`. +>>>>>>> 82edf2d (New md files from RunPod) + Jumuisha mkusanyiko katika ufunguo wa sehemu (partition key). + Tumia vichujio kulingana na hoja za GraphQL. + +4. **Utendaji wa Ombi**: + Tekeleza ombi la CQL dhidi ya Cassandra. + Linganisha matokeo na muundo wa jibu la GraphQL. + Tatua sehemu zozote za uhusiano. + Tengeneza jibu kulingana na vipimo vya GraphQL. + +5. **Utoaji wa Jibu**: + Unda `ObjectsQueryResponse` na matokeo. + Jumuisha makosa yoyote ya utekelezaji. + Tuma jibu kupitia Pulsar na kitambulisho cha uhusiano (correlation ID). + +### Mifano ya Data + +<<<<<<< HEAD +> **Kumbuka**: Mpango (schema) uliopo wa `StructuredQueryRequest/Response` unafanya kazi katika `trustgraph-base/trustgraph/schema/services/structured_query.py`. Hata hivyo, hauna vipengele muhimu (mtumiaji, mkusanyiko) na hutumia aina ambazo sio bora. Mifano iliyo hapa chini inaonyesha maendeleo yanayopendekezwa, ambayo inaweza kuchukua nafasi ya mifano iliyopo au kuundwa kama aina mpya za `ObjectsQueryRequest/Response`. +======= +> **Kumbuka**: Mpango (schema) uliopo wa `StructuredQueryRequest/Response` unafanya kazi katika `trustgraph-base/trustgraph/schema/services/structured_query.py`. Hata hivyo, hauna sehemu muhimu (mtumiaji, mkusanyiko) na hutumia aina ambazo sio bora. Mifano iliyo hapa chini inaonyesha maendeleo yanayopendekezwa, ambayo inaweza kuchukua nafasi ya mifano iliyopo au kuundwa kama aina mpya za `ObjectsQueryRequest/Response`. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Mpango wa Ombi (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +<<<<<<< HEAD +**Mazingatio ya mabadiliko kutoka kwa Ombi la Ulinganisho Lililopo:** +Imeongezwa sehemu `user` na `collection` ili kuendana na mtindo wa huduma zingine za utafutaji. +Sehemu hizi ni muhimu kwa kutambua eneo la kuhifadhi data (keyspace) na mkusanyiko (collection) katika Cassandra. +======= +**Mazingatio ya mabadiliko kutoka kwa Ombi la Ulipimaji Uliohifadhiwa (StructuredQueryRequest):** +Imeongezwa sehemu `user` na `collection` ili kuendana na mtindo wa huduma zingine za ulipimaji. +Sehemu hizi ni muhimu kwa kutambua eneo la kuhifadhi (keyspace) na mkusanyiko (collection) wa Cassandra. +>>>>>>> 82edf2d (New md files from RunPod) +Vigezo vinaendelea kuwa Map(String()) kwa sasa, lakini inapaswa kusaidia aina zote za JSON. + +#### Muundo wa Majibu (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**Mazingatio ya mabadiliko kutoka kwa Jibu la Uliopo la StructuredQueryResponse:** +Hutofautisha kati ya makosa ya mfumo (`error`) na makosa ya GraphQL (`errors`) +Hutumia vitu vilivyopangwa vya GraphQLError badala ya safu ya maandishi +Huongeza sehemu `extensions` ili kufuata vipimo vya GraphQL +<<<<<<< HEAD +Huhifadhi data kama mnyororo wa JSON ili kuendana, ingawa aina asilia zingekuwa bora +======= +Huendeleza data kama mnyororo wa JSON kwa utangamano, ingawa aina asilia zingekuwa bora +>>>>>>> 82edf2d (New md files from RunPod) + +### Uboreshaji wa Umasilisho wa Cassandra + +Huduma itaboresha masilisho ya Cassandra kwa: + +<<<<<<< HEAD +1. **Kufuata Vipengele vya Partition:** + Daima jumuisha mkusanyiko katika masilisho + Tumia funguo kuu zilizotolewa na mpango kwa ufanisi + Epuka uchanganuzi kamili wa jedwali + +2. **Kutumia Faharasa:** + Tumia faharasa za sekondari kwa kuchujwa + Unganisha vichujio vingi wakati inafaa + Toa onyo wakati masilisho yanaweza kuwa yasiyo na ufanisi + +3. **Upakiaji wa Kundi:** +======= +1. **Kutii Mifungo ya Sehemu**: + Daima jumuisha mkusanyiko katika masilisho + Tumia funguo kuu zilizotolewa na muundo kwa ufanisi + Epuka uchanganuzi kamili wa jedwali + +2. **Kutumia Faharasa**: + Tumia faharasa za sekondari kwa kuchujua + Unganisha vichujio vingi wakati inafaa + Toa onyo wakati masilisho yanaweza kuwa yasiyo na ufanisi + +3. **Upakiaji wa Kundi**: +>>>>>>> 82edf2d (New md files from RunPod) + Kusanya masilisho ya uhusiano + Tekeleza kwa makundi ili kupunguza safari za kurudi na kuja + Hifadhi matokeo ndani ya muktadha wa ombi + +<<<<<<< HEAD +4. **Usimamizi wa Muunganisho:** +======= +4. **Usimamizi wa Muunganisho**: +>>>>>>> 82edf2d (New md files from RunPod) + Dumishe vipindi vya Cassandra vinavyoendelea + Tumia mabwalo ya muunganisho + Shughulikia muunganisho upya katika hali ya kushindwa + +### Mifano ya Masilisho ya GraphQL + +#### Masilisho ya Mkusaniko Rahisi +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### Swali na Mahusiano +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### Swali lililogawanywa katika kurasa. +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +<<<<<<< HEAD +### Utendaji (Implementation) + +**Strawberry GraphQL**: Kwa uainishaji wa schema ya GraphQL na utekelezaji wa swali. +**Cassandra Driver**: Kwa muunganisho wa hifadhidata (tayari inatumika katika moduli ya uhifadhi). +**TrustGraph Base**: Kwa FlowProcessor na uainishaji wa schema. +======= +### Utendaji (Dependencies) + +**Strawberry GraphQL**: Kwa ufafanuzi wa schema ya GraphQL na utekelezaji wa swali. +**Cassandra Driver**: Kwa muunganisho wa hifadhidata (tayari inatumika katika moduli ya uhifadhi). +**TrustGraph Base**: Kwa FlowProcessor na ufafanuzi wa schema. +>>>>>>> 82edf2d (New md files from RunPod) +**Mfumo wa Usanidi**: Kwa ufuatiliaji na sasisho za schema. + +### Kiolesura cha Amri (Command-Line Interface) + +Huduma itatoa amri ya CLI: `kg-query-objects-graphql-cassandra` + +Majadilisho: +`--cassandra-host`: Alama ya kuwasiliana na kundi la Cassandra. +`--cassandra-username`: Jina la mtumiaji la uthibitishaji. +`--cassandra-password`: Nenosiri la uthibitishaji. +<<<<<<< HEAD +`--config-type`: Aina ya usanidi kwa schema (ya kawaida: "schema"). +======= +`--config-type`: Aina ya usanidi kwa schema (kiwango: "schema"). +>>>>>>> 82edf2d (New md files from RunPod) +Majadilisho ya kawaida ya FlowProcessor (usanidi wa Pulsar, n.k.). + +## Uunganisho wa API + +### Mada za Pulsar + +**Mada ya Ingizo**: `objects-graphql-query-request` +Schema: ObjectsQueryRequest +Inapokea maswali ya GraphQL kutoka kwa huduma za lango. + +**Mada ya Toa**: `objects-graphql-query-response` +Schema: ObjectsQueryResponse +Inarudisha matokeo ya swali na makosa. + +### Uunganisho wa Lango + +Lango na lango la kinyume (reverse-gateway) itahitaji sehemu za: +1. Kukubali maswali ya GraphQL kutoka kwa wateja. +2. Kusambaza kwa huduma ya swali kupitia Pulsar. +3. Kurudisha majibu kwa wateja. +4. Kusaidia maswali ya utafiti wa GraphQL. + +### Uunganisho wa Zana ya Wakala + +<<<<<<< HEAD +Darasa mpya la zana ya wakala itaruhusu: +======= +Darasa jipya la zana ya wakala itaruhusu: +>>>>>>> 82edf2d (New md files from RunPod) +Uundaji wa swali la GraphQL kutoka kwa lugha ya asili. +Utendaji wa moja kwa moja wa swali la GraphQL. +Tafsiri na umbizo wa matokeo. +Uunganisho na mtiririko wa maamuzi wa wakala. + +## Masuala ya Usalama + +**Kipengele cha Kuzuia Kina cha Swali**: Kuzuia maswali yenye kina kikubwa ambacho kinaweza kusababisha matatizo ya utendaji. +**Uchambuzi wa Ufumbuzi wa Swali**: Kupunguza ufumbuzi wa swali ili kuzuia matumizi yasiyofaa ya rasilimali. +**Ruhusa za Kawaida**: Usaidizi wa baadaye kwa udhibiti wa ufikiaji wa kawaida kulingana na majukumu ya mtumiaji. +**Usanifu wa Ingizo**: Kuhakikisha na kusafisha pembejeo zote za swali ili kuzuia mashambulizi ya kuingiza. +**Kipengele cha Kupunguza Kasi**: Kuweka kikomo cha kasi ya swali kwa kila mtumiaji/mkusanyiko. + +## Masuala ya Utendaji + +<<<<<<< HEAD +**Upangaji wa Swali**: Kuchambua maswali kabla ya utekelezaji ili kuongeza ufanisi wa uundaji wa CQL. +**Kuhifadhi Matokeo**: Kuzingatia kuhifadhi data inayopatikana mara kwa mara katika kiwango cha kielekezi cha matokeo. +**Usimamizi wa Muunganisho**: Kudumisha mizingi bora ya muunganisho kwa Cassandra. +======= +**Upangaji wa Swali**: Kuchambua maswali kabla ya utekelezaji ili kuongeza ufanisi wa utengenezaji wa CQL. +**Kuhifadhi Matokeo**: Kuzingatia kuhifadhi data inayopatikana mara kwa mara katika kiwango cha suluhu. +**Usimamizi wa Muunganisho**: Kudumisha mikoa bora ya muunganisho kwa Cassandra. +>>>>>>> 82edf2d (New md files from RunPod) +**Operesheni za Kikundi**: Kuchanganya maswali mengi wakati inafaa ili kupunguza latensi. +**Ufuatiliaji**: Kufuatilia vipimo vya utendaji wa swali kwa ajili ya uboreshaji. + +## Mkakati wa Majaribio + +<<<<<<< HEAD +### Majaribio ya Vitengo +Uzalishaji wa schema kutoka kwenye maelezo ya RowSchema +Uchunguzi na uthibitisho wa swali la GraphQL +Mantiki ya uzalishaji wa swali la CQL +Utendaji wa suluhu za sehemu + +### Majaribio ya Mkataba +Uzingatiaji wa mkataba wa ujumbe wa Pulsar +Uthibitisho wa uhalali wa schema ya GraphQL +Uthibitisho wa muundo wa jibu +Uthibitisho wa muundo wa hitilafu + +### Majaribio ya Uunganishaji +Utendaji wa swali kamili dhidi ya mfano wa Cassandra wa majaribio +Usimamizi wa sasisho za schema +Suluhisho la uhusiano +Urekebishaji na utafutaji +Hali za hitilafu + +### Majaribio ya Utendaji +======= +### Majaribsu ya Vitengo +Uzalishaji wa schema kutoka kwa maelezo ya RowSchema +Uchunguzi na uthibitishaji wa swali la GraphQL +Mantiki ya uzalishaji wa swali la CQL +Utendaji wa suluhu za sehemu + +### Majaribsu ya Mkataba +Uzingatiaji wa mkataba wa ujumbe wa Pulsar +Uthibitisho wa utiifu wa schema ya GraphQL +Uthibitisho wa muundo wa jibu +Uthibitisho wa muundo wa hitilafu + +### Majaribsu ya Uunganishaji +Utendaji wa swali kamili dhidi ya mfano wa Cassandra wa majaribio +Usimamizi wa sasisho za schema +Suluhisho la uhusiano +Urekebishaji na utaratibu +Hali za hitilafu + +### Majaribsu ya Utendaji +>>>>>>> 82edf2d (New md files from RunPod) +Ufanisi wa swali chini ya mzigo +Muda wa jibu kwa utata wa swali mbalimbali +Matumizi ya kumbukumbu na matokeo makubwa +Ufanisi wa kikundi cha muunganisho + +## Mpango wa Uhamishaji + +<<<<<<< HEAD +Uhamishaji hauhitajiki kwani hii ni uwezo mpya. Huduma itafanya: +1. Kusoma schema zilizopo kutoka kwenye usanidi +2. Kuunganisha na meza zilizopo za Cassandra zilizoundwa na moduli ya uhifadhi +3. Kuanza kukubali maswali mara tu inaposanikishwa + +## Muda +======= +Hakuna uhamishaji unaohitajika kwani hii ni uwezo mpya. Huduma itafanya: +1. Kusoma schema zilizopo kutoka kwa usanidi +2. Kuunganisha na meza zilizopo za Cassandra zilizoundwa na moduli ya uhifadhi +3. Kuanza kukubali maswali mara tu baada ya kuwekwa + +## Ratiba +>>>>>>> 82edf2d (New md files from RunPod) + +Wiki 1-2: Utendaji wa msingi wa huduma na uzalishaji wa schema +Wiki 3: Utendaji wa swali na tafsiri ya CQL +Wiki 4: Suluhisho la uhusiano na uboreshaji +Wiki 5: Majaribio na uboreshaji wa utendaji +Wiki 6: Uunganisho wa lango na maandishi + +## Maswali ya Wazi + +<<<<<<< HEAD +1. **Maendeleo ya Schema**: Huduma inapaswa kushughulikia maswali vipi wakati wa mabadiliko ya schema? +======= +1. **Maendeleo ya Schema**: Huduma inapaswa kushughulikia maswali wakati wa mabadiliko ya schema? +>>>>>>> 82edf2d (New md files from RunPod) + Chaguo: Kuweka maswali kwenye folyo wakati wa sasisho za schema + Chaguo: Kusaidia matoleo mengi ya schema kwa wakati mmoja + +2. **Mkakati wa Uhifadhi**: Je, matokeo ya swali yanapaswa kuhifadhiwa? + Zingatia: Muda wa kumalizika + Zingatia: Ubatilishaji kulingana na tukio + +3. **Usaidizi wa Shirikisho**: Je, huduma inapaswa kusaidia shirikisho la GraphQL ili kuunganisha na vyanzo vingine vya data? + Itaruhusu maswali ya umoja katika data iliyopangwa na ya grafu + +4. **Usaidizi wa Ujiandikishaji**: Je, huduma inapaswa kusaidia uandikishaji wa GraphQL kwa sasisho za wakati halisi? + Itahitaji usaidizi wa WebSocket katika lango + +5. **Scalar Maalum**: Je, aina za scalar maalum zinapaswa kuungwa mkono kwa aina za data maalum za kikoa? + Mifano: DateTime, UUID, nafasi za JSON + +## Marejeleo + +Maelezo ya Kimataifa ya Data Iliyopangwa: `docs/tech-specs/structured-data.md` +<<<<<<< HEAD +Nyaraka za Strawberry GraphQL: https://strawberry.rocks/ +Maelezo ya GraphQL: https://spec.graphql.org/ +Marejeleo ya Apache Cassandra CQL: https://cassandra.apache.org/doc/stable/cassandra/cql/ +Nyaraka za Msimamizi wa Mtiririko wa TrustGraph: Nyaraka za ndani +======= +Nyaraka za GraphQL Strawberry: https://strawberry.rocks/ +Maelezo ya GraphQL: https://spec.graphql.org/ +Marejeleo ya Apache Cassandra CQL: https://cassandra.apache.org/doc/stable/cassandra/cql/ +Nyaraka za Mfumo wa Mchakato wa TrustGraph: Nyaraka za ndani +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/graphql-query.tr.md b/docs/tech-specs/graphql-query.tr.md new file mode 100644 index 00000000..d854224f --- /dev/null +++ b/docs/tech-specs/graphql-query.tr.md @@ -0,0 +1,482 @@ +--- +layout: default +title: "GraphQL Sorgu Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# GraphQL Sorgu 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'ın Apache Cassandra'daki yapılandırılmış veri depolaması için bir GraphQL sorgu arayüzünün uygulanmasını tanımlar. Yapılandırılmış-veri.md spesifikasyonunda belirtilen yapılandırılmış veri yeteneklerine dayanarak, bu belge, çıkarılan ve işlenen yapılandırılmış nesneleri içeren Cassandra tablolarına karşı GraphQL sorgularının nasıl yürütüleceğini ayrıntılı olarak açıklar. + +GraphQL sorgu hizmeti, Cassandra'da depolanan yapılandırılmış verileri sorgulamak için esnek, tür güvenli bir arayüz sağlayacaktır. Şema değişikliklerine dinamik olarak uyum sağlayacak, nesneler arasındaki ilişkiler de dahil olmak üzere karmaşık sorguları destekleyecek ve TrustGraph'ın mevcut mesaj tabanlı mimarisiyle sorunsuz bir şekilde entegre olacaktır. + +## Hedefler + +<<<<<<< HEAD +**Dinamik Şema Desteği**: Hizmeti yeniden başlatmaya gerek kalmadan yapılandırmadaki şema değişikliklerine otomatik olarak uyum sağlayın. +**GraphQL Standartlarına Uygunluk**: Mevcut GraphQL araçları ve istemcileriyle uyumlu, standart bir GraphQL arayüzü sağlayın. +**Verimli Cassandra Sorguları**: GraphQL sorgularını, bölüm anahtarlarını ve dizinleri dikkate alarak verimli Cassandra CQL sorgularına dönüştürün. +**İlişki Çözümlemesi**: Farklı nesne türleri arasındaki ilişkiler için GraphQL alan çözümleyicilerini destekleyin. +**Tür Güvenliği**: Şema tanımlarına göre tür güvenli sorgu yürütme ve yanıt oluşturma sağlayın. +**Ölçeklenebilir Performans**: Uygun bağlantı havuzu ve sorgu optimizasyonu ile eşzamanlı sorguları verimli bir şekilde işleyin. +**İstek/Yanıt Entegrasyonu**: TrustGraph'ın Pulsar tabanlı istek/yanıt kalıbıyla uyumluluğu koruyun. +**Hata İşleme**: Şema uyumsuzlukları, sorgu hataları ve veri doğrulama sorunları için kapsamlı hata raporlama sağlayın. + +## Arka Plan + +Yapılandırılmış veri depolama uygulaması (trustgraph-flow/trustgraph/storage/objects/cassandra/), nesneleri TrustGraph'ın yapılandırma sisteminde depolanan şema tanımlarına göre Cassandra tablolarına yazar. Bu tablolar, koleksiyonlar içindeki verimli sorguları etkinleştiren bileşik bölüm anahtarı yapısı ve şema tanımlı birincil anahtarlar kullanır. + +Bu özellik tarafından ele alınan mevcut sınırlamalar: +Cassandra'da depolanan yapılandırılmış veri için bir sorgu arayüzü yok. +Yapılandırılmış veri için GraphQL'in güçlü sorgu yeteneklerinden yararlanamama. +İlişkili nesneler arasındaki ilişki geçişi için destek eksikliği. +Yapılandırılmış veri erişimi için standart bir sorgu dili eksikliği. + +GraphQL sorgu hizmeti, bunları sağlayarak bu boşlukları dolduracaktır: +Cassandra tablolarını sorgulamak için standart bir GraphQL arayüzü. +TrustGraph yapılandırmasından dinamik olarak GraphQL şemaları oluşturma. +GraphQL sorgularını Cassandra CQL'ye verimli bir şekilde dönüştürme. +Alan çözümleyicileri aracılığıyla ilişki çözümlemesini destekleme. +======= +**Dinamik Şema Desteği**: Hizmeti yeniden başlatmadan yapılandırmadaki şema değişikliklerine otomatik olarak uyum sağlama +**GraphQL Standartlarına Uygunluk**: Mevcut GraphQL araçları ve istemcileriyle uyumlu, standart bir GraphQL arayüzü sağlama +**Verimli Cassandra Sorguları**: GraphQL sorgularını, bölüm anahtarlarını ve dizinleri dikkate alarak verimli Cassandra CQL sorgularına çevirme +**İlişki Çözümleme**: Farklı nesne türleri arasındaki ilişkiler için GraphQL alan çözümleyicilerini destekleme +**Tür Güvenliği**: Şema tanımlarına dayalı olarak tür güvenli sorgu yürütme ve yanıt oluşturma +**Ölçeklenebilir Performans**: Uygun bağlantı havuzu ve sorgu optimizasyonu ile eşzamanlı sorguları verimli bir şekilde işleme +**İstek/Yanıt Entegrasyonu**: TrustGraph'ın Pulsar tabanlı istek/yanıt kalıbıyla uyumluluğu koruma +**Hata İşleme**: Şema uyumsuzlukları, sorgu hataları ve veri doğrulama sorunları için kapsamlı hata raporlama sağlama + +## Arka Plan + +Yapılandırılmış veri depolama uygulaması (trustgraph-flow/trustgraph/storage/objects/cassandra/), nesneleri TrustGraph'ın yapılandırma sisteminde depolanan şema tanımlarına göre Cassandra tablolarına yazar. Bu tablolar, koleksiyonlar içindeki verimli sorguları etkinleştiren bileşik bir bölüm anahtarı yapısı ve şema tanımlı birincil anahtarlar kullanır. + +Bu özellik tarafından ele alınan mevcut sınırlamalar: +Cassandra'da depolanan yapılandırılmış veri için bir sorgu arayüzünün olmaması +Yapılandırılmış veri için GraphQL'in güçlü sorgu yeteneklerinden yararlanamama +İlişkili nesneler arasındaki ilişki geçişi için destek eksikliği +Yapılandırılmış veri erişimi için standart bir sorgu dilinin olmaması + +GraphQL sorgu hizmeti, bu boşlukları aşağıdaki şekilde dolduracaktır: +Cassandra tablolarını sorgulamak için standart bir GraphQL arayüzü sağlama +TrustGraph yapılandırmasından dinamik olarak GraphQL şemaları oluşturma +GraphQL sorgularını verimli bir şekilde Cassandra CQL'ye çevirme +Alan çözümleyicileri aracılığıyla ilişki çözümlemeyi destekleme +>>>>>>> 82edf2d (New md files from RunPod) + +## Teknik Tasarım + +### Mimari + +GraphQL sorgu hizmeti, yerleşik kalıpları izleyen yeni bir TrustGraph akışı işlemci olarak uygulanacaktır: + +**Modül Konumu**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**Ana Bileşenler**: + +1. **GraphQL Sorgu Hizmeti İşlemcisi** +<<<<<<< HEAD + Temel FlowProcessor sınıfını genişletir. + Mevcut sorgu hizmetlerine benzer bir istek/yanıt kalıbını uygular. + Şema güncellemeleri için yapılandırmayı izler. + GraphQL şemasını yapılandırmayla senkronize tutar. + +2. **Dinamik Şema Oluşturucu** + TrustGraph RowSchema tanımlarını GraphQL türlerine dönüştürür. + Uygun alan tanımlarıyla GraphQL nesne türleri oluşturur. + Koleksiyon tabanlı çözümleyicilerle kök Sorgu türünü oluşturur. + Yapılandırma değiştiğinde GraphQL şemasını günceller. + +3. **Sorgu Yürütücüsü** + Gelen GraphQL sorgularını Strawberry kütüphanesi kullanarak ayrıştırır. + Sorguları mevcut şemaya göre doğrular. + Sorguları yürütür ve yapılandırılmış yanıtlar döndürür. + Ayrıntılı hata mesajlarıyla hataları zarif bir şekilde işler. + +4. **Cassandra Sorgu Çevirmeni** + GraphQL seçimlerini CQL sorgularına dönüştürür. + Mevcut dizinlere ve bölüm anahtarlarına göre sorguları optimize eder. + Filtrelemeyi, sayfalama ve sıralamayı işler. + Bağlantı havuzunu ve oturum yaşam döngüsünü yönetir. + +5. **İlişki Çözümleyici** + Nesne ilişkileri için alan çözümleyicilerini uygular. + N+1 sorgularından kaçınmak için verimli toplu yükleme gerçekleştirir. + Çözümlenen ilişkileri istek bağlamı içinde önbelleğe alır. + Hem ileri hem de geri ilişki geçişini destekler. +======= + Temel FlowProcessor sınıfını genişletir + Mevcut sorgu hizmetlerine benzer bir istek/yanıt kalıbını uygular + Şema güncellemeleri için yapılandırmayı izler + GraphQL şemasını yapılandırmayla senkronize tutar + +2. **Dinamik Şema Oluşturucu** + TrustGraph RowSchema tanımlarını GraphQL türlerine dönüştürür + Uygun alan tanımlarıyla GraphQL nesne türleri oluşturur + Koleksiyon tabanlı çözümleyicilerle kök Sorgu türünü oluşturur + Yapılandırma değiştiğinde GraphQL şemasını günceller + +3. **Sorgu Yürütücüsü** + Gelen GraphQL sorgularını Strawberry kütüphanesi kullanarak ayrıştırır + Sorguları mevcut şemaya göre doğrular + Sorguları yürütür ve yapılandırılmış yanıtlar döndürür + Ayrıntılı hata mesajlarıyla hataları zarif bir şekilde işler + +4. **Cassandra Sorgu Çevirmeni** + GraphQL seçimlerini CQL sorgularına dönüştürür + Mevcut dizinlere ve bölüm anahtarlarına göre sorguları optimize eder + Filtrelemeyi, sayfalama ve sıralamayı işler + Bağlantı havuzunu ve oturum yaşam döngüsünü yönetir + +5. **İlişki Çözümleyici** + Nesne ilişkileri için alan çözümleyicilerini uygular + N+1 sorgularından kaçınmak için verimli toplu yükleme gerçekleştirir + Çözümlenen ilişkileri istek bağlamı içinde önbelleğe alır + Hem ileri hem de geri ilişki geçişini destekler +>>>>>>> 82edf2d (New md files from RunPod) + +### Yapılandırma Şeması İzleme + +Hizmet, şema güncellemelerini almak için bir yapılandırma işleyicisi kaydeder: + +```python +self.register_config_handler(self.on_schema_config) +``` + +Şemalar değiştiğinde: +1. Yapılandırmadan yeni şema tanımlarını ayrıştırın. +2. GraphQL türlerini ve çözümleyicileri yeniden oluşturun. +<<<<<<< HEAD +3. Çalıştırılabilir şemayı güncelleyin. +======= +3. Uygulanabilir şemayı güncelleyin. +>>>>>>> 82edf2d (New md files from RunPod) +4. Şemaya bağlı tüm önbellekleri temizleyin. + +### GraphQL Şema Oluşturma + +Yapılandırmadaki her RowSchema için aşağıdaki öğeleri oluşturun: + +1. **GraphQL Nesne Türü**: + Alan türlerini eşleyin (string → String, integer → Int, float → Float, boolean → Boolean). + Gerekli alanları GraphQL'de nullable olmayan olarak işaretleyin. + Şemadan alan açıklamalarını ekleyin. + +2. **Kök Sorgu Alanları**: + Koleksiyon sorgusu (örneğin, `customers`, `transactions`). + İndekslenmiş alanlara göre filtreleme argümanları. + Sayfalama desteği (limit, offset). + Sıralanabilir alanlar için sıralama seçenekleri. + +3. **İlişki Alanları**: + Şemadan yabancı anahtar ilişkilerini belirleyin. + İlgili nesneler için alan çözümleyicileri oluşturun. + Hem tek nesne hem de liste ilişkilerini destekleyin. + +### Sorgu Yürütme Akışı + +1. **İstek Alma**: + Pulsar'dan ObjectsQueryRequest'i alın. + GraphQL sorgu dizesini ve değişkenlerini çıkarın. + Kullanıcıyı ve koleksiyon bağlamını belirleyin. + +2. **Sorgu Doğrulama**: + Strawberry kullanarak GraphQL sorgusunu ayrıştırın. + Mevcut şemaya göre doğrulayın. + Alan seçimlerini ve argüman türlerini kontrol edin. + +3. **CQL Oluşturma**: + GraphQL seçimlerini analiz edin. + Uygun WHERE koşullarına sahip CQL sorgusu oluşturun. + Koleksiyonu bölüm anahtarına dahil edin. + GraphQL argümanlarına göre filtreleri uygulayın. + +4. **Sorgu Yürütme**: + CQL sorgusunu Cassandra'ya karşı yürütün. + Sonuçları GraphQL yanıt yapısına eşleyin. + Herhangi bir ilişki alanını çözün. +<<<<<<< HEAD + Yanıtı GraphQL spesifikasyonuna göre biçimlendirin. +======= + Yanıtı GraphQL belirtimine göre biçimlendirin. +>>>>>>> 82edf2d (New md files from RunPod) + +5. **Yanıt Teslimi**: + Sonuçlarla ObjectsQueryResponse oluşturun. + Herhangi bir yürütme hatasını dahil edin. + Yanıtı korelasyon kimliğiyle Pulsar üzerinden gönderin. + +### Veri Modelleri + +<<<<<<< HEAD +> **Not**: `trustgraph-base/trustgraph/schema/services/structured_query.py`'da mevcut bir StructuredQueryRequest/Response şeması bulunmaktadır. Ancak, bu şemada kritik alanlar (kullanıcı, koleksiyon) eksiktir ve alt optimal türler kullanılmaktadır. Aşağıdaki şemalar, önerilen gelişmeyi temsil etmektedir; bu şemalar ya mevcut şemaları değiştirmeli ya da yeni ObjectsQueryRequest/Response türleri olarak oluşturulmalıdır. +======= +> **Not**: `trustgraph-base/trustgraph/schema/services/structured_query.py`'da mevcut bir StructuredQueryRequest/Response şeması bulunmaktadır. Ancak, bu şema kritik alanları (kullanıcı, koleksiyon) içermemekte ve alt optimal türler kullanmaktadır. Aşağıdaki şemalar, önerilen gelişmeyi temsil etmektedir; bunlar ya mevcut şemaları değiştirmeli ya da yeni ObjectsQueryRequest/Response türleri olarak oluşturulmalıdır. +>>>>>>> 82edf2d (New md files from RunPod) + +#### İstek Şeması (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +**Mevcut StructuredQueryRequest'ten yapılan değişikliklerin gerekçesi:** +<<<<<<< HEAD +Diğer sorgu hizmetlerinin kalıbına uygun olarak `user` ve `collection` alanları eklendi. +======= +Diğer sorgu hizmetlerinin kalıbına uygun olması için `user` ve `collection` alanları eklendi. +>>>>>>> 82edf2d (New md files from RunPod) +Bu alanlar, Cassandra anahtar alanını ve koleksiyonu tanımlamak için gereklidir. +Değişkenler şu anda Map(String()) olarak kalmaktadır, ancak ideal olarak tüm JSON türlerini desteklemelidir. + +#### Yanıt Şeması (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**Mevcut StructuredQueryResponse'tan yapılan değişikliklerin gerekçesi:** +Sistem hatalarını (`error`) ve GraphQL hatalarını (`errors`) ayırır. +Dizi yerine yapılandırılmış GraphQLError nesneleri kullanır. +GraphQL spesifikasyonuna uygunluk için `extensions` alanı eklenmiştir. +Uyumluluk için verileri JSON dizesi olarak tutar, ancak yerel türler tercih edilir. + +### Cassandra Sorgu Optimizasyonu + +Hizmet, Cassandra sorgularını aşağıdaki şekilde optimize edecektir: + +1. **Bölüm Anahtarlarına Saygı Gösterme:** + Her zaman sorgularda koleksiyonu dahil edin. + Şema tanımlı birincil anahtarları verimli bir şekilde kullanın. + Tam tablo taramalarından kaçının. + +2. **Dizinleri Kullanma:** + Filtreleme için ikincil dizinleri kullanın. + Mümkün olduğunda birden fazla filtreyi birleştirin. + Sorguların verimsiz olabileceği durumlarda uyarı verin. + +3. **Toplu Yükleme:** + İlişki sorgularını toplayın. + Gidiş-dönüş sayısını azaltmak için toplu olarak çalıştırın. + Sonuçları istek bağlamı içinde önbelleğe alın. + +4. **Bağlantı Yönetimi:** + Kalıcı Cassandra oturumlarını koruyun. + Bağlantı havuzunu kullanın. + Hatalarda yeniden bağlanmayı yönetin. + +### Örnek GraphQL Sorguları + +#### Basit Koleksiyon Sorgusu +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### İlişkilere Sahip Sorgular +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### Sayfalı Sorgu +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### Uygulama Bağımlılıkları + +**Strawberry GraphQL**: GraphQL şema tanımı ve sorgu yürütme için +**Cassandra Driver**: Veritabanı bağlantısı için (depolama modülünde zaten kullanılıyor) +**TrustGraph Base**: FlowProcessor ve şema tanımları için +**Configuration System**: Şema takibi ve güncellemeleri için + +### Komut Satırı Arayüzü + +Hizmet, aşağıdaki CLI komutunu sağlayacaktır: `kg-query-objects-graphql-cassandra` + +Argümanlar: +`--cassandra-host`: Cassandra kümesi iletişim noktası +`--cassandra-username`: Kimlik doğrulama kullanıcı adı +`--cassandra-password`: Kimlik doğrulama parolası +`--config-type`: Şemalar için yapılandırma türü (varsayılan: "schema") +Standart FlowProcessor argümanları (Pulsar yapılandırması, vb.) + +## API Entegrasyonu + +### Pulsar Konuları + +**Giriş Konusu**: `objects-graphql-query-request` +Şema: ObjectsQueryRequest +Ağ geçidi hizmetlerinden GraphQL sorguları alır + +**Çıkış Konusu**: `objects-graphql-query-response` +Şema: ObjectsQueryResponse +Sorgu sonuçlarını ve hataları döndürür + +### Ağ Geçidi Entegrasyonu + +Ağ geçidi ve ters ağ geçidi, aşağıdaki işlemleri gerçekleştirmek için uç noktalarına ihtiyaç duyacaktır: +1. İstemcilerden GraphQL sorgularını kabul etme +2. Sorguları Pulsar üzerinden sorgu hizmetine yöneltme +3. Yanıtları istemcilere döndürme +4. GraphQL introspeksiyon sorgularını destekleme + +### Aracılık Aracı Entegrasyonu + +Yeni bir aracılık aracı sınıfı, aşağıdaki özellikleri sağlayacaktır: +Doğal dili GraphQL sorgusuna dönüştürme +Doğrudan GraphQL sorgusu yürütme +Sonuçların yorumlanması ve biçimlendirilmesi +Aracılık karar akışlarıyla entegrasyon + +## Güvenlik Hususları + +<<<<<<< HEAD +**Sorgu Derinliği Sınırlaması**: Performans sorunlarına neden olabilecek derinlemesine iç içe sorguları önleme +**Sorgu Karmaşıklığı Analizi**: Kaynak tükenmesini önlemek için sorgu karmaşıklığını sınırlama +**Alan Düzeyi İzinleri**: Kullanıcı rollerine göre alan düzeyinde erişim kontrolü için gelecekteki destek +**Giriş Temizleme**: Enjeksiyon saldırılarını önlemek için tüm sorgu girişlerini doğrulama ve temizleme +**Hız Sınırlaması**: Kullanıcı/koleksiyon başına sorgu hız sınırlaması uygulama +======= +**Sorgu Derinliği Sınırlandırması**: Performans sorunlarına neden olabilecek derinlemesine iç içe sorguları önleme +**Sorgu Karmaşıklığı Analizi**: Kaynak tükenmesini önlemek için sorgu karmaşıklığını sınırlama +**Alan Düzeyi İzinleri**: Kullanıcı rollerine göre alan düzeyinde erişim kontrolü için gelecekteki destek +**Giriş Temizleme**: Enjeksiyon saldırılarını önlemek için tüm sorgu girişlerini doğrulama ve temizleme +**Hız Sınırlandırması**: Kullanıcı/koleksiyon başına sorgu hız sınırlandırması uygulama +>>>>>>> 82edf2d (New md files from RunPod) + +## Performans Hususları + +**Sorgu Planlama**: CQL oluşturmayı optimize etmek için sorguları yürütmeden önce analiz etme +**Sonuç Önbelleği**: Sık erişilen verileri alan çözümleyici düzeyinde önbelleğe alma +**Bağlantı Havuzu**: Cassandra'ya verimli bağlantı havuzları sağlama +**Toplu İşlemler**: Mümkün olduğunda birden fazla sorguyu birleştirme, gecikmeyi azaltma +**İzleme**: Optimizasyon için sorgu performans metriklerini izleme + +## Test Stratejisi + +### Birim Testleri +RowSchema tanımlarından şema oluşturma +GraphQL sorgusu ayrıştırma ve doğrulama +CQL sorgusu oluşturma mantığı +Alan çözümleyici uygulamaları + +### Sözleşme Testleri +Pulsar mesaj sözleşmesi uyumluluğu +GraphQL şema geçerliliği +Yanıt formatı doğrulaması +Hata yapısı doğrulaması + +### Entegrasyon Testleri +Test Cassandra örneğine karşı uçtan uca sorgu yürütme +Şema güncelleme işleme +İlişki çözümü +Sayfalama ve filtreleme +Hata senaryoları + +### Performans Testleri +Yük altında sorgu verimliliği +Çeşitli sorgu karmaşıklıkları için yanıt süresi +Büyük sonuç kümeleriyle bellek kullanımı +Bağlantı havuzu verimliliği + +## Geçiş Planı + +Bu yeni bir özellik olduğu için herhangi bir geçiş gerekli değildir. Hizmet şunları yapacaktır: +1. Mevcut şemaları yapılandırmadan okuyacaktır +2. Depolama modülü tarafından oluşturulan mevcut Cassandra tablolarına bağlanacaktır +3. Dağıtım üzerine hemen sorguları kabul etmeye başlayacaktır + +## Zaman Çizelgesi + +1-2. Hafta: Temel hizmet uygulaması ve şema oluşturma +3. Hafta: Sorgu yürütme ve CQL çevirisi +4. Hafta: İlişki çözümü ve optimizasyon +<<<<<<< HEAD +5. Hafta: Test etme ve performans ayarlaması +======= +5. Hafta: Test ve performans ayarlaması +>>>>>>> 82edf2d (New md files from RunPod) +6. Hafta: Ağ geçidi entegrasyonu ve dokümantasyon + +## Açık Sorular + +1. **Şema Evrimi**: Hizmet, şema geçişleri sırasında sorguları nasıl işlemelidir? + Seçenek: Şema güncellemeleri sırasında sorguları kuyruğa alın + Seçenek: Aynı anda birden fazla şema sürümünü destekleyin + +2. **Önbellekleme Stratejisi**: Sorgu sonuçları önbelleğe alınmalı mı? +<<<<<<< HEAD + Dikkat edilmesi gerekenler: Zaman tabanlı son kullanma tarihi + Dikkat edilmesi gerekenler: Olay tabanlı geçersiz kılma +======= + Dikkate alınması gerekenler: Zaman tabanlı son kullanma tarihi + Dikkate alınması gerekenler: Olay tabanlı geçersiz kılma +>>>>>>> 82edf2d (New md files from RunPod) + +3. **Federasyon Desteği**: Hizmet, diğer veri kaynaklarıyla birleştirme için GraphQL federasyonunu desteklemeli mi? + Yapılandırılmış ve grafik veriler arasında birleşik sorguları etkinleştirir + +4. **Abonelik Desteği**: Hizmet, gerçek zamanlı güncellemeler için GraphQL aboneliklerini desteklemeli mi? + Ağ geçidinde WebSocket desteği gerektirir + +5. **Özel Ölçekler**: Hizmet, alan adlarına özgü veri türleri için özel ölçek türlerini desteklemeli mi? + Örnekler: DateTime, UUID, JSON alanları + +## Referanslar + +Yapılandırılmış Veri Teknik Özelliği: `docs/tech-specs/structured-data.md` +Strawberry GraphQL Dokümantasyonu: https://strawberry.rocks/ +GraphQL Özelliği: https://spec.graphql.org/ +Apache Cassandra CQL Referansı: https://cassandra.apache.org/doc/stable/cassandra/cql/ +TrustGraph Akış İşlemci Dokümantasyonu: İç dokümantasyon diff --git a/docs/tech-specs/graphql-query.zh-cn.md b/docs/tech-specs/graphql-query.zh-cn.md new file mode 100644 index 00000000..351b724a --- /dev/null +++ b/docs/tech-specs/graphql-query.zh-cn.md @@ -0,0 +1,438 @@ +--- +layout: default +title: "GraphQL 查询技术规范" +parent: "Chinese (Beta)" +--- + +# GraphQL 查询技术规范 + +> **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. + +## 概述 + +<<<<<<< HEAD +本规范描述了用于 TrustGraph 结构化数据存储在 Apache Cassandra 中的 GraphQL 查询接口的实现。 在结构化数据功能方面,本规范基于结构化数据规范 (structured-data.md),详细说明了如何对包含提取和摄取的结构化对象的 Cassandra 表执行 GraphQL 查询。 +======= +本规范描述了用于 TrustGraph 结构化数据存储在 Apache Cassandra 中的 GraphQL 查询接口的实现。 在结构化数据功能方面,本规范基于结构化数据规范 (structured-data.md),详细说明了如何针对包含提取和导入的结构化对象的 Cassandra 表执行 GraphQL 查询。 +>>>>>>> 82edf2d (New md files from RunPod) + +GraphQL 查询服务将提供一个灵活、类型安全的接口,用于查询存储在 Cassandra 中的结构化数据。 它将动态适应模式更改,支持包括对象之间的关系在内的复杂查询,并与 TrustGraph 现有的基于消息的架构无缝集成。 + +## 目标 + +**动态模式支持**: 在不重新启动服务的情况下,自动适应配置中的模式更改 +**GraphQL 标准兼容性**: 提供与现有 GraphQL 工具和客户端兼容的标准 GraphQL 接口 +**高效的 Cassandra 查询**: 将 GraphQL 查询转换为高效的 Cassandra CQL 查询,同时尊重分区键和索引 +**关系解析**: 支持用于不同对象类型之间关系的 GraphQL 字段解析器 +**类型安全**: 基于模式定义,确保类型安全地执行查询并生成响应 +**可扩展的性能**: 通过适当的连接池和查询优化,高效地处理并发查询 +**请求/响应集成**: 保持与 TrustGraph 基于 Pulsar 的请求/响应模式的兼容性 +**错误处理**: 提供全面的错误报告,用于模式不匹配、查询错误和数据验证问题 + +## 背景 + +<<<<<<< HEAD +结构化数据存储实现 (trustgraph-flow/trustgraph/storage/objects/cassandra/) 根据存储在 TrustGraph 配置系统中的模式定义,将对象写入 Cassandra 表。 这些表使用复合分区键结构,具有集合和基于模式定义的键,从而可以在集合中实现高效的查询。 +======= +结构化数据存储实现 (trustgraph-flow/trustgraph/storage/objects/cassandra/) 根据存储在 TrustGraph 配置系统中的模式定义,将对象写入 Cassandra 表。 这些表使用复合分区键结构,以及基于集合和模式定义的键,从而实现集合内部的高效查询。 +>>>>>>> 82edf2d (New md files from RunPod) + +当前的局限性,本规范旨在解决: +缺少用于存储在 Cassandra 中的结构化数据的查询接口 +无法利用 GraphQL 的强大查询功能来处理结构化数据 +缺少对相关对象之间关系遍历的支持 +<<<<<<< HEAD +缺少用于结构化数据访问的标准化查询语言 + +GraphQL 查询服务将通过以下方式弥补这些差距: +提供用于查询 Cassandra 表的标准 GraphQL 接口 +======= +缺少一种用于结构化数据访问的标准查询语言 + +GraphQL 查询服务将通过以下方式弥补这些差距: +为查询 Cassandra 表提供标准的 GraphQL 接口 +>>>>>>> 82edf2d (New md files from RunPod) +从 TrustGraph 配置动态生成 GraphQL 模式 +高效地将 GraphQL 查询转换为 Cassandra CQL +通过字段解析器支持关系解析 + +## 技术设计 + +### 架构 + +GraphQL 查询服务将作为新的 TrustGraph 流处理器实现,遵循既定的模式: + +**模块位置**: `trustgraph-flow/trustgraph/query/objects/cassandra/` + +**主要组件**: + +1. **GraphQL 查询服务处理器** + 扩展基础 FlowProcessor 类 + 实现类似于现有查询服务的请求/响应模式 + 监控配置以进行模式更新 + 保持与配置同步的 GraphQL 模式 + +2. **动态模式生成器** + 将 TrustGraph RowSchema 定义转换为 GraphQL 类型 + 创建具有适当字段定义的 GraphQL 对象类型 + 生成具有基于集合的解析器的根 Query 类型 + 在配置更改时更新 GraphQL 模式 + +3. **查询执行器** + 使用 Strawberry 库解析传入的 GraphQL 查询 + 根据当前模式验证查询 + 执行查询并返回结构化响应 + 通过详细的错误消息优雅地处理错误 + +4. **Cassandra 查询转换器** + 将 GraphQL 选择转换为 CQL 查询 + 根据可用的索引和分区键优化查询 + 处理过滤、分页和排序 + 管理连接池和会话生命周期 + +5. **关系解析器** +<<<<<<< HEAD + 实现用于对象之间关系的字段解析器 +======= + 实现对象之间关系的字段解析器 +>>>>>>> 82edf2d (New md files from RunPod) + 执行批量加载以避免 N+1 查询 + 在请求上下文中缓存解析的关系 + 支持正向和反向关系遍历 + +### 配置模式监控 + +该服务将注册一个配置处理程序以接收模式更新: + +```python +self.register_config_handler(self.on_schema_config) +``` + +当模式发生变化时: +1. 从配置中解析新的模式定义 +2. 重新生成 GraphQL 类型和解析器 +3. 更新可执行的模式 +4. 清除任何依赖于模式的缓存 + +### GraphQL 模式生成 + +对于配置中的每个 RowSchema,生成: + +1. **GraphQL 对象类型**: + 映射字段类型(string → String, integer → Int, float → Float, boolean → Boolean) + 将必需字段标记为 GraphQL 中的非空值 + 从模式中添加字段描述 + +2. **根查询字段**: +<<<<<<< HEAD + 集合查询(例如,`customers`,`transactions`) +======= + 集合查询(例如,`customers`, `transactions`) +>>>>>>> 82edf2d (New md files from RunPod) + 基于索引字段的过滤参数 + 分页支持(limit, offset) + 可排序字段的排序选项 + +3. **关系字段**: + 从模式中识别外键关系 + 为相关对象创建字段解析器 + 支持单对象和列表关系 + +### 查询执行流程 + +1. **请求接收**: + 从 Pulsar 接收 ObjectsQueryRequest + 提取 GraphQL 查询字符串和变量 + 识别用户和集合上下文 + +2. **查询验证**: + 使用 Strawberry 解析 GraphQL 查询 +<<<<<<< HEAD + 验证与当前模式 +======= + 验证与当前模式的匹配 +>>>>>>> 82edf2d (New md files from RunPod) + 检查字段选择和参数类型 + +3. **CQL 生成**: + 分析 GraphQL 选择 + 构建带有适当 WHERE 子句的 CQL 查询 + 将集合包含在分区键中 + 根据 GraphQL 参数应用过滤器 + +4. **查询执行**: + 对 Cassandra 执行 CQL 查询 + 将结果映射到 GraphQL 响应结构 + 解析任何关系字段 + 格式化响应以符合 GraphQL 规范 + +5. **响应发送**: + 创建包含结果的 ObjectsQueryResponse + 包含任何执行错误 + 通过 Pulsar 发送带有相关 ID 的响应 + +### 数据模型 + +<<<<<<< HEAD +> **注意**: `trustgraph-base/trustgraph/schema/services/structured_query.py` 中存在现有的 StructuredQueryRequest/Response 模式。但是,它缺少关键字段(用户、集合),并且使用了次优类型。以下模式代表推荐的演进,应该替换现有的模式,或者创建新的 ObjectsQueryRequest/Response 类型。 +======= +> **注意**: `trustgraph-base/trustgraph/schema/services/structured_query.py` 中已存在一个 StructuredQueryRequest/Response 模式。但是,它缺少关键字段(用户、集合),并且使用了次优类型。以下模式代表推荐的演进,应替换现有模式或创建为新的 ObjectsQueryRequest/Response 类型。 +>>>>>>> 82edf2d (New md files from RunPod) + +#### 请求模式 (ObjectsQueryRequest) + +```python +from pulsar.schema import Record, String, Map, Array + +class ObjectsQueryRequest(Record): + user = String() # Cassandra keyspace (follows pattern from TriplesQueryRequest) + collection = String() # Data collection identifier (required for partition key) + query = String() # GraphQL query string + variables = Map(String()) # GraphQL variables (consider enhancing to support all JSON types) + operation_name = String() # Operation to execute for multi-operation documents +``` + +**对现有 StructuredQueryRequest 的更改原因:** +添加了 `user` 和 `collection` 字段,以匹配其他查询服务的模式。 +<<<<<<< HEAD +这些字段对于识别 Cassandra 键空间和集合至关重要。 +======= +这些字段对于标识 Cassandra 键空间和集合至关重要。 +>>>>>>> 82edf2d (New md files from RunPod) +变量目前仍然是 Map(String()),但理想情况下应该支持所有 JSON 类型。 + +#### 响应模式 (ObjectsQueryResponse) + +```python +from pulsar.schema import Record, String, Array +from ..core.primitives import Error + +class GraphQLError(Record): + message = String() + path = Array(String()) # Path to the field that caused the error + extensions = Map(String()) # Additional error metadata + +class ObjectsQueryResponse(Record): + error = Error() # System-level error (connection, timeout, etc.) + data = String() # JSON-encoded GraphQL response data + errors = Array(GraphQLError) # GraphQL field-level errors + extensions = Map(String()) # Query metadata (execution time, etc.) +``` + +**对现有 StructuredQueryResponse 更改的理由:** +区分系统错误 (`error`) 和 GraphQL 错误 (`errors`) +使用结构化的 GraphQLError 对象,而不是字符串数组 +<<<<<<< HEAD +添加 `extensions` 字段,以符合 GraphQL 规范 +======= +添加 `extensions` 字段以符合 GraphQL 规范 +>>>>>>> 82edf2d (New md files from RunPod) +为了兼容性,将数据保留为 JSON 字符串,尽管使用原生类型会更好 + +### Cassandra 查询优化 + +该服务将通过以下方式优化 Cassandra 查询: + +1. **尊重分区键:** + 始终在查询中包含集合 + 高效使用 schema 定义的主键 + 避免全表扫描 + +2. **利用索引:** + 使用二级索引进行过滤 + 尽可能组合多个过滤器 + 当查询可能效率低下时,发出警告 + +3. **批量加载:** + 收集关系查询 + 批量执行以减少网络请求次数 + 在请求上下文中缓存结果 + +4. **连接管理:** + 维护持久的 Cassandra 会话 + 使用连接池 + 在发生故障时处理重连 + +### 示例 GraphQL 查询 + +<<<<<<< HEAD +#### 简单的集合查询 +======= +#### 简单集合查询 +>>>>>>> 82edf2d (New md files from RunPod) +```graphql +{ + customers(status: "active") { + customer_id + name + email + registration_date + } +} +``` + +#### 查询与关系 +```graphql +{ + orders(order_date_gt: "2024-01-01") { + order_id + total_amount + customer { + name + email + } + items { + product_name + quantity + price + } + } +} +``` + +#### 分页查询 +```graphql +{ + products(limit: 20, offset: 40) { + product_id + name + price + category + } +} +``` + +### 实现依赖 + +**Strawberry GraphQL**: 用于 GraphQL 模式定义和查询执行 +**Cassandra Driver**: 用于数据库连接(已在存储模块中使用) +**TrustGraph Base**: 用于 FlowProcessor 和模式定义 +**Configuration System**: 用于模式监控和更新 + +### 命令行界面 + +该服务将提供一个 CLI 命令:`kg-query-objects-graphql-cassandra` + +参数: +`--cassandra-host`: Cassandra 集群联系点 +`--cassandra-username`: 身份验证用户名 +`--cassandra-password`: 身份验证密码 +`--config-type`: 用于模式的配置类型(默认:"schema") +标准 FlowProcessor 参数(Pulsar 配置等) + +## API 集成 + +### Pulsar 主题 + +**输入主题**: `objects-graphql-query-request` +Schema: ObjectsQueryRequest +接收来自网关服务的 GraphQL 查询 + +**输出主题**: `objects-graphql-query-response` +Schema: ObjectsQueryResponse +返回查询结果和错误 + +### 网关集成 + +网关和反向网关需要端点来: +1. 接受来自客户端的 GraphQL 查询 +2. 通过 Pulsar 将其转发到查询服务 +3. 将响应返回给客户端 +4. 支持 GraphQL 内省查询 + +### 代理工具集成 + +一个新的代理工具类将启用: +自然语言到 GraphQL 查询的生成 +直接 GraphQL 查询执行 +结果解释和格式化 +与代理决策流程的集成 + +## 安全注意事项 + +**查询深度限制**: 阻止深度嵌套的查询,以防止性能问题 +**查询复杂度分析**: 限制查询复杂度以防止资源耗尽 +**字段级权限**: 未来支持基于用户角色的字段级访问控制 +**输入验证**: 验证和清理所有查询输入以防止注入攻击 +**速率限制**: 为每个用户/集合实施查询速率限制 + +## 性能注意事项 + +**查询规划**: 在执行之前分析查询以优化 CQL 生成 +**结果缓存**: 考虑缓存频繁访问的数据,位于字段解析器级别 +**连接池**: 维护与 Cassandra 的高效连接池 +**批量操作**: 尽可能组合多个查询以减少延迟 +**监控**: 跟踪查询性能指标以进行优化 + +## 测试策略 + +### 单元测试 +从 RowSchema 定义生成模式 +GraphQL 查询解析和验证 +CQL 查询生成逻辑 +字段解析器实现 + +### 契约测试 +Pulsar 消息契约合规性 +GraphQL 模式有效性 +响应格式验证 +错误结构验证 + +### 集成测试 +对测试 Cassandra 实例执行端到端查询 +模式更新处理 +关系解析 +分页和过滤 +错误场景 + +### 性能测试 +负载下的查询吞吐量 +各种查询复杂度的响应时间 +大结果集下的内存使用情况 +连接池效率 + +## 迁移计划 + +<<<<<<< HEAD +由于这是一个新功能,因此不需要迁移。该服务将: +======= +由于这是一个新功能,因此不需要迁移。 该服务将: +>>>>>>> 82edf2d (New md files from RunPod) +1. 从配置中读取现有模式 +2. 连接到存储模块创建的现有 Cassandra 表 +3. 立即在部署后开始接受查询 + +## 时间表 + +第 1-2 周:核心服务实现和模式生成 +第 3 周:查询执行和 CQL 转换 +第 4 周:关系解析和优化 +第 5 周:测试和性能调整 +第 6 周:网关集成和文档 + +## 开放问题 + +1. **模式演进**: 服务应该如何处理查询期间的模式转换? + 选项:在模式更新期间排队查询 + 选项:同时支持多个模式版本 + +2. **缓存策略**: 是否应该缓存查询结果? + 考虑:基于时间的过期 + 考虑:基于事件的失效 + +3. **联邦支持**: 该服务是否应该支持 GraphQL 联邦,以与其他数据源组合? + 将启用跨结构化和图形数据的统一查询 + +4. **订阅支持**: 该服务是否应该支持 GraphQL 订阅以进行实时更新? + 需要网关中的 WebSocket 支持 + +5. **自定义标量**: 是否应该支持自定义标量类型,用于特定领域的的数据类型? + 示例:DateTime、UUID、JSON 字段 + +## 参考文献 + +结构化数据技术规范:`docs/tech-specs/structured-data.md` +Strawberry GraphQL 文档:https://strawberry.rocks/ +GraphQL 规范:https://spec.graphql.org/ +Apache Cassandra CQL 参考:https://cassandra.apache.org/doc/stable/cassandra/cql/ +TrustGraph Flow Processor 文档:内部文档 diff --git a/docs/tech-specs/graphrag-performance-optimization.ar.md b/docs/tech-specs/graphrag-performance-optimization.ar.md new file mode 100644 index 00000000..06d0a6ef --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.ar.md @@ -0,0 +1,770 @@ +--- +layout: default +title: "GraphRAG Performance Optimisation Technical Specification" +parent: "Arabic (Beta)" +--- + +# GraphRAG Performance Optimisation 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 + +يصف هذا المستند تفصيليًا تحسينات الأداء الشاملة لخوارزمية GraphRAG (Graph Retrieval-Augmented Generation) في TrustGraph. تعاني التنفيذ الحالي من نقاط اختناق أداء كبيرة تحد من قابلية التوسع وأوقات الاستجابة. يتناول هذا المستند أربعة مجالات رئيسية للتحسين: + +1. **تحسين اجتياز الرسم البياني**: التخلص من استعلامات قاعدة البيانات المتكررة غير الفعالة وتنفيذ استكشاف الرسم البياني المجمّع. +2. **تحسين حل التسميات**: استبدال استرداد التسميات التسلسلي بعمليات متوازية/مجمعة. +3. **تحسين استراتيجية التخزين المؤقت**: تنفيذ تخزين مؤقت ذكي مع إخلاء LRU والتعبئة المسبقة. +4. **تحسين الاستعلام**: إضافة تدوين النتائج وتخزين تضمينات الاستعلام لتحسين أوقات الاستجابة. + +## الأهداف + +**تقليل حجم استعلامات قاعدة البيانات**: تحقيق تقليل بنسبة 50-80٪ في إجمالي استعلامات قاعدة البيانات من خلال التجميع والتخزين المؤقت. +<<<<<<< HEAD +**تحسين أوقات الاستجابة**: استهداف سرعة بناء الرسوم البيانية الفرعية بمقدار 3-5 مرات وسرعة حل التسميات بمقدار 2-3 مرات. +**تعزيز قابلية التوسع**: دعم رسوم بيانية معرفية أكبر مع إدارة أفضل للذاكرة. +======= +**تحسين أوقات الاستجابة**: استهداف سرعة بناء الرسوم البيانية الفرعية 3-5 مرات أسرع وسرعة حل التسميات 2-3 مرات أسرع. +**تعزيز قابلية التوسع**: دعم رسوم بيانية معرفية أكبر مع إدارة ذاكرة أفضل. +>>>>>>> 82edf2d (New md files from RunPod) +**الحفاظ على الدقة**: الحفاظ على وظائف GraphRAG الحالية وجودة النتائج. +**تمكين التزامن**: تحسين إمكانيات المعالجة المتوازية للطلبات المتزامنة المتعددة. +**تقليل البصمة الذاكرة**: تنفيذ هياكل بيانات وإدارة ذاكرة فعالة. +**إضافة إمكانية المراقبة**: تضمين مقاييس الأداء وقدرات المراقبة. +**ضمان الموثوقية**: إضافة معالجة مناسبة للأخطاء وآليات المهلة. + +## الخلفية + +يُظهر التنفيذ الحالي لـ GraphRAG في `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` العديد من مشكلات الأداء الهامة التي تؤثر بشدة على قابلية توسع النظام: + +### المشكلات الحالية في الأداء + +**1. اجتياز الرسم البياني غير الفعال (دالة `follow_edges`، الأسطر 79-127)** +يقوم بإجراء 3 استعلامات لقاعدة البيانات لكل كيان لكل مستوى عمق. +نمط الاستعلام: استعلامات تعتمد على الموضوع، واستعلامات تعتمد على الرابط، واستعلامات تعتمد على الكائن لكل كيان. +لا يوجد تجميع: يعالج كل استعلام كيانًا واحدًا فقط في كل مرة. +<<<<<<< HEAD +لا يوجد اكتشاف دورات: يمكن إعادة زيارة نفس العقد عدة مرات. +======= +لا يوجد اكتشاف للدورات: يمكن إعادة زيارة نفس العقد عدة مرات. +>>>>>>> 82edf2d (New md files from RunPod) +يؤدي التنفيذ المتكرر بدون تدوين إلى تعقيد أسي. +التعقيد الزمني: O(entities × max_path_length × triple_limit³) + +**2. حل تسلسلي للتسميات (دالة `get_labelgraph`، الأسطر 144-171)** +يعالج كل مكون ثلاثي (موضوع، رابط، كائن) بالتسلسل. +قد يؤدي كل استدعاء لـ `maybe_label` إلى استعلام لقاعدة البيانات. +لا يوجد تنفيذ متوازي أو تجميع لاستعلامات التسمية. +<<<<<<< HEAD +يؤدي إلى ما يصل إلى 3 × استعلامات قاعدة بيانات فردية بحجم الرسم البياني الفرعي. +======= +يؤدي إلى ما يصل إلى 3 × استعلامات قاعدة البيانات الفردية لحجم الرسم البياني الفرعي. +>>>>>>> 82edf2d (New md files from RunPod) + +**3. استراتيجية تخزين مؤقت بدائية (دالة `maybe_label`، الأسطر 62-77)** +ذاكرة تخزين مؤقت بسيطة للقواميس بدون حدود حجم أو TTL. +لا توجد سياسة إخلاء للتخزين المؤقت تؤدي إلى نمو غير محدود للذاكرة. +تؤدي أخطاء التخزين المؤقت إلى استعلامات قاعدة بيانات فردية. +لا يوجد تعبئة مسبقة أو تخزين مؤقت ذكي. + +**4. أنماط استعلام دون المستوى الأمثل** +استعلامات تشابه متجه الكيان غير مخزنة مؤقتًا بين الطلبات المتشابهة. +لا يوجد تدوين للنتائج لأنماط الاستعلام المتكررة. +<<<<<<< HEAD +أنماط استعلام مفقودة للوصول الشائع. +======= +أنماط استعلام مفقودة للتحسين للأنماط الشائعة للوصول. +>>>>>>> 82edf2d (New md files from RunPod) + +**5. مشكلات حرجة في عمر الكائن (`rag.py:96-102`)** +**يتم إعادة إنشاء كائن GraphRag لكل طلب**: يتم إنشاء نسخة جديدة لكل استعلام، مما يفقد جميع فوائد التخزين المؤقت. +**عمر كائن الاستعلام قصير للغاية**: يتم إنشاؤه وتدميره داخل تنفيذ استعلام واحد (الأسطر 201-207). +**يتم إعادة تعيين ذاكرة التخزين المؤقت للتسميات لكل طلب**: يتم فقد التخزين المؤقت والتراكم المعرفي بين الطلبات. +**نفقات إعادة إنشاء العميل**: قد يتم إعادة إنشاء عملاء قاعدة البيانات لكل طلب. +**لا يوجد تحسين عبر الطلبات**: لا يمكن الاستفادة من أنماط الاستعلام أو مشاركة النتائج. + +### تحليل تأثير الأداء + +السيناريو الأسوأ الحالي لطلب نموذجي: +**استرداد الكيان**: استعلام واحد لتقارب المتجهات. +**اجتياز الرسم البياني**: entities × max_path_length × 3 × triple_limit استعلامات. +**حل التسميات**: subgraph_size × 3 استعلامات تسمية فردية. + +<<<<<<< HEAD +للإعدادات الافتراضية (50 كيانًا، وطول المسار 2، وقيود على 30 ثلاثية، وحجم الرسم البياني الفرعي 150): +**عدد الاستعلامات:** 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9451 استعلامًا لقاعدة البيانات** +======= +للإعدادات الافتراضية (50 كيانًا، وطول المسار 2، وقيود على 30 ثلاثية، وحجم الرسوم البيانية الفرعية 150): +**الاستعلامات الدنيا:** 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9451 استعلامًا لقاعدة البيانات** +>>>>>>> 82edf2d (New md files from RunPod) +**وقت الاستجابة:** 15-30 ثانية للرسوم البيانية متوسطة الحجم +**استخدام الذاكرة:** نمو غير محدود لذاكرة التخزين المؤقت بمرور الوقت +**فعالية التخزين المؤقت:** 0% - يتم إعادة تعيين ذاكرة التخزين المؤقت في كل طلب +**تكلفة إنشاء الكائنات:** يتم إنشاء كائنات GraphRag + Query وتدميرها لكل طلب + +تعالج هذه المواصفات هذه الثغرات من خلال تنفيذ الاستعلامات المجمعة، والتخزين المؤقت الذكي، والمعالجة المتوازية. من خلال تحسين أنماط الاستعلام والوصول إلى البيانات، يمكن لـ TrustGraph: +<<<<<<< HEAD +دعم رسوم بيانية معرفية على نطاق المؤسسات تحتوي على ملايين الكيانات +توفير أوقات استجابة أقل من ثانية للاستعلامات النموذجية +التعامل مع مئات طلبات GraphRAG المتزامنة +التوسع بكفاءة مع حجم الرسم البياني وتعقيده +======= +دعم الرسوم البيانية المعرفية على نطاق المؤسسات مع ملايين الكيانات +توفير أوقات استجابة أقل من ثانية للاستعلامات النموذجية +التعامل مع مئات طلبات GraphRAG المتزامنة +التوسع بكفاءة مع حجم وتعقيد الرسم البياني +>>>>>>> 82edf2d (New md files from RunPod) + +## التصميم الفني + +### البنية + +يتطلب تحسين أداء GraphRAG المكونات الفنية التالية: + +#### 1. **إعادة هيكلة دورة حياة الكائنات** + **جعل GraphRag يعمل لفترة أطول:** نقل مثيل GraphRag إلى مستوى المعالج للاستمرارية عبر الطلبات + **الحفاظ على ذاكرة التخزين المؤقت:** الحفاظ على ذاكرة التخزين المؤقت للتسميات، وذاكرة التخزين المؤقت للتضمينات، وذاكرة التخزين المؤقت لنتائج الاستعلام بين الطلبات + **تحسين كائن الاستعلام:** إعادة هيكلة الاستعلام كسياق تنفيذ خفيف الوزن، وليس حاوية بيانات +<<<<<<< HEAD + **استمرارية الاتصال:** الحفاظ على اتصالات عميل قاعدة البيانات عبر الطلبات + + الوحدة: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (تم التعديل) + +#### 2. **محرك اجتياز الرسم البياني المحسن** + استبدال `follow_edges` التكراري ببحث عرضي تكراري + تنفيذ معالجة مجمعة للكيانات في كل مستوى من مستويات الاجتياز +======= + **استمرار الاتصال:** الحفاظ على اتصالات عميل قاعدة البيانات عبر الطلبات + + الوحدة: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (تم التعديل) + +#### 2. **محرك اجتياز الرسوم البيانية المحسن** + استبدال `follow_edges` التكراري ببحث عرضي تكراري + تنفيذ معالجة الكيانات المجمعة في كل مستوى من مستويات الاجتياز +>>>>>>> 82edf2d (New md files from RunPod) + إضافة اكتشاف الدورات باستخدام تتبع العقد التي تمت زيارتها + تضمين الإنهاء المبكر عند الوصول إلى الحدود + + الوحدة: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **نظام حل التسميات المتوازي** + تجميع استعلامات التسميات لعدة كيانات في وقت واحد + تنفيذ أنماط async/await للوصول المتزامن إلى قاعدة البيانات + إضافة استرجاع استباقي لأنماط التسميات الشائعة + تضمين استراتيجيات تسخين ذاكرة التخزين المؤقت للتسميات + + الوحدة: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **طبقة تخزين مؤقت محافظة للتسميات** +<<<<<<< HEAD + ذاكرة تخزين مؤقت LRU مع TTL قصيرة للتسميات فقط (5 دقائق) لتحقيق التوازن بين الأداء والاتساق + مراقبة مقاييس ذاكرة التخزين المؤقت ونسبة النجاح + **لا يوجد تخزين مؤقت للتضمينات:** يتم تخزينها بالفعل لكل استعلام، ولا يوجد فائدة عبر الاستعلامات + **لا يوجد تخزين مؤقت لنتائج الاستعلام:** بسبب مخاوف اتساق تغييرات الرسم البياني +======= + ذاكرة تخزين مؤقت LRU مع TTL قصيرة للتسميات فقط (5 دقائق) لتحقيق التوازن بين الأداء مقابل الاتساق + مراقبة مقاييس ذاكرة التخزين المؤقت ونسبة الإصابة + **لا يوجد تخزين مؤقت للتضمينات:** يتم تخزينها بالفعل لكل استعلام، ولا يوجد فائدة عبر الاستعلامات + **لا يوجد تخزين مؤقت لنتائج الاستعلام:** بسبب مخاوف اتساق تعديل الرسم البياني +>>>>>>> 82edf2d (New md files from RunPod) + + الوحدة: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **إطار تحسين الاستعلام** + تحليل الاستعلام واقتراحات التحسين + منسق استعلامات مجمعة للوصول إلى قاعدة البيانات + تجميع الاتصالات وإدارة مهلة الاستعلام + مراقبة الأداء وجمع المقاييس + + الوحدة: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### نماذج البيانات + +<<<<<<< HEAD +#### حالة اجتياز الرسم البياني المحسنة +======= +#### حالة اجتياز الرسوم البيانية المحسنة +>>>>>>> 82edf2d (New md files from RunPod) + +يحتفظ محرك الاجتياز بالحالة لتجنب العمليات المتكررة: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +تسمح هذه الطريقة بما يلي: +الكشف الفعال عن الدورات من خلال تتبع الكيانات التي تمت زيارتها. +إعداد استعلامات مجمعة في كل مستوى من مستويات التكرار. +إدارة حالة فعالة من حيث الذاكرة. +الإنهاء المبكر عند الوصول إلى حدود الحجم. + +#### هيكل ذاكرة تخزين مؤقتة مُحسّن + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### هياكل الاستعلامات المجمعة + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### واجهات برمجة التطبيقات (APIs) + +#### واجهات برمجة تطبيقات جديدة: + +**واجهة برمجة تطبيقات GraphTraversal** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**واجهة برمجة تطبيقات (API) لحل مشكلات التسمية الدفعية.** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**واجهة برمجة تطبيقات إدارة ذاكرة التخزين المؤقت** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### واجهات برمجة التطبيقات (APIs) المعدلة: + +**GraphRag.query()** - تم تحسينها مع تحسينات في الأداء: +إضافة معلمة `cache_manager` للتحكم في التخزين المؤقت. +تضمين قيمة الإرجاع `performance_metrics`. +إضافة معلمة `query_timeout` للموثوقية. + +**فئة Query** - تم إعادة هيكلتها لمعالجة الدفعات: +استبدال معالجة الكيانات الفردية بعمليات الدفعات. +إضافة مديري سياق غير متزامنين لتنظيف الموارد. +<<<<<<< HEAD +تضمين استدعاءات رد الاتصال للتقدم لعمليات طويلة الأمد. +======= +تضمين ردود اتصال التقدم للعمليات التي تستغرق وقتًا طويلاً. +>>>>>>> 82edf2d (New md files from RunPod) + +### تفاصيل التنفيذ + +#### المرحلة 0: إعادة هيكلة عمرية معمارية حاسمة + +**التنفيذ الحالي الذي يمثل مشكلة:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +**هيكل معماري مُحسّن وعالي الأداء:** +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +هذا التغيير المعماري يوفر: +**تقليل بنسبة 10-20٪ في استعلامات قاعدة البيانات** للرسوم البيانية التي تحتوي على علاقات شائعة (مقارنة بـ 0٪ حاليًا). +**إزالة تكلفة إنشاء الكائنات** لكل طلب. +**تجميع الاتصالات المستمرة وإعادة استخدام العملاء**. +**تحسينات عبر الطلبات** ضمن إطارات زمنية للتخزين المؤقت (TTL). + +**قيود مهمة تتعلق بتناسق التخزين المؤقت:** +<<<<<<< HEAD +يؤدي التخزين المؤقت طويل الأجل إلى خطر حدوث بيانات قديمة عندما يتم حذف الكيانات/التصنيفات أو تعديلها في الرسم البياني الأساسي. يوفر التخزين المؤقت الأقل استخدامًا (LRU) مع إطار زمني للتخزين (TTL) توازنًا بين مكاسب الأداء وحداثة البيانات، ولكنه لا يمكنه اكتشاف تغييرات الرسم البياني في الوقت الفعلي. +======= +يؤدي التخزين المؤقت طويل الأجل إلى خطر حدوث بيانات قديمة عندما يتم حذف الكيانات/التصنيفات أو تعديلها في الرسم البياني الأساسي. يوفر التخزين المؤقت الأقل استخدامًا (LRU) مع TTL توازنًا بين مكاسب الأداء وحداثة البيانات، ولكنه لا يمكنه اكتشاف تغييرات الرسم البياني في الوقت الفعلي. +>>>>>>> 82edf2d (New md files from RunPod) + +#### المرحلة الأولى: تحسين اجتياز الرسم البياني. + +**مشاكل التنفيذ الحالية:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**التنفيذ الأمثل:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### المرحلة الثانية: حل التسميات المتوازية + +**التنفيذ التسلسلي الحالي:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**التنفيذ المتوازي المُحسّن:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### المرحلة الثالثة: استراتيجية التخزين المؤقت المتقدمة + +**ذاكرة تخزين مؤقت LRU مع TTL:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### المرحلة الرابعة: تحسين الاستعلامات والمراقبة + +**جمع مقاييس الأداء:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**مهلة الاستعلام وقاطع الدائرة:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## اعتبارات تناسق ذاكرة التخزين المؤقت + +**موازنات بين قدوم البيانات:** +**ذاكرة تخزين مؤقت للتسميات (TTL مدته 5 دقائق):** خطر عرض تسميات الكيانات المحذوفة/المُعادة تسميتها. +**لا يوجد تخزين مؤقت للتضمينات:** غير ضروري - يتم تخزين التضمينات بالفعل لكل استعلام. +**لا يوجد تخزين مؤقت للنتائج:** يمنع النتائج الفرعية غير المستقرة من الرسوم البيانية الناتجة عن الكيانات/العلاقات المحذوفة. + +**استراتيجيات التخفيف:** +**قيم TTL محافظة:** الموازنة بين مكاسب الأداء (10-20٪) مع تحديث البيانات. +**خطافات إبطال ذاكرة التخزين المؤقت:** تكامل اختياري مع أحداث تعديل الرسم البياني. +**لوحات مراقبة:** تتبع معدلات نجاح ذاكرة التخزين المؤقت مقابل حوادث عدم الاستقرار. +**سياسات ذاكرة تخزين مؤقت قابلة للتكوين:** السماح بضبط لكل توزيع بناءً على تكرار التعديل. + +<<<<<<< HEAD +**تكوين ذاكرة التخزين المؤقت الموصى به بناءً على معدل تعديل الرسم البياني:** +======= +**تكوين ذاكرة التخزين المؤقت الموصى به حسب معدل تعديل الرسم البياني:** +>>>>>>> 82edf2d (New md files from RunPod) +**تعديل مرتفع (>100 تغيير/ساعة):** TTL=60 ثانية، أحجام ذاكرة تخزين مؤقت أصغر. +**تعديل متوسط (10-100 تغيير/ساعة):** TTL=300 ثانية (افتراضي). +**تعديل منخفض (<10 تغيير/ساعة):** TTL=600 ثانية، أحجام ذاكرة تخزين مؤقت أكبر. + +## اعتبارات الأمان + +**منع حقن الاستعلام:** +التحقق من صحة جميع معرفات الكيانات ومعلمات الاستعلام. +استخدم استعلامات مُعلمات لجميع التفاعلات مع قاعدة البيانات. +تنفيذ حدود تعقيد الاستعلام لمنع هجمات الحرمان من الخدمة. + +**حماية الموارد:** +<<<<<<< HEAD +فرض حدود قصوى لحجم الرسم البياني. +======= +فرض حدود قصوى لحجم الرسم البياني الفرعي. +>>>>>>> 82edf2d (New md files from RunPod) +تنفيذ مهلات الاستعلام لمنع استنفاد الموارد. +إضافة مراقبة حدود استخدام الذاكرة. + +**التحكم في الوصول:** +الحفاظ على عزل المستخدمين والمجموعات الحالي. +إضافة تسجيل تدقيق للعمليات التي تؤثر على الأداء. +تنفيذ تحديد المعدل للعمليات المكلفة. + +## اعتبارات الأداء + +### التحسينات المتوقعة في الأداء + +**تقليل عدد الاستعلامات:** +الحالي: ~9000+ استعلام للطلب النموذجي. +مُحسَّن: ~50-100 استعلام مجمعة (تقليل بنسبة 98٪). + +**تحسينات في وقت الاستجابة:** +اجتياز الرسم البياني: 15-20 ثانية → 3-5 ثوانٍ (أسرع بـ 4-5 مرات). +<<<<<<< HEAD +حل التسميات: 8-12 ثانية → 2-4 ثوانٍ (أسرع بـ 3 مرات). +الاستعلام الإجمالي: 25-35 ثانية → 6-10 ثوانٍ (تحسين بنسبة 3-4 مرات). +======= +حل التسمية: 8-12 ثانية → 2-4 ثوانٍ (أسرع بـ 3 مرات). +الاستعلام الإجمالي: 25-35 ثانية → 6-10 ثوانٍ (تحسين بـ 3-4 مرات). +>>>>>>> 82edf2d (New md files from RunPod) + +**كفاءة الذاكرة:** +تمنع أحجام ذاكرة التخزين المؤقت المحددة تسرب الذاكرة. +تقلل الهياكل البيانية الفعالة من البصمة الذاكرة بنسبة ~40٪. +<<<<<<< HEAD +جمع القمامة بشكل أفضل من خلال التنظيف المناسب للموارد. +======= +تحسين جمع البيانات المهملة من خلال التنظيف المناسب للموارد. +>>>>>>> 82edf2d (New md files from RunPod) + +**توقعات واقعية للأداء:** +**ذاكرة تخزين مؤقت للتسميات:** تقليل استعلام بنسبة 10-20٪ للرسوم البيانية ذات العلاقات الشائعة. +**تحسين التجميع:** تقليل استعلام بنسبة 50-80٪ (التحسين الأساسي). +**تحسين عمر الكائن:** إزالة النفقات العامة لإنشاء الطلبات لكل طلب. +<<<<<<< HEAD +**تحسين إجمالي:** تحسين وقت الاستجابة بنسبة 3-4 مرات بشكل أساسي من خلال التجميع. +======= +**تحسين إجمالي:** تحسين وقت الاستجابة بـ 3-4 مرات بشكل أساسي من خلال التجميع. +>>>>>>> 82edf2d (New md files from RunPod) + +**تحسينات قابلية التوسع:** +دعم رسوم بيانية معرفية أكبر بـ 3-5 مرات (محدود بمتطلبات تناسق ذاكرة التخزين المؤقت). +سعة أعلى للطلبات المتزامنة بـ 3-5 مرات. +استخدام أفضل للموارد من خلال إعادة استخدام الاتصالات. + +### مراقبة الأداء + +**مقاييس في الوقت الفعلي:** +أوقات تنفيذ الاستعلام حسب نوع العملية. +نسب نجاح ذاكرة التخزين المؤقت وفعاليتها. +استخدام مجموعة اتصالات قاعدة البيانات. +<<<<<<< HEAD +استخدام الذاكرة وتأثير جمع القمامة. +======= +استخدام الذاكرة وتأثير جمع البيانات المهملة. +>>>>>>> 82edf2d (New md files from RunPod) + +**قياس الأداء:** +اختبارات انحدار الأداء الآلية +اختبارات التحميل باستخدام أحجام بيانات واقعية +معايير مقارنة مقابل التنفيذ الحالي + +## استراتيجية الاختبار + +<<<<<<< HEAD +### اختبارات الوحدة +اختبار المكونات الفردية للتنقل والتخزين المؤقت وحل التسميات +محاكاة تفاعلات قاعدة البيانات لأغراض اختبار الأداء +اختبار إزالة التخزين المؤقت وانتهاء صلاحية TTL +معالجة الأخطاء وسيناريوهات المهلة الزمنية + +### اختبار التكامل +اختبار شامل لاستعلامات GraphRAG مع التحسينات +======= +### اختبار الوحدة +اختبار المكونات الفردية للتنقل والتخزين المؤقت وحل التسميات +محاكاة تفاعلات قاعدة البيانات لأغراض اختبار الأداء +اختبار إزالة التخزين المؤقت وانتهاء صلاحية TTL +معالجة الأخطاء وسيناريوهات المهلة + +### اختبار التكامل +اختبار شامل لاستعلام GraphRAG مع التحسينات +>>>>>>> 82edf2d (New md files from RunPod) +اختبار تفاعلات قاعدة البيانات باستخدام بيانات حقيقية +معالجة الطلبات المتزامنة وإدارة الموارد +اكتشاف تسرب الذاكرة والتحقق من تنظيف الموارد + +### اختبار الأداء +اختبارات قياس الأداء مقابل التنفيذ الحالي +<<<<<<< HEAD +اختبارات التحميل بأحجام وتعقيدات رسومية مختلفة +======= +اختبارات التحميل بأحجام وتعقيدات رسوم بيانية مختلفة +>>>>>>> 82edf2d (New md files from RunPod) +اختبارات الضغط لحدود الذاكرة والاتصالات +اختبارات الانحدار لتحسينات الأداء + +### اختبار التوافق +التحقق من توافق واجهة برمجة تطبيقات GraphRAG الحالية +<<<<<<< HEAD +الاختبار مع قواعد بيانات رسومية مختلفة +======= +الاختبار مع قواعد بيانات رسوم بيانية مختلفة +>>>>>>> 82edf2d (New md files from RunPod) +التحقق من دقة النتائج مقارنة بالتنفيذ الحالي + +## خطة التنفيذ + +### نهج التنفيذ المباشر +نظرًا لأن واجهات برمجة التطبيقات مسموح لها بالتغيير، قم بتنفيذ التحسينات مباشرةً دون تعقيد الترحيل: + +<<<<<<< HEAD +1. **استبدال `follow_edges`:** أعد كتابة باستخدام تجول دفعي تكراري +======= +1. **استبدال `follow_edges`:** أعد كتابة باستخدام تجول مجمّع تكراري +>>>>>>> 82edf2d (New md files from RunPod) +2. **تحسين `get_labelgraph`:** قم بتنفيذ حل تسميات متوازي +3. **إضافة GraphRag طويل الأمد:** قم بتعديل المعالج للحفاظ على مثيل دائم +4. **تنفيذ التخزين المؤقت للتسميات:** أضف ذاكرة تخزين مؤقت LRU مع TTL إلى فئة GraphRag + +### نطاق التغييرات +<<<<<<< HEAD +**فئة الاستعلام:** استبدل ~50 سطرًا في `follow_edges`، وأضف ~30 سطرًا لمعالجة الدفعات +======= +**فئة الاستعلام:** استبدل ~50 سطرًا في `follow_edges`، وأضف ~30 سطرًا لمعالجة الدُفعات +>>>>>>> 82edf2d (New md files from RunPod) +**فئة GraphRag:** أضف طبقة التخزين المؤقت (~40 سطرًا) +**فئة المعالج:** قم بتعديل لاستخدام مثيل GraphRag دائم (~20 سطرًا) +**الإجمالي:** ~140 سطرًا من التغييرات المركزة، معظمها داخل الفئات الحالية + +## الجدول الزمني + +<<<<<<< HEAD +**الأسبوع 1: التنفيذ الأساسي** +استبدل `follow_edges` بالتجول الدفعي التكراري +======= +**الأسبوع الأول: التنفيذ الأساسي** +استبدل `follow_edges` بتجول تكراري مجمّع +>>>>>>> 82edf2d (New md files from RunPod) +قم بتنفيذ حل تسميات متوازي في `get_labelgraph` +أضف مثيل GraphRag طويل الأمد إلى المعالج +قم بتنفيذ طبقة التخزين المؤقت للتسميات + +<<<<<<< HEAD +**الأسبوع 2: الاختبار والتكامل** +اختبارات الوحدة لمنطق التجول والتخزين المؤقت الجديد +قياس أداء مقابل التنفيذ الحالي +اختبار التكامل مع بيانات رسومية حقيقية +مراجعة التعليمات البرمجية والتحسين + +**الأسبوع 3: النشر** +نشر التنفيذ المحسن +مراقبة تحسينات الأداء +ضبط TTL للتخزين المؤقت وأحجام الدفعات بناءً على الاستخدام الفعلي +======= +**الأسبوع الثاني: الاختبار والتكامل** +اختبارات الوحدة لمنطق التجول والتخزين المؤقت الجديد +قياس أداء مقابل التنفيذ الحالي +اختبارات التكامل مع بيانات الرسم البياني الحقيقية +مراجعة التعليمات البرمجية والتحسين + +**الأسبوع الثالث: النشر** +نشر التنفيذ المحسن +مراقبة تحسينات الأداء +ضبط TTL للتخزين المؤقت وأحجام الدُفعات بناءً على الاستخدام الفعلي +>>>>>>> 82edf2d (New md files from RunPod) + +## أسئلة مفتوحة + +**تجميع الاتصالات بقاعدة البيانات:** هل يجب علينا تنفيذ تجميع اتصالات مخصص أم الاعتماد على تجميع عملاء قاعدة البيانات الحالي؟ +**استمرارية التخزين المؤقت:** هل يجب أن تستمر ذاكرات التخزين المؤقت للتسميات والتضمينات عبر عمليات إعادة تشغيل الخدمة؟ +**التخزين المؤقت الموزع:** بالنسبة لنشرات متعددة المثيلات، هل يجب علينا تنفيذ تخزين مؤقت موزع باستخدام Redis/Memcached؟ +**تنسيق نتيجة الاستعلام:** هل يجب علينا تحسين التمثيل الداخلي للثلاثيات لتحسين كفاءة الذاكرة؟ +**تكامل المراقبة:** ما هي المقاييس التي يجب عرضها على أنظمة المراقبة الحالية (Prometheus، إلخ)؟ + +## المراجع + +[التنفيذ الأصلي لـ GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +<<<<<<< HEAD +[مبادئ معمارية TrustGraph](architecture-principles.md) +[مواصفات إدارة المجموعة](collection-management.md) +======= +[مبادئ بنية TrustGraph](architecture-principles.md) +[مواصفات إدارة المجموعات](collection-management.md) +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/graphrag-performance-optimization.es.md b/docs/tech-specs/graphrag-performance-optimization.es.md new file mode 100644 index 00000000..66edf252 --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.es.md @@ -0,0 +1,309 @@ +--- +layout: default +title: "Especificación Técnica de Optimización de Rendimiento de GraphRAG" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Optimización de Rendimiento de GraphRAG + +> **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 de rendimiento integrales para el algoritmo GraphRAG (Graph Retrieval-Augmented Generation) en TrustGraph. La implementación actual sufre de cuellos de botella de rendimiento significativos que limitan la escalabilidad y los tiempos de respuesta. Esta especificación aborda cuatro áreas principales de optimización: + +1. **Optimización de la Recorrido del Grafo**: Eliminar consultas ineficientes a la base de datos y implementar exploración de grafos por lotes. +2. **Optimización de la Resolución de Etiquetas**: Reemplazar la obtención secuencial de etiquetas con operaciones paralelas/por lotes. +3. **Mejora de la Estrategia de Almacenamiento en Caché**: Implementar un almacenamiento en caché inteligente con desalojo LRU (Least Recently Used) y precarga. +4. **Optimización de Consultas**: Agregar memorización de resultados y almacenamiento en caché de incrustaciones para mejorar los tiempos de respuesta. + +## Objetivos + +- **Reducir el Volumen de Consultas a la Base de Datos**: Lograr una reducción del 50-80% en el volumen total de consultas a la base de datos a través del procesamiento por lotes y el almacenamiento en caché. +- **Mejorar los Tiempos de Respuesta**: Reducir el tiempo de construcción de subgrafos en un factor de 3 a 5 y el tiempo de resolución de etiquetas en un factor de 2 a 3. +- **Mejorar la Escalabilidad**: Compatibilizar con grafos de conocimiento más grandes con una mejor gestión de la memoria. +- **Mantener la Precisión**: Preservar la funcionalidad existente de GraphRAG y la calidad de los resultados. +- **Habilitar la Concurrencia**: Mejorar las capacidades de procesamiento paralelo para múltiples solicitudes concurrentes. +- **Reducir la Huella de Memoria**: Implementar estructuras de datos eficientes y gestión de la memoria. +- **Agregar Observabilidad**: Incluir métricas de rendimiento y capacidades de monitoreo. +- **Garantizar la Confiabilidad**: Agregar un manejo adecuado de errores y mecanismos de tiempo de espera. + +## Antecedentes + +La implementación actual de GraphRAG en `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` presenta varios problemas de rendimiento críticos que afectan gravemente la escalabilidad del sistema: + +### Problemas de Rendimiento Actuales + +**1. Recorrido Ineficiente del Grafo (`follow_edges` function, líneas 79-127)** +- Realiza 3 consultas separadas a la base de datos por entidad y nivel de profundidad. +- Patrón de consulta: consultas basadas en sujeto, predicado y objeto para cada entidad. +- Sin procesamiento por lotes: Cada consulta procesa solo una entidad a la vez. +- Sin detección de ciclos: Puede volver a visitar los mismos nodos varias veces. +- La implementación recursiva sin memorización conduce a una complejidad exponencial. +- Complejidad temporal: O(entidades × max_path_length × triple_limit³) + +**2. Resolución Secuencial de Etiquetas (`get_labelgraph` function, líneas 144-171)** +- Procesa cada componente de triple (sujeto, predicado, objeto) de forma secuencial. +- Cada llamada a `maybe_label` potencialmente desencadena una consulta a la base de datos. +- No hay ejecución paralela ni procesamiento por lotes de las consultas de etiquetas. +- Resulta en hasta 3 consultas individuales a la base de datos por tamaño del subgrafo. + +**3. Estrategia de Almacenamiento en Caché Primitiva (`maybe_label` function, líneas 62-77)** +- Un diccionario de caché simple sin límites de tamaño ni TTL (Time To Live). +- No hay política de desalojo de caché, lo que lleva a un crecimiento ilimitado de la memoria. +- Las fallas de caché desencadenan consultas individuales a la base de datos. +- No hay precarga ni calentamiento inteligente de la caché. + +**4. Patrones de Consulta Subóptimos** +- Las consultas de similitud de vectores de entidades no se almacenan en caché entre solicitudes similares. +- No hay memorización de resultados para patrones de consulta repetidos. +- Faltan optimizaciones de consulta para patrones de acceso comunes. + +**5. Problemas Críticos del Ciclo de Vida de los Objetos (`rag.py:96-102`)** +- **El objeto GraphRag se recrea por solicitud**: Se crea una nueva instancia para cada consulta, perdiendo todos los beneficios de la caché. +- **El objeto Query tiene una vida útil extremadamente corta**: Se crea y destruye dentro de la ejecución de una sola consulta (líneas 201-207). +- **La caché de etiquetas se restablece por solicitud**: El calentamiento de la caché y el conocimiento acumulado se pierden entre las solicitudes. +- **Sobrecarga de recreación del cliente**: Los clientes de la base de datos se restablecen potencialmente para cada solicitud. +- **No hay optimización entre solicitudes**: No se puede beneficiar de patrones de consulta o uso compartido de resultados. + +### Análisis del Impacto en el Rendimiento + +Escenario de peor caso actual para una consulta típica: +- **Recuperación de Entidades**: 1 consulta de similitud de vectores. +- **Recorrido del Grafo**: consultas de entidades × max_path_length × 3 × triple_limit. +- **Resolución de Etiquetas**: consultas individuales de tamaño del subgrafo × 3 de etiquetas. + +Para parámetros predeterminados (50 entidades, longitud de ruta 2, límite de triple 30, tamaño de subgrafo 150): +- **Número mínimo de consultas**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9.451 consultas a la base de datos**. +- **Tiempo de respuesta**: 15-30 segundos para grafos de tamaño moderado. +- **Uso de memoria**: Crecimiento ilimitado de la caché con el tiempo. +- **Eficacia de la caché**: 0% - las cachés se restablecen en cada solicitud. +- **Sobrecarga de creación de objetos**: Se crean/destruyen objetos GraphRag + Query por solicitud. + +Esta especificación aborda estas deficiencias implementando consultas por lotes, almacenamiento en caché inteligente y procesamiento paralelo. Al optimizar los patrones de consulta y el acceso a los datos, TrustGraph puede: +- Compatibilizar con grafos de conocimiento a escala empresarial con millones de entidades. +- Proporcionar tiempos de respuesta de subsegundo para consultas típicas. +- Manejar cientos de solicitudes concurrentes de GraphRAG. +- Escalar de manera eficiente con el tamaño y la complejidad del grafo. + +## Diseño Técnico + +### Arquitectura + +La optimización del rendimiento de GraphRAG requiere los siguientes componentes técnicos: + +#### 1. **Refactorización Arquitectónica del Ciclo de Vida de los Objetos** + - **Hacer que GraphRag tenga una vida útil prolongada**: Mover la instancia de GraphRag al nivel del Procesador para la persistencia entre solicitudes. + - **Preservar las cachés**: Mantener la caché de etiquetas, la caché de incrustaciones y la caché de resultados de consulta entre las solicitudes. + - **Optimizar el objeto Query**: Refactorizar Query como un contexto de ejecución ligero, no como un contenedor de datos. + - **Persistencia de la conexión**: Mantener las conexiones del cliente de la base de datos entre las solicitudes. + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (modificado) + +#### 2. **Motor de Recorrido del Grafo Optimizada** + - Reemplazar `follow_edges` recursivo con una búsqueda en amplitud iterativa. + - Implementar procesamiento por lotes de entidades en cada nivel de recorrido. + - Agregar detección de ciclos utilizando el seguimiento de nodos visitados. + - Incluir finalización temprana cuando se alcanzan los límites. + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **Sistema de Resolución de Etiquetas Paralelo** + - Consultas de etiquetas por lotes para múltiples entidades simultáneamente. + - Implementar patrones async/await para el acceso concurrente a la base de datos. + - Agregar precarga inteligente para patrones de etiquetas comunes. + - Incluir estrategias de calentamiento de etiquetas. + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **Capa de Almacenamiento en Caché Conservadora** + - Caché LRU con un TTL (Tiempo de Vida) corto para las etiquetas (5 minutos) para equilibrar el rendimiento y la coherencia. + - Métricas de caché y monitoreo de la tasa de aciertos. + - **No se almacena en caché las incrustaciones**: Ya se almacenan en caché por consulta, no hay beneficio entre consultas. + - **No se almacenan en caché los resultados de la consulta**: Debido a las preocupaciones sobre la consistencia de la mutación del grafo. + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **Marco de Optimización de Consultas** + - Análisis y sugerencias de optimización de patrones de consulta. + - Coordinador de consultas por lotes para el acceso a la base de datos. + - Pooling de conexiones y gestión de tiempos de espera de consulta. + - Monitoreo de rendimiento y recopilación de métricas. + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### Modelos de Datos + +#### Estado de Recorrido del Grafo Optimizada + +El motor de recorrido mantiene el siguiente estado: + +```python +@dataclass +class GraphTraversalState: + current_node: Node + path: List[Node] + visited_nodes: Set[Node] +``` + +#### Caching +```python +class Cache: + def __init__(self, max_size: int): + self.cache = {} + self.max_size = max_size + + def get(self, key): + if key in self.cache: + return self.cache.pop(key) + return None + + def put(self, key, value): + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + self.cache[key] = value +``` + +#### PerformanceMetrics +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +### Seguridad + +**Prevenir Inyección de Consultas:** +- Validar todos los identificadores de entidad y parámetros de consulta. +- Usar consultas parametrizadas para todas las interacciones con la base de datos. +- Implementar límites de complejidad de consulta para prevenir ataques de denegación de servicio. + +**Protección de Recursos:** +- Hacer cumplir los límites máximos del tamaño del subgrafo. +- Implementar tiempos de espera de consulta para evitar el agotamiento de recursos. +- Agregar monitoreo del uso de la memoria y límites. + +**Control de Acceso:** +- Mantener el aislamiento existente de usuarios y colecciones. +- Agregar registro de auditoría para operaciones que afectan el rendimiento. +- Implementar la limitación de velocidad para las operaciones costosas. + +## Consideraciones de Rendimiento + +### Mejoras de Rendimiento Esperadas + +**Reducción de Consultas:** +- Actual: ~9.000+ consultas por solicitud típica. +- Optimizada: ~50-100 consultas por lotes (reducción del 98%). + +**Mejoras en el Tiempo de Respuesta:** +- Recorrido del grafo: 15-20s → 3-5s (4-5 veces más rápido). +- Resolución de etiquetas: 8-12s → 2-4s (3 veces más rápido). +- Consulta general: 25-35s → 6-10s (mejora de 3-4 veces). + +**Eficiencia de la Memoria:** +- Los tamaños de caché limitados evitan las fugas de memoria. +- Las estructuras de datos eficientes reducen la huella de memoria en un ~40%. +- Mejor recolección de basura a través de una limpieza adecuada de recursos. + +**Mejoras de Escalabilidad:** +- Compatibilidad con grafos de conocimiento 3-5 veces más grandes (limitado por las necesidades de coherencia de la caché). +- Capacidad de solicitud concurrente 3-5 veces mayor. +- Mejor utilización de recursos a través de la reutilización de conexiones. + +### Monitoreo del Rendimiento + +**Métricas en Tiempo Real:** +- Tiempos de ejecución de operaciones por tipo de operación. +- Tasas de aciertos y efectividad de la caché. +- Utilización del grupo de conexiones de la base de datos. +- Uso de memoria y impacto de la recolección de basura. + +**Pruebas de Rendimiento:** +- Pruebas comparativas contra la implementación actual. +- Pruebas de carga con volúmenes de datos realistas. +- Pruebas de estrés para límites de memoria y conexión. +- Pruebas de regresión para mejoras de rendimiento. + +## Estrategia de Pruebas + +### Pruebas Unitarias +- Pruebas de componentes individuales para recorrido, almacenamiento en caché y resolución de etiquetas. +- Interacciones simuladas con la base de datos para pruebas de rendimiento. +- Pruebas de desalojo y expiración de TTL de la caché. +- Escenarios de manejo de errores y tiempo de espera. + +### Pruebas de Integración +- Pruebas de extremo a extremo de la consulta GraphRAG con optimizaciones. +- Pruebas de interacción con la base de datos con datos reales. +- Manejo de solicitudes concurrentes y gestión de recursos. +- Detección de fugas de memoria y verificación de limpieza de recursos. + +### Pruebas de Rendimiento +- Pruebas comparativas contra la implementación actual. +- Pruebas de carga con diferentes tamaños y complejidades de grafos. +- Pruebas de estrés para límites de memoria y conexión. +- Pruebas de regresión para mejoras de rendimiento. + +### Pruebas de Compatibilidad +- Verificar la compatibilidad de la API GraphRAG existente. +- Probar con varios backends de bases de datos de grafos. +- Validar la precisión de los resultados en comparación con la implementación actual. + +## Plan de Implementación + +### Enfoque de Implementación Directa +Dado que se permiten cambios en las API, implemente optimizaciones directamente sin complejidad de migración: + +1. **Reemplace el método `follow_edges`**: Reescriba con un recorrido iterativo por lotes. +2. **Optimice `get_labelgraph`**: Implemente la resolución de etiquetas en paralelo. +3. **Agregue GraphRag de larga duración**: Modifique el Procesador para usar una instancia persistente. +4. **Implemente la estrategia de almacenamiento en caché**: Agregue una capa de caché LRU a la clase GraphRag. + +### Alcance de los Cambios +- **Clase Query**: Reemplace ~50 líneas en `follow_edges`, agregue ~30 líneas de manejo por lotes. +- **Clase GraphRag**: Agregue una capa de almacenamiento en caché (~40 líneas). +- **Clase Procesador**: Modifique para usar una instancia GraphRag persistente (~20 líneas). +- **Total**: ~140 líneas de cambios enfocados, principalmente dentro de clases existentes. + +## Cronograma + +**Semana 1: Implementación Central** +- Reemplace `follow_edges` con un recorrido iterativo por lotes. +- Implemente la resolución de etiquetas en paralelo en `get_labelgraph`. +- Agregue una instancia GraphRag de larga duración al Procesador. +- Implemente la capa de almacenamiento en caché. + +**Semana 2: Pruebas e Integración** +- Pruebas unitarias para la nueva lógica de recorrido y almacenamiento en caché. +- Pruebas comparativas de rendimiento con la implementación actual. +- Pruebas de integración con datos de grafo reales. +- Revisión de código y optimización. + +**Semana 3: Implementación** +- Implemente la implementación optimizada. +- Monitoree las mejoras de rendimiento. +- Ajuste el TTL y los tamaños de lote de la caché en función del uso real. + +## Preguntas Abiertas + +- **Pooling de Conexiones de la Base de Datos**: ¿Deberíamos implementar un pooling de conexiones personalizado o confiar en el pooling de clientes de la base de datos existente? +- **Persistencia de la Caché**: ¿Deberían las cachés de etiquetas y de incrustaciones persistir entre reinicios del servicio? +- **Almacenamiento en Caché Distribuido**: Para implementaciones multi instancia, ¿deberíamos implementar un almacenamiento en caché distribuido con Redis/Memcached? +- **Formato de Resultados de Consulta**: ¿Deberíamos optimizar la representación interna del triple para una mejor eficiencia de la memoria? +- **Integración de Monitoreo**: ¿Qué métricas deben exponerse a los sistemas de monitoreo existentes (Prometheus, etc.)? + +## Referencias + +- [Implementación Original de GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +- [Principios de Arquitectura de TrustGraph](architecture-principles.md) +- [Especificación de Gestión de Colecciones](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.he.md b/docs/tech-specs/graphrag-performance-optimization.he.md new file mode 100644 index 00000000..64acf953 --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.he.md @@ -0,0 +1,807 @@ +--- +layout: default +title: "מפרט טכני לשיפור ביצועי GraphRAG" +parent: "Hebrew (Beta)" +--- + +# מפרט טכני לשיפור ביצועי GraphRAG + +> **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. + +## סקירה כללית + +<<<<<<< HEAD +מפרט זה מתאר שיפורי ביצועים מקיפים עבור אלגוריתם GraphRAG (Graph Retrieval-Augmented Generation) ב-TrustGraph. יישום הנוכחי סובל מבעיות ביצועים משמעותיות המגבילות את יכולת ההרחבה וזמני התגובה. מפרט זה מתייחס לארבעה תחומים עיקריים של אופטימיזציה: + +1. **אופטימיזציה של מעבר גרפים**: ביטול שאילתות מסד נתונים רקורסיביות לא יעילות ויישום חקר גרפים באצווה. +2. **אופטימיזציה של פתרון תגיות**: החלפת אחזור תגיות רציף בפעולות מקבילות/באצווה. +3. **שיפור אסטרטגיית אחסון במטמון**: יישום אחסון במטמון חכם עם פינוי LRU וטעינה מראש. +4. **אופטימיזציה של שאילתות**: הוספת שמירת תוצאות במטמון ואחסון במטמון של הטמעות לשיפור זמני התגובה. + +## מטרות + +**הפחתת נפח שאילתות מסד הנתונים**: השגת הפחתה של 50-80% בסך כל שאילתות מסד הנתונים באמצעות אצווה ואחסון במטמון. +**שיפור זמני תגובה**: יעד לבניית תת-גרפים מהירה פי 3-5 ופתרון תגיות מהיר פי 2-3. +**שיפור יכולת הרחבה**: תמיכה בגרפי ידע גדולים יותר עם ניהול זיכרון טוב יותר. +**שמירה על דיוק**: שמירה על פונקציונליות ואיכות תוצאות GraphRAG הקיימות. +**אפשרות לעיבוד מקבילי**: שיפור יכולות עיבוד מקבילי עבור בקשות מרובות בו-זמנית. +**הפחתת טביעת רגל של זיכרון**: יישום מבני נתונים וניהול זיכרון יעילים. +**הוספת יכולת ניטור**: הכללת מדדי ביצועים ויכולות ניטור. +**הבטחת אמינות**: הוספת טיפול בשגיאות ומנגנוני תזמון מתאימים. +======= +מפרט זה מתאר שיפורים מקיפים בביצועים עבור אלגוריתם GraphRAG (Graph Retrieval-Augmented Generation) ב-TrustGraph. יישום הנוכחי סובל מבעיות ביצועים משמעותיות המגבילות את יכולת ההרחבה וזמני התגובה. מפרט זה מתייחס לארבעה תחומים עיקריים של אופטימיזציה: + +1. **אופטימיזציה של מעבר גרפים**: ביטול שאילתות מסד נתונים רקורסיביות לא יעילות ויישום חקר גרפים בקבוצות +2. **אופטימיזציה של פתרון תגיות**: החלפת שליפת תגיות רציפה בפעולות מקבילות/בקבוצות +3. **שיפור אסטרטגיית אחסון במטמון**: יישום אחסון במטמון חכם עם פינוי LRU וטעינה מראש +4. **אופטימיזציה של שאילתות**: הוספת שמירת תוצאות במטמון ואחסון במטמון של הטמעות לשיפור זמני התגובה + +## מטרות + +**הפחתת נפח שאילתות מסד הנתונים**: השגת הפחתה של 50-80% בסך כל שאילתות מסד הנתונים באמצעות קיבוץ ואחסון במטמון +**שיפור זמני תגובה**: יעד לבניית תת-גרפים מהירה פי 3-5 ופתרון תגיות מהיר פי 2-3 +**שיפור יכולת הרחבה**: תמיכה בגרפי ידע גדולים יותר עם ניהול זיכרון טוב יותר +**שמירה על דיוק**: שמירה על פונקציונליות ואיכות תוצאות GraphRAG הקיימות +**אפשרות לעיבוד מקבילי**: שיפור יכולות עיבוד מקבילי עבור בקשות מרובות בו-זמנית +**הפחתת טביעת רגל של זיכרון**: יישום מבני נתונים וניהול זיכרון יעילים +**הוספת יכולת ניטור**: הכללת מדדי ביצועים ויכולות ניטור +**הבטחת אמינות**: הוספת טיפול מתאים בשגיאות ומנגנוני תזמון +>>>>>>> 82edf2d (New md files from RunPod) + +## רקע + +יישום GraphRAG הנוכחי ב-`trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` מציג מספר בעיות ביצועים קריטיות המשפיעות באופן משמעותי על יכולת ההרחבה של המערכת: + +### בעיות ביצועים נוכחיות + +**1. מעבר גרפים לא יעיל (פונקציה `follow_edges`, שורות 79-127)** +<<<<<<< HEAD +מבצע 3 שאילתות נפרדות למסד הנתונים עבור כל ישות בכל רמת עומק. +תבנית שאילתה: שאילתות מבוססות נושא, מבוססות פרידיקט ומבוססות אובייקט עבור כל ישות. +ללא אצווה: כל שאילתה מעבדת רק ישות אחת בכל פעם. +ללא זיהוי מעגלים: ניתן לחזור על צמתים זהים מספר פעמים. +יישום רקורסיבי ללא שמירה במטמון מוביל למורכבות אקספוננציאלית. +מורכבות זמן: O(entities × max_path_length × triple_limit³) + +**2. פתרון תגיות רציף (פונקציה `get_labelgraph`, שורות 144-171)** +מעבד כל רכיב משולש (נושא, פרידיקט, אובייקט) ברצף. +כל קריאה ל-`maybe_label` עלולה לגרום לשאילתה למסד הנתונים. +ללא ביצוע מקבילי או אצווה של שאילתות תגיות. +גורם עד ל-3 × קריאות אישיות למסד הנתונים עבור גודל תת-גרף. + +**3. אסטרטגיית אחסון במטמון בסיסית (פונקציה `maybe_label`, שורות 62-77)** +מטמון מילון פשוט ללא מגבלות גודל או TTL. +מדיניות פינוי מטמון חסרת גבולות מובילה לצמיחה בלתי מוגבלת של זיכרון. +החסרה במטמון גורמת לשאילתות נפרדות למסד הנתונים. +ללא טעינה מראש או אחסון במטמון חכם. + +**4. תבניות שאילתות לא אופטימליות** +שאילתות דמיון וקטורי לישויות אינן מאוחסנות במטמון בין בקשות דומות. +ללא שמירת תוצאות במטמון לתבניות שאילתות חוזרות. +חסרים אופטימיזציות שאילתות לתבניות גישה נפוצות. + +**5. בעיות קריטיות של חיי אובייקט (`rag.py:96-102`)** +**אובייקט GraphRag נוצר מחדש עבור כל בקשה**: מופע חדש נוצר עבור כל שאילתה, תוך אובדן כל יתרונות המטמון. +**אובייקט שאילתה בעל אורך חיים קצר ביותר**: נוצר ונהרס בתוך ביצוע שאילתה יחיד (שורות 201-207). +**מטמון תגיות מאופס עבור כל בקשה**: חימום מטמון וידע שנצבר אובדים בין בקשות. +**תקורה של יצירת לקוח מחדש**: לקוחות מסד נתונים פוטנציאליים מוקמים מחדש עבור כל בקשה. +**ללא אופטימיזציה חוצה בקשות**: לא ניתן להפיק תועלת מתבניות שאילתות או שיתוף תוצאות. +======= +מבצע 3 שאילתות נפרדות למסד הנתונים עבור כל ישות בכל רמת עומק +תבנית שאילתה: שאילתות מבוססות נושא, שאילתות מבוססות פרידיקט ושאילתות מבוססות אובייקט עבור כל ישות +ללא קיבוץ: כל שאילתה מעבדת רק ישות אחת בכל פעם +ללא זיהוי מעגלים: ניתן לחזור על צמתים זהים מספר פעמים +יישום רקורסיבי ללא שמירה במטמון מוביל למורכבות אקספוננציאלית +מורכבות זמן: O(entities × max_path_length × triple_limit³) + +**2. פתרון תגיות רציף (פונקציה `get_labelgraph`, שורות 144-171)** +מעבד כל רכיב משולש (נושא, פרידיקט, אובייקט) ברצף +כל קריאה ל-`maybe_label` עלולה לגרום לשאילתה למסד הנתונים +ללא ביצוע מקבילי או קיבוץ של שאילתות תגיות +גורם עד ל-3 × קריאות אישיות למסד הנתונים עבור גודל תת-גרף + +**3. אסטרטגיית אחסון במטמון בסיסית (פונקציה `maybe_label`, שורות 62-77)** +מטמון מילון פשוט ללא מגבלות גודל או TTL +מדיניות פינוי מטמון חסרת גבולות מובילה לצמיחה בלתי מוגבלת של זיכרון +החסרה במטמון גורמת לשאילתות נפרדות למסד הנתונים +ללא טעינה מראש או אחסון במטמון חכם + +**4. תבניות שאילתות לא אופטימליות** +שאילתות דמיון וקטורי לישויות אינן מאוחסנות במטמון בין בקשות דומות +ללא שמירת תוצאות במטמון לתבניות שאילתות חוזרות +חסרים אופטימיזציות שאילתות לתבניות גישה נפוצות + +**5. בעיות קריטיות של חיי אובייקט (`rag.py:96-102`)** +**אובייקט GraphRag נוצר מחדש עבור כל בקשה**: מופע חדש נוצר עבור כל שאילתה, ומאבד את כל יתרונות האחסון במטמון +**אובייקט שאילתה בעל אורך חיים קצר ביותר**: נוצר ונהרס בתוך ביצוע שאילתה יחידה (שורות 201-207) +**מטמון תגיות מאופס עבור כל בקשה**: חימום מטמון וידע שנצבר הולכים לאיבוד בין בקשות +**תקורה של יצירת לקוח**: לקוחות מסד נתונים פוטנציאליים נוצרים מחדש עבור כל בקשה +**ללא אופטימיזציה חוצה בקשות**: לא ניתן להפיק תועלת מתבניות שאילתות או שיתוף תוצאות +>>>>>>> 82edf2d (New md files from RunPod) + +### ניתוח השפעת ביצועים + +תרחיש גרוע ביותר נוכחי עבור שאילתה טיפוסית: +<<<<<<< HEAD +**אחזור ישות**: שאילתת דמיון וקטורית אחת. +**מעבר גרפים**: entities × max_path_length × 3 × שאילתות triple_limit. +**פתרון תגיות**: 3 × שאילתות תגיות אישיות עבור גודל תת-גרף. +פלט חוזה (יש לעקוב אחר הפורמט המדויק). +עבור פרמטרים ברירת מחדל (50 ישויות, אורך נתיב 2, מגבלת 30 משולשים, גודל תת-גרף 150): +======= +**שליפת ישות**: שאילתה אחת לדמיון וקטורי +**מעבר גרפים**: entities × max_path_length × 3 × שאילתות triple_limit +**פתרון תגיות**: 3 × שאילתות אישיות לגודל תת-גרף +פלט חוזה (יש לעקוב אחר הפורמט המדויק). +עבור פרמטרים ברירת מחדל (50 ישויות, אורך נתיב 2, מגבלת טריפל של 30, גודל תת-גרף של 150): +>>>>>>> 82edf2d (New md files from RunPod) +**מספר שאילתות מינימלי**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9,451 שאילתות למסד נתונים** +**זמן תגובה**: 15-30 שניות עבור גרפים בגודל בינוני +**שימוש בזיכרון**: צמיחה בלתי מוגבלת של מטמון לאורך זמן +**יעילות מטמון**: 0% - המטמון מאופס בכל בקשה +**תקורה של יצירת אובייקטים**: אובייקטי GraphRag + שאילתה נוצרים/נמחקים עבור כל בקשה + +מפרט זה מתייחס לפערים אלה על ידי יישום שאילתות באצווה, מטמון חכם ועיבוד מקבילי. על ידי אופטימיזציה של דפוסי שאילתות וגישה לנתונים, TrustGraph יכולה: +לתמוך בגרפי ידע בקנה מידה ארגוני עם מיליוני ישויות +לספק זמני תגובה של פחות משנייה עבור שאילתות טיפוסיות +לטפל במאות בקשות GraphRAG מקבילות +להתרחב ביעילות עם גודל ומורכבות הגרף + +## עיצוב טכני + +### ארכיטקטורה + +אופטימיזציית הביצועים של GraphRAG דורשת את הרכיבים הטכניים הבאים: + +#### 1. **שינוי ארכיטקטורה של משך חיי אובייקטים** + **הפוך את GraphRag לבעל חיים ארוך**: העבר את המופע של GraphRag לרמה של המעבד לצורך שמירה בין בקשות + **שמור על מטמון**: שמור על מטמון תוויות, מטמון הטבעות ומטמון תוצאות שאילתה בין בקשות +<<<<<<< HEAD + **אופטימיזציה של אובייקט שאילתה**: שנה את מבנה אובייקט השאילתה כהקשר ביצוע קל משקל, ולא כמכל נתונים +======= + **אופטימיזציה של אובייקט שאילתה**: שנה את מבנה אובייקט השאילתה כך שיהיה הקשר ביצוע קל משקל, ולא מיכל נתונים +>>>>>>> 82edf2d (New md files from RunPod) + **שמירה על חיבורים**: שמור על חיבורי לקוח למסד הנתונים בין בקשות + + מודול: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (עודכן) + +#### 2. **מנוע מעבר גרפים מותאם** + החלף את `follow_edges` רקורסיבי בחיפוש רוחב-ראשוני איטרטיבי +<<<<<<< HEAD + הטמעת עיבוד אצווה של ישויות בכל רמת מעבר + הוסף זיהוי מעגלים באמצעות מעקב אחר צמתים מבקרים + כלול סיום מוקדם כאשר מגיעים למגבלות +======= + הטמע עיבוד אצווה של ישויות בכל רמת מעבר + הוסף זיהוי מעגלים באמצעות מעקב אחר צמתים שנצפו + כלול סיום מוקדם כאשר מגיעים לגבולות +>>>>>>> 82edf2d (New md files from RunPod) + + מודול: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **מערכת פתרון תוויות מקבילה** + שאילתות תוויות באצווה עבור מספר ישויות בו-זמנית +<<<<<<< HEAD + הטמעת דפוסי async/await לגישה מקבילה למסד הנתונים +======= + הטמע דפוסי async/await לגישה מקבילה למסד הנתונים +>>>>>>> 82edf2d (New md files from RunPod) + הוסף אחזור מוקדם לדפוסי תוויות נפוצים + כלול אסטרטגיות חימום מטמון תוויות + + מודול: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **שכבת מטמון תוויות שמרנית** + מטמון LRU עם TTL קצר עבור תוויות בלבד (5 דקות) כדי לאזן בין ביצועים ועקביות + ניטור מדדי מטמון ויחס פגיעות + **ללא מטמון הטבעות**: כבר שמורים עבור כל שאילתה, אין יתרון בין שאילתות + **ללא מטמון תוצאות שאילתה**: עקב חששות לגבי עקביות שינוי גרף + + מודול: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **מסגרת אופטימיזציה של שאילתות** + ניתוח אופטימיזציה של דפוסי שאילתות והצעות + מתאם שאילתות באצווה לגישה למסד הנתונים +<<<<<<< HEAD + ניהול בריכת חיבורים וזמן קצוב של שאילתות +======= + ניהול בריכת חיבורים ותזמון תפוגה של שאילתות +>>>>>>> 82edf2d (New md files from RunPod) + ניטור ביצועים ואיסוף מדדים + + מודול: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### מודלים של נתונים + +#### מצב מעבר גרפים מותאם + +מנוע המעבר שומר על מצב כדי להימנע מפעולות מיותרות: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +גישה זו מאפשרת: +<<<<<<< HEAD +זיהוי יעיל של מעגלים באמצעות מעקב אחר ישויות שביקרו +הכנת שאילתות באצווה בכל רמת מעבר +ניהול מצב חסכוני בזיכרון +סיום מוקדם כאשר מגיעים למגבלות גודל +======= +זיהוי יעיל של מעגלים באמצעות מעקב אחר ישויות שכבר נבדקו. +הכנת שאילתות בקבוצות בכל רמת מעבר. +ניהול מצב חסכוני בזיכרון. +סיום מוקדם כאשר מגבלות גודל הושגו. +>>>>>>> 82edf2d (New md files from RunPod) + +#### מבנה מטמון משופר + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### מבני שאילתות אצווה + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### ממשקי API + +#### ממשקי API חדשים: + +**ממשק GraphTraversal API** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**ממשק API לפתרון תגיות אצווה** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**ממשק ניהול מטמון (Cache Management API)** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### ממשקי API שעודכנו: + +**GraphRag.query()** - שופר עם אופטימיזציות ביצועים: +הוסף פרמטר cache_manager לשליטה על המטמון +הוסף ערך החזרה performance_metrics +הוסף פרמטר query_timeout לאמינות + +**מחלקה Query** - שופרה לעיבוד באצווה: +החלף עיבוד ישויות בודדות בפעולות באצווה +הוסף מנהלי הקשר אסינכרוניים לניקוי משאבים +הוסף פונקציות החזרה (callbacks) להתקדמות עבור פעולות ארוכות + +### פרטי יישום + +#### שלב 0: שינוי ארכיטקטורה קריטי + +**יישום בעייתי נוכחי:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +**ארכיטקטורה ארוכת טווח ומותאמת:** +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +שינוי ארכיטקטורה זה מספק: +**הפחתת שאילתות מסד נתונים ב-10-20%** עבור גרפים עם קשרים נפוצים (בהשוואה ל-0% כיום) +**ביטול תקורה של יצירת אובייקטים** עבור כל בקשה +**בריכת חיבורים קבועה** ושימוש חוזר בלקוח +**אופטימיזציה בין בקשות** בתוך חלונות TTL של מטמון + +**מגבלה חשובה של עקביות מטמון:** +אחסון מטמון לטווח ארוך מכניס סיכון של מידע מיושן כאשר ישויות/תוויות נמחקים או משתנים בגרף הבסיסי. מטמון LRU עם TTL מספק איזון בין שיפורי ביצועים ורעננות נתונים, אך אינו יכול לזהות שינויים בזמן אמת בגרף. + +#### שלב 1: אופטימיזציה של מעבר גרפים + +**בעיות ביישום הנוכחי:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**יישום אופטימלי:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### שלב 2: פתרון מקבילי של תגיות + +**יישום סדרתי נוכחי:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**יישום מקבילי אופטימלי:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### שלב 3: אסטרטגיית אחסון מטמון מתקדמת + +**מטמון LRU עם TTL:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### שלב 4: אופטימיזציה וניטור של שאילתות + +**איסוף מדדי ביצועים:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +<<<<<<< HEAD +**זמן תגובה מקסימלי ומנגנון ניתוב מחדש:** +======= +**מגבלת זמן שאילתה ומנגנון ניתוב:** +>>>>>>> 82edf2d (New md files from RunPod) +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## שיקולים בנוגע לעקביות מטמון + +<<<<<<< HEAD +**פשרות בנוגע לרעננות נתונים:** +**מטמון תוויות (TTL של 5 דקות)**: סיכון להצגת תוויות של ישויות שנמחקו/ששמותיהן שונו. +**ללא שמירת מטמון של הטמעות (embeddings)**: לא נדרש - הטמעות כבר שמורות מטמון עבור כל שאילתה. +**ללא שמירת מטמון של תוצאות**: מונע קבלת תוצאות תת-גרף לא עדכניות מישויות/קשרים שנמחקו. +======= +**פשרות בין רעננות נתונים:** +**מטמון תוויות (TTL של 5 דקות)**: סיכון בהצגת תוויות של ישויות שנמחקו/ששמותיהן שונו. +**ללא שמירת מטמון של הטמעות (embeddings)**: לא נדרש - הטמעות כבר שמורות מטמון עבור כל שאילתה. +**ללא שמירת מטמון של תוצאות**: מונע תוצאות תת-גרף שגויות מישויות/קשרים שנמחקו. +>>>>>>> 82edf2d (New md files from RunPod) + +**אסטרטגיות הפחתה:** +**ערכי TTL שמרניים**: איזון בין שיפורי ביצועים (10-20%) לבין רעננות נתונים. +**מנגנוני ביטול מטמון**: שילוב אופציונלי עם אירועי שינוי בגרף. +<<<<<<< HEAD +**לוחות מחוונים לניטור**: מעקב אחר אחוזי פגיעה במטמון (cache hit rates) לעומת מקרים של נתונים לא עדכניים. +**מדיניות מטמון הניתנות לתצורה**: אפשרות לכוונון פר-פריסה בהתאם לתדירות השינויים. + +**תצורת מטמון מומלצת בהתאם לקצב שינויים בגרף:** +**קצב שינויים גבוה (>100 שינויים/שעה)**: TTL=60 שניות, גדלי מטמון קטנים יותר. +**קצב שינויים בינוני (10-100 שינויים/שעה)**: TTL=300 שניות (ברירת מחדל). +**קצב שינויים נמוך (<10 שינויים/שעה)**: TTL=600 שניות, גדלי מטמון גדולים יותר. + +## שיקולים בנוגע לאבטחה + +**מניעת הזרקת שאילתות:** +אימות כל מזהי ישויות ופרמטרים של שאילתות. +שימוש בשאילתות מפורמטות עבור כל אינטראקציות עם מסד הנתונים. +יישום מגבלות על מורכבות השאילתות כדי למנוע התקפות מניעת שירות (DoS). + +**הגנה על משאבים:** +אכיפת מגבלות על גודל תת-גרף מקסימלי. +יישום זמני קצבה לשאילתות כדי למנוע מיצוי משאבים. +הוספת ניטור מגבלות לשימוש בזיכרון. +======= +**לוחות מחוונים לניטור**: מעקב אחר שיעורי פגיעות במטמון לעומת מקרים של נתונים לא מעודכנים. +**מדיניות מטמון הניתנות לתצורה**: אפשרות לכוונון עדין בהתאם לתדירות השינויים בכל פריסה. + +**תצורת מטמון מומלצת בהתאם לקצב שינויים בגרף:** +**שינויים רבים (>100 שינויים/שעה)**: TTL=60 שניות, גדלי מטמון קטנים יותר. +**שינויים בינוניים (10-100 שינויים/שעה)**: TTL=300 שניות (ברירת מחדל). +**שינויים מעטים (<10 שינויים/שעה)**: TTL=600 שניות, גדלי מטמון גדולים יותר. + +## שיקולים בנושא אבטחה + +**מניעת הזרקת שאילתות:** +אימות כל מזהי ישויות ופרמטרים של שאילתות. +שימוש בשאילתות מפורטות עבור כל אינטראקציות עם מסד הנתונים. +יישום מגבלות מורכבות שאילתות למניעת התקפות מניעת שירות (DoS). + +**הגנה על משאבים:** +אכיפת מגבלות גודל תת-גרף מקסימלי. +יישום זמני קצבי שאילתות למניעת מיצוי משאבים. +הוספת ניטור מגבלות שימוש בזיכרון. +>>>>>>> 82edf2d (New md files from RunPod) + +**בקרת גישה:** +שמירה על בידוד משתמשים ואוספים קיימים. +הוספת רישום ביקורת עבור פעולות המשפיעות על הביצועים. +יישום הגבלת קצב עבור פעולות יקרות. + +<<<<<<< HEAD +## שיקולים בנוגע לביצועים +======= +## שיקולים בנושא ביצועים +>>>>>>> 82edf2d (New md files from RunPod) + +### שיפורי ביצועים צפויים + +**הפחתת מספר שאילתות:** +נוכחי: ~9,000+ שאילתות עבור בקשה טיפוסית. +אופטימלי: ~50-100 שאילתות מקובצות (הפחתה של 98%). + +**שיפורי זמן תגובה:** +מעבר בגרף: 15-20 שניות → 3-5 שניות (מהיר פי 4-5). +פתרון תוויות: 8-12 שניות → 2-4 שניות (מהיר פי 3). +שאילתה כוללת: 25-35 שניות → 6-10 שניות (שיפור של פי 3-4). + +**יעילות זיכרון:** +גדלי מטמון מוגבלים מונעים דליפות זיכרון. +מבני נתונים יעילים מפחיתים את טביעת הרגל של הזיכרון בערך ב-40%. +איסוף אשפה טוב יותר באמצעות ניקוי משאבים נכון. + +**ציפיות ריאליות בנוגע לביצועים:** +<<<<<<< HEAD +**מטמון תוויות**: הפחתה של 10-20% במספר השאילתות עבור גרפים עם קשרים נפוצים. +**אופטימיזציה של קיבוץ**: הפחתה של 50-80% במספר השאילתות (אופטימיזציה עיקרית). +======= +**מטמון תוויות**: הפחתת שאילתות ב-10-20% עבור גרפים עם קשרים נפוצים. +**אופטימיזציה של קיבוץ**: הפחתת שאילתות ב-50-80% (אופטימיזציה עיקרית). +>>>>>>> 82edf2d (New md files from RunPod) +**אופטימיזציה של חיי אובייקט**: ביטול תקורה של יצירה מחדש בכל בקשה. +**שיפור כולל**: שיפור של פי 3-4 בזמן התגובה בעיקר בזכות קיבוץ. + +**שיפורי יכולת הרחבה:** +תמיכה בגרפי ידע גדולים פי 3-5 (מוגבל על ידי צרכי עקביות מטמון). +קיבולת גבוהה יותר פי 3-5 של בקשות מקבילות. +ניצול טוב יותר של משאבים באמצעות שימוש חוזר בחיבורים. + +### ניטור ביצועים + +**מדדים בזמן אמת:** +זמני ביצוע שאילתות לפי סוג פעולה. +<<<<<<< HEAD +אחוזי פגיעה במטמון ויעילות. +שימוש בבריכת חיבורים למסד הנתונים. +======= +שיעורי פגיעה ויעילות של מטמון. +שימוש בבריכת חיבורי מסד נתונים. +>>>>>>> 82edf2d (New md files from RunPod) +שימוש בזיכרון והשפעת איסוף אשפה. + +**בדיקות ביצועים:** +בדיקות רגרסיה אוטומטיות לביצועים +בדיקות עומסים עם נפחי נתונים ריאליים +השוואות ביצועים מול המימוש הנוכחי + +## אסטרטגיית בדיקות + +### בדיקות יחידה +<<<<<<< HEAD +בדיקת רכיבים בודדים עבור מעבר, אחסון במטמון ופתרון תגיות +הדמיית אינטראקציות עם מסד נתונים לצורך בדיקות ביצועים +בדיקת פינוי מטמון ותפוגה של זמן תפוגה (TTL) +======= +בדיקת רכיבים בודדים עבור מעבר, אחסון במטמון ופתרון תוויות +הדמיית אינטראקציות עם מסד נתונים לצורך בדיקות ביצועים +בדיקת פינוי מטמון ותפוגת זמן (TTL) +>>>>>>> 82edf2d (New md files from RunPod) +בדיקת טיפול בשגיאות ותסריטי תזמון + +### בדיקות אינטגרציה +בדיקות מקצה לקצה של שאילתות GraphRAG עם אופטימיזציות +בדיקת אינטראקציות עם מסד נתונים עם נתונים אמיתיים +טיפול בבקשות מקבילות וניהול משאבים +<<<<<<< HEAD +זיהוי דליפות זיכרון ואימות ניקוי משאבים +======= +זיהוי דליפות זיכרון ובדיקת ניקוי משאבים +>>>>>>> 82edf2d (New md files from RunPod) + +### בדיקות ביצועים +בדיקות ביצועים מול המימוש הנוכחי +בדיקות עומסים עם גדלים ומורכבויות גרף משתנים +בדיקות לחץ עבור מגבלות זיכרון וחיבורים +בדיקות רגרסיה לשיפורי ביצועים + +### בדיקות תאימות +אימות תאימות של ממשקי API קיימים של GraphRAG +בדיקה עם מנועי גרפים שונים +אימות דיוק התוצאות בהשוואה למימוש הנוכחי + +## תוכנית יישום + +### גישת יישום ישירה +<<<<<<< HEAD +מכיוון שמותר לשנות ממשקי API, ליישם אופטימיזציות ישירות ללא מורכבות של העברה: + +1. **החלפת `follow_edges`:** כתיבה מחדש עם מעבר אצווה איטרטיבי +2. **אופטימיזציה של `get_labelgraph`:** יישום פתרון תגיות מקבילי +3. **הוספת GraphRag ארוך טווח:** שינוי של מעבד כדי לשמור על מופע קבוע +4. **יישום אחסון במטמון של תגיות:** הוספת מטמון LRU עם TTL למחלקת GraphRag + +### היקף השינויים +**מחלקה של שאילתות:** החלפת כ-50 שורות ב-`follow_edges`, הוספת כ-30 שורות לטיפול באצווה +**מחלקה של GraphRag:** הוספת שכבת אחסון במטמון (כ-40 שורות) +**מחלקה של מעבד:** שינוי לשימוש במופע קבוע של GraphRag (כ-20 שורות) +======= +מכיוון שמותר לשנות ממשקי API, ליישם אופטימיזציות ישירות ללא מורכבות של מעבר: + +1. **החלפת `follow_edges`:** כתיבה מחדש עם מעבר אצווה איטרטיבי +2. **אופטימיזציה של `get_labelgraph`:** יישום פתרון תוויות מקבילי +3. **הוספת GraphRag ארוך טווח:** שינוי של Processor לשמירה על מופע קבוע +4. **יישום אחסון תוויות במטמון:** הוספת מטמון LRU עם TTL למחלקת GraphRag + +### היקף השינויים +**מחלקת שאילתה:** החלפת כ-50 שורות ב-`follow_edges`, הוספת כ-30 שורות לטיפול באצווה +**מחלקת GraphRag:** הוספת שכבת אחסון במטמון (כ-40 שורות) +**מחלקת Processor:** שינוי לשימוש במופע קבוע של GraphRag (כ-20 שורות) +>>>>>>> 82edf2d (New md files from RunPod) +**סה"כ:** כ-140 שורות של שינויים ממוקדים, בעיקר בתוך מחלקות קיימות + +## ציר זמן + +**שבוע 1: יישום ליבה** +החלפת `follow_edges` עם מעבר אצווה איטרטיבי +<<<<<<< HEAD +יישום פתרון תגיות מקבילי ב-`get_labelgraph` +הוספת מופע GraphRag ארוך טווח למעבד +יישום שכבת אחסון במטמון של תגיות +======= +יישום פתרון תוויות מקבילי ב-`get_labelgraph` +הוספת מופע GraphRag ארוך טווח ל-Processor +יישום שכבת אחסון במטמון +>>>>>>> 82edf2d (New md files from RunPod) + +**שבוע 2: בדיקות ושילוב** +בדיקות יחידה ללוגיקה חדשה של מעבר ואחסון במטמון +בדיקות ביצועים מול המימוש הנוכחי +בדיקות אינטגרציה עם נתוני גרף אמיתיים +סקירת קוד ואופטימיזציה + +**שבוע 3: פריסה** +פריסת המימוש המותאם +ניטור שיפורי ביצועים +כוונון עדין של זמן תפוגה של מטמון וגדלי אצווה בהתבסס על שימוש אמיתי + +## שאלות פתוחות + +**בריכת חיבורים למסד נתונים:** האם עלינו ליישם בריכת חיבורים מותאמת אישית או להסתמך על בריכת חיבורים קיימת של לקוח מסד נתונים? +<<<<<<< HEAD +**שימור מטמון:** האם מטמון התגיות וההטבעות צריך להתמיד בין הפעלות מחדש של השירות? +**אחסון במטמון מבוזר:** עבור פריסות מרובות מופעים, האם עלינו ליישם אחסון במטמון מבוזר עם Redis/Memcached? +**פורמט תוצאות שאילתה:** האם עלינו לייעל את הייצוג הפנימי של משולש לטובת יעילות זיכרון טובה יותר? +**שילוב ניטור:** אילו מדדים יש לחשוף למערכות ניטור קיימות (Prometheus, וכו')? +======= +**שימור מטמון:** האם מטמון תוויות ו-embedding צריך להתמיד בין הפעלות מחדש של השירות? +**אחסון מבוזר:** עבור פריסות מרובות מופעים, האם עלינו ליישם אחסון מבוזר עם Redis/Memcached? +**פורמט תוצאות שאילתה:** האם עלינו לייעל את הייצוג הפנימי של משולש לטובת יעילות זיכרון טובה יותר? +**שילוב ניטור:** אילו מדדים צריכים להיות חשופים למערכות ניטור קיימות (Prometheus, וכו')? +>>>>>>> 82edf2d (New md files from RunPod) + +## הפניות + +[מימוש מקורי של GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +[עקרונות ארכיטקטורה של TrustGraph](architecture-principles.md) +[מפרט ניהול אוספים](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.hi.md b/docs/tech-specs/graphrag-performance-optimization.hi.md new file mode 100644 index 00000000..4a1e725e --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.hi.md @@ -0,0 +1,759 @@ +--- +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. **क्वेरी अनुकूलन**: बेहतर प्रतिक्रिया समय के लिए परिणाम मेमोइज़ेशन और एम्बेडिंग कैशिंग जोड़ें। + +## लक्ष्य + +<<<<<<< HEAD +**डेटाबेस क्वेरी की मात्रा को कम करें**: बैचिंग और कैशिंग के माध्यम से कुल डेटाबेस प्रश्नों में 50-80% की कमी प्राप्त करें। +**प्रतिक्रिया समय में सुधार**: सबग्राफ निर्माण और लेबल रिज़ॉल्यूशन में 3-5 गुना तेजी और 2-3 गुना तेजी लाने का लक्ष्य रखें। +**स्केलेबिलिटी में वृद्धि**: बेहतर मेमोरी प्रबंधन के साथ बड़े नॉलेज ग्राफ का समर्थन करें। +**सटीकता बनाए रखें**: मौजूदा ग्राफआरएजी कार्यक्षमता और परिणाम गुणवत्ता को संरक्षित करें। +**समवर्तीता सक्षम करें**: एकाधिक समवर्ती अनुरोधों के लिए समानांतर प्रसंस्करण क्षमताओं में सुधार करें। +**मेमोरी पदचिह्न को कम करें**: कुशल डेटा संरचनाओं और मेमोरी प्रबंधन को लागू करें। +======= +**डेटाबेस क्वेरी की मात्रा कम करें**: बैचिंग और कैशिंग के माध्यम से कुल डेटाबेस प्रश्नों में 50-80% की कमी प्राप्त करें। +**प्रतिक्रिया समय में सुधार**: सबग्राफ निर्माण और लेबल रिज़ॉल्यूशन में 3-5 गुना तेजी और 2-3 गुना तेजी लाने का लक्ष्य रखें। +**स्केलेबिलिटी बढ़ाएं**: बेहतर मेमोरी प्रबंधन के साथ बड़े नॉलेज ग्राफ का समर्थन करें। +**सटीकता बनाए रखें**: मौजूदा ग्राफआरएजी कार्यक्षमता और परिणाम गुणवत्ता को संरक्षित करें। +**समवर्तीता सक्षम करें**: एकाधिक समवर्ती अनुरोधों के लिए समानांतर प्रसंस्करण क्षमताओं में सुधार करें। +**मेमोरी पदचिह्न कम करें**: कुशल डेटा संरचनाओं और मेमोरी प्रबंधन को लागू करें। +>>>>>>> 82edf2d (New md files from RunPod) +**अवलोकनशीलता जोड़ें**: प्रदर्शन मेट्रिक्स और निगरानी क्षमताओं को शामिल करें। +**विश्वसनीयता सुनिश्चित करें**: उचित त्रुटि हैंडलिंग और टाइमआउट तंत्र जोड़ें। + +## पृष्ठभूमि + +`trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` में वर्तमान ग्राफआरएजी कार्यान्वयन में कई महत्वपूर्ण प्रदर्शन मुद्दे हैं जो सिस्टम स्केलेबिलिटी को गंभीर रूप से प्रभावित करते हैं: + +### वर्तमान प्रदर्शन समस्याएं + +**1. अक्षम ग्राफ ट्रैवर्सल (`follow_edges` फ़ंक्शन, लाइनें 79-127)** +<<<<<<< HEAD +प्रत्येक इकाई प्रति गहराई स्तर के लिए 3 अलग-अलग डेटाबेस क्वेरी करता है। +क्वेरी पैटर्न: प्रत्येक इकाई के लिए विषय-आधारित, विधेय-आधारित और ऑब्जेक्ट-आधारित क्वेरी। +कोई बैचिंग नहीं: प्रत्येक क्वेरी एक समय में केवल एक इकाई को संसाधित करती है। +======= +प्रति इकाई प्रति गहराई स्तर के लिए 3 अलग-अलग डेटाबेस क्वेरी करता है। +क्वेरी पैटर्न: प्रत्येक इकाई के लिए विषय-आधारित, विधेय-आधारित और ऑब्जेक्ट-आधारित क्वेरी। +कोई बैचिंग नहीं: प्रत्येक क्वेरी केवल एक इकाई को संसाधित करती है। +>>>>>>> 82edf2d (New md files from RunPod) +कोई चक्र का पता नहीं: समान नोड्स को कई बार फिर से देख सकता है। +मेमोइज़ेशन के बिना पुनरावर्ती कार्यान्वयन घातीय जटिलता की ओर ले जाता है। +समय जटिलता: O(entities × max_path_length × triple_limit³) + +**2. क्रमिक लेबल रिज़ॉल्यूशन (`get_labelgraph` फ़ंक्शन, लाइनें 144-171)** +प्रत्येक ट्रिपल घटक (विषय, विधेय, ऑब्जेक्ट) को क्रमिक रूप से संसाधित करता है। +प्रत्येक `maybe_label` कॉल संभावित रूप से एक डेटाबेस क्वेरी को ट्रिगर करता है। +लेबल क्वेरी के समानांतर निष्पादन या बैचिंग नहीं। +परिणाम में subgraph_size × 3 व्यक्तिगत डेटाबेस कॉल होते हैं। + +**3. आदिम कैशिंग रणनीति (`maybe_label` फ़ंक्शन, लाइनें 62-77)** +आकार सीमा या टीटीएल के बिना एक साधारण शब्दकोश कैश। +<<<<<<< HEAD +कोई कैश निष्कासन नीति नहीं जिसके परिणामस्वरूप असीमित मेमोरी वृद्धि होती है। +======= +कोई कैश निष्कासन नीति असीमित मेमोरी वृद्धि की ओर ले जाती है। +>>>>>>> 82edf2d (New md files from RunPod) +कैश मिस व्यक्तिगत डेटाबेस क्वेरी को ट्रिगर करते हैं। +कोई प्रीफ़ेचिंग या बुद्धिमान कैश वार्मिंग नहीं। + +**4. उप-इष्टतम क्वेरी पैटर्न** +समान अनुरोधों के बीच इकाई वेक्टर समानता क्वेरी कैश नहीं की जाती हैं। +दोहराए गए क्वेरी पैटर्न के लिए कोई परिणाम मेमोइज़ेशन नहीं। +सामान्य एक्सेस पैटर्न के लिए कोई क्वेरी अनुकूलन नहीं। + +**5. महत्वपूर्ण ऑब्जेक्ट लाइफटाइम मुद्दे (`rag.py:96-102`)** +**प्रत्येक अनुरोध के लिए GraphRag ऑब्जेक्ट फिर से बनाया गया**: प्रत्येक क्वेरी के लिए एक नया उदाहरण बनाया जाता है, जिससे सभी कैश लाभ खो जाते हैं। +<<<<<<< HEAD +**क्वेरी ऑब्जेक्ट बहुत कम समय तक रहता है**: एकल क्वेरी निष्पादन के भीतर बनाया और नष्ट किया जाता है (लाइनें 201-207)। +======= +**क्वेरी ऑब्जेक्ट बहुत कम समय तक जीवित रहता है**: एक ही क्वेरी निष्पादन के भीतर बनाया और नष्ट किया जाता है (लाइनें 201-207)। +>>>>>>> 82edf2d (New md files from RunPod) +**प्रत्येक अनुरोध के लिए लेबल कैश रीसेट**: कैश वार्मिंग और संचित ज्ञान के बीच खो जाता है। +**क्लाइंट पुन: निर्माण ओवरहेड**: प्रत्येक अनुरोध के लिए डेटाबेस क्लाइंट संभावित रूप से फिर से स्थापित होते हैं। +**क्रॉस-रिक्वेस्ट अनुकूलन नहीं**: क्वेरी पैटर्न या परिणाम साझाकरण से लाभ नहीं उठाया जा सकता है। + +### प्रदर्शन प्रभाव विश्लेषण + +एक विशिष्ट क्वेरी के लिए वर्तमान सबसे खराब स्थिति परिदृश्य: +<<<<<<< HEAD +**इकाई पुनर्प्राप्ति**: 1 वेक्टर समानता क्वेरी +**ग्राफ ट्रैवर्सल**: entities × max_path_length × 3 × triple_limit क्वेरी +**लेबल रिज़ॉल्यूशन**: subgraph_size × 3 व्यक्तिगत लेबल क्वेरी + +डिफ़ॉल्ट मापदंडों के लिए (50 एंटिटीज, पथ लंबाई 2, 30 ट्रिपल सीमा, 150 सबग्राफ आकार): +**न्यूनतम क्वेरीज़**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9,451 डेटाबेस क्वेरीज़** +**प्रतिक्रिया समय**: मध्यम आकार के ग्राफ़ के लिए 15-30 सेकंड +**मेमोरी उपयोग**: समय के साथ असीमित कैश वृद्धि +**कैश प्रभावशीलता**: 0% - प्रत्येक अनुरोध पर कैश रीसेट हो जाते हैं +**ऑब्जेक्ट निर्माण ओवरहेड**: प्रति अनुरोध बनाए गए/विनाशित GraphRag + Query ऑब्जेक्ट + +यह विनिर्देश इन कमियों को बैच क्वेरी, बुद्धिमान कैशिंग और समानांतर प्रसंस्करण को लागू करके संबोधित करता है। क्वेरी पैटर्न और डेटा एक्सेस को अनुकूलित करके, TrustGraph निम्न कार्य कर सकता है: +लाखों एंटिटीज वाले एंटरप्राइज-स्केल नॉलेज ग्राफ़ का समर्थन करें +विशिष्ट क्वेरीज़ के लिए उप-सेकंड प्रतिक्रिया समय प्रदान करें +सैकड़ों समवर्ती GraphRAG अनुरोधों को संभालें +ग्राफ के आकार और जटिलता के साथ कुशलतापूर्वक स्केल करें +======= +**इकाई पुनर्प्राप्ति**: 1 वेक्टर समानता क्वेरी। +**ग्राफ ट्रैवर्सल**: entities × max_path_length × 3 × triple_limit क्वेरी। +**लेबल रिज़ॉल्यूशन**: subgraph_size × 3 व्यक्तिगत लेबल क्वेरी। + +डिफ़ॉल्ट मापदंडों के लिए (50 एंटिटीज, पथ लंबाई 2, 30 ट्रिपल सीमा, 150 सबग्राफ आकार): +**न्यूनतम क्वेरीज़**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9,451 डेटाबेस क्वेरीज़** +**प्रतिक्रिया समय**: मध्यम आकार के ग्राफ के लिए 15-30 सेकंड +**मेमोरी उपयोग**: समय के साथ असीमित कैश वृद्धि +**कैश प्रभावशीलता**: 0% - प्रत्येक अनुरोध पर कैश रीसेट हो जाते हैं +**ऑब्जेक्ट निर्माण ओवरहेड**: प्रति अनुरोध बनाए गए/विनाश किए गए ग्राफराग + क्वेरी ऑब्जेक्ट + +यह विनिर्देश इन कमियों को बैच क्वेरी, बुद्धिमान कैशिंग और समानांतर प्रसंस्करण को लागू करके संबोधित करता है। क्वेरी पैटर्न और डेटा एक्सेस को अनुकूलित करके, ट्रस्टग्राफ निम्न कार्य कर सकता है: +लाखों एंटिटीज वाले एंटरप्राइज-स्केल नॉलेज ग्राफ का समर्थन करें +विशिष्ट क्वेरीज़ के लिए उप-सेकंड प्रतिक्रिया समय प्रदान करें +सैकड़ों समवर्ती ग्राफराग अनुरोधों को संभालें +ग्राफ आकार और जटिलता के साथ कुशलतापूर्वक स्केल करें +>>>>>>> 82edf2d (New md files from RunPod) + +## तकनीकी डिज़ाइन + +### आर्किटेक्चर + +<<<<<<< HEAD +GraphRAG प्रदर्शन अनुकूलन के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है: + +#### 1. **ऑब्जेक्ट लाइफटाइम आर्किटेक्चरल रीफैक्टर** + **GraphRag को लंबे समय तक चलने वाला बनाएं**: GraphRag इंस्टेंस को प्रोसेसर स्तर पर ले जाएं ताकि यह अनुरोधों के बीच बना रहे + **कैश बनाए रखें**: लेबल कैश, एम्बेडिंग कैश और क्वेरी परिणाम कैश को अनुरोधों के बीच बनाए रखें + **क्वेरी ऑब्जेक्ट को अनुकूलित करें**: Query को एक हल्के निष्पादन संदर्भ के रूप में रीफैक्टर करें, डेटा कंटेनर के रूप में नहीं +======= +ग्राफराग प्रदर्शन अनुकूलन के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है: + +#### 1. **ऑब्जेक्ट लाइफटाइम आर्किटेक्चरल रीफैक्टर** + **ग्राफराग को लंबे समय तक चलने वाला बनाएं**: ग्राफराग इंस्टेंस को प्रोसेसर स्तर पर ले जाएं ताकि यह अनुरोधों के बीच बना रहे + **कैश बनाए रखें**: लेबल कैश, एम्बेडिंग कैश और क्वेरी परिणाम कैश को अनुरोधों के बीच बनाए रखें + **क्वेरी ऑब्जेक्ट को अनुकूलित करें**: क्वेरी को एक हल्के निष्पादन संदर्भ के रूप में रीफैक्टर करें, डेटा कंटेनर के रूप में नहीं +>>>>>>> 82edf2d (New md files from RunPod) + **कनेक्शन दृढ़ता**: डेटाबेस क्लाइंट कनेक्शन को अनुरोधों के बीच बनाए रखें + + मॉड्यूल: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (संशोधित) + +#### 2. **अनुकूलित ग्राफ ट्रैवर्सल इंजन** + पुनरावर्ती `follow_edges` को पुनरावृत्त चौड़ाई-पहली खोज से बदलें + प्रत्येक ट्रैवर्सल स्तर पर बैच एंटिटी प्रोसेसिंग लागू करें + देखे गए नोड ट्रैकिंग का उपयोग करके चक्र का पता लगाएं + सीमाओं तक पहुंचने पर प्रारंभिक समाप्ति शामिल करें + + मॉड्यूल: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **समानांतर लेबल रिज़ॉल्यूशन सिस्टम** +<<<<<<< HEAD + एक साथ कई एंटिटीज के लिए लेबल क्वेरीज़ को बैच करें +======= + एक साथ कई एंटिटीज के लिए बैच लेबल क्वेरी +>>>>>>> 82edf2d (New md files from RunPod) + समवर्ती डेटाबेस एक्सेस के लिए एसिंक्रोनस/अवेट पैटर्न लागू करें + सामान्य लेबल पैटर्न के लिए बुद्धिमान प्रीफ़ेटिंग जोड़ें + लेबल कैश वार्मिंग रणनीतियों शामिल करें + + मॉड्यूल: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **रूढ़िवादी लेबल कैशिंग लेयर** +<<<<<<< HEAD + प्रदर्शन बनाम स्थिरता को संतुलित करने के लिए केवल लेबल के लिए लघु TTL के साथ LRU कैश (5 मिनट) + कैश मेट्रिक्स और हिट अनुपात निगरानी + **कोई एम्बेडिंग कैशिंग नहीं**: पहले से ही प्रति-क्वेरी कैश किया गया है, कोई क्रॉस-क्वेरी लाभ नहीं + **कोई क्वेरी परिणाम कैशिंग नहीं**: ग्राफ परिवर्तन स्थिरता संबंधी चिंताओं के कारण +======= + केवल लेबल के लिए लघु TTL के साथ LRU कैश (5 मिनट) प्रदर्शन बनाम स्थिरता को संतुलित करने के लिए + कैश मेट्रिक्स और हिट अनुपात निगरानी + **कोई एम्बेडिंग कैशिंग नहीं**: पहले से ही प्रति-क्वेरी कैश किया गया है, कोई क्रॉस-क्वेरी लाभ नहीं + **कोई क्वेरी परिणाम कैशिंग नहीं**: ग्राफ उत्परिवर्तन स्थिरता संबंधी चिंताओं के कारण +>>>>>>> 82edf2d (New md files from RunPod) + + मॉड्यूल: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **क्वेरी अनुकूलन ढांचा** + क्वेरी पैटर्न विश्लेषण और अनुकूलन सुझाव + डेटाबेस एक्सेस के लिए बैच क्वेरी समन्वयक + कनेक्शन पूलिंग और क्वेरी टाइमआउट प्रबंधन + प्रदर्शन निगरानी और मेट्रिक्स संग्रह + + मॉड्यूल: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### डेटा मॉडल + +#### अनुकूलित ग्राफ ट्रैवर्सल स्थिति + +ट्रैवर्सल इंजन अनावश्यक कार्यों से बचने के लिए स्थिति बनाए रखता है: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +<<<<<<< HEAD +यह दृष्टिकोण निम्नलिखित सुविधाएँ प्रदान करता है: +======= +यह दृष्टिकोण निम्नलिखित कार्य करने की अनुमति देता है: +>>>>>>> 82edf2d (New md files from RunPod) +विज़िट किए गए एंटिटी को ट्रैक करके कुशल चक्र का पता लगाना +प्रत्येक ट्रैवर्सल स्तर पर बैच में क्वेरी तैयार करना +मेमोरी-कुशल स्थिति प्रबंधन +जब आकार की सीमाएँ पूरी हो जाती हैं तो प्रारंभिक समाप्ति + +#### बेहतर कैश संरचना + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### बैच क्वेरी संरचनाएं + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### एपीआई (APIs) + +#### नए एपीआई (New APIs): + +**ग्राफ ट्रावर्सल एपीआई (GraphTraversal API)** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**बैच लेबल रिज़ॉल्यूशन एपीआई** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**कैश प्रबंधन एपीआई** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### संशोधित एपीआई: + +**GraphRag.query()** - प्रदर्शन अनुकूलन के साथ बेहतर: +कैश नियंत्रण के लिए `cache_manager` पैरामीटर जोड़ें +`performance_metrics` रिटर्न वैल्यू शामिल करें +विश्वसनीयता के लिए `query_timeout` पैरामीटर जोड़ें + +**क्वेरी क्लास** - बैच प्रोसेसिंग के लिए पुनर्गठित: +व्यक्तिगत इकाई प्रसंस्करण को बैच ऑपरेशनों से बदलें +<<<<<<< HEAD +संसाधन सफाई के लिए एसिंक्रोनस कॉन्टेक्स्ट मैनेजर जोड़ें +======= +संसाधन सफाई के लिए एसिंक्रोनस संदर्भ प्रबंधक जोड़ें +>>>>>>> 82edf2d (New md files from RunPod) +लंबे समय तक चलने वाले ऑपरेशनों के लिए प्रगति कॉलबैक शामिल करें + +### कार्यान्वयन विवरण + +<<<<<<< HEAD +#### चरण 0: महत्वपूर्ण आर्किटेक्चरल लाइफटाइम रिफैक्टर +======= +#### चरण 0: महत्वपूर्ण वास्तुशिल्प जीवनचक्र पुनर्गठन +>>>>>>> 82edf2d (New md files from RunPod) + +**वर्तमान समस्याग्रस्त कार्यान्वयन:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +**अनुकूलित, दीर्घकालिक संरचना:** +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +यह वास्तुशिल्पीय परिवर्तन निम्नलिखित सुविधाएँ प्रदान करता है: +**सामान्य संबंधों वाले ग्राफों के लिए डेटाबेस क्वेरी में 10-20% की कमी** (वर्तमान में 0% की तुलना में) +प्रत्येक अनुरोध के लिए **ऑब्जेक्ट निर्माण ओवरहेड को समाप्त करना** +**स्थायी कनेक्शन पूलिंग** और क्लाइंट पुन: उपयोग +**कैश टीटीएल विंडो के भीतर क्रॉस-अनुरोध अनुकूलन** + +**महत्वपूर्ण कैश स्थिरता सीमा:** +<<<<<<< HEAD +दीर्घकालिक कैशिंग से अप्रचलन का जोखिम होता है जब अंतर्निहित ग्राफ में एंटिटीज/लेबल हटा दिए जाते हैं या संशोधित किए जाते हैं। एलआरयू कैश जिसमें टीटीएल है, प्रदर्शन लाभ और डेटा ताज़गी के बीच संतुलन प्रदान करता है, लेकिन यह वास्तविक समय में ग्राफ परिवर्तनों का पता नहीं लगा सकता है। +======= +दीर्घकालिक कैशिंग से पुरानी जानकारी का जोखिम होता है जब अंतर्निहित ग्राफ में एंटिटीज/लेबल हटा दिए जाते हैं या संशोधित किए जाते हैं। एलआरयू कैश, टीटीएल के साथ, प्रदर्शन लाभ और डेटा ताज़गी के बीच एक संतुलन प्रदान करता है, लेकिन यह वास्तविक समय में ग्राफ परिवर्तनों का पता नहीं लगा सकता है। +>>>>>>> 82edf2d (New md files from RunPod) + +#### चरण 1: ग्राफ ट्रैवर्सल अनुकूलन + +**वर्तमान कार्यान्वयन समस्याएं:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**अनुकूलित कार्यान्वयन:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### चरण 2: समानांतर लेबल समाधान + +**वर्तमान अनुक्रमिक कार्यान्वयन:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**अनुकूलित समानांतर कार्यान्वयन:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### चरण 3: उन्नत कैशिंग रणनीति + +**एलआरयू (LRU) कैश टीटीएल (TTL) के साथ:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### चरण 4: क्वेरी अनुकूलन और निगरानी + +**प्रदर्शन मेट्रिक्स संग्रह:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**क्वेरी टाइमआउट और सर्किट ब्रेकर:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## कैश कंसिस्टेंसी पर विचार + +**डेटा स्टेलनेस ट्रेड-ऑफ:** +<<<<<<< HEAD +**लेबल कैश (5 मिनट TTL)**: डिलीट किए गए/रीनेम किए गए एंटिटी लेबल को प्रदर्शित करने का जोखिम। +**कोई एम्बेडिंग कैशिंग नहीं:** आवश्यक नहीं है - एम्बेडिंग पहले से ही प्रति-क्वेरी कैश किए गए हैं। +**कोई परिणाम कैशिंग नहीं:** डिलीट किए गए एंटिटीज/रिलेशनशिप से पुराने सबग्राफ परिणामों को रोकता है। +======= +**लेबल कैश (5 मिनट TTL)**: हटाए गए/पुनर्नाम किए गए एंटिटी लेबल को प्रदर्शित करने का जोखिम। +**कोई एम्बेडिंग कैशिंग नहीं:** आवश्यक नहीं है - एम्बेडिंग पहले से ही प्रति-क्वेरी कैश किए गए हैं। +**कोई परिणाम कैशिंग नहीं:** हटाए गए एंटिटीज/रिलेशनशिप से पुराने सबग्राफ परिणामों को रोकता है। +>>>>>>> 82edf2d (New md files from RunPod) + +**शमन रणनीतियाँ:** +**रूढ़िवादी TTL मान:** प्रदर्शन लाभ (10-20%) को डेटा की ताजगी के साथ संतुलित करें। +**कैश अमान्यकरण हुक:** ग्राफ उत्परिवर्तन घटनाओं के साथ वैकल्पिक एकीकरण। +**निगरानी डैशबोर्ड:** कैश हिट दरों बनाम स्टेलनेस घटनाओं को ट्रैक करें। +**कॉन्फ़िगर करने योग्य कैश नीतियां:** उत्परिवर्तन आवृत्ति के आधार पर प्रति-तैनाती ट्यूनिंग की अनुमति दें। + +<<<<<<< HEAD +**ग्राफ उत्परिवर्तन दर द्वारा अनुशंसित कैश कॉन्फ़िगरेशन:** +======= +**अनुशंसित कैश कॉन्फ़िगरेशन ग्राफ उत्परिवर्तन दर द्वारा:** +>>>>>>> 82edf2d (New md files from RunPod) +**उच्च उत्परिवर्तन (>100 परिवर्तन/घंटा):** TTL=60s, छोटे कैश आकार। +**मध्यम उत्परिवर्तन (10-100 परिवर्तन/घंटा):** TTL=300s (डिफ़ॉल्ट)। +**कम उत्परिवर्तन (<10 परिवर्तन/घंटा):** TTL=600s, बड़े कैश आकार। + +## सुरक्षा संबंधी विचार + +**क्वेरी इंजेक्शन रोकथाम:** +सभी एंटिटी पहचानकर्ताओं और क्वेरी मापदंडों को मान्य करें। +सभी डेटाबेस इंटरैक्शन के लिए पैरामीटराइज़्ड क्वेरी का उपयोग करें। +DoS हमलों को रोकने के लिए क्वेरी जटिलता सीमाएं लागू करें। + +<<<<<<< HEAD +**संसाधन सुरक्षा:** +======= +**संसाधन संरक्षण:** +>>>>>>> 82edf2d (New md files from RunPod) +अधिकतम सबग्राफ आकार सीमाओं को लागू करें। +संसाधन समाप्त होने से रोकने के लिए क्वेरी टाइमआउट लागू करें। +मेमोरी उपयोग निगरानी और सीमाएं जोड़ें। + +**पहुंच नियंत्रण:** +मौजूदा उपयोगकर्ता और संग्रह अलगाव बनाए रखें। +<<<<<<< HEAD +प्रदर्शन-प्रभावित करने वाले कार्यों के लिए ऑडिट लॉगिंग जोड़ें। +महंगे कार्यों के लिए दर सीमित करना लागू करें। +======= +प्रदर्शन-प्रभावित संचालन के लिए ऑडिट लॉगिंग जोड़ें। +महंगे संचालन के लिए दर सीमित करना लागू करें। +>>>>>>> 82edf2d (New md files from RunPod) + +## प्रदर्शन संबंधी विचार + +### अपेक्षित प्रदर्शन सुधार + +**क्वेरी में कमी:** +<<<<<<< HEAD +वर्तमान: विशिष्ट अनुरोध के लिए ~9,000+ क्वेरी +अनुकूलित: ~50-100 बैच क्वेरी (98% कमी) + +**प्रतिक्रिया समय में सुधार:** +ग्राफ ट्रैवर्सल: 15-20s → 3-5s (4-5x तेज़) +लेबल रिज़ॉल्यूशन: 8-12s → 2-4s (3x तेज़) +कुल क्वेरी: 25-35s → 6-10s (3-4x सुधार) + +**मेमोरी दक्षता:** +बाउंडेड कैश आकार मेमोरी लीक को रोकते हैं। +======= +वर्तमान: विशिष्ट अनुरोध के लिए ~9,000+ क्वेरी। +अनुकूलित: ~50-100 बैच क्वेरी (98% कमी)। + +**प्रतिक्रिया समय में सुधार:** +ग्राफ ट्रैवर्सल: 15-20s → 3-5s (4-5x तेज़)। +लेबल रिज़ॉल्यूशन: 8-12s → 2-4s (3x तेज़)। +कुल क्वेरी: 25-35s → 6-10s (3-4x सुधार)। + +**मेमोरी दक्षता:** +बंधी हुई कैश आकार मेमोरी लीक को रोकते हैं। +>>>>>>> 82edf2d (New md files from RunPod) +कुशल डेटा संरचनाएं मेमोरी पदचिह्न को ~40% तक कम करती हैं। +उचित संसाधन सफाई के माध्यम से बेहतर कचरा संग्रह। + +**यथार्थवादी प्रदर्शन अपेक्षाएं:** +**लेबल कैश:** सामान्य संबंधों वाले ग्राफ़ के लिए 10-20% क्वेरी में कमी। +**बैचिंग अनुकूलन:** 50-80% क्वेरी में कमी (प्राथमिक अनुकूलन)। +**ऑब्जेक्ट लाइफटाइम अनुकूलन:** प्रति-अनुरोध निर्माण ओवरहेड को समाप्त करें। +**कुल सुधार:** बैचिंग से मुख्य रूप से 3-4x प्रतिक्रिया समय में सुधार। + +**स्केलेबिलिटी में सुधार:** +3-5x बड़े नॉलेज ग्राफ़ के लिए समर्थन (कैश कंसिस्टेंसी आवश्यकताओं द्वारा सीमित)। +3-5x उच्च समवर्ती अनुरोध क्षमता। +कनेक्शन पुन: उपयोग के माध्यम से बेहतर संसाधन उपयोग। + +### प्रदर्शन निगरानी + +**रियल-टाइम मेट्रिक्स:** +ऑपरेशन प्रकार द्वारा क्वेरी निष्पादन समय। +कैश हिट अनुपात और प्रभावशीलता। +डेटाबेस कनेक्शन पूल उपयोग। +मेमोरी उपयोग और कचरा संग्रह प्रभाव। + +**प्रदर्शन बेंचमार्किंग:** +स्वचालित प्रदर्शन प्रतिगमन परीक्षण +वास्तविक डेटा वॉल्यूम के साथ लोड परीक्षण +वर्तमान कार्यान्वयन के खिलाफ तुलना बेंचमार्क + +## परीक्षण रणनीति + +### यूनिट परीक्षण +ट्रैवर्सल, कैशिंग और लेबल रिज़ॉल्यूशन के लिए व्यक्तिगत घटक परीक्षण +प्रदर्शन परीक्षण के लिए मॉक डेटाबेस इंटरैक्शन +कैश निष्कासन और TTL समाप्ति परीक्षण +त्रुटि हैंडलिंग और टाइमआउट परिदृश्य + +### एकीकरण परीक्षण +अनुकूलन के साथ एंड-टू-एंड GraphRAG क्वेरी परीक्षण +वास्तविक डेटा के साथ डेटाबेस इंटरैक्शन परीक्षण +समवर्ती अनुरोध हैंडलिंग और संसाधन प्रबंधन +मेमोरी लीक का पता लगाना और संसाधन सफाई सत्यापन + +### प्रदर्शन परीक्षण +वर्तमान कार्यान्वयन के खिलाफ बेंचमार्क परीक्षण +विभिन्न ग्राफ आकारों और जटिलताओं के साथ लोड परीक्षण +मेमोरी और कनेक्शन सीमाओं के लिए तनाव परीक्षण +प्रदर्शन सुधारों के लिए प्रतिगमन परीक्षण + +### अनुकूलता परीक्षण +मौजूदा GraphRAG API संगतता सत्यापित करें +विभिन्न ग्राफ डेटाबेस बैकएंड के साथ परीक्षण करें +वर्तमान कार्यान्वयन की तुलना में परिणाम सटीकता को मान्य करें + +## कार्यान्वयन योजना + +### प्रत्यक्ष कार्यान्वयन दृष्टिकोण +<<<<<<< HEAD +चूंकि API में परिवर्तन की अनुमति है, इसलिए माइग्रेशन जटिलता के बिना अनुकूलन को सीधे लागू करें: +======= +चूंकि एपीआई में बदलाव की अनुमति है, इसलिए माइग्रेशन जटिलता के बिना अनुकूलन को सीधे लागू करें: +>>>>>>> 82edf2d (New md files from RunPod) + +1. **`follow_edges` विधि को बदलें**: पुनरावृत्त बैच ट्रैवर्सल के साथ फिर से लिखें +2. **`get_labelgraph` को अनुकूलित करें**: समानांतर लेबल रिज़ॉल्यूशन लागू करें +3. **लंबे समय तक चलने वाला GraphRag जोड़ें**: प्रोसेसर को एक स्थायी उदाहरण बनाए रखने के लिए संशोधित करें +4. **लेबल कैशिंग लागू करें**: GraphRag क्लास में LRU कैश और TTL जोड़ें + +### परिवर्तनों का दायरा +**क्वेरी क्लास**: `follow_edges` में ~50 पंक्तियों को बदलें, बैच हैंडलिंग के लिए ~30 पंक्तियाँ जोड़ें +**GraphRag क्लास**: एक कैशिंग परत जोड़ें (~40 पंक्तियाँ) +**प्रोसेसर क्लास**: एक स्थायी GraphRag उदाहरण का उपयोग करने के लिए संशोधित करें (~20 पंक्तियाँ) +**कुल**: केंद्रित परिवर्तनों की ~140 पंक्तियाँ, ज्यादातर मौजूदा कक्षाओं के भीतर + +## समयरेखा + +**सप्ताह 1: मुख्य कार्यान्वयन** +बैच पुनरावृत्त ट्रैवर्सल के साथ `follow_edges` को बदलें +`get_labelgraph` में समानांतर लेबल रिज़ॉल्यूशन लागू करें +प्रोसेसर में एक लंबे समय तक चलने वाला GraphRag उदाहरण जोड़ें +एक लेबल कैशिंग परत लागू करें + +**सप्ताह 2: परीक्षण और एकीकरण** +<<<<<<< HEAD +नए ट्रैवर्सल और कैशिंग तर्क के लिए यूनिट परीक्षण +======= +नए ट्रैवर्सल और कैशिंग लॉजिक के लिए यूनिट परीक्षण +>>>>>>> 82edf2d (New md files from RunPod) +वर्तमान कार्यान्वयन के खिलाफ प्रदर्शन बेंचमार्किंग +वास्तविक ग्राफ डेटा के साथ एकीकरण परीक्षण +कोड समीक्षा और अनुकूलन + +**सप्ताह 3: परिनियोजन** +अनुकूलित कार्यान्वयन को तैनात करें +प्रदर्शन सुधारों की निगरानी करें +वास्तविक उपयोग के आधार पर कैश TTL और बैच आकारों को ठीक करें + +## खुले प्रश्न + +**डेटाबेस कनेक्शन पूलिंग**: क्या हमें कस्टम कनेक्शन पूलिंग लागू करनी चाहिए या मौजूदा डेटाबेस क्लाइंट पूलिंग पर भरोसा करना चाहिए? +<<<<<<< HEAD +**कैश दृढ़ता**: क्या लेबल और एम्बेडिंग कैश सेवा पुनरारंभों में बने रहने चाहिए? +======= +**कैश दृढ़ता**: क्या लेबल और एम्बेडिंग कैश सेवा पुनरारंभों में बने रहेंगे? +>>>>>>> 82edf2d (New md files from RunPod) +**वितरित कैशिंग**: मल्टी-इंस्टेंस परिनियोजन के लिए, क्या हमें Redis/Memcached के साथ वितरित कैशिंग लागू करनी चाहिए? +**क्वेरी परिणाम प्रारूप**: क्या हमें बेहतर मेमोरी दक्षता के लिए आंतरिक ट्रिपल प्रतिनिधित्व को अनुकूलित करना चाहिए? +**निगरानी एकीकरण**: मौजूदा निगरानी प्रणालियों (Prometheus, आदि) के लिए कौन से मेट्रिक्स उजागर किए जाने चाहिए? + +## संदर्भ + +[GraphRAG मूल कार्यान्वयन](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +[ट्रस्टग्राफ आर्किटेक्चर सिद्धांत](architecture-principles.md) +[संग्रह प्रबंधन विनिर्देश](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.md b/docs/tech-specs/graphrag-performance-optimization.md index da6e1667..9598ad81 100644 --- a/docs/tech-specs/graphrag-performance-optimization.md +++ b/docs/tech-specs/graphrag-performance-optimization.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "GraphRAG Performance Optimisation Technical Specification" +parent: "Tech Specs" +--- + # GraphRAG Performance Optimisation Technical Specification ## Overview diff --git a/docs/tech-specs/graphrag-performance-optimization.pt.md b/docs/tech-specs/graphrag-performance-optimization.pt.md new file mode 100644 index 00000000..5258ab8f --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.pt.md @@ -0,0 +1,758 @@ +--- +layout: default +title: "Especificação Técnica de Otimização de Desempenho do GraphRAG" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Otimização de Desempenho do GraphRAG + +> **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 abrangentes de desempenho para o algoritmo GraphRAG (Graph Retrieval-Augmented Generation) no TrustGraph. A implementação atual sofre de gargalos de desempenho significativos que limitam a escalabilidade e os tempos de resposta. Esta especificação aborda quatro áreas principais de otimização: + +1. **Otimização de Traversal de Grafos**: Eliminar consultas ineficientes ao banco de dados e implementar exploração de grafos em lote. +2. **Otimização de Resolução de Rótulos**: Substituir a busca sequencial de rótulos por operações paralelas/em lote. +3. **Aprimoramento da Estratégia de Cache**: Implementar um cache inteligente com remoção LRU (Least Recently Used) e pré-busca. +<<<<<<< HEAD +4. **Otimização de Consultas**: Adicionar memorização de resultados e cache de incorporações para melhorar os tempos de resposta. +======= +4. **Otimização de Consulta**: Adicionar memorização de resultados e cache de embeddings para melhorar os tempos de resposta. +>>>>>>> 82edf2d (New md files from RunPod) + +## Objetivos + +**Reduzir o Volume de Consultas ao Banco de Dados**: Alcançar uma redução de 50-80% no volume total de consultas ao banco de dados por meio de loteamento e cache. +**Melhorar os Tempos de Resposta**: Almejar uma construção de subgrafo 3-5 vezes mais rápida e uma resolução de rótulos 2-3 vezes mais rápida. +**Aprimorar a Escalabilidade**: Suportar grafos de conhecimento maiores com melhor gerenciamento de memória. +**Manter a Precisão**: Preservar a funcionalidade e a qualidade dos resultados do GraphRAG existentes. +**Habilitar a Concorrência**: Melhorar as capacidades de processamento paralelo para vários запросов simultâneos. +**Reduzir a Pegada de Memória**: Implementar estruturas de dados e gerenciamento de memória eficientes. +**Adicionar Observabilidade**: Incluir métricas de desempenho e capacidades de monitoramento. +<<<<<<< HEAD +**Garantir a Confiabilidade**: Adicionar tratamento de erros adequado e mecanismos de tempo limite. +======= +**Garantir a Confiabilidade**: Adicionar tratamento de erros adequado e mecanismos de timeout. +>>>>>>> 82edf2d (New md files from RunPod) + +## Contexto + +A implementação atual do GraphRAG em `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` apresenta vários problemas de desempenho críticos que afetam severamente a escalabilidade do sistema: + +### Problemas de Desempenho Atuais + +**1. Traversal de Grafos Ineficiente (função `follow_edges`, linhas 79-127)** +Realiza 3 consultas separadas ao banco de dados por entidade por nível de profundidade. +Padrão de consulta: consultas baseadas em sujeito, baseadas em predicado e baseadas em objeto para cada entidade. +Sem loteamento: Cada consulta processa apenas uma entidade por vez. +Sem detecção de ciclo: Pode revisitar os mesmos nós várias vezes. +A implementação recursiva sem memorização leva a uma complexidade exponencial. +Complexidade de tempo: O(entidades × max_path_length × triple_limit³) + +**2. Resolução Sequencial de Rótulos (função `get_labelgraph`, linhas 144-171)** +Processa cada componente de tripla (sujeito, predicado, objeto) sequencialmente. +Cada chamada de `maybe_label` pode acionar uma consulta ao banco de dados. +Sem execução paralela ou loteamento de consultas de rótulos. +Resulta em até 3 × subgraph_size chamadas individuais ao banco de dados. + +**3. Estratégia de Cache Primitiva (função `maybe_label`, linhas 62-77)** +Cache de dicionário simples sem limites de tamanho ou TTL (Time To Live). +A ausência de uma política de remoção de cache leva a um crescimento de memória ilimitado. +Falhas de cache acionam consultas individuais ao banco de dados. +Sem pré-busca ou aquecimento inteligente do cache. + +**4. Padrões de Consulta Subótimos** +<<<<<<< HEAD +Consultas de similaridade de vetores de entidade não são armazenadas em cache entre запросов semelhantes. +======= +Consultas de similaridade de vetores de entidades não são armazenadas em cache entre запросов semelhantes. +>>>>>>> 82edf2d (New md files from RunPod) +Sem memorização de resultados para padrões de consulta repetidos. +Otimização de consulta ausente para padrões de acesso comuns. + +**5. Problemas Críticos de Tempo de Vida de Objetos (`rag.py:96-102`)** +**Objeto GraphRag recriado por запросом**: Uma nova instância é criada para cada consulta, perdendo todos os benefícios do cache. +**Objeto de consulta com vida extremamente curta**: Criado e destruído dentro da execução de uma única consulta (linhas 201-207). +**Cache de rótulos redefinido por запросом**: O aquecimento do cache e o conhecimento acumulado são perdidos entre запросов. +**Sobrecarga de recriação do cliente**: Clientes de banco de dados podem ser reestabelecidos para cada запросом. +**Sem otimização entre запросов**: Não é possível se beneficiar de padrões de consulta ou compartilhamento de resultados. + +### Análise de Impacto no Desempenho + +Cenário de pior caso atual para uma consulta típica: +**Recuperação de Entidade**: 1 consulta de similaridade de vetor. +**Traversal de Grafos**: entidades × max_path_length × 3 × consultas de triplas. +**Resolução de Rótulos**: subgraph_size × 3 consultas individuais de rótulos. + +Para parâmetros padrão (50 entidades, comprimento do caminho 2, limite de 30 triplas, tamanho do subgrafo de 150): +<<<<<<< HEAD +**Consultas mínimas**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9.451 consultas ao banco de dados** +**Tempo de resposta**: 15-30 segundos para grafos de tamanho moderado +**Uso de memória**: Crescimento ilimitado do cache ao longo do tempo +**Eficiência do cache**: 0% - os caches são reiniciados em cada solicitação +**Sobrecarga de criação de objetos**: Objetos GraphRag + Query criados/destruídos por solicitação +======= +**Número de consultas:** 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9.451 consultas ao banco de dados** +**Tempo de resposta:** 15-30 segundos para grafos de tamanho moderado +**Uso de memória:** Crescimento ilimitado do cache ao longo do tempo +**Eficiência do cache:** 0% - os caches são reiniciados em cada solicitação +**Sobrecarga de criação de objetos:** Objetos GraphRag + Query criados/destruídos por solicitação +>>>>>>> 82edf2d (New md files from RunPod) + +Esta especificação aborda essas lacunas implementando consultas em lote, cache inteligente e processamento paralelo. Ao otimizar padrões de consulta e acesso a dados, o TrustGraph pode: +Suportar grafos de conhecimento em escala empresarial com milhões de entidades +Fornecer tempos de resposta de menos de um segundo para consultas típicas +Lidar com centenas de solicitações GraphRAG simultâneas +Escalar de forma eficiente com o tamanho e a complexidade do grafo + +## Design Técnico + +### Arquitetura + +A otimização de desempenho do GraphRAG requer os seguintes componentes técnicos: + +#### 1. **Refatoração Arquitetural do Ciclo de Vida dos Objetos** +<<<<<<< HEAD + **Tornar o GraphRag de longa duração**: Mover a instância GraphRag para o nível do Processador para persistência entre solicitações + **Preservar caches**: Manter o cache de rótulos, o cache de incorporações e o cache de resultados de consulta entre solicitações + **Otimizar o objeto Query**: Refatorar o Query como um contexto de execução leve, não como um contêiner de dados + **Persistência de conexão**: Manter as conexões do cliente do banco de dados entre solicitações +======= + **Tornar o GraphRag de longa duração:** Mover a instância GraphRag para o nível do Processador para persistência entre solicitações + **Preservar caches:** Manter o cache de rótulos, o cache de incorporações e o cache de resultados de consulta entre solicitações + **Otimizar o objeto Query:** Refatorar o Query como um contexto de execução leve, não como um contêiner de dados + **Persistência de conexão:** Manter as conexões do cliente do banco de dados entre solicitações +>>>>>>> 82edf2d (New md files from RunPod) + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (modificado) + +#### 2. **Motor de Traversal de Grafos Otimizado** + Substituir a recursão `follow_edges` por busca em largura iterativa + Implementar o processamento em lote de entidades em cada nível de traversal + Adicionar detecção de ciclo usando o rastreamento de nós visitados + Incluir a terminação antecipada quando os limites são atingidos + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **Sistema de Resolução de Rótulos Paralelo** + Agrupar consultas de rótulos para várias entidades simultaneamente + Implementar padrões async/await para acesso concorrente ao banco de dados + Adicionar pré-busca inteligente para padrões de rótulos comuns + Incluir estratégias de aquecimento de cache de rótulos + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **Camada de Cache Conservadora de Rótulos** + Cache LRU com TTL curto apenas para rótulos (5 minutos) para equilibrar desempenho e consistência + Monitoramento de métricas e taxa de acerto do cache +<<<<<<< HEAD + **Sem cache de incorporações**: Já armazenado em cache por consulta, sem benefício entre consultas + **Sem cache de resultados de consulta**: Devido a preocupações com a consistência da mutação do grafo + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **Framework de Otimização de Consulta** +======= + **Sem cache de incorporações:** Já armazenado em cache por consulta, sem benefício entre consultas + **Sem cache de resultados de consulta:** Devido a preocupações com a consistência da mutação do grafo + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **Framework de Otimização de Consultas** +>>>>>>> 82edf2d (New md files from RunPod) + Análise e sugestões de otimização de padrões de consulta + Coordenador de consultas em lote para acesso ao banco de dados + Pool de conexões e gerenciamento de tempo limite de consulta + Monitoramento de desempenho e coleta de métricas + + Módulo: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### Modelos de Dados + +#### Estado Otimizado de Traversal de Grafos + +O motor de traversal mantém o estado para evitar operações redundantes: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +Esta abordagem permite: +Detecção eficiente de ciclos através do rastreamento de entidades visitadas. +Preparação de consultas em lote em cada nível de travessia. +Gerenciamento de estado com eficiência de memória. +Término antecipado quando os limites de tamanho são atingidos. + +#### Estrutura de Cache Aprimorada + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### Estruturas de Consulta em Lote + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### APIs + +#### Novas APIs: + +**API de GraphTraversal** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**API de Resolução de Rótulos em Lote** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**API de Gerenciamento de Cache** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### APIs Modificados: + +**GraphRag.query()** - Aprimorado com otimizações de desempenho: +<<<<<<< HEAD +Adicionado parâmetro `cache_manager` para controle de cache. +Incluído valor de retorno `performance_metrics`. +Adicionado parâmetro `query_timeout` para confiabilidade. +======= +Adicionado o parâmetro `cache_manager` para controle de cache. +Incluído o valor de retorno `performance_metrics`. +Adicionado o parâmetro `query_timeout` para confiabilidade. +>>>>>>> 82edf2d (New md files from RunPod) + +**Classe Query** - Refatorada para processamento em lote: +Substituição do processamento individual de entidades por operações em lote. +Adicionados gerenciadores de contexto assíncronos para limpeza de recursos. +Incluídas funções de retorno de progresso para operações de longa duração. + +### Detalhes da Implementação + +#### Fase 0: Refatoração Crítica do Ciclo de Vida da Arquitetura + +**Implementação Atualmente Problemática:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +**Arquitetura Otimizada e de Longa Duração:** +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +Esta mudança arquitetural oferece: +**Redução de 10-20% nas consultas ao banco de dados** para grafos com relacionamentos comuns (em comparação com 0% atualmente) +**Eliminação da sobrecarga de criação de objetos** para cada requisição +**Pool de conexões persistentes** e reutilização do cliente +**Otimização entre requisições** dentro das janelas de tempo de vida (TTL) do cache + +<<<<<<< HEAD +**Limitação Importante de Consistência do Cache:** +O cache de longo prazo introduz o risco de dados desatualizados quando entidades/rótulos são excluídos ou modificados no grafo subjacente. O cache LRU com TTL oferece um equilíbrio entre ganhos de desempenho e frescor dos dados, mas não pode detectar alterações em tempo real no grafo. +======= +**Importante Limitação de Consistência do Cache:** +O cache de longo prazo introduz o risco de dados desatualizados quando entidades/rótulos são excluídos ou modificados no grafo subjacente. O cache LRU com TTL oferece um equilíbrio entre ganhos de desempenho e frescor dos dados, mas não detecta alterações em tempo real no grafo. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Fase 1: Otimização de Traversal de Grafos + +**Problemas na Implementação Atual:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**Implementação Otimizada:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### Fase 2: Resolução Paralela de Rótulos + +**Implementação Sequencial Atual:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**Implementação Paralela Otimizada:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### Fase 3: Estratégia Avançada de Cache + +**Cache LRU com TTL:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### Fase 4: Otimização de Consulta e Monitoramento + +**Coleta de Métricas de Desempenho:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**Tempo Limite de Consulta e Disjuntor:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## Considerações sobre a Consistência do Cache + +**Compensações entre a Atualidade dos Dados:** +<<<<<<< HEAD +**Cache de rótulos (TTL de 5 minutos)**: Risco de exibir rótulos de entidades excluídas/renomeadas. +**Sem cache de embeddings**: Não é necessário - os embeddings já são armazenados em cache por consulta. +**Sem cache de resultados**: Impede que resultados de subgrafos desatualizados sejam exibidos devido à exclusão de entidades/relacionamentos. + +**Estratégias de Mitigação:** +**Valores de TTL conservadores**: Equilibre os ganhos de desempenho (10-20%) com a atualização dos dados. +**Hooks de invalidação de cache**: Integração opcional com eventos de mutação do grafo. +**Painéis de monitoramento**: Acompanhe as taxas de acerto do cache versus incidentes de desatualização. +**Políticas de cache configuráveis**: Permite ajustes específicos para cada implantação, com base na frequência de mutação. + +**Configuração de Cache Recomendada pela Taxa de Mutação do Grafo:** +**Alta mutação (>100 alterações/hora)**: TTL=60s, tamanhos de cache menores. +**Média mutação (10-100 alterações/hora)**: TTL=300s (padrão). +**Baixa mutação (<10 alterações/hora)**: TTL=600s, tamanhos de cache maiores. +======= +**Cache de rótulos (TTL de 5 minutos)**: Risco de servir rótulos de entidades excluídas/renomeadas +**Sem cache de embeddings**: Não necessário - os embeddings já são armazenados em cache por consulta +**Sem cache de resultados**: Impede que resultados de subgrafos desatualizados sejam retornados devido à exclusão de entidades/relacionamentos + +**Estratégias de Mitigação:** +**Valores de TTL conservadores**: Equilibre os ganhos de desempenho (10-20%) com a atualização dos dados +**Hooks de invalidação de cache**: Integração opcional com eventos de mutação do grafo +**Painéis de monitoramento**: Acompanhe as taxas de acerto do cache versus incidentes de desatualização +**Políticas de cache configuráveis**: Permite ajustes específicos para cada implantação, com base na frequência de mutação + +**Configuração de Cache Recomendada pela Taxa de Mutação do Grafo:** +**Alta mutação (>100 alterações/hora)**: TTL=60s, tamanhos de cache menores +**Média mutação (10-100 alterações/hora)**: TTL=300s (padrão) +**Baixa mutação (<10 alterações/hora)**: TTL=600s, tamanhos de cache maiores +>>>>>>> 82edf2d (New md files from RunPod) + +## Considerações de Segurança + +**Prevenção de Injeção de Consulta:** +<<<<<<< HEAD +Valide todos os identificadores de entidade e parâmetros de consulta. +Use consultas parametrizadas para todas as interações com o banco de dados. +Implemente limites de complexidade de consulta para evitar ataques de negação de serviço (DoS). + +**Proteção de Recursos:** +Aplique limites máximos de tamanho de subgrafo. +Implemente tempos limite de consulta para evitar o esgotamento de recursos. +Adicione monitoramento e limites de uso de memória. + +**Controle de Acesso:** +Mantenha o isolamento existente de usuários e coleções. +Adicione registro de auditoria para operações que afetam o desempenho. +Implemente limitação de taxa para operações dispendiosas. +======= +Valide todos os identificadores de entidade e parâmetros de consulta +Use consultas parametrizadas para todas as interações com o banco de dados +Implemente limites de complexidade de consulta para evitar ataques de negação de serviço (DoS) + +**Proteção de Recursos:** +Aplique limites máximos de tamanho de subgrafo +Implemente tempos limite de consulta para evitar o esgotamento de recursos +Adicione monitoramento e limites de uso de memória + +**Controle de Acesso:** +Mantenha o isolamento existente de usuários e coleções +Adicione registro de auditoria para operações que afetam o desempenho +Implemente limitação de taxa para operações dispendiosas +>>>>>>> 82edf2d (New md files from RunPod) + +## Considerações de Desempenho + +### Melhorias de Desempenho Esperadas + +**Redução de Consultas:** +<<<<<<< HEAD +Atual: ~9.000+ consultas para um pedido típico. +Otimizado: ~50-100 consultas agrupadas (redução de 98%). + +**Melhorias no Tempo de Resposta:** +Travessia do grafo: 15-20s → 3-5s (4-5 vezes mais rápido). +Resolução de rótulos: 8-12s → 2-4s (3 vezes mais rápido). +Consulta geral: 25-35s → 6-10s (melhora de 3-4 vezes). + +**Eficiência de Memória:** +Tamanhos de cache limitados evitam vazamentos de memória. +Estruturas de dados eficientes reduzem a pegada de memória em ~40%. +Melhor coleta de lixo através da limpeza adequada de recursos. + +**Expectativas Realistas de Desempenho:** +**Cache de rótulos**: Redução de 10-20% nas consultas para grafos com relacionamentos comuns. +**Otimização de agrupamento**: Redução de 50-80% nas consultas (otimização primária). +**Otimização do ciclo de vida do objeto**: Elimina a sobrecarga de criação por pedido. +**Melhora geral**: Melhoria de 3-4 vezes no tempo de resposta, principalmente devido ao agrupamento. + +**Melhorias de Escalabilidade:** +Suporte para grafos de conhecimento 3-5 vezes maiores (limitado pelas necessidades de consistência do cache). +Capacidade de solicitação concorrente 3-5 vezes maior. +Melhor utilização de recursos através da reutilização de conexões. +======= +Atual: ~9.000+ consultas para um pedido típico +Otimizado: ~50-100 consultas em lote (redução de 98%) + +**Melhorias no Tempo de Resposta:** +Traversal do grafo: 15-20s → 3-5s (4-5x mais rápido) +Resolução de rótulos: 8-12s → 2-4s (3x mais rápido) +Consulta geral: 25-35s → 6-10s (melhora de 3-4x) + +**Eficiência de Memória:** +Tamanhos de cache limitados evitam vazamentos de memória +Estruturas de dados eficientes reduzem a pegada de memória em ~40% +Melhor coleta de lixo através da limpeza adequada de recursos + +**Expectativas Realistas de Desempenho:** +**Cache de rótulos**: Redução de 10-20% nas consultas para grafos com relacionamentos comuns +**Otimização de lote**: Redução de 50-80% nas consultas (otimização primária) +**Otimização do ciclo de vida do objeto**: Elimina a sobrecarga de criação por pedido +**Melhora geral**: Melhoria de 3-4x no tempo de resposta, principalmente devido ao lote + +**Melhorias na Escalabilidade:** +Suporte para grafos de conhecimento 3-5x maiores (limitado pelas necessidades de consistência do cache) +Capacidade de solicitação concorrente 3-5x maior +Melhor utilização de recursos através da reutilização de conexões +>>>>>>> 82edf2d (New md files from RunPod) + +### Monitoramento de Desempenho + +**Métricas em Tempo Real:** +<<<<<<< HEAD +Tempos de execução de consultas por tipo de operação. +Taxas de acerto e eficácia do cache. +Utilização do pool de conexões do banco de dados. +Uso de memória e impacto da coleta de lixo. +======= +Tempos de execução de consultas por tipo de operação +Taxas de acerto e eficácia do cache +Utilização do pool de conexões do banco de dados +Uso de memória e impacto na coleta de lixo +>>>>>>> 82edf2d (New md files from RunPod) + +**Benchmarking de Desempenho:** +Testes de regressão de desempenho automatizados +Testes de carga com volumes de dados realistas +Benchmarks de comparação com a implementação atual + +## Estratégia de Testes + +### Testes Unitários +<<<<<<< HEAD +Teste de componentes individuais para travessia, cache e resolução de rótulos +======= +Testes de componentes individuais para travessia, cache e resolução de rótulos +>>>>>>> 82edf2d (New md files from RunPod) +Simulações de interações com o banco de dados para testes de desempenho +Testes de expiração de cache e TTL +Tratamento de erros e cenários de timeout + +### Testes de Integração +Testes de ponta a ponta de consultas GraphRAG com otimizações +Testes de interação com o banco de dados com dados reais +Tratamento de solicitações concorrentes e gerenciamento de recursos +Detecção de vazamentos de memória e verificação da limpeza de recursos + +### Testes de Desempenho +Testes de benchmark contra a implementação atual +<<<<<<< HEAD +Testes de carga com tamanhos e complexidades de grafos variáveis +======= +Testes de carga com diferentes tamanhos e complexidades de grafos +>>>>>>> 82edf2d (New md files from RunPod) +Testes de estresse para limites de memória e conexões +Testes de regressão para melhorias de desempenho + +### Testes de Compatibilidade +Verificar a compatibilidade da API GraphRAG existente +Testar com vários backends de banco de dados de grafos +Validar a precisão dos resultados em comparação com a implementação atual + +## Plano de Implementação + +### Abordagem de Implementação Direta +Como as APIs podem ser alteradas, implemente as otimizações diretamente sem a complexidade da migração: + +1. **Substituir `follow_edges`**: Reescrever com travessia em lote iterativa +2. **Otimizar `get_labelgraph`**: Implementar resolução de rótulos paralela +3. **Adicionar GraphRag de longa duração**: Modificar o Processador para manter uma instância persistente +4. **Implementar cache de rótulos**: Adicionar um cache LRU com TTL à classe GraphRag + +### Escopo das Alterações +**Classe de consulta**: Substituir ~50 linhas em `follow_edges`, adicionar ~30 linhas para tratamento em lote +**Classe GraphRag**: Adicionar uma camada de cache (~40 linhas) +**Classe Processador**: Modificar para usar uma instância persistente de GraphRag (~20 linhas) +**Total**: ~140 linhas de alterações focadas, principalmente dentro das classes existentes + +## Cronograma + +**Semana 1: Implementação Central** +Substituir `follow_edges` por travessia iterativa em lote +Implementar resolução de rótulos paralela em `get_labelgraph` +Adicionar uma instância de longa duração de GraphRag ao Processador +Implementar a camada de cache de rótulos + +**Semana 2: Testes e Integração** +Testes unitários para a nova lógica de travessia e cache +Benchmarking de desempenho contra a implementação atual +Testes de integração com dados de grafos reais +Revisão de código e otimização + +**Semana 3: Implantação** +Implantar a implementação otimizada +Monitorar as melhorias de desempenho +Ajustar o TTL do cache e os tamanhos do lote com base no uso real + +## Perguntas Abertas + +**Pool de Conexões do Banco de Dados**: Devemos implementar um pool de conexões personalizado ou usar o pool de conexões do cliente do banco de dados existente? +**Persistência do Cache**: Os caches de rótulos e embeddings devem persistir entre as reinicializações do serviço? +**Cache Distribuído**: Para implantações multi-instância, devemos implementar um cache distribuído com Redis/Memcached? +**Formato do Resultado da Consulta**: Devemos otimizar a representação interna da tripla para uma melhor eficiência de memória? +**Integração de Monitoramento**: Quais métricas devem ser expostas aos sistemas de monitoramento existentes (Prometheus, etc.)? + +## Referências + +[Implementação Original do GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +[Princípios de Arquitetura do TrustGraph](architecture-principles.md) +[Especificação de Gerenciamento de Coleções](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.ru.md b/docs/tech-specs/graphrag-performance-optimization.ru.md new file mode 100644 index 00000000..05907468 --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.ru.md @@ -0,0 +1,745 @@ +--- +layout: default +title: "Техническая спецификация оптимизации производительности GraphRAG" +parent: "Russian (Beta)" +--- + +# Техническая спецификация оптимизации производительности GraphRAG + +> **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. + +## Обзор + +Эта спецификация описывает комплексные оптимизации производительности для алгоритма GraphRAG (Graph Retrieval-Augmented Generation) в TrustGraph. Текущая реализация страдает от значительных узких мест в производительности, которые ограничивают масштабируемость и время отклика. Эта спецификация охватывает четыре основные области оптимизации: + +1. **Оптимизация обхода графа**: Исключение неэффективных рекурсивных запросов к базе данных и реализация пакетной обработки графа. +2. **Оптимизация разрешения меток**: Замена последовательной загрузки меток параллельными/пакетными операциями. +3. **Улучшение стратегии кэширования**: Реализация интеллектуального кэширования с вытеснением по принципу LRU и предварительной загрузкой. +4. **Оптимизация запросов**: Добавление мемоизации результатов и кэширования вложений для повышения скорости отклика. + +## Цели + +**Сокращение объема запросов к базе данных**: Достижение снижения общего количества запросов к базе данных на 50-80% за счет пакетной обработки и кэширования. +**Улучшение времени отклика**: Целевое увеличение скорости построения подграфов в 3-5 раз и ускорение разрешения меток в 2-3 раза. +**Повышение масштабируемости**: Поддержка более крупных графов знаний с улучшением управления памятью. +**Сохранение точности**: Сохранение существующей функциональности GraphRAG и качества результатов. +**Обеспечение параллельности**: Улучшение возможностей параллельной обработки для нескольких одновременных запросов. +<<<<<<< HEAD +**Уменьшение объема памяти**: Реализация эффективных структур данных и управления памятью. +======= +**Уменьшение объема используемой памяти**: Реализация эффективных структур данных и управления памятью. +>>>>>>> 82edf2d (New md files from RunPod) +**Добавление возможностей мониторинга**: Включение показателей производительности и возможностей мониторинга. +**Обеспечение надежности**: Добавление надлежащей обработки ошибок и механизмов таймаута. + +## Предыстория + +Текущая реализация GraphRAG в `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` имеет несколько критических проблем с производительностью, которые серьезно влияют на масштабируемость системы: + +### Текущие проблемы с производительностью + +**1. Неэффективный обход графа (функция `follow_edges`, строки 79-127)** +Выполняет 3 отдельных запроса к базе данных для каждой сущности на каждом уровне глубины. +Шаблон запроса: запросы на основе субъекта, запросы на основе предиката и запросы на основе объекта для каждой сущности. +Без пакетной обработки: Каждый запрос обрабатывает только одну сущность за раз. +Без обнаружения циклов: Может повторно посещать одни и те же узлы несколько раз. +Рекурсивная реализация без мемоизации приводит к экспоненциальной сложности. +Временная сложность: O(entities × max_path_length × triple_limit³) + +**2. Последовательное разрешение меток (функция `get_labelgraph`, строки 144-171)** +Обрабатывает каждый компонент тройки (субъект, предикат, объект) последовательно. +Каждый вызов `maybe_label` потенциально вызывает запрос к базе данных. +Без параллельного выполнения или пакетной обработки запросов меток. +<<<<<<< HEAD +В результате получается до 3 × subgraph_size отдельных вызовов базы данных. +======= +Приводит до 3 × subgraph_size отдельных вызовов базы данных. +>>>>>>> 82edf2d (New md files from RunPod) + +**3. Примитивная стратегия кэширования (функция `maybe_label`, строки 62-77)** +Простой кэш в виде словаря без ограничений размера или TTL. +Отсутствие политики вытеснения кэша приводит к неограниченному росту памяти. +Пропуски кэша вызывают отдельные запросы к базе данных. +Без предварительной загрузки или интеллектуального подогрева кэша. + +**4. Субоптимальные шаблоны запросов** +Запросы на сравнение векторного сходства сущностей не кэшируются между похожими запросами. +Без мемоизации результатов для повторяющихся шаблонов запросов. +<<<<<<< HEAD +Отсутствие оптимизации запросов для распространенных шаблонов доступа. +======= +Отсутствует оптимизация запросов для распространенных шаблонов доступа. +>>>>>>> 82edf2d (New md files from RunPod) + +**5. Критические проблемы с жизненным циклом объектов (`rag.py:96-102`)** +**Объект GraphRag создается для каждого запроса**: Новый экземпляр создается для каждого запроса, что приводит к потере всех преимуществ кэша. +**Объект запроса имеет очень короткий срок службы**: Создается и уничтожается в течение выполнения одного запроса (строки 201-207). +**Кэш меток сбрасывается для каждого запроса**: Подогрев кэша и накопленные знания теряются между запросами. +<<<<<<< HEAD +**Накладные расходы на повторное создание клиента**: Клиенты базы данных потенциально повторно устанавливаются для каждого запроса. +**Без оптимизации между запросами**: Невозможно извлечь выгоду из шаблонов запросов или совместного использования результатов. +======= +**Накладные расходы на повторное создание клиента**: Клиенты базы данных потенциально пересоздаются для каждого запроса. +**Отсутствие оптимизации между запросами**: Невозможно извлечь выгоду из шаблонов запросов или обмена результатами. +>>>>>>> 82edf2d (New md files from RunPod) + +### Анализ влияния на производительность + +Текущий наихудший сценарий для типичного запроса: +**Извлечение сущности**: 1 запрос на сравнение векторного сходства. +**Обход графа**: entities × max_path_length × 3 × triple_limit запросов. +**Разрешение меток**: subgraph_size × 3 отдельных запросов на разрешение меток. + +<<<<<<< HEAD +Для параметров по умолчанию (50 сущностей, длина пути 2, ограничение в 30 тройки, размер подграфа 150): +**Минимальное количество запросов**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9451 запрос к базе данных** +**Время отклика**: 15-30 секунд для графов среднего размера +**Использование памяти**: Неограниваемый рост кэша со временем +======= +Для параметров по умолчанию (50 сущностей, длина пути 2, ограничение в 30 троек, размер подграфа 150): +**Минимальное количество запросов**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9451 запрос к базе данных** +**Время отклика**: 15-30 секунд для графов среднего размера +**Использование памяти**: Неограниченный рост кэша со временем +>>>>>>> 82edf2d (New md files from RunPod) +**Эффективность кэша**: 0% - кэши сбрасываются при каждом запросе +**Накладные расходы на создание объектов**: Объекты GraphRag + Query создаются/удаляются для каждого запроса + +Эта спецификация решает эти проблемы, реализуя пакетные запросы, интеллектуальное кэширование и параллельную обработку. Оптимизируя шаблоны запросов и доступ к данным, TrustGraph может: +Поддерживать графы знаний корпоративного уровня с миллионами сущностей +Обеспечивать время отклика менее 1 секунды для типичных запросов +Обрабатывать сотни одновременных запросов GraphRAG +<<<<<<< HEAD +Эффективно масштабироваться в зависимости от размера и сложности графа +======= +Эффективно масштабироваться с увеличением размера и сложности графа +>>>>>>> 82edf2d (New md files from RunPod) + +## Технический дизайн + +### Архитектура + +Оптимизация производительности GraphRAG требует следующих технических компонентов: + +#### 1. **Архитектурная реорганизация жизненного цикла объектов** +<<<<<<< HEAD + **Сделать GraphRag долгоживущим**: Переместить экземпляр GraphRag на уровень Processor для сохранения между запросами + **Сохранять кэши**: Поддерживать кэш меток, кэш вложений и кэш результатов запросов между запросами + **Оптимизировать объект Query**: Переработать Query как легковесный контекст выполнения, а не контейнер данных + **Сохранять подключения к базе данных**: Поддерживать подключения к базе данных между запросами +======= + **Сделать GraphRag долгоживущим**: Переместить экземпляр GraphRag на уровень Processor для сохранения данных между запросами + **Сохранять кэши**: Поддерживать кэш меток, кэш вложений и кэш результатов запросов между запросами + **Оптимизировать объект Query**: Переработать Query как легковесный контекст выполнения, а не контейнер данных + **Сохранять соединения с базой данных**: Поддерживать соединения с базой данных между запросами +>>>>>>> 82edf2d (New md files from RunPod) + + Модуль: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (изменен) + +#### 2. **Оптимизированный движок обхода графа** +<<<<<<< HEAD + Заменить рекурсивную `follow_edges` на итеративный поиск в ширину + Реализовать пакетную обработку сущностей на каждом уровне обхода + Добавить обнаружение циклов с помощью отслеживания посещенных узлов +======= + Заменить рекурсивную функцию `follow_edges` на итеративный поиск в ширину + Реализовать пакетную обработку сущностей на каждом уровне обхода + Добавить обнаружение циклов с использованием отслеживания посещенных узлов +>>>>>>> 82edf2d (New md files from RunPod) + Включить раннее завершение при достижении лимитов + + Модуль: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **Параллельная система разрешения меток** + Пакетные запросы меток для нескольких сущностей одновременно + Реализовать шаблоны async/await для параллельного доступа к базе данных + Добавить интеллектуальную предварительную загрузку для распространенных шаблонов меток + Включить стратегии предварительного заполнения кэша меток + + Модуль: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **Консервативный слой кэширования меток** + Кэш LRU с коротким TTL только для меток (5 минут) для баланса между производительностью и согласованностью +<<<<<<< HEAD + Мониторинг метрик кэша и коэффициента попадания + **Без кэширования вложений**: Уже кэшируются для каждого запроса, нет преимуществ для межзапросных данных +======= + Мониторинг метрик кэша и коэффициента попаданий + **Без кэширования вложений**: Уже кэшируются для каждого запроса, нет преимуществ для межзапросных операций +>>>>>>> 82edf2d (New md files from RunPod) + **Без кэширования результатов запросов**: Из-за проблем согласованности изменений графа + + Модуль: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **Фреймворк оптимизации запросов** + Анализ шаблонов запросов и предложения по оптимизации + Пакетный координатор запросов для доступа к базе данных +<<<<<<< HEAD + Управление пулами соединений и временем ожидания запросов +======= + Управление пулом соединений и временем ожидания запросов +>>>>>>> 82edf2d (New md files from RunPod) + Мониторинг производительности и сбор метрик + + Модуль: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### Модели данных + +#### Оптимизированное состояние обхода графа + +Движок обхода поддерживает состояние для предотвращения избыточных операций: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +Этот подход позволяет: +Эффективное обнаружение циклов за счет отслеживания посещенных сущностей. +Подготовку запросов пакетами на каждом уровне обхода. +Экономичное использование памяти для управления состоянием. +Раннее завершение, когда достигнуты ограничения по размеру. + +#### Улучшенная структура кэша + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### Структуры пакетных запросов + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### API + +#### Новые API: + +**API GraphTraversal** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**API для разрешения меток пакетов** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**API управления кэшем** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### Измененные API: + +**GraphRag.query()** - Улучшено с оптимизациями производительности: +Добавлен параметр cache_manager для управления кэшем. +Добавлено возвращаемое значение performance_metrics. +Добавлен параметр query_timeout для повышения надежности. + +**Класс Query** - Рефакторинг для пакетной обработки: +Замена обработки отдельных сущностей на пакетные операции. +Добавлены асинхронные контекстные менеджеры для очистки ресурсов. +Добавлены обратные вызовы для отслеживания прогресса длительных операций. + +### Детали реализации + +#### Фаза 0: Критическая архитектурная реорганизация жизненного цикла + +**Текущая проблемная реализация:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +**Оптимизированная архитектура с длительным сроком службы:** +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +Это архитектурное изменение обеспечивает: +**Сокращение количества запросов к базе данных на 10-20%** для графов с общими связями (по сравнению с текущими 0%) +**Устранение накладных расходов на создание объектов** для каждого запроса +**Постоянное использование пула соединений и повторное использование клиентов** +**Оптимизация между запросами** в пределах временных окон TTL кэша + +**Важное ограничение согласованности кэша:** +Долгосрочное кэширование создает риск устаревания данных, когда сущности/метки удаляются или изменяются в базовом графе. Кэш LRU с TTL обеспечивает баланс между повышением производительности и актуальностью данных, но не может обнаруживать изменения в графе в режиме реального времени. + +#### Фаза 1: Оптимизация обхода графа + +**Проблемы текущей реализации:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**Оптимизированная реализация:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### Фаза 2: Параллельное разрешение меток + +**Текущая последовательная реализация:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**Оптимизированная параллельная реализация:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### Фаза 3: Продвинутая стратегия кэширования + +**Кэш LRU с TTL:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### Фаза 4: Оптимизация запросов и мониторинг + +**Сбор показателей производительности:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**Тайм-аут запроса и предохранитель:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## Соображения по обеспечению согласованности кэша + +**Компромиссы между актуальностью данных:** +**Кэш меток (TTL 5 минут):** Риск предоставления устаревших меток сущностей (удаленных или переименованных). +<<<<<<< HEAD +**Отсутствие кэширования вложений:** Не требуется, так как вложения уже кэшируются для каждого запроса. +======= +**Отсутствие кэширования вложений:** Не требуется - вложения уже кэшируются для каждого запроса. +>>>>>>> 82edf2d (New md files from RunPod) +**Отсутствие кэширования результатов:** Предотвращает получение устаревших результатов подграфов из-за удаленных сущностей/связей. + +**Стратегии смягчения:** +**Консервативные значения TTL:** Баланс между приростом производительности (10-20%) и актуальностью данных. +<<<<<<< HEAD +**Хуки для аннулирования кэша:** Необязательная интеграция с событиями изменения графа. +**Панели мониторинга:** Отслеживание показателей попадания в кэш по сравнению с инцидентами устаревания данных. +**Настраиваемые политики кэширования:** Возможность тонкой настройки для каждого развертывания в зависимости от частоты изменений. + +**Рекомендуемая конфигурация кэша в зависимости от частоты изменений графа:** +**Высокая частота изменений (>100 изменений/час):** TTL=60 секунд, меньшие размеры кэша. +**Средняя частота изменений (10-100 изменений/час):** TTL=300 секунд (по умолчанию). +**Низкая частота изменений (<10 изменений/час):** TTL=600 секунд, большие размеры кэша. +======= +**Механизмы аннулирования кэша:** Необязательная интеграция с событиями изменения графа. +**Информационные панели мониторинга:** Отслеживание показателей попадания в кэш по сравнению с инцидентами устаревания данных. +**Настраиваемые политики кэширования:** Возможность тонкой настройки для каждого развертывания в зависимости от частоты изменений. + +**Рекомендуемая конфигурация кэша в зависимости от скорости изменений графа:** +**Высокая скорость изменений (>100 изменений/час):** TTL=60 секунд, меньшие размеры кэша. +**Средняя скорость изменений (10-100 изменений/час):** TTL=300 секунд (по умолчанию). +**Низкая скорость изменений (<10 изменений/час):** TTL=600 секунд, большие размеры кэша. +>>>>>>> 82edf2d (New md files from RunPod) + +## Соображения безопасности + +**Предотвращение внедрения запросов:** +Проверка всех идентификаторов сущностей и параметров запроса. +Использование параметризованных запросов для всех взаимодействий с базой данных. +Реализация ограничений на сложность запросов для предотвращения атак типа "отказ в обслуживании" (DoS). + +**Защита ресурсов:** +Применение ограничений на максимальный размер подграфа. +Реализация таймаутов запросов для предотвращения исчерпания ресурсов. +Добавление мониторинга и ограничений использования памяти. + +**Контроль доступа:** +Поддержание существующей изоляции пользователей и коллекций. +Добавление ведения журнала аудита для операций, влияющих на производительность. +Реализация ограничения скорости для дорогостоящих операций. + +## Соображения производительности + +<<<<<<< HEAD +### Ожидаемые улучшения производительности + +**Сокращение количества запросов:** +Сейчас: ~9000+ запросов для типичного запроса. +Оптимизировано: ~50-100 пакетных запросов (снижение на 98%). +======= +### Ожидаемое повышение производительности + +**Сокращение количества запросов:** +Текущее: ~9000+ запросов для типичного запроса. +Оптимизированное: ~50-100 пакетных запросов (снижение на 98%). +>>>>>>> 82edf2d (New md files from RunPod) + +**Улучшение времени отклика:** +Обход графа: 15-20 секунд → 3-5 секунд (в 4-5 раза быстрее). +Разрешение меток: 8-12 секунд → 2-4 секунды (в 3 раза быстрее). +Общий запрос: 25-35 секунд → 6-10 секунд (улучшение в 3-4 раза). + +**Эффективность использования памяти:** +Ограниченные размеры кэша предотвращают утечки памяти. +Эффективные структуры данных уменьшают объем используемой памяти примерно на 40%. +<<<<<<< HEAD +Улучшен сбор мусора благодаря правильной очистке ресурсов. +======= +Улучшенная сборка мусора благодаря правильной очистке ресурсов. +>>>>>>> 82edf2d (New md files from RunPod) + +**Реалистичные ожидания производительности:** +**Кэш меток:** Уменьшение количества запросов на 10-20% для графов с общими связями. +**Оптимизация пакетной обработки:** Уменьшение количества запросов на 50-80% (основная оптимизация). +**Оптимизация времени жизни объектов:** Исключение накладных расходов на создание объектов для каждого запроса. +**Общее улучшение:** Улучшение времени отклика в 3-4 раза, в основном за счет пакетной обработки. + +**Улучшения масштабируемости:** +Поддержка графов знаний в 3-5 раза большего размера (ограничено потребностями согласованности кэша). +Увеличение количества одновременных запросов в 3-5 раза. +Лучшее использование ресурсов благодаря повторному использованию соединений. + +### Мониторинг производительности + +**Метрики в реальном времени:** +Время выполнения запросов по типу операции. +Показатели попадания в кэш и его эффективность. +Использование пула соединений с базой данных. +Использование памяти и влияние сборки мусора. + +**Бенчмаркинг производительности:** +Автоматизированное регрессионное тестирование производительности +Тестирование нагрузки с использованием реалистичных объемов данных +Сравнительные тесты с текущей реализацией + +## Стратегия тестирования + +### Модульное тестирование +Тестирование отдельных компонентов для обхода графа, кэширования и разрешения меток +Эмуляция взаимодействия с базой данных для тестирования производительности +Тестирование вытеснения из кэша и истечения срока действия TTL +Обработка ошибок и сценарии таймаутов + +### Интеграционное тестирование +Комплексное тестирование запросов GraphRAG с оптимизациями +Тестирование взаимодействия с базой данных с использованием реальных данных +Обработка одновременных запросов и управление ресурсами +Обнаружение утечек памяти и проверка очистки ресурсов + +### Тестирование производительности +Тестирование производительности по сравнению с текущей реализацией +<<<<<<< HEAD +Тестирование нагрузки с различными размерами и сложностью графов +======= +Тестирование нагрузки с графами различного размера и сложности +>>>>>>> 82edf2d (New md files from RunPod) +Стресс-тестирование для проверки лимитов памяти и соединений +Регрессионное тестирование для проверки улучшений производительности + +### Тестирование совместимости +Проверка совместимости существующего API GraphRAG +Тестирование с различными бэкендами графовых баз данных +Проверка точности результатов по сравнению с текущей реализацией + +## План реализации + +### Прямой подход к реализации +Поскольку API могут изменяться, реализуйте оптимизации напрямую без сложности миграции: + +1. **Замените метод `follow_edges`**: Перепишите с использованием пакетного итеративного обхода +2. **Оптимизируйте `get_labelgraph`**: Реализуйте параллельное разрешение меток +3. **Добавьте долгоживущий GraphRag**: Измените Processor для поддержания постоянной инстанции +<<<<<<< HEAD +4. **Реализуйте кэширование меток**: Добавьте кэш LRU с TTL в класс GraphRag +======= +4. **Реализуйте кэширование меток**: Добавьте кэш LRU со сроком действия TTL в класс GraphRag +>>>>>>> 82edf2d (New md files from RunPod) + +### Область изменений +**Класс запроса**: Замените ~50 строк в `follow_edges`, добавьте ~30 строк для обработки пакетов +**Класс GraphRag**: Добавьте слой кэширования (~40 строк) +**Класс Processor**: Измените для использования постоянной инстанции GraphRag (~20 строк) +<<<<<<< HEAD +**Всего**: ~140 строк целенаправленных изменений, в основном в существующих классах +======= +**Всего**: ~140 строк изменений, в основном в существующих классах +>>>>>>> 82edf2d (New md files from RunPod) + +## Временная шкала + +**Неделя 1: Основная реализация** +Замените `follow_edges` пакетным итеративным обходом +Реализуйте параллельное разрешение меток в `get_labelgraph` +Добавьте долгоживущую инстанцию GraphRag в Processor +Реализуйте слой кэширования меток + +**Неделя 2: Тестирование и интеграция** +Модульные тесты для новой логики обхода и кэширования +Бенчмаркинг производительности по сравнению с текущей реализацией +<<<<<<< HEAD +Интеграционное тестирование с реальными данными графа +======= +Интеграционное тестирование с реальными графовыми данными +>>>>>>> 82edf2d (New md files from RunPod) +Проверка кода и оптимизация + +**Неделя 3: Развертывание** +Разверните оптимизированную реализацию +Отслеживайте улучшения производительности +<<<<<<< HEAD +Тонкая настройка TTL кэша и размеров пакетов на основе реального использования + +## Открытые вопросы + +**Пул соединений с базой данных**: Следует ли нам реализовать собственный пул соединений или использовать существующий пул соединений от клиента базы данных? +**Постоянство кэша**: Должны ли кэши меток и внедрений сохраняться после перезапуска службы? +**Распределенное кэширование**: Для развернутых в нескольких экземплярах систем следует ли нам реализовать распределенное кэширование с использованием Redis/Memcached? +**Формат результата запроса**: Следует ли нам оптимизировать внутреннее представление тройки для повышения эффективности использования памяти? +======= +Тонкая настройка срока действия TTL кэша и размеров пакетов на основе реального использования + +## Открытые вопросы + +**Пул соединений с базой данных**: Следует ли нам реализовывать собственный пул соединений или использовать существующий пул соединений от клиента базы данных? +**Постоянство кэша**: Должны ли кэши меток и вложений сохраняться после перезапуска сервиса? +**Распределенное кэширование**: Для развернутых в нескольких инстанциях систем следует ли реализовывать распределенное кэширование с использованием Redis/Memcached? +**Формат результата запроса**: Следует ли оптимизировать внутреннее представление тройки для повышения эффективности использования памяти? +>>>>>>> 82edf2d (New md files from RunPod) +**Интеграция мониторинга**: Какие метрики следует предоставлять существующим системам мониторинга (Prometheus и т. д.)? + +## Ссылки + +<<<<<<< HEAD +[Оригинальная реализация GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +======= +[Исходная реализация GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +>>>>>>> 82edf2d (New md files from RunPod) +[Принципы архитектуры TrustGraph](architecture-principles.md) +[Спецификация управления коллекциями](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.sw.md b/docs/tech-specs/graphrag-performance-optimization.sw.md new file mode 100644 index 00000000..6eb03a8b --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.sw.md @@ -0,0 +1,899 @@ +--- +layout: default +title: "Vipimo vya Ufanisi wa GraphRAG kwa Uboreshaji wa Kawaida" +parent: "Swahili (Beta)" +--- + +<<<<<<< HEAD +# Vipimo vya Ufanisi wa GraphRAG kwa Uboreshaji wa Kawaida + +> **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. +======= +# Vipimo vya Ufanisi wa GraphRAG kwa Uboreshaji wa Kiufundi +>>>>>>> 82edf2d (New md files from RunPod) + +## Maelezo + +<<<<<<< HEAD +Hati hii inaeleza uboreshaji wa kina wa utendaji wa algorithm ya GraphRAG (Graph Retrieval-Augmented Generation) katika TrustGraph. Utaratibu wa sasa una matatizo makubwa ya utendaji ambayo yanapunguza uwezo wa kupanuka na wakati wa majibu. Hati hii inashughulikia maeneo manne makuu ya uboreshaji: + +1. **Uboreshaji wa Ufuatiliaji wa Grafu**: Ondoa maswali ya hivi karibuni ya hivi karibuni ya hivi karibuni na tekeleza utafutaji wa grafu wa kikundi +2. **Uboreshaji wa Utatuzi wa Lebo**: Badilisha upekuzi wa hivi karibuni wa lebo na shughuli za sambamba/za kikundi +3. **Uboreshaji wa Mkakati wa Kumbukumbu**: Tekeleza kumbukumbu mahiri na kuondoa kwa LRU na utabiri +4. **Uboreshaji wa Ulipaji**: Ongeza kumbukumbu ya matokeo na kumbukumbu ya uingizaji kwa kuboresha wakati wa majibu + +## Lengo + +**Punguza Kiasi cha Maswali ya Hivi Karibuni**: Pata kupunguzwa kwa 50-80% katika jumla ya maswali ya hivi karibuni kupitia kikundi na kumbukumbu +**Boresha Wakati wa Majibu**: Lenga ujenzi wa subgrafu wa haraka 3-5x na utatuzi wa lebo wa haraka 2-3x +**Boresha Uwezo wa Kupanuka**: Unga grafu kubwa za maarifa na usimamizi bora wa kumbukumbu +**Dumishe Usahihi**: Dumishe utendaji na ubora wa matokeo ya GraphRAG iliyopo +**Wezesha Ulinganifu**: Boresha uwezo wa usindikaji sambamba kwa maombi mengi ya sambamba +**Punguza Uzito wa Kumbukumbu**: Tekeleza miundo ya data na usimamizi wa kumbukumbu bora +**Ongeza Ufuatiliaji**: Jumuisha metriki za utendaji na uwezo wa ufuatiliaji +**Hakikisha Utendaji**: Ongeza ushughulikiaji sahihi wa makosa na mitambo ya muda +======= +Maelekezo haya yanaelezea uboreshaji wa kina wa utendaji kwa algorithm ya GraphRAG (Graph Retrieval-Augmented Generation) katika TrustGraph. Utaratibu wa sasa una matatizo makubwa ya utendaji ambayo yanapunguza uwezo wa kupanuka na wakati wa majibu. Maelekezo haya yanaangazia maeneo manne makuu ya uboreshaji: + +1. **Uboreshaji wa Ufuatiliaji wa Grafu**: Ondoa maswali ya hivi karibuni ya hivi karibuni ya hivi karibuni na tekeleza utafutaji wa grafu wa kikundi. +2. **Uboreshaji wa Utatuzi wa Lebo**: Badilisha upekuzi wa lebo wa mfululizo na shughuli za sambamba/za kikundi. +3. **Uboreshaji wa Mkakati wa Kumbukumbu**: Tekeleza kumbukumbu mahiri na kuondoa kwa LRU na utabiri. +4. **Uboreshaji wa Ulipaji**: Ongeza kumbukumbu ya matokeo na kumbukumbu ya uingizaji kwa kuboresha wakati wa majibu. + +## Lengo + +**Punguza Kiasi cha Maswali ya Hivi Karibuni**: Pata kupunguzwa kwa 50-80% katika jumla ya maswali ya hivi karibuni kupitia kikundi na kumbukumbu. +**Boresha Wakati wa Majibu**: Lenga ujenzi wa subgraph wa haraka 3-5x na utatuzi wa lebo wa haraka 2-3x. +**Boresha Uwezo wa Kupanuka**: Unga grafu kubwa za maarifa na usimamizi bora wa kumbukumbu. +**Dumishe Usahihi**: Dumishe utendaji na ubora wa matokeo ya GraphRAG iliyopo. +**Wezesha Ulinganifu**: Boresha uwezo wa usindikaji sambamba kwa maombi mengi ya sambamba. +**Punguza Uzito wa Kumbukumbu**: Tekeleza miundo ya data na usimamizi wa kumbukumbu bora. +**Ongeza Ufuatiliaji**: Jumuisha metriki za utendaji na uwezo wa ufuatiliaji. +**Hakikisha Utendaji**: Ongeza ushughulikiaji sahihi wa makosa na mitambo ya muda. +>>>>>>> 82edf2d (New md files from RunPod) + +## Asili + +Utaratibu wa sasa wa GraphRAG katika `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` una masuala muhimu ya utendaji ambayo yanaathiri sana uwezo wa kupanuka wa mfumo: + +### Matatizo ya Sasa ya Utendaji + +**1. Ufuatiliaji Usio na Ufanisi wa Grafu (kitendaji cha `follow_edges`, mistari 79-127)** +<<<<<<< HEAD +Hufanya maswali 3 tofauti ya hivi karibuni kwa kila kitu kwa kila kiwango cha kina +Mfumo wa swali: maswali ya msingi ya mada, maswali ya msingi ya tabia, na maswali ya msingi ya kitu kwa kila kitu +Hakuna kikundi: Kila swali huchakata kitu kimoja wakati mmoja +Hakuna utambuzi wa mzunguko: Inaweza kurudi kwenye nodi sawa mara nyingi +Utaratibu wa hivi karibuni bila kumbukumbu husababisha utata wa kielelekevu +Utata wa wakati: O(vitabu × urefu_max_ya_njia × triple_limit³) + +**2. Utatuzi wa Hivi Karibuni wa Lebo (kitendaji cha `get_labelgraph`, mistari 144-171)** +Huchakata kila sehemu ya tatu (mhusika, tabia, kitu) kwa hivi karibuni +Kila wito wa `maybe_label` inaweza kusababisha swali la hivi karibuni la hivi karibuni +Hakuna utekelezaji sambamba au kikundi cha maswali ya lebo +Hupelekea hadi simu 3 × ya hivi karibuni ya hivi karibuni ya hivi karibuni. + +**3. Mkakati wa Kumbukumbu wa Msingi (kitendaji cha `maybe_label`, mistari 62-77)** +Kumbukumbu rahisi ya kamusi bila mipaka ya saizi au TTL +Hakuna sera ya kuondoa kumbukumbu inayosababisha ukuaji usio na kikomo wa kumbukumbu +Kupoteza kumbukumbu hutuma maswali ya hivi karibuni ya hivi karibuni ya hivi karibuni +Hakuna utabiri au uongezaji mahiri wa kumbukumbu + +**4. Mfumo Usio na Ufanisi wa Maswali** +Maswali ya ufanano wa vekta ya kitu hayahifadhiwi kati ya maombi sawa +Hakuna kumbukumbu ya matokeo kwa mifumo ya swali iliyorudiwa +Uboreshaji wa swali unaokosekana kwa mifumo ya kawaida ya ufikiaji + +**5. Masuala Muhimu ya Maisha ya Kitu (`rag.py:96-102`)** +**Kitu cha GraphRag kinaundwa kwa kila ombi**: Toleo jipya huundwa kwa kila swali, na kupoteza faida zote za kumbukumbu +**Kitu cha swali kina muda mfupi sana**: Huundwa na kuharibiwa ndani ya utekelezaji wa swali moja (mistari 201-207) +**Kumbukumbu ya lebo inarejeshwa kwa kila ombi**: Uongezaji wa kumbukumbu na maarifa yaliyokusanywa yanapotea kati ya maombi +**Upeo wa upya wa mteja**: Wateja wa hivi karibuni wanaweza kuanzishwa tena kwa kila ombi +**Hakuna uboreshaji wa kati ya maombi**: Haiwezi kufaidika na mifumo ya swali au ushirikishwaji wa matokeo +======= +Hufanya maswali 3 tofauti ya hivi karibuni kwa kila kitu kwa kila ngazi ya kina. +Mfumo wa swali: maswali ya msingi ya mada, maswali ya msingi ya tabia, na maswali ya msingi ya kitu kwa kila kitu. +Hakuna kikundi: Kila swali huchakata kitu kimoja wakati mmoja. +Hakuna utambuzi wa mzunguko: Inaweza kurudi kwenye nodi sawa mara nyingi. +Utaratibu wa hivi karibuni bila kumbukumbu husababisha utata wa kielelekeo. +Utata wa muda: O(vitabu × urefu_max_wa_njia × kikomo_cha_triple³) + +**2. Utatuzi wa Msingi wa Lebo (kitendaji cha `get_labelgraph`, mistari 144-171)** +Huchakata kila sehemu ya triple (mhusika, tabia, kitu) kwa utaratibu. +Kila wito wa `maybe_label` inaweza kusababisha swali la hivi karibuni. +Hakuna utekelezaji sambamba au kikundi cha maswali ya lebo. +Hupelekea hadi simu 3 × ya hivi karibuni ya mtu binafsi ya hivi karibuni. + +**3. Mkakati wa Kumbukumbu ya Msingi (kitendaji cha `maybe_label`, mistari 62-77)** +Kumbukumbu rahisi ya kamusi bila mipaka ya ukubwa au TTL. +Hakuna sera ya kuondoa kumbukumbu inayosababisha ukuaji usio na kikomo wa kumbukumbu. +Kupoteza kumbukumbu hutuma maswali ya hivi karibuni ya mtu binafsi ya hivi karibuni. +Hakuna utabiri au uongezaji mahiri wa kumbukumbu. + +**4. Mfumo Usio na Ufanisi wa Maswali** +Maswali ya ufanano wa vekta ya kitu hayahifadhiwi kati ya maombi sawa. +Hakuna kumbukumbu ya matokeo kwa mifumo ya swali iliyorudiwa. +Uboreshaji wa swali unaokosekana kwa mifumo ya kawaida ya ufikiaji. + +**5. Masuala Muhimu ya Muda wa Kitu (`rag.py:96-102`)** +**Kitu cha GraphRag kinaundwa kila maombi**: Mfano mpya huundwa kwa kila swali, ukipoteza faida zote za kumbukumbu. +**Kitu cha swali kina muda mfupi sana**: Huundwa na kuharibiwa ndani ya utekelezaji wa swali moja (mistari 201-207). +**Kumbukumbu ya lebo inarejeshwa kwa kila maombi**: Uongezaji wa kumbukumbu na maarifa yaliyokusanywa hupotea kati ya maombi. +**Upekee wa upya wa mteja**: Wateja wa hivi karibuni wanaweza kuanzishwa tena kwa kila maombi. +**Hakuna uboreshaji wa maombi**: Haiwezi kufaidika na mifumo ya swali au ushirikishwaji wa matokeo. +>>>>>>> 82edf2d (New md files from RunPod) + +### Uchambuzi wa Athari ya Utendaji + +Hali mbaya zaidi ya sasa kwa swali la kawaida: +<<<<<<< HEAD +**Upekuzi wa Kitu**: swali 1 la ufanano wa vekta +**Ufuatiliaji wa Grafu**: vitu × urefu_max_ya_njia × 3 × maswali ya hivi karibuni ya hivi karibuni ya hivi karibuni +**Utatuzi wa Lebo**: maswali ya hivi karibuni ya hivi karibuni ya hivi karibuni ya subgrafu_size × 3 + +Kwa vigezo chache (vitu 50, urefu wa njia 2, kikomo cha triplet 30, saizi ya subgraph 150): +**Maswali ya chini**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **maswali 9,451 ya hifadhidata** +**Wakati wa majibu**: Sekunde 15-30 kwa vielelezo vya saizi ya wastani +**Matumizi ya kumbukumbu**: Ukubwa wa kumbukumbu unaoongezeka bila kikomo baada ya muda +**Ufanisi wa kumbukumbu**: 0% - kumbukumbu hurejeshwa kila ombi +======= +**Upekuzi wa Kitu**: swali 1 la ufanano wa vekta. +**Ufuatiliaji wa Grafu**: vitabu × urefu_max_wa_njia × 3 × maswali ya hivi karibuni ya triple. +**Utatuzi wa Lebo**: maswali ya mtu binafsi ya hivi karibuni ya lebo ya subgraph_size × 3. + +Kwa vigezo chaguvi (vitu 50, urefu wa njia 2, kikomo cha triplet 30, saizi ya subgraph 150): +**Maswali ya chini**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **maswali 9,451 ya hifadhidata** +**Wakati wa majibu**: sekunde 15-30 kwa vielelezo vya saizi ya wastani +**Matumizi ya kumbukumbu**: ukuaji usio na kikomo wa kumbukumbu kwa muda +**Ufanisi wa kumbukumbu**: 0% - kumbukumbu hurekebishwa kila mara +>>>>>>> 82edf2d (New md files from RunPod) +**Utozo wa kuunda vitu**: Vitu vya GraphRag + Query vinaundwa/vinaharibiwa kwa kila ombi + +Maelezo haya yanaangazia pengo hizi kwa kutumia maswali ya kikundi, uhifadhi mahiri, na usindikaji wa sambamba. Kwa kuboresha mifumo ya maswali na ufikiaji wa data, TrustGraph inaweza: +Kusaidia vielelezo vya maarifa vya kiwango cha shirika na mamilioni ya vitu +Kutoa wakati wa majibu ya chini ya sekunde kwa maswali ya kawaida +Kushughulikia maombi mamia ya GraphRAG kwa wakati mmoja +Kuongezeka kwa ufanisi na saizi na utata wa vielelezo + +## Muundo wa Kiufundi + +### Usanifu + +Uboreshaji wa utendaji wa GraphRAG unahitaji vipengele hivi vya kiufundi: + +#### 1. **Urekebishaji wa Usanifu wa Muda wa Vitu** +<<<<<<< HEAD + **Fanya GraphRag iwe na muda mrefu**: Hamisha mfano wa GraphRag hadi ngazi ya Processor ili kudumu katika maombi + **Ondoa kumbukumbu**: Dumishe kumbukumbu ya lebo, kumbukumbu ya uingizaji, na kumbukumbu ya matokeo ya swali kati ya maombi + **Boresha kitu cha Swali**: Rekebisha Swali ili iwe mfumo wa utekelezaji mwepesi, sio chombo cha data + **Usaidizi wa muunganisho**: Dumishe miunganisho ya mteja wa hifadhidata katika maombi +======= + **Fanya GraphRag iwe ya muda mrefu**: Hamisha mfano wa GraphRag hadi ngazi ya Processor ili kudumu katika ombi + **Ondoa kumbukumbu**: Dumishe kumbukumbu ya lebo, kumbukumbu ya uingizaji, na kumbukumbu ya matokeo ya swali kati ya ombi + **Boresha kitu cha Swali**: Rekebisha Swali ili iwe muktadha wa utekelezaji mwepesi, sio chombo cha data + **Usaidizi wa muunganisho**: Dumishe miunganisho ya mteja wa hifadhidata katika ombi +>>>>>>> 82edf2d (New md files from RunPod) + + Moduli: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (iliyorekebishwa) + +#### 2. **Injini Iliyoboreshwa ya Ufuatiliaji wa Vielelezo** + Badilisha `follow_edges` ya kurudia na utafutaji wa upana wa mara kwa mara + Tekeleza usindikaji wa kikundi wa vitu katika kila ngazi ya ufuatiliaji + Ongeza ugunduzi wa mzunguko kwa kufuatilia nodi zilizotembelewa + Jumuisha kumalizika mapema wakati mipaka inafikiwa + + Moduli: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +<<<<<<< HEAD +#### 3. **Mfumo wa Ufafanuzi wa Lebo Sambamba** + Kikundi maswali ya lebo kwa vitu vingi kwa wakati mmoja + Tekeleza mifumo ya async/await kwa ufikiaji sambamba wa hifadhidata + Ongeza upakiaji wa akili kwa mifumo ya kawaida ya lebo + Jumuisha mikakati ya ukausha wa kumbukumbu ya lebo + + Moduli: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **Nafasi ya Kumbukumbu ya Lebo Iliyohifadhiwa** + Kumbukumbu ya LRU na TTL fupi kwa lebo pekee (dakika 5) ili kusawazisha utendaji na uthabiti + Fuatilia metriki na uwiano wa hit + **Hakuna ukaushaji wa uingizaji**: Tayari umehifadhiwa kwa kila swali, hakuna faida ya kati ya maswali + **Hakuna ukaushaji wa matokeo ya swali**: Kutokana na wasiwasi wa uthabiti wa mabadiliko ya vielelezo +======= +#### 3. **Mfumo wa Suluhisho la Lebo Sambamba** + Kikundi maswali ya lebo kwa vitu vingi kwa wakati mmoja + Tekeleza mifumo ya async/await kwa ufikiaji sambamba wa hifadhidata + Ongeza utabiri wa kupata kwa mifumo ya kawaida ya lebo + Jumuisha mikakati ya kupasha joto ya kumbukumbu ya lebo + + Moduli: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **Nafasi Hifadhi ya Lebo** + Kumbukumbu ya LRU na TTL fupi kwa lebo pekee (dakika 5) ili kusawazisha utendaji dhidi ya uthabiti + Fuatilia metriki na uwiano wa hit + **Hakuna kumbukumbu ya uingizaji**: Tayari imehifadhiwa kwa kila swali, hakuna faida ya kati ya maswali + **Hakuna kumbukumbu ya matokeo ya swali**: Kutokana na wasiwasi wa uthabiti wa mabadiliko ya vielelezo +>>>>>>> 82edf2d (New md files from RunPod) + + Moduli: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **Mfumo wa Uboreshaji wa Swali** + Uchambuzi na mapendekezo ya uboreshaji wa mfumo wa swali + Mratibu wa swali la kikundi kwa ufikiaji wa hifadhidata + Uunganisho wa mabwawa na usimamaji wa muda wa swali + Ufuatiliaji wa utendaji na ukusanyaji wa metriki + + Moduli: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### Mifano ya Data + +#### Hali Iliyoboreshwa ya Ufuatiliaji wa Vielelezo + +<<<<<<< HEAD +Injini ya ufuatiliaji inahifadhi hali ili kuepuka shughuli za ziada: +======= +Injini ya ufuatiliaji inadumisha hali ili kuepuka shughuli za ziada: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +Mbinu hii inaruhusu: +<<<<<<< HEAD +Uchunguzi wa haraka wa mzunguko kupitia kufuatilia vitu vilivyotembelewa +Maandalizi ya maswali kwa wingi katika kila ngazi ya utafutaji +Usimamizi wa hali unaohifadhi kumbukumbu +Kukomesha mapema wakati mipaka ya ukubwa inafikiwa +======= +Uchunguzi wa haraka wa mzunguko kupitia kufuatilia vitu vilivyotembelewa. +Maandalizi ya maswali kwa wingi katika kila ngazi ya utafutaji. +Usimamizi wa hali unaohifadhi kumbukumbu. +Kukomesha mapema wakati mipaka ya ukubwa inafikiwa. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Muundo Ulioboreshwa wa Kumbukumbu (Cache) + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +<<<<<<< HEAD +#### Muundo wa Maswali ya Kundi +======= +#### Muundo wa Maswali kwa Wingi +>>>>>>> 82edf2d (New md files from RunPod) + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### API + +#### API mpya: + +**API ya GraphTraversal** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**API ya Utatuzi wa Lebo za Kundi** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**API ya Usimamizi wa Kumbukumbu (Cache)** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### API Zilizobadilishwa: + +**GraphRag.query()** - Imeboreshwa kwa matumizi bora: +Ongeza parameter ya `cache_manager` kwa udhibiti wa kumbukumbu. +Jumuisha thamani ya kurudiwa ya `performance_metrics`. +Ongeza parameter ya `query_timeout` kwa uaminifu. + +<<<<<<< HEAD +**Darasa la `Query`** - Limepangwa upya kwa usindikaji wa jumla: +Badilisha usindikaji wa kila kitu kwa shughuli za jumla. +Ongeza menejeri wa muktadha wa async kwa usafi wa rasilimali. +Jumuisha miongozo ya maendeleo kwa operesheni za muda mrefu. + +### Maelezo ya Utendaji + +#### Awamu ya 0: Urekebishaji Muhimu wa Muundo na Muda wa Maisha +======= +**Kifaa cha `Query`** - Kimepangwa upya kwa usindikaji wa jumla: +Badilisha usindikaji wa kila kitu kwa shughuli za jumla. +Ongeza menejimenti ya muktadha wa async kwa usafi wa rasilimali. +Jumuisha miongozo ya maendeleo kwa shughuli za muda mrefu. + +### Maelezo ya Utendaji + +#### Awamu ya 0: Urekebishaji Muhimu wa Muundo na Muda +>>>>>>> 82edf2d (New md files from RunPod) + +**Utendaji Sasa Usiofaa:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +<<<<<<< HEAD +**Muundo Ulioboreshwa na Umeundwa Kudumu:** +======= +**Muundo Uliounganishwa Vizuri na Umeundwa kwa Muda Mrefu:** +>>>>>>> 82edf2d (New md files from RunPod) +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +Mabadiliko haya ya usanifu yanatoa: +**Punguuzo la 10-20% la maswali ya hifadhidata** kwa grafu zilizo na uhusiano wa kawaida (kulinganisha na 0% kwa sasa) +<<<<<<< HEAD +**Kuondolewa kwa gharama ya ziada ya uundaji wa vitu** kwa kila ombi +**Uunganishaji wa kudumu na matumizi ya upya** kwa wateja +**Uboreshaji wa ombi hadi ombi** ndani ya vipindi vya muda wa kuhifadhi (TTL) + +**Kizuia Muhimu cha Utangamano wa Kumbukumbu:** +Uhifadhi wa muda mrefu unaweza kusababisha data kuwa potofu wakati vitu/lebo zinafutwa au kubadilishwa katika grafu iliyoko. Kumbukumbu ya LRU yenye TTL hutoa usawa kati ya faida za utendaji na usafi wa data, lakini haiwezi kuchunguza mabadiliko ya grafu ya wakati halisi. +======= +**Kuondolewa kwa gharama ya utengenezaji wa kitu** kwa kila ombi +**Uunganishaji wa kudumu na matumizi ya mteja tena** +**Uboreshaji wa ombi hadi ombi** ndani ya vipindi vya muda wa kuhifadhi (TTL) + +**Kizuia Muhimu cha Utangamano wa Kumbukumbu:** +Uhifadhi wa muda mrefu unaweza kusababisha hatari ya data kuwa potofu wakati vitu/lebo zinafutwa au kubadilishwa katika grafu iliyoko. Kumbukumbu ya LRU yenye TTL hutoa usawa kati ya faida za utendaji na uongevu wa data, lakini haiwezi kuchunguza mabadiliko ya grafu ya wakati halisi. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Awamu ya 1: Uboreshaji wa Ufuatiliaji wa Grafu + +**Matatizo ya Utendaji wa Sasa:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**Utekelezaji Ulioboreshwa:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### Awamu ya 2: Utatuzi wa Lebo Sambamba + +<<<<<<< HEAD +**Utendaji wa Sasa wa Mfululizo:** +======= +**Utaratibu wa Sasa wa Utendaji:** +>>>>>>> 82edf2d (New md files from RunPod) +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**Utekelezaji Ufuatao Mfumo Sambamba Uliorekebishwa:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +<<<<<<< HEAD +#### Awamu ya 3: Mkakati wa Kupanua Data (Caching) wa Juu + +**Kupanua Data (Cache) la LRU pamoja na TTL:** +======= +#### Awamu ya 3: Mbinu Iliyoboreshwa ya Kuhifadhi Data + +**Kifaa cha Kuhifadhi Data cha LRU (Least Recently Used) pamoja na TTL (Time To Live):** +>>>>>>> 82edf2d (New md files from RunPod) +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +<<<<<<< HEAD +#### Awamu ya 4: Ubora wa Ufuatiliaji na Ufuatiliaji +======= +#### Awamu ya 4: Ubora wa Ufuatiliaji na Usimamizi +>>>>>>> 82edf2d (New md files from RunPod) + +**Ukusanyaji wa Vipimo vya Utendaji:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**Mipangilio ya Muda wa Muda na Mfumo wa Kuzuia:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +<<<<<<< HEAD +## Mawasilisho ya Ulinganishaji wa Kumbukumbu (Cache) + +**Ulinganishaji wa Uharibifu wa Data:** +**Kumbukumbu ya lebo (TTL ya dakika 5)**: Hatari ya kuonyesha lebo za vitu ambazo zimefutwa/kubadilishwa +**Hakuna uwekaji kumbukumbu wa embeddings**: Haihitajiki - embeddings tayari zimehifadhiwa kwa kila swali +**Hakuna uwekaji kumbukumbu wa matokeo**: Inazuia matokeo ya subgrafu ya zamani kutoka kwa vitu/uhusiano ambao wamefutwa + +**Mikakati ya Kupunguza Madhara:** +**Manufaa ya TTL ya kihafidhia:** Kusawazisha faida za utendaji (10-20%) na usafi wa data +**Viunganishi vya kutengua kumbukumbu:** Uunganishi wa hiari na matukio ya mabadiliko ya grafu +**Dashibodi za ufuatiliaji:** Kufuatilia viwango vya hit ya kumbukumbu dhidi ya matukio ya usafi +**Mawasilisho ya kumbukumbu yanayoweza kusanidi:** Kuruhusu urekebishaji kwa kila usakinishaji kulingana na masafa ya mabadiliko + +**Mawasilisho Yanayopendekezwa ya Kumbukumbu Kulingana na Kasi ya Mabadiliko ya Grafu:** +**Mabadiliko ya juu (>100 mabadiliko/saa)**: TTL=60s, saizi ndogo za kumbukumbu +**Mabadiliko ya wastani (10-100 mabadiliko/saa)**: TTL=300s (ya kawaida) +**Mabadiliko ya chini (<10 mabadiliko/saa)**: TTL=600s, saizi kubwa za kumbukumbu + +## Mawasilisho ya Usalama + +**Kuzuia Uingizwaji wa Swali:** +======= +## Mawasilisho ya Ulinganishaji wa Hifadhi (Cache) + +**Ulinganishaji wa Uharibifu wa Data:** +**Hifadhi ya lebo (TTL ya dakika 5)**: Hatari ya kuonyesha lebo za vitu ambazo zimefutwa/kubadilishwa +**Hakuna uhifadhi wa embeddings**: Haihitajiki - embeddings tayari zimehifadhiwa kwa kila swali +**Hakuna uhifadhi wa matokeo**: Inazuia matokeo ya subgrafu ya zamani kutoka kwa vitu/uhusiano ambao umeondolewa + +**Mikakati ya Kupunguza Madhara:** +**Manufaa ya TTL ya kiuchunguzi:** Kusawazisha faida za utendaji (10-20%) na usafi wa data +**Viunganishi vya kutengua hifadhi:** Unganisho wa hiari na matukio ya mabadiliko ya grafu +**Dashibodi za ufuatiliaji:** Kufuatilia viwango vya hit ya hifadhi dhidi ya matukio ya uharibifu +**Mbinu za hifadhi zinazoweza kusanidi:** Kuruhusu urekebishaji wa kila usakinishaji kulingana na masafa ya mabadiliko + +**Mazingatio Yanayopendekezwa ya Hifadhi Kulingana na Kasi ya Mabadiliko ya Grafu:** +**Mabadiliko ya juu (>100 mabadiliko/saa)**: TTL=60s, saizi ndogo za hifadhi +**Mabadiliko ya wastani (10-100 mabadiliko/saa)**: TTL=300s (ya kawaida) +**Mabadiliko ya chini (<10 mabadiliko/saa)**: TTL=600s, saizi kubwa za hifadhi + +## Masuala ya Usalama + +**Kuzuia Uingizwaji wa Maswali:** +>>>>>>> 82edf2d (New md files from RunPod) +Thibitisha kitambulisho vyote vya vitu na vigezo vya swali +Tumia maswali yaliyoparametishwa kwa mwingiliano wote wa hifadhidata +Tekeleza mipaka ya utata wa swali ili kuzuia mashambulizi ya aina ya kukataa huduma (DoS) + +**Ulinzi wa Rasilimali:** +Enforce mipaka ya juu ya saizi ya subgrafu +<<<<<<< HEAD +Tekeleza muda wa mwisho wa swali ili kuzuia kutokuwa na rasilimali +Ongeza ufuatiliaji na mipaka ya matumizi ya kumbukumbu + +**Kidhibiti cha Ufikiaji:** +Endeleza kutengwa kwa watumiaji na ukusanyaji iliyopo +======= +Tekeleza muda wa mwisho wa swali ili kuzuia uchovu wa rasilimali +Ongeza ufuatiliaji na mipaka ya matumizi ya kumbukumbu + +**Kidhibiti cha Ufikiaji:** +Endeleza kutengwa kwa watumiaji na mkusanyiko iliyopo +>>>>>>> 82edf2d (New md files from RunPod) +Ongeza uandikaji wa ukaguzi kwa operesheni zinazoathiri utendaji +Tekeleza kikomo cha kiwango kwa operesheni ghali + +## Mawasilisho ya Utendaji + +### Maboresho Yanayotarajiwa ya Utendaji + +<<<<<<< HEAD +**Upunguzaji wa Swali:** +Sasa: ~9,000+ maswali kwa ombi la kawaida +Yaliyoboreshwa: ~50-100 maswali yaliyunganishwa (upunguzaji wa 98%) +======= +**Upunguzaji wa Maswali:** +Sasa: ~9,000+ maswali kwa ombi la kawaida +Yaliyoboreshwa: ~50-100 maswali yaliyogawanywa (upunguzaji wa 98%) +>>>>>>> 82edf2d (New md files from RunPod) + +**Maboresho ya Muda wa Jibu:** +Ufuatiliaji wa grafu: 15-20s → 3-5s (haraka 4-5x) +Utatuzi wa lebo: 8-12s → 2-4s (haraka 3x) +Swali kamili: 25-35s → 6-10s (maboresho ya 3-4x) + +**Ufanisi wa Kumbukumbu:** +<<<<<<< HEAD +Saizi zilizokadiriwa za kumbukumbu inazuia uvujaji wa kumbukumbu +======= +Saizi zilizokadiriwa za hifadhi inazuia uvujaji wa kumbukumbu +>>>>>>> 82edf2d (New md files from RunPod) +Miundo ya data inayofaa hupunguza athari ya kumbukumbu kwa ~40% +Urekebishaji wa taka bora kupitia usafi sahihi wa rasilimali + +**Mataifa ya Kweli ya Utendaji:** +<<<<<<< HEAD +**Kumbukumbu ya lebo**: Upunguzaji wa 10-20% wa swali kwa grafu zilizo na uhusiano wa kawaida +**Uboreshaji wa uunganisho**: Upunguzaji wa 50-80% wa swali (uboresho mkuu) +**Uboreshaji wa maisha ya kitu**: Ondoa gharama ya kila ombi +**Maboresho ya jumla**: Maboresho ya 3-4x ya muda wa jibu hasa kutoka kwa uunganisho + +**Maboresho ya Uwezo wa Kupanuka:** +Usaidizi wa grafu za maarifa kubwa 3-5x (vikomo na mahitaji ya ulinganishaji wa utendaji) +======= +**Hifadhi ya lebo**: Upunguzaji wa 10-20% wa maswali kwa grafu zilizo na uhusiano wa kawaida +**Uboreshaji wa uainishaji**: Upunguzaji wa 50-80% wa maswali (uboresho mkuu) +**Uboreshaji wa maisha ya kitu**: Ondoa gharama ya kila ombi +**Maboresho ya jumla**: Maboresho ya 3-4x ya muda wa jibu hasa kutoka kwa uainishaji + +**Maboresho ya Uwezo wa Kupanuka:** +Usaidizi wa grafu za maarifa kubwa 3-5x (mdogo na mahitaji ya ulinganishaji wa data) +>>>>>>> 82edf2d (New md files from RunPod) +Uwezo wa juu 3-5x wa ombi la wakati mmoja +Matumizi bora ya rasilimali kupitia matumizi ya upya ya muunganisho + +### Ufuatiliaji wa Utendaji + +<<<<<<< HEAD +**Hesabu za Muda Halisi:** +Muda wa utekelezaji wa swali kwa aina ya operesheni +Viwango vya hit na ufanisi wa kumbukumbu +Matumizi ya kikundi cha muunganisho wa hifadhidata +======= +**Mataifa ya Muda Halisi:** +Muda wa utekelezaji wa swali kwa aina ya operesheni +Viwango vya hit na ufanisi wa hifadhi +Matumizi ya dimbidi ya muunganisho wa hifadhidata +>>>>>>> 82edf2d (New md files from RunPod) +Matumizi ya kumbukumbu na athari ya urekebishaji wa taka + +**Ufuatiliaji wa Utendaji:** +Mtihirika wa kiotomatiki wa utendaji +<<<<<<< HEAD +Mtihirika wa mzigo ukitumia data halisi +Viwango vya utendaji dhidi ya utekelezaji wa sasa +======= +Mtihirika wa mzigo kwa matumizi halisi ya data +Viwango vya kulinganisho dhidi ya utekelezaji wa sasa +>>>>>>> 82edf2d (New md files from RunPod) + +## Mkakati wa Mtihirika + +### Mtihirika wa Vitengo +Mtihirika wa vipengele vya mtu binafsi kwa ajili ya utekelezaji, kuhifadhi, na utatuzi wa lebo +<<<<<<< HEAD +Mwingiliano wa bandarini ya bandarini kwa ajili ya mtihirika wa utendaji +Mtihirika wa kuondoa data kutoka kwa kumbukumbu na muda wa kumalizika +Usimamizi wa makosa na hali za muda + +### Mtihirika wa Uunganisho +Mtihirika wa mwisho hadi mwisho wa swali la GraphRAG ukiwa na uboreshaji +Mtihirika wa mwingiliano wa bandarini ya bandarini ukitumia data halisi +======= +Mwingiliano wa bandarini ya hila kwa ajili ya mtihirika wa utendaji +Mtihirika wa kuondoa data kutoka kwa kumbukumbu na kumalizika kwa muda +Usimamizi wa makosa na hali za muda + +### Mtihirika wa Uunganisho +Mtihirika wa mwisho hadi mwisho wa swali la GraphRAG na uboreshaji +Mtihirika wa mwingiliano wa bandarini ya data halisi +>>>>>>> 82edf2d (New md files from RunPod) +Usimamizi wa ombi la wakati mmoja na rasilimali +Udagano wa uvujaji wa kumbukumbu na uthibitisho wa kusafisha rasilimali + +### Mtihirika wa Utendaji +Mtihirika dhidi ya utekelezaji wa sasa +<<<<<<< HEAD +Mtihirika wa mzigo ukitumia saizi na utata tofauti wa grafu +Mtihirika wa shinikizo kwa mipaka ya kumbukumbu na uunganisho +Mtihirika wa utendaji kwa uboreshaji + +### Mtihirika wa Ulinganishi +Thibitisha ulinganishi wa API ya GraphRAG iliyopo +Mtihirika ukitumia bandarini ya bandarini tofauti za bandarini ya grafu +======= +Mtihirika wa mzigo kwa saizi na utata tofauti wa grafu +Mtihirika wa shinikizo kwa mipaka ya kumbukumbu na uunganisho +Mtihirika wa marejesho kwa maboresho ya utendaji + +### Mtihirika wa Ulinganishi +Thibitisha ulinganishi wa API ya GraphRAG iliyopo +Mtihirika na bandarini tofauti za hifadhi ya grafu +>>>>>>> 82edf2d (New md files from RunPod) +Thibitisha usahihi wa matokeo ikilinganishwa na utekelezaji wa sasa + +## Mpango wa Utendaji + +### Mbinu ya Utendaji Moja kwa Moja +Kwa kuwa API zinaweza kubadilika, tekeleza uboreshaji moja kwa moja bila utata wa uhamishaji: + +<<<<<<< HEAD +1. **Badilisha `follow_edges` mbinu**: Andika upya ukitumia utekelezaji wa kikundi +2. **Boresha `get_labelgraph`**: Tepeleza utatuzi wa lebo kwa wingi +======= +1. **Badilisha `follow_edges` mbinu**: Andika upya kwa utekelezaji wa kikundi +2. **Boresha `get_labelgraph`**: Tepeleza utatuzi wa lebo kwa njia ya sambamba +>>>>>>> 82edf2d (New md files from RunPod) +3. **Ongeza GraphRag ya muda mrefu**: Badilisha Processor ili kudumisha mfano wa kudumu +4. **Tepeleza uhifadhi wa lebo**: Ongeza kumbukumbu ya LRU na TTL kwa darasa la GraphRag + +### Wigo wa Mabadiliko +**Darasa la swali**: Badilisha mistari ~50 katika `follow_edges`, ongeza mistari ~30 ya utunzaji wa kikundi +**Darasa la GraphRag**: Ongeza safu ya kuhifadhi (~mistari 40) +**Darasa la Processor**: Badilisha ili kutumia mfano wa kudumu wa GraphRag (~mistari 20) +**Jumla**: ~mistari 140 ya mabadiliko, hasa ndani ya madarasa yaliyopo + +## Ratiba + +**Wiki ya 1: Utendaji wa Msingi** +<<<<<<< HEAD +Badilisha `follow_edges` ukitumia utekelezaji wa kikundi +Tepeleza utatuzi wa lebo kwa wingi katika `get_labelgraph` +======= +Badilisha `follow_edges` kwa utekelezaji wa kikundi +Tepeleza utatuzi wa lebo kwa njia ya sambamba katika `get_labelgraph` +>>>>>>> 82edf2d (New md files from RunPod) +Ongeza mfano wa GraphRag wa muda mrefu kwa Processor +Tepeleza safu ya uhifadhi + +**Wiki ya 2: Mtihirika na Uunganisho** +Mtihirika wa vitengo kwa ajili ya utekelezaji mpya wa utekelezaji na uhifadhi +<<<<<<< HEAD +Ufuatiliaji wa utendaji dhidi ya utekelezaji wa sasa +Mtihirika wa uunganisho ukitumia data halisi ya grafu +Mtihirika wa msimamizi na uboreshaji + +**Wiki ya 3: Utekelezaji** +Tepeleza utekelezaji ulioboreshwa +Fuatilia uboreshaji wa utendaji +Punguza muda wa TTL wa kumbukumbu na saizi za kikundi kulingana na matumizi halisi + +## Maswali ya Funguo + +**Uunganisho wa Bandarini**: Je, tunapaswa kutekeleza uunganisho wa bandarini maalum au kutegemea uunganisho wa bandarini wa bandarini ya bandarini iliyopo? +**Ukurasa wa Kumbukumbu**: Je, kumbukumbu za lebo na uwekaji wa kumbukumbu zinapaswa kudumu katika kuanzishwa upya za huduma? +**Ukurasa Uliogawanyika**: Kwa matoleo mengi, je, tunapaswa kutekeleza ukurasa uliogawanyika ukitumia Redis/Memcached? +**Muundo wa Matokeo ya Swali**: Je, tunapaswa kuboresha uwakilishi wa ndani wa triple ili kuboresha ufanisi wa kumbukumbu? +**Uunganisho wa Ufuatiliaji**: Vipimo vipi vinapaswa kuonyeshwa kwa mifumo ya ufuatiliaji iliyopo (Prometheus, n.k.)? +======= +Mtihirika wa utendaji dhidi ya utekelezaji wa sasa +Mtihirika wa uunganisho na data halisi ya grafu +Mtihirika wa msimamizi na uboreshaji + +**Wiki ya 3: Uwekaji** +Weka utekelezaji ulioboreshwa +Fuatilia maboresho ya utendaji +Punguza muda wa uhifadhi na saizi za kikundi kulingana na matumizi halisi + +## Maswali ya Funguo + +**Uunganisho wa Bandarini**: Je, tunapaswa kutekeleza bandarini ya uunganisho maalum au kutegemea bandarini ya mteja wa hifadhi iliyopo? +**Ukurasa wa Uhifadhi**: Je, uhifadhi wa lebo na uwekaji unapaswa kudumu katika kuanzishwa upya huduma? +**Ukurasa Uliogawanyika**: Kwa matoleo mengi, je, tunapaswa kutekeleza ukurasa uliogawanyika na Redis/Memcached? +**Muundo wa Matokeo ya Swali**: Je, tunapaswa kuboresha uwakilishi wa ndani wa utatu kwa ufanisi bora wa kumbukumbu? +**Uunganisho wa Ufuatiliaji**: Ni metri gani ambazo zinapaswa kuonyeshwa kwa mifumo ya ufuatiliaji iliyopo (Prometheus, n.k.)? +>>>>>>> 82edf2d (New md files from RunPod) + +## Marejeleo + +[Utekelezaji Asili wa GraphRAG](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +<<<<<<< HEAD +[Kanuni za Usanifu wa TrustGraph](architecture-principles.md) +======= +[Kanuni za Usawa wa TrustGraph](architecture-principles.md) +>>>>>>> 82edf2d (New md files from RunPod) +[Maelekezo ya Usimamizi wa Mkusanyiko](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.tr.md b/docs/tech-specs/graphrag-performance-optimization.tr.md new file mode 100644 index 00000000..0b0d8afa --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.tr.md @@ -0,0 +1,726 @@ +--- +layout: default +title: "GraphRAG Performans Optimizasyonu Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# GraphRAG Performans Optimizasyonu 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'taki GraphRAG (Graf Çıkarım Destekli Üretim) algoritması için kapsamlı performans iyileştirmelerini açıklamaktadır. Mevcut uygulama, ölçeklenebilirliği ve yanıt sürelerini sınırlayan önemli performans darboğazlarına sahiptir. Bu özellik, dört birincil optimizasyon alanını ele almaktadır: + +1. **Graf Gezinme Optimizasyonu**: Verimsiz yinelemeli veritabanı sorgularını ortadan kaldırın ve toplu grafik keşfi uygulayın. +2. **Etiket Çözümleme Optimizasyonu**: Sıralı etiket alma işlemlerini, paralel/toplu işlemlere dönüştürün. +3. **Önbellekleme Stratejisi İyileştirmesi**: LRU (En Son Kullanılmayan) çıkarma ve ön yükleme ile akıllı bir önbellekleme uygulayın. +4. **Sorgu Optimizasyonu**: İyileştirilmiş yanıt süreleri için sonuç memoizasyonu ve gömme önbelleği ekleyin. + +## Hedefler + +**Veritabanı Sorgusu Hacmini Azaltın**: Toplu işleme ve önbellekleme yoluyla toplam veritabanı sorgularında %50-80'lik bir azalma elde edin. +**Yanıt Sürelerini İyileştirin**: Alt grafik oluşturma için 3-5 kat daha hızlı ve etiket çözümleme için 2-3 kat daha hızlı hedefleyin. +**Ölçeklenebilirliği Artırın**: Daha iyi bellek yönetimi ile daha büyük bilgi grafiklerini destekleyin. +**Doğruluğu Koruyun**: Mevcut GraphRAG işlevselliğini ve sonuç kalitesini koruyun. +**Eşzamanlılığı Etkinleştirin**: Çoklu eşzamanlı istekler için paralel işleme yeteneklerini iyileştirin. +**Bellek Ayak İzini Azaltın**: Verimli veri yapıları ve bellek yönetimi uygulayın. +<<<<<<< HEAD +**Gözlemlenebilirliği Ekleyin**: Performans ölçümleri ve izleme yetenekleri ekleyin. +======= +**Gözlenebilirliği Ekleyin**: Performans ölçümleri ve izleme yetenekleri ekleyin. +>>>>>>> 82edf2d (New md files from RunPod) +**Güvenilirliği Sağlayın**: Uygun hata işleme ve zaman aşımı mekanizmaları ekleyin. + +## Arka Plan + +`trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` içindeki mevcut GraphRAG uygulaması, sistem ölçeklenebilirliğini önemli ölçüde etkileyen çeşitli kritik performans sorunları sergilemektedir: + +### Mevcut Performans Sorunları + +**1. Verimsiz Graf Gezinme (`follow_edges` fonksiyonu, 79-127 satırlar)** +<<<<<<< HEAD +Her varlık için her derinlik seviyesinde 3 ayrı veritabanı sorgusu yapar. +Sorgu kalıbı: Her varlık için konu tabanlı, öznelik tabanlı ve nesne tabanlı sorgular. +Toplu işleme yok: Her sorgu yalnızca bir varlığı işler. +Döngü algılama yok: Aynı düğümlere birden çok kez geri dönülebilir. +Memoizasyon olmadan yinelemeli uygulama, üstel karmaşıklığa yol açar. +Zaman karmaşıklığı: O(varlıklar × max_path_length × triple_limit³) + +**2. Sıralı Etiket Çözümleme (`get_labelgraph` fonksiyonu, 144-171 satırlar)** +Her üç bileşenli (konu, öznelik, nesne) üçlü öğeyi sırasıyla işler. +Her `maybe_label` çağrısı potansiyel olarak bir veritabanı sorgusu tetikler. +Etiket sorgularının paralel yürütülmesi veya toplu işlenmesi yoktur. +subgraph_size × 3 adet ayrı veritabanı çağrısına yol açar. + +**3. Basit Önbellekleme Stratejisi (`maybe_label` fonksiyonu, 62-77 satırlar)** +Boyut sınırları veya TTL (Yaşam Süresi) olmadan basit bir sözlük önbelleği. +Önbellek çıkarma politikası olmaması, sınırsız bellek büyümesine yol açar. +Önbellek hataları, ayrı veritabanı sorgularını tetikler. +Ön yükleme veya akıllı önbellek önleme yoktur. + +**4. Alt Optimum Sorgu Kalıpları** +Benzer istekler arasında varlık vektör benzerliği sorguları önbelleğe alınmaz. +Tekrarlayan sorgu kalıpları için sonuç memoizasyonu yoktur. +Yaygın erişim kalıpları için sorgu optimizasyonu eksiktir. +======= +Her varlık için 3 ayrı veritabanı sorgusu yapar. +Sorgu kalıbı: her varlık için konu tabanlı, öznelik tabanlı ve nesne tabanlı sorgular. +Toplu işleme yok: Her sorgu yalnızca bir varlığı işler. +Döngü algılama yok: Aynı düğümlere birden çok kez geri dönülebilir. +Memoizasyon olmadan yinelemeli uygulama, üstel karmaşıklığa yol açar. +Zaman karmaşıklığı: O(varlıklar × maks_yol_uzunluğu × üçlü_sınırı³) + +**2. Sıralı Etiket Çözümleme (`get_labelgraph` fonksiyonu, 144-171 satırlar)** +Her üç bileşenli (konu, öznelik, nesne) sırayla işler. +Her `maybe_label` çağrısı potansiyel olarak bir veritabanı sorgusu tetikler. +Etiket sorgularının paralel yürütülmesi veya toplu işlenmesi yok. +subgraph_size × 3 adet ayrı veritabanı çağrısına yol açar. + +**3. Basit Önbellekleme Stratejisi (`maybe_label` fonksiyonu, 62-77 satırlar)** +Boyut sınırları veya TTL (Yaşam Süresi Sonu) olmadan basit bir sözlük önbelleği. +Önbellek çıkarma politikası olmaması, sınırsız bellek büyümesine yol açar. +Önbellek hataları, ayrı veritabanı sorgularını tetikler. +Ön yükleme veya akıllı önbellek önleme yok. + +**4. Alt Optimum Sorgu Kalıpları** +Benzer istekler arasında varlık vektör benzerliği sorguları önbelleğe alınmaz. +Tekrarlayan sorgu kalıpları için sonuç memoizasyonu yok. +Yaygın erişim kalıpları için sorgu optimizasyonu eksik. +>>>>>>> 82edf2d (New md files from RunPod) + +**5. Kritik Nesne Ömrü Sorunları (`rag.py:96-102`)** +**GraphRag nesnesi her istek için yeniden oluşturulur**: Her sorgu için yeni bir örnek oluşturulur, böylece tüm önbellek avantajları kaybolur. +**Sorgu nesnesi son derece kısa ömürlüdür**: Tek bir sorgu yürütmesi içinde oluşturulur ve yok edilir (201-207 satırlar). +**Etiket önbelleği her istek için sıfırlanır**: Önbellek önleme ve birikmiş bilgi istekler arasında kaybolur. +**İstemci yeniden oluşturma ek yükü**: Veritabanı istemcileri potansiyel olarak her istek için yeniden oluşturulur. +<<<<<<< HEAD +**İstekler arası optimizasyon yok**: Sorgu kalıplarından veya sonuç paylaşımından yararlanamaz. +======= +**Çapraz istek optimizasyonu yok**: Sorgu kalıplarından veya sonuç paylaşımından yararlanamaz. +>>>>>>> 82edf2d (New md files from RunPod) + +### Performans Etki Analizi + +Tipik bir sorgu için mevcut en kötü senaryo: +**Varlık Alma**: 1 vektör benzerliği sorgusu. +<<<<<<< HEAD +**Graf Gezinme**: varlıklar × max_path_length × 3 × triple_limit sorgusu. +======= +**Graf Gezinme**: varlıklar × maks_yol_uzunluğu × 3 × üçlü_sınırı sorguları. +>>>>>>> 82edf2d (New md files from RunPod) +**Etiket Çözümleme**: subgraph_size × 3 adet ayrı etiket sorgusu. + +Varsayılan parametreler için (50 varlık, yol uzunluğu 2, 30 üçlü sınırı, 150 alt grafik boyutu): +**Minimum sorgular**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9.451 veritabanı sorgusu** +**Yanıt süresi**: Orta büyüklükteki grafikler için 15-30 saniye +**Bellek kullanımı**: Zamanla sınırsız önbellek büyümesi +**Önbellek etkinliği**: %0 - her istekte önbellekler sıfırlanır +<<<<<<< HEAD +**Nesne oluşturma ek yükü**: Her istek için oluşturulan/silinen GraphRag + Sorgu nesneleri +======= +**Nesne oluşturma ek yükü**: Her istek için GraphRag + Sorgu nesneleri oluşturulur/silinir +>>>>>>> 82edf2d (New md files from RunPod) + +Bu özellik, toplu sorguları, akıllı önbelleği ve paralel işleme uygulayarak bu eksiklikleri giderir. Sorgu kalıplarını ve veri erişimini optimize ederek TrustGraph şunları yapabilir: +Milyonlarca varlığa sahip kurumsal ölçekli bilgi grafiklerini destekleyin +Tipik sorgular için saniyeden daha kısa yanıt süreleri sağlayın +Yüzlerce eşzamanlı GraphRAG isteğini işleyin +Grafik boyutu ve karmaşıklığıyla verimli bir şekilde ölçeklendirin + +## Teknik Tasarım + +### Mimari + +GraphRAG performans optimizasyonu, aşağıdaki teknik bileşenleri gerektirir: + +#### 1. **Nesne Ömrü Mimari Yeniden Düzenlemesi** + **GraphRag'i uzun ömürlü hale getirin**: GraphRag örneğini, istekler arasında süreklilik sağlamak için İşlemci seviyesine taşıyın + **Önbellekleri koruyun**: Etiket önbelleğini, gömme önbelleğini ve sorgu sonucu önbelleğini istekler arasında koruyun + **Sorgu nesnesini optimize edin**: Sorguyu, veri kapsayıcısı değil, hafif bir yürütme bağlamı olarak yeniden düzenleyin + **Bağlantı sürekliliği**: Veritabanı istemci bağlantılarını istekler arasında koruyun + + Modül: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (değiştirildi) + +#### 2. **Optimize Edilmiş Grafik Gezinme Motoru** + Özyinelemeli `follow_edges`'ı yinelemeli genişlik öncelikli arama ile değiştirin + Her gezinme seviyesinde toplu varlık işleme uygulayın + Ziyaret edilen düğüm takibi kullanarak döngü algılama ekleyin + Sınırlar aşıldığında erken sonlandırma ekleyin + + Modül: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **Paralel Etiket Çözümleme Sistemi** + Birden çok varlık için etiket sorgularını aynı anda toplu olarak sorgulayın + Eşzamanlı veritabanı erişimi için asenkron/bekle kalıplarını uygulayın + Yaygın etiket kalıpları için akıllı ön yükleme ekleyin + Etiket önbelleği ısıtma stratejileri ekleyin + + Modül: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **Muhafazakar Etiket Önbelleği Katmanı** + Performans ve tutarlılık dengesini sağlamak için yalnızca etiketler için kısa TTL'ye sahip LRU önbelleği (5 dakika) + Önbellek metriklerini ve isabet oranını izleme + **Gömme önbelleği yok**: Zaten her sorgu için önbelleğe alınmıştır, sorgular arası bir fayda yoktur + **Sorgu sonucu önbelleği yok**: Grafik mutasyon tutarlılığı endişeleri nedeniyle + + Modül: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **Sorgu Optimizasyon Çerçevesi** + Sorgu kalıbı analizi ve optimizasyon önerileri + Veritabanı erişimi için toplu sorgu koordinatörü + Bağlantı havuzu ve sorgu zaman aşımı yönetimi + Performans izleme ve ölçüm toplama + + Modül: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### Veri Modelleri + +#### Optimize Edilmiş Grafik Gezinme Durumu + +Gezinme motoru, gereksiz işlemleri önlemek için durumu korur: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +Bu yaklaşım şunları sağlar: +Ziyaret edilen varlıkları takip ederek verimli döngü tespiti +Her gezinme seviyesinde toplu sorgu hazırlama +Bellek verimli durum yönetimi +Boyut limitlerine ulaşıldığında erken sonlandırma + +#### Gelişmiş Önbellek Yapısı + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### Toplu Sorgu Yapıları + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### API'ler + +#### Yeni API'ler: + +**GraphTraversal API'si** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**Toplu Etiket Çözümleme API'si** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**Önbellek Yönetimi API'si** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### Değiştirilmiş API'ler: + +**GraphRag.query()** - Performans optimizasyonlarıyla geliştirildi: +Önbellek kontrolü için `cache_manager` parametresi eklendi. +Performans metriklerini içeren `performance_metrics` dönüş değeri eklendi. +Güvenilirlik için `query_timeout` parametresi eklendi. + +**Query sınıfı** - Toplu işleme için yeniden düzenlendi: +Bireysel varlık işleme yerine toplu işlemler kullanıldı. +Kaynak temizliği için asenkron bağlam yöneticileri eklendi. +Uzun süren işlemler için ilerleme geri çağırmaları eklendi. + +### Uygulama Detayları + +#### Aşama 0: Kritik Mimari Yaşam Döngüsü Yeniden Düzenlemesi + +**Mevcut Sorunlu Uygulama:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +**Optimize Edilmiş, Uzun Ömürlü Mimari:** +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +Bu mimari değişiklik şunları sağlar: +**Ortak ilişkileri olan grafikler için veritabanı sorgu sayısında %10-20'lik bir azalma** (şu anda %0'a kıyasla) +<<<<<<< HEAD +Her istek için **ortadan kaldırılan nesne oluşturma ek yükü** +======= +Her istek için **oluşturulan nesnelerin getirdiği ek yükün ortadan kaldırılması** +>>>>>>> 82edf2d (New md files from RunPod) +**Sürekli bağlantı havuzu** ve istemci yeniden kullanımı +Önbellek TTL (Yaşam Süresi) aralıkları içinde **istemler arası optimizasyon** + +**Önemli Önbellek Tutarlılık Sınırlaması:** +<<<<<<< HEAD +Uzun süreli önbellekleme, temel grafikteki varlıkların/etiketlerin silindiği veya değiştirildiği durumlarda, güncelliği kaybetme riski oluşturur. LRU (En Son Kullanılmayan) önbelleği, performans kazanımları ile veri tazeliği arasında bir denge sağlarken, gerçek zamanlı grafik değişikliklerini tespit edemez. +======= +Uzun süreli önbellekleme, temel grafikteki varlıkların/etiketlerin silindiği veya değiştirildiği durumlarda, verilerin güncelliğini yitirme riski oluşturur. LRU (En Son Kullanılmayan) önbelleği, performans artışları ve veri tazeliği arasında bir denge sağlar, ancak gerçek zamanlı grafik değişikliklerini tespit edemez. +>>>>>>> 82edf2d (New md files from RunPod) + +#### 1. Aşama: Grafik Gezinme Optimizasyonu + +**Mevcut Uygulama Sorunları:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**Optimize Edilmiş Uygulama:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### 2. Aşama: Paralel Etiket Çözümlemesi + +**Mevcut Sıralı Uygulama:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +**Optimize Edilmiş Paralel Uygulama:** +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### 3. Aşama: Gelişmiş Önbellekleme Stratejisi + +**TTL ile LRU Önbelleği:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### 4. Aşama: Sorgu Optimizasyonu ve İzleme + +**Performans Metrikleri Toplama:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**Sorgu Zaman Aşımı ve Devre Kesici:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## Önbellek Tutarlılık Hususları + +**Veri Güncelliği Dengesi:** +**Etiket önbelleği (5 dakika TTL):** Silinmiş/yeniden adlandırılmış varlık etiketlerini sunma riski. +**Gömme önbelleği yok:** Gerekli değil - gömmeler zaten her sorgu için önbelleğe alınmıştır. +**Sonuç önbelleği yok:** Silinmiş varlıklar/ilişkilerden kaynaklanan eski alt grafik sonuçlarını önler. + +**Azaltma Stratejileri:** +**Muhafazakar TTL değerleri:** Performans kazanımları (10-20%) ile veri güncelliği arasındaki denge. +<<<<<<< HEAD +**Önbellek geçersiz kılma kancaları:** İsteğe bağlı olarak grafik mutasyon olaylarıyla entegrasyon. +======= +**Önbellek geçersiz kılma mekanizmaları:** Grafik mutasyon olaylarıyla isteğe bağlı entegrasyon. +>>>>>>> 82edf2d (New md files from RunPod) +**İzleme panoları:** Önbellek isabet oranlarını, veri güncelliği sorunlarıyla karşılaştırarak izleyin. +**Yapılandırılabilir önbellek politikaları:** Mutasyon sıklığına göre dağıtıma özel ayarlamalar yapılmasına izin verir. + +**Grafik Mutasyon Oranına Göre Önerilen Önbellek Yapılandırması:** +**Yüksek mutasyon (>100 değişiklik/saat):** TTL=60s, daha küçük önbellek boyutları. +**Orta mutasyon (10-100 değişiklik/saat):** TTL=300s (varsayılan). +**Düşük mutasyon (<10 değişiklik/saat):** TTL=600s, daha büyük önbellek boyutları. + +## Güvenlik Hususları + +<<<<<<< HEAD +**Sorgu Enjeksiyonunu Önleme:** +======= +**Sorgu Enjeksiyonu Önleme:** +>>>>>>> 82edf2d (New md files from RunPod) +Tüm varlık tanımlayıcılarını ve sorgu parametrelerini doğrulayın. +Tüm veritabanı etkileşimleri için parametreli sorgular kullanın. +DoS saldırılarını önlemek için sorgu karmaşıklığı limitleri uygulayın. + +**Kaynak Koruması:** +<<<<<<< HEAD +Maksimum alt grafik boyutları limitlerini uygulayın. +Kaynak tükenmesini önlemek için sorgu zaman aşımlarını uygulayın. +======= +Maksimum alt grafik boyutları için limitler uygulayın. +Kaynak tükenmesini önlemek için sorgu zaman aşımları uygulayın. +>>>>>>> 82edf2d (New md files from RunPod) +Bellek kullanımı izleme ve limitleri ekleyin. + +**Erişim Kontrolü:** +Mevcut kullanıcı ve koleksiyon izolasyonunu koruyun. +Performansı etkileyen işlemler için denetim kaydı ekleyin. +Pahalı işlemler için hız sınırlaması uygulayın. + +## Performans Hususları + +### Beklenen Performans İyileştirmeleri + +**Sorgu Azaltma:** +<<<<<<< HEAD +Mevcut: Tipik bir istek için ~9.000+ sorgu. +======= +Mevcut: Tipik bir istek için ~9.000'den fazla sorgu. +>>>>>>> 82edf2d (New md files from RunPod) +Optimize edilmiş: ~50-100 toplu sorgu (98% azalma). + +**Yanıt Süresi İyileştirmeleri:** +Grafik geçişi: 15-20s → 3-5s (4-5 kat daha hızlı). +Etiket çözümü: 8-12s → 2-4s (3 kat daha hızlı). +Genel sorgu: 25-35s → 6-10s (3-4 kat iyileşme). + +**Bellek Verimliliği:** +Sınırlı önbellek boyutları, bellek sızıntılarını önler. +Verimli veri yapıları, bellek ayak izini yaklaşık %40 azaltır. +Uygun kaynak temizliği sayesinde daha iyi çöp toplama. + +**Gerçekçi Performans Beklentileri:** +**Etiket önbelleği:** Ortak ilişkilere sahip grafikler için sorgu azaltmada %10-20. +**Toplu optimizasyon:** %50-80 sorgu azaltma (birincil optimizasyon). +**Nesne ömrü optimizasyonu:** Her istekte oluşturma ek yükünü ortadan kaldırır. +**Genel iyileşme:** Toplu işlemden kaynaklanan 3-4 kat yanıt süresi iyileşmesi. + +**Ölçeklenebilirlik İyileştirmeleri:** +<<<<<<< HEAD +3-5 kat daha büyük bilgi grafiklerini destekler (önbellek tutarlılık ihtiyaçları ile sınırlıdır). +======= +3-5 kat daha büyük bilgi grafiklerini destekler (önbellek tutarlılık gereksinimleriyle sınırlıdır). +>>>>>>> 82edf2d (New md files from RunPod) +3-5 kat daha yüksek eşzamanlı istek kapasitesi. +Bağlantı yeniden kullanımı sayesinde daha iyi kaynak kullanımı. + +### Performans İzleme + +**Gerçek Zamanlı Metrikler:** +İşlem türüne göre sorgu yürütme süreleri. +Önbellek isabet oranları ve etkinliği. +Veritabanı bağlantı havuzu kullanımı. +Bellek kullanımı ve çöp toplama etkisi. + +**Performans Karşılaştırması:** +Otomatik performans gerileme testi +Gerçekçi veri hacimleriyle yük testi +Mevcut uygulamaya karşı karşılaştırma testleri + +## Test Stratejisi + +### Birim Testi +Gezinme, önbellekleme ve etiket çözümleme için bireysel bileşen testi +Performans testi için sahte veritabanı etkileşimleri +Önbellek temizleme ve TTL (Yaşam Süresi) sonlandırma testi +Hata işleme ve zaman aşımı senaryoları + +### Entegrasyon Testi +Optimizasyonlarla uçtan uca GraphRAG sorgu testi +<<<<<<< HEAD +Gerçek verilerle veritabanı etkileşim testi +======= +Gerçek verilerle veritabanı etkileşimi testi +>>>>>>> 82edf2d (New md files from RunPod) +Eşzamanlı istek işleme ve kaynak yönetimi +Bellek sızıntısı tespiti ve kaynak temizleme doğrulaması + +### Performans Testi +Mevcut uygulamaya karşı karşılaştırma testi +Farklı grafik boyutları ve karmaşıklıklarla yük testi +Bellek ve bağlantı limitleri için stres testi +Performans iyileştirmeleri için regresyon testi + +### Uyumluluk Testi +Mevcut GraphRAG API uyumluluğunu doğrulayın +Çeşitli grafik veritabanı arka uçlarıyla test yapın +Mevcut uygulamaya kıyasla sonuç doğruluğunu doğrulayın + +## Uygulama Planı + +### Doğrudan Uygulama Yaklaşımı +API'lerin değişmesine izin verildiğinden, geçiş karmaşıklığı olmadan doğrudan optimizasyonları uygulayın: + +1. **`follow_edges` yöntemini değiştirin**: Yinelemeli toplu işleme ile yeniden yazın +<<<<<<< HEAD +2. **`get_labelgraph`'ı optimize edin**: Paralel etiket çözümlemeyi uygulayın +3. **Uzun ömürlü GraphRag ekleyin**: Kalıcı bir örnek tutmak için İşlemci'yi değiştirin +4. **Etiket önbelleğini uygulayın**: GraphRag sınıfına TTL ile LRU (En Son Kullanılan) önbelleği ekleyin +======= +2. **`get_labelgraph`'ı optimize edin**: Paralel etiket çözümlemesini uygulayın +3. **Uzun ömürlü GraphRag ekleyin**: Kalıcı bir örnek tutmak için İşlemci'yi değiştirin +4. **Etiket önbelleklemesini uygulayın**: GraphRag sınıfına TTL ile LRU (En Son Kullanılan) önbelleği ekleyin +>>>>>>> 82edf2d (New md files from RunPod) + +### Değişiklik Kapsamı +**Sorgu sınıfı**: `follow_edges` içinde ~50 satırı değiştirin, toplu işleme için ~30 satır ekleyin +**GraphRag sınıfı**: Önbellekleme katmanı ekleyin (~40 satır) +**İşlemci sınıfı**: Kalıcı bir GraphRag örneği kullanmak için değiştirin (~20 satır) +**Toplam**: Odaklanmış değişikliklerin ~140 satırı, çoğunlukla mevcut sınıfların içinde + +## Zaman Çizelgesi + +**1. Hafta: Temel Uygulama** +`follow_edges`'ı toplu yinelemeli gezinmeyle değiştirin +<<<<<<< HEAD +`get_labelgraph` içinde paralel etiket çözümlemeyi uygulayın +======= +`get_labelgraph` içinde paralel etiket çözümlemesini uygulayın +>>>>>>> 82edf2d (New md files from RunPod) +İşlemci'ye uzun ömürlü GraphRag örneği ekleyin +Etiket önbellekleme katmanı uygulayın + +**2. Hafta: Test ve Entegrasyon** +Yeni gezinme ve önbellekleme mantığı için birim testleri +Mevcut uygulamaya karşı performans karşılaştırması +Gerçek grafik verileriyle entegrasyon testi +Kod incelemesi ve optimizasyon + +**3. Hafta: Dağıtım** +Optimize edilmiş uygulamayı dağıtın +Performans iyileştirmelerini izleyin +<<<<<<< HEAD +Gerçek kullanım temelinde önbellek TTL'sini ve toplu boyutları ayarlayın +======= +Gerçek kullanım bazında önbellek TTL'sini ve toplu boyutları ayarlayın +>>>>>>> 82edf2d (New md files from RunPod) + +## Açık Sorular + +**Veritabanı Bağlantı Havuzu**: Özel bir bağlantı havuzu mu uygulamalıyız yoksa mevcut veritabanı istemci havuzuna mı güvenmeliyiz? +**Önbellek Kalıcılığı**: Etiket ve gömme önbellekleri hizmet yeniden başlatmalarında kalıcı mı olmalı? +**Dağıtılmış Önbellekleme**: Çok örnekli dağıtımlar için Redis/Memcached ile dağıtılmış önbellekleme mi uygulamalıyız? +**Sorgu Sonucu Formatı**: Daha iyi bellek verimliliği için dahili üçlü gösterimi optimize etmeli miyiz? +**İzleme Entegrasyonu**: Hangi ölçümler mevcut izleme sistemlerine (Prometheus, vb.) maruz bırakılmalıdır? + +## Referanslar + +[GraphRAG Orijinal Uygulaması](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +[TrustGraph Mimari Prensipleri](architecture-principles.md) +[Koleksiyon Yönetimi Özellikleri](collection-management.md) diff --git a/docs/tech-specs/graphrag-performance-optimization.zh-cn.md b/docs/tech-specs/graphrag-performance-optimization.zh-cn.md new file mode 100644 index 00000000..15fcdc4b --- /dev/null +++ b/docs/tech-specs/graphrag-performance-optimization.zh-cn.md @@ -0,0 +1,774 @@ +--- +layout: default +title: "GraphRAG 性能优化技术规范" +parent: "Chinese (Beta)" +--- + +# GraphRAG 性能优化技术规范 + +> **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 中 GraphRAG (基于图的检索增强生成) 算法的全面性能优化。当前的实现存在严重的性能瓶颈,限制了可扩展性和响应时间。本规范解决了四个主要的优化领域: + +1. **图遍历优化**: 消除低效的递归数据库查询,并实现批量图探索 +2. **标签解析优化**: 使用并行/批量操作替换顺序标签获取 +3. **缓存策略增强**: 实现智能缓存,采用 LRU 淘汰策略和预取 +4. **查询优化**: 添加结果记忆化和嵌入式缓存,以提高响应时间 + +## 目标 + +**减少数据库查询量**: 通过批量和缓存,实现总数据库查询量减少 50-80% +**提高响应时间**: 目标是子图构建速度提高 3-5 倍,标签解析速度提高 2-3 倍 +<<<<<<< HEAD +**增强可扩展性**: 更好地管理内存,支持更大的知识图谱 +======= +**增强可扩展性**: 通过更好的内存管理,支持更大的知识图谱 +>>>>>>> 82edf2d (New md files from RunPod) +**保持准确性**: 保持现有的 GraphRAG 功能和结果质量 +**启用并发性**: 提高并行处理能力,以支持多个并发请求 +**减少内存占用**: 实现高效的数据结构和内存管理 +**增加可观察性**: 包含性能指标和监控功能 +**确保可靠性**: 添加适当的错误处理和超时机制 + +## 背景 + +在 `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` 中的当前 GraphRAG 实现存在几个关键的性能问题,严重影响系统的可扩展性: + +### 当前性能问题 + +**1. 低效的图遍历 (`follow_edges` 函数,第 79-127 行)** +对每个实体,每个深度级别执行 3 次独立的数据库查询 +查询模式:针对主体、谓词和对象进行查询 +没有批量处理:每次查询仅处理一个实体 +没有循环检测:可以多次访问相同的节点 +没有记忆化的递归实现会导致指数级复杂度 +时间复杂度:O(entities × max_path_length × triple_limit³) + +**2. 顺序的标签解析 (`get_labelgraph` 函数,第 144-171 行)** +顺序处理每个三元组组件 (主体、谓词、对象) +每次 `maybe_label` 调用可能触发数据库查询 +没有并行执行或批量标签查询 +导致最多 subgraph_size × 3 次独立的数据库调用 + +**3. 原始的缓存策略 (`maybe_label` 函数,第 62-77 行)** +简单的字典缓存,没有大小限制或 TTL +没有缓存淘汰策略会导致内存无限增长 +缓存未命中会触发独立的数据库查询 +没有预取或智能缓存预热 + +**4. 不佳的查询模式** +实体向量相似性查询在相似请求之间没有缓存 +没有对重复查询模式进行结果记忆化 +缺少针对常见访问模式的查询优化 + +**5. 关键的对象生命周期问题 (`rag.py:96-102`)** +**GraphRag 对象每个请求重新创建**: 为每个查询创建一个新的实例,失去所有缓存的好处 +**查询对象寿命极短**: 在单个查询执行中创建和销毁 (第 201-207 行) +**标签缓存每个请求重置**: 缓存预热和积累的知识在请求之间丢失 +**客户端重新创建开销**: 数据库客户端可能为每个请求重新建立 +**没有跨请求优化**: 无法从查询模式或结果共享中受益 + +### 性能影响分析 + +当前典型查询的最坏情况: +**实体检索**: 1 次向量相似性查询 +**图遍历**: entities × max_path_length × 3 × triple_limit 次查询 +**标签解析**: subgraph_size × 3 次独立的标签查询 + +对于默认参数(50个实体,路径长度2,30个三元组限制,150个子图大小): +**最小查询次数**: 1 + (50 × 2 × 3 × 30) + (150 × 3) = **9,451次数据库查询** +**响应时间**: 中等大小图的响应时间为15-30秒 +**内存使用**: 缓存会随着时间增长 +**缓存有效性**: 0% - 每次请求都会重置缓存 +<<<<<<< HEAD +**对象创建开销**: 每个请求都会创建/销毁GraphRag + Query对象 + +本规范通过实现批量查询、智能缓存和并行处理来解决这些问题。通过优化查询模式和数据访问,TrustGraph可以: +支持拥有数百万个实体的企业级知识图谱 +为典型的查询提供亚秒级的响应时间 +======= +**对象创建开销**: 每个请求会创建/销毁GraphRag + Query对象 + +本规范通过实现批量查询、智能缓存和并行处理来解决这些问题。通过优化查询模式和数据访问,TrustGraph可以: +支持拥有数百万个实体的企业级知识图谱 +为典型查询提供亚秒级的响应时间 +>>>>>>> 82edf2d (New md files from RunPod) +处理数百个并发的GraphRAG请求 +随着图的大小和复杂性而高效扩展 + +## 技术设计 + +### 架构 + +GraphRAG性能优化需要以下技术组件: + +#### 1. **对象生命周期架构重构** + **使GraphRag具有长期生命周期**: 将GraphRag实例移动到处理器级别,以便在请求之间保持持久性 + **保留缓存**: 在请求之间维护标签缓存、嵌入缓存和查询结果缓存 + **优化Query对象**: 将Query重构为轻量级的执行上下文,而不是数据容器 + **连接持久化**: 在请求之间保持数据库客户端连接 + + 模块: `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (已修改) + +#### 2. **优化的图遍历引擎** + 使用迭代广度优先搜索替换递归的`follow_edges` + 在每个遍历级别实现批量实体处理 + 添加循环检测,使用已访问节点跟踪 + 在达到限制时包含早期终止 + + 模块: `trustgraph-flow/trustgraph/retrieval/graph_rag/optimized_traversal.py` + +#### 3. **并行标签解析系统** + 批量查询多个实体的标签 + 使用async/await模式进行并发数据库访问 + 添加智能预取,用于常见的标签模式 + 包含标签缓存预热策略 + + 模块: `trustgraph-flow/trustgraph/retrieval/graph_rag/label_resolver.py` + +#### 4. **保守的标签缓存层** + 使用LRU缓存,仅对标签使用,TTL为5分钟,以平衡性能与一致性 + 监控缓存指标和命中率 + **不缓存嵌入**: 已经针对每个查询进行缓存,没有跨查询的好处 + **不缓存查询结果**: 由于图的突变一致性问题 + + 模块: `trustgraph-flow/trustgraph/retrieval/graph_rag/cache_manager.py` + +#### 5. **查询优化框架** + 查询模式分析和优化建议 + 批量查询协调器,用于数据库访问 + 连接池和查询超时管理 + 性能监控和指标收集 + + 模块: `trustgraph-flow/trustgraph/retrieval/graph_rag/query_optimizer.py` + +### 数据模型 + +#### 优化的图遍历状态 + +遍历引擎维护状态以避免重复操作: + +```python +@dataclass +class TraversalState: + visited_entities: Set[str] + current_level_entities: Set[str] + next_level_entities: Set[str] + subgraph: Set[Tuple[str, str, str]] + depth: int + query_batch: List[TripleQuery] +``` + +这种方法允许: +<<<<<<< HEAD +通过跟踪访问的实体实现高效的循环检测 +======= +通过跟踪访问过的实体实现高效的循环检测 +>>>>>>> 82edf2d (New md files from RunPod) +在每个遍历层级进行批量查询准备 +内存效率高的状态管理 +当达到大小限制时,可以提前终止 + +#### 增强的缓存结构 + +```python +@dataclass +class CacheEntry: + value: Any + timestamp: float + access_count: int + ttl: Optional[float] + +class CacheManager: + label_cache: LRUCache[str, CacheEntry] + embedding_cache: LRUCache[str, CacheEntry] + query_result_cache: LRUCache[str, CacheEntry] + cache_stats: CacheStatistics +``` + +#### 批量查询结构 + +```python +@dataclass +class BatchTripleQuery: + entities: List[str] + query_type: QueryType # SUBJECT, PREDICATE, OBJECT + limit_per_entity: int + +@dataclass +class BatchLabelQuery: + entities: List[str] + predicate: str = LABEL +``` + +### API 接口 + +#### 新增 API 接口: + +**图遍历 API** +```python +async def optimized_follow_edges_batch( + entities: List[str], + max_depth: int, + triple_limit: int, + max_subgraph_size: int +) -> Set[Tuple[str, str, str]] +``` + +**批量标签解析 API** +```python +async def resolve_labels_batch( + entities: List[str], + cache_manager: CacheManager +) -> Dict[str, str] +``` + +**缓存管理 API** +```python +class CacheManager: + async def get_or_fetch_label(self, entity: str) -> str + async def get_or_fetch_embeddings(self, query: str) -> List[float] + async def cache_query_result(self, query_hash: str, result: Any, ttl: int) + def get_cache_statistics(self) -> CacheStatistics +``` + +#### 修改后的 API: + +**GraphRag.query()** - 增强了性能优化: +<<<<<<< HEAD +添加了 cache_manager 参数以进行缓存控制 +包含 performance_metrics 返回值 +添加了 query_timeout 参数以提高可靠性 + +**Query 类** - 进行了重构,用于批量处理: +将单个实体处理替换为批量操作 +添加了异步上下文管理器以进行资源清理 +======= +添加 `cache_manager` 参数以进行缓存控制 +包含 `performance_metrics` 返回值 +添加 `query_timeout` 参数以提高可靠性 + +**Query 类** - 重新设计,用于批量处理: +将单个实体处理替换为批量操作 +添加异步上下文管理器以进行资源清理 +>>>>>>> 82edf2d (New md files from RunPod) +包含进度回调函数,用于长时间运行的操作 + +### 实施细节 + +#### 阶段 0:关键架构生命周期重构 + +**当前存在问题的实现:** +```python +# INEFFICIENT: GraphRag recreated every request +class Processor(FlowProcessor): + async def on_request(self, msg, consumer, flow): + # PROBLEM: New GraphRag instance per request! + self.rag = GraphRag( + embeddings_client = flow("embeddings-request"), + graph_embeddings_client = flow("graph-embeddings-request"), + triples_client = flow("triples-request"), + prompt_client = flow("prompt-request"), + verbose=True, + ) + # Cache starts empty every time - no benefit from previous requests + response = await self.rag.query(...) + +# VERY SHORT-LIVED: Query object created/destroyed per request +class GraphRag: + async def query(self, query, user="trustgraph", collection="default", ...): + q = Query(rag=self, user=user, collection=collection, ...) # Created + kg = await q.get_labelgraph(query) # Used briefly + # q automatically destroyed when function exits +``` + +<<<<<<< HEAD +**优化后的长期运行架构:** +======= +**优化后的长寿命架构:** +>>>>>>> 82edf2d (New md files from RunPod) +```python +class Processor(FlowProcessor): + def __init__(self, **params): + super().__init__(**params) + self.rag_instance = None # Will be initialized once + self.client_connections = {} + + async def initialize_rag(self, flow): + """Initialize GraphRag once, reuse for all requests""" + if self.rag_instance is None: + self.rag_instance = LongLivedGraphRag( + embeddings_client=flow("embeddings-request"), + graph_embeddings_client=flow("graph-embeddings-request"), + triples_client=flow("triples-request"), + prompt_client=flow("prompt-request"), + verbose=True, + ) + return self.rag_instance + + async def on_request(self, msg, consumer, flow): + # REUSE the same GraphRag instance - caches persist! + rag = await self.initialize_rag(flow) + + # Query object becomes lightweight execution context + response = await rag.query_with_context( + query=v.query, + execution_context=QueryContext( + user=v.user, + collection=v.collection, + entity_limit=entity_limit, + # ... other params + ) + ) + +class LongLivedGraphRag: + def __init__(self, ...): + # CONSERVATIVE caches - balance performance vs consistency + self.label_cache = LRUCacheWithTTL(max_size=5000, ttl=300) # 5min TTL for freshness + # Note: No embedding cache - already cached per-query, no cross-query benefit + # Note: No query result cache due to consistency concerns + self.performance_metrics = PerformanceTracker() + + async def query_with_context(self, query: str, context: QueryContext): + # Use lightweight QueryExecutor instead of heavyweight Query object + executor = QueryExecutor(self, context) # Minimal object + return await executor.execute(query) + +@dataclass +class QueryContext: + """Lightweight execution context - no heavy operations""" + user: str + collection: str + entity_limit: int + triple_limit: int + max_subgraph_size: int + max_path_length: int + +class QueryExecutor: + """Lightweight execution context - replaces old Query class""" + def __init__(self, rag: LongLivedGraphRag, context: QueryContext): + self.rag = rag + self.context = context + # No heavy initialization - just references + + async def execute(self, query: str): + # All heavy lifting uses persistent rag caches + return await self.rag.execute_optimized_query(query, self.context) +``` + +<<<<<<< HEAD +这种架构上的改变提供了: +**对于具有常见关系的图,数据库查询减少 10-20%**(相对于目前 0% 的减少) +**消除了每个请求中的对象创建开销** +======= +这一架构变更提供了: +**对于具有常见关系的图,数据库查询减少 10-20%**(相对于目前 0% 的减少) +**消除了每个请求的对象的创建开销** +>>>>>>> 82edf2d (New md files from RunPod) +**持久连接池和客户端重用** +**缓存 TTL 窗口内的跨请求优化** + +**重要的缓存一致性限制:** +长期缓存会带来数据陈旧的风险,尤其是在底层图中删除或修改实体/标签时。 LRU 缓存和 TTL 在性能提升和数据新鲜度之间提供了一种平衡,但无法检测到实时图的变化。 + +#### 第一阶段:图遍历优化 + +**当前实现的缺点:** +```python +# INEFFICIENT: 3 queries per entity per level +async def follow_edges(self, ent, subgraph, path_length): + # Query 1: s=ent, p=None, o=None + res = await self.rag.triples_client.query(s=ent, p=None, o=None, limit=self.triple_limit) + # Query 2: s=None, p=ent, o=None + res = await self.rag.triples_client.query(s=None, p=ent, o=None, limit=self.triple_limit) + # Query 3: s=None, p=None, o=ent + res = await self.rag.triples_client.query(s=None, p=None, o=ent, limit=self.triple_limit) +``` + +**优化实现:** +```python +async def optimized_traversal(self, entities: List[str], max_depth: int) -> Set[Triple]: + visited = set() + current_level = set(entities) + subgraph = set() + + for depth in range(max_depth): + if not current_level or len(subgraph) >= self.max_subgraph_size: + break + + # Batch all queries for current level + batch_queries = [] + for entity in current_level: + if entity not in visited: + batch_queries.extend([ + TripleQuery(s=entity, p=None, o=None), + TripleQuery(s=None, p=entity, o=None), + TripleQuery(s=None, p=None, o=entity) + ]) + + # Execute all queries concurrently + results = await self.execute_batch_queries(batch_queries) + + # Process results and prepare next level + next_level = set() + for result in results: + subgraph.update(result.triples) + next_level.update(result.new_entities) + + visited.update(current_level) + current_level = next_level - visited + + return subgraph +``` + +#### 第二阶段:并行标签解析 + +**当前的顺序实现方式:** +```python +# INEFFICIENT: Sequential processing +for edge in subgraph: + s = await self.maybe_label(edge[0]) # Individual query + p = await self.maybe_label(edge[1]) # Individual query + o = await self.maybe_label(edge[2]) # Individual query +``` + +<<<<<<< HEAD +**优化后的并行实现:** +======= +**优化并行实现:** +>>>>>>> 82edf2d (New md files from RunPod) +```python +async def resolve_labels_parallel(self, subgraph: List[Triple]) -> List[Triple]: + # Collect all unique entities needing labels + entities_to_resolve = set() + for s, p, o in subgraph: + entities_to_resolve.update([s, p, o]) + + # Remove already cached entities + uncached_entities = [e for e in entities_to_resolve if e not in self.label_cache] + + # Batch query for all uncached labels + if uncached_entities: + label_results = await self.batch_label_query(uncached_entities) + self.label_cache.update(label_results) + + # Apply labels to subgraph + return [ + (self.label_cache.get(s, s), self.label_cache.get(p, p), self.label_cache.get(o, o)) + for s, p, o in subgraph + ] +``` + +#### 第三阶段:高级缓存策略 + +**LRU 缓存与 TTL:** +```python +class LRUCacheWithTTL: + def __init__(self, max_size: int, default_ttl: int = 3600): + self.cache = OrderedDict() + self.max_size = max_size + self.default_ttl = default_ttl + self.access_times = {} + + async def get(self, key: str) -> Optional[Any]: + if key in self.cache: + # Check TTL expiration + if time.time() - self.access_times[key] > self.default_ttl: + del self.cache[key] + del self.access_times[key] + return None + + # Move to end (most recently used) + self.cache.move_to_end(key) + return self.cache[key] + return None + + async def put(self, key: str, value: Any): + if key in self.cache: + self.cache.move_to_end(key) + else: + if len(self.cache) >= self.max_size: + # Remove least recently used + oldest_key = next(iter(self.cache)) + del self.cache[oldest_key] + del self.access_times[oldest_key] + + self.cache[key] = value + self.access_times[key] = time.time() +``` + +#### 第四阶段:查询优化和监控 + +**性能指标收集:** +```python +@dataclass +class PerformanceMetrics: + total_queries: int + cache_hits: int + cache_misses: int + avg_response_time: float + subgraph_construction_time: float + label_resolution_time: float + total_entities_processed: int + memory_usage_mb: float +``` + +**查询超时和断路器:** +```python +async def execute_with_timeout(self, query_func, timeout: int = 30): + try: + return await asyncio.wait_for(query_func(), timeout=timeout) + except asyncio.TimeoutError: + logger.error(f"Query timeout after {timeout}s") + raise GraphRagTimeoutError(f"Query exceeded timeout of {timeout}s") +``` + +## 缓存一致性考虑 + +**数据时效性权衡:** +**标签缓存 (5 分钟 TTL)**:存在提供已删除/重命名的实体标签的风险。 +**不缓存嵌入 (embeddings)**:不需要 - 嵌入已按查询缓存。 +**不缓存结果**:防止从已删除的实体/关系中获取过时的子图结果。 + +**缓解策略:** +**保守的 TTL 值**:在性能提升 (10-20%) 和数据新鲜度之间取得平衡。 +**缓存失效钩子**:可选地与图的修改事件集成。 +<<<<<<< HEAD +**监控仪表板**:跟踪缓存命中率与数据时效性事件。 +**可配置的缓存策略**:允许根据修改频率进行按部署的调整。 + +**根据图修改速率推荐的缓存配置:** +======= +**监控仪表板**:跟踪缓存命中率与数据陈旧事件。 +**可配置的缓存策略**:允许根据修改频率进行按部署的调整。 + +**基于图修改速率的推荐缓存配置:** +>>>>>>> 82edf2d (New md files from RunPod) +**高修改速率 (>100 次/小时)**:TTL=60 秒,较小的缓存大小。 +**中等修改速率 (10-100 次/小时)**:TTL=300 秒 (默认值)。 +**低修改速率 (<10 次/小时)**:TTL=600 秒,较大的缓存大小。 + +## 安全性考虑 + +**查询注入防护:** +验证所有实体标识符和查询参数。 +对所有数据库交互使用参数化查询。 +实施查询复杂度限制以防止拒绝服务 (DoS) 攻击。 + +**资源保护:** +强制执行最大子图大小限制。 +实施查询超时以防止资源耗尽。 +添加内存使用情况监控和限制。 + +**访问控制:** +维护现有的用户和集合隔离。 +添加对影响性能的操作的审计日志。 +实施速率限制以防止对昂贵操作的滥用。 + +## 性能考虑 + +### 预期的性能提升 + +**查询减少:** +<<<<<<< HEAD +当前:典型请求需要 ~9,000+ 次查询。 +优化后:~50-100 个批处理查询 (减少 98%)。 +======= +当前:典型请求约 9,000+ 个查询。 +优化后:约 50-100 个批处理查询 (减少 98%)。 +>>>>>>> 82edf2d (New md files from RunPod) + +**响应时间改进:** +图遍历:15-20 秒 → 3-5 秒 (快 4-5 倍)。 +标签解析:8-12 秒 → 2-4 秒 (快 3 倍)。 +总体查询:25-35 秒 → 6-10 秒 (提升 3-4 倍)。 + +**内存效率:** +限制的缓存大小可防止内存泄漏。 +<<<<<<< HEAD +高效的数据结构可减少内存占用 ~40%。 +======= +高效的数据结构可将内存占用减少约 40%。 +>>>>>>> 82edf2d (New md files from RunPod) +通过适当的资源清理实现更好的垃圾回收。 + +**现实的性能期望:** +**标签缓存**:对于具有常见关系的图,查询减少 10-20%。 +**批处理优化**:查询减少 50-80% (主要优化)。 +**对象生命周期优化**:消除每个请求的创建开销。 +**总体改进**:主要通过批处理实现响应时间提升 3-4 倍。 + +**可扩展性改进:** +支持 3-5 倍更大的知识图 (受缓存一致性需求限制)。 +3-5 倍更高的并发请求容量。 +通过连接重用实现更好的资源利用率。 + +### 性能监控 + +**实时指标:** +按操作类型划分的查询执行时间。 +缓存命中率和有效性。 +数据库连接池利用率。 +内存使用情况和垃圾回收影响。 + +<<<<<<< HEAD +**性能基准测试 (Xìngnéng Jīzhǔ Cèshì):** +自动化性能回归测试 (Zìdònghuà xìngnéng huíguī cèshì) +使用真实数据量的负载测试 (Shǐyòng zhēnshí shùjùliàng de fùzài cèshì) +与当前实现相比的基准测试 (Yǔ xiàncái shíxiàn xiāngbǐ de jīzhǔ cèshì) +======= +**性能基准测试:** +自动化性能回归测试 +使用真实数据量的负载测试 +与当前实现相比的基准测试 +>>>>>>> 82edf2d (New md files from RunPod) + +## 测试策略 (Cèshì Cèlüè) + +<<<<<<< HEAD +### 单元测试 (Dānyuán Cèshì) +对遍历、缓存和标签解析等各个组件进行单独测试 (Duì biànlì, cáichǔ hé biāoqiān jiěshì děng gège zǔjiàn jìnxíng dānduǒ cèshì) +模拟数据库交互以进行性能测试 (Mónǐ shùjùkù jiāohù yǐ jìnxíng xìngnéng cèshì) +缓存驱逐和 TTL 过期测试 (Cáichǔ qūzhí hé TTL guòqí cèshì) +错误处理和超时场景测试 (Cuòwù chǔlǐ hé chāoshí chǎngjǐng cèshì) + +### 集成测试 (Jíchéng Cèshì) +使用优化后的 GraphRAG 查询的端到端测试 (Shǐyòng yōuhuà hòu de GraphRAG shōuchá de duān dào duān cèshì) +使用真实数据的数据库交互测试 (Shǐyòng zhēnshí shùjù de shùjùkù jiāohù cèshì) +并发请求处理和资源管理测试 (Bìngfā qǐngqiú chǔlǐ hé zīyuán guǎnlǐ cèshì) +内存泄漏检测和资源清理验证 (Nèicún liūlèi jiǎncè hé zīyuán qīnglǐ yànzhèng) + +### 性能测试 (Xìngnéng Cèshì) +与当前实现相比的基准测试 (Yǔ xiàncái shíxiàn xiāngbǐ de jīzhǔ cèshì) +使用不同大小和复杂度的图的负载测试 (Shǐyòng bùtóng dàxiǎo hé fùzá dù de tú de fùzài cèshì) +压力测试以确定内存和连接限制 (Yālì cèshì yǐ quèdìng nèicún hé liánjiē xiànzhì) +用于性能改进的回归测试 (Yòng yú xìngnéng gǎijìn de huíguī cèshì) + +### 兼容性测试 (Jiānróng Xìng Cèshì) +验证现有 GraphRAG API 的兼容性 (Yànzhèng xiàn yǒu GraphRAG API de jiānróng xìng) +使用各种图数据库后端进行测试 (Shǐyòng gè zhǒng tú shùjùkù hòudùàn jìnxíng cèshì) +验证与当前实现相比的结果准确性 (Yànzhèng yǔ xiàncái shíxiàn xiāngbǐ de jiéguǒ zhǔnquè xìng) +======= +### 单元测试 +对遍历、缓存和标签解析的各个组件进行测试 +模拟数据库交互以进行性能测试 +缓存驱逐和 TTL 过期测试 +错误处理和超时场景 + +### 集成测试 +使用优化后的 GraphRAG 查询进行端到端测试 +使用真实数据进行数据库交互测试 +并发请求处理和资源管理 +内存泄漏检测和资源清理验证 + +### 性能测试 +与当前实现相比的基准测试 +使用不同大小和复杂度的图进行负载测试 +压力测试以检查内存和连接限制 +针对性能改进进行的回归测试 + +### 兼容性测试 +验证现有 GraphRAG API 的兼容性 +使用各种图数据库后端进行测试 +验证与当前实现相比的结果准确性 +>>>>>>> 82edf2d (New md files from RunPod) + +## 实施计划 (Shíshī Jìhuà) + +<<<<<<< HEAD +### 直接实施方法 (Zhíjiē Shíshī Fāngfǎ) +由于允许 API 更改,因此在不引入迁移复杂性的情况下,直接实施优化:(Yóuyú yǔnxǔ API gēnggǎi, yīncǐ zài bù yǐnrù qiān yí fùzá xìng de qíngkuàng xià, zhíjiē shíshī yōuhuà:) + +1. **替换 `follow_edges` 方法**: 使用迭代批量遍历重写 (Tiānyuē `follow_edges` fāngfǎ: Shǐyòng diànxìng pīliàng biànlì chóngxīn xiě) +2. **优化 `get_labelgraph`**: 实施并行标签解析 (Yōuhuà `get_labelgraph`: Shíshī bìngxíng biāoqiān jiěshì) +3. **添加长期 GraphRag**: 修改处理器以维护持久实例 (Tiānjiā chángqí GraphRag: Gǎixiāng chǔlǐ qì yǐ wéihù chíjiǔ yǐnshì) +4. **实施标签缓存**: 为 GraphRag 类添加 LRU 缓存和 TTL (Shíshī biāoqiān cáichǔ: Wèi GraphRag lèi tiānjiā LRU cáichǔ hé TTL) + +### 变更范围 (Biàngēng Fànwéi) +**查询类 (Query Class)**: 替换 `follow_edges` 中的 ~50 行代码,添加 ~30 行批量处理代码 (Tiānyuē `follow_edges` zhōng de ~50 háng dàimǎ, tiānjiā ~30 háng pīliàng chǔlǐ dàimǎ) +**GraphRag 类 (GraphRag Class)**: 添加缓存层 (~40 行代码) (Tiānjiā cáichǔ céng (~40 háng dàimǎ)) +**处理器类 (Processor Class)**: 修改为使用持久的 GraphRag 实例 (~20 行代码) (Gǎixiāng wéi shǐyòng chíjiǔ de GraphRag yǐnshì (~20 háng dàimǎ)) +**总计 (Zǒngjì)**: ~140 行专注于的变更,主要在现有类中 (~140 háng zhuānzhù yú de biàngēng, zhǔyào zài xiàn yǒu lèi zhōng) +======= +### 直接实施方法 +由于允许 API 更改,因此无需迁移复杂性,可以直接实现优化: + +1. **替换 `follow_edges` 方法**: 使用迭代批量遍历重写 +2. **优化 `get_labelgraph`**: 实现并行标签解析 +3. **添加长期 GraphRag**: 修改 Processor 以维护持久实例 +4. **实现标签缓存**: 为 GraphRag 类添加 LRU 缓存和 TTL + +### 变更范围 +**查询类**: 替换 `follow_edges` 中的约 50 行代码,添加约 30 行批量处理代码 +**GraphRag 类**: 添加缓存层(约 40 行代码) +**Processor 类**: 修改为使用持久的 GraphRag 实例(约 20 行代码) +**总计**: 约 140 行代码的集中性变更,主要在现有类中 +>>>>>>> 82edf2d (New md files from RunPod) + +## 时间线 (Shíjiān Xiàn) + +<<<<<<< HEAD +**第一周: 核心实施 (Dì Yī Zhōu: Héxīn Shíshī)** +使用批量迭代遍历替换 `follow_edges` (Shǐyòng pīliàng diànxìng biànlì tiānyuē `follow_edges`) +在 `get_labelgraph` 中实施并行标签解析 (Zài `get_labelgraph` zhōng shíshī bìngxíng biāoqiān jiěshì) +向处理器添加长期 GraphRag 实例 (Xiàng chǔlǐ qì tiānjiā chángqí GraphRag yǐnshì) +实施标签缓存层 (Shíshī biāoqiān cáichǔ céng) + +**第二周: 测试和集成 (Dì Èr Zhōu: Cèshì hé Jíchéng)** +对新的遍历和缓存逻辑进行单元测试 (Duì xīn de biànlì hé cáichǔ luójí jìnxíng dānyuán cèshì) +与当前实现相比进行性能基准测试 (Yǔ xiàncái shíxiàn xiāngbǐ jìnxíng xìngnéng jīzhǔ cèshì) +使用真实图数据进行集成测试 (Shǐyòng zhēnshí tú shùjù jìnxíng jíchéng cèshì) +代码审查和优化 (Dàimǎ shěnchá hé yōuhuà) + +**第三周: 部署 (Dì Sān Zhōu: Bùshǔ)** +部署优化后的实现 (Bùshǔ yōuhuà hòu de shíshī) +监控性能改进 (Jiānkòng xìngnéng gǎijìn) +根据实际使用情况微调缓存 TTL 和批量大小 (Gēnjù shíjì shǐyòng qíngkuàng wēitiáo cáichǔ TTL hé pīliàng dàxiǎo) +======= +**第一周:核心实施** +使用批量迭代遍历替换 `follow_edges` +在 `get_labelgraph` 中实现并行标签解析 +在 Processor 中添加长期 GraphRag 实例 +实现标签缓存层 + +**第二周:测试和集成** +对新的遍历和缓存逻辑进行单元测试 +与当前实现相比的性能基准测试 +使用真实图数据的集成测试 +代码审查和优化 + +**第三周:部署** +部署优化的实现 +监控性能改进 +根据实际使用情况微调缓存 TTL 和批次大小 +>>>>>>> 82edf2d (New md files from RunPod) + +## 开放性问题 (Kāifàng Xìng Wèntí) + +<<<<<<< HEAD +**数据库连接池 (Shùjùkù Liánjiē Chí)**: 我们应该实施自定义连接池,还是依赖于现有的数据库客户端连接池?(Wǒmen yīnggāi shíshī zìdìngyì liánjiē chí, háishì yīlài yú xiàn yǒu de shùjùkù kèfāngliánjiē chí?) +**缓存持久性 (Cáichǔ Chíjiǔ Xìng)**: 标签和嵌入式缓存是否应该在服务重启后持久存在?(Biāoqiān hé qiànrùshì cáichǔ shìfǒu yīnggāi zài fúwù chóngqí hòu chíjiǔ cúnzài?) +**分布式缓存 (Fēn Bùshì Cáichǔ)**: 对于多实例部署,我们是否应该实施具有 Redis/Memcached 的分布式缓存?(Duìyú duō yǐnshì bùshǔ, wǒmen shìfǒu yīnggāi shíshī yǒuyú Redis/Memcached de fēn bùshì cáichǔ?) +**查询结果格式 (Shōuchá Jiéguǒ Géshì)**: 我们是否应该优化内部三元组表示以获得更好的内存效率?(Wǒmen shìfǒu yīnggāi yōuhuà nèibù sān yuánzǔ biǎoshì yǐ huòdé gèng hǎo de nèicún xiàolǜ?) +**监控集成 (Jiānkòng Jíchéng)**: 哪些指标应该暴露给现有的监控系统(Prometheus 等)?(Nǎxiē zhǐbiāo yīnggāi bàolù gěi xiàn yǒu de jiānkòng xìtǒng (Prometheus děng)?) + +## 参考文献 (Cānkǎo Z tàiliào) + +GraphRAG API 文档 (GraphRAG API 文档) +示例代码 (Lìmiàn dàimǎ) +相关论文 (Xiāngguān lùnwén) +======= +**数据库连接池**: 我们应该实现自定义连接池,还是依赖于现有的数据库客户端池? +**缓存持久性**: 标签和嵌入式缓存是否应该在服务重启后持久存在? +**分布式缓存**: 对于多实例部署,我们是否应该实现使用 Redis/Memcached 的分布式缓存? +**查询结果格式**: 我们是否应该优化内部三元组表示以获得更好的内存效率? +**监控集成**: 哪些指标应该暴露给现有的监控系统(Prometheus 等)? + +## 参考文献 + +[GraphRAG 原始实现](trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py) +[TrustGraph 架构原则](architecture-principles.md) +[集合管理规范](collection-management.md) +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/import-export-graceful-shutdown.ar.md b/docs/tech-specs/import-export-graceful-shutdown.ar.md new file mode 100644 index 00000000..6da52f7c --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.ar.md @@ -0,0 +1,717 @@ +--- +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 تواجه حاليًا فقدان الرسائل أثناء إغلاق WebSocket في كل من عمليات الاستيراد والتصدير. يحدث هذا بسبب حالات السباق حيث يتم التخلص من الرسائل أثناء النقل قبل وصولها إلى وجهتها (قوائم انتظار Pulsar للاستيراد، عملاء WebSocket للتصدير). + +### مشاكل جانب الاستيراد +1. مخزن مؤقت asyncio.Queue الخاص بالناشر غير فارغ عند الإغلاق. +2. يتم إغلاق WebSocket قبل التأكد من وصول الرسائل الموجودة في قائمة الانتظار إلى Pulsar. +3. لا يوجد آلية تأكيد لتسليم الرسائل بنجاح. + +### مشاكل جانب التصدير +1. يتم تأكيد الرسائل في Pulsar قبل التسليم الناجح إلى العملاء. +2. تؤدي قيم المهلة الثابتة إلى فقدان الرسائل عندما تكون قوائم الانتظار ممتلئة. +3. لا يوجد آلية للتحكم في التدفق للتعامل مع المستهلكين البطيئين. +4. نقاط تخزين مؤقت متعددة حيث يمكن فقدان البيانات. + +## نظرة عامة على البنية + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +<<<<<<< HEAD +## التحسينات المقترحة +======= +## الحلول المقترحة +>>>>>>> 82edf2d (New md files from RunPod) + +### 1. تحسينات الناشر (جانب الاستيراد) + +#### أ. تفريغ سلس للانتظار + +**الملف:** `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**المزايا الرئيسية للتصميم:** +**موقع إرسال واحد**: جميع استدعاءات `producer.send()` تحدث في مكان واحد داخل الطريقة `run()`. +<<<<<<< HEAD +**آلة حالة واضحة:** ثلاثة حالات واضحة - قيد التشغيل، في مرحلة التفريغ، متوقفة. +======= +**آلة حالة واضحة:** ثلاثة حالات واضحة - قيد التشغيل، في طور التفريغ، متوقفة. +>>>>>>> 82edf2d (New md files from RunPod) +**حماية من المهلة الزمنية:** لن تتعطل بشكل دائم أثناء التفريغ. +**إمكانية مراقبة أفضل:** تسجيل واضح لتقدم التفريغ والانتقالات بين الحالات. +**رفض الرسائل الاختياري:** يمكن رفض الرسائل الجديدة أثناء مرحلة الإغلاق. + +#### ب. ترتيب الإغلاق المحسّن + +**الملف:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. تحسينات المشترك (الجانب التصديري) + +#### أ. نمط التصريف المتكامل + +**الملف:** `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**المزايا الرئيسية للتصميم (مطابقة لنمط الناشر):** +<<<<<<< HEAD +**موقع معالجة واحد:** تتم جميع عمليات معالجة الرسائل في الطريقة `run()`. +**آلة حالة واضحة:** ثلاثة حالات واضحة - قيد التشغيل، في مرحلة التفريغ، متوقفة. +**الإيقاف المؤقت أثناء التفريغ:** تتوقف عن قبول رسائل جديدة من Pulsar أثناء تفريغ قوائم الانتظار الحالية. +**حماية ضد المهلة:** لن تتعطل إلى أجل غير مسمى أثناء التفريغ. +======= +**موقع معالجة واحد:** تتم معالجة جميع الرسائل في الطريقة `run()`. +**آلة حالة واضحة:** ثلاثة حالات واضحة - قيد التشغيل، في مرحلة التفريغ، متوقفة. +**الإيقاف المؤقت أثناء التفريغ:** تتوقف عن قبول رسائل جديدة من Pulsar أثناء تفريغ قوائم الانتظار الحالية. +**حماية المهلة الزمنية:** لن تتعطل إلى أجل غير مسمى أثناء التفريغ. +>>>>>>> 82edf2d (New md files from RunPod) +**تنظيف صحيح:** تعترف بأي رسائل لم يتم تسليمها على الإغلاق. + +#### ب. تحسينات معالج التصدير + +**الملف:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. تحسينات على مستوى المقابس. + +**الملف:** `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## خيارات التكوين + +إضافة دعم للتكوين لضبط السلوك: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## استراتيجية الاختبار + +### اختبارات الوحدة + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### اختبارات التكامل + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## خطة التنفيذ + +### المرحلة الأولى: الإصلاحات الحرجة (الأسبوع الأول) +إصلاح توقيت إقرار المشترك (لمنع فقدان الرسائل) +إضافة تفريغ قائمة الناشر +النشر في بيئة الاختبار + +### المرحلة الثانية: الإغلاق التدريجي (الأسبوع الثاني) +<<<<<<< HEAD +تطبيق تنسيق الإغلاق +======= +تطبيق التنسيق للإغلاق +>>>>>>> 82edf2d (New md files from RunPod) +إضافة استراتيجيات الضغط العكسي +اختبار الأداء + +### المرحلة الثالثة: المراقبة والضبط (الأسبوع الثالث) +إضافة مقاييس لعمق قائمة الانتظار +إضافة تنبيهات لفقدان الرسائل +ضبط قيم المهلة بناءً على بيانات الإنتاج + +## المراقبة والتنبيهات + +### المقاييس التي يجب تتبعها +`publisher.queue.depth` - حجم قائمة الانتظار الحالية للناشر +`publisher.messages.dropped` - الرسائل المفقودة أثناء الإغلاق +`subscriber.messages.negatively_acknowledged` - عمليات التسليم الفاشلة +`websocket.graceful_shutdowns` - عمليات الإغلاق التدريجي الناجحة +`websocket.forced_shutdowns` - عمليات الإغلاق القسري/المهلة + +### التنبيهات +عمق قائمة الانتظار للناشر > 80٪ من السعة +أي فقدان للرسائل أثناء الإغلاق +معدل الإقرار السلبي للمشترك > 1٪ +تجاوز مهلة الإغلاق + +## التوافق مع الإصدارات السابقة + +جميع التغييرات تحافظ على التوافق مع الإصدارات السابقة: +السلوك الافتراضي لم يتغير بدون تكوين +تستمر عمليات النشر الحالية في العمل +تدهور تدريجي في حالة عدم توفر الميزات الجديدة + +## اعتبارات الأمان + +<<<<<<< HEAD +لم يتم إدخال مسارات هجوم جديدة +======= +لم يتم تقديم مسارات هجوم جديدة +>>>>>>> 82edf2d (New md files from RunPod) +يمنع الضغط العكسي هجمات استنفاد الذاكرة +تمنع الحدود القابلة للتكوين إساءة استخدام الموارد + +## تأثير الأداء + +تكلفة إضافية قليلة أثناء التشغيل العادي +قد يستغرق الإغلاق ما يصل إلى 5 ثوانٍ إضافية (قابل للتكوين) +<<<<<<< HEAD +يحد استخدام الذاكرة من خلال حدود حجم قائمة الانتظار +======= +استخدام الذاكرة محدود بحدود حجم قائمة الانتظار +>>>>>>> 82edf2d (New md files from RunPod) +التأثير على وحدة المعالجة المركزية ضئيل (<1٪ زيادة) diff --git a/docs/tech-specs/import-export-graceful-shutdown.es.md b/docs/tech-specs/import-export-graceful-shutdown.es.md new file mode 100644 index 00000000..cead11af --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.es.md @@ -0,0 +1,725 @@ +--- +layout: default +title: "Especificación Técnica para el Cierre de Sesión Gratuito de Importación/Exportación" +parent: "Spanish (Beta)" +--- + +<<<<<<< HEAD +# Especificación Técnica para el Cierre de Sesión Gratuito de Importación/Exportación + +> **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. + +## Declaración del Problema + +Actualmente, la puerta de enlace TrustGraph experimenta pérdida de mensajes durante el cierre de la conexión websocket tanto en las operaciones de importación como de exportación. Esto ocurre debido a condiciones de carrera donde los mensajes en tránsito se descartan antes de llegar a su destino (colas Pulsar para importaciones, clientes websocket para exportaciones). + +### Problemas del Lado de Importación +1. El búfer de la cola asyncio del publicador no se vacía durante el apagado. +2. La conexión websocket se cierra antes de asegurarse de que los mensajes en cola lleguen a Pulsar. +3. No hay un mecanismo de confirmación para la entrega exitosa de mensajes. + +### Problemas del Lado de Exportación +======= +# Especificación Técnica para el Cierre Gratuito de Importación/Exportación + +## Declaración del Problema + +Actualmente, la puerta de enlace TrustGraph experimenta pérdida de mensajes durante el cierre de WebSocket tanto en las operaciones de importación como de exportación. Esto ocurre debido a condiciones de carrera donde los mensajes en tránsito se descartan antes de llegar a su destino (colas de Pulsar para importaciones, clientes de WebSocket para exportaciones). + +### Problemas del Lado de la Importación +1. El búfer de la cola asyncio del publicador no se vacía durante el apagado. +2. El WebSocket se cierra antes de asegurarse de que los mensajes en cola lleguen a Pulsar. +3. No hay un mecanismo de confirmación para la entrega exitosa de mensajes. + +### Problemas del Lado de la Exportación +>>>>>>> 82edf2d (New md files from RunPod) +1. Los mensajes se confirman en Pulsar antes de la entrega exitosa a los clientes. +2. Los tiempos de espera codificados de forma rígida causan la pérdida de mensajes cuando las colas están llenas. +3. No hay un mecanismo de retroalimentación para manejar consumidores lentos. +4. Múltiples puntos de búfer donde los datos pueden perderse. + +## Descripción General de la Arquitectura + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## Soluciones propuestas + +### 1. Mejoras para el publicador (lado de importación) + +#### A. Vaciado de la cola de forma gradual + +**Archivo**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**Beneficios Clave del Diseño:** +**Ubicación Única para el Envío**: Todas las llamadas a `producer.send()` se realizan en un solo lugar dentro del método `run()`. +**Máquina de Estados Clara**: Tres estados claros: en ejecución, en drenaje, detenido. +**Protección contra Tiempo de Espera**: No se quedará bloqueado indefinidamente durante el drenaje. +**Mejor Observabilidad**: Registro claro del progreso del drenaje y las transiciones de estado. +**Rechazo de Mensajes Opcional**: Puede rechazar nuevos mensajes durante la fase de apagado. + +#### B. Orden de Apagado Mejorado + +**Archivo**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. Mejoras para el Suscriptor (Lado de Exportación) + +#### A. Patrón de Drenaje Integrado + +**Archivo**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**Beneficios clave del diseño (que coinciden con el patrón del editor):** +<<<<<<< HEAD +**Ubicación de procesamiento única**: Todo el procesamiento de mensajes se realiza en el método `run()`. +**Máquina de estados limpia**: Tres estados claros: en ejecución, vaciado, detenido. +**Pausa durante el vaciado**: Deja de aceptar nuevos mensajes de Pulsar mientras vacía las colas existentes. +**Protección por tiempo de espera**: No se quedará bloqueado indefinidamente durante el vaciado. +**Limpieza adecuada**: Reconoce negativamente cualquier mensaje no entregado al apagar. +======= +**Ubicación de procesamiento única**: Todo el procesamiento de mensajes se realiza en el método `run()` +**Máquina de estados limpia**: Tres estados claros: en ejecución, vaciado, detenido +**Pausa durante el vaciado**: Deja de aceptar nuevos mensajes de Pulsar mientras vacía las colas existentes +**Protección por tiempo de espera**: No se quedará bloqueado indefinidamente durante el vaciado +**Limpieza adecuada**: Reconoce negativamente cualquier mensaje no entregado al apagar +>>>>>>> 82edf2d (New md files from RunPod) + +#### B. Mejoras del controlador de exportación + +**Archivo**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. Mejoras a nivel de socket + +**Archivo**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## Opciones de configuración + +Agregar soporte de configuración para ajustar el comportamiento: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## Estrategia de pruebas + +### Pruebas unitarias + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### Pruebas de Integración + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## Plan de Implementación + +### Fase 1: Correcciones Críticas (Semana 1) +Corregir el tiempo de confirmación del suscriptor (prevenir la pérdida de mensajes) +Agregar el vaciado de la cola del publicador +<<<<<<< HEAD +Implementar en el entorno de pruebas +======= +Desplegar en el entorno de pruebas +>>>>>>> 82edf2d (New md files from RunPod) + +### Fase 2: Cierre Gratuito (Semana 2) +Implementar la coordinación del cierre +Agregar estrategias de contrapresión +Pruebas de rendimiento + +### Fase 3: Monitoreo y Ajuste (Semana 3) +Agregar métricas para las profundidades de la cola +Agregar alertas para la pérdida de mensajes +Ajustar los valores de tiempo de espera según los datos de producción + +## Monitoreo y Alertas + +### Métricas a Monitorear +`publisher.queue.depth` - Tamaño actual de la cola del publicador +`publisher.messages.dropped` - Mensajes perdidos durante el cierre +`subscriber.messages.negatively_acknowledged` - Entregas fallidas +<<<<<<< HEAD +`websocket.graceful_shutdowns` - Cierres gratuitos exitosos +======= +`websocket.graceful_shutdowns` - Cierres suaves exitosos +>>>>>>> 82edf2d (New md files from RunPod) +`websocket.forced_shutdowns` - Cierres forzados/por tiempo de espera + +### Alertas +Profundidad de la cola del publicador > 80% de capacidad +Cualquier pérdida de mensajes durante el cierre +Tasa de acuse de recibo negativo del suscriptor > 1% +Tiempo de espera del cierre excedido + +## Compatibilidad con Versiones Anteriores + +Todos los cambios mantienen la compatibilidad con versiones anteriores: +El comportamiento predeterminado no cambia sin configuración +<<<<<<< HEAD +Las implementaciones existentes continúan funcionando +======= +Los despliegues existentes continúan funcionando +>>>>>>> 82edf2d (New md files from RunPod) +Degradación gradual si las nuevas funciones no están disponibles + +## Consideraciones de Seguridad + +No se introducen nuevos vectores de ataque +La contrapresión evita los ataques de agotamiento de memoria +Los límites configurables previenen el abuso de recursos + +## Impacto en el Rendimiento + +Sobre carga mínima durante la operación normal +El cierre puede tardar hasta 5 segundos más (configurable) +El uso de memoria está limitado por los límites del tamaño de la cola +El impacto en la CPU es insignificante (<1% de aumento) diff --git a/docs/tech-specs/import-export-graceful-shutdown.he.md b/docs/tech-specs/import-export-graceful-shutdown.he.md new file mode 100644 index 00000000..9723432a --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.he.md @@ -0,0 +1,713 @@ +--- +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. + +## הצהרת בעיה + +<<<<<<< HEAD +שער TrustGraph חווה כרגע אובדן הודעות במהלך סגירת WebSocket בפעולות ייבוא ויצוא כאחד. זה קורה עקב מצבי מירוץ שבהם הודעות בתנועה נזרקות לפני שהן מגיעות ליעדים שלהן (תורי Pulsar לייבוא, לקוחות WebSocket לייצוא). +======= +שער TrustGraph חווה כרגע אובדן הודעות במהלך סגירת WebSocket בפעולות ייבוא ויצוא כאחד. זה קורה עקב מצבי מירוץ שבהם הודעות בתנועה נזרקות לפני שהן מגיעות ליעדים שלהן (תורי Pulsar עבור ייבוא, לקוחות WebSocket עבור יצוא). +>>>>>>> 82edf2d (New md files from RunPod) + +### בעיות בצד הייבוא +1. מאגר ה-asyncio.Queue של המפרסם אינו מרוקן במהלך השבתה. +2. WebSocket נסגר לפני הבטחה שהודעות בתור יגיעו ל-Pulsar. +3. אין מנגנון אישור עבור מסירת הודעות מוצלחת. + +### בעיות בצד היצוא +1. הודעות מאושרות ב-Pulsar לפני מסירה מוצלחת ללקוחות. +2. זמני תפוגה מוגדרים מראש גורמים לאובדן הודעות כאשר התורים מלאים. +3. אין מנגנון לחץ נגדי לטיפול בצרכנים איטיים. +4. נקודות מאגר מרובות שבהן ניתן לאבד נתונים. + +## סקירה כללית של הארכיטקטורה + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## תיקונים מוצעים + +### 1. שיפורים עבור מפרסמים (צד הייבוא) + +#### א. ניקוז תור חלק + +**קובץ:** `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**יתרונות עיצוב מרכזיים:** +**מיקום שליחה יחיד**: כל הקריאות ל-`producer.send()` מתרחשות במקום אחד בתוך השיטה `run()`. +**מצב פעולה ברור:** שלושה מצבים ברורים - פעיל, ריקון, עצור. +<<<<<<< HEAD +**הגנה מפני תזמון מוגזם:** לא יימשך ללא הגבלת זמן במהלך הריקון. +======= +**הגנה מפני תזמון מוגזם:** לא יימשך ללא סוף במהלך הריקון. +>>>>>>> 82edf2d (New md files from RunPod) +**יכולת ניטור משופרת:** רישום ברור של התקדמות הריקון ומעברי מצב. +**דחיית הודעות אופציונלית:** ניתן לדחות הודעות חדשות במהלך שלב השבתה. + +#### ב. סדר השבתה משופר + +**קובץ:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. שיפורים למנויים (צד היצוא) + +#### א. תבנית ניקוז משולבת + +<<<<<<< HEAD +**קובץ**: `trustgraph-base/trustgraph/base/subscriber.py` +======= +**קובץ:** `trustgraph-base/trustgraph/base/subscriber.py` +>>>>>>> 82edf2d (New md files from RunPod) + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**יתרונות עיצוב מרכזיים (התאמה לדפוס של המפרסם):** +<<<<<<< HEAD +**מיקום עיבוד יחיד**: כל עיבוד ההודעות מתבצע בשיטה `run()`. +**מצב מכונה נקי**: שלושה מצבים ברורים - פעיל, ריקון, עצור. +**השהיה במהלך ריקון**: מפסיק לקבל הודעות חדשות מ-Pulsar תוך כדי ריקון תורים קיימים. +**הגנה מפני תזמון מוגזם**: לא ייקפא ללא סיבה במהלך הריקון. +======= +**מיקום עיבוד יחיד**: כל פעולות העיבוד של ההודעות מתבצעות בשיטה `run()`. +**מצב מכונה נקי**: שלושה מצבים ברורים - פעיל, ריקון, עצור. +**השהיה במהלך הריקון**: מפסיק לקבל הודעות חדשות מ-Pulsar תוך כדי ריקון תורים קיימים. +**הגנה מפני תקיעות**: לא ייגרם תקיעה אינסופי במהלך הריקון. +>>>>>>> 82edf2d (New md files from RunPod) +**ניקוי תקין**: מודה בשלילה על כל הודעות שלא נמסרו בעת השבתה. + +#### ב. שיפורים למטפל ייצוא + +**קובץ:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. שיפורים ברמת החיבור (Socket) + +**קובץ:** `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## אפשרויות תצורה + +הוספת תמיכה בתצורה לשינוי התנהגות: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## אסטרטגיית בדיקות + +### בדיקות יחידה + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### בדיקות אינטגרציה + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## תוכנית הטמעה + +### שלב 1: תיקונים קריטיים (שבוע 1) +תיקון תזמון אישור מנויים (מניעת אובדן הודעות) +הוספת ניקוז תור משדר +הטמעה בסביבת בדיקות + +### שלב 2: השבתה חלקה (שבוע 2) +הטמעת תיאום השבתה +הוספת אסטרטגיות לחץ נגדי +בדיקות ביצועים + +### שלב 3: ניטור וכוונון (שבוע 3) +הוספת מדדים לעומק תורים +הוספת התראות לאובדן הודעות +כוונון ערכי זמן קצוב בהתבסס על נתוני ייצור + +## ניטור והתראות + +### מדדים שיש לעקוב אחריהם +`publisher.queue.depth` - גודל נוכחי של תור המשדר +`publisher.messages.dropped` - הודעות שאבדו במהלך השבתה +`subscriber.messages.negatively_acknowledged` - משלוחים שנכשלו +`websocket.graceful_shutdowns` - השבתות חלקות מוצלחות +`websocket.forced_shutdowns` - השבתות בכוח/עקב חריגה מהזמן הקצוב + +### התראות +עומק תור המשדר > 80% מהקיבולת +כל אובדן הודעות במהלך השבתה +קצב אישור שלילי של מנויים > 1% +חריגה מהזמן הקצוב להשבתה + +## תאימות לאחור + +כל השינויים שומרים על תאימות לאחור: +התנהגות ברירת המחדל לא משתנה ללא תצורה +הטמעות קיימות ממשיכות לתפקד +ירידה הדרגתית בפעולה אם תכונות חדשות אינן זמינות + +## שיקולי אבטחה + +לא הוצגו וקטורי תקיפה חדשים +לחץ נגדי מונע התקפות של התעמקות זיכרון +מגבלות הניתנות לתצורה מונעות ניצול משאבים + +## השפעה על הביצועים + +תקורה מינימלית במהלך פעולה רגילה +השבתה עשויה לקחת עד 5 שניות נוספות (ניתן להגדרה) +השימוש בזיכרון מוגבל על ידי מגבלות גודל התור +<<<<<<< HEAD +השפעה על ה-CPU זניחה (<1% עלייה) +======= +השפעה על מעבד זניחה (<1% עלייה) +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/import-export-graceful-shutdown.hi.md b/docs/tech-specs/import-export-graceful-shutdown.hi.md new file mode 100644 index 00000000..883090fd --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.hi.md @@ -0,0 +1,718 @@ +--- +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. + +## समस्या विवरण + +<<<<<<< HEAD +ट्रस्टग्राफ गेटवे वर्तमान में आयात और निर्यात दोनों कार्यों के दौरान वेबसॉकेट बंद होने के समय संदेश हानि का अनुभव करता है। यह दौड़ की स्थितियों के कारण होता है जहां पारगमन में मौजूद संदेश अपने गंतव्य (आयात के लिए पल्सर कतारों, निर्यात के लिए वेबसॉकेट क्लाइंट) तक पहुंचने से पहले त्याग दिए जाते हैं। +======= +ट्रस्टग्राफ गेटवे वर्तमान में आयात और निर्यात दोनों कार्यों के दौरान वेबसॉकेट बंद होने के समय संदेशों के खो जाने की समस्या का सामना करता है। यह दौड़ की स्थितियों के कारण होता है, जिसमें रास्ते में मौजूद संदेशों को उनके गंतव्य (आयात के लिए पल्सर कतारों, निर्यात के लिए वेबसॉकेट क्लाइंट) तक पहुंचने से पहले त्याग दिया जाता है। +>>>>>>> 82edf2d (New md files from RunPod) + +### आयात-पक्ष की समस्याएं +1. प्रकाशक का asyncio.Queue बफर शटडाउन पर खाली नहीं होता है। +2. वेबसॉकेट बंद होने से पहले यह सुनिश्चित नहीं किया जाता है कि कतारबद्ध संदेश पल्सर तक पहुंचें। +3. सफल संदेश वितरण के लिए कोई स्वीकृति तंत्र नहीं है। + +### निर्यात-पक्ष की समस्याएं +1. संदेशों को क्लाइंट को सफलतापूर्वक वितरित होने से पहले पल्सर में स्वीकार किया जाता है। +2. हार्ड-कोडेड टाइमआउट के कारण संदेश ड्रॉप हो जाते हैं जब कतारें भरी होती हैं। +3. धीमी उपभोक्ताओं को संभालने के लिए कोई बैकप्रेशर तंत्र नहीं है। +<<<<<<< HEAD +4. कई बफर बिंदु जहां डेटा खो सकता है। +======= +4. कई बफर बिंदु हैं जहां डेटा खो सकता है। +>>>>>>> 82edf2d (New md files from RunPod) + +## वास्तुकला अवलोकन + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## प्रस्तावित सुधार + +### 1. प्रकाशक में सुधार (आयात पक्ष) + +#### ए. सुचारू कतार खाली करना + +**फ़ाइल**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**मुख्य डिज़ाइन लाभ:** +**एकल प्रेषण स्थान**: सभी `producer.send()` कॉल `run()` विधि के भीतर एक ही स्थान पर होते हैं। +**स्वच्छ स्टेट मशीन**: तीन स्पष्ट अवस्थाएँ - चल रही, खाली करने की प्रक्रिया में, बंद। +**टाइमआउट सुरक्षा**: खाली करने के दौरान अनिश्चित काल तक नहीं रुकेगा। +**बेहतर अवलोकन क्षमता**: खाली करने की प्रगति और अवस्था परिवर्तनों का स्पष्ट लॉगिंग। +**वैकल्पिक संदेश अस्वीकृति**: शटडाउन चरण के दौरान नए संदेशों को अस्वीकार किया जा सकता है। + +#### बी. बेहतर शटडाउन क्रम + +**फ़ाइल**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. ग्राहक सुधार (निर्यात पक्ष) + +#### ए. एकीकृत जल निकासी पैटर्न + +**फ़ाइल**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +<<<<<<< HEAD +**मुख्य डिज़ाइन लाभ (प्रकाशक पैटर्न से मेल खाता):** +======= +**मुख्य डिज़ाइन लाभ (प्रकाशक पैटर्न से मेल खाता है):** +>>>>>>> 82edf2d (New md files from RunPod) +**एकल प्रसंस्करण स्थान**: सभी संदेश प्रसंस्करण `run()` विधि में होता है। +**स्वच्छ स्टेट मशीन**: तीन स्पष्ट अवस्थाएँ - चल रही, खाली करने की प्रक्रिया में, बंद। +**खाली करते समय विराम**: मौजूदा कतारों को खाली करते समय, पल्सर से नए संदेश स्वीकार करना बंद हो जाता है। +**समय-सीमा सुरक्षा**: खाली करने की प्रक्रिया के दौरान अनिश्चित काल तक नहीं रुकेगा। +<<<<<<< HEAD +**उचित सफाई**: शटडाउन पर, किसी भी अप्राप्त संदेश को नकारात्मक रूप से स्वीकार किया जाता है। +======= +**उचित सफाई**: शटडाउन पर किसी भी अप्राप्त संदेश को नकारात्मक रूप से स्वीकार करता है। +>>>>>>> 82edf2d (New md files from RunPod) + +#### बी. एक्सपोर्ट हैंडलर में सुधार + +**फ़ाइल**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +<<<<<<< HEAD +### 3. सॉकेट-स्तरीय सुधार +======= +### 3. सॉकेट-स्तर में सुधार +>>>>>>> 82edf2d (New md files from RunPod) + +**फ़ाइल**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## कॉन्फ़िगरेशन विकल्प + +व्यवहार को अनुकूलित करने के लिए कॉन्फ़िगरेशन समर्थन जोड़ें: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## परीक्षण रणनीति + +<<<<<<< HEAD +### यूनिट परीक्षण +======= +### इकाई परीक्षण +>>>>>>> 82edf2d (New md files from RunPod) + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +<<<<<<< HEAD +### एकीकरण परीक्षण (एकीकरण परीक्षण) +======= +### एकीकरण परीक्षण +>>>>>>> 82edf2d (New md files from RunPod) + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## रोलआउट योजना + +### चरण 1: महत्वपूर्ण सुधार (सप्ताह 1) +सब्सक्राइबर स्वीकृति समय को ठीक करें (संदेश हानि को रोकें) +पब्लिशर क्यू को खाली करने की सुविधा जोड़ें +स्टेजिंग वातावरण में तैनात करें + +### चरण 2: सुचारू शटडाउन (सप्ताह 2) +शटडाउन समन्वय लागू करें +बैकप्रेशर रणनीतियों को जोड़ें +प्रदर्शन परीक्षण + +### चरण 3: निगरानी और ट्यूनिंग (सप्ताह 3) +क्यू की गहराई के लिए मेट्रिक्स जोड़ें +संदेश ड्रॉप के लिए अलर्ट जोड़ें +उत्पादन डेटा के आधार पर टाइमआउट मानों को ट्यून करें + +## निगरानी और अलर्ट + +### ट्रैक करने के लिए मेट्रिक्स +`publisher.queue.depth` - वर्तमान पब्लिशर क्यू का आकार +`publisher.messages.dropped` - शटडाउन के दौरान खोए गए संदेश +`subscriber.messages.negatively_acknowledged` - विफल डिलीवरी +`websocket.graceful_shutdowns` - सफल सुचारू शटडाउन +`websocket.forced_shutdowns` - मजबूर/टाइमआउट शटडाउन + +### अलर्ट +पब्लिशर क्यू की गहराई > 80% क्षमता +शटडाउन के दौरान कोई भी संदेश ड्रॉप +सब्सक्राइबर नकारात्मक स्वीकृति दर > 1% +शटडाउन टाइमआउट समाप्त + +## पिछली अनुकूलता + +सभी परिवर्तनों में पिछली अनुकूलता बनी हुई है: +कॉन्फ़िगरेशन के बिना डिफ़ॉल्ट व्यवहार अपरिवर्तित रहता है +मौजूदा डिप्लॉयमेंट सामान्य रूप से काम करना जारी रखते हैं +यदि नई सुविधाएँ अनुपलब्ध हैं तो सुचारू गिरावट + +## सुरक्षा संबंधी विचार + +कोई नया आक्रमण वेक्टर नहीं जोड़ा गया +बैकप्रेशर मेमोरी थकावट हमलों को रोकता है +कॉन्फ़िगर करने योग्य सीमाएँ संसाधन दुरुपयोग को रोकती हैं + +## प्रदर्शन प्रभाव + +सामान्य संचालन के दौरान न्यूनतम ओवरहेड +शटडाउन में 5 सेकंड तक अधिक समय लग सकता है (कॉन्फ़िगर करने योग्य) +मेमोरी उपयोग क्यू आकार सीमाओं द्वारा सीमित है +CPU पर प्रभाव नगण्य (<1% वृद्धि) diff --git a/docs/tech-specs/import-export-graceful-shutdown.md b/docs/tech-specs/import-export-graceful-shutdown.md index 40c904f2..579353d8 100644 --- a/docs/tech-specs/import-export-graceful-shutdown.md +++ b/docs/tech-specs/import-export-graceful-shutdown.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Import/Export Graceful Shutdown Technical Specification" +parent: "Tech Specs" +--- + # Import/Export Graceful Shutdown Technical Specification ## Problem Statement @@ -679,4 +685,4 @@ All changes maintain backwards compatibility: - Minimal overhead during normal operation - Shutdown may take up to 5 seconds longer (configurable) - Memory usage bounded by queue size limits -- CPU impact negligible (<1% increase) \ No newline at end of file +- CPU impact negligible (<1% increase) diff --git a/docs/tech-specs/import-export-graceful-shutdown.pt.md b/docs/tech-specs/import-export-graceful-shutdown.pt.md new file mode 100644 index 00000000..1efbfd19 --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.pt.md @@ -0,0 +1,710 @@ +--- +layout: default +title: "Especificação Técnica de Desligamento Gratuito de Importação/Exportação" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Desligamento Gratuito de Importação/Exportação + +> **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. + +## Declaração do Problema + +Atualmente, o gateway TrustGraph experimenta perda de mensagens durante o fechamento do WebSocket tanto em operações de importação quanto de exportação. Isso ocorre devido a condições de corrida em que as mensagens em trânsito são descartadas antes de atingir seu destino (filas Pulsar para importações, clientes WebSocket para exportações). + +### Problemas no Lado da Importação +1. O buffer da fila asyncio do publicador não é esvaziado durante o desligamento. +2. O WebSocket é fechado antes de garantir que as mensagens enfileiradas cheguem ao Pulsar. +3. Não há mecanismo de confirmação para a entrega bem-sucedida da mensagem. + +### Problemas no Lado da Exportação +1. As mensagens são confirmadas no Pulsar antes da entrega bem-sucedida aos clientes. +2. Os tempos limite fixos causam a perda de mensagens quando as filas estão cheias. +3. Não há mecanismo de controle de fluxo para lidar com consumidores lentos. +4. Múltiplos pontos de buffer onde os dados podem ser perdidos. + +## Visão Geral da Arquitetura + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## Correções Propostas + +### 1. Melhorias no Publicador (Lado da Importação) + +#### A. Esvaziamento Gratuito da Fila + +**Arquivo**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**Principais Vantagens do Design:** +<<<<<<< HEAD +**Local de Envio Único**: Todas as chamadas de `producer.send()` ocorrem em um único local dentro do método `run()`. +======= +**Local de Envio Único**: Todas as chamadas `producer.send()` ocorrem em um único local dentro do método `run()`. +>>>>>>> 82edf2d (New md files from RunPod) +**Máquina de Estados Clara**: Três estados claros - em execução, esvaziando, parado. +**Proteção por Timeout**: Não fica indefinidamente travado durante o esvaziamento. +**Melhor Observabilidade**: Registro claro do progresso do esvaziamento e das transições de estado. +**Rejeição de Mensagens Opcional**: Pode rejeitar novas mensagens durante a fase de desligamento. + +#### B. Ordem de Desligamento Aprimorada + +**Arquivo**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. Melhorias para o Assinante (Lado de Exportação) + +#### A. Padrão de Drenagem Integrado + +**Arquivo**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +<<<<<<< HEAD +**Principais Vantagens do Design (compatível com o padrão do Editor):** +**Local de Processamento Único**: Todo o processamento de mensagens ocorre no método `run()` +**Máquina de Estados Clara**: Três estados claros - em execução, esvaziando, parado +**Pausa Durante o Esvaziamento**: Interrompe a aceitação de novas mensagens do Pulsar enquanto esvazia as filas existentes +**Proteção por Timeout**: Não fica indefinidamente travado durante o esvaziamento +======= +**Principais Vantagens do Design (compatível com o padrão do Publicador):** +**Local de Processamento Único**: Todo o processamento de mensagens ocorre no método `run()` +**Máquina de Estados Clara**: Três estados claros - em execução, esvaziando, parado +**Pausa Durante o Esvaziamento**: Interrompe a aceitação de novas mensagens do Pulsar enquanto esvazia as filas existentes +**Proteção por Timeout**: Não fica indefinidamente bloqueado durante o esvaziamento +>>>>>>> 82edf2d (New md files from RunPod) +**Limpeza Adequada**: Reconhece negativamente quaisquer mensagens não entregues durante o desligamento + +#### B. Melhorias no Manipulador de Exportação + +**Arquivo**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. Melhorias no Nível de Socket + +**Arquivo**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## Opções de Configuração + +Adicionar suporte para configuração para ajustar o comportamento: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## Estratégia de Testes + +### Testes Unitários + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### Testes de Integração + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## Plano de Implementação + +### Fase 1: Correções Críticas (Semana 1) +Corrigir o tempo de reconhecimento do assinante (evitar perda de mensagens) +Adicionar esvaziamento da fila do publicador +Implantar no ambiente de teste + +### Fase 2: Desligamento Gradual (Semana 2) +<<<<<<< HEAD +Implementar coordenação de desligamento +======= +Implementar a coordenação de desligamento +>>>>>>> 82edf2d (New md files from RunPod) +Adicionar estratégias de backpressure +Testes de desempenho + +### Fase 3: Monitoramento e Ajuste (Semana 3) +Adicionar métricas para profundidade da fila +Adicionar alertas para perda de mensagens +Ajustar valores de timeout com base em dados de produção + +## Monitoramento e Alertas + +### Métricas a serem Monitoradas +`publisher.queue.depth` - Tamanho atual da fila do publicador +`publisher.messages.dropped` - Mensagens perdidas durante o desligamento +`subscriber.messages.negatively_acknowledged` - Entregas falhadas +`websocket.graceful_shutdowns` - Desligamentos graduais bem-sucedidos +`websocket.forced_shutdowns` - Desligamentos forçados/por timeout + +### Alertas +Profundidade da fila do publicador > 80% da capacidade +Qualquer perda de mensagens durante o desligamento +Taxa de reconhecimento negativo do assinante > 1% +Timeout de desligamento excedido + +## Compatibilidade com Versões Anteriores + +Todas as alterações mantêm a compatibilidade com versões anteriores: +Comportamento padrão inalterado sem configuração +Implantações existentes continuam a funcionar +Degradação gradual se novos recursos não estiverem disponíveis + +## Considerações de Segurança + +Nenhum novo vetor de ataque introduzido +O backpressure impede ataques de esgotamento de memória +<<<<<<< HEAD +Limites configuráveis ​​evitam o abuso de recursos +======= +Limites configuráveis evitam o abuso de recursos +>>>>>>> 82edf2d (New md files from RunPod) + +## Impacto no Desempenho + +Sobrecarga mínima durante a operação normal +O desligamento pode levar até 5 segundos a mais (configurável) +O uso de memória é limitado pelos limites do tamanho da fila +O impacto na CPU é insignificante (<1% de aumento) diff --git a/docs/tech-specs/import-export-graceful-shutdown.ru.md b/docs/tech-specs/import-export-graceful-shutdown.ru.md new file mode 100644 index 00000000..740e963e --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.ru.md @@ -0,0 +1,717 @@ +--- +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 испытывает потерю сообщений во время закрытия WebSocket как при импорте, так и при экспорте. Это происходит из-за гонок, когда сообщения, находящиеся в процессе передачи, отбрасываются до того, как они достигнут своего назначения (очереди Pulsar для импорта, клиенты WebSocket для экспорта). + +### Проблемы на стороне импорта +1. Буфер asyncio.Queue издателя не очищается при завершении работы. +2. WebSocket закрывается до того, как будет гарантировано, что сообщения в очереди достигнут Pulsar. +3. Отсутствует механизм подтверждения успешной доставки сообщений. + +### Проблемы на стороне экспорта +1. Сообщения подтверждаются в Pulsar до успешной доставки клиентам. +2. Жестко заданные таймауты приводят к потере сообщений, когда очереди заполнены. +3. Отсутствует механизм обратной связи для обработки медленных потребителей. +4. Несколько буферных областей, где данные могут быть потеряны. + +## Обзор архитектуры + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## Предлагаемые исправления + +### 1. Улучшения для издателя (сторона импорта) + +#### A. Плавная очистка очереди + +**Файл**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**Основные преимущества дизайна:** +**Единое место отправки:** Все вызовы `producer.send()` происходят в одном месте внутри метода `run()`. +**Чистая конечная машина состояний:** Три четких состояния - работа, слив, остановка. +**Защита от таймаута:** Не зависнет бесконечно во время слива. +**Улучшенная наблюдаемость:** Четкое логирование хода слива и переходов состояний. +**Опциональное отклонение сообщений:** Может отклонять новые сообщения во время фазы завершения работы. + +#### B. Улучшенный порядок завершения работы + +**Файл:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. Улучшения для подписчиков (экспортная сторона) + +#### A. Интегрированная схема отвода + +**Файл**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**Основные преимущества дизайна (соответствие шаблону издателя):** +<<<<<<< HEAD +**Единое место обработки сообщений**: Вся обработка сообщений происходит в методе `run()` +**Чистая конечная машина состояний**: Три четких состояния - работа, слив, остановка +**Приостановка во время слива**: Прекращает прием новых сообщений из Pulsar во время слива существующих очередей +**Защита от таймаутов**: Не зависнет бесконечно во время слива +**Правильная очистка**: Отправляет отрицательные подтверждения для любых неотправленных сообщений при завершении работы +======= +**Единое место обработки сообщений**: Вся обработка сообщений происходит в методе `run()`. +**Чистый конечный автомат**: Три четких состояния - работа, слив, остановка. +**Приостановка во время слива**: Прекращает прием новых сообщений из Pulsar во время слива существующих очередей. +**Защита от таймаутов**: Не зависнет бесконечно во время слива. +**Правильная очистка**: Отправляет отрицательные подтверждения для любых неотправленных сообщений при завершении работы. +>>>>>>> 82edf2d (New md files from RunPod) + +#### B. Улучшения обработчика экспорта + +**Файл**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. Улучшения на уровне сокетов + +**Файл**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## Варианты конфигурации + +Добавить поддержку конфигурации для настройки поведения: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## Стратегия тестирования + +### Юнит-тесты + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### Интеграционные тесты + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## План внедрения + +<<<<<<< HEAD +### Фаза 1: Критические исправления (Неделя 1) +======= +### Этап 1: Критические исправления (Неделя 1) +>>>>>>> 82edf2d (New md files from RunPod) +Исправить время подтверждения подписки (предотвратить потерю сообщений) +Добавить очистку очереди издателя +Развернуть в тестовой среде + +<<<<<<< HEAD +### Фаза 2: Плавное завершение работы (Неделя 2) +======= +### Этап 2: Плавное завершение работы (Неделя 2) +>>>>>>> 82edf2d (New md files from RunPod) +Реализовать координацию завершения работы +Добавить стратегии обратной связи +Тестирование производительности + +<<<<<<< HEAD +### Фаза 3: Мониторинг и настройка (Неделя 3) +======= +### Этап 3: Мониторинг и настройка (Неделя 3) +>>>>>>> 82edf2d (New md files from RunPod) +Добавить метрики для глубины очередей +Добавить оповещения о потере сообщений +Настроить значения тайм-аутов на основе данных производственной среды + +## Мониторинг и оповещения + +### Метрики для отслеживания +`publisher.queue.depth` - Текущий размер очереди издателя +`publisher.messages.dropped` - Сообщения, потерянные во время завершения работы +`subscriber.messages.negatively_acknowledged` - Неудачные доставки +`websocket.graceful_shutdowns` - Успешные плавные завершения работы +`websocket.forced_shutdowns` - Принудительные/тайм-аут завершения работы + +### Оповещения +Глубина очереди издателя > 80% от максимальной емкости +Любая потеря сообщений во время завершения работы +Частота отрицательных подтверждений от подписчика > 1% +Превышен тайм-аут завершения работы + +## Обратная совместимость + +<<<<<<< HEAD +Все изменения сохраняют обратную совместимость: +Поведение по умолчанию не изменено без конфигурации +Существующие развертывания продолжают работать +Плавное снижение производительности в случае недоступности новых функций +======= +Все изменения поддерживают обратную совместимость: +Поведение по умолчанию не изменено без конфигурации +Существующие развертывания продолжают работать +Плавное снижение функциональности в случае недоступности новых функций +>>>>>>> 82edf2d (New md files from RunPod) + +## Вопросы безопасности + +Не введено новых векторов атак +Обратная связь предотвращает атаки, приводящие к исчерпанию памяти +Настраиваемые лимиты предотвращают злоупотребление ресурсами + +## Влияние на производительность + +Минимальные накладные расходы во время нормальной работы +Завершение работы может занять до 5 секунд больше (настраивается) +Использование памяти ограничено лимитами размера очереди +Влияние на ЦП незначительно (<1% увеличение) diff --git a/docs/tech-specs/import-export-graceful-shutdown.sw.md b/docs/tech-specs/import-export-graceful-shutdown.sw.md new file mode 100644 index 00000000..cc995f89 --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.sw.md @@ -0,0 +1,738 @@ +--- +layout: default +title: "Vipimo vya Kiufundi vya Uanzishaji na Kukomesha Kazi kwa Ufasaha (Import/Export)" +parent: "Swahili (Beta)" +--- + +# Vipimo vya Kiufundi vya Uanzishaji na Kukomesha Kazi kwa Ufasaha (Import/Export) + +> **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. + +## Tatizo + +Hivi sasa, mlango wa TrustGraph unapoteza ujumbe wakati wa kufunga muunganisho wa websocket katika operesheni za uanzishaji na kukomesha kazi. Hii hutokea kwa sababu ya migogoro ambapo ujumbe unaendelea hutupwa kabla ya kufika kwa lengo lake (mifereji ya Pulsar kwa uanzishaji, wateja wa websocket kwa kukomesha kazi). + +### Masuala ya Upande wa Uanzishaji +1. Picha ya folyo ya `asyncio.Queue` ya mchapishaji haijafunguliwa wakati wa kukomesha kazi. +2. Websocket hufungwa kabla ya kuhakikisha kwamba ujumbe uliopangwa kufika kwenye Pulsar. +<<<<<<< HEAD +3. Hakuna mfumo wa uthibitisho wa uwasilishaji wa ujumbe kwa mafanikio. + +### Masuala ya Upande wa Kukomesha Kazi +1. Ujumbe unaidhinishwa katika Pulsar kabla ya uwasilishaji wa mafanikio kwa wateja. +2. Muda uliopangwa (timeouts) husababisha kupotea kwa ujumbe wakati mifereji imejaa. +3. Hakuna mfumo wa kudhibiti kasi (backpressure) wa kushughulikia watumiaji (consumers) ambao ni polepole. +======= +3. Hakuna mfumo wa utambuzi kwa uwasilishaji wa ujumbe unaofanikiwa. + +### Masuala ya Upande wa Kukomesha Kazi +1. Ujumbe hutambuliwa katika Pulsar kabla ya uwasilishaji wa mafanikio kwa wateja. +2. Muda uliopangwa (timeouts) husababisha kupotea kwa ujumbe wakati mifereji imejaa. +3. Hakuna mfumo wa kudhibiti kasi (backpressure) kwa kushughulikia watumiaji (consumers) ambao ni polepole. +>>>>>>> 82edf2d (New md files from RunPod) +4. Vituo vingi vya kuhifadhi ambapo data inaweza kupotea. + +## Muhtasari wa Muundo + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## Marekebisho Yanayopendekezwa + +### 1. Maboresho ya Mchapishaji (Upande wa Uingizaji) + +#### A. Kusafisha Kina Kesi ya Mfululizo + +**Faili**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**Manufaa Muhimu ya Ubunifu:** +**Eneo Moja la Kutuma:** Wito wote wa `producer.send()` hutokea katika sehemu moja ndani ya mbinu ya `run()`. +<<<<<<< HEAD +**Mashine ya Hali Safi:** Hali tatu wazi - inafanya kazi, inatakatishwa, imesimama. +**Ulinzi wa Muda:** Haingii katika hali ya kukwama kwa muda usio na kikomo wakati wa utaratibu wa utakatishaji. +**Ufuatiliaji Bora:** Uandikaji wazi wa maendeleo ya utaratibu wa utakatishaji na mabadiliko ya hali. +**Kukataa kwa Ujumbe (Hiari):** Inaweza kukataa ujumbe mpya wakati wa awamu ya kuzima. +======= +**Mashine ya Hali Safi:** Hali tatu wazi - inafanya kazi, inachosha, imesimama. +**Ulinzi wa Muda:** Haitemei kwa muda usio na kikomo wakati wa kuchosha. +**Ufuatiliaji Bora:** Uandikaji wazi wa maendeleo ya kuchosha na mabadiliko ya hali. +**Kukataa Ujumbe wa Hiari:** Inaweza kukataa ujumbe mpya wakati wa awamu ya kuzima. +>>>>>>> 82edf2d (New md files from RunPod) + +#### B. Mpangilio Ulioboreshwa wa Kuzima + +**Faili:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. Maboresho kwa Wateja (Upande wa Uhamisho) + +#### A. Mfumo Uliounganishwa wa Utoaji + +**Faili**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**Manufaa Muhimu ya Ubunifu (kulingana na mtindo wa Mchapishaji):** +**Eneo Moja la Ufuatiliaji**: Ufuatiliaji wote wa ujumbe hutokea katika njia ya `run()` +<<<<<<< HEAD +**Mashine Safi ya Hali**: Hali tatu wazi - inafanya kazi, inachosha, imesimama +**Kusitisha Wakati wa Kuchosha**: Inasimamisha kupokea ujumbe mpya kutoka Pulsar wakati inachosha folyo zilizopo +**Ulinzi wa Muda**: Haingii katika hali ya kukwama kwa muda usio na kikomo wakati wa kuchosha +======= +**Mashine ya Hali Safi**: Hali tatu wazi - inafanya kazi, inatakatishwa, imesimama +**Kusitisha Wakati wa Kufyatua**: Inasimamisha kupokea ujumbe mpya kutoka Pulsar wakati wa kufyatua folyo zilizopo +**Ulinzi wa Muda**: Haingii katika hali ya kukamatwa kwa muda usio na kikomo wakati wa kufyatua +>>>>>>> 82edf2d (New md files from RunPod) +**Usafi Sawa**: Inatambua vibaya ujumbe wowote usiofikishwa wakati wa kuzima + +#### B. Maboresho ya Kidhibiti cha Uhamisho + +**Faili**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. Maboresho ya Kawaida ya Soketi + +**Faili**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## Chaguo za Usanidi + +Ongeza usaidizi wa usanidi ili kurekebisha tabia: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## Mkakati wa Majaribio + +### Majaribio ya Kitengo + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### Majaribio ya Uunganishaji + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +<<<<<<< HEAD +## Mpango wa Utendaji +======= +## Mpango wa Utumizaji +>>>>>>> 82edf2d (New md files from RunPod) + +### Awamu ya 1: Marekebisho Muhimu (Wiki ya 1) +Marekebisho ya muda wa utambuzi wa mshabiki (kuzuia upotevu wa ujumbe) +Ongeza utaratibu wa kusafisha folyo ya mchapishaji +<<<<<<< HEAD +Tuma kwenye mazingira ya majaribio + +### Awamu ya 2: Kusitisha kwa Ufasaha (Wiki ya 2) +Lenga kusitisha kwa ufasaha +Ongeza mikakati ya shinikizo nyuma +======= +Toa toleo kwenye mazingira ya majaribio + +### Awamu ya 2: Kusitisha kwa Ufasaha (Wiki ya 2) +Lenga utaratibu wa usitishaji +Ongeza mikakati ya kupunguza mzigo +>>>>>>> 82edf2d (New md files from RunPod) +Vipimo vya utendaji + +### Awamu ya 3: Ufuatiliaji na Urekebishaji (Wiki ya 3) +Ongeza vipimo vya kina ya folyo +Ongeza arifa za upotevu wa ujumbe +Rekebisha maadili ya muda wa kusubiri kulingana na data ya uzalishaji + +## Ufuatiliaji na Arifa + +### Vipimo vya Kufuata +`publisher.queue.depth` - Ukubwa wa sasa wa folyo ya mchapishaji +`publisher.messages.dropped` - Ujumbe uliopotea wakati wa kusitisha +`subscriber.messages.negatively_acknowledged` - Utoaji ambao haujafanikiwa +<<<<<<< HEAD +`websocket.graceful_shutdowns` - Kusitisha kwa ufasaha ambavyo vimefanikiwa +`websocket.forced_shutdowns` - Kusitisha kwa nguvu/kwa muda mrefu +======= +`websocket.graceful_shutdowns` - Usitishaji wa ufasaha ambao umefanikiwa +`websocket.forced_shutdowns` - Usitishaji wa lazima/wa muda +>>>>>>> 82edf2d (New md files from RunPod) + +### Arifa +Kina cha folyo ya mchapishaji > 80% ya uwezo +Upotevu wowote wa ujumbe wakati wa kusitisha +Kiwango cha kukataa cha mshabiki > 1% +<<<<<<< HEAD +Muda wa kusitisha umepita +======= +Muda wa kusitisha ambao umevuka +>>>>>>> 82edf2d (New md files from RunPod) + +## Ulinganifu na Mifumo ya Zamani + +Marekebisho yote yanahifadhi ulinganifu na mifumo ya zamani: +Tabia ya kawaida haibadiliki bila usanidi +Uwekaji wa sasa unaendelea kufanya kazi +Kupungua kwa utendaji ikiwa vipengele vipya havipatikani + +## Masuala ya Usalama + +Vipengele vipya vya mashambulizi haviongezwi +<<<<<<< HEAD +Shinikizo nyuma huzuia mashambulizi ya kutumia kumbukumbu nyingi +Mipaka inayoweza kusanidiwa huzuia matumizi mabaya ya rasilimali +======= +Kupunguza mzigo huzuia mashambulizi ya kutokwa na kumbukumbu +Mipaka inayoweza kusanidiwa inazuia unyonyaji wa rasilimali +>>>>>>> 82edf2d (New md files from RunPod) + +## Athari za Utendaji + +Uwezekano mdogo wakati wa operesheni ya kawaida +Kusitisha kunaweza kuchukua sekunde 5 zaidi (inaweza kusanidiwa) +Matumizi ya kumbukumbu yanapingika na mipaka ya ukubwa wa folyo +Athari ya CPU ni ndogo (<1% ya ongezeko) diff --git a/docs/tech-specs/import-export-graceful-shutdown.tr.md b/docs/tech-specs/import-export-graceful-shutdown.tr.md new file mode 100644 index 00000000..5b35b1bc --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.tr.md @@ -0,0 +1,729 @@ +--- +layout: default +title: "İçe/Dışa Aktarma, Zarif Kapanış Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# İçe/Dışa Aktarma, Zarif Kapanış 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. + +## Problem Tanımı + +<<<<<<< HEAD +TrustGraph ağ geçidi, hem içe aktarma hem de dışa aktarma işlemlerinde websocket kapanışı sırasında mesaj kaybı yaşamaktadır. Bu, aktarım halindeki mesajların, hedeflerine (içe aktarmalar için Pulsar kuyrukları, dışa aktarmalar için websocket istemcileri) ulaşmadan önce atıldığı yarış koşulları nedeniyle oluşmaktadır. + +### İçe Aktarma Tarafındaki Sorunlar +1. Yayınlayıcının asyncio.Queue tamponu, kapanışta boşaltılmamaktadır. +======= +TrustGraph geçidi, hem içe hem de dışa aktarma işlemlerinde websocket kapanması sırasında mesaj kaybı yaşamaktadır. Bu, aktarım halindeki mesajların, hedeflerine (içe aktarmalar için Pulsar kuyrukları, dışa aktarmalar için websocket istemcileri) ulaşmadan önce atıldığı yarış koşulları nedeniyle oluşmaktadır. + +### İçe Aktarma Tarafındaki Sorunlar +1. Yayınlayıcının asyncio.Queue tamponu, kapanmada boşaltılmamaktadır. +>>>>>>> 82edf2d (New md files from RunPod) +2. Websocket, kuyruğa alınmış mesajların Pulsar'a ulaşmasını sağladıktan sonra kapanmaktadır. +3. Başarılı mesaj teslimatı için bir onay mekanizması bulunmamaktadır. + +### Dışa Aktarma Tarafındaki Sorunlar +1. Mesajlar, istemcilere başarılı bir şekilde teslim edilmeden önce Pulsar'da onaylanmaktadır. +2. Sabit kodlu zaman aşımı değerleri, kuyruklar dolduğunda mesaj kayıplarına neden olmaktadır. +3. Yavaş tüketicileri işlemek için bir geri basınç mekanizması bulunmamaktadır. +<<<<<<< HEAD +4. Verilerin kaybolabileceği birden fazla tampon noktası bulunmaktadır. +======= +4. Verilerin kaybolabileceği birden fazla tamponlama noktası bulunmaktadır. +>>>>>>> 82edf2d (New md files from RunPod) + +## Mimari Genel Bakış + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## Önerilen Çözümler + +### 1. Yayıncı İyileştirmeleri (İçe Aktarma Tarafı) + +#### A. Zarif Kuyruk Boşaltma + +**Dosya**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**Temel Tasarım Avantajları:** +**Tek Gönderme Konumu**: Tüm `producer.send()` çağrıları, `run()` metodu içinde tek bir yerde gerçekleşir. +**Temiz Durum Makinesi**: Üç açık durum - çalışıyor, boşaltılıyor, durdurulmuş. +**Zaman Aşımı Koruması**: Boşaltma sırasında sonsuza kadar takılmayacaktır. +**Daha İyi Gözlemlenebilirlik**: Boşaltma ilerlemesi ve durum geçişlerinin açık bir şekilde günlüğe kaydedilmesi. +<<<<<<< HEAD +**İsteğe Bağlı Mesaj Reddi**: Kapatma aşamasında yeni mesajları reddedebilir. +======= +**İsteğe Bağlı Mesaj Reddi**: Kapatma aşamasında yeni mesajları reddetme imkanı. +>>>>>>> 82edf2d (New md files from RunPod) + +#### B. İyileştirilmiş Kapatma Sırası + +**Dosya**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. Abonelik İyileştirmeleri (Dışa Aktarma Tarafı) + +#### A. Entegre Boşaltma Modeli + +**Dosya**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**Temel Tasarım Avantajları (Yayıncı modeline uygun):** +**Tek İşlem Konumu**: Tüm mesaj işleme, `run()` metodu içinde gerçekleşir. +<<<<<<< HEAD +**Temiz Durum Makinesi**: Üç açık durum - çalışıyor, boşaltma, durdurulmuş. +**Boşaltma Sırasında Duraklama**: Mevcut kuyrukları boşaltırken, Pulsar'dan yeni mesaj kabul etmeyi durdurur. +**Zaman Aşımı Koruması**: Boşaltma sırasında sonsuza kadar takılmayacaktır. +**Doğru Temizleme**: Kapatma sırasında teslim edilmemiş mesajlar varsa, bunlara ilişkin olumsuz onaylar gönderilir. +======= +**Temiz Durum Makinesi**: Üç açık durum - çalışıyor, boşaltılıyor, durdurulmuş. +**Boşaltma Sırasında Duraklama**: Mevcut kuyrukları boşaltırken, Pulsar'dan yeni mesaj kabul etmeyi durdurur. +**Zaman Aşımı Koruması**: Boşaltma sırasında sonsuza kadar takılmayacaktır. +**Doğru Temizleme**: Kapatma sırasında teslim edilmemiş herhangi bir mesaj için olumsuz onay gönderir. +>>>>>>> 82edf2d (New md files from RunPod) + +#### B. Dışa Aktarma İşleyici İyileştirmeleri + +**Dosya**: `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. Soket Seviyesindeki İyileştirmeler + +**Dosya**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## Yapılandırma Seçenekleri + +Davranışı ayarlamak için yapılandırma desteği ekleyin: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## Test Stratejisi + +### Birim Testleri + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### Entegrasyon Testleri + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## Dağıtım Planı + +### Aşama 1: Kritik Düzeltmeler (1. Hafta) +Abonelik onayı zamanlaması düzeltildi (mesaj kaybını önler) +Yayıncı kuyruğu boşaltma özelliği eklendi +Staging ortamına dağıtıldı + +### Aşama 2: Düzenli Kapanış (2. Hafta) +Kapanış koordinasyonu uygulandı +Geri basınç stratejileri eklendi +Performans testi + +### Aşama 3: İzleme ve Ayarlama (3. Hafta) +Kuyruk derinlikleri için metrikler eklendi +Mesaj kayıpları için uyarılar eklendi +Üretim verilerine göre zaman aşımı değerleri ayarlandı + +## İzleme ve Uyarılar + +### İzlenecek Metrikler +`publisher.queue.depth` - Mevcut yayıncı kuyruğu boyutu +`publisher.messages.dropped` - Kapanma sırasında kaybolan mesajlar +`subscriber.messages.negatively_acknowledged` - Başarısız teslimatlar +`websocket.graceful_shutdowns` - Başarılı düzenli kapanışlar +`websocket.forced_shutdowns` - Zorlanmış/zaman aşımı kapanışları + +### Uyarılar +<<<<<<< HEAD +Yayıncı kuyruğu derinliği %80 kapasitenin üzerinde +Kapanma sırasında herhangi bir mesaj kaybı +Abonelik olumsuz onay oranı > %1 +Kapanış zaman aşımı aşıldı +======= +Yayıncı kuyruğu derinliği %80 kapasiteyi aştığında +Kapanma sırasında herhangi bir mesaj kaybı olduğunda +Abonelik olumsuz onay oranı > %1 olduğunda +Kapanış zaman aşımı aşıldığında +>>>>>>> 82edf2d (New md files from RunPod) + +## Geriye Dönük Uyumluluk + +Tüm değişiklikler geriye dönük uyumluluğu korur: +<<<<<<< HEAD +Yapılandırma olmadan varsayılan davranış değişmedi +Mevcut dağıtımlar çalışmaya devam ediyor +Yeni özellikler kullanılamıyorsa, kademeli bozulma + +## Güvenlik Hususları + +Herhangi bir yeni saldırı vektörü tanıtılmadı +======= +Yapılandırma olmadan varsayılan davranış değişmez +Mevcut dağıtımlar çalışmaya devam eder +Yeni özellikler kullanılamadığında, düzgün bir şekilde performans düşüşü olur + +## Güvenlik Hususları + +Herhangi bir yeni saldırı vektörü tanıtılmamıştır +>>>>>>> 82edf2d (New md files from RunPod) +Geri basınç, bellek tükenmesi saldırılarını önler +Yapılandırılabilir sınırlar, kaynak kötüye kullanımını önler + +## Performans Etkisi + +Normal çalışma sırasında minimum ek yük +Kapanma, 5 saniyeye kadar daha uzun sürebilir (yapılandırılabilir) +Bellek kullanımı, kuyruk boyutu sınırları ile sınırlıdır +CPU etkisi ihmal edilebilir (<%1 artış) diff --git a/docs/tech-specs/import-export-graceful-shutdown.zh-cn.md b/docs/tech-specs/import-export-graceful-shutdown.zh-cn.md new file mode 100644 index 00000000..6ce90311 --- /dev/null +++ b/docs/tech-specs/import-export-graceful-shutdown.zh-cn.md @@ -0,0 +1,725 @@ +--- +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. + +## 问题陈述 + +<<<<<<< HEAD +TrustGraph 网关在导入和导出操作中,在 WebSocket 连接关闭时,目前存在消息丢失的问题。 这是由于存在竞争条件,导致正在传输的消息在到达目的地之前被丢弃(对于导入,是丢弃到 Pulsar 队列的消息;对于导出,是丢弃到 WebSocket 客户端的消息)。 + +### 导入端问题 +1. 发布者的 asyncio.Queue 缓冲区在关闭时未被清空 +2. 在确保所有排队的消息到达 Pulsar 之前,WebSocket 连接关闭 +======= +TrustGraph 网关在导入和导出操作的 WebSocket 关闭过程中,目前存在消息丢失的问题。 这是由于存在竞争条件,导致正在传输的消息在到达目的地之前被丢弃(对于导入,是丢弃到 Pulsar 队列的消息;对于导出,是丢弃到 WebSocket 客户端的消息)。 + +### 导入端问题 +1. 发布者的 asyncio.Queue 缓冲区在关闭时未被清空 +2. 在确保所有排队的消息到达 Pulsar 之前,WebSocket 被关闭 +>>>>>>> 82edf2d (New md files from RunPod) +3. 没有用于确认消息成功传递的机制 + +### 导出端问题 +1. 消息在成功传递到客户端之前,已在 Pulsar 中得到确认 +2. 预定义的超时时间会导致队列已满时消息丢失 +3. 没有用于处理慢速消费者的反压机制 +4. 存在多个缓冲区,数据可能在此处丢失 + +## 架构概述 + +``` +Import Flow: +Client -> Websocket -> TriplesImport -> Publisher -> Pulsar Queue + +Export Flow: +Pulsar Queue -> Subscriber -> TriplesExport -> Websocket -> Client +``` + +## 建议的修复方案 + +### 1. 发布者改进(导入端) + +#### A. 优雅的队列清空 + +**文件**: `trustgraph-base/trustgraph/base/publisher.py` + +```python +class Publisher: + def __init__(self, client, topic, schema=None, max_size=10, + chunking_enabled=True, drain_timeout=5.0): + self.client = client + self.topic = topic + self.schema = schema + self.q = asyncio.Queue(maxsize=max_size) + self.chunking_enabled = chunking_enabled + self.running = True + self.draining = False # New state for graceful shutdown + self.task = None + self.drain_timeout = drain_timeout + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + try: + producer = self.client.create_producer( + topic=self.topic, + schema=JsonSchema(self.schema), + chunking_enabled=self.chunking_enabled, + ) + + drain_end_time = None + + while self.running or self.draining: + try: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Publisher entering drain mode, timeout={self.drain_timeout}s") + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + if not self.q.empty(): + logger.warning(f"Drain timeout reached with {self.q.qsize()} messages remaining") + self.draining = False + break + + # Calculate wait timeout based on mode + if self.draining: + # Shorter timeout during draining to exit quickly when empty + timeout = min(0.1, drain_end_time - time.time()) + else: + # Normal operation timeout + timeout = 0.25 + + # Get message from queue + id, item = await asyncio.wait_for( + self.q.get(), + timeout=timeout + ) + + # Send the message (single place for sending) + if id: + producer.send(item, { "id": id }) + else: + producer.send(item) + + except asyncio.TimeoutError: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + except asyncio.QueueEmpty: + # If draining and queue is empty, we're done + if self.draining and self.q.empty(): + logger.info("Publisher queue drained successfully") + self.draining = False + break + continue + + # Flush producer before closing + if producer: + producer.flush() + producer.close() + + except Exception as e: + logger.error(f"Exception in publisher: {e}", exc_info=True) + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def send(self, id, item): + """Send still works normally - just adds to queue""" + if self.draining: + # Optionally reject new messages during drain + raise RuntimeError("Publisher is shutting down, not accepting new messages") + await self.q.put((id, item)) +``` + +**主要设计优势:** +**单一发送位置:** 所有 `producer.send()` 调用都发生在 `run()` 方法内的单一位置。 +**清晰的状态机:** 三个明确的状态 - 运行中、正在排空、已停止。 +**超时保护:** 在排空过程中不会无限期挂起。 +**更好的可观察性:** 清晰地记录排空进度和状态转换。 +**可选的消息拒绝:** 可以在关闭阶段拒绝新的消息。 + +#### B. 改进的关闭顺序 + +**文件:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_import.py` + +```python +class TriplesImport: + async def destroy(self): + """Enhanced destroy with proper shutdown order""" + # Step 1: Stop accepting new messages + self.running.stop() + + # Step 2: Wait for publisher to drain its queue + logger.info("Draining publisher queue...") + await self.publisher.stop() + + # Step 3: Close websocket only after queue is drained + if self.ws: + await self.ws.close() +``` + +### 2. 订阅者改进(导出端) + +#### A. 集成排空模式 + +**文件**: `trustgraph-base/trustgraph/base/subscriber.py` + +```python +class Subscriber: + def __init__(self, client, topic, subscription, consumer_name, + schema=None, max_size=100, metrics=None, + backpressure_strategy="block", drain_timeout=5.0): + # ... existing init ... + self.backpressure_strategy = backpressure_strategy + self.running = True + self.draining = False # New state for graceful shutdown + self.drain_timeout = drain_timeout + self.pending_acks = {} # Track messages awaiting delivery + + async def stop(self): + """Initiate graceful shutdown with draining""" + self.running = False + self.draining = True + + if self.task: + # Wait for run() to complete draining + await self.task + + async def run(self): + """Enhanced run method with integrated draining logic""" + while self.running or self.draining: + if self.metrics: + self.metrics.state("stopped") + + try: + self.consumer = self.client.subscribe( + topic = self.topic, + subscription_name = self.subscription, + consumer_name = self.consumer_name, + schema = JsonSchema(self.schema), + ) + + if self.metrics: + self.metrics.state("running") + + logger.info("Subscriber running...") + drain_end_time = None + + while self.running or self.draining: + # Start drain timeout when entering drain mode + if self.draining and drain_end_time is None: + drain_end_time = time.time() + self.drain_timeout + logger.info(f"Subscriber entering drain mode, timeout={self.drain_timeout}s") + + # Stop accepting new messages from Pulsar during drain + self.consumer.pause_message_listener() + + # Check drain timeout + if self.draining and time.time() > drain_end_time: + async with self.lock: + total_pending = sum( + q.qsize() for q in + list(self.q.values()) + list(self.full.values()) + ) + if total_pending > 0: + logger.warning(f"Drain timeout reached with {total_pending} messages in queues") + self.draining = False + break + + # Check if we can exit drain mode + if self.draining: + async with self.lock: + all_empty = all( + q.empty() for q in + list(self.q.values()) + list(self.full.values()) + ) + if all_empty and len(self.pending_acks) == 0: + logger.info("Subscriber queues drained successfully") + self.draining = False + break + + # Process messages only if not draining + if not self.draining: + try: + msg = await asyncio.to_thread( + self.consumer.receive, + timeout_millis=250 + ) + except _pulsar.Timeout: + continue + except Exception as e: + logger.error(f"Exception in subscriber receive: {e}", exc_info=True) + raise e + + if self.metrics: + self.metrics.received() + + # Process the message + await self._process_message(msg) + else: + # During draining, just wait for queues to empty + await asyncio.sleep(0.1) + + except Exception as e: + logger.error(f"Subscriber exception: {e}", exc_info=True) + + finally: + # Negative acknowledge any pending messages + for msg in self.pending_acks.values(): + self.consumer.negative_acknowledge(msg) + self.pending_acks.clear() + + if self.consumer: + self.consumer.unsubscribe() + self.consumer.close() + self.consumer = None + + if self.metrics: + self.metrics.state("stopped") + + if not self.running and not self.draining: + return + + # If handler drops out, sleep a retry + await asyncio.sleep(1) + + async def _process_message(self, msg): + """Process a single message with deferred acknowledgment""" + # Store message for later acknowledgment + msg_id = str(uuid.uuid4()) + self.pending_acks[msg_id] = msg + + try: + id = msg.properties()["id"] + except: + id = None + + value = msg.value() + delivery_success = False + + async with self.lock: + # Deliver to specific subscribers + if id in self.q: + delivery_success = await self._deliver_to_queue( + self.q[id], value + ) + + # Deliver to all subscribers + for q in self.full.values(): + if await self._deliver_to_queue(q, value): + delivery_success = True + + # Acknowledge only on successful delivery + if delivery_success: + self.consumer.acknowledge(msg) + del self.pending_acks[msg_id] + else: + # Negative acknowledge for retry + self.consumer.negative_acknowledge(msg) + del self.pending_acks[msg_id] + + async def _deliver_to_queue(self, queue, value): + """Deliver message to queue with backpressure handling""" + try: + if self.backpressure_strategy == "block": + # Block until space available (no timeout) + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_oldest": + # Drop oldest message if queue full + if queue.full(): + try: + queue.get_nowait() + if self.metrics: + self.metrics.dropped() + except asyncio.QueueEmpty: + pass + await queue.put(value) + return True + + elif self.backpressure_strategy == "drop_new": + # Drop new message if queue full + if queue.full(): + if self.metrics: + self.metrics.dropped() + return False + await queue.put(value) + return True + + except Exception as e: + logger.error(f"Failed to deliver message: {e}") + return False +``` + +**主要设计优势(与发布者模式匹配):** +<<<<<<< HEAD +**单一处理位置:** 所有消息处理都在 `run()` 方法中进行。 +======= +**单一处理位置:** 所有消息处理都发生在 `run()` 方法中。 +>>>>>>> 82edf2d (New md files from RunPod) +**清晰的状态机:** 三个明确的状态 - 运行中、正在排空、已停止。 +**排空期间暂停:** 在排空现有队列时,停止从 Pulsar 接收新消息。 +**超时保护:** 在排空过程中不会无限期挂起。 +**正确的清理:** 在关闭时,会对任何未发送的消息进行否定确认。 + +#### B. 导出处理程序改进 + +**文件:** `trustgraph-flow/trustgraph/gateway/dispatch/triples_export.py` + +```python +class TriplesExport: + async def destroy(self): + """Enhanced destroy with graceful shutdown""" + # Step 1: Signal stop to prevent new messages + self.running.stop() + + # Step 2: Wait briefly for in-flight messages + await asyncio.sleep(0.5) + + # Step 3: Unsubscribe and stop subscriber (triggers queue drain) + if hasattr(self, 'subs'): + await self.subs.unsubscribe_all(self.id) + await self.subs.stop() + + # Step 4: Close websocket last + if self.ws and not self.ws.closed: + await self.ws.close() + + async def run(self): + """Enhanced run with better error handling""" + self.subs = Subscriber( + client = self.pulsar_client, + topic = self.queue, + consumer_name = self.consumer, + subscription = self.subscriber, + schema = Triples, + backpressure_strategy = "block" # Configurable + ) + + await self.subs.start() + + self.id = str(uuid.uuid4()) + q = await self.subs.subscribe_all(self.id) + + consecutive_errors = 0 + max_consecutive_errors = 5 + + while self.running.get(): + try: + resp = await asyncio.wait_for(q.get(), timeout=0.5) + await self.ws.send_json(serialize_triples(resp)) + consecutive_errors = 0 # Reset on success + + except asyncio.TimeoutError: + continue + + except queue.Empty: + continue + + except Exception as e: + logger.error(f"Exception sending to websocket: {str(e)}") + consecutive_errors += 1 + + if consecutive_errors >= max_consecutive_errors: + logger.error("Too many consecutive errors, shutting down") + break + + # Brief pause before retry + await asyncio.sleep(0.1) + + # Graceful cleanup handled in destroy() +``` + +### 3. Socket 级别改进 + +**文件**: `trustgraph-flow/trustgraph/gateway/endpoint/socket.py` + +```python +class SocketEndpoint: + async def listener(self, ws, dispatcher, running): + """Enhanced listener with graceful shutdown""" + async for msg in ws: + if msg.type == WSMsgType.TEXT: + await dispatcher.receive(msg) + continue + elif msg.type == WSMsgType.BINARY: + await dispatcher.receive(msg) + continue + else: + # Graceful shutdown on close + logger.info("Websocket closing, initiating graceful shutdown") + running.stop() + + # Allow time for dispatcher cleanup + await asyncio.sleep(1.0) + break + + async def handle(self, request): + """Enhanced handler with better cleanup""" + # ... existing setup code ... + + try: + async with asyncio.TaskGroup() as tg: + running = Running() + + dispatcher = await self.dispatcher( + ws, running, request.match_info + ) + + worker_task = tg.create_task( + self.worker(ws, dispatcher, running) + ) + + lsnr_task = tg.create_task( + self.listener(ws, dispatcher, running) + ) + + except ExceptionGroup as e: + logger.error("Exception group occurred:", exc_info=True) + + # Attempt graceful dispatcher shutdown + try: + await asyncio.wait_for( + dispatcher.destroy(), + timeout=5.0 + ) + except asyncio.TimeoutError: + logger.warning("Dispatcher shutdown timed out") + except Exception as de: + logger.error(f"Error during dispatcher cleanup: {de}") + + except Exception as e: + logger.error(f"Socket exception: {e}", exc_info=True) + + finally: + # Ensure dispatcher cleanup + if dispatcher and hasattr(dispatcher, 'destroy'): + try: + await dispatcher.destroy() + except: + pass + + # Ensure websocket is closed + if ws and not ws.closed: + await ws.close() + + return ws +``` + +## 配置选项 + +添加配置支持,用于调整行为: + +```python +# config.py +class GracefulShutdownConfig: + # Publisher settings + PUBLISHER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + PUBLISHER_FLUSH_TIMEOUT = 2.0 # Producer flush timeout + + # Subscriber settings + SUBSCRIBER_DRAIN_TIMEOUT = 5.0 # Seconds to wait for queue drain + BACKPRESSURE_STRATEGY = "block" # Options: "block", "drop_oldest", "drop_new" + SUBSCRIBER_MAX_QUEUE_SIZE = 100 # Maximum queue size before backpressure + + # Socket settings + SHUTDOWN_GRACE_PERIOD = 1.0 # Seconds to wait for graceful shutdown + MAX_CONSECUTIVE_ERRORS = 5 # Maximum errors before forced shutdown + + # Monitoring + LOG_QUEUE_STATS = True # Log queue statistics on shutdown + METRICS_ENABLED = True # Enable metrics collection +``` + +## 测试策略 + +### 单元测试 + +```python +async def test_publisher_queue_drain(): + """Verify Publisher drains queue on shutdown""" + publisher = Publisher(...) + + # Fill queue with messages + for i in range(10): + await publisher.send(f"id-{i}", {"data": i}) + + # Stop publisher + await publisher.stop() + + # Verify all messages were sent + assert publisher.q.empty() + assert mock_producer.send.call_count == 10 + +async def test_subscriber_deferred_ack(): + """Verify Subscriber only acks on successful delivery""" + subscriber = Subscriber(..., backpressure_strategy="drop_new") + + # Fill queue to capacity + queue = await subscriber.subscribe("test") + for i in range(100): + await queue.put({"data": i}) + + # Try to add message when full + msg = create_mock_message() + await subscriber._process_message(msg) + + # Verify negative acknowledgment + assert msg.negative_acknowledge.called + assert not msg.acknowledge.called +``` + +### 集成测试 + +```python +async def test_import_graceful_shutdown(): + """Test import path handles shutdown gracefully""" + # Setup + import_handler = TriplesImport(...) + await import_handler.start() + + # Send messages + messages = [] + for i in range(100): + msg = {"metadata": {...}, "triples": [...]} + await import_handler.receive(msg) + messages.append(msg) + + # Shutdown while messages in flight + await import_handler.destroy() + + # Verify all messages reached Pulsar + received = await pulsar_consumer.receive_all() + assert len(received) == 100 + +async def test_export_no_message_loss(): + """Test export path doesn't lose acknowledged messages""" + # Setup Pulsar with test messages + for i in range(100): + await pulsar_producer.send({"data": i}) + + # Start export handler + export_handler = TriplesExport(...) + export_task = asyncio.create_task(export_handler.run()) + + # Receive some messages + received = [] + for _ in range(50): + msg = await websocket.receive() + received.append(msg) + + # Force shutdown + await export_handler.destroy() + + # Continue receiving until websocket closes + while not websocket.closed: + try: + msg = await websocket.receive() + received.append(msg) + except: + break + + # Verify no acknowledged messages were lost + assert len(received) >= 50 +``` + +## 部署计划 + +<<<<<<< HEAD +### 第一阶段:关键修复(第一周) +修复订阅者确认时序问题(防止消息丢失) +添加发布者队列排空功能 +部署到测试环境 + +### 第二阶段:平滑关闭(第二周) +======= +### 第一阶段:关键修复 (第一周) +修复订阅者确认时序问题 (防止消息丢失) +添加发布者队列排空功能 +部署到测试环境 + +### 第二阶段:平滑关闭 (第二周) +>>>>>>> 82edf2d (New md files from RunPod) +实施关闭协调 +添加反压策略 +性能测试 + +<<<<<<< HEAD +### 第三阶段:监控与调优(第三周) +======= +### 第三阶段:监控与调优 (第三周) +>>>>>>> 82edf2d (New md files from RunPod) +添加队列深度的指标 +添加消息丢失的告警 +根据生产数据调整超时值 + +## 监控与告警 + +### 跟踪指标 +`publisher.queue.depth` - 当前发布者队列大小 +`publisher.messages.dropped` - 关闭期间丢失的消息数量 +`subscriber.messages.negatively_acknowledged` - 失败的交付 +`websocket.graceful_shutdowns` - 成功的平滑关闭 +`websocket.forced_shutdowns` - 强制/超时关闭 + +### 告警 +<<<<<<< HEAD +发布者队列深度超过 80% 的容量 +======= +发布者队列深度超过 80% 容量 +>>>>>>> 82edf2d (New md files from RunPod) +关闭期间出现任何消息丢失 +订阅者否定确认率 > 1% +关闭超时 + +## 向后兼容性 + +所有更改都保持向后兼容性: +在没有配置的情况下,默认行为保持不变 +现有部署继续正常运行 +如果新的功能不可用,则会进行优雅降级 + +## 安全注意事项 + +没有引入新的攻击向量 +反压可防止内存耗尽攻击 +可配置的限制可防止资源滥用 + +## 性能影响 + +正常运行期间的开销很小 +<<<<<<< HEAD +关闭可能需要长达 5 秒(可配置) +内存使用量受队列大小限制 +CPU 影响可以忽略不计(<1% 的增加) +======= +关闭可能需要长达 5 秒钟 (可配置) +内存使用量受队列大小限制 +CPU 影响可以忽略不计 (<1% 的增长) +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/jsonl-prompt-output.ar.md b/docs/tech-specs/jsonl-prompt-output.ar.md new file mode 100644 index 00000000..44aa7d82 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.ar.md @@ -0,0 +1,540 @@ +--- +layout: default +title: "المواصفات الفنية للإخراج بتنسيق JSONL" +parent: "Arabic (Beta)" +--- + +# المواصفات الفنية للإخراج بتنسيق JSONL + +> **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. + +## نظرة عامة + +<<<<<<< HEAD +تصف هذه المواصفات تطبيق تنسيق JSONL (JSON Lines) للإخراج +======= +تصف هذه المواصفات تنفيذ تنسيق JSONL (JSON Lines) للإخراج +>>>>>>> 82edf2d (New md files from RunPod) +في TrustGraph. يتيح JSONL استخراجًا مقاومًا للتقطيع للبيانات المنظمة من +استجابات نماذج اللغة الكبيرة (LLM)، مما يعالج المشكلات الهامة المتعلقة +بتلف مخرجات JSON array عندما تصل استجابات نماذج اللغة الكبيرة إلى حدود +الرموز المميزة للإخراج. + +<<<<<<< HEAD +يدعم هذا التطبيق حالات الاستخدام التالية: +======= +يدعم هذا التنفيذ حالات الاستخدام التالية: +>>>>>>> 82edf2d (New md files from RunPod) + +1. **الاستخراج المقاوم للتقطيع**: استخراج نتائج جزئية صالحة حتى عندما + يتم اقتطاع إخراج نموذج اللغة الكبيرة في منتصف الاستجابة. +2. **الاستخراج على نطاق واسع**: التعامل مع استخراج العديد من العناصر دون + خطر الفشل التام بسبب حدود الرموز المميزة. +3. **الاستخراج بأنواع متعددة**: دعم استخراج أنواع متعددة من الكيانات + (التعريفات، والعلاقات، والكيانات، والسمات) في طلب واحد. +4. **الإخراج المتوافق مع التدفق**: تمكين المعالجة المستقبلية التدريجية/المتزايدة + لنتائج الاستخراج. + +## الأهداف + +**التوافق مع الإصدارات السابقة**: تظل الطلبات الحالية التي تستخدم `response-type: "text"` و + `response-type: "json"` تعمل دون تعديل. +<<<<<<< HEAD +**مقاومة التقطيع**: تؤدي مخرجات نماذج اللغة الكبيرة الجزئية إلى نتائج + جزئية صالحة بدلاً من الفشل التام. +**التحقق من المخطط**: دعم التحقق من مخطط JSON للكائنات الفردية. +**الاتحادات المميزة**: دعم المخرجات ذات الأنواع المختلطة باستخدام حقل `type` + مميز. +**تغييرات API الحد الأدنى**: توسيع تكوين الطلب الحالي بنوع استجابة جديد + ومفتاح مخطط. +======= +**مقاومة التقطيع**: تؤدي المخرجات الجزئية لنماذج اللغة الكبيرة إلى نتائج + جزئية صالحة بدلاً من الفشل التام. +**التحقق من المخطط**: دعم التحقق من مخطط JSON للكائنات الفردية. +**الاتحادات المميزة**: دعم المخرجات بأنواع متعددة باستخدام حقل `type` + كـ "مميّز". +**تغييرات API قليلة**: توسيع تكوين الطلب الحالي بنوع استجابة جديد ومفتاح + مخطط. +>>>>>>> 82edf2d (New md files from RunPod) + +## الخلفية + +### البنية الحالية + +يدعم خدمة الطلبات نوعين من الاستجابات: + +1. `response-type: "text"` - استجابة نصية خام يتم إرجاعها كما هي. +2. `response-type: "json"` - JSON يتم تحليله من الاستجابة، ويتم التحقق منه مقابل + `schema` اختياري. + +التنفيذ الحالي في `trustgraph-flow/trustgraph/template/prompt_manager.py`: + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### القيود الحالية + +عندما تطلب مطالبات الاستخراج إخراجًا بتنسيق مصفوفات JSON (`[{...}, {...}, ...]`): + +**تلف بسبب الاقتطاع**: إذا وصلت LLM إلى حدود رموز الإخراج أثناء المصفوفة، يصبح + الرد بأكمله JSON غير صالح ولا يمكن تحليله. +**التحليل الكل أو لا شيء**: يجب استقبال الإخراج الكامل قبل التحليل. +**لا توجد نتائج جزئية**: يؤدي الرد المقتطع إلى عدم وجود بيانات قابلة للاستخدام. +**غير موثوق به للاستخراج الكبير**: كلما زاد عدد العناصر المستخرجة، زاد خطر الفشل. + +تعالج هذه المواصفات هذه القيود من خلال تقديم تنسيق JSONL لمطالبات +<<<<<<< HEAD +الاستخراج، حيث يكون كل عنصر مستخرج كائن JSON كامل في سطر منفصل. + + +## التصميم الفني +======= +الاستخراج، حيث يكون كل عنصر مستخرج كائن JSON كامل على سطر منفصل. + + +## التصميم التقني +>>>>>>> 82edf2d (New md files from RunPod) + +### إضافة نوع استجابة جديد + +أضف نوع استجابة جديد `"jsonl"` بالإضافة إلى الأنواع الموجودة `"text"` و `"json"`. + +#### تغييرات التكوين + +<<<<<<< HEAD +**قيمة نوع الاستجابة الجديدة:** +======= +**قيمة نوع الاستجابة الجديد:** +>>>>>>> 82edf2d (New md files from RunPod) + +``` +"response-type": "jsonl" +``` + +**تفسير المخطط:** + +يتم استخدام المفتاح `"schema"` الموجود لكل من نوعي الاستجابة `"json"` و `"jsonl"`. +يعتمد التفسير على نوع الاستجابة: + +`"json"`: يصف المخطط الاستجابة بأكملها (عادةً ما يكون مصفوفة أو كائن). +`"jsonl"`: يصف المخطط كل سطر/كائن فردي. + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +هذا يمنع التغييرات في أدوات تكوين المطالبات والمحررات. + +### مواصفات تنسيق JSONL + +#### الاستخراج البسيط + +بالنسبة للمطالبات التي تستخرج نوعًا واحدًا من الكائنات (التعريفات، العلاقات، +الموضوعات، الصفوف)، يكون الإخراج عبارة عن كائن JSON واحد لكل سطر بدون أي غلاف: + +**تنسيق إخراج المطالبة:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +**مقارنة مع تنسيق مصفوفة JSON السابق:** +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +إذا قام نموذج اللغة الكبير بقطع النص بعد السطر الثاني، فإن تنسيق مصفوفة JSON ينتج عنه JSON غير صالح، +<<<<<<< HEAD +بينما ينتج عن JSONL كائنان صالحان. + +#### استخراج أنواع مختلطة (الاتحادات المميزة) + +بالنسبة إلى التعليمات التي تستخرج أنواعًا متعددة من الكائنات (مثل التعريفات والأمثلة). +العلاقات، أو الكيانات، والعلاقات، والخصائص)، استخدم `"type"` +الحقل كعامل تمييز: +======= +بينما ينتج عن JSONL كائني JSON صالحين. + +#### استخراج الأنواع المختلطة (الاتحادات المميزة) + +بالنسبة إلى التعليمات التي تستخرج أنواعًا متعددة من الكائنات (مثل التعريفات والأمثلة). +العلاقات، أو الكيانات، والعلاقات، والخصائص)، استخدم `"type"` +الحقل كمعرّف: +>>>>>>> 82edf2d (New md files from RunPod) + +**تنسيق إخراج التعليمات:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**مخطط للاتحادات المميّزة يستخدم `oneOf`:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### استخراج علم المفاهيم + +لاستخراج علم المفاهيم بناءً على الكيانات والعلاقات والخصائص: + +**تنسيق إخراج التعليمات البرمجية:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### تفاصيل التنفيذ + +#### فئة المطالبة (Prompt Class) + +لا تتطلب الفئة الحالية `Prompt` أي تغييرات. يتم إعادة استخدام الحقل `schema` +لـ JSONL، ويتم تحديد تفسيره بواسطة `response_type`: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +<<<<<<< HEAD +لا توجد تغييرات مطلوبة - عملية تحميل التكوين الحالية تتعامل بالفعل مع +======= +لا توجد تغييرات مطلوبة - فإن عملية تحميل التكوين الحالية تتعامل بالفعل مع +>>>>>>> 82edf2d (New md files from RunPod) +`schema`. + +#### تحليل JSONL + +إضافة طريقة تحليل جديدة لنتائج JSONL: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### تغييرات في PromptManager.invoke + +قم بتوسيع طريقة "invoke" للتعامل مع نوع الاستجابة الجديد: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### المطالبات المتأثرة + +يجب ترحيل المطالبات التالية إلى تنسيق JSONL: + +| معرف المطالبة | الوصف | حقل النوع | +|-----------|-------------|------------| +| `extract-definitions` | استخراج الكيانات/التعريفات | لا (نوع واحد) | +| `extract-relationships` | استخراج العلاقات | لا (نوع واحد) | +| `extract-topics` | استخراج الموضوعات/التعريفات | لا (نوع واحد) | +| `extract-rows` | استخراج الصفوف المنظمة | لا (نوع واحد) | +| `agent-kg-extract` | استخراج التعريفات والعلاقات المجمعة | نعم: `"definition"`، `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | الاستخراج القائم على علم الوجود | نعم: `"entity"`، `"relationship"`، `"attribute"` | + +### تغييرات واجهة برمجة التطبيقات (API) + +#### من وجهة نظر العميل + +تحليل JSONL شفاف لمستخدمي واجهة برمجة التطبيقات (API) لخدمة المطالبات. يتم التحليل +من جانب الخادم في خدمة المطالبات، ويتم إرجاع الاستجابة عبر الحقل القياسي +`PromptResponse.object` كمصفوفة JSON مسلسلة. + +<<<<<<< HEAD +عندما يستدعي العملاء خدمة المطالبات (عبر `PromptClient.prompt()` أو ما شابه): +======= +عندما يستدعي العملاء خدمة المطالبات (عبر `PromptClient.prompt()` أو ما شابه ذلك): +>>>>>>> 82edf2d (New md files from RunPod) + +**`response-type: "json"`** مع مخطط المصفوفة → يتلقى العميل كائن Python `list` +**`response-type: "jsonl"`** → يتلقى العميل كائن Python `list` + +من وجهة نظر العميل، فإن كلا الخيارين يُرجِعان هياكل بيانات متطابقة. +الفرق يكمن بالكامل في كيفية تحليل مخرجات نموذج اللغة الكبير (LLM) من جهة الخادم: + +تنسيق مصفوفة JSON: استدعاء واحد لـ `json.loads()`؛ يفشل تمامًا إذا تم اقتطاعه. +<<<<<<< HEAD +تنسيق JSONL: تحليل سطريًا؛ ينتج عنه نتائج جزئية إذا تم اقتطاعه. +======= +تنسيق JSONL: تحليل سطرًا بسطر؛ ينتج عنه نتائج جزئية إذا تم اقتطاعه. +>>>>>>> 82edf2d (New md files from RunPod) + +هذا يعني أن التعليمات البرمجية للعميل الحالية التي تتوقع قائمة من مطالبات الاستخراج +لا تتطلب أي تغييرات عند ترحيل المطالبات من تنسيق JSON إلى تنسيق JSONL. + +#### القيمة المُرجَعة من الخادم + +بالنسبة لـ `response-type: "jsonl"`، تُرجع الطريقة `PromptManager.invoke()` +`list[dict]` تحتوي على جميع الكائنات التي تم تحليلها والتحقق من صحتها بنجاح. يتم بعد ذلك تسلسل هذه +القائمة إلى JSON لحقل `PromptResponse.object`. + +#### معالجة الأخطاء + +نتائج فارغة: تُرجع قائمة فارغة `[]` مع سجل تحذير. +فشل جزئي في التحليل: تُرجع قائمة بالكائنات التي تم تحليلها بنجاح مع + سجلات تحذير للأخطاء. +فشل كامل في التحليل: تُرجع قائمة فارغة `[]` مع سجلات تحذير. + +هذا يختلف عن `response-type: "json"` الذي يثير `RuntimeError` في حالة +فشل التحليل. السلوك المتسامح لـ JSONL مقصود لتوفير مقاومة للاقتطاع. + + +### مثال على التكوين + +مثال كامل لتكوين المطالبة: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## اعتبارات الأمان + +**التحقق من صحة الإدخال**: يستخدم تحليل JSON معيار `json.loads()` وهو آمن + ضد هجمات الحقن. +**التحقق من صحة المخطط**: يستخدم `jsonschema.validate()` لفرض المخطط. +<<<<<<< HEAD +**لا توجد مساحة هجومية جديدة**: تحليل JSONL أكثر أمانًا بشكل صارم من تحليل مصفوفة JSON +======= +**لا توجد نقاط ضعف جديدة**: تحليل JSONL أكثر أمانًا بشكل صارم من تحليل مصفوفة JSON +>>>>>>> 82edf2d (New md files from RunPod) + بسبب المعالجة سطرًا بسطر. + +## اعتبارات الأداء + +**الذاكرة**: يستخدم التحليل سطرًا بسطر ذاكرة قصوى أقل من تحميل مصفوفات JSON كاملة. + **زمن الوصول**: أداء التحليل مماثل لأداء تحليل مصفوفة JSON. +**التحقق من الصحة**: يتم تشغيل التحقق من صحة المخطط لكل كائن، مما يضيف حملًا إضافيًا ولكنه +<<<<<<< HEAD +يمكّن النتائج الجزئية في حالة فشل التحقق من الصحة. +======= +يتيح الحصول على نتائج جزئية في حالة فشل التحقق من الصحة. +>>>>>>> 82edf2d (New md files from RunPod) + +## استراتيجية الاختبار + +### اختبارات الوحدة + + +تحليل JSONL مع إدخال صالح. +تحليل JSONL مع أسطر فارغة. +تحليل JSONL مع أقسام التعليمات البرمجية بتنسيق Markdown. +تحليل JSONL مع سطر نهائي مقطوع. +تحليل JSONL مع أسطر JSON غير صالحة متداخلة. +التحقق من صحة المخطط مع اتحاد `oneOf` المميّز. +<<<<<<< HEAD +التوافق مع الإصدارات السابقة: تظل المطالبات `"text"` و `"json"` الحالية دون تغيير. +======= +التوافق مع الإصدارات السابقة: تظل المطالبات الحالية `"text"` و `"json"` دون تغيير. +>>>>>>> 82edf2d (New md files from RunPod) + +### اختبارات التكامل + +استخراج شامل مع مطالبات JSONL. +الاستخراج مع محاكاة القطع (استجابة محدودة بشكل مصطنع). +الاستخراج المختلط الأنواع مع مميز النوع. +استخراج علم الوجود مع الأنواع الثلاثة. + +<<<<<<< HEAD +### اختبارات جودة الاستخراج. +======= +### اختبارات جودة الاستخراج +>>>>>>> 82edf2d (New md files from RunPod) + +مقارنة نتائج الاستخراج: تنسيق JSONL مقابل تنسيق مصفوفة JSON. +التحقق من قدرة تحمل التقصير: ينتج عن تنسيق JSONL نتائج جزئية في الحالات التي يفشل فيها تنسيق JSON. + +## خطة الترحيل + +### المرحلة الأولى: التنفيذ + +1. تنفيذ الطريقة `parse_jsonl()` في `PromptManager`. +<<<<<<< HEAD +2. توسيع `invoke()` للتعامل مع `response-type: "jsonl"`. +======= +2. توسيع نطاق `invoke()` للتعامل مع `response-type: "jsonl"`. +>>>>>>> 82edf2d (New md files from RunPod) +3. إضافة اختبارات الوحدة. + +### المرحلة الثانية: ترحيل المطالبات + +1. تحديث المطالبة `extract-definitions` والإعدادات. +2. تحديث المطالبة `extract-relationships` والإعدادات. +3. تحديث المطالبة `extract-topics` والإعدادات. +4. تحديث المطالبة `extract-rows` والإعدادات. +5. تحديث المطالبة `agent-kg-extract` والإعدادات. +6. تحديث المطالبة `extract-with-ontologies` والإعدادات. + +### المرحلة الثالثة: التحديثات اللاحقة + +<<<<<<< HEAD +1. تحديث أي كود يستهلك نتائج الاستخراج للتعامل مع نوع الإرجاع القائمة. +2. تحديث الكود الذي يصنف الاستخراجات ذات الأنواع المختلطة باستخدام الحقل `type`. +3. تحديث الاختبارات التي تؤكد على تنسيق إخراج الاستخراج. +======= +1. تحديث أي كود يستخدم نتائج الاستخراج للتعامل مع نوع الإرجاع القائمة. +2. تحديث الكود الذي يصنف الاستخراجات ذات الأنواع المختلطة باستخدام الحقل `type`. +3. تحديث الاختبارات التي تتحقق من تنسيق إخراج الاستخراج. +>>>>>>> 82edf2d (New md files from RunPod) + +## أسئلة مفتوحة + +لا يوجد حاليًا. + +## المراجع + +التنفيذ الحالي: `trustgraph-flow/trustgraph/template/prompt_manager.py`. +مواصفات JSON Lines: https://jsonlines.org/. +مخطط JSON `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof. +المواصفة ذات الصلة: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`). diff --git a/docs/tech-specs/jsonl-prompt-output.es.md b/docs/tech-specs/jsonl-prompt-output.es.md new file mode 100644 index 00000000..69cebafc --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.es.md @@ -0,0 +1,524 @@ +--- +layout: default +title: "Especificación técnica de la salida de JSONL para prompts" +parent: "Spanish (Beta)" +--- + +# Especificación técnica de la salida de JSONL para prompts + +> **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 la implementación del formato de salida JSONL (JSON Lines) +para respuestas de prompts en TrustGraph. JSONL permite la extracción resistente a +la truncación de datos estructurados de las respuestas de los LLM, abordando problemas +críticos con las salidas de matrices JSON que se corrompen cuando las respuestas de +los LLM alcanzan los límites de tokens de salida. + +Esta implementación admite los siguientes casos de uso: + +1. **Extracción resistente a la truncación**: Extraer resultados parciales válidos + incluso cuando la salida del LLM se trunca a la mitad de la respuesta. +2. **Extracción a gran escala**: Manejar la extracción de muchos elementos sin riesgo + de fallo completo debido a los límites de tokens. +3. **Extracción de tipos mixtos**: Admitir la extracción de múltiples tipos de + entidades (definiciones, relaciones, entidades, atributos) en un solo prompt. +4. **Salida compatible con el streaming**: Permitir el procesamiento futuro de + resultados de extracción de forma incremental. + +## Objetivos + +**Compatibilidad con versiones anteriores**: Las indicaciones existentes que utilizan `response-type: "text"` y + `response-type: "json"` siguen funcionando sin modificaciones. +<<<<<<< HEAD +**Resiliencia a la truncación**: Las salidas parciales del LLM producen resultados válidos parciales +======= +**Resiliencia ante la truncación**: Las salidas parciales del LLM producen resultados válidos parciales +>>>>>>> 82edf2d (New md files from RunPod) + en lugar de un fallo completo. +**Validación de esquema**: Soporte para la validación de esquemas JSON para objetos individuales. +**Uniones discriminadas**: Soporte para salidas de tipos mixtos utilizando un campo `type` + discriminador. +**Cambios mínimos en la API**: Extiende la configuración de indicaciones existente con un nuevo + tipo de respuesta y clave de esquema. + +<<<<<<< HEAD +## Contexto +======= +## Antecedentes +>>>>>>> 82edf2d (New md files from RunPod) + +### Arquitectura actual + +El servicio de indicaciones admite dos tipos de respuesta: + +1. `response-type: "text"`: Respuesta de texto sin formato devuelta tal cual. +2. `response-type: "json"`: JSON analizado de la respuesta, validado contra + un esquema `schema` opcional. + +Implementación actual en `trustgraph-flow/trustgraph/template/prompt_manager.py`: + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### Limitaciones actuales + +Cuando las indicaciones de extracción solicitan una salida en formato de matrices JSON (`[{...}, {...}, ...]`): + +**Corrupción por truncamiento**: Si el LLM alcanza los límites de tokens de salida a la mitad de la matriz, + toda la respuesta se vuelve JSON inválido y no se puede analizar. +**Análisis todo o nada**: Debe recibir la salida completa antes de analizarla. +**Sin resultados parciales**: Una respuesta truncada produce cero datos utilizables. +**No es fiable para extracciones grandes**: Cuantos más elementos se extraen, mayor es el riesgo de fallo. + +<<<<<<< HEAD +Esta especificación aborda estas limitaciones introduciendo el formato JSONL para +======= +Esta especificación aborda estas limitaciones mediante la introducción del formato JSONL para +>>>>>>> 82edf2d (New md files from RunPod) +las indicaciones de extracción, donde cada elemento extraído es un objeto JSON completo en su +propia línea. + +## Diseño técnico + +### Extensión del tipo de respuesta + +Agregue un nuevo tipo de respuesta `"jsonl"` junto con los tipos existentes `"text"` y `"json"`. + +#### Cambios de configuración + +**Nuevo valor del tipo de respuesta:** + +``` +"response-type": "jsonl" +``` + +**Interpretación del esquema:** + +La clave existente `"schema"` se utiliza tanto para el tipo de respuesta `"json"` como para el tipo de respuesta `"jsonl"`. +La interpretación depende del tipo de respuesta: + +`"json"`: El esquema describe toda la respuesta (típicamente un array u objeto). +`"jsonl"`: El esquema describe cada línea/objeto individual. + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +Esto evita cambios en las herramientas de configuración y los editores. + +### Especificación del formato JSONL + +#### Extracción simple + +<<<<<<< HEAD +Para los prompts que extraen un solo tipo de objeto (definiciones, relaciones, +temas, filas), la salida es un objeto JSON por línea sin envoltorio: + +**Formato de salida del prompt:** +======= +Para las indicaciones que extraen un solo tipo de objeto (definiciones, relaciones, +temas, filas), la salida es un objeto JSON por línea sin envoltorio: + +**Formato de salida de la indicación:** +>>>>>>> 82edf2d (New md files from RunPod) +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +**Contraste con el formato anterior de matriz JSON:** +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +Si el modelo de lenguaje (LLM) trunca después de la línea 2, el formato de matriz JSON produce JSON inválido, +mientras que JSONL produce dos objetos válidos. + +#### Extracción de Tipos Mixtos (Uniones Discriminadas) + +<<<<<<< HEAD +Para las indicaciones que extraen múltiples tipos de objetos (por ejemplo, tanto definiciones como +======= +Para indicaciones que extraen múltiples tipos de objetos (por ejemplo, tanto definiciones como +>>>>>>> 82edf2d (New md files from RunPod) +relaciones, o entidades, relaciones y atributos), utilice un campo `"type"` +como discriminador: + +**Formato de salida de la indicación:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**Esquema para uniones discriminadas utiliza `oneOf`:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### Extracción de Ontología + +Para la extracción basada en ontologías con entidades, relaciones y atributos: + +**Formato de salida del prompt:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### Detalles de implementación + +#### Clase Prompt + +La clase `Prompt` existente no requiere cambios. El campo `schema` se reutiliza +para JSONL, y su interpretación está determinada por `response_type`: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +No se requieren cambios: la carga de configuración existente ya gestiona la +clave `schema`. + +#### Análisis de JSONL + +Agregar un nuevo método de análisis para respuestas JSONL: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### Cambios en PromptManager.invoke + +Extender el método invoke para manejar el nuevo tipo de respuesta: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### Prompts Afectados + +Los siguientes prompts deben migrarse al formato JSONL: + +| ID del Prompt | Descripción | Campo de Tipo | +|-----------|-------------|------------| +| `extract-definitions` | Extracción de entidades/definiciones | No (un solo tipo) | +| `extract-relationships` | Extracción de relaciones | No (un solo tipo) | +| `extract-topics` | Extracción de temas/definiciones | No (un solo tipo) | +| `extract-rows` | Extracción de filas estructuradas | No (un solo tipo) | +| `agent-kg-extract` | Extracción combinada de definiciones + relaciones | Sí: `"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | Extracción basada en ontología | Sí: `"entity"`, `"relationship"`, `"attribute"` | + +### Cambios en la API + +#### Perspectiva del Cliente + +El análisis JSONL es transparente para los clientes de la API del servicio de prompts. El análisis se +realiza en el servidor en el servicio de prompts, y la respuesta se devuelve a través del +campo estándar `PromptResponse.object` como una matriz JSON serializada. + +Cuando los clientes llaman al servicio de prompts (a través de `PromptClient.prompt()` o similar): + +**`response-type: "json"`** con esquema de matriz → el cliente recibe Python `list` +**`response-type: "jsonl"`** → el cliente recibe Python `list` + +Desde la perspectiva del cliente, ambos devuelven estructuras de datos idénticas. La +<<<<<<< HEAD +diferencia es completamente en cómo se analiza la salida del LLM en el servidor: + +Formato de matriz JSON: Una sola llamada a `json.loads()`; falla completamente si se trunca +Formato JSONL: Análisis línea por línea; produce resultados parciales si se trunca + +Esto significa que el código de cliente existente que espera una lista de los prompts de extracción +no requiere cambios al migrar los prompts de JSON a JSONL. +======= +diferencia radica completamente en cómo se analiza la salida del LLM en el servidor: + +Formato de matriz JSON: Una sola llamada a `json.loads()`; falla por completo si se trunca +Formato JSONL: Análisis línea por línea; produce resultados parciales si se trunca + +Esto significa que el código de cliente existente que espera una lista de los prompts de extracción +no requiere cambios al migrar los prompts del formato JSON al formato JSONL. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Valor de Retorno del Servidor + +Para `response-type: "jsonl"`, el método `PromptManager.invoke()` devuelve un +`list[dict]` que contiene todos los objetos analizados y validados correctamente. Esta +lista se serializa luego a JSON para el campo `PromptResponse.object`. + +#### Manejo de Errores + +Resultados vacíos: Devuelve una lista vacía `[]` con un registro de advertencia +Fallo parcial de análisis: Devuelve una lista de objetos analizados correctamente con + registros de advertencia para los fallos +Fallo completo de análisis: Devuelve una lista vacía `[]` con registros de advertencia + +<<<<<<< HEAD +Esto difiere de `response-type: "json"` que lanza `RuntimeError` en +======= +Esto difiere de `response-type: "json"`, que lanza `RuntimeError` en +>>>>>>> 82edf2d (New md files from RunPod) +caso de fallo de análisis. El comportamiento permisivo para JSONL es intencional para proporcionar +resistencia a la truncación. + +### Ejemplo de Configuración + +Ejemplo completo de configuración de prompt: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## Consideraciones de seguridad + +**Validación de entrada**: El análisis JSON utiliza `json.loads()` estándar, que es seguro + contra ataques de inyección. +**Validación de esquema**: Utiliza `jsonschema.validate()` para la aplicación de esquemas. +**Sin nueva superficie de ataque**: El análisis de JSONL es estrictamente más seguro que el análisis de matrices JSON + debido al procesamiento línea por línea. + +## Consideraciones de rendimiento + +**Memoria**: El análisis línea por línea utiliza menos memoria máxima que la carga de matrices JSON completas. +<<<<<<< HEAD + +**Latencia**: El rendimiento del análisis es comparable al análisis de matrices JSON. +**Validación**: La validación de esquema se ejecuta por objeto, lo que añade sobrecarga, pero + permite resultados parciales en caso de fallo de la validación. + +## Estrategia de pruebas + +======= + **Latencia**: El rendimiento del análisis es comparable al análisis de matrices JSON. +**Validación**: La validación de esquemas se ejecuta por objeto, lo que añade sobrecarga, pero +permite resultados parciales en caso de fallo de la validación. + +## Estrategia de pruebas + + +>>>>>>> 82edf2d (New md files from RunPod) +### Pruebas Unitarias + +Análisis de JSONL con entrada válida +Análisis de JSONL con líneas vacías +Análisis de JSONL con bloques de código Markdown +<<<<<<< HEAD +Análisis de JSONL con línea final truncada +Análisis de JSONL con líneas JSON inválidas intercaladas +Validación de esquema con uniones discriminadas `oneOf` +Compatibilidad hacia atrás: las indicaciones existentes `"text"` y `"json"` no se modifican +======= +Análisis de JSONL con líneas finales truncadas +Análisis de JSONL con líneas JSON inválidas intercaladas +Validación de esquema con uniones discriminadas `oneOf` +Compatibilidad con versiones anteriores: las indicaciones `"text"` y `"json"` existentes no se modifican +>>>>>>> 82edf2d (New md files from RunPod) + +### Pruebas de Integración + +Extracción de extremo a extremo con indicaciones JSONL +Extracción con truncamiento simulado (respuesta artificialmente limitada) +Extracción de tipos mixtos con discriminador de tipo +Extracción de ontología con los tres tipos + +### Pruebas de Calidad de Extracción + +Comparar los resultados de la extracción: formato JSONL frente a formato de matriz JSON. +Verificar la resistencia a la truncación: JSONL produce resultados parciales donde JSON falla. + +## Plan de Migración + +### Fase 1: Implementación + +1. Implementar el método `parse_jsonl()` en `PromptManager`. +2. Extender `invoke()` para manejar `response-type: "jsonl"`. +3. Agregar pruebas unitarias. + +### Fase 2: Migración de Prompts + +1. Actualizar el prompt y la configuración de `extract-definitions`. +2. Actualizar el prompt y la configuración de `extract-relationships`. +3. Actualizar el prompt y la configuración de `extract-topics`. +4. Actualizar el prompt y la configuración de `extract-rows`. +5. Actualizar el prompt y la configuración de `agent-kg-extract`. +6. Actualizar el prompt y la configuración de `extract-with-ontologies`. + +### Fase 3: Actualizaciones Posteriores + +1. Actualizar cualquier código que consuma los resultados de la extracción para manejar el tipo de retorno de lista. +2. Actualizar el código que categoriza las extracciones de tipos mixtos según el campo `type`. +3. Actualizar las pruebas que afirman sobre el formato de salida de la extracción. + +## Preguntas Abiertas + +Ninguna por el momento. + +## Referencias + +<<<<<<< HEAD +Implementación actual: `trustgraph-flow/trustgraph/template/prompt_manager.py`. +Especificación de JSON Lines: https://jsonlines.org/. +Esquema JSON `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof. +Especificación relacionada: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`). +======= +Implementación actual: `trustgraph-flow/trustgraph/template/prompt_manager.py` +Especificación de JSON Lines: https://jsonlines.org/ +Esquema JSON `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof +Especificación relacionada: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`) +>>>>>>> 82edf2d (New md files from RunPod) diff --git a/docs/tech-specs/jsonl-prompt-output.he.md b/docs/tech-specs/jsonl-prompt-output.he.md new file mode 100644 index 00000000..2b30a682 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.he.md @@ -0,0 +1,548 @@ +--- +layout: default +title: "מפרט טכני של פלט JSONL" +parent: "Hebrew (Beta)" +--- + +# מפרט טכני של פלט JSONL + +> **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. + +## סקירה כללית + +מפרט זה מתאר את יישום פורמט הפלט JSONL (JSON Lines) +עבור תשובות לשאילתות ב-TrustGraph. JSONL מאפשר חילוץ עמיד לקיטוע +של נתונים מובנים מתשובות של מודלי שפה גדולים (LLM), תוך התמודדות עם בעיות +<<<<<<< HEAD +קריטיות שבהן פלט מערך JSON נפגע כאשר תשובות ה-LLM מגיעות למגבלות +של מספר הטוקנים. +======= +קריטיות שבהן מערכי JSON יוצאים מכלל שימוש כאשר תשובות ה-LLM מגיעות +למגבלות מספר הטוקנים. +>>>>>>> 82edf2d (New md files from RunPod) + +יישום זה תומך בתרחישי שימוש הבאים: + +1. **חילוץ עמיד לקיטוע**: חילוץ תוצאות חלקיות ותקינות גם כאשר + פלט ה-LLM מקוטע באמצע התגובה. +2. **חילוץ בקנה מידה גדול**: טיפול בחילוץ של פריטים רבים מבלי +<<<<<<< HEAD + להסתכן בכשל מוחלט עקב מגבלות טוקנים. +======= + להסתכן בכשל מוחלט עקב מגבלות מספר הטוקנים. +>>>>>>> 82edf2d (New md files from RunPod) +3. **חילוץ מסוגים מעורבים**: תמיכה בחילוץ של סוגי ישויות מרובים + (הגדרות, קשרים, ישויות, תכונות) בשאילתה אחת. +4. **פלט תואם לסטרימינג**: אפשור עיבוד עתידי של תוצאות החילוץ + בצורה של סטרימינג/הדרגתית. + +## מטרות + +**תאימות לאחור**: שאילתות קיימות המשתמשות ב-`response-type: "text"` ו- + `response-type: "json"` ממשיכות לעבוד ללא שינוי. +**עמידות לקיטוע**: פלטים חלקיים של LLM מניבים תוצאות חלקיות ותקינות + במקום כשל מוחלט. +**אימות סכימה**: תמיכה באימות סכימה של JSON עבור אובייקטים בודדים. +**איחודים מובחנים**: תמיכה בפלטים מסוגים מעורבים באמצעות שדה `type` + מפריד. +**שינויים מינימליים ב-API**: הרחבת תצורת השאילתה הקיימת עם סוג + תגובה חדש ומפתח סכימה. + +## רקע + +### ארכיטקטורה נוכחית + +<<<<<<< HEAD +שירות השאילתות תומך בשני סוגי תגובה: + +1. `response-type: "text"` - תגובה טקסטואלית גולמית המוחזרת כפי שהיא. +2. `response-type: "json"` - JSON המנותח מהתגובה, ומאומת כנגד +======= +שירות השאילתות תומך בשני סוגי תגובות: + +1. `response-type: "text"` - תגובה טקסטואלית גולמית המוחזרת כפי שהיא. +2. `response-type: "json"` - JSON המנותח מהתגובה, ומאומת מול +>>>>>>> 82edf2d (New md files from RunPod) + `schema` אופציונלי. + +יישום נוכחי ב-`trustgraph-flow/trustgraph/template/prompt_manager.py`: + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### מגבלות נוכחיות + +כאשר הנחיות החילוץ מבקשות פלט כמערכים מסוג JSON (`[{...}, {...}, ...]`): + +<<<<<<< HEAD +**שחיתות עקב קיטום**: אם מודל השפה (LLM) מגיע למגבלת מספר הטוקנים במהלך יצירת המערך, +======= +**שחיתות עקב קיטוע:** אם מודל השפה (LLM) מגיע למגבלת מספר הטוקנים במהלך יצירת המערך, +>>>>>>> 82edf2d (New md files from RunPod) + התגובה כולה הופכת ל-JSON לא חוקי ואי אפשר לנתח אותה. +**ניתוח "הכל או כלום":** יש לקבל את הפלט השלם לפני הניתוח. +**אין תוצאות חלקיות:** תגובה מקוטעת מניבה אפס נתונים שניתן להשתמש בהם. +**לא אמין עבור חילוצים גדולים:** ככל שיותר פריטים מחולצים, כך גדל הסיכון לכישלון. + +מפרט זה מתייחס למגבלות אלה על ידי הצגת פורמט JSONL עבור +הנחיות חילוץ, כאשר כל פריט מחולץ הוא אובייקט JSON שלם בשורה +משלו. + +## עיצוב טכני + +### הרחבת סוג התגובה + +הוסף סוג תגובה חדש `"jsonl"` לצד סוגי `"text"` ו-`"json"` הקיימים. + +#### שינויי תצורה + +<<<<<<< HEAD +**ערך חדש עבור סוג התגובה:** +======= +**ערך סוג תגובה חדש:** +>>>>>>> 82edf2d (New md files from RunPod) + +``` +"response-type": "jsonl" +``` + +**פרשנות של הסכימה:** + +המפתח הקיים `"schema"` משמש הן עבור סוג התגובה `"json"` והן עבור סוג התגובה `"jsonl"`. +הפרשנות תלויה בסוג התגובה: + +`"json"`: הסכימה מתארת את כל התגובה (בדרך כלל מערך או אובייקט). +`"jsonl"`: הסכימה מתארת כל שורה/אובייקט בנפרד. + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +זה מונע שינויים בכלי התצורה ובתוכנות העריכה. + +### מפרט פורמט JSONL + +#### חילוץ פשוט + +עבור שאילתות המפיקות סוג אחד של אובייקט (הגדרות, קשרים, +נושאים, שורות), הפלט הוא אובייקט JSON אחד בכל שורה, ללא עטיפה: + +**פורמט פלט של השאילתה:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +<<<<<<< HEAD +**ניגוד לפורמט מערך JSON הקודם:** +======= +**השוואה לפורמט מערך JSON הקודם:** +>>>>>>> 82edf2d (New md files from RunPod) +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +אם מודל השפה הגדול (LLM) מקצר אחרי השורה 2, פורמט מערך ה-JSON ייתן JSON לא תקין, +בעוד ש-JSONL ייתן שני אובייקטים תקינים. + +<<<<<<< HEAD +#### חילוץ של טיפוסים מעורבים (איחודים מובחנים) + +עבור הנחיות המפיקות מספר סוגים של אובייקטים (לדוגמה, גם הגדרות וגם +קשרים, או ישויות, קשרים ומאפיינים), השתמש בשדה `"type"` +======= +#### חילוץ מסוגים מעורבים (איחודים מובחנים) + +עבור הנחיות המפיקות סוגים מרובים של אובייקטים (לדוגמה, גם הגדרות וגם +קשרים, או ישויות, קשרים ומאפיינים), השתמשו בשדה `"type"` +>>>>>>> 82edf2d (New md files from RunPod) +כמבחין: + +**פורמט פלט של ההנחיה:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**הסכימה עבור איחודים מובחנים משתמשת ב-`oneOf`:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### חילוץ אונטולוגיה + +עבור חילוץ המבוסס על אונטולוגיה, הכולל ישויות, קשרים ומאפיינים: + +**פורמט פלט של ההנחיה:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### פרטי יישום + +#### מחלקת Prompt + +המחלקה הקיימת `Prompt` אינה דורשת שינויים. השדה `schema` משמש מחדש +עבור JSONL, והפרשנות שלו נקבעת על ידי `response_type`: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +אין צורך בשינויים - הטעינה הקיימת של התצורה כבר מטפלת במפתח +`schema`. + +#### ניתוח JSONL + +הוסף שיטת ניתוח חדשה לתגובות JSONL: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### שינויים ב-PromptManager.invoke + +<<<<<<< HEAD +הרחב את השיטה invoke כדי לטפל בסוג התגובה החדש: +======= +הרחב את המיפעל invoke כדי לטפל בסוג התגובה החדש: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### הנחיות מושפעות + +ההנחיות הבאות צריכות להיות מועברות לפורמט JSONL: + +| מזהה הנחיה | תיאור | שדה סוג | +|-----------|-------------|------------| +| `extract-definitions` | חילוץ ישויות/הגדרות | לא (סוג בודד) | +| `extract-relationships` | חילוץ קשרים | לא (סוג בודד) | +| `extract-topics` | חילוץ נושא/הגדרה | לא (סוג בודד) | +| `extract-rows` | חילוץ שורה מובנית | לא (סוג בודד) | +| `agent-kg-extract` | חילוץ משולב של הגדרה + קשר | כן: `"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | חילוץ מבוסס אונטולוגיה | כן: `"entity"`, `"relationship"`, `"attribute"` | + +### שינויים ב-API + +#### נקודת מבט של הלקוח + +ניתוח JSONL שקוף למשתמשי ה-API של שירות ההנחיות. הניתוח מתבצע +<<<<<<< HEAD +בצד השרת בשירות ההנחיות, והתגובה מוחזרת באמצעות השדה הסטנדרטי +======= +בצד השרת בשירות ההנחיות, והתגובה מוחזרת דרך השדה הסטנדרטי +>>>>>>> 82edf2d (New md files from RunPod) +`PromptResponse.object` כמערך JSON מוסרי. + +כאשר לקוחות קוראים לשירות ההנחיות (דרך `PromptClient.prompt()` או דומה): + +**`response-type: "json"`** עם סכימת מערך → הלקוח מקבל `list` בפייתון +**`response-type: "jsonl"`** → הלקוח מקבל `list` בפייתון + +מנקודת מבטו של הלקוח, שתי השיטות מחזירות מבני נתונים זהים. ההבדל +<<<<<<< HEAD +הוא אך ורק באופן שבו פלט ה-LLM מנותח בצד השרת: + +פורמט מערך JSON: קריאה אחת ל-`json.loads()`; נכשל לחלוטין אם הוא חתוך +פורמט JSONL: ניתוח שורה אחר שורה; מייצר תוצאות חלקיות אם הוא חתוך +======= +הוא אך ורק באופן שבו הפלט של מודל השפה הגדול (LLM) מנותח בצד השרת: + +פורמט מערך JSON: קריאה אחת ל-`json.loads()`; נכשל לחלוטין אם הוא חתוך. +פורמט JSONL: ניתוח שורה אחר שורה; מייצר תוצאות חלקיות אם הוא חתוך. +>>>>>>> 82edf2d (New md files from RunPod) + +המשמעות היא שקוד לקוח קיים שמצפה לרשימה מהנחיות חילוץ +אינו דורש שינויים בעת העברת הנחיות מפורמט JSON לפורמט JSONL. + +#### ערך החזרה של השרת + +עבור `response-type: "jsonl"`, השיטה `PromptManager.invoke()` מחזירה +`list[dict]` המכיל את כל האובייקטים שנותחו ואומתו בהצלחה. +רשימה זו מוסרת אז ל-JSON עבור השדה `PromptResponse.object`. + +#### טיפול בשגיאות + +<<<<<<< HEAD +תוצאות ריקות: מחזיר רשימה ריקה `[]` עם רישום אזהרה +כשל חלקי בניתוח: מחזיר רשימה של אובייקטים שנותחו בהצלחה עם + רישומי אזהרה עבור כשלים +כשל מוחלט בניתוח: מחזיר רשימה ריקה `[]` עם רישומי אזהרה +======= +תוצאות ריקות: מחזיר רשימה ריקה `[]` עם רישום אזהרה. +כשל חלקי בניתוח: מחזיר רשימה של אובייקטים שנותחו בהצלחה עם + רישומי אזהרה עבור כשלים. +כשל מוחלט בניתוח: מחזיר רשימה ריקה `[]` עם רישומי אזהרה. +>>>>>>> 82edf2d (New md files from RunPod) + +זה שונה מ-`response-type: "json"` שמגביר `RuntimeError` +בעת כשל בניתוח. ההתנהגות הסלחנית עבור JSONL היא מכוונת כדי לספק +עמידות לחיתוך. + +### דוגמה לתצורה + +דוגמה מלאה לתצורה של הנחיה: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## שיקולי אבטחה + +<<<<<<< HEAD +**בדיקת תקינות קלט**: ניתוח JSON משתמש ב-`json.loads()` הסטנדרטי, שהוא בטוח + מפני התקפות הזרקה. +**בדיקת תאימות סכימה**: משתמש ב-`jsonschema.validate()` לאכיפת סכימה. +**ללא משטח תקיפה חדש**: ניתוח JSONL בטוח יותר מניתוח מערך JSON +======= +**בדיקת קלט**: ניתוח JSON משתמש ב-`json.loads()` הסטנדרטי, שהוא בטוח + מפני התקפות הזרקה. +**בדיקת סכימה**: משתמש ב-`jsonschema.validate()` לאכיפת סכימה. +**ללא נקודות תורפה חדשות**: ניתוח JSONL בטוח יותר מניתוח מערך JSON +>>>>>>> 82edf2d (New md files from RunPod) + בשל עיבוד שורה אחר שורה. + +## שיקולי ביצועים + +<<<<<<< HEAD +**זיכרון**: ניתוח שורה אחר שורה משתמש בפחות זיכרון שיא בהשוואה לטעינת מערכי JSON שלמים. + +**השהיה**: ביצועי הניתוח דומים לניתוח מערך JSON. +**בדיקת תאימות**: בדיקת תאימות סכימה מתבצעת עבור כל אובייקט, מה שמוסיף תקורה אך + מאפשר תוצאות חלקיות במקרה של כשל בבדיקת התאימות. +======= +**זיכרון**: ניתוח שורה אחר שורה משתמש בפחות זיכרון שיא בהשוואה לטעינת + מערכי JSON שלמים. +**השהיה**: ביצועי הניתוח דומים לניתוח מערך JSON. +**בדיקה**: בדיקת סכימה מתבצעת עבור כל אובייקט, מה שמוסיף תקורה אך + מאפשר תוצאות חלקיות במקרה של כשל בבדיקה. +>>>>>>> 82edf2d (New md files from RunPod) + +## אסטרטגיית בדיקות + +### בדיקות יחידה + +ניתוח JSONL עם קלט תקין. +ניתוח JSONL עם שורות ריקות. +ניתוח JSONL עם גדרות קוד Markdown. +ניתוח JSONL עם שורה אחרונה חתוכה. +ניתוח JSONL עם שורות JSON לא תקינות המפוזרות. +<<<<<<< HEAD +בדיקת תאימות סכימה עם איחודים מובחנים של `oneOf`. +======= +בדיקת סכימה עם איחודים מובחנים של `oneOf`. +>>>>>>> 82edf2d (New md files from RunPod) +תאימות לאחור: הנחיות `"text"` ו-`"json"` קיימות אינן משתנות. + +### בדיקות אינטגרציה + +חילוץ מקצה לקצה עם הנחיות JSONL. +חילוץ עם קיצוץ מדומם (תגובה מוגבלת באופן מלאכותי). +חילוץ מסוגים מעורבים עם מפריד סוגים. +חילוץ אונטולוגיה עם שלושת הסוגים. + +### בדיקות איכות חילוץ + +השוואת תוצאות חילוץ: פורמט JSONL לעומת מערך JSON. +<<<<<<< HEAD +בדיקת עמידות בפני קיטוע: JSONL מניב תוצאות חלקיות כאשר JSON נכשל. +======= +בדיקת עמידות בפני קיטוע: פורמט JSONL מספק תוצאות חלקיות כאשר פורמט JSON נכשל. +>>>>>>> 82edf2d (New md files from RunPod) + +## תוכנית מעבר + +### שלב 1: הטמעה + +1. הטמעת שיטה `parse_jsonl()` ב-`PromptManager`. +2. הרחבת `invoke()` כדי לטפל ב-`response-type: "jsonl"`. +3. הוספת בדיקות יחידה. + +### שלב 2: מעבר להנחיות + +1. עדכון ההנחיה והתצורה של `extract-definitions`. +2. עדכון ההנחיה והתצורה של `extract-relationships`. +3. עדכון ההנחיה והתצורה של `extract-topics`. +4. עדכון ההנחיה והתצורה של `extract-rows`. +5. עדכון ההנחיה והתצורה של `agent-kg-extract`. +6. עדכון ההנחיה והתצורה של `extract-with-ontologies`. + +### שלב 3: עדכונים במערכות משימתיות + +<<<<<<< HEAD +1. עדכון כל קוד המשתמש בתוצאות החילוץ כדי לטפל בסוג החזרה של רשימה. +2. עדכון קוד המקטלג חילוצים מסוגים מעורבים לפי שדה `type`. +======= +1. עדכון כל קוד הצורך בתוצאות החילוץ כדי לטפל בסוג החזרה של רשימה. +2. עדכון קוד שמקטלג חילוצים מסוגים מעורבים לפי שדה `type`. +>>>>>>> 82edf2d (New md files from RunPod) +3. עדכון בדיקות המאמתות את פורמט הפלט של החילוץ. + +## שאלות פתוחות + +אין כרגע. + +## הפניות + +יישום נוכחי: `trustgraph-flow/trustgraph/template/prompt_manager.py`. +מפרט JSON Lines: https://jsonlines.org/. +סכימת JSON `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof. +מפרט קשור: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`). diff --git a/docs/tech-specs/jsonl-prompt-output.hi.md b/docs/tech-specs/jsonl-prompt-output.hi.md new file mode 100644 index 00000000..cbcae92e --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.hi.md @@ -0,0 +1,561 @@ +--- +layout: default +title: "JSONL प्रॉम्प्ट आउटपुट तकनीकी विनिर्देश" +parent: "Hindi (Beta)" +--- + +# JSONL प्रॉम्प्ट आउटपुट तकनीकी विनिर्देश + +> **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. + +## अवलोकन + +<<<<<<< HEAD +यह विनिर्देश ट्रस्टग्राफ में प्रॉम्प्ट प्रतिक्रियाओं के लिए JSONL (JSON लाइन्स) आउटपुट प्रारूप के कार्यान्वयन का वर्णन करता है। JSONL, LLM प्रतिक्रियाओं से संरचित डेटा को निकालने में सक्षम बनाता है, जो कि LLM प्रतिक्रियाओं के आउटपुट टोकन सीमाओं तक पहुंचने पर JSON सरणी आउटपुट के दूषित होने जैसी महत्वपूर्ण समस्याओं को हल करता है। + + + + +======= +यह विनिर्देश ट्रस्टग्राफ में प्रॉम्प्ट प्रतिक्रियाओं के लिए JSONL (JSON लाइन्स) आउटपुट प्रारूप के कार्यान्वयन का वर्णन करता है। JSONL, LLM प्रतिक्रियाओं से संरचित डेटा को निकालने में सक्षम बनाता है, जो कि LLM प्रतिक्रियाओं के आउटपुट टोकन सीमाओं तक पहुंचने पर JSON सरणी आउटपुट के दूषित होने जैसी महत्वपूर्ण समस्याओं का समाधान करता है। +>>>>>>> 82edf2d (New md files from RunPod) + + +<<<<<<< HEAD +1. **ट्रंकेशन-रेज़िलिएंट एक्सट्रैक्शन (Truncation-Resilient Extraction)**: वैध आंशिक परिणाम निकालें, भले ही + एलएलएम (LLM) आउटपुट प्रतिक्रिया के बीच में ही काट दिया गया हो। +2. **बड़े पैमाने पर एक्सट्रैक्शन (Large-Scale Extraction)**: टोकन सीमाओं के कारण पूर्ण विफलता के जोखिम के बिना, कई वस्तुओं के निष्कर्षण को संभालें। + 3. **मिश्रित-प्रकार एक्सट्रैक्शन (Mixed-Type Extraction)**: एक ही प्रॉम्प्ट में कई इकाई प्रकारों (परिभाषाओं, संबंधों, संस्थाओं, विशेषताओं) के निष्कर्षण का समर्थन करें। +4. **स्ट्रीमिंग-संगत आउटपुट (Streaming-Compatible Output)**: निष्कर्षण परिणामों की भविष्य की स्ट्रीमिंग/क्रमिक + प्रसंस्करण को सक्षम करें। + + +======= + + + +यह कार्यान्वयन निम्नलिखित उपयोग परिदृश्यों का समर्थन करता है: + +1. **ट्रंकेशन-प्रतिरोधी निष्कर्षण**: भले ही एलएलएम आउटपुट प्रतिक्रिया के बीच में काट दिया गया हो, फिर भी मान्य आंशिक परिणाम निकालें। + एलएलएम आउटपुट प्रतिक्रिया के बीच में काट दिया गया हो, फिर भी मान्य आंशिक परिणाम निकालें। +2. **बड़ी-पैमाने पर निष्कर्षण**: टोकन सीमाओं के कारण पूर्ण विफलता के जोखिम के बिना, कई वस्तुओं के निष्कर्षण को संभालें। + टोकन सीमाओं के कारण पूर्ण विफलता के जोखिम के बिना, कई वस्तुओं के निष्कर्षण को संभालें। +3. **मिश्रित-प्रकार निष्कर्षण**: एक ही प्रॉम्प्ट में कई इकाई प्रकारों (परिभाषाएँ, संबंध, इकाइयाँ, विशेषताएँ) के निष्कर्षण का समर्थन करें। + एक ही प्रॉम्प्ट में कई इकाई प्रकारों (परिभाषाएँ, संबंध, इकाइयाँ, विशेषताएँ) के निष्कर्षण का समर्थन करें। +4. **स्ट्रीमिंग-संगत आउटपुट**: निष्कर्षण परिणामों की भविष्य की स्ट्रीमिंग/क्रमिक प्रसंस्करण को सक्षम करें। + निष्कर्षण परिणामों की भविष्य की स्ट्रीमिंग/क्रमिक प्रसंस्करण को सक्षम करें। +>>>>>>> 82edf2d (New md files from RunPod) + +## लक्ष्य + +**पिछड़ा संगतता (Backward Compatibility)**: मौजूदा प्रॉम्प्ट जो `response-type: "text"` और का उपयोग करते हैं, +<<<<<<< HEAD + `response-type: "json"` बिना किसी बदलाव के काम करना जारी रखते हैं। +**अतिसंयमी लचीलापन (Truncation Resilience)**: आंशिक एलएलएम आउटपुट आंशिक, मान्य परिणाम देते हैं, + पूर्ण विफलता के बजाय। +**स्कीमा सत्यापन (Schema Validation)**: व्यक्तिगत ऑब्जेक्ट के लिए JSON स्कीमा सत्यापन का समर्थन। +======= + `response-type: "json"`, बिना किसी बदलाव के काम करना जारी रखते हैं। +**अतिसंयमी लचीलापन (Truncation Resilience)**: आंशिक एलएलएम आउटपुट आंशिक, मान्य परिणाम देते हैं, + पूर्ण विफलता के बजाय। +**स्कीमा सत्यापन (Schema Validation)**: व्यक्तिगत वस्तुओं के लिए JSON स्कीमा सत्यापन का समर्थन। +>>>>>>> 82edf2d (New md files from RunPod) +**विभेदक संघ (Discriminated Unions)**: `type` फ़ील्ड का उपयोग करके मिश्रित-प्रकार के आउटपुट का समर्थन। + विभेदक। +**न्यूनतम एपीआई परिवर्तन (Minimal API Changes)**: नए प्रतिक्रिया प्रकार और स्कीमा कुंजी के साथ मौजूदा प्रॉम्प्ट कॉन्फ़िगरेशन का विस्तार। + + +## पृष्ठभूमि + +### वर्तमान आर्किटेक्चर + +प्रॉम्प्ट सेवा दो प्रकार के प्रतिक्रियाओं का समर्थन करती है: + +1. `response-type: "text"` - बिना किसी बदलाव के वापस की गई कच्ची टेक्स्ट प्रतिक्रिया +<<<<<<< HEAD +2. `response-type: "json"` - प्रतिक्रिया से पार्स किया गया JSON, जिसकी जाँच `response-type: "json"` के विरुद्ध की जाती है + वैकल्पिक `schema` + +`trustgraph-flow/trustgraph/template/prompt_manager.py` में वर्तमान कार्यान्वयन: +======= +2. `response-type: "json"` - प्रतिक्रिया से पार्स किया गया JSON, जिसकी तुलना + वैकल्पिक `schema` से की जाती है + +वर्तमान कार्यान्वयन `trustgraph-flow/trustgraph/template/prompt_manager.py` में: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +<<<<<<< HEAD +### वर्तमान सीमाएँ + +जब निष्कर्षण प्रॉम्प्ट आउटपुट को JSON सरणियों (`[{...}, {...}, ...]`) के रूप में मांगते हैं: + +**अतिसंक्षेपण भ्रष्टाचार**: यदि LLM आउटपुट टोकन सीमाओं को सरणी के बीच में पार करता है, तो + संपूर्ण प्रतिक्रिया अमान्य JSON बन जाती है और इसे पार्स नहीं किया जा सकता है। +**सब कुछ या कुछ नहीं पार्सिंग**: पार्स करने से पहले पूर्ण आउटपुट प्राप्त करना आवश्यक है। +**कोई आंशिक परिणाम नहीं**: एक छोटा आउटपुट शून्य उपयोगी डेटा उत्पन्न करता है। +**बड़े निष्कर्षणों के लिए अविश्वसनीय**: अधिक निकाले गए आइटम = उच्च विफलता जोखिम। + +यह विनिर्देश इन सीमाओं को JSONL प्रारूप को पेश करके संबोधित करता है, जहाँ प्रत्येक निकाले गए आइटम को अपनी +======= +### वर्तमान सीमाएं + +जब निष्कर्षण प्रॉम्प्ट आउटपुट को JSON सरणियों (`[{...}, {...}, ...]`) के रूप में मांगते हैं: + +**अतिसंयोजन भ्रष्टाचार**: यदि LLM आउटपुट टोकन सीमाओं को सरणी के बीच में पार करता है, तो + संपूर्ण प्रतिक्रिया अमान्य JSON बन जाती है और इसे पार्स नहीं किया जा सकता है। +**सब कुछ या कुछ नहीं पार्सिंग**: पार्स करने से पहले पूर्ण आउटपुट प्राप्त करना आवश्यक है। +**कोई आंशिक परिणाम नहीं**: एकtruncated प्रतिक्रिया शून्य उपयोगी डेटा उत्पन्न करती है। +**बड़े निष्कर्षणों के लिए अविश्वसनीय**: अधिक निकाले गए आइटम = उच्च विफलता जोखिम। + +यह विनिर्देश इन सीमाओं को JSONL प्रारूप को पेश करके संबोधित करता है, जहां प्रत्येक निकाले गए आइटम को अपनी +>>>>>>> 82edf2d (New md files from RunPod) +पंक्ति पर एक पूर्ण JSON ऑब्जेक्ट के रूप में दर्शाया जाता है। + + +## तकनीकी डिज़ाइन + +### प्रतिक्रिया प्रकार विस्तार + +मौजूदा `"text"` और `"json"` प्रकारों के साथ एक नया प्रतिक्रिया प्रकार `"jsonl"` जोड़ें। + +#### कॉन्फ़िगरेशन परिवर्तन + +**नया प्रतिक्रिया प्रकार मान:** + +``` +"response-type": "jsonl" +``` + +**स्कीमा व्याख्या:** + +मौजूदा `"schema"` कुंजी का उपयोग `"json"` और `"jsonl"` दोनों प्रतिक्रिया प्रकारों के लिए किया जाता है। +व्याख्या प्रतिक्रिया के प्रकार पर निर्भर करती है: + +`"json"`: स्कीमा संपूर्ण प्रतिक्रिया का वर्णन करता है (आमतौर पर एक सरणी या ऑब्जेक्ट)। +`"jsonl"`: स्कीमा प्रत्येक व्यक्तिगत पंक्ति/ऑब्जेक्ट का वर्णन करता है। + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +यह प्रॉम्प्ट कॉन्फ़िगरेशन टूलिंग और संपादकों में बदलावों से बचाता है। + +### JSONL प्रारूप विनिर्देश + +#### सरल निष्कर्षण + +उन प्रॉम्प्ट के लिए जो केवल एक प्रकार की वस्तु (परिभाषाएँ, संबंध, +<<<<<<< HEAD +विषय, पंक्तियाँ) निकालते हैं, आउटपुट में बिना किसी अतिरिक्त आवरण के प्रति पंक्ति एक JSON ऑब्जेक्ट होता है: +======= +विषय, पंक्तियाँ) निकालते हैं, आउटपुट में बिना किसी अतिरिक्त आवरण के, प्रति पंक्ति एक JSON ऑब्जेक्ट होता है: +>>>>>>> 82edf2d (New md files from RunPod) + +**प्रॉम्प्ट आउटपुट प्रारूप:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +**पिछले JSON सरणी प्रारूप के साथ अंतर:** +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +यदि एलएलएम (LLM) दूसरी पंक्ति के बाद कट जाता है, तो JSON सरणी प्रारूप अमान्य JSON उत्पन्न करता है, +जबकि JSONL दो मान्य ऑब्जेक्ट उत्पन्न करता है। + +#### मिश्रित-प्रकार निष्कर्षण (भेदभावपूर्ण संघ) + +<<<<<<< HEAD +उन प्रॉम्प्ट के लिए जो ऑब्जेक्ट के कई प्रकारों को निकालते हैं (उदाहरण के लिए, परिभाषाएँ और +संबंध, या इकाइयाँ, संबंध और विशेषताएँ), एक `"type"` +फ़ील्ड को विभेदक के रूप में उपयोग करें: +======= +उन प्रॉम्प्ट के लिए जो कई प्रकार की वस्तुओं को निकालते हैं (उदाहरण के लिए, परिभाषाएँ और +संबंध, या इकाइयाँ, संबंध और विशेषताएँ), एक `"type"` +फ़ील्ड का उपयोग विभेदक के रूप में करें: +>>>>>>> 82edf2d (New md files from RunPod) + +**प्रॉम्प्ट आउटपुट प्रारूप:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**विभेदक संघों के लिए स्कीमा `oneOf` का उपयोग करता है:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### शब्दावली निष्कर्षण + +संस्थाओं, संबंधों और विशेषताओं के साथ शब्दावली-आधारित निष्कर्षण के लिए: + +**प्रॉम्प्ट आउटपुट प्रारूप:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### कार्यान्वयन विवरण + +#### प्रॉम्प्ट क्लास + +मौजूदा `Prompt` क्लास में कोई बदलाव आवश्यक नहीं है। `schema` फ़ील्ड का पुन: उपयोग किया गया है। +JSONL के लिए, जिसका अर्थ `response_type` द्वारा निर्धारित किया जाता है: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +<<<<<<< HEAD +#### प्रॉम्प्टमैनेजर.लोड_कॉन्फ़िगरेशन +======= +#### PromptManager.load_config +>>>>>>> 82edf2d (New md files from RunPod) + +कोई बदलाव आवश्यक नहीं है - मौजूदा कॉन्फ़िगरेशन लोड करने की प्रक्रिया पहले से ही +`schema` कुंजी को संभालती है। + +#### JSONL पार्सिंग + +JSONL प्रतिक्रियाओं के लिए एक नई पार्सिंग विधि जोड़ें: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### प्रॉम्प्टमैनेजर.इनवॉइक में बदलाव + +इनवॉइक विधि को नए प्रतिक्रिया प्रकार को संभालने के लिए विस्तारित करें: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### प्रभावित संकेत (प्रॉम्प्ट) + +निम्नलिखित संकेतों को JSONL प्रारूप में स्थानांतरित किया जाना चाहिए: + +| संकेत आईडी | विवरण | प्रकार फ़ील्ड | +|-----------|-------------|------------| +| `extract-definitions` | इकाई/परिभाषा निष्कर्षण | नहीं (एकल प्रकार) | +| `extract-relationships` | संबंध निष्कर्षण | नहीं (एकल प्रकार) | +| `extract-topics` | विषय/परिभाषा निष्कर्षण | नहीं (एकल प्रकार) | +| `extract-rows` | संरचित पंक्ति निष्कर्षण | नहीं (एकल प्रकार) | +| `agent-kg-extract` | संयुक्त परिभाषा + संबंध निष्कर्षण | हाँ: `"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | ज्ञान-आधारित निष्कर्षण | हाँ: `"entity"`, `"relationship"`, `"attribute"` | + +### एपीआई में बदलाव + +#### क्लाइंट का दृष्टिकोण + +JSONL पार्सिंग, प्रॉम्प्ट सर्विस एपीआई उपयोगकर्ताओं के लिए पारदर्शी है। पार्सिंग प्रॉम्प्ट सर्विस में सर्वर-साइड पर होता है, और प्रतिक्रिया मानक ⟦CODE_0⟧ फ़ील्ड के रूप में एक क्रमबद्ध JSON सरणी के माध्यम से वापस की जाती है। + +`PromptResponse.object` + +जब ग्राहक प्रॉम्प्ट सेवा को कॉल करते हैं (`PromptClient.prompt()` या इसी तरह के माध्यम से): + +**`response-type: "json"`** जिसमें एरे स्कीमा है → ग्राहक को पायथन `list` प्राप्त होता है। +**`response-type: "jsonl"`** → ग्राहक को पायथन `list` प्राप्त होता है। + +<<<<<<< HEAD +ग्राहक के दृष्टिकोण से, दोनों समान डेटा संरचनाएं लौटाते हैं। +अंतर पूरी तरह से इस बात में है कि सर्वर-साइड पर एलएलएम आउटपुट को कैसे पार्स किया जाता है: + +JSON सरणी प्रारूप: एक `json.loads()` कॉल; यदि छोटा किया गया तो पूरी तरह से विफल हो जाता है। +JSONL प्रारूप: लाइन-दर-लाइन पार्सिंग; यदि छोटा किया गया तो आंशिक परिणाम देता है। +======= +ग्राहक के दृष्टिकोण से, दोनों समान डेटा संरचनाएँ लौटाते हैं। +अंतर पूरी तरह से इस बात में है कि सर्वर-साइड पर एलएलएम आउटपुट को कैसे पार्स किया जाता है: + +JSON सरणी प्रारूप: एक `json.loads()` कॉल; यदि छोटा किया गया तो पूरी तरह विफल हो जाता है। +JSONL प्रारूप: पंक्ति-दर-पंक्ति पार्सिंग; यदि छोटा किया गया तो आंशिक परिणाम देता है। +>>>>>>> 82edf2d (New md files from RunPod) + +इसका मतलब है कि मौजूदा क्लाइंट कोड जो एक्सट्रैक्शन प्रॉम्प्ट से एक सूची की अपेक्षा करता है, +को JSON से JSONL प्रारूप में प्रॉम्प्ट माइग्रेट करते समय किसी भी बदलाव की आवश्यकता नहीं होती है। + +#### सर्वर रिटर्न वैल्यू + +`response-type: "jsonl"` के लिए, `PromptManager.invoke()` विधि एक +<<<<<<< HEAD +`list[dict]` लौटाती है जिसमें सभी सफलतापूर्वक पार्स और मान्य किए गए ऑब्जेक्ट शामिल होते हैं। इस +======= +`list[dict]` लौटाती है जिसमें सभी सफलतापूर्वक पार्स किए गए और मान्य ऑब्जेक्ट शामिल हैं। इस +>>>>>>> 82edf2d (New md files from RunPod) +सूची को तब `PromptResponse.object` फ़ील्ड के लिए JSON में क्रमबद्ध किया जाता है। + +#### त्रुटि प्रबंधन + +<<<<<<< HEAD +खाली परिणाम: खाली सूची `[]` लौटाता है चेतावनी लॉग के साथ। +आंशिक पार्स विफलता: सफलतापूर्वक पार्स किए गए ऑब्जेक्ट की सूची लौटाता है, + विफलताओं के लिए चेतावनी लॉग के साथ। +पूर्ण पार्स विफलता: खाली सूची `[]` लौटाता है, चेतावनी लॉग के साथ। + +यह `response-type: "json"` से अलग है, जो पार्स विफलता पर `RuntimeError` उत्पन्न करता है। +======= +खाली परिणाम: खाली सूची `[]` लौटाता है, साथ में चेतावनी लॉग। +आंशिक पार्स विफलता: सफलतापूर्वक पार्स किए गए ऑब्जेक्ट की सूची लौटाता है, + विफलताओं के लिए चेतावनी लॉग के साथ। +पूर्ण पार्स विफलता: खाली सूची `[]` लौटाता है, साथ में चेतावनी लॉग। + +यह `response-type: "json"` से भिन्न है, जो पार्स विफलता पर `RuntimeError` उत्पन्न करता है। +>>>>>>> 82edf2d (New md files from RunPod) +JSONL के लिए उदार व्यवहार जानबूझकर प्रदान किया गया है ताकि ट्रंकेशन के प्रति लचीलापन मिल सके। + + +### कॉन्फ़िगरेशन उदाहरण + +पूर्ण प्रॉम्प्ट कॉन्फ़िगरेशन उदाहरण: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## सुरक्षा संबंधी विचार + +**इनपुट सत्यापन**: JSON पार्सिंग मानक `json.loads()` का उपयोग करता है, जो इंजेक्शन हमलों के खिलाफ सुरक्षित है। + **स्कीमा सत्यापन**: स्कीमा प्रवर्तन के लिए ⟦CODE_0⟧ का उपयोग करता है। +**स्कीमा सत्यापन**: स्कीमा के अनुपालन को सुनिश्चित करने के लिए `jsonschema.validate()` का उपयोग करता है। +**कोई नया आक्रमण क्षेत्र नहीं**: JSONL पार्सिंग, लाइन-दर-लाइन प्रसंस्करण के कारण, JSON सरणी पार्सिंग की तुलना में बहुत अधिक सुरक्षित है। + + +## प्रदर्शन संबंधी विचार + +<<<<<<< HEAD +**मेमोरी**: पंक्ति-दर-पंक्ति पार्सिंग, पूरे JSON सरणियों को लोड करने की तुलना में कम चरम मेमोरी का उपयोग करती है। +======= +**मेमोरी**: लाइन-दर-लाइन पार्सिंग, पूरे JSON सरणियों को लोड करने की तुलना में कम चरम मेमोरी का उपयोग करती है। +>>>>>>> 82edf2d (New md files from RunPod) + **विलंबता**: पार्सिंग प्रदर्शन, JSON सरणी पार्सिंग के समान है। +**सत्यापन**: स्कीमा सत्यापन प्रत्येक ऑब्जेक्ट के लिए किया जाता है, जिससे ओवरहेड बढ़ता है, लेकिन सत्यापन विफलता पर आंशिक परिणाम प्राप्त करने की अनुमति मिलती है। + + ## परीक्षण रणनीति + +## परीक्षण रणनीति + +### यूनिट परीक्षण (Unit Tests) + +मान्य इनपुट के साथ JSONL पार्सिंग +खाली पंक्तियों के साथ JSONL पार्सिंग +मार्कडाउन कोड फ़ेंस के साथ JSONL पार्सिंग +<<<<<<< HEAD +कटे हुए अंतिम पंक्ति के साथ JSONL पार्सिंग +======= +truncated अंतिम पंक्ति के साथ JSONL पार्सिंग +>>>>>>> 82edf2d (New md files from RunPod) +अमान्य JSON पंक्तियों के साथ JSONL पार्सिंग +`oneOf` विभेदक संघों के साथ स्कीमा सत्यापन +पिछली अनुकूलता: मौजूदा `"text"` और `"json"` प्रॉम्प्ट अपरिवर्तित + +### एकीकरण परीक्षण (Integration Tests) + +JSONL प्रॉम्प्ट के साथ एंड-टू-एंड निष्कर्षण +<<<<<<< HEAD +अनुकरणित कटाई के साथ निष्कर्षण (कृत्रिम रूप से सीमित प्रतिक्रिया) +======= +अनुकरणित ट्रंकेशन के साथ निष्कर्षण (कृत्रिम रूप से सीमित प्रतिक्रिया) +>>>>>>> 82edf2d (New md files from RunPod) +टाइप डिस्क्रिमिनेटर के साथ मिश्रित-प्रकार निष्कर्षण +सभी तीन प्रकारों के साथ ऑन्टोलॉजी निष्कर्षण + +### निष्कर्षण गुणवत्ता परीक्षण (Extraction Quality Tests) + +निष्कर्षण परिणामों की तुलना करें: JSONL बनाम JSON सरणी प्रारूप +ट्रंकेशन के प्रति लचीलापन की जाँच करें: JSONL आंशिक परिणाम देता है जहाँ JSON विफल रहता है + +## माइग्रेशन योजना + +### चरण 1: कार्यान्वयन + +1. `parse_jsonl()` विधि को `PromptManager` में लागू करें +2. `invoke()` को `response-type: "jsonl"` को संभालने के लिए विस्तारित करें +3. यूनिट परीक्षण जोड़ें + +### चरण 2: प्रॉम्प्ट माइग्रेशन + +1. `extract-definitions` प्रॉम्प्ट और कॉन्फ़िगरेशन को अपडेट करें +2. `extract-relationships` प्रॉम्प्ट और कॉन्फ़िगरेशन को अपडेट करें +3. `extract-topics` प्रॉम्प्ट और कॉन्फ़िगरेशन को अपडेट करें +4. `extract-rows` प्रॉम्प्ट और कॉन्फ़िगरेशन को अपडेट करें +5. `agent-kg-extract` प्रॉम्प्ट और कॉन्फ़िगरेशन को अपडेट करें +6. `extract-with-ontologies` प्रॉम्प्ट और कॉन्फ़िगरेशन को अपडेट करें + +### चरण 3: डाउनस्ट्रीम अपडेट + +1. निष्कर्षण परिणामों का उपयोग करने वाले किसी भी कोड को सूची रिटर्न प्रकार को संभालने के लिए अपडेट करें +2. `type` फ़ील्ड द्वारा मिश्रित-प्रकार के निष्कर्षणों को वर्गीकृत करने वाले कोड को अपडेट करें +<<<<<<< HEAD +3. निष्कर्षण आउटपुट प्रारूप पर दावा करने वाले परीक्षणों को अपडेट करें +======= +3. निष्कर्षण आउटपुट प्रारूप पर जोर देने वाले परीक्षणों को अपडेट करें +>>>>>>> 82edf2d (New md files from RunPod) + +## खुले प्रश्न + +फिलहाल कोई नहीं। + +## संदर्भ + +वर्तमान कार्यान्वयन: `trustgraph-flow/trustgraph/template/prompt_manager.py` +JSON लाइन्स विनिर्देश: https://jsonlines.org/ +JSON स्कीमा `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof +संबंधित विनिर्देश: स्ट्रीमिंग LLM प्रतिक्रियाएँ (`docs/tech-specs/streaming-llm-responses.md`) diff --git a/docs/tech-specs/jsonl-prompt-output.md b/docs/tech-specs/jsonl-prompt-output.md index d8872fd4..8624979e 100644 --- a/docs/tech-specs/jsonl-prompt-output.md +++ b/docs/tech-specs/jsonl-prompt-output.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "JSONL Prompt Output Technical Specification" +parent: "Tech Specs" +--- + # JSONL Prompt Output Technical Specification ## Overview diff --git a/docs/tech-specs/jsonl-prompt-output.pt.md b/docs/tech-specs/jsonl-prompt-output.pt.md new file mode 100644 index 00000000..63280c28 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.pt.md @@ -0,0 +1,504 @@ +--- +layout: default +title: "Especificação Técnica de Saída de Prompt JSONL" +parent: "Portuguese (Beta)" +--- + +<<<<<<< HEAD +# Especificação Técnica de Saída de Prompt JSONL + +> **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. +======= +# Especificação Técnica da Saída de Prompt JSONL +>>>>>>> 82edf2d (New md files from RunPod) + +## Visão Geral + +Esta especificação descreve a implementação do formato de saída JSONL (JSON Lines) +<<<<<<< HEAD +para respostas de prompt no TrustGraph. JSONL permite a extração de dados estruturados +de forma resiliente à truncagem das respostas de LLM, abordando problemas críticos +relacionados à corrupção de saídas de matriz JSON quando as respostas de LLM atingem +======= +para respostas de prompt no TrustGraph. O JSONL permite a extração de dados estruturados +de forma resistente a truncamentos das respostas de LLM, abordando problemas críticos +relacionados à corrupção de saídas de matrizes JSON quando as respostas de LLM atingem +>>>>>>> 82edf2d (New md files from RunPod) +os limites de tokens de saída. + +Esta implementação suporta os seguintes casos de uso: + +1. **Extração Resistente à Truncagem**: Extrair resultados parciais válidos mesmo quando + a saída do LLM é truncada no meio da resposta. +2. **Extração em Larga Escala**: Lidar com a extração de muitos itens sem risco de + falha completa devido a limites de tokens. +3. **Extração de Tipos Mistos**: Suportar a extração de vários tipos de entidades + (definições, relacionamentos, entidades, atributos) em um único prompt. +4. **Saída Compatível com Streaming**: Permitir o processamento futuro de streaming/incremental + dos resultados da extração. + +## Objetivos + +**Compatibilidade com versões anteriores**: As instruções existentes que usam `response-type: "text"` e + `response-type: "json"` continuam a funcionar sem modificação. +**Resiliência à truncagem**: Saídas parciais do LLM produzem resultados válidos parciais + em vez de falha completa. +**Validação de esquema**: Suporte à validação de esquema JSON para objetos individuais. +**Uniões discriminadas**: Suporte a saídas de tipos mistos usando um campo `type` + discriminador. +**Alterações mínimas na API**: Estenda a configuração de instruções existente com um novo + tipo de resposta e chave de esquema. + +## Contexto + +### Arquitetura atual + +O serviço de instruções suporta dois tipos de resposta: + +1. `response-type: "text"` - Resposta de texto bruto retornada como está. +2. `response-type: "json"` - JSON analisado da resposta, validado contra + um `schema` opcional. + +Implementação atual em `trustgraph-flow/trustgraph/template/prompt_manager.py`: + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### Limitações Atuais + +Quando os prompts de extração solicitam a saída como arrays JSON (`[{...}, {...}, ...]`): + +**Corrupção por truncamento**: Se o LLM atinge os limites de tokens de saída no meio do array, a + resposta inteira se torna JSON inválido e não pode ser analisada. +**Análise "tudo ou nada"**: É necessário receber a saída completa antes de analisar. +**Sem resultados parciais**: Uma resposta truncada produz zero dados utilizáveis. +**Não confiável para grandes extrações**: Quanto mais itens extraídos, maior o risco de falha. + +<<<<<<< HEAD +Esta especificação aborda essas limitações introduzindo o formato JSONL para +======= +Esta especificação aborda essas limitações, introduzindo o formato JSONL para +>>>>>>> 82edf2d (New md files from RunPod) +prompts de extração, onde cada item extraído é um objeto JSON completo em sua +própria linha. + +## Design Técnico + +### Extensão do Tipo de Resposta + +Adicione um novo tipo de resposta `"jsonl"`, juntamente com os tipos existentes `"text"` e `"json"`. + +#### Alterações de Configuração + +**Novo valor do tipo de resposta:** + +``` +"response-type": "jsonl" +``` + +**Interpretação do esquema:** + +A chave existente `"schema"` é usada tanto para o tipo de resposta `"json"` quanto para o tipo de resposta `"jsonl"`. +A interpretação depende do tipo de resposta: + +`"json"`: O esquema descreve toda a resposta (geralmente um array ou objeto). +`"jsonl"`: O esquema descreve cada linha/objeto individual. + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +Isso evita alterações nas ferramentas de configuração e nos editores. + +### Especificação do Formato JSONL + +#### Extração Simples + +Para prompts que extraem um único tipo de objeto (definições, relacionamentos, +tópicos, linhas), a saída é um objeto JSON por linha, sem wrapper: + +**Formato de saída do prompt:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +<<<<<<< HEAD +**Contraste com o formato anterior de array JSON:** +======= +**Contraste com o formato de array JSON anterior:** +>>>>>>> 82edf2d (New md files from RunPod) +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +Se o LLM truncar após a linha 2, o formato de array JSON resulta em JSON inválido, +<<<<<<< HEAD +enquanto o JSONL produz dois objetos válidos. +======= +enquanto o JSONL gera dois objetos válidos. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Extração de Tipos Mistos (Uniões Discriminadas) + +Para prompts que extraem vários tipos de objetos (por exemplo, definições e +relacionamentos, ou entidades, relacionamentos e atributos), use um campo `"type"` +como discriminador: + +**Formato de saída do prompt:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**Esquema para uniões discriminadas usa `oneOf`:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### Extração de Ontologia + +Para extração baseada em ontologia com entidades, relacionamentos e atributos: + +**Formato de saída do prompt:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### Detalhes de Implementação + +#### Classe Prompt + +A classe `Prompt` existente não requer alterações. O campo `schema` é reutilizado +para JSONL, com sua interpretação determinada por `response_type`: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +<<<<<<< HEAD +Nenhuma alteração necessária - o carregamento da configuração existente já lida com a +`schema` chave. +======= +Nenhuma alteração necessária - o carregamento da configuração existente já trata da +chave `schema`. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Análise de JSONL + +Adicionar um novo método de análise para respostas JSONL: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### Alterações no PromptManager.invoke + +Estenda o método invoke para lidar com o novo tipo de resposta: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### Prompts Afetados + +Os seguintes prompts devem ser migrados para o formato JSONL: + +| ID do Prompt | Descrição | Campo de Tipo | +|-----------|-------------|------------| +| `extract-definitions` | Extração de entidade/definição | Não (tipo único) | +| `extract-relationships` | Extração de relacionamento | Não (tipo único) | +| `extract-topics` | Extração de tópico/definição | Não (tipo único) | +| `extract-rows` | Extração de linha estruturada | Não (tipo único) | +| `agent-kg-extract` | Extração combinada de definição + relacionamento | Sim: `"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | Extração baseada em ontologia | Sim: `"entity"`, `"relationship"`, `"attribute"` | + +### Alterações na API + +#### Perspectiva do Cliente + +A análise JSONL é transparente para os chamadores da API do serviço de prompt. A análise ocorre +no lado do servidor no serviço de prompt, e a resposta é retornada através do campo padrão +`PromptResponse.object` como um array JSON serializado. + +Quando os clientes chamam o serviço de prompt (via `PromptClient.prompt()` ou similar): + +**`response-type: "json"`** com esquema de array → o cliente recebe `list` do Python +**`response-type: "jsonl"`** → o cliente recebe `list` do Python + +Da perspectiva do cliente, ambos retornam estruturas de dados idênticas. A +diferença está inteiramente em como a saída do LLM é analisada no lado do servidor: + +Formato de array JSON: Uma única chamada `json.loads()`; falha completamente se truncado +Formato JSONL: Análise linha por linha; produz resultados parciais se truncado + +Isso significa que o código do cliente existente que espera uma lista de prompts de extração +não requer alterações ao migrar prompts de JSON para JSONL. + +#### Valor de Retorno do Servidor + +Para `response-type: "jsonl"`, o método `PromptManager.invoke()` retorna um +`list[dict]` contendo todos os objetos analisados e validados com sucesso. Esta +lista é então serializada para JSON para o campo `PromptResponse.object`. + +#### Tratamento de Erros + +Resultados vazios: Retorna uma lista vazia `[]` com um log de aviso +Falha parcial na análise: Retorna uma lista de objetos analisados com sucesso com + logs de aviso para as falhas +Falha completa na análise: Retorna uma lista vazia `[]` com logs de aviso + +Isso difere de `response-type: "json"`, que lança `RuntimeError` em +caso de falha na análise. O comportamento tolerante para JSONL é intencional para fornecer +resiliência à truncagem. + +### Exemplo de Configuração + +Exemplo completo de configuração de prompt: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## Considerações de Segurança + +**Validação de Entrada**: A análise JSON utiliza o padrão `json.loads()`, que é seguro + contra ataques de injeção. +**Validação de Esquema**: Utiliza `jsonschema.validate()` para a aplicação do esquema. +<<<<<<< HEAD +**Sem Nova Superfície de Ataque**: A análise de JSONL é estritamente mais segura do que a análise de arrays JSON +======= +**Sem Nova Superfície de Ataque**: A análise JSONL é estritamente mais segura do que a análise de arrays JSON +>>>>>>> 82edf2d (New md files from RunPod) + devido ao processamento linha por linha. + +## Considerações de Desempenho + +**Memória**: A análise linha por linha usa menos memória máxima do que o carregamento de arrays JSON completos. + **Latência**: O desempenho da análise é comparável à análise de arrays JSON. +**Validação**: A validação de esquema é executada por objeto, o que adiciona sobrecarga, mas +permite resultados parciais em caso de falha na validação. + +<<<<<<< HEAD + +## Estratégia de Testes + +======= +## Estratégia de Testes + + +>>>>>>> 82edf2d (New md files from RunPod) +### Testes Unitários + +Análise de JSONL com entrada válida +Análise de JSONL com linhas vazias +Análise de JSONL com blocos de código Markdown +Análise de JSONL com linha final truncada +Análise de JSONL com linhas JSON inválidas intercaladas +Validação de esquema com uniões discriminadas `oneOf` +Compatibilidade com versões anteriores: prompts `"text"` e `"json"` existentes permanecem inalterados + +### Testes de Integração + +Extração ponta a ponta com prompts JSONL +Extração com truncamento simulado (resposta artificialmente limitada) +Extração de tipos mistos com discriminador de tipo +Extração de ontologia com todos os três tipos + +### Testes de Qualidade de Extração + +Compare os resultados da extração: formato JSONL versus array JSON. +Verifique a resiliência à truncagem: o JSONL produz resultados parciais onde o JSON falha. + +## Plano de Migração + +### Fase 1: Implementação + +1. Implemente o método `parse_jsonl()` em `PromptManager`. +2. Estenda `invoke()` para lidar com `response-type: "jsonl"`. +3. Adicione testes unitários. + +### Fase 2: Migração de Prompts + +1. Atualize o prompt e a configuração `extract-definitions`. +2. Atualize o prompt e a configuração `extract-relationships`. +3. Atualize o prompt e a configuração `extract-topics`. +4. Atualize o prompt e a configuração `extract-rows`. +5. Atualize o prompt e a configuração `agent-kg-extract`. +6. Atualize o prompt e a configuração `extract-with-ontologies`. + +### Fase 3: Atualizações para Sistemas Dependentes + +1. Atualize qualquer código que consuma os resultados da extração para lidar com o tipo de retorno de lista. +2. Atualize o código que categoriza extrações de tipos mistos pelo campo `type`. +<<<<<<< HEAD +3. Atualize os testes que afirmam o formato da saída da extração. +======= +3. Atualize os testes que afirmam o formato de saída da extração. +>>>>>>> 82edf2d (New md files from RunPod) + +## Perguntas Abertas + +Nenhuma neste momento. + +## Referências + +Implementação atual: `trustgraph-flow/trustgraph/template/prompt_manager.py` +Especificação JSON Lines: https://jsonlines.org/ +Esquema JSON `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof +Especificação relacionada: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`) diff --git a/docs/tech-specs/jsonl-prompt-output.ru.md b/docs/tech-specs/jsonl-prompt-output.ru.md new file mode 100644 index 00000000..536f0a43 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.ru.md @@ -0,0 +1,491 @@ +--- +layout: default +title: "Техническая спецификация формата вывода JSONL для запросов" +parent: "Russian (Beta)" +--- + +# Техническая спецификация формата вывода JSONL для запросов + +> **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. + +## Обзор + +Эта спецификация описывает реализацию формата вывода JSONL (JSON Lines) для ответов на запросы в TrustGraph. JSONL обеспечивает устойчивость к усечению при извлечении структурированных данных из ответов LLM, решая критические проблемы, связанные с повреждением выходных массивов JSON, когда ответы LLM достигают лимита токенов. + + + + + +Эта реализация поддерживает следующие сценарии использования: + +1. **Извлечение, устойчивое к усечению**: Извлекайте допустимые частичные результаты, даже когда + вывод LLM усекается в середине ответа. +<<<<<<< HEAD +2. **Извлечение в больших масштабах**: Обрабатывайте извлечение большого количества элементов без риска +======= +2. **Масштабное извлечение**: Обрабатывайте извлечение большого количества элементов без риска +>>>>>>> 82edf2d (New md files from RunPod) + полной сбоя из-за ограничений на количество токенов. +3. **Извлечение данных разных типов**: Поддерживайте извлечение нескольких типов сущностей + (определения, отношения, сущности, атрибуты) в одном запросе. +4. **Вывод, совместимый со стримингом**: Обеспечьте возможность будущей потоковой/инкрементной + обработки результатов извлечения. + +## Цели + +**Обратная совместимость**: Существующие запросы, использующие `response-type: "text"` и + `response-type: "json"`, продолжают работать без изменений. +**Устойчивость к усечению**: Частичные выходные данные LLM приводят к частичным, но допустимым результатам, + а не к полному сбою. +**Проверка схемы**: Поддержка проверки JSON-схемы для отдельных объектов. +**Дискриминированные объединения**: Поддержка выходных данных смешанных типов с использованием поля `type` + в качестве дискриминатора. +<<<<<<< HEAD +**Минимальные изменения API**: Расширение существующей конфигурации запросов с добавлением нового + типа ответа и ключа схемы. + +## Обзор +======= +**Минимальные изменения API**: Расширение существующей конфигурации запросов с помощью нового + типа ответа и ключа схемы. + +## Контекст +>>>>>>> 82edf2d (New md files from RunPod) + +### Текущая архитектура + +Сервис запросов поддерживает два типа ответов: + +1. `response-type: "text"` - Необработанный текстовый ответ, возвращаемый как есть. +2. `response-type: "json"` - JSON, полученный из ответа и проверенный на соответствие + необязательной `schema`. + +Текущая реализация в `trustgraph-flow/trustgraph/template/prompt_manager.py`: + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### Текущие ограничения + +Когда запросы извлечения требуют вывод в виде массивов JSON (`[{...}, {...}, ...]`): + +**Повреждение из-за усечения**: Если языковая модель достигает лимита выходных токенов в середине массива, + весь ответ становится недействительным JSON и не может быть проанализирован. +**Анализ "все или ничего"**: Необходимо получить полный вывод перед анализом. +**Нет частичных результатов**: Усеченный ответ дает нулевые полезные данные. +**Ненадежно для больших извлечений**: Чем больше извлеченных элементов, тем выше риск сбоя. + +Данная спецификация решает эти ограничения, вводя формат JSONL для +запросов извлечения, где каждый извлеченный элемент является полным JSON-объектом на своей +строке. + +## Техническое проектирование + +### Расширение типа ответа + +Добавьте новый тип ответа `"jsonl"` наряду с существующими типами `"text"` и `"json"`. + +#### Изменения конфигурации + +**Новое значение типа ответа:** + +``` +"response-type": "jsonl" +``` + +**Интерпретация схемы:** + +Существующий ключ `"schema"` используется как для `"json"`, так и для `"jsonl"` типов ответов. +Интерпретация зависит от типа ответа: + +`"json"`: Схема описывает весь ответ (обычно массив или объект). +`"jsonl"`: Схема описывает каждую отдельную строку/объект. + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +Это позволяет избежать изменений в инструментах и редакторах конфигурации подсказок. + +### Спецификация формата JSONL + +#### Простое извлечение + +Для подсказок, извлекающих один тип объекта (определения, отношения, +темы, строки), вывод представляет собой один объект JSON на строку без обертки: + +**Формат вывода подсказки:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +**Контраст с предыдущим форматом JSON-массива:** +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +Если LLM обрезает текст после строки 2, формат массива JSON приводит к недействительному JSON, +в то время как JSONL дает два допустимых объекта. + +#### Извлечение данных смешанных типов (дискриминированные объединения) + +Для запросов, извлекающих несколько типов объектов (например, определения и +отношения, или сущности, отношения и атрибуты), используйте поле `"type"` +в качестве дискриминатора: + +**Формат вывода запроса:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**Схема для дискриминированных объединений использует `oneOf`:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### Извлечение онтологии + +Для извлечения онтологии на основе сущностей, связей и атрибутов: + +**Формат вывода запроса:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### Детали реализации + +#### Класс Prompt + +Существующий класс `Prompt` не требует изменений. Поле `schema` используется повторно +<<<<<<< HEAD +для JSONL, а его интерпретация определяется `response_type`: +======= +для JSONL, и его интерпретация определяется `response_type`: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +Изменения не требуются - существующая загрузка конфигурации уже обрабатывает +ключ `schema`. + +#### Разбор JSONL + +Добавлен новый метод разбора ответов в формате JSONL: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### Изменения в PromptManager.invoke + +Расширить метод invoke для обработки нового типа ответа: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### Затронутые запросы + +Следующие запросы должны быть перенесены в формат JSONL: + +| Идентификатор запроса | Описание | Тип поля | +|-----------|-------------|------------| +| `extract-definitions` | Извлечение сущностей/определений | Нет (один тип) | +| `extract-relationships` | Извлечение отношений | Нет (один тип) | +| `extract-topics` | Извлечение темы/определения | Нет (один тип) | +| `extract-rows` | Извлечение структурированных строк | Нет (один тип) | +| `agent-kg-extract` | Комбинированное извлечение определений + отношений | Да: `"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | Извлечение на основе онтологии | Да: `"entity"`, `"relationship"`, `"attribute"` | + +### Изменения API + +#### Точка зрения клиента + +Разбор JSONL прозрачен для вызывающих API сервиса запросов. Разбор происходит +на стороне сервера в сервисе запросов, и ответ возвращается через стандартное +поле `PromptResponse.object` в виде сериализованного массива JSON. + +Когда клиенты вызывают сервис запросов (через `PromptClient.prompt()` или аналогично): + +**`response-type: "json"`** с схемой массива → клиент получает Python `list` +**`response-type: "jsonl"`** → клиент получает Python `list` + +С точки зрения клиента, оба возвращают идентичные структуры данных. Разница заключается только в том, как вывод LLM разбирается на стороне сервера: + + +Формат массива JSON: Один вызов `json.loads()`; полностью завершается с ошибкой, если усечен +Формат JSONL: Разбор построчно; дает частичные результаты, если усечен + +Это означает, что существующий клиентский код, ожидающий список от запросов извлечения, +не требует изменений при переносе запросов из формата JSON в формат JSONL. + +#### Возвращаемое значение сервера + +Для `response-type: "jsonl"` метод `PromptManager.invoke()` возвращает +`list[dict]`, содержащий все успешно разобранные и проверенные объекты. Этот +список затем сериализуется в JSON для поля `PromptResponse.object`. + +### Обработка ошибок + +Пустые результаты: Возвращает пустой список `[]` с предупреждением в журнале +Частная ошибка разбора: Возвращает список успешно разобранных объектов с + предупреждениями в журналах об ошибках +Полная ошибка разбора: Возвращает пустой список `[]` с предупреждениями в журналах + +Это отличается от `response-type: "json"`, который вызывает `RuntimeError` при +ошибке разбора. Легкое поведение для JSONL намеренно, чтобы обеспечить +устойчивость к усечению. + +### Пример конфигурации + +Полный пример конфигурации запроса: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## Соображения безопасности + +**Проверка входных данных**: Разбор JSON использует стандартную `json.loads()`, что безопасно + от атак внедрения. +**Проверка схемы**: Используется `jsonschema.validate()` для обеспечения соответствия схеме. +**Отсутствие новых уязвимостей**: Разбор JSONL значительно безопаснее, чем разбор JSON-массивов, + благодаря обработке построчно. + +## Соображения производительности + +**Память**: Построчный разбор использует меньше пиковой памяти, чем загрузка полных + JSON-массивов. +**Задержка**: Производительность разбора сопоставима с разбором JSON-массивов. +**Проверка**: Проверка схемы выполняется для каждого объекта, что добавляет накладные + расходы, но позволяет получать частичные результаты в случае сбоя проверки. + +## Стратегия тестирования + +### Юнит-тесты + +Разбор JSONL с допустимыми входными данными. +Разбор JSONL с пустыми строками. +<<<<<<< HEAD +Разбор JSONL с блоками форматированного текста Markdown. +======= +Разбор JSONL с блоками кода Markdown. +>>>>>>> 82edf2d (New md files from RunPod) +Разбор JSONL с обрезанной последней строкой. +Разбор JSONL со строками, содержащими недопустимый JSON. +Проверка схемы с использованием `oneOf` для дискриминируемых объединений. +Обратная совместимость: существующие `"text"` и `"json"` подсказки не изменены. + +### Интеграционные тесты + +<<<<<<< HEAD +Комплексная извлечение данных с использованием подсказок JSONL. +Извлечение данных с имитацией усечения (искусственно ограниченный ответ). +Извлечение данных смешанных типов с использованием дискриминатора типов. +Извлечение данных онтологии со всеми тремя типами. + +### Тесты качества извлечения данных. +======= +Комплексная извлечение с подсказками JSONL. +Извлечение с имитацией усечения (искусственно ограниченный ответ). +Извлечение смешанных типов с использованием дискриминатора типа. +Извлечение онтологии со всеми тремя типами. + +### Тесты качества извлечения. +>>>>>>> 82edf2d (New md files from RunPod) + +Сравнение результатов извлечения: формат JSONL против массива JSON. +Проверка устойчивости к усечению: JSONL возвращает частичные результаты, в то время как JSON - нет. + +## План миграции + +### Этап 1: Реализация + +1. Реализовать метод `parse_jsonl()` в `PromptManager`. +2. Расширить `invoke()` для обработки `response-type: "jsonl"`. +3. Добавить модульные тесты. + +### Этап 2: Миграция подсказок + +1. Обновить подсказку `extract-definitions` и конфигурацию. +2. Обновить подсказку `extract-relationships` и конфигурацию. +3. Обновить подсказку `extract-topics` и конфигурацию. +4. Обновить подсказку `extract-rows` и конфигурацию. +5. Обновить подсказку `agent-kg-extract` и конфигурацию. +6. Обновить подсказку `extract-with-ontologies` и конфигурацию. + +### Этап 3: Обновления для последующих этапов + +1. Обновить любой код, использующий результаты извлечения, чтобы он мог обрабатывать возвращаемый тип списка. +2. Обновить код, который категоризует извлечения смешанных типов, используя поле `type`. +3. Обновить тесты, которые проверяют формат выходных данных извлечения. + +## Открытые вопросы + +На данный момент нет. + +## Ссылки + +Текущая реализация: `trustgraph-flow/trustgraph/template/prompt_manager.py` +Спецификация JSON Lines: https://jsonlines.org/ +Схема JSON `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof +Связанная спецификация: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`) diff --git a/docs/tech-specs/jsonl-prompt-output.sw.md b/docs/tech-specs/jsonl-prompt-output.sw.md new file mode 100644 index 00000000..f18f84a9 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.sw.md @@ -0,0 +1,626 @@ +--- +layout: default +title: "MASHIRIKA YA KIUFUNZI YA TOKEZI YA JSONL" +parent: "Swahili (Beta)" +--- + +# MASHIRIKA YA KIUFUNZI YA TOKEZI YA JSONL + +> **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. + +## Utangulizi + +Mashirika haya yanamaanisha utekelezaji wa umbizo la tokeo la JSONL (JSON Lines) kwa majibu ya ombi katika TrustGraph. JSONL inaruhusu utoaji wa data iliyopangwa kwa ufanisi hata pale ombi linapotokea, ikishughulikia matatizo muhimu ambayo hutokea pale anwani za JSON zinapotokea wakati anwani za LLM zinafikia mipaka ya tokeni. + +Mashirika haya yanaunga mkono matumizi yafuatayo: + +1. **Utoaji wa Matokeo Bila Kukatizwa**: Kuondoa matokeo halali hata pale ombi linapotokea katikati ya jibu. +2. **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa kutokana na mipaka ya tokeni. +3. **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +4. **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mabadiliko Muhimu:** + +* **`response-type`**: Imewekwa kama `"jsonl"`. +* **`schema`**: Imerekebishwa ili kuendana na umbizo la JSONL. +* **`parse_jsonl()`**: Funzione mpya kwa utoaji wa JSONL. + +**Hati muhimu:** + +* **`docs/tech-specs/streaming-llm-responses.md`**: (Uhusiano na utoaji wa anwani) +* **`jsonlines.org`**: (Taarifa kuhusu JSON Lines) +* **`json-schema.org/understanding-json-schema/reference/combining.html#oneof`**: (Maelezo kuhusu "oneOf" katika schema ya JSON) + +**Kumbuka:** + +* Mashirika ya awali yaliyotumia `"json"` yatahitaji marekebisho ili kuendana na umbizo la JSONL. + +**Msisitizo:** + +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa kutokana na mipaka ya tokeni. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mambo Muhimu:** + +* **Urahisi wa Matumizi**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Upeo**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu). +* **Urahisi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Maelezo Mengine:** + +* **`response-type`**: Imewekwa kama `"jsonl"`. +* **`schema`**: Imerekebishwa ili kuendana na umbizo la JSONL. +* **`parse_jsonl()`**: Funzione mpya kwa utoaji wa JSONL. +* **`docs/tech-specs/streaming-llm-responses.md`**: (Uhusiano na utoaji wa anwani) +* **`jsonlines.org`**: (Taarifa kuhusu JSON Lines) +* **`json-schema.org/understanding-json-schema/reference/combining.html#oneof`**: (Maelezo kuhusu "oneOf" katika schema ya JSON) +* **Kumbuka**: Mashirika ya awali yaliyotumia `"json"` yatahitaji marekebisho ili kuendana na umbizo la JSONL. + +**Msisitizo**: Urahisi wa matumizi, upeo, aina mbalimbali, na urahisi. + +**Mambo Muhimu**: Urahisi wa matumizi, upeo, aina mbalimbali, na urahisi. + +**Mchakato wa Utekelezaji**: + +1. **Usanifu**: Utekelezaji wa mashirika na umbizo. +2. **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +3. **Usanifu**: Marekebisho na uboreshaji. +4. **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. + +**Mjadala wa Hatari**: + +* **Utoaji wa Data**: Hakikisha usalama wa data katika utoaji. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha usanifu na urahisi wa matumizi. +* **Uchunguzi**: Hakikisha utendakazi na ufanisi wa mashirika. +* **Marekebisho**: Marekebisho na uboreshaji wa mashirika. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji salama na ufanisi wa data. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Ufafanuzi wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha urahisi wa matumizi na usanifu. +* **Uchunguzi**: Hakikisha utendakazi na ufanisi wa mashirika. +* **Marekebisho**: Marekebisho na uboreshaji wa mashirika. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha urahisi wa matumizi na usanifu. +* **Uchunguzi**: Hakikisha utendakazi na ufanisi wa mashirika. +* **Marekebisho**: Marekebisho na uboreshaji wa mashirika. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Ufafanuzi wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha urahisi wa matumizi na usanifu. +* **Uchunguzi**: Hakikisha utendakazi na ufanisi wa mashirika. +* **Marekebisho**: Marekebisho na uboreshaji wa mashirika. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha urahisi wa matumizi na usanifu. +* **Uchunguzi**: Hakikisha utendakazi na ufanisi wa mashirika. +* **Marekebisho**: Marekebisho na uboreshaji wa mashirika. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Hakikisha urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakazi. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakazi na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakazi na ufanisi wa utoaji wa anwani. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakaji na ufanisi wa utoaji wa anwani. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Hakikisha utendakaji na ufanisi wa utoaji wa anwani. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mada Zinazohusiana**: + +* **Utoaji wa Data**: Utoaji wa data katika mfumo salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Mjadala wa Mada**: + +* **Utoaji wa Data**: Hakikisha usalama na ufanisi wa utoaji wa data. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. + +**Umuhimu wa Mada**: + +* **Utoaji wa Data**: Utoaji wa data salama na ufanisi. +* **Utoaji wa Anwani**: Utoaji wa anwani na utendakaji. +* **Usanifu**: Urahisi wa matumizi na usanifu. +* **Uchunguzi**: Uchunguzi wa utendakaji na ufanisi. +* **Marekebisho**: Marekebisho na uboreshaji. +* **Utoaji**: Utoaji wa mashirika yaliyorekebishwa. +* **Utoaji wa Matokeo Bila Kukatizwa**: Utoaji wa matokeo halali hata pale ombi linapotokea. +* **Utoaji wa Upeo Mkuu**: Kushughulikia uondoaji wa vitu vingi bila hatari ya kushindwa kabisa. +* **Utoaji wa Aina Mbalimbali**: Kusaidia uondoaji wa aina tofauti za vitu (ufafanuzi, uhusiano, vitu, safu) katika ombi moja. +* **Urahisi wa Usanidi**: Urahisi wa usanifu na matengenezo ya mashirika. diff --git a/docs/tech-specs/jsonl-prompt-output.tr.md b/docs/tech-specs/jsonl-prompt-output.tr.md new file mode 100644 index 00000000..7a08ab61 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.tr.md @@ -0,0 +1,556 @@ +--- +layout: default +title: "JSONL İstek Çıktısı Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# JSONL İstek Çıktısı 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'ta istek yanıtları için JSONL (JSON Lines) çıktı biçiminin uygulanmasını tanımlar. JSONL, LLM yanıtlarından yapılandırılmış verilerin, LLM yanıtları çıktı belirteç sınırlarına ulaştığında JSON dizisi çıktıları bozulduğunda ortaya çıkan kritik sorunları ele alarak, kesme hatalarına karşı dayanıklı bir şekilde çıkarılmasını sağlar. + + + + + +Bu uygulama, aşağıdaki kullanım senaryolarını destekler: + +1. **Kesintiye Dayanıklı Çıkarma**: LLM çıktısı yanıtın ortasında kesildiğinde bile geçerli kısmi sonuçları çıkarın. + +2. **Büyük Ölçekli Çıkarma**: Token limitleri nedeniyle tam bir başarısızlık riski olmadan birçok öğenin çıkarılmasını işleyin. + +3. **Karma Tip Çıkarma**: Tek bir istemde birden fazla varlık türünün (tanımlar, ilişkiler, varlıklar, özellikler) çıkarılmasını destekleyin. + +4. **Akışla Uyumlu Çıktı**: Çıkarma sonuçlarının gelecekteki akış/artımlı + işlenmesini sağlayın. + +## Hedefler + +<<<<<<< HEAD +**Geriye Dönük Uyumluluk**: `response-type: "text"` kullanan mevcut istemler ve + `response-type: "json"`, herhangi bir değişiklik yapılmadan çalışmaya devam eder. +**Kesinti Dayanıklılığı**: Kısmi LLM çıktıları, tam bir başarısızlık yerine kısmi, geçerli sonuçlar üretir. + +**Şema Doğrulama**: Bireysel nesneler için JSON şema doğrulamasını destekler. +**Ayırıcı Birleşimler**: `type` alanını kullanarak karma türlü çıktıları destekler. + +**Minimum API Değişiklikleri**: Mevcut istem yapılandırmasını, yeni + yanıt türü ve şema anahtarıyla genişletir. +======= +**Geriye Dönük Uyumluluk**: `response-type: "text"` ve + `response-type: "json"` kullanan mevcut istemler, herhangi bir değişiklik yapılmadan çalışmaya devam eder. +**Kesme Direnci**: Kısmi LLM çıktıları, tam bir başarısızlık yerine, kısmi geçerli sonuçlar üretir. + +**Şema Doğrulama**: Bireysel nesneler için JSON Şema doğrulamasını destekleyin. +**Ayırıcı Birleşimler**: `type` alanı kullanılarak farklı türlerde çıktıları destekleyin. + ayırıcı. +**Minimum API Değişiklikleri**: Mevcut istem yapılandırmasını yeni + yanıt türü ve şema anahtarıyla genişletin. +>>>>>>> 82edf2d (New md files from RunPod) + +## Arka Plan + +### Mevcut Mimari + +İstek hizmeti, iki tür yanıtı destekler: + +1. `response-type: "text"` - Ham metin yanıtı, olduğu gibi döndürülür. +2. `response-type: "json"` - Yanıttan ayrıştırılan JSON, isteğe bağlı `response-type: "json"`'a göre doğrulanır. + isteğe bağlı `schema` + +<<<<<<< HEAD +`trustgraph-flow/trustgraph/template/prompt_manager.py`'daki mevcut uygulama: +======= +Mevcut uygulama `trustgraph-flow/trustgraph/template/prompt_manager.py` içinde: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### Mevcut Sınırlamalar + +Çıkarma komutları, çıktıyı JSON dizileri (`[{...}, {...}, ...]`) olarak istediğinde: + +<<<<<<< HEAD +**Kesme nedeniyle oluşan bozulma**: Eğer LLM, dizi ortasında çıktı belirteç sınırlarına ulaştığında, + tüm yanıt geçersiz bir JSON haline gelir ve işlenemez. +**Tümünü veya hiçbirini işleme**: İşlemeye başlamadan önce tam çıktıyı almanız gerekir. +**Kısmi sonuçlar yok**: Kesilmiş bir yanıt, kullanılabilir veri olarak sıfır veri verir. +**Büyük çıkarmalar için güvenilir değil**: Çıkarılan öğe sayısı arttıkça, başarısızlık riski daha yüksektir. +======= +**Kesme bozulması**: Eğer LLM, dizi ortasında çıktı belirteç sınırlarına ulaştığında, + tüm yanıt geçersiz bir JSON haline gelir ve işlenemez. +**Tüm veya hiçbir işleme**: İşlemeye başlamadan önce tam çıktının alınması gerekir. +**Kısmi sonuçlar yok**: Kesilmiş bir yanıt, kullanılabilir veri olarak sıfır veri verir. +**Büyük çıkarmalar için güvenilir değil**: Çıkarılan öğe sayısı arttıkça, başarısızlık riski artar. +>>>>>>> 82edf2d (New md files from RunPod) + +Bu özellik, her çıkarılan öğenin kendi satırında bulunan tam bir JSON nesnesi olduğu JSONL formatını kullanarak, bu sınırlamaları ele alır. + + + +## Teknik Tasarım + +### Yanıt Tipi Genişletmesi + +Mevcut `"text"` ve `"json"` türlerinin yanı sıra yeni bir yanıt türü `"jsonl"` ekleyin. + +<<<<<<< HEAD + +#### Yapılandırma Değişiklikleri + +======= +#### Yapılandırma Değişiklikleri + +**Yeni yanıt türü değeri:** +>>>>>>> 82edf2d (New md files from RunPod) + +``` +"response-type": "jsonl" +``` + +**Şema yorumlaması:** + +Mevcut `"schema"` anahtarı, hem `"json"` hem de `"jsonl"` yanıtları için kullanılmaktadır. +Yorumlama, yanıt türüne bağlıdır: + +`"json"`: Şema, tüm yanıtı (genellikle bir dizi veya nesne) tanımlar. +`"jsonl"`: Şema, her bir satırı/nesneyi ayrı ayrı tanımlar. + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +Bu, istem yapılandırma araçlarına ve düzenleyicilere yapılan değişiklikleri önler. + +### JSONL Biçim Özellikleri + +#### Basit Çıkarma + +Tek bir nesne türünü (tanımlar, ilişkiler, +konular, satırlar) çıkaran istemler için, çıktı her satırda bir JSON nesnesidir ve herhangi bir sarma bulunmaz: + +**İstem çıktı biçimi:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +**Önceki JSON dizi formatıyla karşılaştırma:** +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +<<<<<<< HEAD +Eğer LLM, 2. satırdan sonra kesilirse, JSON dizisi formatı geçersiz bir JSON oluşturur, +ancak JSONL iki geçerli nesne üretir. + +#### Karışık Tip Çıkarımı (Ayırıcı Birleşimler) + +Birden fazla nesne türünü çıkaran (örneğin, hem tanımları hem de +ilişkileri, veya varlıklar, ilişkiler ve özellikler) istemler için, bir `"type"` +======= +Eğer LLM, 2. satırdan sonra kesilirse, JSON dizisi formatı geçersiz bir JSON oluştururken, +JSONL ise iki geçerli nesne üretir. + +#### Karışık Tip Çıkarımı (Ayırıcı Birleşimler) + +Birden fazla nesne türünü çıkaran (örneğin, hem tanımları ve +ilişkiler veya varlıklar, ilişkiler ve özellikler) istemler için, bir `"type"` +>>>>>>> 82edf2d (New md files from RunPod) +alanını ayırıcı olarak kullanın: + +**İstem çıktısı formatı:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +**Ayırıcı birleşimler için şema, `oneOf` kullanır:** +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +#### Ontoloji Çıkarımı + +Varlıklar, ilişkiler ve özelliklerle ontoloji tabanlı çıkarım için: + +**İstenen çıktı formatı:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### Uygulama Detayları + +#### İstek Sınıfı + +Mevcut `Prompt` sınıfı herhangi bir değişiklik gerektirmiyor. `schema` alanı yeniden kullanılıyor. +JSONL formatı için, yorumlanması `response_type` ile belirlenir: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +Herhangi bir değişiklik gerekli değil - mevcut yapılandırma yüklemesi zaten +`schema` anahtarını işlemektedir. + +#### JSONL Ayrıştırma + +JSONL yanıtları için yeni bir ayrıştırma yöntemi ekleyin: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### PromptManager.invoke Değişiklikleri + +Yeni yanıt türünü işleyebilmek için invoke yöntemini genişletin: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### Etkilenen İstekler + +Aşağıdaki istekler JSONL formatına aktarılmalıdır: + +| İstek Kimliği | Açıklama | Tür Alanı | +|-----------|-------------|------------| +| `extract-definitions` | Varlık/tanım çıkarma | Hayır (tek tür) | +| `extract-relationships` | İlişki çıkarma | Hayır (tek tür) | +| `extract-topics` | Konu/tanım çıkarma | Hayır (tek tür) | +| `extract-rows` | Yapılandırılmış satır çıkarma | Hayır (tek tür) | +| `agent-kg-extract` | Birleştirilmiş tanım + ilişki çıkarma | Evet: `"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | Ontoloji tabanlı çıkarma | Evet: `"entity"`, `"relationship"`, `"attribute"` | + +### API Değişiklikleri + +#### Müşteri Perspektifi + +<<<<<<< HEAD +JSONL ayrıştırması, istem hizmeti API'sini kullananlar için şeffaftır. Ayrıştırma, istem hizmetinde sunucu tarafında gerçekleşir ve yanıt standart +bir şekilde döndürülür. +`PromptResponse.object` alanını seri hale edilmiş bir JSON dizisi olarak. + +Müşteriler, istem hizmetini (`PromptClient.prompt()` veya benzeri bir yöntemle) kullandığında: + +**`response-type: "json"`** (dizi şeması ile) → müşteri, Python `list` alır. +**`response-type: "jsonl"`** → müşteri, Python `list` alır. + +Müşterinin bakış açısıyla, her iki yöntem de aynı veri yapılarını döndürür. +Fark, tamamen LLM çıktısının sunucu tarafında nasıl işlendiğindedir: + +JSON dizisi formatı: Tek `json.loads()` çağrısı; kısaltılırsa tamamen başarısız olur. +JSONL formatı: Satır satır ayrıştırma; kısaltılırsa kısmi sonuçlar verir. + +Bu, çıkarma istemlerinden bir liste bekleyen mevcut istemci kodunun, istemleri JSON'dan JSONL formatına geçirirken herhangi bir değişikliğe ihtiyaç duymamasını sağlar. + + +#### Sunucu Dönüş Değeri + +`response-type: "jsonl"` için, `PromptManager.invoke()` metodu, +başarıyla ayrıştırılmış ve doğrulanmış tüm nesneleri içeren bir `list[dict]` döndürür. Bu +liste, daha sonra `PromptResponse.object` alanı için JSON'a dönüştürülür. + +#### Hata Yönetimi + +Boş sonuçlar: Uyarı günlüğü ile boş bir liste `[]` döndürür. +Kısmi ayrıştırma hatası: Başarıyla ayrıştırılmış nesnelerin bir listesini ve + hatalar için uyarı günlüklerini döndürür. +Tam ayrıştırma hatası: Uyarı günlükleriyle boş bir liste `[]` döndürür. + +Bu, `response-type: "json"`'den farklıdır, çünkü `RuntimeError` ayrıştırma hatası durumunda `RuntimeError` hatası oluşturur. +JSONL için daha hoşgörülü davranış, kesintilere karşı dayanıklılık sağlamak amacıyla kasıtlıdır. +======= +JSONL ayrıştırması, istek hizmeti API kullanıcıları için şeffaftır. Ayrıştırma, isteğin +sunucu tarafında gerçekleşir ve yanıt, standart +`PromptResponse.object` alanı aracılığıyla seri hale getirilmiş bir JSON dizisi olarak döndürülür. + +Müşteriler, istek hizmetini (`PromptClient.prompt()` veya benzeri aracılığıyla) çağırdığında: + +**`response-type: "json"`** dizi şeması ile → müşteri, Python `list` alır +**`response-type: "jsonl"`** → müşteri, Python `list` alır + +Müşteri açısından, her iki yöntem de aynı veri yapılarını döndürür. Fark, yalnızca LLM çıktısının +sunucu tarafında nasıl ayrıştırıldığıdır: + +JSON dizisi formatı: Tek `json.loads()` çağrısı; kesintiye uğratılırsa tamamen başarısız olur +JSONL formatı: Satır satır ayrıştırma; kesintiye uğratılırsa kısmi sonuçlar verir + +Bu, çıkarma isteklerinden gelen listeleri bekleyen mevcut müşteri kodunun, +istekleri JSON'dan JSONL formatına geçirirken herhangi bir değişikliğe ihtiyaç duymamasını sağlar. + +#### Sunucu Dönüş Değeri + +`response-type: "jsonl"` için, `PromptManager.invoke()` yöntemi bir +`list[dict]` döndürür ve bu, başarıyla ayrıştırılmış ve doğrulanmış tüm nesneleri içerir. +Bu liste daha sonra `PromptResponse.object` alanı için JSON'a seri hale getirilir. + +#### Hata Yönetimi + +Boş sonuçlar: Uyarı günlüğü ile boş bir liste `[]` döndürülür +Kısmi ayrıştırma hatası: Başarıyla ayrıştırılmış nesnelerin listesi, hatalar için + uyarı günlükleriyle birlikte döndürülür +Tam ayrıştırma hatası: Uyarı günlükleriyle boş bir liste `[]` döndürülür + +Bu, ayrıştırma hatası durumunda `RuntimeError`'i yükselten `response-type: "json"`'dan farklıdır. +JSONL için esnek davranış, kesintiye karşı dayanıklılık sağlamak için kasıtlıdır. +>>>>>>> 82edf2d (New md files from RunPod) + + +### Yapılandırma Örneği + +<<<<<<< HEAD +Tam istem yapılandırma örneği: +======= +Tam istek yapılandırma örneği: +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## Güvenlik Hususları + +**Girdi Doğrulama**: JSON ayrıştırması, standart `json.loads()`'ı kullanır ve bu, enjeksiyon saldırılarına karşı güvenlidir. + **Şema Doğrulama**: Şema zorlaması için ⟦CODE_0⟧ kullanılır. +**Şema Doğrulama**: Şema uyumluluğunu sağlamak için `jsonschema.validate()` kullanılır. +**Yeni Bir Saldırı Yüzeyi Yok**: JSONL ayrıştırması, satır satır işlenmesi nedeniyle JSON dizisi ayrıştırmasından çok daha güvenlidir. + + +## Performans Hususları + +**Bellek**: Satır satır ayrıştırma, tam JSON dizilerini yüklemekten daha az bellek kullanır. +<<<<<<< HEAD + **Gecikme**: Ayrıştırma performansı, JSON dizisi ayrıştırmasıyla karşılaştırılabilir. +**Doğrulama**: Şema doğrulaması, her bir nesne için yapılır, bu da ek yük getirir ancak +doğrulama başarısız olduğunda kısmi sonuçlar elde etmeyi sağlar. + +## Test Stratejisi + +======= + +**Gecikme**: Ayrıştırma performansı, JSON dizisi ayrıştırmasıyla karşılaştırılabilir. +**Doğrulama**: Şema doğrulaması, her bir nesne için yapılır, bu da ek yük getirir ancak + doğrulama başarısız olduğunda kısmi sonuçlar elde etmeyi sağlar. + +## Test Stratejisi +>>>>>>> 82edf2d (New md files from RunPod) + +### Birim Testleri + +Geçerli giriş ile JSONL ayrıştırma +Boş satırlarla JSONL ayrıştırma +Markdown kod bloklarıyla JSONL ayrıştırma +Kesilmiş son satırla JSONL ayrıştırma +Geçersiz JSON satırlarının arasına serpiştirilmiş JSONL ayrıştırma +`oneOf` ayrımcı birleşimlerle şema doğrulaması +Geriye dönük uyumluluk: Mevcut `"text"` ve `"json"` istemleri değişmeden kalır + +### Entegrasyon Testleri + +JSONL istemleriyle uçtan uca çıkarma +Simüle edilmiş kesme ile çıkarma (yapay olarak sınırlı yanıt) +Tür ayrımcısı ile karma tür çıkarma +Üç türün tamamıyla ontoloji çıkarma + +### Çıkarma Kalitesi Testleri + +Çıkarma sonuçlarını karşılaştırın: JSONL ile JSON dizisi formatı +Kesme dayanıklılığını doğrulayın: JSONL, JSON'un başarısız olduğu durumlarda kısmi sonuçlar verir + +## Geçiş Planı + +### 1. Aşama: Uygulama + +1. `parse_jsonl()` yöntemini `PromptManager` içinde uygulayın +2. `invoke()`'ı `response-type: "jsonl"`'i işleyebilecek şekilde genişletin +3. Birim testleri ekleyin + +### 2. Aşama: İstek Geçişi + +1. `extract-definitions` isteğini ve yapılandırmasını güncelleyin +2. `extract-relationships` isteğini ve yapılandırmasını güncelleyin +3. `extract-topics` isteğini ve yapılandırmasını güncelleyin +4. `extract-rows` isteğini ve yapılandırmasını güncelleyin +5. `agent-kg-extract` isteğini ve yapılandırmasını güncelleyin +6. `extract-with-ontologies` isteğini ve yapılandırmasını güncelleyin + +### 3. Aşama: Aşağı Akış Güncellemeleri + +1. Çıkarma sonuçlarını kullanan tüm kodu, liste dönüş türünü işleyebilecek şekilde güncelleyin +<<<<<<< HEAD +2. `type` alanına göre karma türdeki çıkarma sonuçlarını kategorize eden kodu güncelleyin +======= +2. `type` alanıyla karma türdeki çıkarma türlerini sınıflandıran kodu güncelleyin +>>>>>>> 82edf2d (New md files from RunPod) +3. Çıkarma çıktısı formatı hakkında doğrulama yapan testleri güncelleyin + +## Açık Sorular + +Şu anda yok. + +## Referanslar + +Mevcut uygulama: `trustgraph-flow/trustgraph/template/prompt_manager.py` +JSON Lines belirtimi: https://jsonlines.org/ +JSON Şeması `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof +İlgili belirtim: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`) diff --git a/docs/tech-specs/jsonl-prompt-output.zh-cn.md b/docs/tech-specs/jsonl-prompt-output.zh-cn.md new file mode 100644 index 00000000..a2ac42e9 --- /dev/null +++ b/docs/tech-specs/jsonl-prompt-output.zh-cn.md @@ -0,0 +1,532 @@ +--- +layout: default +title: "JSONL 提示输出技术规范" +parent: "Chinese (Beta)" +--- + +# JSONL 提示输出技术规范 + +> **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. + +## 概述 + +<<<<<<< HEAD +本规范描述了在 TrustGraph 中,用于提示响应的 JSONL(JSON Lines)输出格式的实现。JSONL 允许在大型语言模型(LLM)的响应中,以一种能够抵抗截断的方式提取结构化数据,从而解决了当 LLM 响应达到输出令牌限制时,JSON 数组输出可能被损坏的关键问题。 +======= +本规范描述了在 TrustGraph 中,用于提示响应的 JSONL(JSON Lines)输出格式的实现。JSONL 允许在大型语言模型 (LLM) 响应中提取结构化数据,即使在响应达到输出令牌限制时,也能保持数据的完整性。 +JSONL 能够实现对结构化数据的截断鲁棒性提取,解决了当 LLM 响应达到输出令牌限制时,JSON 数组输出可能被破坏的关键问题。 +>>>>>>> 82edf2d (New md files from RunPod) + + + + +<<<<<<< HEAD + +======= +>>>>>>> 82edf2d (New md files from RunPod) +本实现支持以下用例: + +1. **抗截断提取**: 即使当 + LLM 输出在响应过程中被截断时,也能提取有效的中间结果。 +2. **大规模提取**: 能够处理大量项的提取,而不会因 token 限制导致完全失败的风险。 + 3. **混合类型提取**: 支持在单个提示中提取多种实体类型(定义、关系、实体、属性)。 +4. **支持流式输出**: 允许对提取结果进行未来的流式/增量处理。 + +## 目标 + + +## 目标 + +**向后兼容性**: 仍然可以使用 `response-type: "text"` 和 + `response-type: "json"` 的现有提示,无需修改即可继续工作。 +<<<<<<< HEAD +**截断恢复能力**: 即使是部分 LLM 输出,也能产生部分有效的结果, + 而不是完全失败。 +**模式验证**: 支持对单个对象进行 JSON 模式验证。 +**区分联合类型**: 支持使用 `type` 字段作为区分器的混合类型输出。 + **最小的 API 变更**: 通过新的 +======= +**截断鲁棒性**: 即使是部分 LLM 输出,也能产生部分有效的结果, + 而不是完全失败。 +**模式验证**: 支持对单个对象进行 JSON 模式验证。 +**区分联合**: 支持使用 `type` 字段作为区分器的混合类型输出。 + **最小的 API 更改**: 通过新的 +>>>>>>> 82edf2d (New md files from RunPod) +响应类型和模式键来扩展现有的提示配置。 + + +## 背景 + +### 当前架构 + +提示服务支持两种响应类型: + +1. `response-type: "text"` - 原始文本响应,按原样返回。 +2. `response-type: "json"` - 从响应中解析的 JSON 数据,并根据 + 可选的 `schema` 进行验证。 + +当前在 `trustgraph-flow/trustgraph/template/prompt_manager.py` 中的实现: + +```python +class Prompt: + def __init__(self, template, response_type = "text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema +``` + +### 当前限制 + +当提取提示要求输出为 JSON 数组 (`[{...}, {...}, ...]`) 时: + +**截断损坏:** 如果 LLM 在数组中间达到输出令牌限制,则整个响应变为无效的 JSON,无法解析。 + **全或无解析:** 必须接收完整的输出才能进行解析。 +**没有部分结果:** 截断的响应会产生零可用数据。 +**不适用于大型提取:** 提取的项目越多,失败的风险越高。 + + +此规范通过引入 JSONL 格式来解决这些限制,其中每个提取的项目都是一个完整的 JSON 对象,位于其自己的行上。 + + + +## 技术设计 + +### 响应类型扩展 + +添加一个新的响应类型 `"jsonl"`,与现有的 `"text"` 和 `"json"` 类型并列。 + +#### 配置更改 + +**新的响应类型值:** + +``` +"response-type": "jsonl" +``` + +**模式解释:** + +现有的 `"schema"` 键同时用于 `"json"` 和 `"jsonl"` 响应类型。 +解释取决于响应类型: + +`"json"`:模式描述整个响应(通常是数组或对象)。 +`"jsonl"`:模式描述每个单独的行/对象。 + +```json +{ + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["entity", "definition"] + } +} +``` + +<<<<<<< HEAD +这避免了对提示配置工具和编辑器的修改。 +======= +这避免了对提示配置工具和编辑器的更改。 +>>>>>>> 82edf2d (New md files from RunPod) + +### JSONL 格式规范 + +#### 简单提取 + +对于提取单一类型对象(定义、关系、 +主题、行)的提示,输出为每行一个 JSON 对象,没有包装: + +**提示输出格式:** +``` +{"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"} +{"entity": "chlorophyll", "definition": "Green pigment in plants"} +{"entity": "mitochondria", "definition": "Powerhouse of the cell"} +``` + +**与之前的 JSON 数组格式对比:** +```json +[ + {"entity": "photosynthesis", "definition": "Process by which plants convert sunlight"}, + {"entity": "chlorophyll", "definition": "Green pigment in plants"}, + {"entity": "mitochondria", "definition": "Powerhouse of the cell"} +] +``` + +<<<<<<< HEAD +如果大型语言模型在第2行之后截断,JSON数组格式会产生无效的JSON, +而JSONL会产生两个有效的对象。 +======= +如果大型语言模型在第2行之后截断,JSON数组格式将产生无效的JSON, +而JSONL格式将产生两个有效的对象。 +>>>>>>> 82edf2d (New md files from RunPod) + +#### 混合类型提取(区分联合) + +对于需要提取多种类型对象(例如,定义和 +关系,或者实体、关系和属性)的提示,请使用一个 `"type"` +字段作为区分器: + +**提示输出格式:** +``` +{"type": "definition", "entity": "DNA", "definition": "Molecule carrying genetic instructions"} +{"type": "relationship", "subject": "DNA", "predicate": "located_in", "object": "cell nucleus", "object-entity": true} +{"type": "definition", "entity": "RNA", "definition": "Molecule that carries genetic information"} +{"type": "relationship", "subject": "RNA", "predicate": "transcribed_from", "object": "DNA", "object-entity": true} +``` + +<<<<<<< HEAD +**区分联合的模式使用 `oneOf`:** +======= +**区分联合的模式使用 `oneOf`:** +>>>>>>> 82edf2d (New md files from RunPod) +```json +{ + "response-type": "jsonl", + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { "const": "definition" }, + "entity": { "type": "string" }, + "definition": { "type": "string" } + }, + "required": ["type", "entity", "definition"] + }, + { + "type": "object", + "properties": { + "type": { "const": "relationship" }, + "subject": { "type": "string" }, + "predicate": { "type": "string" }, + "object": { "type": "string" }, + "object-entity": { "type": "boolean" } + }, + "required": ["type", "subject", "predicate", "object", "object-entity"] + } + ] + } +} +``` + +<<<<<<< HEAD +#### 本体抽取 + +对于基于本体的抽取,涉及实体、关系和属性: +======= +#### 本体提取 + +对于基于本体的实体、关系和属性提取: +>>>>>>> 82edf2d (New md files from RunPod) + +**提示输出格式:** +``` +{"type": "entity", "entity": "Cornish pasty", "entity_type": "fo/Recipe"} +{"type": "entity", "entity": "beef", "entity_type": "fo/Food"} +{"type": "relationship", "subject": "Cornish pasty", "subject_type": "fo/Recipe", "relation": "fo/has_ingredient", "object": "beef", "object_type": "fo/Food"} +{"type": "attribute", "entity": "Cornish pasty", "entity_type": "fo/Recipe", "attribute": "fo/serves", "value": "4 people"} +``` + +### 实现细节 + +#### 提示类 + +现有的`Prompt`类不需要进行任何更改。 `schema`字段将被重用。 +用于 JSONL 格式,其解释由 `response_type` 决定: + +```python +class Prompt: + def __init__(self, template, response_type="text", terms=None, schema=None): + self.template = template + self.response_type = response_type + self.terms = terms + self.schema = schema # Interpretation depends on response_type +``` + +#### PromptManager.load_config + +无需修改 - 现有的配置加载已经处理了 +`schema` 键。 + +#### JSONL 解析 + +添加一种新的解析方法,用于解析 JSONL 格式的响应: + +```python +def parse_jsonl(self, text): + """ + Parse JSONL response, returning list of valid objects. + + Invalid lines (malformed JSON, empty lines) are skipped with warnings. + This provides truncation resilience - partial output yields partial results. + """ + results = [] + + for line_num, line in enumerate(text.strip().split('\n'), 1): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Skip markdown code fence markers if present + if line.startswith('```'): + continue + + try: + obj = json.loads(line) + results.append(obj) + except json.JSONDecodeError as e: + # Log warning but continue - this provides truncation resilience + logger.warning(f"JSONL parse error on line {line_num}: {e}") + + return results +``` + +#### PromptManager.invoke 变更 + +扩展 invoke 方法以处理新的响应类型: + +```python +async def invoke(self, id, input, llm): + logger.debug("Invoking prompt template...") + + terms = self.terms | self.prompts[id].terms | input + resp_type = self.prompts[id].response_type + + prompt = { + "system": self.system_template.render(terms), + "prompt": self.render(id, input) + } + + resp = await llm(**prompt) + + if resp_type == "text": + return resp + + if resp_type == "json": + try: + obj = self.parse_json(resp) + except: + logger.error(f"JSON parse failed: {resp}") + raise RuntimeError("JSON parse fail") + + if self.prompts[id].schema: + try: + validate(instance=obj, schema=self.prompts[id].schema) + logger.debug("Schema validation successful") + except Exception as e: + raise RuntimeError(f"Schema validation fail: {e}") + + return obj + + if resp_type == "jsonl": + objects = self.parse_jsonl(resp) + + if not objects: + logger.warning("JSONL parse returned no valid objects") + return [] + + # Validate each object against schema if provided + if self.prompts[id].schema: + validated = [] + for i, obj in enumerate(objects): + try: + validate(instance=obj, schema=self.prompts[id].schema) + validated.append(obj) + except Exception as e: + logger.warning(f"Object {i} failed schema validation: {e}") + return validated + + return objects + + raise RuntimeError(f"Response type {resp_type} not known") +``` + +### 受影响的提示语 + +以下提示语应迁移到 JSONL 格式: + +| 提示语 ID | 描述 | 类型字段 | +|-----------|-------------|------------| +| `extract-definitions` | 实体/定义提取 | 否(单个类型)| +| `extract-relationships` | 关系提取 | 否(单个类型)| +| `extract-topics` | 主题/定义提取 | 否(单个类型)| +| `extract-rows` | 结构化行提取 | 否(单个类型)| +| `agent-kg-extract` | 组合定义 + 关系提取 | 是:`"definition"`, `"relationship"` | +| `extract-with-ontologies` / `ontology-extract` | 基于本体的提取 | 是:`"entity"`, `"relationship"`, `"attribute"` | + +### API 变更 + +#### 客户端视角 + +JSONL 解析对提示服务 API 的调用者是透明的。解析过程 +在提示服务的服务器端进行,响应通过标准的 +`PromptResponse.object` 字段以序列化的 JSON 数组形式返回。 + +当客户端调用提示服务(通过 `PromptClient.prompt()` 或类似方式时): + +<<<<<<< HEAD +**`response-type: "json"`**(带有数组模式)→ 客户端接收 Python `list` +**`response-type: "jsonl"`** → 客户端接收 Python `list` + +从客户端的角度来看,两者都返回相同的的数据结构。 +======= +**`response-type: "json"`** (带有数组模式) → 客户端接收 Python `list` +**`response-type: "jsonl"`** → 客户端接收 Python `list` + +从客户端的角度来看,两者都返回相同的数据结构。 +>>>>>>> 82edf2d (New md files from RunPod) +区别完全在于服务器端如何解析 LLM 的输出: + +JSON 数组格式:单个 `json.loads()` 调用;如果被截断,则完全失败。 +JSONL 格式:逐行解析;如果被截断,则产生部分结果。 + +这意味着,现有的客户端代码期望从提取提示中获得列表, +在将提示从 JSON 迁移到 JSONL 格式时,不需要进行任何更改。 + +#### 服务器返回值 + +对于 `response-type: "jsonl"`,`PromptManager.invoke()` 方法返回一个 +`list[dict]`,其中包含所有成功解析和验证的对象。 此 +列表随后被序列化为 JSON,用于 `PromptResponse.object` 字段。 + +#### 错误处理 + +空结果:返回一个空列表 `[]`,并带有警告日志。 +部分解析失败:返回成功解析的对象列表, + 并为解析失败的情况记录警告日志。 +完全解析失败:返回一个空列表 `[]`,并带有警告日志。 + +这与 `response-type: "json"` 不同,后者会在解析失败时引发 `RuntimeError`。 +对于 JSONL 的宽松处理是故意的,目的是为了提供截断恢复能力。 + + +### 配置示例 + +完整的提示配置示例: + +```json +{ + "prompt": "Extract all entities and their definitions from the following text. Output one JSON object per line.\n\nText:\n{{text}}\n\nOutput format per line:\n{\"entity\": \"\", \"definition\": \"\"}", + "response-type": "jsonl", + "schema": { + "type": "object", + "properties": { + "entity": { + "type": "string", + "description": "The entity name" + }, + "definition": { + "type": "string", + "description": "A clear definition of the entity" + } + }, + "required": ["entity", "definition"] + } +} +``` + +## 安全注意事项 + +**输入验证**: JSON 解析使用标准的 `json.loads()`,这可以防止注入攻击。 + **模式验证**: 使用 ⟦CODE_0⟧ 来强制执行模式。 +**模式验证**: 使用 `jsonschema.validate()` 进行模式强制。 +<<<<<<< HEAD +**没有新的攻击面:** JSONL 解析比 JSON 数组解析更安全,因为它采用逐行处理的方式。 +======= +**无新的攻击面**: JSONL 解析比 JSON 数组解析更安全,因为采用逐行处理的方式。 +>>>>>>> 82edf2d (New md files from RunPod) + parsing due to line-by-line processing + +## 性能考量 + +**内存**: 逐行解析比加载完整的 JSON 数组消耗更少的峰值内存。 + **延迟**: 解析性能与 JSON 数组解析相当。 +**验证**: 模式验证按对象进行,这会增加开销,但 +可以在验证失败时提供部分结果。 + +## 测试策略 + + +### 单元测试 + +使用有效输入的 JSONL 解析 +使用空行的 JSONL 解析 +使用 Markdown 代码块的 JSONL 解析 +使用截断的最终行的 JSONL 解析 +包含穿插无效 JSON 行的 JSONL 解析 +使用 `oneOf` 区分联合的模式验证 +<<<<<<< HEAD +向后兼容性:现有的 `"text"` 和 `"json"` 提示词保持不变 + +### 集成测试 + +使用 JSONL 提示词的端到端提取 +======= +向后兼容性:现有的 `"text"` 和 `"json"` 提示保持不变 + +### 集成测试 + +使用 JSONL 提示的端到端提取 +>>>>>>> 82edf2d (New md files from RunPod) +使用模拟截断的提取(人为限制响应) +使用类型区分器的混合类型提取 +使用所有三种类型的本体提取 + +### 提取质量测试 + +比较提取结果:JSONL 与 JSON 数组格式 +验证截断恢复能力:JSONL 在 JSON 失败的情况下,可以产生部分结果 + +## 迁移计划 + +### 第一阶段:实施 + +1. 在 `parse_jsonl()` 中实现 `PromptManager` 方法 +2. 扩展 `invoke()` 以处理 `response-type: "jsonl"` +3. 添加单元测试 + +<<<<<<< HEAD +### 第二阶段:提示词迁移 + +1. 更新 `extract-definitions` 提示词和配置 +2. 更新 `extract-relationships` 提示词和配置 +3. 更新 `extract-topics` 提示词和配置 +4. 更新 `extract-rows` 提示词和配置 +5. 更新 `agent-kg-extract` 提示词和配置 +6. 更新 `extract-with-ontologies` 提示词和配置 +======= +### 第二阶段:提示迁移 + +1. 更新 `extract-definitions` 提示和配置 +2. 更新 `extract-relationships` 提示和配置 +3. 更新 `extract-topics` 提示和配置 +4. 更新 `extract-rows` 提示和配置 +5. 更新 `agent-kg-extract` 提示和配置 +6. 更新 `extract-with-ontologies` 提示和配置 +>>>>>>> 82edf2d (New md files from RunPod) + +### 第三阶段:下游更新 + +1. 更新任何使用提取结果的代码,使其能够处理列表返回类型。 +2. 更新根据 `type` 字段对混合类型提取进行分类的代码。 +<<<<<<< HEAD +3. 更新用于断言提取输出格式的测试。 +======= +3. 更新断言提取输出格式的测试。 +>>>>>>> 82edf2d (New md files from RunPod) + +## 待解决问题 + +目前没有。 + +## 参考文献 + +当前实现:`trustgraph-flow/trustgraph/template/prompt_manager.py` +JSON Lines 规范:https://jsonlines.org/ +JSON Schema `oneOf`:https://json-schema.org/understanding-json-schema/reference/combining.html#oneof +相关规范:Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`) diff --git a/docs/tech-specs/large-document-loading.ar.md b/docs/tech-specs/large-document-loading.ar.md new file mode 100644 index 00000000..1351c84e --- /dev/null +++ b/docs/tech-specs/large-document-loading.ar.md @@ -0,0 +1,992 @@ +--- +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. **معالجة ملفات PDF الكبيرة**: تحميل ومعالجة ملفات PDF متعددة الميجابايت + دون استنفاد الذاكرة +2. **التحميل القابل للاستئناف**: السماح للتحميلات المتقطعة بمواصلة من حيث + توقفت بدلاً من إعادة البدء +3. **ملاحظات التقدم**: تزويد المستخدمين برؤية في الوقت الفعلي لعملية التحميل + والمعالجة +4. **معالجة فعالة للذاكرة**: معالجة المستندات بطريقة متدفقة + دون الاحتفاظ بملفات كاملة في الذاكرة + +## الأهداف + +**التحميل التدريجي**: دعم تحميل المستندات على شكل أجزاء عبر REST و WebSocket +**التحويلات القابلة للاستئناف**: تمكين الاسترداد من التحميلات المتقطعة +**رؤية التقدم**: توفير ملاحظات حول تقدم التحميل/المعالجة للعملاء +**كفاءة الذاكرة**: القضاء على التخزين المؤقت للمستند بأكمله في جميع أنحاء المسار +**التوافق مع الإصدارات السابقة**: تظل سير العمل الحالية للمستندات الصغيرة دون تغيير +**المعالجة المتدفقة**: تعمل فك ترميز PDF وتقطيع النص على التدفقات + +## الخلفية + +### البنية الحالية + +يمر تدفق إرسال المستندات عبر المسار التالي: + +1. يرسل **العميل** المستند عبر REST (`POST /api/v1/librarian`) أو WebSocket +2. يتلقى **بوابة API** الطلب الكامل مع محتوى المستند المشفر بـ base64 +3. يترجم **LibrarianRequestor** الطلب إلى رسالة Pulsar +4. يتلقى **خدمة Librarian** الرسالة، ويفك تشفير المستند في الذاكرة +5. يقوم **BlobStore** بتحميل المستند إلى Garage/S3 +6. تخزن **Cassandra** البيانات الوصفية مع مرجع الكائن +7. للمعالجة: يتم استرداد المستند من S3، وفك ترميزه، وتقطيعه - كل ذلك في الذاكرة + +الملفات الرئيسية: +نقطة الدخول REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +النواة الأساسية لـ Librarian: `trustgraph-flow/trustgraph/librarian/librarian.py` +تخزين الكائنات الثنائية: `trustgraph-flow/trustgraph/librarian/blob_store.py` +جداول Cassandra: `trustgraph-flow/trustgraph/tables/library.py` +مخطط API: `trustgraph-base/trustgraph/schema/services/library.py` + +### القيود الحالية + +تحتوي التصميم الحالي على عدة مشكلات مركبة في الذاكرة وتجربة المستخدم: + +1. **عملية تحميل ذرية**: يجب إرسال المستند بأكمله في + طلب واحد. تتطلب المستندات الكبيرة طلبات طويلة الأمد بدون + مؤشر للتقدم ولا توجد آلية لإعادة المحاولة في حالة فشل الاتصال. + +2. **تصميم API**: تتوقع كل من واجهات برمجة تطبيقات REST و WebSocket المستند + بأكمله في رسالة واحدة. يحتوي المخطط (`LibrarianRequest`) على `content` + حقل واحد يحتوي على المستند المشفر بـ base64 بأكمله. + +3. **ذاكرة Librarian**: تقوم خدمة Librarian بفك تشفير المستند بأكمله + في الذاكرة قبل تحميله إلى S3. بالنسبة لملف PDF بحجم 500 ميجابايت، هذا يعني + الاحتفاظ بـ 500 ميجابايت + في ذاكرة العملية. + +4. **ذاكرة فك ترميز PDF**: عند بدء المعالجة، يقوم فك ترميز PDF بتحميل + ملف PDF بأكمله في الذاكرة لاستخراج النص. تتطلب مكتبات PyPDF وما شابه ذلك + عادةً الوصول إلى المستند بأكمله. + +5. **ذاكرة القطع**: يتلقى برنامج القطع النص المستخرج بالكامل + ويحتفظ به في الذاكرة أثناء إنتاج الأجزاء. + +**مثال على تأثير الذاكرة** (ملف PDF بحجم 500 ميجابايت): +البوابة: ~700 ميجابايت (نفقات ترميز base64) +Librarian: ~500 ميجابايت (بايت مُفككة) +فك ترميز PDF: ~500 ميجابايت + مخازن مؤقتة للاستخراج +القطع: نص مستخرج (متغير، قد يصل إلى 100 ميجابايت +) + +يمكن أن تتجاوز الذاكرة القصوى لملف مستند كبير واحد 2 جيجابايت. + +## التصميم الفني + +### مبادئ التصميم + +1. **واجهة API**: يمر كل تفاعل عميل من خلال واجهة برمجة تطبيقات Librarian. العملاء + ليس لديهم وصول مباشر أو معرفة بالتخزين الأساسي S3/Garage. + +2. **تحميل متعدد الأجزاء لـ S3**: استخدم تحميل متعدد الأجزاء قياسي لـ S3. + هذا مدعوم على نطاق واسع في الأنظمة المتوافقة مع S3 (AWS S3، MinIO، Garage، + Ceph، DigitalOcean Spaces، Backblaze B2، إلخ) مما يضمن إمكانية النقل. + +3. **الإكمال الذري**: عمليات تحميل متعددة الأجزاء لـ S3 ذرية بطبيعتها - يتم تحميل + الأجزاء التي تم تحميلها والتي لا تظهر حتى يتم استدعاء `CompleteMultipartUpload`. لا توجد + ملفات مؤقتة أو عمليات إعادة تسمية مطلوبة. + +4. **حالة قابلة للتتبع**: يتم تتبع جلسات التحميل في Cassandra، مما يوفر + رؤية للتحميلات غير المكتملة ويمكنه تمكين إمكانية الاستئناف. + +### تدفق التحميل المقسم + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +العميل لا يتفاعل أبدًا مع S3 مباشرةً. يقوم المكتبار بترجمة البيانات بين +واجهة برمجة التطبيقات الخاصة بنا لتحميل البيانات على أجزاء و عمليات S3 متعددة الأجزاء داخليًا. + +### عمليات واجهة برمجة التطبيقات الخاصة بالمكتبار + +#### `begin-upload` + +تهيئة جلسة تحميل بيانات على أجزاء. + +الطلب: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +الرد: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +أمين المكتبة: +1. يقوم بإنشاء رمز فريد `upload_id` و `object_id` (معرف فريد لتخزين الكائنات) +2. يستدعي S3 `CreateMultipartUpload`، ويتلقى `s3_upload_id` +3. يقوم بإنشاء سجل جلسة في Cassandra +4. يعيد `upload_id` إلى العميل + +#### `upload-chunk` + +تحميل جزء واحد. + +الطلب: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +الرد: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +أمين المكتبة: +1. البحث عن الجلسة باستخدام `upload_id` +2. التحقق من الملكية (يجب أن يتطابق المستخدم مع منشئ الجلسة) +3. استدعاء S3 `UploadPart` مع بيانات الجزء، وتلقي `etag` +4. تحديث سجل الجلسة بفهرس الجزء وعلامة etag +5. إرجاع التقدم إلى العميل + +يمكن إعادة محاولة الأجزاء الفاشلة - فقط أرسل `chunk-index` مرة أخرى. + +#### `complete-upload` + +إنهاء التحميل وإنشاء المستند. + +الطلب: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +الرد: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +أمين المكتبة: +1. يبحث عن الجلسة، ويتحقق من استلام جميع الأجزاء. +2. يستدعي S3 `CompleteMultipartUpload` مع علامات الجزء (S3 تدمج الأجزاء داخليًا - لا توجد تكلفة ذاكرة لأمين المكتبة). + 3. ينشئ سجل مستند في Cassandra مع البيانات الوصفية وإشارة الكائن. +4. يحذف سجل جلسة التحميل. +5. يعيد معرف المستند إلى العميل. +6. + +#### `abort-upload` + +إلغاء عملية تحميل قيد التقدم. + +الطلب: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +أمين المكتبة: +1. يستدعي `AbortMultipartUpload` لتنظيف الأجزاء. +2. يحذف سجل الجلسة من Cassandra. + +#### `get-upload-status` + +حالة استعلام عن عملية تحميل (لإمكانية الاستئناف). + +الطلب: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +الرد: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +عرض قائمة التحميلات غير المكتملة لمستخدم. + +الطلب: +```json +{ + "operation": "list-uploads" +} +``` + +الرد: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### تخزين جلسات التحميل + +تتبع عمليات التحميل الجارية في Cassandra: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**سلوك TTL:** +تنتهي الجلسات بعد 24 ساعة إذا لم تكتمل. +عندما تنتهي صلاحية TTL في Cassandra، يتم حذف سجل الجلسة. +يتم تنظيف أجزاء S3 المهجورة بواسطة سياسة دورة حياة S3 (يتم التكوين على الحاوية). + +### معالجة الأخطاء والتماسك + +**فشل تحميل الأجزاء:** +يحاول العميل إعادة تحميل الجزء الذي فشل (بنفس `upload_id` و `chunk-index`). +عملية S3 `UploadPart` متسقة لنفس رقم الجزء. +تتتبع الجلسة الأجزاء التي نجحت. + +**انقطاع اتصال العميل أثناء التحميل:** +تظل الجلسة موجودة في Cassandra مع تسجيل الأجزاء المستلمة. +يمكن للعميل استدعاء `get-upload-status` لمعرفة ما هو مفقود. +يمكن استئناف التحميل عن طريق تحميل الأجزاء المفقودة فقط، ثم `complete-upload`. + +**فشل التحميل الكامل:** +عملية S3 `CompleteMultipartUpload` ذرية - إما أنها تنجح بالكامل أو تفشل. +في حالة الفشل، تظل الأجزاء موجودة ويمكن للعميل إعادة محاولة `complete-upload`. +لا يمكن رؤية أي مستند جزئي على الإطلاق. + +**انتهاء صلاحية الجلسة:** +تحذف Cassandra سجل الجلسة بعد 24 ساعة. +تقوم سياسة دورة حياة حاوية S3 بتنظيف عمليات التحميل متعددة الأجزاء غير المكتملة. +لا يلزم أي تنظيف يدوي. + +### تماسك S3 متعدد الأجزاء + +توفر عمليات تحميل S3 متعددة الأجزاء تماسكًا مدمجًا: + +1. **الأجزاء غير مرئية**: لا يمكن الوصول إلى الأجزاء التي تم تحميلها ككائنات. + إنها موجودة فقط كأجزاء من عملية تحميل متعددة الأجزاء غير مكتملة. + +2. **الإكمال الذري**: `CompleteMultipartUpload` إما أنها تنجح (يظهر الكائن بشكل ذري) أو تفشل (لا يتم إنشاء كائن). لا توجد حالة جزئية. + + +3. **لا حاجة لإعادة التسمية**: يتم تحديد مفتاح الكائن النهائي في وقت + `CreateMultipartUpload`. يتم دمج الأجزاء مباشرة في هذا المفتاح. + +4. **الدمج من جانب الخادم**: تقوم S3 بدمج الأجزاء داخليًا. لا يقرأ أمين المكتبة + الأجزاء مرة أخرى - لا توجد تكلفة إضافية للذاكرة بغض النظر عن حجم المستند. + +### امتدادات BlobStore + +**الملف:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +أضف طرق التحميل متعددة الأجزاء: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### اعتبارات حجم الجزء + +**الحد الأدنى لـ S3**: 5 ميجابايت لكل جزء (باستثناء الجزء الأخير) +**الحد الأقصى لـ S3**: 10,000 جزء لكل عملية تحميل +**الإعداد الافتراضي العملي**: أجزاء بحجم 5 ميجابايت + مستند بحجم 500 ميجابايت = 100 جزء + مستند بحجم 5 جيجابايت = 1,000 جزء +**دقة التقدم**: أجزاء أصغر = تحديثات تقدم أكثر دقة +**كفاءة الشبكة**: أجزاء أكبر = عدد أقل من عمليات الإرسال + +يمكن تكوين حجم الجزء من قبل العميل ضمن الحدود (5 ميجابايت - 100 ميجابايت). + +### معالجة المستندات: الاسترجاع المتدفق + +يهدف سير عمل التحميل إلى إدخال المستندات إلى التخزين بكفاءة. يهدف سير عمل المعالجة إلى استخراج وتقسيم المستندات دون تحميلها بالكامل في الذاكرة. + + +#### مبدأ التصميم: المعرف، وليس المحتوى + + +حاليًا، عند بدء المعالجة، يتدفق محتوى المستند عبر رسائل Pulsar. يؤدي هذا إلى تحميل المستندات بأكملها في الذاكرة. بدلاً من ذلك: + + +تحمل رسائل Pulsar فقط **معرف المستند** +تقوم المعالجات باسترداد محتوى المستند مباشرة من المكتبة +يتم الاسترداد كـ **تدفق إلى ملف مؤقت** +يعمل التحليل الخاص بالمستند (PDF، نص، إلخ) مع الملفات، وليس مخازن الذاكرة + +هذا يجعل المكتبة غير معتمدة على هيكل المستند. يظل تحليل PDF واستخراج النص ومنطق محدد التنسيق الأخرى في فك التشفير الخاص بها. + + +#### سير المعالجة + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### واجهة برمجة تطبيقات (API) لخدمة أمين المكتبة. + +إضافة عملية استرجاع مستندات متدفقة: + +**`stream-document`** + +الطلب: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +الاستجابة: أجزاء ثنائية متدفقة (وليست استجابة واحدة). + +بالنسبة لواجهة برمجة التطبيقات REST، فإن هذا يُرجع استجابة متدفقة مع `Transfer-Encoding: chunked`. + +بالنسبة للمكالمات الداخلية بين الخدمات (من المعالج إلى أمين المكتبة)، يمكن أن يكون ذلك: +بث مباشر من S3 عبر عنوان URL مسبق التوقيع (إذا سمحت الشبكة الداخلية بذلك). +استجابات مقسمة عبر بروتوكول الخدمة. +نقطة نهاية مخصصة للبث. + +المتطلب الأساسي: تتدفق البيانات في أجزاء، ولا يتم تخزينها بالكامل مؤقتًا في أمين المكتبة. + +#### تغييرات في فك ترميز PDF. + +**التنفيذ الحالي** (يستهلك الكثير من الذاكرة): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**تنفيذ جديد** (ملف مؤقت، تدريجي): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +ملف تعريف الذاكرة: +ملف مؤقت على القرص: حجم ملف PDF (القرص رخيص). +في الذاكرة: صفحة واحدة من النص في كل مرة. +أقصى استخدام للذاكرة: محدود، ولا يعتمد على حجم المستند. + +#### تغييرات في وحدة فك ترميز المستندات النصية. + +بالنسبة للمستندات النصية العادية، الأمر أبسط حتى - لا حاجة لملف مؤقت: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +يمكن لملفات النصوص أن تُرسل مباشرةً دون الحاجة إلى ملف مؤقت نظرًا لأنها +مُنظمة بشكل خطي. + +#### تكامل وحدة تقسيم البيانات (Chunker). + +تتلقى وحدة تقسيم البيانات مُكررًا للنصوص (صفحات أو فقرات) وتُنتج +أجزاء بشكل تدريجي: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### خط أنابيب المعالجة الشاملة + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +في أي نقطة، لا يتم الاحتفاظ بالمستند الكامل أو النص المستخرج بالكامل في الذاكرة. + +#### اعتبارات ملفات مؤقتة + +**الموقع**: استخدم دليل النظام المؤقت (`/tmp` أو ما يعادله). بالنسبة إلى +عمليات النشر في حاويات، تأكد من أن الدليل المؤقت لديه مساحة كافية +وأنه موجود على مساحة تخزين سريعة (وليس مثبتًا على الشبكة إن أمكن). + +**التنظيف**: استخدم مديري السياق (`with tempfile...`) لضمان التنظيف +حتى في حالة حدوث استثناءات. + +**المعالجة المتزامنة**: تحصل كل مهمة معالجة على ملف مؤقت خاص بها. +لا توجد تعارضات بين معالجة المستندات المتوازية. + +**مساحة القرص**: الملفات المؤقتة قصيرة الأجل (مدة المعالجة). بالنسبة إلى +ملف PDF بحجم 500 ميجابايت، يلزم وجود مساحة مؤقتة تبلغ 500 ميجابايت أثناء المعالجة. يمكن +تطبيق حد الحجم في وقت التحميل إذا كانت مساحة القرص محدودة. + +### واجهة المعالجة الموحدة: المستندات الفرعية + +يجب أن تساهم عملية استخراج PDF ومعالجة المستندات النصية في نفس +خط المعالجة اللاحق (تقسيم إلى أجزاء → تضمينات → تخزين). لتحقيق ذلك باستخدام +واجهة "جلب حسب المعرف" متسقة، يتم تخزين كتل النص المستخرجة مرة أخرى +في المكتبة كمستندات فرعية. + +#### سير العمل مع المستندات الفرعية + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +تمتلك وحدة التقسيم واجهة موحدة واحدة: +استقبال معرف المستند (عبر Pulsar) +تدفق المحتوى من أمين المكتبة +تقسيم المحتوى + +لا تعرف أو تهتم ما إذا كان المعرف يشير إلى: +مستند نصي تم تحميله بواسطة المستخدم +جزء نصي مستخرج من صفحة PDF +أي نوع مستند مستقبلي + +#### بيانات وصفية للمستندات الفرعية + +قم بتوسيع مخطط المستند لتتبع العلاقات بين المستندات الرئيسية والفرعية: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**أنواع المستندات:** + +| `document_type` | الوصف | +|-----------------|-------------| +| `source` | مستند تم تحميله بواسطة المستخدم (PDF، نص، إلخ) | +| `extracted` | مشتق من مستند مصدر (مثل نص صفحة PDF) | + +**حقول البيانات الوصفية:** + +| الحقل | المستند المصدر | المستند الفرعي المستخرج | +|-------|-----------------|-----------------| +| `id` | مقدم من المستخدم أو تم إنشاؤه | تم إنشاؤه (مثل `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | معرف المستند الأصل | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`، إلخ. | `text/plain` | +| `title` | مقدم من المستخدم | تم إنشاؤه (مثل "الصفحة 3 من Report.pdf") | +| `user` | مستخدم مصرح له | نفس المستند الأصل | + +#### واجهة برمجة تطبيقات أمين المكتبة للمستندات الفرعية + +**إنشاء المستندات الفرعية** (داخلي، يستخدم بواسطة pdf-extractor): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +بالنسبة للنصوص الصغيرة المستخرجة (عادةً ما يكون نص الصفحة أقل من 100 كيلوبايت)، فإن التحميل في عملية واحدة مقبول. بالنسبة لاستخراج النصوص الكبيرة جدًا، يمكن استخدام التحميل المقسم. + +**عرض المستندات الفرعية** (لأغراض التصحيح/الإدارة): + +**عرض المستندات الفرعية** (لأغراض التصحيح/الإدارة): + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +الرد: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### السلوك الظاهر للمستخدم + +**السلوك الافتراضي `list-documents`:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +تظهر فقط المستندات الرئيسية (المصدر) في قائمة المستندات الخاصة بالمستخدم. +يتم استبعاد المستندات الفرعية افتراضيًا. + +**علامة "include-children" اختيارية** (للمسؤولين/تصحيح الأخطاء): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### حذف متسلسل + +عندما يتم حذف مستند رئيسي، يجب حذف جميع العناصر التابعة له: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### اعتبارات التخزين + +النصوص المستخرجة قد تتضمن تكرارًا للمحتوى: +ملف PDF الأصلي مُخزن في "Garage". +النص المستخرج لكل صفحة مُخزن أيضًا في "Garage". + +هذا الحل يتيح: +**واجهة موحدة للتقطيع**: يقوم "Chunker" دائمًا باسترداد البيانات بمعرف (ID). +**الاستئناف/إعادة المحاولة**: يمكن إعادة تشغيل العملية في مرحلة "Chunker" دون إعادة استخراج ملف PDF. +**تصحيح الأخطاء**: يمكن فحص النص المستخرج. +**فصل المهام**: خدمة استخراج ملف PDF وخدمة "Chunker" هما خدمتان مستقلتان. + +بالنسبة لملف PDF بحجم 500 ميجابايت و200 صفحة بمتوسط 5 كيلوبايت من النص لكل صفحة: +تخزين ملف PDF: 500 ميجابايت. +تخزين النص المستخرج: حوالي 1 ميجابايت إجمالاً. +التكلفة الإضافية: ضئيلة. + +#### مخرجات مُستخرج ملف PDF + +يقوم مُستخرج ملف PDF (pdf-extractor)، بعد معالجة المستند: + +1. يقوم بتحميل ملف PDF من "librarian" إلى ملف مؤقت. +2. يستخرج النص صفحةً تلو الأخرى. +3. لكل صفحة، يقوم بتخزين النص المستخرج كمستند فرعي عبر "librarian". +4. يرسل معرفات المستندات الفرعية إلى قائمة انتظار "Chunker". + +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +يتلقى المعالج هذه المعرفات الفرعية ويقوم بمعالجتها بنفس الطريقة التي يعالج بها مستند نصي تم تحميله بواسطة المستخدم. +كيف كان سيعالجها. + +### تحديثات العميل + +#### حزمة تطوير البرمجيات (SDK) بلغة بايثون + +يجب أن تتعامل حزمة تطوير البرمجيات (SDK) بلغة بايثون (`trustgraph-base/trustgraph/api/library.py`) مع عمليات التحميل المقسمة بشفافية. يظل الواجهة العامة دون تغيير: + + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +داخليًا، يكتشف الـ SDK حجم المستند ويغير الاستراتيجية: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**استدعاءات ردود الأفعال للتقدم** (تحسين اختياري): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +هذا يسمح لواجهات المستخدم بعرض تقدم التحميل دون تغيير واجهة برمجة التطبيقات الأساسية. + +#### أدوات سطر الأوامر + +**`tg-add-library-document`** يستمر في العمل دون تغيير: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +يمكن إضافة عرض اختياري للتقدم: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**تمت إزالة الأدوات القديمة:** + +`tg-load-pdf` - قديمة، استخدم `tg-add-library-document` +`tg-load-text` - قديمة، استخدم `tg-add-library-document` + +**أوامر الإدارة/التصحيح** (اختياري، أولوية منخفضة): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +قد تكون هذه خيارات في الأمر الحالي بدلاً من أدوات منفصلة. + +#### تحديثات مواصفات واجهة برمجة التطبيقات (API) + +تحتاج مواصفات OpenAPI (`specs/api/paths/librarian.yaml`) إلى تحديثات فيما يلي: + +**عمليات جديدة:** + +`begin-upload` - تهيئة جلسة تحميل مقسمة +`upload-chunk` - تحميل جزء فردي +`complete-upload` - إنهاء التحميل +`abort-upload` - إلغاء التحميل +`get-upload-status` - الاستعلام عن تقدم التحميل +`list-uploads` - قائمة بالتحميلات غير المكتملة للمستخدم +`stream-document` - استرجاع المستندات المتدفقة +`add-child-document` - تخزين النص المستخرج (داخلي) +`list-children` - قائمة بالمستندات الفرعية (للمسؤول) + +**عمليات معدلة:** + +`list-documents` - إضافة معلمة `include-children` + +**مخططات جديدة:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**تحديثات مواصفات WebSocket** (`specs/websocket/`): + +قم بمحاكاة العمليات REST لعملاء WebSocket، مما يتيح تحديثات التقدم في الوقت الفعلي +أثناء التحميل. + +#### اعتبارات تجربة المستخدم (UX) + +تتيح تحديثات مواصفات واجهة برمجة التطبيقات (API) تحسينات في الواجهة الأمامية: + +**واجهة مستخدم لتقدم التحميل:** +شريط تقدم يوضح الأجزاء التي تم تحميلها +الوقت المقدر المتبقي +إمكانية الإيقاف المؤقت/الاستئناف + +**استعادة الأخطاء:** +خيار "استئناف التحميل" للتحميلات المتقطعة +قائمة بالتحميلات المعلقة عند إعادة الاتصال + +**التعامل مع الملفات الكبيرة:** +اكتشاف حجم الملف من جانب العميل +تحميل مقسم تلقائي للملفات الكبيرة +ملاحظات واضحة أثناء عمليات التحميل الطويلة + +تتطلب هذه التحسينات في تجربة المستخدم (UX) عملًا في الواجهة الأمامية يتم توجيهه بواسطة مواصفات واجهة برمجة التطبيقات (API) المحدثة. diff --git a/docs/tech-specs/large-document-loading.es.md b/docs/tech-specs/large-document-loading.es.md new file mode 100644 index 00000000..9eb5811d --- /dev/null +++ b/docs/tech-specs/large-document-loading.es.md @@ -0,0 +1,1097 @@ +--- +layout: default +title: "Especificación Técnica de Carga de Documentos Grandes" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Carga de Documentos Grandes + +> **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 aborda los problemas de escalabilidad y la experiencia del usuario al cargar +documentos grandes en TrustGraph. La arquitectura actual trata la carga de documentos +como una operación atómica única, lo que provoca una alta carga de memoria en varios puntos del +proceso y no proporciona ninguna indicación de progreso ni opciones de recuperación a los usuarios. + +Esta implementación tiene como objetivo los siguientes casos de uso: + +1. **Procesamiento de PDF Grandes**: Cargar y procesar archivos PDF de varios cientos de megabytes + sin agotar la memoria. +2. **Cargas Reanudables**: Permitir que las cargas interrumpidas continúen desde donde + se detuvieron en lugar de reiniciarse. +<<<<<<< HEAD +3. **Indicación de Progreso**: Proporcionar a los usuarios visibilidad en tiempo real del +======= +3. **Retroalimentación de Progreso**: Proporcionar a los usuarios visibilidad en tiempo real del +>>>>>>> 82edf2d (New md files from RunPod) + progreso de la carga y el procesamiento. +4. **Procesamiento Eficiente en Memoria**: Procesar documentos de forma continua + sin mantener archivos completos en la memoria. + +## Objetivos + +<<<<<<< HEAD +**Carga Incremental**: Soporte para la carga de documentos en fragmentos a través de REST y WebSocket. +**Transferencias Reanudables**: Permitir la recuperación de cargas interrumpidas. +**Visibilidad del Progreso**: Proporcionar retroalimentación de carga/procesamiento a los clientes. +**Eficiencia de Memoria**: Eliminar el almacenamiento en búfer de documentos completos en todo el proceso. +**Compatibilidad con Versiones Anteriores**: Los flujos de trabajo existentes para documentos pequeños continúan sin cambios. +**Procesamiento por Flujo Continuo**: La decodificación de PDF y el fragmentado de texto operan en flujos. +======= +**Carga Incremental**: Soporte para la carga de documentos por partes a través de REST y WebSocket. +**Transferencias Reanudables**: Permitir la recuperación de cargas interrumpidas. +**Visibilidad del Progreso**: Proporcionar retroalimentación de progreso de carga/procesamiento a los clientes. +**Eficiencia de Memoria**: Eliminar el almacenamiento en búfer de documentos completos en todo el proceso. +**Compatibilidad con Versiones Anteriores**: Los flujos de trabajo existentes para documentos pequeños continúan sin cambios. +**Procesamiento por Transmisión**: La decodificación de PDF y el fragmentado de texto operan en flujos. +>>>>>>> 82edf2d (New md files from RunPod) + +## Antecedentes + +### Arquitectura Actual + +El flujo de envío de documentos sigue la siguiente ruta: + +1. El **cliente** envía el documento a través de REST (`POST /api/v1/librarian`) o WebSocket. +2. La **API Gateway** recibe la solicitud completa con el contenido del documento codificado en base64. +3. El **LibrarianRequestor** traduce la solicitud a un mensaje Pulsar. +4. El **Librarian Service** recibe el mensaje, decodifica el documento en la memoria. +5. **BlobStore** carga el documento en Garage/S3. +6. **Cassandra** almacena los metadatos con la referencia del objeto. +<<<<<<< HEAD +7. Para el procesamiento: el documento se recupera de S3, se decodifica y se divide en fragmentos, todo en la memoria. +======= +7. Para el procesamiento: el documento se recupera de S3, se decodifica y se divide en partes, todo en la memoria. +>>>>>>> 82edf2d (New md files from RunPod) + +Archivos clave: +Punto de entrada REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +Núcleo de Librarian: `trustgraph-flow/trustgraph/librarian/librarian.py` +Almacenamiento de blobs: `trustgraph-flow/trustgraph/librarian/blob_store.py` +Tablas de Cassandra: `trustgraph-flow/trustgraph/tables/library.py` +Esquema de la API: `trustgraph-base/trustgraph/schema/services/library.py` + +### Limitaciones Actuales + +<<<<<<< HEAD +El diseño actual tiene varios problemas de memoria y experiencia de usuario que se agravan: +======= +El diseño actual tiene varios problemas de memoria y experiencia de usuario: +>>>>>>> 82edf2d (New md files from RunPod) + +1. **Operación de Carga Atómica**: Se debe transmitir todo el documento en una + solicitud única. Los documentos grandes requieren solicitudes de larga duración sin + indicación de progreso ni mecanismo de reintento si la conexión falla. + +2. **Diseño de la API**: Tanto las API REST como WebSocket esperan el documento + completo en un solo mensaje. El esquema (`LibrarianRequest`) tiene un campo `content` + que contiene todo el documento codificado en base64. + +3. **Memoria del Librarian**: El servicio librarian decodifica todo el documento +<<<<<<< HEAD + en la memoria antes de cargarlo en S3. Para un PDF de 500 MB, esto significa mantener + 500 MB+ en la memoria del proceso. + +4. **Memoria del Decodificador de PDF**: Cuando comienza el procesamiento, el decodificador de PDF carga + todo el PDF en la memoria para extraer el texto. Las bibliotecas como PyPDF y similares + típicamente requieren acceso a todo el documento. +======= + en la memoria antes de cargarlo en S3. Para un archivo PDF de 500 MB, esto significa mantener + 500 MB+ en la memoria del proceso. + +4. **Memoria del Decodificador de PDF**: Cuando comienza el procesamiento, el decodificador de PDF carga + todo el PDF en la memoria para extraer el texto. Las bibliotecas como PyPDF normalmente + requieren acceso a todo el documento. +>>>>>>> 82edf2d (New md files from RunPod) + +5. **Memoria del Fragmentador**: El fragmentador de texto recibe todo el texto extraído + y lo mantiene en la memoria mientras produce fragmentos. + +**Ejemplo de Impacto en la Memoria** (PDF de 500 MB): +Gateway: ~700 MB (sobrecarga de codificación base64) +Librarian: ~500 MB (bytes decodificados) +Decodificador de PDF: ~500 MB + búferes de extracción +Fragmentador: texto extraído (variable, potencialmente 100 MB+) + +El pico total de memoria puede exceder los 2 GB para un solo documento grande. + +## Diseño Técnico + +### Principios de Diseño + +1. **Fachada de la API**: Toda la interacción del cliente pasa por la API de librarian. Los clientes + no tienen acceso directo ni conocimiento del almacenamiento subyacente de S3/Garage. + +2. **Carga Multipart de S3**: Utilice la carga multipart estándar de S3. + Esto está ampliamente soportado en sistemas compatibles con S3 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2, etc.), lo que garantiza la portabilidad. + +3. **Completación Atómica**: Las cargas multipart de S3 son inherentemente atómicas: las partes cargadas +<<<<<<< HEAD + son invisibles hasta que se llama a `CompleteMultipartUpload`. No se necesitan archivos temporales ni +======= + no son visibles hasta que se llama a `CompleteMultipartUpload`. No se necesitan archivos temporales ni +>>>>>>> 82edf2d (New md files from RunPod) + operaciones de renombrado. + +4. **Estado Rastreable**: Las sesiones de carga se rastrean en Cassandra, lo que proporciona + visibilidad de las cargas incompletas y permite la capacidad de reanudación. + +<<<<<<< HEAD +### Flujo de Carga Fragmentada +======= +### Flujo de Carga por Partes +>>>>>>> 82edf2d (New md files from RunPod) + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +El cliente nunca interactúa directamente con S3. El "librarian" (bibliotecario) traduce entre +nuestra API de carga por partes y las operaciones multipart de S3 internamente. + +### Operaciones de la API del "Librarian" + +#### `begin-upload` + +Inicializar una sesión de carga por partes. + +Solicitud: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +Respuesta: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +El bibliotecario: +<<<<<<< HEAD +1. Genera un `upload_id` y un `object_id` únicos (UUID para almacenamiento de blobs). +======= +1. Genera un `upload_id` y un `object_id` únicos (UUID para el almacenamiento de blobs). +>>>>>>> 82edf2d (New md files from RunPod) +2. Llama a S3 `CreateMultipartUpload`, recibe `s3_upload_id`. +3. Crea un registro de sesión en Cassandra. +4. Devuelve `upload_id` al cliente. + +#### `upload-chunk` + +<<<<<<< HEAD +Cargar un único fragmento. +======= +Carga un único fragmento. +>>>>>>> 82edf2d (New md files from RunPod) + +Solicitud: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +Respuesta: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +El bibliotecario: +1. Busca la sesión por `upload_id` +2. Valida la propiedad (el usuario debe coincidir con el creador de la sesión) +3. Llama a S3 `UploadPart` con los datos del fragmento, recibe `etag` +4. Actualiza el registro de la sesión con el índice del fragmento y la etiqueta (etag) +5. Devuelve el progreso al cliente + +<<<<<<< HEAD +Los fragmentos fallidos se pueden reintentar; simplemente envía el mismo `chunk-index` nuevamente. +======= +Los fragmentos fallidos se pueden reintentar: simplemente envía el mismo `chunk-index` nuevamente. +>>>>>>> 82edf2d (New md files from RunPod) + +#### `complete-upload` + +Finaliza la carga y crea el documento. + +Solicitud: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +Respuesta: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +El bibliotecario: +1. Busca la sesión, verifica que se hayan recibido todos los fragmentos. +2. Llama a S3 `CompleteMultipartUpload` con los ETags de las partes (S3 combina las partes +<<<<<<< HEAD + internamente, sin costo de memoria para el bibliotecario). +======= + internamente, lo que no tiene costo de memoria para el bibliotecario). +>>>>>>> 82edf2d (New md files from RunPod) +3. Crea un registro de documento en Cassandra con metadatos y referencia al objeto. +4. Elimina el registro de la sesión de carga. +5. Devuelve el ID del documento al cliente. + +#### `abort-upload` + +Cancelar una carga en curso. + +Solicitud: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +El bibliotecario: +1. Llama a S3 `AbortMultipartUpload` para limpiar partes. +2. Elimina el registro de sesión de Cassandra. + +#### `get-upload-status` + +Consulta el estado de una carga (para la capacidad de reanudación). + +Solicitud: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +Respuesta: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +Listar las subidas incompletas para un usuario. + +Solicitud: +```json +{ + "operation": "list-uploads" +} +``` + +Respuesta: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### Almacenamiento de Sesión de Carga + +Realizar un seguimiento de las cargas en curso en Cassandra: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**Comportamiento de TTL:** +Las sesiones expiran después de 24 horas si no se completan. +Cuando expira el TTL de Cassandra, se elimina el registro de la sesión. +Las partes de S3 huérfanas se eliminan mediante la política de ciclo de vida de S3 (configurar en el bucket). + +### Manejo de errores y atomicidad + +**Fallo en la carga de fragmentos:** +<<<<<<< HEAD +El cliente reintenta el fragmento fallido (mismo `upload_id` y `chunk-index`). +======= +El cliente reintenta el fragmento fallido (con el mismo `upload_id` y `chunk-index`). +>>>>>>> 82edf2d (New md files from RunPod) +`UploadPart` de S3 es idempotente para el mismo número de parte. +La sesión realiza un seguimiento de qué fragmentos tuvieron éxito. + +**Desconexión del cliente durante la carga:** +La sesión permanece en Cassandra con los fragmentos recibidos registrados. +El cliente puede llamar a `get-upload-status` para ver qué falta. +Reanudar cargando solo los fragmentos faltantes, luego `complete-upload`. + +**Fallo en la carga completa:** +`CompleteMultipartUpload` de S3 es atómico: o tiene éxito por completo o falla. +En caso de fallo, las partes permanecen y el cliente puede reintentar `complete-upload`. +Nunca se muestra un documento parcial. + +**Vencimiento de la sesión:** +El TTL de Cassandra elimina el registro de la sesión después de 24 horas. +<<<<<<< HEAD +La política de ciclo de vida del bucket de S3 limpia las cargas multipartes incompletas. +No se requiere limpieza manual. + +### Atomicidad de las cargas multipartes de S3 + +Las cargas multipartes de S3 proporcionan atomicidad integrada: + +1. **Las partes son invisibles:** Las partes cargadas no se pueden acceder como objetos. + Solo existen como partes de una carga multipartes incompleta. +======= +La política de ciclo de vida del bucket de S3 limpia las cargas multipart incompletas. +No se requiere limpieza manual. + +### Atomicidad de las cargas multipart de S3 + +Las cargas multipart de S3 proporcionan atomicidad integrada: + +1. **Las partes son invisibles:** Las partes cargadas no se pueden acceder como objetos. + Solo existen como partes de una carga multipart incompleta. +>>>>>>> 82edf2d (New md files from RunPod) + +2. **Finalización atómica:** `CompleteMultipartUpload` tiene éxito (el objeto + aparece de forma atómica) o falla (no se crea ningún objeto). No hay estado parcial. + +<<<<<<< HEAD +3. **No se necesita renombrar:** La clave de objeto final se especifica en + el momento de `CreateMultipartUpload`. Las partes se combinan directamente en esa clave. +======= +3. **No se necesita renombrar:** La clave del objeto final se especifica en + el momento de `CreateMultipartUpload`. Las partes se combinan directamente con esa clave. +>>>>>>> 82edf2d (New md files from RunPod) + +4. **Combinación del lado del servidor:** S3 combina las partes internamente. El bibliotecario + nunca lee las partes de nuevo: cero sobrecarga de memoria independientemente del tamaño del documento. + +### Extensiones de BlobStore + +**Archivo:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +<<<<<<< HEAD +Agregar métodos de carga multipartes: +======= +Agregar métodos de carga multipart: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### Consideraciones sobre el tamaño de los bloques + +**Mínimo de S3**: 5 MB por parte (excepto la última parte) +**Máximo de S3**: 10,000 partes por carga +**Valor predeterminado práctico**: bloques de 5 MB + Documento de 500 MB = 100 bloques + Documento de 5 GB = 1000 bloques +**Granularidad del progreso**: Bloques más pequeños = actualizaciones de progreso más detalladas +**Eficiencia de la red**: Bloques más grandes = menos viajes de ida y vuelta + +El tamaño del bloque podría ser configurable por el cliente dentro de un rango (5 MB - 100 MB). + +### Procesamiento de documentos: Recuperación en streaming + +El flujo de carga se ocupa de almacenar documentos de manera eficiente. El flujo de procesamiento se ocupa de extraer y dividir documentos sin cargarlos +por completo en la memoria. + + +#### Principio de diseño: Identificador, no contenido + +Actualmente, cuando se inicia el procesamiento, el contenido del documento fluye a través de mensajes de Pulsar. Esto carga documentos completos en la memoria. En cambio: + + +Los mensajes de Pulsar solo contienen el **identificador del documento** +Los procesadores recuperan el contenido del documento directamente de la biblioteca. +La recuperación se realiza como un **flujo a un archivo temporal** +El análisis específico del documento (PDF, texto, etc.) funciona con archivos, no con búferes de memoria. + +Esto mantiene a la biblioteca independiente de la estructura del documento. El análisis de PDF, la extracción de texto y otras lógicas específicas del formato permanecen en los decodificadores correspondientes. + + +#### Flujo de procesamiento + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### API de flujo de trabajo del bibliotecario + +Agregar una operación de recuperación de documentos en flujo continuo: + +**`stream-document`** + +Solicitud: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +Respuesta: Fragmentos binarios transmitidos (no una respuesta única). + +Para la API REST, esto devuelve una respuesta transmitida con `Transfer-Encoding: chunked`. + +Para llamadas internas de servicio a servicio (del procesador al bibliotecario), esto podría ser: +Transmisión directa de S3 a través de una URL prefirmada (si la red interna lo permite). +Respuestas fragmentadas a través del protocolo del servicio. +Un punto final de transmisión dedicado. + +El requisito clave: los datos fluyen en fragmentos, nunca completamente almacenados en búfer en el bibliotecario. + +#### Cambios en el decodificador de PDF + +**Implementación actual** (que consume mucha memoria): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**Nueva implementación** (archivo temporal, incremental): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +Perfil de memoria: +Archivo temporal en disco: tamaño del PDF (el disco es barato). +En memoria: una página de texto a la vez. +Memoria máxima: limitada, independiente del tamaño del documento. + +#### Cambios en el decodificador de documentos de texto. + +Para documentos de texto plano, aún más simple: no se necesita archivo temporal. + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +Los documentos de texto pueden transmitirse directamente sin un archivo temporal, ya que están +estructurados linealmente. + +#### Integración del Fragmentador (Chunker) + +El fragmentador recibe un iterador de texto (páginas o párrafos) y produce +fragmentos de forma incremental: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +<<<<<<< HEAD +#### Canalización de procesamiento de extremo a extremo +======= +#### Canalización de Procesamiento de Extremo a Extremo +>>>>>>> 82edf2d (New md files from RunPod) + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +<<<<<<< HEAD +En ningún momento, se mantiene en memoria el documento completo o el texto extraído completo. +======= +En ningún momento, el documento completo o el texto extraído se mantienen en la memoria. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Consideraciones sobre archivos temporales + +**Ubicación**: Utilice el directorio temporal del sistema (`/tmp` o equivalente). Para +implementaciones en contenedores, asegúrese de que el directorio temporal tenga suficiente espacio +y que esté en un almacenamiento rápido (no montado en red, si es posible). + +**Limpieza**: Utilice administradores de contexto (`with tempfile...`) para garantizar la limpieza +incluso en caso de excepciones. + +**Procesamiento concurrente**: Cada trabajo de procesamiento obtiene su propio archivo temporal. +No hay conflictos entre el procesamiento paralelo de documentos. + +**Espacio en disco**: Los archivos temporales son de corta duración (duración del procesamiento). Para +un archivo PDF de 500 MB, se necesitan 500 MB de espacio temporal durante el procesamiento. El límite de tamaño podría +aplicarse en el momento de la carga si el espacio en disco es limitado. + +### Interfaz de procesamiento unificada: Documentos secundarios + +La extracción de PDF y el procesamiento de documentos de texto deben integrarse en la misma +canalización descendente (fragmentación → incrustaciones → almacenamiento). Para lograr esto con una interfaz "recuperación por ID" consistente, los bloques de texto extraídos se almacenan de nuevo +en el sistema de gestión de documentos como documentos secundarios. + +#### Flujo de procesamiento con documentos secundarios + +Después de la última línea traducida, incluir una línea final que contenga exactamente: [[__END_OF_TRANSLATION__]] +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +El componente de segmentación tiene una interfaz uniforme: +Recibir un ID de documento (a través de Pulsar) +Obtener el contenido del bibliotecario +Segmentarlo + +No sabe ni le importa si el ID se refiere a: +Un documento de texto subido por un usuario +Un fragmento de texto extraído de una página de PDF +Cualquier tipo de documento futuro + +#### Metadatos del Documento Hijo + +Extender el esquema del documento para rastrear las relaciones padre/hijo: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**Tipos de documentos:** + +| `document_type` | Descripción | +|-----------------|-------------| +| `source` | Documento subido por el usuario (PDF, texto, etc.) | +| `extracted` | Derivado de un documento fuente (por ejemplo, texto de una página PDF) | + +**Campos de metadatos:** + +| Campo | Documento fuente | Documento hijo extraído | +|-------|-----------------|-----------------| +| `id` | proporcionado por el usuario o generado | generado (por ejemplo, `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | ID del documento padre | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, etc. | `text/plain` | +| `title` | proporcionado por el usuario | generado (por ejemplo, "Página 3 del Informe.pdf") | +| `user` | usuario autenticado | igual que el padre | + +<<<<<<< HEAD +#### API de Librarian para documentos hijos + +**Creación de documentos hijos** (interno, utilizado por pdf-extractor): +======= +#### API de Librarian para documentos hijo + +**Creación de documentos hijo** (interno, utilizado por pdf-extractor): +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +Para textos pequeños extraídos (el texto típico de una página es menor a 100 KB), la carga en una sola operación es aceptable. Para extracciones de texto muy grandes, se podría utilizar la carga por bloques. + +**Listado de documentos secundarios** (para depuración/administración): + +**Listado de documentos secundarios** (para depuración/administración): + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +Respuesta: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### Comportamiento visible para el usuario + +**`list-documents` comportamiento predeterminado:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +Solo los documentos de nivel superior (fuente) aparecen en la lista de documentos del usuario. +Los documentos secundarios se filtran de forma predeterminada. + +<<<<<<< HEAD +**Opción de incluir subdocumentos** (para administradores/depuración): +======= +**Opción de incluir documentos secundarios** (para administradores/depuración): +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### Eliminación en cascada + +Cuando se elimina un documento padre, todos los documentos hijos deben ser eliminados: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### Consideraciones de almacenamiento + +Los bloques de texto extraídos duplican el contenido: +El PDF original se almacena en Garage. +El texto extraído por página también se almacena en Garage. + +Este compromiso permite: +**Interfaz de fragmentación uniforme**: El fragmentador siempre recupera por ID. +**Reanudación/reintento**: Se puede reiniciar en la etapa del fragmentador sin volver a extraer el PDF. +**Depuración**: El texto extraído es inspeccionable. +**Separación de responsabilidades**: El extractor de PDF y el fragmentador son servicios independientes. + +Para un PDF de 500 MB con 200 páginas que promedian 5 KB de texto por página: +Almacenamiento del PDF: 500 MB. +Almacenamiento del texto extraído: ~1 MB en total. +Sobrecarga: insignificante. + +#### Salida del extractor de PDF + +El extractor de PDF, después de procesar un documento: + +1. Transmite el PDF desde el bibliotecario a un archivo temporal. +2. Extrae el texto página por página. +3. Para cada página, almacena el texto extraído como un documento secundario a través del bibliotecario. +4. Envía los ID de los documentos secundarios a la cola del fragmentador. +<<<<<<< HEAD +Después de la última línea traducida, incluir una línea final que contenga exactamente: [[__END_OF_TRANSLATION__]] +======= + +>>>>>>> 82edf2d (New md files from RunPod) +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +El componente de segmentación recibe estos ID de elementos secundarios y los procesa de la misma manera que procesaría un documento de texto subido por el usuario. + +### Actualizaciones del cliente + +#### SDK de Python + + +El SDK de Python (`trustgraph-base/trustgraph/api/library.py`) debe manejar +las cargas fragmentadas de forma transparente. La interfaz pública permanece sin cambios: + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +Internamente, el SDK detecta el tamaño del documento y cambia de estrategia: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**Callbacks de progreso** (mejora opcional): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +Esto permite que las interfaces de usuario muestren el progreso de la carga sin cambiar la API básica. + +#### Herramientas de línea de comandos + +**`tg-add-library-document`** continúa funcionando sin cambios: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +Se podría agregar una visualización opcional del progreso: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**Herramientas heredadas eliminadas:** + +`tg-load-pdf` - obsoleto, usar `tg-add-library-document` +`tg-load-text` - obsoleto, usar `tg-add-library-document` + +**Comandos de administración/depuración** (opcional, baja prioridad): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +Estas podrían ser banderas en el comando existente en lugar de herramientas separadas. + +#### Actualizaciones de la Especificación de la API + +La especificación OpenAPI (`specs/api/paths/librarian.yaml`) necesita actualizaciones para: + +**Nuevas operaciones:** + +`begin-upload` - Inicializar sesión de carga por partes +`upload-chunk` - Cargar parte individual +`complete-upload` - Finalizar carga +`abort-upload` - Cancelar carga +`get-upload-status` - Consultar el progreso de la carga +`list-uploads` - Listar cargas incompletas para el usuario +`stream-document` - Recuperación de documentos en streaming +`add-child-document` - Almacenar texto extraído (interno) +`list-children` - Listar documentos secundarios (administrador) + +**Operaciones modificadas:** + +`list-documents` - Agregar parámetro `include-children` + +**Nuevos esquemas:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**Actualizaciones de la especificación WebSocket** (`specs/websocket/`): + +Reflejar las operaciones REST para clientes WebSocket, lo que permite actualizaciones de progreso en tiempo real +durante la carga. + +#### Consideraciones de la Experiencia de Usuario + +Las actualizaciones de la especificación de la API permiten mejoras en la interfaz de usuario: + +**Interfaz de usuario del progreso de la carga:** +Barra de progreso que muestra las partes cargadas +Tiempo estimado restante +Capacidad de pausa/reanudación + +**Recuperación de errores:** +Opción de "reintentar la carga" para cargas interrumpidas +Lista de cargas pendientes al reconectar + +**Manejo de archivos grandes:** +Detección del tamaño del archivo en el lado del cliente +Carga automática por partes para archivos grandes +<<<<<<< HEAD +Retroalimentación clara durante cargas largas +======= +Retroalimentación clara durante las cargas largas +>>>>>>> 82edf2d (New md files from RunPod) + +Estas mejoras en la experiencia de usuario requieren trabajo en la interfaz de usuario, guiado por la especificación de la API actualizada. diff --git a/docs/tech-specs/large-document-loading.he.md b/docs/tech-specs/large-document-loading.he.md new file mode 100644 index 00000000..7d207926 --- /dev/null +++ b/docs/tech-specs/large-document-loading.he.md @@ -0,0 +1,992 @@ +--- +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. **עיבוד PDF גדול**: העלאה ועיבוד של קבצי PDF בגודל מאות מגה-בייטים + מבלי למצות את הזיכרון +2. **העלאות ניתנות לחידוש**: אפשרות להמשיך העלאות שהופסקו מאותה נקודה + במקום להתחיל מחדש +3. **משוב התקדמות**: מתן למשתמשים תצוגה חיה של התקדמות ההעלאה + והעיבוד +4. **עיבוד חסכוני בזיכרון**: עיבוד מסמכים בצורה רציפה + מבלי לשמור את כל הקבצים בזיכרון + +## מטרות + +**העלאה הדרגתית**: תמיכה בהעלאה מקוטעת של מסמכים באמצעות REST ו-WebSocket +**העברות ניתנות לחידוש**: אפשרות להתאושש מהעלאות שהופסקו +**נראות של התקדמות**: מתן משוב על התקדמות ההעלאה/עיבוד ללקוחות +**יעילות זיכרון**: ביטול אחסון מלא של מסמכים לאורך כל המערכת +**תאימות לאחור**: זרימות עבודה קיימות עבור מסמכים קטנים ממשיכות לפעול ללא שינוי +**עיבוד רציף**: פענוח PDF וחלוקת טקסט מתבצעות על זרמים + +## רקע + +### ארכיטקטורה נוכחית + +זרימת הגשת מסמכים עוברת דרך הנתיב הבא: + +1. **לקוח** מגיש מסמך באמצעות REST (`POST /api/v1/librarian`) או WebSocket +2. **שער API** מקבל בקשה שלמה עם תוכן המסמך מקודד ב-base64 +3. **LibrarianRequestor** מתרגם את הבקשה להודעת Pulsar +4. **שירות Librarian** מקבל את ההודעה, מפענח את המסמך לזיכרון +5. **BlobStore** מעלה את המסמך ל-Garage/S3 +6. **Cassandra** שומר מטא-דאטה עם הפניה לאובייקט +7. לצורך עיבוד: המסמך נשלף מ-S3, מפענח, מחולק - הכל בזיכרון + +קבצים מרכזיים: +נקודת כניסה REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +ליבה של Librarian: `trustgraph-flow/trustgraph/librarian/librarian.py` +אחסון Blob: `trustgraph-flow/trustgraph/librarian/blob_store.py` +טבלאות Cassandra: `trustgraph-flow/trustgraph/tables/library.py` +סכימת API: `trustgraph-base/trustgraph/schema/services/library.py` + +### מגבלות נוכחיות + +לעיצוב הנוכחי יש מספר בעיות מורכבות של זיכרון וחוויית משתמש: + +1. **פעולת העלאה אטומית**: יש להעביר את כל המסמך בבקשה אחת. + מסמכים גדולים דורשים בקשות ארוכות עם אינדיקציה מועטה להתקדמות + וללא מנגנון ניסיון חוזר אם החיבור נכשל. + +2. **עיצוב API**: גם ממשקי REST וגם WebSocket מצפים לקבל את כל המסמך + בהודעה אחת. הסכימה (`LibrarianRequest`) כוללת שדה `content` + יחיד המכיל את תוכן המסמך המקודד ב-base64. + +3. **זיכרון של Librarian**: שירות ה-librarian מפענח את כל המסמך + לזיכרון לפני העלאתו ל-S3. עבור קובץ PDF בגודל 500 מגה-בייטים, + זה אומר שמירת 500 מגה-בייטים+ בזיכרון התהליך. + +4. **זיכרון של מפענח PDF**: כאשר העיבוד מתחיל, מפענח ה-PDF טוען את + ה-PDF כולו לזיכרון כדי לחלץ טקסט. ספריות כמו PyPDF דורשות + בדרך כלל גישה מלאה למסמך. + +5. **זיכרון של חולק הטקסט**: החולק של הטקסט מקבל את הטקסט + שחולץ ומחזיק אותו בזיכרון תוך יצירת חלקים. + +**דוגמה להשפעה על הזיכרון** (PDF בגודל 500 מגה-בייטים): +Gateway: ~700 מגה-בייטים (עקב קידוד base64) +Librarian: ~500 מגה-בייטים (בייטים מפוענחים) +מפענח PDF: ~500 מגה-בייטים + חוצצים לחילוץ +חולק: טקסט שחולץ (משתנה, פוטנציאלית 100 מגה-בייטים+) + +הזיכרון המקסימלי יכול לעלות על 2 ג'יגה-בייטים עבור מסמך גדול יחיד. + +## עיצוב טכני + +### עקרונות עיצוב + +1. **ממשק API**: כל האינטראקציות עם הלקוח עוברות דרך ה-API של ה-librarian. + ללקוחות אין גישה ישירה או ידע לגבי אחסון S3/Garage הבסיסי. + +2. **העלאה מרובת חלקים של S3**: שימוש בהעלאה מרובת חלקים סטנדרטית של S3. + זה נתמך באופן נרחב במערכות התואמות ל-S3 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2 וכו') ומבטיח ניידות. + +3. **השלמה אטומית**: העלאות מרובות חלקים של S3 הן מטבען אטומיות - חלקים שהועלו + אינם גלויים עד ש-`CompleteMultipartUpload` נקרא. אין צורך בקבצים זמניים או פעולות + שינוי שם. + +4. **מצב הניתן למעקב**: סשנים של העלאה נרשמים ב-Cassandra ומאפשרים + התאוששות במקרה של כשל. + + + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +הלקוח לעולם אינו מתקשר ישירות עם S3. הספרן מתרגם בין +ממשק ההעלאה המקוטעת שלנו לפעולות ה-multipart של S3 באופן פנימי. + +### פעולות ממשק ה-API של הספרן + +#### `begin-upload` + +אתחול סשן העלאה מקוטעת. + +בקשה: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +תגובה: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +הספרן: +1. מייצר `upload_id` ו-`object_id` ייחודיים (UUID עבור אחסון בלובים). +2. קורא ל-S3 `CreateMultipartUpload`, מקבל `s3_upload_id`. +3. יוצר רשומת סשן ב-Cassandra. +4. מחזיר `upload_id` ללקוח. + +#### `upload-chunk` + +העלאת מקטע בודד. + +בקשה: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +תגובה: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +הספרן: +1. מחפש את הסשן לפי `upload_id` +2. מאמת בעלות (המשתמש חייב להתאים ליוצר הסשן) +3. קורא ל-S3 `UploadPart` עם נתוני החלק, מקבל `etag` +4. מעדכן את רשומת הסשן עם אינדקס החלק ו-etag +5. מחזיר התקדמות ללקוח + +חלקים שנכשלו ניתנים לניסיון חוזר - פשוט שלחו שוב את `chunk-index`. + +#### `complete-upload` + +השלמת ההעלאה ויצירת המסמך. + +בקשה: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +תגובה: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +הספרן: +1. מחפש את הסשן, מוודא שכל החלקים התקבלו. +2. קורא ל-S3 `CompleteMultipartUpload` עם תגיות חלק (S3 ממזגת חלקים + באופן פנימי - אין עלות זיכרון לספרן). +3. יוצר רשומת מסמך ב-Cassandra עם מטא-דאטה והפניה לאובייקט. +4. מוחק את רשומת סשן ההעלאה. +5. מחזיר את מזהה המסמך ללקוח. + +#### `abort-upload` + +ביטול העלאה בתהליך. + +בקשה: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +הספרן: +1. מתקשר ל-S3 `AbortMultipartUpload` כדי לנקות חלקים. +2. מוחק את רשומת הסשן מ-Cassandra. + +#### `get-upload-status` + +בדיקת סטטוס של העלאה (לצורך אפשרות המשך). + +בקשה: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +תגובה: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +הצגת רשימה של העלאות חסרות השלמה עבור משתמש. + +בקשה: +```json +{ + "operation": "list-uploads" +} +``` + +תגובה: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### אחסון סשן העלאה + +מעקב אחר העלאות בתהליך ב-Cassandra: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**התנהגות TTL:** +סשנים פוקעים לאחר 24 שעות אם לא הושלמו. +כאשר TTL של Cassandra פוקע, רשומת הסשן נמחקת. +חלקים של S3 שנותרו מאחור מנוקים על ידי מדיניות מחזור חיים של S3 (יש להגדיר על ה-bucket). + +### טיפול בכשלים ואטומיות + +**כשל בהעלאת חלק:** +הלקוח מנסה שוב את החלק שנכשל (באמצעות אותו `upload_id` ו-`chunk-index`). +`UploadPart` של S3 היא פעולה אידempotent עבור אותו מספר חלק. +הסשן עוקב אחר אילו חלקים הצליחו. + +**ניתוק לקוח במהלך העלאה:** +הסשן נשאר ב-Cassandra עם החלקים שהתקבלו. +הלקוח יכול לקרוא ל-`get-upload-status` כדי לראות מה חסר. +ניתן לחדש על ידי העלאת רק החלקים החסרים, ולאחר מכן `complete-upload`. + +**כשל בהעלאה מלאה:** +`CompleteMultipartUpload` של S3 היא פעולה אטומית - או מצליחה לחלוטין או נכשלת. +במקרה של כשל, החלקים נשארים והלקוח יכול לנסות שוב את `complete-upload`. +לא ניתן לראות מסמך חלקי. + +**תפוגת הסשן:** +TTL של Cassandra מוחקת את רשומת הסשן לאחר 24 שעות. +מדיניות מחזור חיים של bucket ב-S3 מנקה העלאות מרובות חלקים לא שלמות. +אין צורך בניקוי ידני. + +### אטומיות של העלאות מרובות חלקים ב-S3 + +העלאות מרובות חלקים ב-S3 מספקות אטומיות מובנית: + +1. **חלקים אינם גלויים**: חלקים שהועלו לא ניתנים לגישה כאובייקטים. + הם קיימים רק כחלקים של העלאה מרובת חלקים לא שלמה. + +2. **השלמה אטומית**: `CompleteMultipartUpload` מצליחה (האובייקט + מופיע באופן אטומי) או נכשלת (לא נוצר אובייקט). אין מצב חלקי. + +3. **אין צורך בשינוי שם**: המפתח של האובייקט הסופי מצוין בזמן + `CreateMultipartUpload`. החלקים משולבים ישירות למפתח זה. + +4. **שילוב בצד השרת**: S3 משלבת חלקים באופן פנימי. ה-librarian + לעולם לא קורא בחזרה חלקים - אין עומס זיכרון ללא קשר לגודל המסמך. + +### הרחבות BlobStore + +**קובץ:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +הוספת שיטות העלאה מרובות חלקים: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### שיקולי גודל מקטע + +**מינימום עבור S3**: 5MB לכל חלק (למעט החלק האחרון) +**מקסימום עבור S3**: 10,000 חלקים לכל העלאה +**ערך ברירת מחדל מעשי**: מקטעים בגודל 5MB + מסמך בגודל 500MB = 100 מקטעים + מסמך בגודל 5GB = 1,000 מקטעים +**גרנולריות של התקדמות**: מקטעים קטנים יותר = עדכוני התקדמות מדויקים יותר +**יעילות רשת**: מקטעים גדולים יותר = פחות מעברים + +גודל המקטע יכול להיות מוגדר על ידי הלקוח בטווח מסוים (5MB - 100MB). + +### עיבוד מסמכים: אחזור סטרימינג + +זרימת ההעלאה מטפלת בהעברת מסמכים לאחסון בצורה יעילה. זרימת העיבוד מטפלת בחילוץ ופיצול מסמכים מבלי לטעון +אותם כולם לזיכרון. + + +#### עקרון עיצוב: מזהה, לא תוכן + +כיום, כאשר עיבוד מופעל, תוכן המסמך זורם באמצעות הודעות Pulsar. זה טוען מסמכים שלמים לזיכרון. במקום זאת: + + +הודעות Pulsar נושאות רק את **מזהה המסמך** +מעבדים שולפים תוכן מסמך ישירות מהספרן (librarian) +השליפה מתבצעת כ**זרם לקובץ זמני** +ניתוח ספציפי למסמך (PDF, טקסט, וכו') עובד עם קבצים, ולא עם מאגרי זיכרון + +זה שומר על כך שהספרן אינו תלוי במבנה המסמך. ניתוח PDF, חילוץ טקסט, ולוגיקה ספציפית אחרת לפורמט נשארים בדקודינג המתאים. + + +#### זרימת עיבוד + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### ממשק API של ספריות + +הוספת פעולת שליפה של מסמכים בסטרימינג: + +**`stream-document`** + +בקשה: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +תגובה: מקטעי נתונים בינאריים (ולא תגובה יחידה). + +עבור ממשק API REST, זה מחזיר תגובה סטרימינג עם `Transfer-Encoding: chunked`. + +עבור שיחות פנימיות בין שירותים (ממעבד לספרן), זה יכול להיות: +סטרימינג ישיר מ-S3 באמצעות כתובת URL חתומה מראש (אם רשת פנימית מאפשרת זאת). +תגובות מחולקות באמצעות פרוטוקול השירות. +נקודת קצה ייעודית לסטרימינג. + +הדרישה העיקרית: הנתונים זורמים במקטעים, ואינם מאוחסנים באופן מלא בזיכרון בספרן. + +#### שינויים במפענח PDF + +**יישום נוכחי** (דורש משאבים רבים בזיכרון): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**יישום חדש** (קובץ זמני, מצטבר): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +פרופיל זיכרון: +קובץ זמני בדיסק: גודל קובץ ה-PDF (דיסק זול). +בזיכרון: עמוד טקסט אחד בכל פעם. +שיא זיכרון: מוגבל, בלתי תלוי בגודל המסמך. + +#### שינויים במפענח מסמכי טקסט + +עבור מסמכי טקסט רגילים, זה אפילו פשוט יותר - אין צורך בקובץ זמני: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +מסמכי טקסט יכולים לעבור סטרימינג ישירות ללא קובץ זמני מכיוון שהם +בנויים בצורה ליניארית. + +#### שילוב עם מודול חלוקה (Chunker) + +המודול חלוקה מקבל איטרטור של טקסט (עמודים או פסקאות) ומייצר +חלקים באופן הדרגתי: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### צינור עיבוד מקצה לקצה + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +בשום שלב לא נשמר המסמך השלם או הטקסט החלץ בזיכרון. + +#### שיקולים לגבי קבצי זמניים + +**מיקום**: יש להשתמש בספריית הזמנים של המערכת (`/tmp` או מקביל). עבור +פריסות מבוססות קונטיינרים, ודאו שספריית הזמנים מכילה מספיק מקום +ושנמצאת באחסון מהיר (לא מחובר לרשת, אם אפשר). + +**ניקוי**: יש להשתמש במנהלי הקשר (context managers) (`with tempfile...`) כדי להבטיח ניקוי +גם במקרה של חריגות. + +**עיבוד מקבילי**: כל משימת עיבוד מקבלת קובץ זמני משלה. +אין התנגשויות בין עיבוד מקבילי של מסמכים. + +**שטח דיסק**: קבצים זמניים הם קצרי טווח (משך העיבוד). עבור +קובץ PDF בגודל 500MB, נדרש שטח זמני של 500MB במהלך העיבוד. ניתן +לאכוף מגבלת גודל בזמן ההעלאה אם יש מגבלות על שטח הדיסק. + +### ממשק עיבוד מאוחד: מסמכים משניים + +חילוץ PDF ועיבוד מסמכי טקסט צריכים להזין לאותו +צינור עיבוד המשכיות (chunker → embeddings → storage). כדי להשיג זאת עם +ממשק "שליפה לפי מזהה" עקבי, חלקי טקסט חלצים מאוחסנים בחזרה +ל-librarian כמסמכים משניים. + +#### זרימת עיבוד עם מסמכים משניים + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +למודול החלוקה יש ממשק אחיד אחד: +קבלת מזהה מסמך (דרך Pulsar) +קבלת תוכן מהספרן +חלוקת התוכן לחלקים + +הוא לא יודע או אכפת לו האם המזהה מתייחס ל: +מסמך טקסט שהועלה על ידי משתמש +פיסת טקסט שחולצה מעמוד PDF +כל סוג מסמך עתידי + +#### מטא-נתונים של מסמכים משניים + +הרחבת הסכימה של המסמך כדי לעקוב אחר קשרים הוריים/משניים: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**סוגי מסמכים:** + +| `document_type` | תיאור | +|-----------------|-------------| +| `source` | מסמך שהועלה על ידי משתמש (PDF, טקסט, וכו') | +| `extracted` | נגזר ממסמך מקור (לדוגמה, טקסט של עמוד PDF) | + +**שדות מטא-דאטה:** + +| שדה | מסמך מקור | מסמך משני | +|-------|-----------------|-----------------| +| `id` | שסופק על ידי המשתמש או נוצר | נוצר (לדוגמה, `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | מזהה מסמך הורה | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, וכו' | `text/plain` | +| `title` | שסופק על ידי המשתמש | נוצר (לדוגמה, "עמוד 3 של Report.pdf") | +| `user` | משתמש מאומת | זהה למסמך הורה | + +#### ממשק API של הספרן עבור מסמכים משניים + +**יצירת מסמכים משניים** (פנימי, בשימוש על ידי pdf-extractor): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +עבור טקסט קצר שחולץ (טקסט עמוד טיפוסי הוא פחות מ-100KB), העלאה בפעולה אחת מקובלת. עבור חילוצי טקסט גדולים מאוד, ניתן להשתמש בהעלאה מחולקת. + +**רשימת מסמכים משניים** (לצרכי ניפוי באגים/ניהול): + +**הצגת מסמכים משניים** (לצרכי ניפוי באגים/ניהול): + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +תגובה: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### התנהגות מול המשתמש + +**התנהגות ברירת מחדל `list-documents`:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +רק מסמכים ברמה העליונה (מקור) מופיעים ברשימת המסמכים של המשתמש. +מסמכים משניים מסוננים כברירת מחדל. + +**דגל "הכללה של תת-מסמכים" אופציונלי** (למנהל/דיבוג): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### מחיקה מדורגת + +כאשר מסמך הורה נמחק, יש למחוק את כל הצאצאים: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### שיקולי אחסון + +קטעי טקסט שחולצו מכפילים תוכן: +קובץ PDF מקורי מאוחסן ב-"Garage" +טקסט שחולץ לכל עמוד מאוחסן גם ב-"Garage" + +פשרה זו מאפשרת: +**ממשק "חיתוך" אחיד**: "חיתוך" תמיד שולף לפי מזהה +**התחלה מחדש/ניסיון חוזר**: ניתן להתחיל בשלב ה-"חיתוך" מבלי לחלץ מחדש את קובץ ה-PDF +**ניפוי שגיאות**: ניתן לבדוק את הטקסט שחולץ +**הפרדת אחריות**: שירות חילוץ ה-PDF ושירות ה-"חיתוך" הם שירותים עצמאיים + +עבור קובץ PDF בגודל 500MB עם 200 עמודים, כאשר בממוצע יש 5KB טקסט לעמוד: +אחסון קובץ PDF: 500MB +אחסון טקסט שחולץ: כ-1MB בסך הכל +תקורה: זניחה + +#### פלט של מופע חילוץ PDF + +מופע חילוץ ה-PDF, לאחר עיבוד מסמך: + +1. מוריד את קובץ ה-PDF מה-"librarian" לקובץ זמני +2. מחלץ טקסט עמוד אחר עמוד +3. עבור כל עמוד, שומר את הטקסט שחולץ כמסמך משני דרך ה-"librarian" +4. שולח מזהי מסמכים משניים לתור ה-"chunker" +פלט חוזה (יש לעקוב אחר הפורמט המדויק). +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +המודול שמחלק את הטקסט מקבל את מזהי הילדים הללו ומעבד אותם באופן זהה +לאופן שבו הוא היה מעבד מסמך טקסט שהועלה על ידי משתמש. + +### עדכונים עבור הלקוח + +#### ערכת פיתוח תוכנה (SDK) עבור Python + +ערכת הפיתוח תוכנה (`trustgraph-base/trustgraph/api/library.py`) עבור Python צריכה לטפל +בהעלאות מחולקות בצורה שקופה. הממשק הציבורי נשאר ללא שינוי: + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +מבפנים, ה-SDK מזהה את גודל המסמך ועובר לאסטרטגיה אחרת: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**החזרות התקדמות** (שיפור אופציונלי): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +זה מאפשר לממשקים גרפיים להציג את התקדמות ההעלאה מבלי לשנות את ממשק ה-API הבסיסי. + +#### כלים עבור שורת הפקודה + +**`tg-add-library-document`** ממשיך לעבוד ללא שינוי: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +ניתן להוסיף תצוגת התקדמות אופציונלית: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**כלים מיושנים הוסרו:** + +`tg-load-pdf` - מיושן, השתמשו ב-`tg-add-library-document` +`tg-load-text` - מיושן, השתמשו ב-`tg-add-library-document` + +**פקודות ניהול/דיבוג** (אופציונלי, בעדיפות נמוכה): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +אלו יכולות להיות דגלים בפקודה הקיימת ולא כלים נפרדים. + +#### עדכוני מפרט API + +יש לעדכן את מפרט OpenAPI (`specs/api/paths/librarian.yaml`) עבור: + +**פעולות חדשות:** + +`begin-upload` - אתחול סשן העלאה מקוטעת +`upload-chunk` - העלאת חלק בודד +`complete-upload` - השלמת העלאה +`abort-upload` - ביטול העלאה +`get-upload-status` - שאילתת התקדמות העלאה +`list-uploads` - הצגת רשימת העלאות חלקיות עבור משתמש +`stream-document` - אחזור מסמך בסטרימינג +`add-child-document` - אחסון טקסט חילוץ (פנימי) +`list-children` - הצגת רשימת מסמכים ילדים (מנהל מערכת) + +**פעולות ששונו:** + +`list-documents` - הוספת פרמטר `include-children` + +**סכימות חדשות:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**עדכוני מפרט WebSocket** (`specs/websocket/`): + +שכפול הפעולות REST עבור לקוחות WebSocket, המאפשר עדכונים בזמן אמת +במהלך ההעלאה. + +#### שיקולי UX + +עדכוני מפרט ה-API מאפשרים שיפורים בחזית המשתמש: + +**ממשק התקדמות העלאה:** +סרגל התקדמות המציג חלקים שהועלו +זמן משוער שנותר +אפשרות השהיה/המשך + +**התאוששות משגיאות:** +אפשרות "המשך העלאה" עבור העלאות שהופרעו +רשימת העלאות תלויות לאחר חיבור מחדש + +**טיפול בקבצים גדולים:** +זיהוי גודל קובץ בצד הלקוח +העלאה מקוטעת אוטומטית עבור קבצים גדולים +משוב ברור במהלך העלאות ארוכות + +שיפורי UX אלו דורשים עבודה בצד החזית המשתמש, המונחית על ידי מפרט ה-API המעודכן. diff --git a/docs/tech-specs/large-document-loading.hi.md b/docs/tech-specs/large-document-loading.hi.md new file mode 100644 index 00000000..b2788edd --- /dev/null +++ b/docs/tech-specs/large-document-loading.hi.md @@ -0,0 +1,992 @@ +--- +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. + +## अवलोकन + +यह विनिर्देश स्केलेबिलिटी और उपयोगकर्ता अनुभव से संबंधित मुद्दों को संबोधित करता है जो तब उत्पन्न होते हैं जब TrustGraph में बड़े दस्तावेज़ लोड किए जाते हैं। वर्तमान आर्किटेक्चर दस्तावेज़ अपलोड को एक एकल, अविभाज्य ऑपरेशन के रूप में मानता है, जिससे पाइपलाइन के कई बिंदुओं पर मेमोरी का दबाव पड़ता है और उपयोगकर्ताओं को कोई प्रतिक्रिया या रिकवरी विकल्प नहीं मिलते हैं। + +यह कार्यान्वयन निम्नलिखित उपयोग मामलों को लक्षित करता है: + + + + +1. **बड़े पीडीएफ प्रसंस्करण**: सैकड़ों मेगाबाइट के पीडीएफ फ़ाइलों को अपलोड करें और संसाधित करें + बिना मेमोरी समाप्त किए। +2. **फिर से शुरू करने योग्य अपलोड**: बाधित अपलोड को वहीं से जारी करने की अनुमति दें जहां से + वे रुके थे, न कि पुनः आरंभ करने के बजाय। +3. **प्रगति प्रतिक्रिया**: उपयोगकर्ताओं को अपलोड और प्रसंस्करण की वास्तविक समय की जानकारी प्रदान करें। + 4. **मेमोरी-कुशल प्रसंस्करण**: दस्तावेज़ों को स्ट्रीमिंग तरीके से संसाधित करें +बिना पूरी फ़ाइलों को मेमोरी में रखे। + + +## लक्ष्य + +**क्रमिक अपलोड**: REST और WebSocket के माध्यम से खंडित दस्तावेज़ अपलोड का समर्थन। +**फिर से शुरू करने योग्य स्थानांतरण**: बाधित अपलोड से उबरने की क्षमता। +**प्रगति दृश्यता**: क्लाइंट को अपलोड/प्रोसेसिंग प्रगति प्रतिक्रिया प्रदान करें। +**मेमोरी दक्षता**: पाइपलाइन में पूरे दस्तावेज़ को बफर करने से बचें। +**पिछड़ा संगतता**: मौजूदा छोटे दस्तावेज़ वर्कफ़्लो बिना किसी बदलाव के जारी रहते हैं। +**स्ट्रीमिंग प्रोसेसिंग**: PDF डिकोडिंग और टेक्स्ट चंकिंग स्ट्रीम पर काम करते हैं। + +## पृष्ठभूमि + +### वर्तमान आर्किटेक्चर + +दस्तावेज़ सबमिशन निम्नलिखित पथ से गुजरता है: + +1. **क्लाइंट** REST (`POST /api/v1/librarian`) या WebSocket के माध्यम से दस्तावेज़ सबमिट करता है। +2. **API गेटवे** बेस64-एन्कोडेड दस्तावेज़ सामग्री के साथ पूर्ण अनुरोध प्राप्त करता है। +3. **LibrarianRequestor** अनुरोध को Pulsar संदेश में बदलता है। +4. **Librarian सर्विस** संदेश प्राप्त करता है, दस्तावेज़ को मेमोरी में डिकोड करता है। +5. **BlobStore** दस्तावेज़ को Garage/S3 पर अपलोड करता है। +6. **Cassandra** ऑब्जेक्ट संदर्भ के साथ मेटाडेटा संग्रहीत करता है। +7. प्रोसेसिंग के लिए: दस्तावेज़ को S3 से पुनर्प्राप्त किया जाता है, डिकोड किया जाता है, खंडित किया जाता है - सभी मेमोरी में। + +मुख्य फाइलें: +REST/WebSocket एंट्री: `trustgraph-flow/trustgraph/gateway/service.py` +Librarian कोर: `trustgraph-flow/trustgraph/librarian/librarian.py` +Blob स्टोरेज: `trustgraph-flow/trustgraph/librarian/blob_store.py` +Cassandra टेबल: `trustgraph-flow/trustgraph/tables/library.py` +API स्कीमा: `trustgraph-base/trustgraph/schema/services/library.py` + +### वर्तमान सीमाएँ + +वर्तमान डिज़ाइन में कई जटिल मेमोरी और उपयोगकर्ता अनुभव संबंधी समस्याएं हैं: + +1. **परमाणु अपलोड ऑपरेशन**: संपूर्ण दस्तावेज़ को एक + एकल अनुरोध में प्रेषित किया जाना चाहिए। बड़े दस्तावेज़ों के लिए लंबे समय तक चलने वाले अनुरोधों की आवश्यकता होती है, जिसमें कोई प्रगति संकेत नहीं होता है और यदि कनेक्शन विफल हो जाता है तो कोई पुनः प्रयास तंत्र नहीं होता है। + + +2. **एपीआई डिज़ाइन**: REST और WebSocket दोनों एपीआई संपूर्ण दस्तावेज़ की अपेक्षा करते हैं + एक ही संदेश में। स्कीमा (`LibrarianRequest`) में एक `content` + फ़ील्ड है जिसमें संपूर्ण बेस64-एन्कोडेड दस्तावेज़ होता है। + +3. **लाइब्रेरियन मेमोरी**: लाइब्रेरियन सेवा पूरे दस्तावेज़ को + मेमोरी में डिकोड करती है, फिर इसे S3 पर अपलोड करने से पहले। 500MB के PDF के लिए, इसका मतलब है कि 500MB+ को प्रोसेस मेमोरी में रखना। + 500MB+ को प्रोसेस मेमोरी में रखना। + +4. **PDF डिकोडर मेमोरी**: जब प्रोसेसिंग शुरू होती है, तो PDF डिकोडर टेक्स्ट निकालने के लिए पूरे PDF को मेमोरी में लोड करता है। PyPDF और समान लाइब्रेरीज़ को आमतौर पर पूरे दस्तावेज़ तक पहुंच की आवश्यकता होती है। + PyPDF और समान लाइब्रेरीज़ को आमतौर पर पूरे दस्तावेज़ तक पहुंच की आवश्यकता होती है। + + +5. **चंकर मेमोरी**: टेक्स्ट चंकर, निकाले गए पूरे टेक्स्ट को प्राप्त करता है + और इसे मेमोरी में रखता है, जबकि चंक्स बनाता है। + +**मेमोरी प्रभाव का उदाहरण** (500MB पीडीएफ): +गेटवे: ~700MB (बेस64 एन्कोडिंग ओवरहेड) +लाइब्रेरियन: ~500MB (डिकोडेड बाइट्स) +पीडीएफ डिकोडर: ~500MB + एक्सट्रैक्शन बफ़र्स +चंकर: निकाला गया टेक्स्ट (चर, संभावित रूप से 100MB+) + +एक बड़े दस्तावेज़ के लिए कुल अधिकतम मेमोरी 2GB से अधिक हो सकती है। + +## तकनीकी डिज़ाइन + +### डिज़ाइन सिद्धांत + +1. **एपीआई फ़ेसड**: सभी क्लाइंट इंटरैक्शन लाइब्रेरियन एपीआई के माध्यम से होते हैं। क्लाइंट + के पास अंतर्निहित S3/गैराज स्टोरेज तक प्रत्यक्ष पहुंच या ज्ञान नहीं है। + +2. **एस3 मल्टीपार्ट अपलोड**: आंतरिक रूप से मानक एस3 मल्टीपार्ट अपलोड का उपयोग करें। + यह एस3-संगत प्रणालियों (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2, आदि) में व्यापक रूप से समर्थित है, जो पोर्टेबिलिटी सुनिश्चित करता है। + +3. **परमाणु पूर्णता**: एस3 मल्टीपार्ट अपलोड स्वाभाविक रूप से परमाणु होते हैं - अपलोड किए गए + भाग तब तक अदृश्य रहते हैं जब तक कि `CompleteMultipartUpload` को कॉल नहीं किया जाता। कोई अस्थायी + फ़ाइलें या नाम बदलने की क्रियाएं आवश्यक नहीं हैं। + +4. **ट्रैक करने योग्य स्थिति**: अपलोड सत्रों को कैसेंड्रा में ट्रैक किया जाता है, जो + अपूर्ण अपलोडों में दृश्यता प्रदान करता है और पुनः आरंभ करने की क्षमता को सक्षम करता है। + +### चंक्ड अपलोड प्रवाह + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +क्लाइंट कभी भी सीधे S3 के साथ इंटरैक्ट नहीं करता है। लाइब्रेरियन हमारे चंक्ड अपलोड API और S3 मल्टीपार्ट ऑपरेशंस के बीच आंतरिक रूप से अनुवाद करता है। + +### लाइब्रेरियन API ऑपरेशन +### लाइब्रेरियन एपीआई ऑपरेशन + +#### `begin-upload` + +एक खंडित अपलोड सत्र शुरू करें। + +अनुरोध: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +प्रतिक्रिया: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +लाइब्रेरियन: +1. एक अद्वितीय `upload_id` और `object_id` उत्पन्न करता है (ब्लॉब स्टोरेज के लिए UUID)। +2. S3 `CreateMultipartUpload` को कॉल करता है, `s3_upload_id` प्राप्त करता है। +3. कैसेंड्रा में सत्र रिकॉर्ड बनाता है। +4. `upload_id` को क्लाइंट को वापस करता है। + +#### `upload-chunk` + +एक सिंगल चंक अपलोड करें। + +अनुरोध: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +प्रतिक्रिया: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +लाइब्रेरियन: +1. `upload_id` द्वारा सत्र खोजें। +2. स्वामित्व की पुष्टि करें (उपयोगकर्ता को सत्र निर्माता से मेल खाना चाहिए)। +3. चंक डेटा के साथ S3 `UploadPart` को कॉल करें, `etag` प्राप्त करें। +4. चंक इंडेक्स और ईटैग के साथ सत्र रिकॉर्ड को अपडेट करें। +5. क्लाइंट को प्रगति वापस करें। + +विफल चंक्स को फिर से प्रयास किया जा सकता है - बस उसी `chunk-index` को फिर से भेजें। + +#### `complete-upload` + +अपलोड को अंतिम रूप दें और दस्तावेज़ बनाएं। + +अनुरोध: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +प्रतिक्रिया: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +लाइब्रेरियन: +1. सत्र की जांच करता है, यह सुनिश्चित करता है कि सभी भाग प्राप्त हो गए हैं। +2. पार्ट एटाग्स के साथ S3 `CompleteMultipartUpload` को कॉल करता है (S3 आंतरिक रूप से भागों को संयोजित करता है - लाइब्रेरियन के लिए शून्य मेमोरी लागत)। + 3. मेटाडेटा और ऑब्जेक्ट संदर्भ के साथ कैसेंड्रा में दस्तावेज़ रिकॉर्ड बनाता है। +4. अपलोड सत्र रिकॉर्ड को हटाता है। +5. क्लाइंट को दस्तावेज़ आईडी वापस करता है। +6. + +#### `abort-upload` + +एक चल रहे अपलोड को रद्द करें। + +अनुरोध: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +लाइब्रेरियन: +1. एस3 `AbortMultipartUpload` को भागों को साफ़ करने के लिए कॉल करता है। +2. कैसेंड्रा से सत्र रिकॉर्ड को हटाता है। + +#### `get-upload-status` + +अपलोड की स्थिति की जांच करें (रिज़्यूम क्षमता के लिए)। + +अनुरोध: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +प्रतिक्रिया: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +किसी उपयोगकर्ता के लिए अपूर्ण अपलोड की सूची प्राप्त करें। + +अनुरोध: +```json +{ + "operation": "list-uploads" +} +``` + +प्रतिक्रिया: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### अपलोड सेशन स्टोरेज + +कैसेंड्रा में चल रहे अपलोड को ट्रैक करें: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**टीटीएल व्यवहार:** +सत्र 24 घंटे के बाद समाप्त हो जाते हैं यदि वे पूरे नहीं होते हैं। +जब कैसेंड्रा टीटीएल समाप्त होता है, तो सत्र रिकॉर्ड हटा दिया जाता है। +अनाथ एस3 भाग को एस3 लाइफसाइकिल नीति द्वारा साफ़ किया जाता है (बकेट पर कॉन्फ़िगर करें)। + +### विफलता प्रबंधन और परमाणुता + +**चंक अपलोड विफलता:** +क्लाइंट विफल चंक को फिर से प्रयास करता है (समान `upload_id` और `chunk-index`)। +एस3 `UploadPart` समान भाग संख्या के लिए अपरिवर्तनीय है। +सत्र ट्रैक करता है कि कौन से चंक सफल हुए। + +**क्लाइंट अपलोड के दौरान डिस्कनेक्ट हो जाता है:** +प्राप्त चंक के साथ सत्र कैसेंड्रा में बना रहता है। +क्लाइंट यह देखने के लिए `get-upload-status` को कॉल कर सकता है कि क्या गायब है। +केवल गायब चंक अपलोड करके फिर से शुरू करें, फिर `complete-upload`। + +**पूर्ण-अपलोड विफलता:** +एस3 `CompleteMultipartUpload` परमाणु है - या तो यह पूरी तरह से सफल होता है या विफल रहता है। +विफलता पर, भाग बने रहते हैं और क्लाइंट `complete-upload` को फिर से प्रयास कर सकता है। +कोई आंशिक दस्तावेज़ कभी भी दिखाई नहीं देता है। + +**सेशन समाप्ति:** +कैसेंड्रा TTL 24 घंटे बाद सेशन रिकॉर्ड को हटा देता है। +S3 बकेट लाइफसाइकिल पॉलिसी अधूरी मल्टीपार्ट अपलोड को साफ़ करती है। +कोई मैनुअल सफाई की आवश्यकता नहीं है। + +### S3 मल्टीपार्ट एटॉमिकिटी + +S3 मल्टीपार्ट अपलोड अंतर्निहित एटॉमिकिटी प्रदान करते हैं: + +1. **भाग अदृश्य होते हैं**: अपलोड किए गए भागों को ऑब्जेक्ट के रूप में एक्सेस नहीं किया जा सकता है। + वे केवल एक अधूरी मल्टीपार्ट अपलोड के हिस्से के रूप में मौजूद होते हैं। + +2. **पूर्णता (Atomic completion)**: `CompleteMultipartUpload` या तो सफल होता है (वस्तु परमाणु रूप से दिखाई देती है) या विफल होता है (कोई वस्तु नहीं बनाई जाती है)। कोई आंशिक स्थिति नहीं। + +3. **नाम बदलने की आवश्यकता नहीं**: अंतिम वस्तु कुंजी ⟦CODE_0⟧ समय पर निर्दिष्ट की जाती है। भाग सीधे उस कुंजी पर संयोजित होते हैं। + + `CreateMultipartUpload` समय। भाग सीधे उस कुंजी में संयोजित किए जाते हैं। + +4. **सर्वर-साइड कोएलेसेंस (Server-side coalesce)**: S3 आंतरिक रूप से भागों को जोड़ता है। लाइब्रेरियन + कभी भी भागों को वापस नहीं पढ़ता है - दस्तावेज़ के आकार की परवाह किए बिना शून्य मेमोरी ओवरहेड। + +### ब्लबस्टोर एक्सटेंशन (BlobStore Extensions) + +**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +मल्टीपार्ट अपलोड विधियों को जोड़ें: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### चंक आकार (Chunk Size) पर विचार + +**S3 न्यूनतम**: प्रति भाग 5MB (अंतिम भाग को छोड़कर) +**S3 अधिकतम**: प्रति अपलोड 10,000 भाग +**व्यावहारिक डिफ़ॉल्ट**: 5MB के चंक + 500MB का दस्तावेज़ = 100 चंक + 5GB का दस्तावेज़ = 1,000 चंक +**प्रगति की सूक्ष्मता**: छोटे चंक = अधिक सटीक प्रगति अपडेट +**नेटवर्क दक्षता**: बड़े चंक = कम राउंड ट्रिप + +चंक का आकार (5MB - 100MB) की सीमा के भीतर क्लाइंट द्वारा कॉन्फ़िगर किया जा सकता है। + +### दस्तावेज़ प्रसंस्करण: स्ट्रीमिंग पुनर्प्राप्ति + +अपलोड प्रवाह भंडारण में दस्तावेजों को कुशलतापूर्वक लाने के लिए है। प्रसंस्करण प्रवाह दस्तावेजों को पूरी तरह से मेमोरी में लोड किए बिना, उन्हें निकालने और चंक में विभाजित करने के लिए है। + +#### डिज़ाइन सिद्धांत: पहचानकर्ता, सामग्री नहीं + +वर्तमान में, जब प्रसंस्करण शुरू होता है, तो दस्तावेज़ सामग्री पल्सर संदेशों के माध्यम से प्रवाहित होती है। इससे पूरे दस्तावेज़ मेमोरी में लोड हो जाते हैं। इसके बजाय: + +पल्सर संदेश केवल **दस्तावेज़ पहचानकर्ता** ले जाते हैं +प्रोसेसर सीधे लाइब्रेरियन से दस्तावेज़ सामग्री प्राप्त करते हैं +पुनर्प्राप्ति एक **अस्थायी फ़ाइल में स्ट्रीम** के रूप में होती है +दस्तावेज़-विशिष्ट पार्सिंग (PDF, टेक्स्ट, आदि) फ़ाइलों के साथ काम करते हैं, मेमोरी बफ़र्स के साथ नहीं + +यह लाइब्रेरियन को दस्तावेज़-संरचना-अज्ञेयवादी रखता है। PDF पार्सिंग, टेक्स्ट +निष्कर्षण और अन्य प्रारूप-विशिष्ट तर्क संबंधित डिकोडर में रहते हैं। + +#### प्रसंस्करण प्रवाह + + +#### प्रसंस्करण प्रवाह + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### लाइब्रेरियन स्ट्रीम एपीआई + +एक स्ट्रीमिंग दस्तावेज़ पुनर्प्राप्ति ऑपरेशन जोड़ें: + +**`stream-document`** + +अनुरोध: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +प्रतिक्रिया: स्ट्रीम किए गए बाइनरी खंड (एकल प्रतिक्रिया नहीं)। + +REST API के लिए, यह `Transfer-Encoding: chunked` के साथ एक स्ट्रीमिंग प्रतिक्रिया लौटाता है। + +आंतरिक सेवा-से-सेवा कॉल के लिए (प्रोसेसर से लाइब्रेरियन तक), यह हो सकता है: +सीधे प्रीसाइंड URL के माध्यम से S3 स्ट्रीमिंग (यदि आंतरिक नेटवर्क अनुमति देता है) +सेवा प्रोटोकॉल पर खंडित प्रतिक्रियाएं +एक समर्पित स्ट्रीमिंग एंडपॉइंट + +मुख्य आवश्यकता: डेटा खंडों में प्रवाहित होता है, और कभी भी पूरी तरह से लाइब्रेरियन में बफर नहीं होता है। + +#### PDF डिकोडर परिवर्तन + +**वर्तमान कार्यान्वयन** (मेमोरी-गहन): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**नया कार्यान्वयन** (अस्थायी फ़ाइल, क्रमिक): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +मेमोरी प्रोफाइल: +अस्थायी फ़ाइल डिस्क पर: पीडीएफ का आकार (डिस्क सस्ती है) +मेमोरी में: एक बार में एक पृष्ठ का टेक्स्ट +अधिकतम मेमोरी: सीमित, दस्तावेज़ के आकार से स्वतंत्र + +#### टेक्स्ट डॉक्यूमेंट डिकोडर में बदलाव + +सादे टेक्स्ट दस्तावेज़ों के लिए, और भी सरल - किसी अस्थायी फ़ाइल की आवश्यकता नहीं: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +टेक्स्ट दस्तावेज़ सीधे अस्थायी फ़ाइल के बिना स्ट्रीम किए जा सकते हैं क्योंकि वे +रैखिक रूप से संरचित होते हैं। + +#### स्ट्रीमिंग चंकर एकीकरण + +चंकर टेक्स्ट (पृष्ठों या पैराग्राफों) का एक इटरेटर प्राप्त करता है और क्रमिक रूप से +चंक्स उत्पन्न करता है: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### एंड-टू-एंड प्रोसेसिंग पाइपलाइन + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +किसी भी समय, संपूर्ण दस्तावेज़ या संपूर्ण निकाले गए पाठ को मेमोरी में संग्रहीत नहीं किया जाता है। + +#### अस्थायी फ़ाइल संबंधी विचार + +**स्थान:** सिस्टम के अस्थायी फ़ोल्डर का उपयोग करें (`/tmp` या समकक्ष)। कंटेनरयुक्त परिनियोजन के लिए, सुनिश्चित करें कि अस्थायी फ़ोल्डर में पर्याप्त जगह है +और यह तेज़ स्टोरेज पर है (यदि संभव हो तो नेटवर्क-माउंटेड नहीं)। + + +**सफाई:** सफाई सुनिश्चित करने के लिए संदर्भ प्रबंधकों (`with tempfile...`) का उपयोग करें +यहां तक कि अपवादों पर भी। + +**समवर्ती प्रसंस्करण:** प्रत्येक प्रसंस्करण कार्य का अपना अस्थायी फ़ाइल होता है। +समानांतर दस्तावेज़ प्रसंस्करण के बीच कोई टकराव नहीं होता है। + +**डिस्क स्पेस**: अस्थायी फ़ाइलें अल्पकालिक होती हैं (प्रोसेसिंग की अवधि)। +500MB के PDF के लिए, प्रोसेसिंग के दौरान 500MB अस्थायी स्थान की आवश्यकता होती है। यदि डिस्क स्पेस सीमित है, तो आकार सीमा अपलोड के समय लागू की जा सकती है। + + +### एकीकृत प्रोसेसिंग इंटरफ़ेस: चाइल्ड दस्तावेज़ + +PDF निष्कर्षण और टेक्स्ट दस्तावेज़ प्रोसेसिंग को एक ही +डाउनस्ट्रीम पाइपलाइन (चंकर → एम्बेडिंग → स्टोरेज) में फीड करने की आवश्यकता है। इसे एक सुसंगत "आईडी द्वारा प्राप्त करें" इंटरफ़ेस के साथ प्राप्त करने के लिए, निकाले गए टेक्स्ट ब्लॉकों को "चाइल्ड दस्तावेज़" के रूप में लाइब्रेरियन में वापस संग्रहीत किया जाता है। + + + +#### चाइल्ड दस्तावेज़ों के साथ प्रोसेसिंग प्रवाह + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +चंकर (chunker) में एक समान इंटरफ़ेस है: +एक दस्तावेज़ आईडी प्राप्त करें (पल्सर के माध्यम से) +लाइब्रेरियन से सामग्री स्ट्रीम करें +इसे छोटे भागों में विभाजित करें + +यह नहीं जानता या परवाह नहीं करता कि आईडी किस चीज़ को संदर्भित करती है: +एक उपयोगकर्ता द्वारा अपलोड किया गया टेक्स्ट दस्तावेज़ +एक पीडीएफ पृष्ठ से निकाला गया टेक्स्ट ब्लॉक +कोई भी भविष्य का दस्तावेज़ प्रकार + +#### चाइल्ड दस्तावेज़ मेटाडेटा + +दस्तावेज़ स्कीमा को पैरेंट/चाइल्ड संबंधों को ट्रैक करने के लिए विस्तारित करें: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**दस्तावेज़ के प्रकार:** + +| `document_type` | विवरण | +|-----------------|-------------| +| `source` | उपयोगकर्ता द्वारा अपलोड किया गया दस्तावेज़ (पीडीएफ, टेक्स्ट, आदि) | +| `extracted` | स्रोत दस्तावेज़ से प्राप्त (उदाहरण के लिए, पीडीएफ पृष्ठ पाठ) | + +**मेटाडेटा फ़ील्ड:** + +| फ़ील्ड | स्रोत दस्तावेज़ | निकाली गई चाइल्ड | +|-------|-----------------|-----------------| +| `id` | उपयोगकर्ता द्वारा प्रदान किया गया या उत्पन्न | उत्पन्न (उदाहरण के लिए, `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | मूल दस्तावेज़ आईडी | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, आदि | `text/plain` | +| `title` | उपयोगकर्ता द्वारा प्रदान किया गया | उत्पन्न (उदाहरण के लिए, "रिपोर्ट.pdf का पृष्ठ 3") | +| `user` | प्रमाणित उपयोगकर्ता | मूल के समान | + +#### चाइल्ड दस्तावेज़ों के लिए लाइब्रेरियन एपीआई + +**चाइल्ड दस्तावेज़ बनाना** (आंतरिक, pdf-extractor द्वारा उपयोग किया जाता है): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +छोटे, निकाले गए टेक्स्ट के लिए (सामान्य पृष्ठ टेक्स्ट < 100KB है), सिंगल-ऑपरेशन अपलोड स्वीकार्य है। बहुत बड़े टेक्स्ट एक्सट्रैक्शन के लिए, चंक्ड अपलोड का उपयोग किया जा सकता है। + +**चाइल्ड दस्तावेज़ों की सूची** (डीबगिंग/एडमिन के लिए): + +**चाइल्ड दस्तावेज़ों की सूची** (डीबगिंग/प्रशासन के लिए): + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +प्रतिक्रिया: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### उपयोगकर्ता-सामना करने वाला व्यवहार + +**`list-documents` डिफ़ॉल्ट व्यवहार:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +केवल शीर्ष-स्तरीय (मूल) दस्तावेज़ ही उपयोगकर्ता की दस्तावेज़ सूची में दिखाई देते हैं। +चाइल्ड दस्तावेज़ डिफ़ॉल्ट रूप से फ़िल्टर कर दिए जाते हैं। + +**वैकल्पिक 'शामिल-चाइल्ड' फ़्लैग** (व्यवस्थापक/डीबगिंग के लिए): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### कैस्केड डिलीट + +जब कोई पैरेंट दस्तावेज़ हटाया जाता है, तो सभी चाइल्ड दस्तावेज़ों को भी हटाया जाना चाहिए: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### भंडारण संबंधी विचार + +निकाले गए टेक्स्ट ब्लॉक डुप्लिकेट सामग्री बनाते हैं: +मूल पीडीएफ "गैराज" में संग्रहीत है। +प्रत्येक पृष्ठ के लिए निकाला गया टेक्स्ट भी "गैराज" में संग्रहीत है। + +यह समझौता निम्नलिखित को सक्षम बनाता है: +**समान चंकर इंटरफ़ेस**: चंकर हमेशा आईडी द्वारा डेटा प्राप्त करता है। +**फिर से शुरू/पुनः प्रयास**: पीडीएफ को फिर से निकालने के बिना, चंकर चरण पर पुनः आरंभ किया जा सकता है। +**डीबगिंग**: निकाले गए टेक्स्ट का निरीक्षण किया जा सकता है। +**चिंताओं का पृथक्करण**: पीडीएफ एक्सट्रैक्टर और चंकर स्वतंत्र सेवाएं हैं। + +500 एमबी के पीडीएफ में 200 पृष्ठ हैं, जिनमें से प्रत्येक पृष्ठ पर औसतन 5 केबी टेक्स्ट है: +पीडीएफ भंडारण: 500 एमबी +निकाले गए टेक्स्ट भंडारण: लगभग 1 एमबी +अतिरिक्त भार: नगण्य + +#### पीडीएफ एक्सट्रैक्टर आउटपुट + +पीडीएफ-एक्सट्रैक्टर, किसी दस्तावेज़ को संसाधित करने के बाद: + +1. पीडीएफ को लाइब्रेरियन से अस्थायी फ़ाइल में स्ट्रीम करता है। +2. पृष्ठ दर पृष्ठ टेक्स्ट निकालता है। +3. प्रत्येक पृष्ठ के लिए, निकाले गए टेक्स्ट को लाइब्रेरियन के माध्यम से एक चाइल्ड दस्तावेज़ के रूप में संग्रहीत करता है। +4. चाइल्ड दस्तावेज़ आईडी को चंकर कतार में भेजता है। + +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +चंकर इन चाइल्ड आईडी को प्राप्त करता है और उन्हें उसी तरह संसाधित करता है जैसे कि वह किसी उपयोगकर्ता द्वारा अपलोड किए गए टेक्स्ट दस्तावेज़ को संसाधित करता है। +चंकर इन चाइल्ड आईडी को प्राप्त करता है और उन्हें उसी तरह संसाधित करता है जैसे कि वह किसी उपयोगकर्ता द्वारा अपलोड किए गए टेक्स्ट दस्तावेज़ को संसाधित करता है। + +### क्लाइंट अपडेट + +#### पायथन एसडीके + +पायथन एसडीके (`trustgraph-base/trustgraph/api/library.py`) को खंडित अपलोड को पारदर्शी रूप से संभालना चाहिए। सार्वजनिक इंटरफ़ेस अपरिवर्तित रहता है: +खंडित अपलोड को पारदर्शी रूप से संभालना चाहिए। सार्वजनिक इंटरफ़ेस अपरिवर्तित रहता है: + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +आंतरिक रूप से, SDK दस्तावेज़ के आकार का पता लगाता है और रणनीति बदलता है: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**प्रगति कॉलबैक** (वैकल्पिक संवर्द्धन): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +यह यूआई को बुनियादी एपीआई को बदले बिना अपलोड की प्रगति प्रदर्शित करने की अनुमति देता है। + +#### कमांड लाइन उपकरण + +**`tg-add-library-document`** बिना किसी बदलाव के काम करता रहता है: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +वैकल्पिक प्रगति प्रदर्शन जोड़ा जा सकता है: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**पुराने उपकरण हटा दिए गए:** + +`tg-load-pdf` - अप्रचलित, `tg-add-library-document` का उपयोग करें। +`tg-load-text` - अप्रचलित, `tg-add-library-document` का उपयोग करें। + +**व्यवस्थापक/डीबग कमांड** (वैकल्पिक, कम प्राथमिकता): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +ये मौजूदा कमांड पर मौजूद फ़्लैग हो सकते हैं, अलग-अलग टूल नहीं। + +#### एपीआई विनिर्देश अपडेट + +OpenAPI विनिर्देश (`specs/api/paths/librarian.yaml`) को निम्नलिखित के लिए अपडेट करने की आवश्यकता है: + +**नए ऑपरेशन:** + +`begin-upload` - चंक्ड अपलोड सत्र को आरंभ करें +`upload-chunk` - व्यक्तिगत चंक अपलोड करें +`complete-upload` - अपलोड को अंतिम रूप दें +`abort-upload` - अपलोड को रद्द करें +`get-upload-status` - अपलोड की प्रगति की जांच करें +`list-uploads` - उपयोगकर्ता के लिए अपूर्ण अपलोड की सूची बनाएं +`stream-document` - दस्तावेज़ पुनर्प्राप्ति (स्ट्रीमिंग) +`add-child-document` - निकाले गए पाठ को संग्रहीत करें (आंतरिक) +`list-children` - चाइल्ड दस्तावेज़ों की सूची बनाएं (व्यवस्थापक) + +**संशोधित ऑपरेशन:** + +`list-documents` - `include-children` पैरामीटर जोड़ें + +**नए स्कीमा:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**WebSocket विनिर्देश अपडेट** (`specs/websocket/`): + +WebSocket क्लाइंट के लिए REST ऑपरेशन को प्रतिबिंबित करें, जिससे अपलोड के दौरान वास्तविक समय +प्रगति अपडेट सक्षम हो सके। + +#### यूएक्स विचार + +एपीआई विनिर्देश अपडेट फ्रंटएंड में सुधारों को सक्षम करते हैं: + +**अपलोड प्रगति यूआई:** +अपलोड किए गए चंक्स को दिखाने वाला प्रगति बार +अनुमानित शेष समय +पॉज़/रीज़्यूम क्षमता + +**त्रुटि सुधार:** +बाधित अपलोड के लिए "अपलोड फिर से शुरू करें" विकल्प +पुनः कनेक्ट करने पर लंबित अपलोड की सूची + +**बड़ी फ़ाइल हैंडलिंग:** +क्लाइंट-साइड फ़ाइल आकार का पता लगाना +बड़ी फ़ाइलों के लिए स्वचालित चंक्ड अपलोड +लंबे अपलोड के दौरान स्पष्ट प्रतिक्रिया + +ये यूएक्स सुधार अपडेट किए गए एपीआई विनिर्देश द्वारा निर्देशित फ्रंटएंड कार्य की आवश्यकता है। diff --git a/docs/tech-specs/large-document-loading.md b/docs/tech-specs/large-document-loading.md index 497d7bce..036957d5 100644 --- a/docs/tech-specs/large-document-loading.md +++ b/docs/tech-specs/large-document-loading.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Large Document Loading Technical Specification" +parent: "Tech Specs" +--- + # Large Document Loading Technical Specification ## Overview diff --git a/docs/tech-specs/large-document-loading.pt.md b/docs/tech-specs/large-document-loading.pt.md new file mode 100644 index 00000000..178d4f09 --- /dev/null +++ b/docs/tech-specs/large-document-loading.pt.md @@ -0,0 +1,1105 @@ +--- +layout: default +title: "Especificação Técnica de Carregamento de Documentos Grandes" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Carregamento de Documentos Grandes + +> **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 aborda problemas de escalabilidade e experiência do usuário ao carregar +documentos grandes no TrustGraph. A arquitetura atual trata o upload de documentos +como uma operação atômica única, causando pressão de memória em vários pontos do +pipeline e não fornecendo feedback ou opções de recuperação aos usuários. + +Esta implementação visa os seguintes casos de uso: + +1. **Processamento de PDF Grandes**: Fazer upload e processar arquivos PDF de centenas de megabytes + sem esgotar a memória +2. **Uploads Retomáveis**: Permitir que uploads interrompidos continuem de onde + pararam, em vez de reiniciar +3. **Feedback de Progresso**: Fornecer aos usuários visibilidade em tempo real do upload + e do progresso do processamento +4. **Processamento Eficiente em Memória**: Processar documentos de forma streaming + sem manter arquivos inteiros na memória + +## Objetivos + +**Upload Incremental**: Suportar upload de documentos em partes via REST e WebSocket +**Transferências Retomáveis**: Permitir a recuperação de uploads interrompidos +**Visibilidade do Progresso**: Fornecer feedback de upload/processamento aos clientes +**Eficiência de Memória**: Eliminar o buffer de documentos completos em todo o pipeline +**Compatibilidade com Versões Anteriores**: Os fluxos de trabalho existentes de documentos pequenos continuam inalterados +**Processamento em Streaming**: A decodificação de PDF e o particionamento de texto operam em streams + +## Contexto + +### Arquitetura Atual + +O fluxo de envio de documentos passa pelo seguinte caminho: + +1. **Cliente** envia o documento via REST (`POST /api/v1/librarian`) ou WebSocket +2. **API Gateway** recebe a solicitação completa com o conteúdo do documento codificado em base64 +3. **LibrarianRequestor** traduz a solicitação para uma mensagem Pulsar +4. **Librarian Service** recebe a mensagem, decodifica o documento na memória +5. **BlobStore** faz upload do documento para Garage/S3 +6. **Cassandra** armazena metadados com a referência do objeto +7. Para processamento: o documento é recuperado do S3, decodificado, particionado - tudo na memória + +Arquivos chave: +<<<<<<< HEAD +Ponto de entrada REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +======= +Entrada REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +>>>>>>> 82edf2d (New md files from RunPod) +Núcleo do Librarian: `trustgraph-flow/trustgraph/librarian/librarian.py` +Armazenamento de blobs: `trustgraph-flow/trustgraph/librarian/blob_store.py` +Tabelas do Cassandra: `trustgraph-flow/trustgraph/tables/library.py` +Esquema da API: `trustgraph-base/trustgraph/schema/services/library.py` + +### Limitações Atuais + +O design atual apresenta vários problemas de memória e UX que se agravam: + +1. **Operação de Upload Atômica**: O documento inteiro deve ser transmitido em um + único pedido. Documentos grandes exigem solicitações de longa duração sem + indicação de progresso e sem mecanismo de repetição se a conexão falhar. + +2. **Design da API**: As APIs REST e WebSocket esperam o documento completo +<<<<<<< HEAD + em uma única mensagem. O esquema (`LibrarianRequest`) tem um campo `content` +======= + em uma única mensagem. O esquema (`LibrarianRequest`) tem um único campo `content` +>>>>>>> 82edf2d (New md files from RunPod) + contendo o documento inteiro codificado em base64. + +3. **Memória do Librarian**: O serviço librarian decodifica o documento inteiro + na memória antes de fazer upload para o S3. Para um PDF de 500 MB, isso significa manter + 500 MB+ na memória do processo. + +4. **Memória do Decodificador de PDF**: Quando o processamento começa, o decodificador de PDF carrega + o PDF inteiro na memória para extrair o texto. Bibliotecas como PyPDF normalmente + exigem acesso ao documento completo. + +5. **Memória do Particionador**: O particionador de texto recebe o texto extraído completo + e o mantém na memória enquanto produz os chunks. + +**Exemplo de Impacto na Memória** (PDF de 500 MB): +<<<<<<< HEAD +Gateway: ~700 MB (overhead de codificação base64) +======= +Gateway: ~700 MB (sobrecarga de codificação base64) +>>>>>>> 82edf2d (New md files from RunPod) +Librarian: ~500 MB (bytes decodificados) +Decodificador de PDF: ~500 MB + buffers de extração +Particionador: texto extraído (variável, potencialmente 100 MB+) + +A memória máxima pode exceder 2 GB para um único documento grande. + +## Design Técnico + +### Princípios de Design + +1. **API Facade**: Toda a interação do cliente passa pela API do librarian. Os clientes + não têm acesso direto ou conhecimento do armazenamento subjacente S3/Garage. + +2. **Upload Multipart do S3**: Use o upload multipart padrão do S3 internamente. + Isso é amplamente suportado em sistemas compatíveis com S3 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2, etc.), garantindo a portabilidade. + +3. **Conclusão Atômica**: Os uploads multipart do S3 são inerentemente atômicos - as partes carregadas + são invisíveis até que `CompleteMultipartUpload` seja chamado. Nenhum arquivo temporário ou operação de renomeação necessária. + +<<<<<<< HEAD +4. **Estado Rastreável**: As sessões de upload são rastreadas no Cassandra, fornecendo +visibilidade para uploads incompletos e permitindo a capacidade de retomada. + +### Fluxo de Upload em Partes + +======= + +4. **Estado Rastreável**: As sessões de upload são rastreadas no Cassandra, fornecendo + visibilidade para uploads incompletos e permitindo a capacidade de retomada. + +### Fluxo de Upload em Partes +>>>>>>> 82edf2d (New md files from RunPod) + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +<<<<<<< HEAD +O cliente nunca interage diretamente com o S3. O "librarian" traduz entre +nossa API de upload em partes e as operações multipart do S3 internamente. + +### Operações da API do "Librarian" +======= +O cliente nunca interage diretamente com o S3. O "bibliotecário" traduz entre +nossa API de upload em partes e as operações multipart do S3 internamente. + +### Operações da API do "Bibliotecário" +>>>>>>> 82edf2d (New md files from RunPod) + +#### `begin-upload` + +Inicializar uma sessão de upload em partes. + +Requisição: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +Resposta: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +O bibliotecário: +1. Gera um `upload_id` e `object_id` únicos (UUID para armazenamento de blobs). +2. Chama o S3 `CreateMultipartUpload`, recebe `s3_upload_id`. +3. Cria um registro de sessão no Cassandra. +4. Retorna `upload_id` para o cliente. + +#### `upload-chunk` + +Envie um único bloco. + +Requisição: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +Resposta: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +O bibliotecário: +1. Busca a sessão por `upload_id` +2. Valida a propriedade (o usuário deve corresponder ao criador da sessão) +<<<<<<< HEAD +3. Chama o S3 `UploadPart` com os dados do chunk, recebe `etag` +4. Atualiza o registro da sessão com o índice do chunk e o etag +5. Retorna o progresso para o cliente + +Os chunks com falha podem ser retentados - basta enviar o mesmo `chunk-index` novamente. +======= +3. Chama o S3 `UploadPart` com os dados do fragmento, recebe `etag` +4. Atualiza o registro da sessão com o índice do fragmento e o etag +5. Retorna o progresso para o cliente + +Fragmentos com falha podem ser retransmitidos - basta enviar o mesmo `chunk-index` novamente. +>>>>>>> 82edf2d (New md files from RunPod) + +#### `complete-upload` + +Finalize o upload e crie o documento. + +Requisição: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +Resposta: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +O bibliotecário: +1. Consulta a sessão, verifica se todos os fragmentos foram recebidos. +2. Chama o S3 `CompleteMultipartUpload` com as etiquetas de parte (S3 combina as partes + internamente - custo de memória zero para o bibliotecário). +3. Cria um registro de documento no Cassandra com metadados e referência ao objeto. +4. Exclui o registro da sessão de upload. +5. Retorna o ID do documento para o cliente. + +#### `abort-upload` + +Cancelar um upload em andamento. + +Requisição: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +O bibliotecário: +1. Chama o S3 `AbortMultipartUpload` para limpar partes. +2. Exclui o registro da sessão do Cassandra. + +#### `get-upload-status` + +Consulta o status de um upload (para a capacidade de retomada). + +Requisição: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +Resposta: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +Listar uploads incompletos para um usuário. + +Requisição: +```json +{ + "operation": "list-uploads" +} +``` + +Resposta: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### Upload de Sessão de Armazenamento + +Acompanhe uploads em andamento no Cassandra: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**Comportamento do TTL:** +<<<<<<< HEAD +As sessões expiram após 24 horas se não forem concluídas. +======= +As sessões expiram após 24 horas, se não forem concluídas. +>>>>>>> 82edf2d (New md files from RunPod) +Quando o TTL do Cassandra expira, o registro da sessão é excluído. +Partes S3 órfãs são limpas pela política de ciclo de vida do S3 (configure no bucket). + +### Tratamento de Falhas e Atomicidade + +<<<<<<< HEAD +**Falha no upload de chunks:** +O cliente tenta novamente o chunk com falha (mesmo `upload_id` e `chunk-index`). +O `UploadPart` do S3 é idempotente para o mesmo número de parte. +A sessão rastreia quais chunks foram bem-sucedidos. + +**Desconexão do cliente durante o upload:** +A sessão permanece no Cassandra com os chunks recebidos registrados. +O cliente pode chamar `get-upload-status` para ver o que está faltando. +Retomar enviando apenas os chunks ausentes e, em seguida, `complete-upload`. +======= +**Falha no upload de partes:** +O cliente tenta novamente a parte com falha (mesmo `upload_id` e `chunk-index`). +O `UploadPart` do S3 é idempotente para o mesmo número de parte. +A sessão rastreia quais partes foram bem-sucedidas. + +**Desconexão do cliente durante o upload:** +A sessão permanece no Cassandra, com as partes recebidas registradas. +O cliente pode chamar `get-upload-status` para ver o que está faltando. +A retomada é feita carregando apenas as partes ausentes e, em seguida, `complete-upload`. +>>>>>>> 82edf2d (New md files from RunPod) + +**Falha no upload completo:** +O `CompleteMultipartUpload` do S3 é atômico - ou tem sucesso total ou falha. +Em caso de falha, as partes permanecem e o cliente pode tentar novamente `complete-upload`. +Nenhum documento parcial é visível. + +**Expiração da sessão:** +O TTL do Cassandra exclui o registro da sessão após 24 horas. +A política de ciclo de vida do bucket S3 limpa uploads multipartes incompletos. +Não é necessário nenhum processo de limpeza manual. + +### Atomicidade Multipart do S3 + +Os uploads multipart do S3 fornecem atomicidade integrada: + +1. **As partes são invisíveis:** As partes carregadas não podem ser acessadas como objetos. + Elas existem apenas como partes de um upload multipart incompleto. + +2. **Conclusão atômica:** `CompleteMultipartUpload` ou tem sucesso (o objeto + aparece atomicamente) ou falha (nenhum objeto é criado). Nenhum estado parcial. + +<<<<<<< HEAD +3. **Não é necessário renomear:** A chave do objeto final é especificada em + `CreateMultipartUpload`. As partes são combinadas diretamente para essa chave. + +4. **Coalescência no lado do servidor:** O S3 combina as partes internamente. O bibliotecário +======= +3. **Não é necessário renomear:** A chave do objeto final é especificada no + momento de `CreateMultipartUpload`. As partes são combinadas diretamente para essa chave. + +4. **Combinação no lado do servidor:** O S3 combina as partes internamente. O bibliotecário +>>>>>>> 82edf2d (New md files from RunPod) + nunca lê as partes de volta - nenhuma sobrecarga de memória, independentemente do tamanho do documento. + +### Extensões BlobStore + +**Arquivo:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +<<<<<<< HEAD +Adicionar métodos de upload multipart: +======= +Adicione métodos de upload multipart: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### Considerações sobre o Tamanho do Chunk + +**Mínimo do S3**: 5MB por parte (exceto a última parte) +**Máximo do S3**: 10.000 partes por upload +**Valor padrão prático**: chunks de 5MB + Documento de 500MB = 100 chunks + Documento de 5GB = 1.000 chunks +**Granularidade do progresso**: Chunks menores = atualizações de progresso mais detalhadas +**Eficiência da rede**: Chunks maiores = menos viagens de ida e volta + +O tamanho do chunk pode ser configurável pelo cliente dentro de limites (5MB - 100MB). + +### Processamento de Documentos: Recuperação em Streaming + +O fluxo de upload visa colocar documentos no armazenamento de forma eficiente. O fluxo de processamento visa extrair e dividir documentos sem carregá-los inteiramente na memória. + +#### Princípio de Design: Identificador, Não Conteúdo + + +Atualmente, quando o processamento é acionado, o conteúdo do documento flui através de mensagens Pulsar. Isso carrega documentos inteiros na memória. Em vez disso: + +As mensagens Pulsar carregam apenas o **identificador do documento** +Os processadores buscam o conteúdo do documento diretamente do "librarian" +A busca ocorre como um **stream para um arquivo temporário** +A análise específica do documento (PDF, texto, etc.) funciona com arquivos, não com buffers de memória + +Isso mantém o "librarian" independente da estrutura do documento. A análise de PDF, a extração de texto e outras lógicas específicas do formato permanecem nos decodificadores respectivos. + +#### Fluxo de Processamento + + +#### Fluxo de Processamento + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### API de fluxo do Bibliotecário + +Adicionar uma operação de recuperação de documentos em fluxo: + +**`stream-document`** + +Requisição: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +Resposta: Blocos binários transmitidos (não uma única resposta). + +Para a API REST, isso retorna uma resposta transmitida com `Transfer-Encoding: chunked`. + +Para chamadas internas de serviço a serviço (do processador para o bibliotecário), isso pode ser: +Transmissão direta do S3 via URL pré-assinada (se a rede interna permitir) +Respostas em blocos sobre o protocolo do serviço +Um endpoint de transmissão dedicado + +O requisito principal: os dados fluem em blocos, nunca totalmente armazenados em buffer no bibliotecário. + +#### Alterações no Decodificador PDF + +**Implementação atual** (que consome muita memória): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**Nova implementação** (arquivo temporário, incremental): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +Perfil de memória: +Arquivo temporário no disco: tamanho do PDF (o disco é barato) +Na memória: uma página de texto por vez +Memória máxima: limitada, independente do tamanho do documento + +#### Alterações no decodificador de documentos de texto + +Para documentos de texto simples, ainda mais simples - nenhum arquivo temporário necessário: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +Documentos de texto podem ser transmitidos diretamente sem um arquivo temporário, pois são +estruturados linearmente. + +#### Integração com o Chunker (Fragmentador) + +O fragmentador recebe um iterador de texto (páginas ou parágrafos) e produz +fragmentos incrementalmente: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### Pipeline de Processamento de Ponta a Ponta + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +Em nenhum momento, o documento completo ou o texto extraído completo são mantidos na memória. + +#### Considerações sobre Arquivos Temporários + +**Localização**: Utilize o diretório temporário do sistema (`/tmp` ou equivalente). Para +<<<<<<< HEAD +implantações em contêineres, certifique-se de que o diretório temporário tenha espaço suficiente +e esteja em armazenamento rápido (não montado em rede, se possível). +======= +implantações em contêineres, certifique-se de que o diretório temporário tenha espaço +suficiente e esteja em armazenamento rápido (não montado em rede, se possível). +>>>>>>> 82edf2d (New md files from RunPod) + +**Limpeza**: Utilize gerenciadores de contexto (`with tempfile...`) para garantir a limpeza +mesmo em caso de exceções. + +**Processamento concorrente**: Cada tarefa de processamento recebe seu próprio arquivo temporário. +Não há conflitos entre o processamento paralelo de documentos. + +**Espaço em disco**: Os arquivos temporários são de curta duração (duração do processamento). Para +um arquivo PDF de 500 MB, são necessários 500 MB de espaço temporário durante o processamento. O limite de tamanho pode +<<<<<<< HEAD +ser imposto no momento do upload, caso o espaço em disco seja limitado. +======= +ser imposto no momento do upload, se o espaço em disco for limitado. +>>>>>>> 82edf2d (New md files from RunPod) + +### Interface de Processamento Unificada: Documentos Filhos + +A extração de PDF e o processamento de documentos de texto precisam ser integrados ao mesmo +<<<<<<< HEAD +pipeline downstream (divisão em partes → incorporações → armazenamento). Para alcançar isso com uma interface consistente de "busca por ID", os blocos de texto extraídos são armazenados de volta +no sistema de gerenciamento de documentos como documentos filhos. + +#### Fluxo de Processamento com Documentos Filhos + +Saída do contrato (deve seguir exatamente o formato abaixo). +======= +pipeline downstream (divisão em partes → incorporações → armazenamento). Para alcançar isso com uma interface +"busca por ID" consistente, os blocos de texto extraídos são armazenados de volta no sistema de gerenciamento +como documentos filhos. + +#### Fluxo de Processamento com Documentos Filhos + +>>>>>>> 82edf2d (New md files from RunPod) +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +O componente de divisão em partes (chunker) possui uma interface uniforme: +Recebe um ID de documento (via Pulsar) +<<<<<<< HEAD +Transmite o conteúdo do "bibliotecário" +Divide em partes + +Ele não sabe nem se importa se o ID se refere a: +Um documento de texto carregado por um usuário +Um trecho de texto extraído de uma página PDF +======= +Obtém o conteúdo do "bibliotecário" (librarian) +Divide o conteúdo em partes (chunks) + +Ele não sabe nem se importa se o ID se refere a: +Um documento de texto carregado por um usuário +Um bloco de texto extraído de uma página PDF +>>>>>>> 82edf2d (New md files from RunPod) +Qualquer tipo de documento futuro + +#### Metadados do Documento Filho + +Estenda o esquema do documento para rastrear relacionamentos pai/filho: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**Tipos de documentos:** + +| `document_type` | Descrição | +|-----------------|-------------| +| `source` | Documento carregado pelo usuário (PDF, texto, etc.) | +| `extracted` | Derivado de um documento de origem (por exemplo, texto da página de um PDF) | + +**Campos de metadados:** + +| Campo | Documento de Origem | Filho Extraído | +|-------|-----------------|-----------------| +| `id` | fornecido pelo usuário ou gerado | gerado (por exemplo, `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | ID do documento pai | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, etc. | `text/plain` | +| `title` | fornecido pelo usuário | gerado (por exemplo, "Página 3 do Relatório.pdf") | +| `user` | usuário autenticado | o mesmo que o pai | + +#### API do Bibliotecário para Documentos Filhos + +**Criando documentos filhos** (interno, usado por pdf-extractor): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +<<<<<<< HEAD +Para pequenas extrações de texto (o texto de uma página típica é menor que 100 KB), o upload em uma única operação é aceitável. Para extrações de texto muito grandes, um upload em partes pode ser usado. +======= +Para pequenas quantidades de texto extraído (o texto de uma página típica é menor que 100 KB), o upload em uma única operação é aceitável. Para extrações de texto muito grandes, um upload em partes pode ser usado. +>>>>>>> 82edf2d (New md files from RunPod) + +**Listando documentos filhos** (para depuração/administração): + +**Listagem de documentos filhos** (para depuração/administração): + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +Resposta: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### Comportamento visível ao usuário + +**`list-documents` comportamento padrão:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +Apenas os documentos de nível superior (originais) aparecem na lista de documentos do usuário. +Os documentos filhos são filtrados por padrão. + +**Flag opcional "incluir_filhos"** (para administração/depuração): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +<<<<<<< HEAD +#### Exclusão em Cadeia +======= +#### Exclusão em Cascata +>>>>>>> 82edf2d (New md files from RunPod) + +Quando um documento pai é excluído, todos os filhos devem ser excluídos: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### Considerações sobre Armazenamento + +Blocos de texto extraídos duplicam conteúdo: +O PDF original é armazenado no "Garage" (espaço de armazenamento). +O texto extraído por página também é armazenado no "Garage". + +Este compromisso permite: +**Interface de "chunker" uniforme**: O "chunker" sempre busca por ID. +<<<<<<< HEAD +**Retomada/repetição**: É possível reiniciar no estágio do "chunker" sem reextrair o PDF. +======= +**Retomada/repetição**: É possível reiniciar no estágio do "chunker" sem extrair novamente o PDF. +>>>>>>> 82edf2d (New md files from RunPod) +**Depuração**: O texto extraído pode ser inspecionado. +**Separação de responsabilidades**: O extrator de PDF e o "chunker" são serviços independentes. + +Para um PDF de 500MB com 200 páginas, com uma média de 5KB de texto por página: +Armazenamento do PDF: 500MB +Armazenamento do texto extraído: ~1MB no total +Sobrecarga: insignificante + +#### Saída do Extrator de PDF + +O extrator de PDF, após processar um documento: + +1. Transfere o PDF do "librarian" para um arquivo temporário. +2. Extrai o texto página por página. +3. Para cada página, armazena o texto extraído como um documento filho através do "librarian". +4. Envia os IDs dos documentos filhos para a fila do "chunker". +<<<<<<< HEAD +Após a última linha traduzida, fornecer uma linha final contendo exatamente: [[__END_OF_TRANSLATION__]] +======= +Após a última linha traduzida, gerar uma linha final contendo exatamente: [[__END_OF_TRANSLATION__]] +>>>>>>> 82edf2d (New md files from RunPod) +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +O componente de divisão recebe esses IDs de elementos filhos e os processa da mesma forma que processaria um documento de texto carregado por um usuário. + +### Atualizações do Cliente + +#### SDK Python + + +O SDK Python (`trustgraph-base/trustgraph/api/library.py`) deve lidar com uploads divididos de forma transparente. A interface pública permanece inalterada: + + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +Internamente, o SDK detecta o tamanho do documento e alterna a estratégia: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**Callbacks de progresso** (melhoria opcional): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +Isso permite que as interfaces de usuário exibam o progresso do upload sem alterar a API básica. + +#### Ferramentas de Linha de Comando (CLI) + +**`tg-add-library-document`** continua a funcionar inalterado: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +<<<<<<< HEAD +Uma exibição de progresso opcional pode ser adicionada: +======= +Uma exibição de progresso opcional poderia ser adicionada: +>>>>>>> 82edf2d (New md files from RunPod) + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**Ferramentas legadas removidas:** + +`tg-load-pdf` - descontinuado, use `tg-add-library-document` +`tg-load-text` - descontinuado, use `tg-add-library-document` + +**Comandos de administração/depuração** (opcional, baixa prioridade): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +Estes poderiam ser flags no comando existente, em vez de ferramentas separadas. + +#### Atualizações da Especificação da API + +A especificação OpenAPI (`specs/api/paths/librarian.yaml`) precisa de atualizações para: + +**Novas operações:** + +`begin-upload` - Inicializar sessão de upload em partes +`upload-chunk` - Enviar parte individual +`complete-upload` - Finalizar upload +`abort-upload` - Cancelar upload +`get-upload-status` - Consultar o progresso do upload +`list-uploads` - Listar uploads incompletos para o usuário +`stream-document` - Recuperação de documentos em streaming +`add-child-document` - Armazenar texto extraído (interno) +`list-children` - Listar documentos filhos (administrador) + +**Operações modificadas:** + +`list-documents` - Adicionar parâmetro `include-children` + +**Novos esquemas:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**Atualizações da especificação WebSocket** (`specs/websocket/`): + +Espelhe as operações REST para clientes WebSocket, permitindo atualizações de progresso em tempo real +durante o upload. + +#### Considerações de UX + +As atualizações da especificação da API permitem melhorias na interface do usuário: + +**Interface do usuário de progresso do upload:** +Barra de progresso mostrando as partes enviadas +Tempo estimado restante +Capacidade de pausar/retomar + +**Recuperação de erros:** +<<<<<<< HEAD +Opção "retomar upload" para uploads interrompidos +======= +Opção "Retomar upload" para uploads interrompidos +>>>>>>> 82edf2d (New md files from RunPod) +Lista de uploads pendentes na reconexão + +**Tratamento de arquivos grandes:** +Detecção do tamanho do arquivo no lado do cliente +Upload automático em partes para arquivos grandes +Feedback claro durante uploads longos + +Essas melhorias de UX exigem trabalho na interface do usuário, guiado pela especificação da API atualizada. diff --git a/docs/tech-specs/large-document-loading.ru.md b/docs/tech-specs/large-document-loading.ru.md new file mode 100644 index 00000000..3a59c39e --- /dev/null +++ b/docs/tech-specs/large-document-loading.ru.md @@ -0,0 +1,992 @@ +--- +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. **Обработка больших PDF-файлов**: Загрузка и обработка PDF-файлов объемом в сотни мегабайт + без переполнения памяти +2. **Возобновляемая загрузка**: Возможность продолжить прерванную загрузку с того места, + где она была остановлена, а не перезапускать ее. +3. **Информативность о ходе выполнения**: Предоставление пользователям информации в режиме реального времени + о ходе загрузки и обработки. +4. **Эффективная обработка памяти**: Обработка документов потоковым способом + без хранения целых файлов в памяти. + +## Цели + +**Инкрементная загрузка**: Поддержка загрузки документов по частям через REST и WebSocket +**Возобновляемые передачи**: Возможность восстановления после прерванных загрузок +**Информативность о ходе выполнения**: Предоставление клиентам информации о ходе загрузки/обработки +**Эффективность использования памяти**: Исключение полной буферизации документов на протяжении всего процесса +**Обратная совместимость**: Существующие процессы загрузки небольших документов продолжают работать без изменений +**Потоковая обработка**: Декодирование PDF и разбиение текста на фрагменты выполняются в потоковом режиме + +## Описание + +### Текущая архитектура + +Процесс отправки документов проходит по следующему пути: + +1. **Клиент** отправляет документ через REST (`POST /api/v1/librarian`) или WebSocket +2. **API Gateway** получает полный запрос с содержимым документа в кодировке base64 +3. **LibrarianRequestor** преобразует запрос в сообщение Pulsar +4. **Librarian Service** получает сообщение, декодирует документ в память +5. **BlobStore** загружает документ в Garage/S3 +6. **Cassandra** хранит метаданные со ссылкой на объект +7. Для обработки: документ извлекается из S3, декодируется, разбивается на фрагменты — все в памяти + +Основные файлы: +Точка входа REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +Основной модуль Librarian: `trustgraph-flow/trustgraph/librarian/librarian.py` +Хранилище объектов: `trustgraph-flow/trustgraph/librarian/blob_store.py` +Таблицы Cassandra: `trustgraph-flow/trustgraph/tables/library.py` +Схема API: `trustgraph-base/trustgraph/schema/services/library.py` + +### Текущие ограничения + +Текущая конструкция имеет несколько взаимосвязанных проблем, связанных с памятью и удобством использования: + +1. **Атомарная операция загрузки**: Весь документ должен быть передан в одном запросе. + Загрузка больших документов требует длительных запросов без индикации хода выполнения + и без механизма повторной отправки в случае сбоя соединения. + +2. **Дизайн API**: И REST, и WebSocket API ожидают получения всего документа + в одном сообщении. Схема (`LibrarianRequest`) имеет одно поле `content` + для хранения всего документа в кодировке base64. + +3. **Память Librarian**: Сервис Librarian декодирует весь документ + в память перед загрузкой в S3. Для PDF-файла объемом 500 МБ это означает + выделение 500 МБ + в оперативной памяти. + +4. **Память декодера PDF**: При начале обработки декодер PDF-файла загружает + весь PDF-файл в память для извлечения текста. Такие библиотеки, как PyPDF, + обычно требуют полного доступа к документу. + +5. **Память разбивающего на фрагменты**: Разбивающий на фрагменты получает весь извлеченный текст + и хранит его в памяти при создании фрагментов. + +**Пример влияния на память** (PDF-файл объемом 500 МБ): +Gateway: ~700 МБ (дополнительный объем для кодирования base64) +Librarian: ~500 МБ (декодированные байты) +Декодер PDF: ~500 МБ + буферы извлечения +Разбивающий на фрагменты: извлеченный текст (переменная, потенциально 100 МБ+) + +Общий пиковый объем используемой памяти может превысить 2 ГБ для одного большого документа. + +## Технический дизайн + +### Принципы проектирования + +1. **API Facade**: Все взаимодействия с клиентом осуществляются через API Librarian. Клиенты + не имеют прямого доступа к хранилищу S3/Garage и не знают о его существовании. + +2. **Многокомпонентная загрузка в S3**: Используется стандартная многокомпонентная загрузка в S3. + Это широко поддерживается в системах, совместимых с S3 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2 и т. д.), что обеспечивает переносимость. + +3. **Атомарное завершение**: Многокомпонентные загрузки в S3 по своей природе являются атомарными — загруженные + фрагменты невидимы до вызова `CompleteMultipartUpload`. Не требуются временные + файлы или операции переименования. + +4. **Отслеживаемое состояние**: Сессии загрузки отслеживаются в Cassandra, что обеспечивает + информацию о незавершенных загрузках и позволяет восстановить загрузку. + +### Поток загрузки по частям + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +Клиент никогда не взаимодействует с S3 напрямую. Библиотека преобразует +наши API загрузки по частям в многокомпонентные операции S3 внутри себя. + +### Операции API библиотеки + +#### `begin-upload` + +Инициализация сессии загрузки по частям. + +Запрос: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +Ответ: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +Библиотекарь: +1. Генерирует уникальный `upload_id` и `object_id` (UUID для хранения объектов) +2. Вызывает `CreateMultipartUpload` S3, получает `s3_upload_id` +3. Создает запись сессии в Cassandra +4. Возвращает `upload_id` клиенту + +#### `upload-chunk` + +Загрузка одного фрагмента. + +Запрос: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +Ответ: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +Библиотекарь: +1. Ищет сессию по `upload_id` +2. Проверяет право собственности (пользователь должен совпадать с создателем сессии) +3. Вызывает S3 `UploadPart` с данными фрагмента, получает `etag` +4. Обновляет запись сессии с индексом фрагмента и etag +5. Возвращает прогресс клиенту + +Неудачные фрагменты можно повторить - просто отправьте тот же `chunk-index` снова. + +#### `complete-upload` + +Завершите загрузку и создайте документ. + +Запрос: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +Ответ: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +Библиотекарь: +1. Ищет сессию, проверяет, все ли фрагменты получены. +2. Вызывает S3 `CompleteMultipartUpload` с информацией о частях (S3 объединяет части + внутри себя - нулевая стоимость по памяти для библиотекаря). +3. Создает запись документа в Cassandra с метаданными и ссылкой на объект. +4. Удаляет запись сессии загрузки. +5. Возвращает идентификатор документа клиенту. + +#### `abort-upload` + +Отмена загрузки, находящейся в процессе. + +Запрос: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +Библиотекарь: +1. Вызывает S3 `AbortMultipartUpload` для очистки разделов. +2. Удаляет запись сессии из Cassandra. + +#### `get-upload-status` + +Проверка статуса загрузки (для возможности возобновления). + +Запрос: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +Ответ: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +Список неполных загрузок для пользователя. + +Запрос: +```json +{ + "operation": "list-uploads" +} +``` + +Ответ: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### Загрузка данных сессии + +Отслеживание текущих загрузок в Cassandra: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**Поведение TTL:** +Сессии истекают через 24 часа, если не завершены. +Когда TTL Cassandra истекает, запись сессии удаляется. +Оставшиеся фрагменты S3 очищаются политикой жизненного цикла S3 (настраивается на бакете). + +### Обработка ошибок и атомарность + +**Ошибка загрузки фрагмента:** +Клиент повторяет загрузку неудачного фрагмента (с теми же `upload_id` и `chunk-index`). +Операция `UploadPart` S3 является идемпотентной для одного и того же номера фрагмента. +Сессия отслеживает, какие фрагменты были успешно загружены. + +**Разрыв соединения клиента во время загрузки:** +Сессия остается в Cassandra с записью о полученных фрагментах. +Клиент может вызвать `get-upload-status`, чтобы узнать, что отсутствует. +Возобновление путем загрузки только отсутствующих фрагментов, затем `complete-upload`. + +**Ошибка полной загрузки:** +Операция `CompleteMultipartUpload` S3 является атомарной - либо успешно завершается полностью, либо не удается. +В случае сбоя фрагменты остаются, и клиент может повторить `complete-upload`. +Ни один частичный документ никогда не отображается. + +**Истечение срока действия сессии:** +TTL Cassandra удаляет запись сессии через 24 часа. +Политика жизненного цикла бакета S3 очищает неполные многокомпонентные загрузки. +Не требуется ручная очистка. + +### Атомарность многокомпонентной загрузки S3 + +Многокомпонентные загрузки S3 обеспечивают встроенную атомарность: + +1. **Фрагменты невидимы**: Загруженные фрагменты не могут быть доступны в качестве объектов. + Они существуют только как части незавершенной многокомпонентной загрузки. + +2. **Атомарное завершение**: `CompleteMultipartUpload` либо успешно завершается (объект + появляется атомарно), либо не удается (объект не создается). Отсутствует частичное состояние. + +3. **Не требуется переименование**: Конечный ключ объекта указывается во время + `CreateMultipartUpload`. Фрагменты объединяются непосредственно в этот ключ. + +4. **Объединение на стороне сервера**: S3 объединяет фрагменты внутренне. Библиотекарь + никогда не считывает фрагменты обратно - нулевые накладные расходы памяти независимо от размера документа. + +### Расширения BlobStore + +**Файл:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +Добавлены методы многокомпонентной загрузки: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### Особенности размера фрагментов + +**Минимальный размер для S3**: 5 МБ на часть (кроме последней части) +**Максимальный размер для S3**: 10 000 частей на загрузку +**Рекомендуемый размер по умолчанию**: фрагменты по 5 МБ + Документ объемом 500 МБ = 100 фрагментов + Документ объемом 5 ГБ = 1000 фрагментов +**Гранулярность прогресса**: Меньшие фрагменты = более точные обновления прогресса +**Эффективность сети**: Большие фрагменты = меньше сетевых запросов + +Размер фрагмента может быть настроен клиентом в пределах заданных ограничений (от 5 МБ до 100 МБ). + +### Обработка документов: Потоковая загрузка + +Процесс загрузки предназначен для эффективной передачи документов в хранилище. Процесс обработки предназначен для извлечения и разделения документов на фрагменты без полной загрузки +их в память. + + +#### Основной принцип: Идентификатор, а не содержимое + +В настоящее время, при запуске обработки, содержимое документа передается через сообщения Pulsar. Это приводит к полной загрузке документов в память. Вместо этого: + + +Сообщения Pulsar содержат только **идентификатор документа** +Обработчики получают содержимое документа непосредственно из хранилища. +Получение происходит в виде **потока во временный файл** +Разбор документов, специфичный для каждого формата (PDF, текст и т.д.), работает с файлами, а не с буферами памяти. + +Это позволяет хранилищу быть независимым от структуры документа. Разбор PDF, извлечение текста и другая логика, специфичная для формата, остается в соответствующих декодерах. + + +#### Процесс обработки + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### API потоковой передачи данных для библиотекаря + +Добавить операцию получения документов в режиме потоковой передачи: + +**`stream-document`** + +Запрос: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +Ответ: Потоковые двоичные фрагменты (не единый ответ). + +Для REST API это возвращает потоковый ответ с `Transfer-Encoding: chunked`. + +Для внутренних вызовов между сервисами (от процессора к библиотеке), это может быть: +Прямая потоковая передача данных через S3 с использованием предварительно подписанного URL (если внутренняя сеть это позволяет). +Фрагментированные ответы через протокол сервиса. +Специальный конечный пункт для потоковой передачи данных. + +Основное требование: данные передаются фрагментами, никогда полностью не буферизуются в библиотеке. + +#### Изменения декодера PDF + +**Текущая реализация** (требует много памяти): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**Новая реализация** (временный файл, постепенная): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +Профиль использования памяти: +Временный файл на диске: размер PDF (диск дешевый). +В памяти: текст одной страницы за раз. +Максимальный объем памяти: ограничен, не зависит от размера документа. + +#### Изменения в декодере текстовых документов + +Для обычных текстовых документов еще проще - временный файл не нужен: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +Текстовые документы могут передаваться напрямую без временного файла, поскольку они имеют +линейную структуру. + +#### Интеграция с модулем разбиения на части (Chunker) + +Модуль разбиения на части (chunker) получает итератор текстовых данных (страниц или абзацев) и +создает фрагменты постепенно: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### Конвейер сквозной обработки + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +В любой момент времени полный документ или полностью извлеченный текст не хранятся в памяти. + +#### Особенности использования временных файлов + +**Расположение**: Используйте системную временную директорию (`/tmp` или эквивалент). Для +контейнеризированных развертываний убедитесь, что временная директория имеет достаточно места +и находится на быстром носителе (желательно не на сетевом диске). + +**Очистка**: Используйте контекстные менеджеры (`with tempfile...`) для обеспечения очистки +даже в случае возникновения исключений. + +**Параллельная обработка**: Каждый процесс обработки получает свой временный файл. +Отсутствуют конфликты между параллельной обработкой документов. + +**Место на диске**: Временные файлы существуют недолго (продолжительность обработки). Для +PDF-файла объемом 500 МБ требуется 500 МБ временного пространства во время обработки. Ограничение размера может +быть применено во время загрузки, если место на диске ограничено. + +### Унифицированный интерфейс обработки: Дочерние документы + +Извлечение текста из PDF-файлов и обработка текстовых документов должны быть интегрированы в одну +общую цепочку обработки (разделение на фрагменты → создание векторных представлений → хранение). Для достижения этого с +использованием единого интерфейса "получение по ID", извлеченные текстовые фрагменты сохраняются обратно +в систему как дочерние документы. + +#### Поток обработки с использованием дочерних документов + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +Модуль разбиения на фрагменты имеет один унифицированный интерфейс: +Получение идентификатора документа (через Pulsar) +Получение содержимого от хранилища данных +Разбиение на фрагменты + +Он не знает и не заботится о том, относится ли идентификатор к: +Текстовому документу, загруженному пользователем +Извлеченному текстовому фрагменту из страницы PDF +Любому будущему типу документов + +#### Метаданные дочернего документа + +Расширьте схему документа для отслеживания отношений родитель/дочерний элемент: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**Типы документов:** + +| `document_type` | Описание | +|-----------------|-------------| +| `source` | Документ, загруженный пользователем (PDF, текст и т.д.) | +| `extracted` | Полученный из исходного документа (например, текст страницы PDF) | + +**Поля метаданных:** + +| Поле | Исходный документ | Извлеченный дочерний элемент | +|-------|-----------------|-----------------| +| `id` | Предоставлено пользователем или сгенерировано | сгенерировано (например, `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | Идентификатор родительского документа | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf` и т.д. | `text/plain` | +| `title` | Предоставлено пользователем | сгенерировано (например, "Страница 3 отчета Report.pdf") | +| `user` | Аутентифицированный пользователь | то же, что и у родительского элемента | + +#### API для дочерних документов + +**Создание дочерних документов** (внутреннее, используется pdf-extractor): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +Для небольших извлеченных фрагментов текста (обычный текст страницы обычно менее 100 КБ) однокрасная загрузка является приемлемой. Для очень больших извлечений текста можно использовать загрузку по частям. + +**Список дочерних документов** (для отладки/администрирования): + +**Отображение дочерних документов** (для отладки/администрирования): + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +Ответ: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### Поведение, видимое пользователю + +**`list-documents` поведение по умолчанию:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +Только документы верхнего уровня отображаются в списке документов пользователя. +Дочерние документы по умолчанию отфильтровываются. + +**Необязательный флаг `include-children`** (для администраторов/отладки): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### Каскадное удаление + +При удалении родительского документа все дочерние элементы должны быть удалены: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### Соображения по поводу хранения + +Извлеченные текстовые фрагменты дублируют контент: +Оригинальный PDF-файл хранится в хранилище "Garage". +Извлеченный текст для каждой страницы также хранится в хранилище "Garage". + +Этот компромисс позволяет: +**Единый интерфейс для разбиения на фрагменты**: Разбиватель всегда получает данные по идентификатору. +**Возобновление/повтор**: Можно перезапустить на этапе разбиения на фрагменты без повторной извлечения PDF-файла. +**Отладка**: Извлеченный текст можно просмотреть. +**Разделение ответственности**: Сервисы извлечения PDF и разбиения на фрагменты являются независимыми. + +Для PDF-файла объемом 500 МБ с 200 страницами, в среднем 5 КБ текста на страницу: +Хранение PDF: 500 МБ. +Хранение извлеченного текста: около 1 МБ в общей сложности. +Дополнительные затраты: незначительные. + +#### Вывод извлечения текста из PDF-файла + +Сервис извлечения текста из PDF-файла, после обработки документа: + +1. Получает PDF-файл из хранилища "librarian" во временный файл. +2. Извлекает текст страницу за страницей. +3. Для каждой страницы сохраняет извлеченный текст как дочерний документ через хранилище "librarian". +4. Отправляет идентификаторы дочерних документов в очередь разбивателя на фрагменты. +Выходной документ. +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +Модуль, отвечающий за разделение на части, получает эти идентификаторы дочерних элементов и обрабатывает их так же, как он бы обрабатывал текстовый документ, загруженный пользователем. + +### Обновления для клиентов + +#### Python SDK + + +Python SDK (`trustgraph-base/trustgraph/api/library.py`) должен обрабатывать +загрузку данных, разделенных на части, прозрачно. Публичный интерфейс остается неизменным: + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +Внутри, SDK определяет размер документа и переключает стратегию: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**Функции обратного вызова для отслеживания прогресса** (необязательное улучшение): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +Это позволяет пользовательским интерфейсам отображать ход загрузки без изменения основного API. + +#### Инструменты командной строки + +**`tg-add-library-document`** продолжает работать без изменений: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +Возможно, можно добавить опциональное отображение прогресса: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**Устаревшие инструменты удалены:** + +`tg-load-pdf` - устарело, используйте `tg-add-library-document` +`tg-load-text` - устарело, используйте `tg-add-library-document` + +**Команды администратора/отладки** (опционально, низкий приоритет): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +Это могут быть флаги для существующей команды, а не отдельные инструменты. + +#### Обновления спецификации API + +Спецификация OpenAPI (`specs/api/paths/librarian.yaml`) требует обновлений для: + +**Новые операции:** + +`begin-upload` - Инициализация сессии загрузки по частям +`upload-chunk` - Загрузка отдельного фрагмента +`complete-upload` - Завершение загрузки +`abort-upload` - Отмена загрузки +`get-upload-status` - Запрос хода загрузки +`list-uploads` - Список незавершенных загрузок для пользователя +`stream-document` - Получение документа в режиме потоковой передачи +`add-child-document` - Сохранение извлеченного текста (внутреннее использование) +`list-children` - Список дочерних документов (для администраторов) + +**Измененные операции:** + +`list-documents` - Добавлен параметр `include-children` + +**Новые схемы:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**Обновления спецификации WebSocket** (`specs/websocket/`): + +Отразите операции REST для клиентов WebSocket, обеспечивая обновления хода загрузки в режиме реального времени. + + +#### Соображения пользовательского интерфейса + +Обновления спецификации API позволяют улучшить пользовательский интерфейс: + +**Интерфейс отображения хода загрузки:** +Индикатор прогресса, показывающий загруженные фрагменты +Оценка оставшегося времени +Возможность приостановки/возобновления + +**Восстановление после ошибок:** +Опция "Возобновить загрузку" для прерванных загрузок +Список ожидающих загрузок при повторном подключении + +**Обработка больших файлов:** +Обнаружение размера файла на стороне клиента +Автоматическая загрузка по частям для больших файлов +Четкая обратная связь во время длительных загрузок + +Эти улучшения пользовательского интерфейса требуют работы на стороне клиентской части, основанной на обновленной спецификации API. diff --git a/docs/tech-specs/large-document-loading.sw.md b/docs/tech-specs/large-document-loading.sw.md new file mode 100644 index 00000000..fccf24a3 --- /dev/null +++ b/docs/tech-specs/large-document-loading.sw.md @@ -0,0 +1,1311 @@ +--- +layout: default +title: "Vipimo vya Utekelezaji wa Teknolojia ya Kupakia Hati Kubwa" +parent: "Swahili (Beta)" +--- + +<<<<<<< HEAD +# Vipimo vya Utekelezaji wa Teknolojia ya Kupakia Hati Kubwa + +> **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 yanaeleza masuala ya uwezo wa kufanya kazi na uzoefu wa mtumiaji wakati wa kupakia +hati kubwa katika TrustGraph. Muundo wa sasa hutumia kupakia hati kama operesheni moja, na kusababisha +shinikizo la kumbukumbu katika hatua nyingi za mchakato na kutoa maelezo au chaguo za kurejesha kwa watumiaji. + + +Utaratibu huu unalenga matumizi yafuatayo: + +1. **Uchakataji wa Hati za PDF Kubwa**: Kupakia na kuchakata faili za PDF zenye mamia ya megabytes + bila kutumia kumbukumbu yote. +2. **Kupakia Ambayo Inaweza Kuendelea**: Kuruhusu kupakia ambacho kimetokea kukatika kuendelea kutoka + ambapo kilisimama badala ya kuanza tena. +3. **Maelezo ya Maendeleo**: Kutoa kwa watumiaji maelezo ya muda halisi kuhusu maendeleo ya + kupakia na uchakataji. +4. **Uchakataji Wenye Ufanisi wa Kumbukumbu**: Kuchakata hati kwa njia ya mtiririko +======= +# Vipimo vya Utekelezaji wa Uteuzi wa Hati Kubwa + +## Muhtasari + +Maelekezo haya yanaeleza masuala ya uwezo wa kutosha na uzoefu wa mtumiaji wakati wa kupakia +hati kubwa katika TrustGraph. Muundo wa sasa hutibu kupakia hati kama operesheni moja na kamili, +na kusababisha shinikizo la kumbukumbu katika sehemu nyingi za +mchakato na kutoa hakikisho au chaguo za urejesho kwa watumiaji. + +Utendaji huu unalenga matumizi yafuatayo: + +1. **Uchakataji wa PDF Kubwa**: Pakia na uchakata faili za PDF zenye mamia ya megabytes + bila kutumia kumbukumbu. +2. **Uipakaji Unaoweza Kuendelea**: Ruhusu uipakaji ambao umevunjika kuendelea kutoka + ambapo ulikuwa umeacha badala ya kuanza tena. +3. **Hakikisho la Maendeleo**: Toa watumiaji maoni ya wakati halisi kuhusu + maendeleo ya uipakaji na uchakataji. +4. **Uchakataji Wenye Ufanisi wa Kumbukumbu**: Chakata hati kwa njia ya mtiririko +>>>>>>> 82edf2d (New md files from RunPod) + bila kuhifadhi faili zilizokamilika katika kumbukumbu. + +## Lengo + +<<<<<<< HEAD +**Kupakia kwa Awamu**: Kusaidia kupakia hati kwa sehemu kupitia REST na WebSocket +**Uhamisho Unaoweza Kuendelea**: Kuruhusu kurejesha kutoka kupakia ambacho kimetokea kukatika +**Uonekana wa Maendeleo**: Kutoa maelezo ya maendeleo ya kupakia/uchakataji kwa wateja +**Ufanisi wa Kumbukumbu**: Kuondoa uhifadhi wa hati zilizokamilika katika mchakato wote +**Ulinganifu na Mifumo ya Zamani**: Mchakato wa sasa wa hati ndogo unaendelea bila mabadiliko +**Uchakataji wa Mtiririko**: Ufichuzi na uainishaji wa maandishi hufanywa kwa kutumia mitiririko +======= +**Uipakaji wa Hatua-Hatua**: Unga uipakaji wa hati kwa sehemu kupitia REST na WebSocket +**Uhamisho Unaoweza Kuendelea**: Ruhusu urejesho kutoka uipakaji ambao umevunjika +**Uonekana wa Maendeleo**: Toa watumiaji maoni ya maendeleo ya uipakaji/uchakataji +**Ufanisi wa Kumbukumbu**: Ondoa kuhifadhi hati zilizokamilika katika mchakato +**Ulinganifu na Mifumo ya Zamani**: Mchakato wa sasa wa hati ndogo unaendelea bila mabadiliko +**Uchakataji wa Mtiririko**: Uvunjaji wa PDF na maandishi hufanya kazi kwenye mitiririko +>>>>>>> 82edf2d (New md files from RunPod) + +## Asili + +### Muundo wa Sasa + +<<<<<<< HEAD +Hati zinatumiwa kupitia njia ifuatayo: + +1. **Mteja** hutuma hati kupitia REST (`POST /api/v1/librarian`) au WebSocket +2. **Lango la API** linapokea ombi kamili lenye maudhui ya hati yaliyokuzwa kwa msingi 64 +3. **LibrarianRequestor** huongeza ombi kwenye ujumbe wa Pulsar +4. **Huduma ya Librarian** inapokea ujumbe, huondoa maudhui ya hati katika kumbukumbu +5. **BlobStore** huhamisha hati kwenye Garage/S3 +6. **Cassandra** huhifadhi metadata pamoja na rejea ya kitu +7. Kwa uchakataji: hati inavyolewa kutoka S3, huondoa maudhui, huainishwa—yote katika kumbukumbu +======= +Mchakato wa kuwasilisha hati hufuatilia njia ifuatayo: + +1. **Mteja** huwasilisha hati kupitia REST (`POST /api/v1/librarian`) au WebSocket +2. **Lango la API** hupokea ombi kamili na maudhui ya hati iliyosimbwa kwa base64 +3. **LibrarianRequestor** huongeza ombi kwenye ujumbe wa Pulsar +4. **Huduma ya Librarian** hupokea ujumbe, huondoa usimbaji wa hati katika kumbukumbu +5. **BlobStore** huipakia hati kwenye Garage/S3 +6. **Cassandra** huhifadhi metadata na rejea la kitu +7. Kwa uchakataji: hati hupelekwa kutoka S3, huondoa usimbaji, huainishwa—yote katika kumbukumbu +>>>>>>> 82edf2d (New md files from RunPod) + +Faili muhimu: +Ingizo la REST/WebSocket: `trustgraph-flow/trustgraph/gateway/service.py` +Msingi wa Librarian: `trustgraph-flow/trustgraph/librarian/librarian.py` +Uhifadhi wa blob: `trustgraph-flow/trustgraph/librarian/blob_store.py` +Jedwali la Cassandra: `trustgraph-flow/trustgraph/tables/library.py` +Mpango wa API: `trustgraph-base/trustgraph/schema/services/library.py` + +### Mapungufu ya Sasa + +<<<<<<< HEAD +Muundo wa sasa una masuala kadhaa ambayo huathiri kumbukumbu na uzoefu wa mtumiaji: + +1. **Operesheni ya Kupakia ya Atomiki**: Hati nzima lazima ihamishwe katika + ombi moja. Hati kubwa zinahitaji ombi linalodumu kwa muda mrefu bila + maelezo ya maendeleo na hakuna njia ya kujaribu tena ikiwa muunganisho utakatika. + +2. **Muundo wa API**: API za REST na WebSocket zinatarajia hati + nzima katika ujumbe mmoja. Mpango (`LibrarianRequest`) una `content` + ambayo ina maudhui ya hati nzima yaliyokuzwa kwa msingi 64. + +3. **Kumbukumbu ya Librarian**: Huduma ya librarian huondoa maudhui ya hati + katika kumbukumbu kabla ya kuihamisha kwenye S3. Kwa PDF ya 500MB, hii inamaanisha + kuhifadhi 500MB+ katika kumbukumbu ya mchakato. + +4. **Kumbukumbu ya Kufichua PDF**: Wakati wa uchakataji, programu ya kufichua PDF + huhamisha hati nzima katika kumbukumbu ili kuchimbua maandishi. Maktaba kama vile PyPDF + zinaweza kuhitaji upataji wa hati nzima. + +5. **Kumbukumbu ya Kifaa cha Kuchakata**: Kifaa cha kuchakata maandishi hupokea maandishi + yaliyochimbuliwa na kuhifadhi katika kumbukumbu huku huchakata na kuunda sehemu. + +**Mfano wa Athari ya Kumbukumbu** (PDF ya 500MB): +Lango: ~700MB (maudhui yaliyokuzwa) +Librarian: ~500MB (bytes zilizofichuliwa) +Kifaa cha Kufichua PDF: ~500MB + buffers za uchimbaji +Kifaa cha Kuchakata: maandishi yaliyochimbuliwa (hubadilika, inaweza kuwa 100MB+) +======= +Muundo wa sasa una masuala kadhaa yanayoathiri kumbukumbu na uzoefu wa mtumiaji: + +1. **Operesheni ya Uipakaji Kamili**: Hati nzima lazima iwasilishwe katika + ombi moja. Hati kubwa zinahitaji ombi linalodumu kwa muda mrefu bila + hakikisho ya maendeleo na hakuna njia ya kujaribu tena ikiwa muunganisho utavunjika. + +2. **Muundo wa API**: API za REST na WebSocket zinatarajia hati + nzima katika ujumbe mmoja. Mpango (`LibrarianRequest`) una `content` + sehemu inayohifadhi maudhui ya hati iliyosimbwa kwa base64. + +3. **Kumbukumbu ya Librarian**: Huduma ya librarian huondoa usimbaji wa hati + nzima katika kumbukumbu kabla ya kuipeleka kwenye S3. Kwa PDF ya 500MB, + hii inamaanisha kuhifadhi 500MB+ katika kumbukumbu ya programu. + +4. **Kumbukumbu ya Dekoda ya PDF**: Wakati uchakataji unaanza, dekoda ya PDF + hupakia hati nzima katika kumbukumbu ili kuchimbua maandishi. Maktabu kama + PyPDF na zile kama hizo kawaida zinahitaji upataji wa hati nzima. + +5. **Kumbukumbu ya Chunker**: Chunker hupokea maandishi yaliyochimbuliwa + na kuhifadhi katika kumbukumbu huku inazalisha sehemu. + +**Mfano wa Athari ya Kumbukumbu** (PDF ya 500MB): +Lango: ~700MB (ghairi ya usimbaji) +Librarian: ~500MB (bytes zilizopunguzwa) +Dekoda ya PDF: ~500MB + buffers za uchimbaji +Chunker: maandishi yaliyopatikana (hubadilika, inaweza kuwa 100MB+) +>>>>>>> 82edf2d (New md files from RunPod) + +Kumbukumbu ya juu inaweza kuzidi 2GB kwa hati kubwa moja. + +## Muundo wa Kiufundi + +### Kanuni za Muundo + +<<<<<<< HEAD +1. **Uhusiano wa API**: Mwingiliano wote wa mteja hupitia API ya librarian. Wateja + hawana upataji wa moja kwa moja au kujua kuhusu uhifadhi wa S3/Garage. + +2. **Kupakia kwa Sehemu ya S3**: Tumia kupakia kwa sehemu ya S3. + Hii inasaidiwa kwa mfumo wowote unaolingana na S3 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2, n.k.) kuhakikisha uwezekano wa kuhamishwa. + +3. **Kukamilika kwa Atomiki**: Kupakia kwa sehemu ya S3 kunaweza kukamilika kwa atomiki - sehemu + zilizopakiwa hazionekani hadi `CompleteMultipartUpload` itakapopigwa. + Hakuna faili za muda au operesheni za kubadilisha. + +4. **Hali Inayoweza Kufuatiliwa**: Vipindi vya kupakia hufuatiliwa katika Cassandra, kutoa + uonevu kuhusu kupakia ambacho hakikamilika na kuruhusu uwezo wa kuanza tena. + +### Mchakato wa Kupakia kwa Sehemu +======= +1. **Kifurushi cha API**: Mwingiliano wote wa mteja hupitia API ya librarian. Wateja + hawana upataji wa moja kwa moja au kujua kuhusu uhifadhi wa S3/Garage. + +2. **Uipakaji wa Sehemu wa S3**: Tumia uipakaji wa sehemu wa S3. + Hii inasaidiwa sana katika mifumo inayolingana na S3 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2, n.k.) kuhakikisha uwezekano wa kuhamishwa. + +3. **Uhakikisho Kamili**: Uipakaji wa sehemu wa S3 ni wa uhakikisho kamili - sehemu + zilizopakiwa hazionekani hadi `CompleteMultipartUpload` itakapopigwa. + Hakuna faili za muda au operesheni za kubadilisha. + +4. **Hali Inayoweza Kufuatiliwa**: Vipindi vya uipakaji hufuatiliwa katika Cassandra, + kutoa uonevu kuhusu uipakaji usio kamili na kuwezesha uwezo wa kuanza tena. + +### Mchakato wa Uipakaji wa Sehemu +>>>>>>> 82edf2d (New md files from RunPod) + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +Mteja hawezi kuwasiliana na S3 moja kwa moja. Msimamizi (librarian) hutafsiri kati ya +API yetu ya kupakia vipande na operesheni za S3 za sehemu nyingi (multipart) kwa ndani. + +### Operesheni za API ya Msimamizi (Librarian) + +#### `begin-upload` + +Anzisha kipindi cha kupakia vipande. + +Ombi: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +Jibu: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +Msimamizi wa maktaba: +1. Huunda nambari ya kipekee `upload_id` na `object_id` (UUID kwa uhifadhi wa data). +2. Huita `CreateMultipartUpload` ya S3, na kupokea `s3_upload_id`. +3. Huunda rekodi ya kikao katika Cassandra. +4. Hurudisha `upload_id` kwa mteja. + +#### `upload-chunk` + +<<<<<<< HEAD +Pakia kipande kimoja. +======= +Pakia sehemu moja. +>>>>>>> 82edf2d (New md files from RunPod) + +Ombi: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +Jibu: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +Msimamizi wa maktaba: +<<<<<<< HEAD +1. Tafuta kikao kwa kutumia `upload_id` +2. Thibitisha umiliki (mtumiaji lazima awe yule aliyeunda kikao) +3. Piga simu kwa S3 `UploadPart` pamoja na data ya sehemu, na upokee `etag` +4. Sasisha rekodi ya kikao na fahirisi ya sehemu na etag +5. Rejesha maelezo ya maendeleo kwa mteja + +Sehemu ambazo hazijafaulu zinaweza kujaribiwa tena - tuma tu `chunk-index` tena. +======= +1. Tafuta kipindi kwa `upload_id` +2. Thibitisha umiliki (mtumiaji lazima awe yule aliyeunda kipindi) +3. Piga S3 `UploadPart` na data ya sehemu, pokea `etag` +4. Sasisha rekodi ya kipindi na fahirisi ya sehemu na etag +5. Rejesha maendeleo kwa mteja + +Sehemu ambazo hazijafaulu zinaweza kujaribiwa tena - tuma tu `chunk-index` ile ile tena. +>>>>>>> 82edf2d (New md files from RunPod) + +#### `complete-upload` + +Hakisha upakiaji na uunde hati. + +Ombi: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +Jibu: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +Msimamizi wa maktaba: +<<<<<<< HEAD +1. Tafuta kikao, thibitisha kwamba vipande vyote vimepokelewa +2. Anapiga S3 `CompleteMultipartUpload` na etags za sehemu (S3 huunganisha sehemu + ndani - hakuna gharama ya kumbukumbu kwa msimamizi) +3. Huunda rekodi ya hati katika Cassandra na metadata na rejeleo la kitu +4. Huondoa rekodi ya kikao cha kupakia +5. Hurudisha kitambulisho cha hati kwa mteja +======= +1. Angalia kikao, thibitisha kwamba vipande vyote vimepokelewa. +2. Anapiga S3 `CompleteMultipartUpload` na etags za sehemu (S3 huunganisha sehemu + ndani - hakuna gharama ya kumbukumbu kwa msimamizi). +3. Huunda rekodi ya hati katika Cassandra na metadata na rejea la kitu. +4. Huondoa rekodi ya kikao cha kupakia. +5. Anarudisha kitambulisho cha hati kwa mteja. +>>>>>>> 82edf2d (New md files from RunPod) + +#### `abort-upload` + +Kuacha kupakia ambacho kinaendelea. + +Ombi: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +Msimamizi wa maktaba: +1. Anapiga simu kwa S3 `AbortMultipartUpload` ili kusafisha sehemu. +2. Anafuta rekodi ya kikao kutoka Cassandra. + +#### `get-upload-status` + +Angalia hali ya kupakia (kwa uwezo wa kuendelea). + +Ombi: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +Jibu: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +Orodha ya vipakuliwa ambavyo havijakamilika kwa mtumiaji. + +Ombi: +```json +{ + "operation": "list-uploads" +} +``` + +Jibu: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### Hifadhi ya Kipindi cha Uipakaji + +Fuatilia uipakaji unaoendelea katika Cassandra: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +<<<<<<< HEAD +**Tabia ya TTL:** +Vikao hupotea baada ya saa 24 ikiwa havijakamilika. +Wakati TTL ya Cassandra inapita, rekodi ya kikao inafutwa. +Sehemu zisizo na uhusiano za S3 huondolewa na sera ya maisha ya S3 (sanidi kwenye ndoo). + +### Usimamizi wa Hitilafu na Uadilifu + +**Hitilafu ya kupakia sehemu:** +Mteja hurudia kupakia sehemu iliyoshindwa (na `upload_id` na `chunk-index` sawa). +======= +**Tabia ya Muda (TTL):** +Vikao hupotea baada ya saa 24 ikiwa havijakamilika. +Wakati muda (TTL) wa Cassandra unapita, rekodi ya kikao inafutwa. +Sehemu zisizo na uhusiano za S3 huondolewa na sera ya maisha ya S3 (sanidi kwenye ndoo). + +### Usimamizi wa Hitilafu na Umoja + +**Hitilafu ya kupakia sehemu:** +Mteja hujaribu tena sehemu iliyoshindwa (na `upload_id` na `chunk-index` sawa). +>>>>>>> 82edf2d (New md files from RunPod) +`UploadPart` ya S3 ni sawa kwa nambari sawa ya sehemu. +Kikao kinafuatilia sehemu zipi zilizofanikiwa. + +**Mteja hukatika wakati wa kupakia:** +Kikao kinaendelea katika Cassandra na sehemu zilizopokelewa zimeandikwa. +Mteja anaweza kupiga `get-upload-status` ili kuona nini kinakosekana. +Anza tena kwa kupakia sehemu ambazo hazijapakiwa, kisha `complete-upload`. + +**Hitilafu ya kupakia kikamilifu:** +<<<<<<< HEAD +`CompleteMultipartUpload` ya S3 ni ya uadilifu - inaweza kufanikiwa kikamilifu au kushindwa. +Katika hali ya kushindwa, sehemu zinaendelea na mteja anaweza kujaribu tena `complete-upload`. +Hati yoyote ya nusu haionekani. + +**Kumalizika kwa kikao:** +TTL ya Cassandra inafuta rekodi ya kikao baada ya saa 24. +Sera ya maisha ya ndoo ya S3 husafisha kupakia kwa sehemu nyingi ambazo hazijakamilika. +Hakuna usafishaji wa mwongozo unaohitajika. + +### Uadilifu wa Sehemu Nyingi za S3 + +Kupakia kwa sehemu nyingi za S3 hutoa uadilifu uliopo: + +1. **Sehemu hazionekani:** Sehemu zilizopakuliwa haziwezi kupatikana kama vitu. + Zipo tu kama sehemu za kupakia kwa sehemu nyingi ambazo hazijakamilika. + +2. **Kukamilisha kwa uadilifu:** `CompleteMultipartUpload` inaweza kufanikiwa (kitu + kinaonekana kwa uadilifu) au kushindwa (hakuna kitu kilichoanzishwa). Hakuna hali ya nusu. + +3. **Hakuna jina tena linalohitajika:** Ufunguo wa mwisho wa kitu unaonyeshwa wakati + `CreateMultipartUpload`. Sehemu huunganishwa moja kwa moja kwenye ufunguo huo. + +4. **Uunganishaji wa upande wa seva:** S3 inaunganisha sehemu ndani. Msimamizi +======= +`CompleteMultipartUpload` ya S3 ni ya umoja - inaweza kufanikiwa kikamilifu au kushindwa. +Katika hali ya kushindwa, sehemu zinaendelea na mteja anaweza kujaribu tena `complete-upload`. +Hati yoyote isiyo kamili haionekani. + +**Muda wa kikao:** +Muda (TTL) wa Cassandra hufuta rekodi ya kikao baada ya saa 24. +Sera ya maisha ya ndoo ya S3 husafisha kupakia kwa sehemu nyingi ambazo hazijakamilika. +Hakuna usafishaji wa mwongozo unaohitajika. + +### Umoja wa Kupakia Sehemu ya S3 + +Kupakia sehemu nyingi za S3 hutoa umoja uliopo: + +1. **Sehemu hazionekani:** Sehemu zilizopakuliwa haziwezi kupatikana kama vitu. + Zipo tu kama sehemu za kupakia sehemu nyingi ambazo hazijakamilika. + +2. **Uhakikisho wa umoja:** `CompleteMultipartUpload` inaweza kufanikiwa (kitu + kinaonekana kikamilifu) au kushindwa (kitu hakitengenezwi). Hakuna hali ya nusu. + +3. **Hakuna haja ya kubadilisha jina:** Ufunguo wa mwisho wa kitu unaonyeshwa wakati + `CreateMultipartUpload`. Sehemu huunganishwa moja kwa moja kwenye ufunguo huo. + +4. **Uunganishaji wa upande wa seva:** S3 huunganisha sehemu ndani. Msimamizi +>>>>>>> 82edf2d (New md files from RunPod) + haisomi sehemu - hakuna gharama ya kumbukumbu bila kujali ukubwa wa hati. + +### Upanuzi wa BlobStore + +**Faili:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +Ongeza mbinu za kupakia sehemu nyingi: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +<<<<<<< HEAD +### Mambo Yanayohusiana na Ukubwa wa Sehemu + +**Kiwango cha chini cha S3**: 5MB kwa kila sehemu (isipokuwa sehemu ya mwisho) +**Kiwango cha juu cha S3**: Sehemu 10,000 kwa kila upakiaji +**Kiwango cha kawaida kinachopendekezwa**: Sehemu za 5MB + Hati ya 500MB = sehemu 100 + Hati ya 5GB = sehemu 1,000 +**Ufuatiliaji wa maendeleo**: Sehemu ndogo = taarifa za maendeleo bora +**Ufanisi wa mtandao**: Sehemu kubwa = safari ndogo + +Ukubwa wa sehemu unaweza kupangwa na mtumiaji ndani ya mipaka (5MB - 100MB). + +### Ufuatiliaji wa Hati: Upakiaji wa Kiasi + +Mchakato wa upakiaji unalenga kuweka hati kwenye hifadhi kwa ufanisi. Mchakato +wa ufuatiliaji unalenga kuchuja na kugawanya hati bila kuzipakia +zote kwenye kumbukumbu. + +#### Kanuni ya Ubunifu: Kitambulisho, Sio Yaliyomo + +Kwa sasa, wakati mchakato unaanza, yaliyomo kwenye hati huhamishwa kupitia +ujumbe wa Pulsar. Hii inapakia hati zote kwenye kumbukumbu. Badala yake: + +Ujumbe wa Pulsar unaonyesha tu **kitambulisho cha hati** +Vifaa vya ufuatiliaji hupata yaliyomo kwenye hati moja kwa moja kutoka kwa mfumo +Kupata hufanyika kama **mtiririko kwenye faili ya muda** +Ufuatiliaji maalum wa hati (PDF, maandishi, n.k.) hufanya kazi na faili, sio +mipaka ya kumbukumbu + +Hii inahakikisha kwamba mfumo wa hati hautegemei muundo wa hati. Ufuatiliaji +wa PDF, ufuatiliaji wa maandishi, na mantiki nyingine maalum ya muundo +inabaki katika vichujio husika. +======= +### Mambo Yanayohusiana na Ukubwa wa Kifurushi + +**Kiwango cha chini cha S3**: 5MB kwa kila sehemu (isipokuwa sehemu ya mwisho) +**Kiwango cha juu cha S3**: Sehemu 10,000 kwa kila upakiaji +**Kiwango cha kawaida kinachopendekezwa**: Kifurushi cha 5MB + Hati ya 500MB = Kifurushi 100 + Hati ya 5GB = Kifurushi 1,000 +**Ufuatiliaji wa maendeleo**: Kifurushi kidogo = Taarifa za maendeleo bora +**Ufanisi wa mtandao**: Kifurushi kikubwa = Safari ndogo + +Ukubwa wa kifurushi unaweza kusanidiwa na mtumiaji ndani ya mipaka (5MB - 100MB). + +### Ufuatiliaji wa Hati: Upakiaji wa Kwenye Mtiririko + +Mchakato wa upakiaji unahusu kuweka hati kwenye hifadhi kwa ufanisi. Mchakato wa ufuatiliaji unahusu kuchuja na kugawanya hati bila kuiziba yote kwenye kumbukumbu. + + + +#### Kanuni ya Ubunifu: Kitambulisho, Sio Yaliyomo + +Kwa sasa, wakati mchakato unaanza, yaliyomo kwenye hati huhamishwa kupitia ujumbe wa Pulsar. Hii huweka hati zilizokamilika kwenye kumbukumbu. Badala yake: + + +Ujumbe wa Pulsar unaonyesha tu **kitambulisho cha hati** +Vifaa hupata yaliyomo kwenye hati moja kwa moja kutoka kwa mfumo wa kumbukumbu +Kupata hufanyika kama **mtiririko kwenye faili ya muda** +Ufuatiliaji maalum wa hati (PDF, maandishi, n.k.) hutumia faili, sio mipaka ya kumbukumbu + +Hii huweka mfumo wa kumbukumbu usio na kujua muundo wa hati. Ufuatiliaji wa PDF, ufuatiliaji wa maandishi, na mantiki nyingine maalum ya muundo huendelea katika vichujio husika. + + +#### Mchakato wa Ufuatiliaji +>>>>>>> 82edf2d (New md files from RunPod) + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +<<<<<<< HEAD +#### API ya Mfumo wa Maktaba + +Ongeza operesheni ya upataji wa hati kwa njia ya mtiririko: +======= +#### API ya Mto wa Huduma za Maktaba + +Ongeza operesheni ya kupata hati kwa mtiririko: +>>>>>>> 82edf2d (New md files from RunPod) + +**`stream-document`** + +Ombi: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +Jibu: Vipande vya binary vilivyotumwa (si jibu moja). + +Kwa API ya REST, hii hurudisha jibu linaloendelea kwa kutumia `Transfer-Encoding: chunked`. + +<<<<<<< HEAD +Kwa simu za ndani kati ya huduma (kwa mfumo wa uprosesa hadi mfumo wa kumbukumbu), hii inaweza kuwa: +Uhamisho wa moja kwa moja wa S3 kupitia URL iliyosainiwa (ikiwa mtandao wa ndani unaruhusu). +Majibu yaliyogawanywa kupitia itifaki ya huduma. +Kituo maalum cha utumaji wa data. +======= +Kwa simu za ndani kati ya huduma (kwa mfumo wa usindikaji hadi kwa mfumo wa kumbukumbu), hii inaweza kuwa: +Uhamisho wa moja kwa moja wa S3 kupitia URL iliyosainiwa (ikiwa mtandao wa ndani unaruhusu). +Majibu yaliyogawanywa kupitia itifaki ya huduma. +Kifaa maalum cha utumaji wa data. +>>>>>>> 82edf2d (New md files from RunPod) + +Mahitaji muhimu: data inatiririka kwa vipande, haijahifadhiwa kikamilifu katika mfumo wa kumbukumbu. + +#### Mabadiliko ya Kipanguli cha PDF + +**Utendaji wa sasa** (unaotumia kumbukumbu nyingi): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**Utekelezaji mpya** (faili ya muda, hatua kwa hatua): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +Profaili ya kumbukumbu: +Faili ya muda kwenye diski: ukubwa wa faili ya PDF (diski ni rahisi). +Katika kumbukumbu: ukurasa mmoja wa maandishi kwa wakati. +Kumbukumbu ya juu: imepunguzwa, haitegemei saizi ya hati. + +#### Mabadiliko ya Kipanguli cha Hati za Nakshata + +Kwa hati za nakshata, rahisi zaidi - hakuna faili ya muda inayohitajika: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +Hati za maandishi zinaweza kutiririka moja kwa moja bila faili ya muda kwa sababu zina +muundo wa mstari. + +<<<<<<< HEAD +#### Jumuisho la Kifaa cha Kugawa (Chunker) + +Kifaa cha kugawa hupokea mfuatiliaji wa maandishi (kurasa au aya) na hutoa +======= +#### Jumuisho la Kichungia (Chunker) + +Kichungia hupokea mfuatiliaji wa maandishi (kurasa au aya) na hutoa +>>>>>>> 82edf2d (New md files from RunPod) +vipande kwa hatua kwa hatua: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### Mchakato Kamili wa Uendeshaji + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +<<<<<<< HEAD +Katika hakuna hatua, hati kamili au maandishi yaliyotolewa kamili hayahifadhiwi kwenye kumbukumbu. +======= +Katika hakuna hatua, hati kamili au maandishi yaliyochukuliwa kamili hayahifadhiwi kwenye kumbukumbu. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Mambo Yanayohusiana na Faili za Muda + +**Mahali:** Tumia saraka ya muda ya mfumo (`/tmp` au sawa). Kwa +matumizi yaliyojumuishwa, hakikisha saraka ya muda ina nafasi ya kutosha +na iko kwenye uhifadhi wa haraka (si iliyounganishwa kwenye mtandao, ikiwezekana). + +**Usafishaji:** Tumia menejeria wa muktadha (`with tempfile...`) ili kuhakikisha usafishaji +hata wakati wa hitilafu. + +**Uchakataji sambamba:** Kazi kila moja ya uchakataji hupata faili yake ya muda. +Hakuna migogoro kati ya uchakataji wa hati sambamba. + +**Nafasi ya diski:** Faili za muda zina muda mfupi (muda wa uchakataji). Kwa +<<<<<<< HEAD +hati ya PDF ya 500MB, inahitaji nafasi ya muda ya 500MB wakati wa uchakataji. Kikomo cha ukubwa +kinaweza kutekelezwa wakati wa kupakia ikiwa nafasi ya diski ni mdogo. + +### Kiolesura Kimoja cha Uchakataji: Hati za Mtoto + +Uchimbaji wa hati za PDF na uchakataji wa hati za maandishi lazima ziingie katika +mstari mmoja wa baadaye (kugawanya → embeddings → uhifadhi). Ili kufanikisha hili kwa +"kupata kwa ID" kiolesura, vipande vya maandishi vilivyochimbwa huhifadhiwa tena +kwenye mfumo kama hati za mtoto. + +#### Mchakato wa Uchakataji na Hati za Mtoto +======= +hati ya PDF ya 500MB, inahitaji nafasi ya muda ya 500MB wakati wa uchakataji. Kizuia cha ukubwa +kunaweza kutekelezwa wakati wa kupakia ikiwa nafasi ya diski ni mdogo. + +### Kiolesura Kimoja cha Uchakataji: Hati za Watoto + +Uchimbaji wa hati za PDF na uchakataji wa maandishi unahitaji kuingia kwenye +mstari mmoja wa baadaye (kugawanya → maandishi → uhifadhi). Ili kufanikisha hili kwa +"kupata kwa ID" kiolesura, vipande vya maandishi vilivyochimbwa huhifadhiwa tena +kwenye mfumo kama hati za watoto. + +#### Mchakato wa Uchakataji na Hati za Watoto +>>>>>>> 82edf2d (New md files from RunPod) + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +Kifaa cha kuainisha (chunker) kina muundo mmoja wa kiungo: +Pokea kitambulisho cha hati (kupitia Pulsar) +Pumua yaliyomo kutoka kwa mfumo wa kumbukumbu (librarian) +Igawanye katika sehemu ndogo + +Haijulishi au hajali kama kitambulisho kinarejelea: +Hati ya maandishi iliyopakiwa na mtumiaji +Sehemu ya maandishi iliyochimbwa kutoka kwa ukurasa wa PDF +Aina yoyote ya hati ya siku zijazo + +<<<<<<< HEAD +#### Meta-data ya Hati Ndogo +======= +#### Meta Data ya Hati Ndogo +>>>>>>> 82edf2d (New md files from RunPod) + +Panua muundo wa hati ili kufuatilia uhusiano wa mzazi/mtoto: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**Aina za nyaraka:** + +| `document_type` | Maelezo | +|-----------------|-------------| +| `source` | Nyaraka zilizopakiwa na mtumiaji (PDF, maandishi, n.k.) | +<<<<<<< HEAD +| `extracted` | Zilizotokana na nyaraka asili (k.m., maandishi ya ukurasa wa PDF) | + +**Nafasi za metadata:** + +| Nafasi | Nyaraka Asili | Nyaraka Zilizotokana | +|-------|-----------------|-----------------| +| `id` | Zilizotolewa na mtumiaji au zilizoundwa | Zilizoundwa (k.m., `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | Kitambulisho cha nyaraka asili | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, n.k. | `text/plain` | +| `title` | Zilizotolewa na mtumiaji | Zilizoundwa (k.m., "Ukurasa wa 3 wa Ripoti.pdf") | +| `user` | Mtumiaji aliyeidhinishwa | Sawa na nyaraka asili | + +#### API ya Maktaba kwa Nyaraka Zilizotokana + +**Kuunda nyaraka zilizotokana** (ya ndani, hutumiwa na pdf-extractor): +======= +| `extracted` | Imetokana na nyaraka ya asili (k.m., maandishi ya ukurasa wa PDF) | + +**Nafasi za metadata:** + +| Nafasi | Nyaraka ya Asili | Mtoto Uliochukuliwa | +|-------|-----------------|-----------------| +| `id` | Iliyotolewa na mtumiaji au iliyoundwa | Iliyoundwa (k.m., `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | Kitambulisho cha nyaraka mama | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, n.k. | `text/plain` | +| `title` | Iliyotolewa na mtumiaji | Iliyoundwa (k.m., "Ukurasa wa 3 wa Ripoti.pdf") | +| `user` | Mtumiaji aliyeidhinishwa | Sawa na nyaraka mama | + +#### API ya Maktaba kwa Nyaraka za Watoto + +**Kutengeneza nyaraka za watoto** (ya ndani, inayotumika na pdf-extractor): +>>>>>>> 82edf2d (New md files from RunPod) + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +<<<<<<< HEAD +Kwa maandishi madogo ambayo yamechukuliwa (maandishi ya kawaida ya ukurasa ni chini ya 100KB), kupakia kwa operesheni moja ni sawa. Kwa matamshi makubwa sana ya maandishi, kupakia kwa sehemu kunaweza kutumika. +======= +Kwa maandishi madogo ambayo yamechukuliwa (maandishi ya kawaida ya ukurasa ni chini ya 100KB), kupakia kwa hatua moja ni la kukubalika. Kwa matamshi makubwa sana ya maandishi, kupakia kwa sehemu kunaweza kutumika. +>>>>>>> 82edf2d (New md files from RunPod) + +**Orodha ya hati za watoto** (kwa ajili ya utatuzi/utawala): + + +<<<<<<< HEAD + +======= +Hati ya Matokeo +>>>>>>> 82edf2d (New md files from RunPod) +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +Jibu: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### Tabia inayoonwa na mtumiaji + +**Tabia ya kawaida ya `list-documents`:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +Tuandishi kuu (vyanzo) pekee ndivyo yanavyoonekana kwenye orodha ya vyanzo vya mtumiaji. +Vyanzo vidogo huondolewa kwa chaguo-msingi. + +**Bendera ya hiari ya kujumuisha-vyanzo-vidogo** (kwa wasimamizi/uchunguzi): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +<<<<<<< HEAD +#### Ufutilishaji wa Kuondoa Data kwa Kadirio + +Wakati hati mama inapoondolewa, watoto wote lazima waondolewe: +======= +#### Ufutilishaji Pamoja na Uharibifu wa Data + +Wakati hati mama inafutwa, watoto wote lazima waondolewe: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +<<<<<<< HEAD +#### Mawazo Kuhusu Uhifadhi + +Matini yaliyotolewa yana nakala sawa: +Nakala asili ya PDF inahifadhiwa katika "Garage" +Nakala iliyotolewa kwa kila ukurasa pia inahifadhiwa katika "Garage" + +Hii inaruhusu: +**Kiolesura sawa cha "chunker"**: "Chunker" daima hupata data kwa kutumia kitambulisho +**Uendelezaji/jaribio tena**: Inaweza kuanza tena katika hatua ya "chunker" bila kuhariri tena PDF +**Urekebishaji**: Nakala iliyotolewa inaweza kuchunguzwa +**Tofauti ya majukumu**: Huduma ya kuchimbua PDF na "chunker" ni huduma tofauti +======= +#### Mawasilisho ya Uhifadhi + +Matini yaliyotolewa yana nakala za maudhui: +Nakala ya asili ya PDF inahifadhiwa katika "Garage" +Nakala ya matini iliyotolewa kwa kila ukurasa pia inahifadhiwa katika "Garage" + +Hii inaruhusu: +**Kiolesura cha kawaida cha "chunker"**: "Chunker" daima hupata kwa kitambulisho +**Uanzishaji upya/jaribio**: Inaweza kuanzisha tena katika hatua ya "chunker" bila kuharibu tena PDF +**Urekebishaji**: Matini iliyotolewa inaweza kuchunguzwa +**Tofauti ya majukumu**: Huduma ya kutolea matini kutoka PDF na "chunker" ni huduma tofauti +>>>>>>> 82edf2d (New md files from RunPod) + +Kwa PDF ya 500MB yenye kurasa 200, kwa wastani ya matini ya 5KB kwa kila ukurasa: +Uhifadhi wa PDF: 500MB +Uhifadhi wa matini iliyotolewa: ~1MB jumla +Gharama ya ziada: ndogo sana + +<<<<<<< HEAD +#### Matokeo ya Kuchimbua PDF + +Kichunguzi cha kuchimbua PDF, baada ya kuchakata hati: + +1. Hupata PDF kutoka kwa "librarian" hadi kwenye faili ya muda +2. Huchimbua matini ukurasa kwa ukurasa +======= +#### Matokeo ya Kutoa Matini kutoka PDF + +Kifaa cha kutoa matini kutoka PDF, baada ya kuchakata hati: + +1. Hupokea PDF kutoka kwa "librarian" hadi faili ya muda +2. Hutoa matini ukurasa kwa ukurasa +>>>>>>> 82edf2d (New md files from RunPod) +3. Kwa kila ukurasa, huhifadhi matini iliyotolewa kama hati ndogo kupitia "librarian" +4. Hutuma kitambulisho cha hati ndogo kwa folyo ya "chunker" + +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +<<<<<<< HEAD +Kifaa cha kuainisha vitapokea kitambulisho hivi vya watoto na vitawatumia kwa njia ile ile +ambayo kingetumia hati ya maandishi iliyopakiwa na mtumiaji. + +### Sasizi za Mteja +======= +Kifaa cha "chunker" hupokea kitambulisho hivi vya watoto na huviweka sawa na +jinsi lingeweza kuchakata hati ya maandishi iliyopakiwa na mtumiaji. + +### Masasisho ya Mteja +>>>>>>> 82edf2d (New md files from RunPod) + +#### SDK ya Python + +SDK ya Python (`trustgraph-base/trustgraph/api/library.py`) inapaswa kushughulikia +<<<<<<< HEAD +vipakio vilivyogawanywa kwa njia ya moja kwa moja. Muundo wa umma haubadiliki: +======= +vipakio vilivyogawanywa kwa njia ambayo haionyeshi. Muundo wa umma haubadiliki: +>>>>>>> 82edf2d (New md files from RunPod) + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +Kwa ndani, SDK hugundua ukubwa wa hati na hubadilisha mkakati: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**Arifa za maendeleo** (ongezeko la hiari): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +Hii inaruhusu programu za kiutengenezaji kuonyesha maendeleo ya kupakia bila kubadilisha API ya msingi. + +#### Zana za CLI (Command Line Interface) + +**`tg-add-library-document`** inaendelea kufanya kazi bila kubadilika: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +Onyesho la maendeleo la hiari linaweza kuongezwa: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**Vifaa vya zamani vimetoolewa:** + +<<<<<<< HEAD +`tg-load-pdf` - imepitwa na wakati, tumia `tg-add-library-document` +`tg-load-text` - imepitwa na wakati, tumia `tg-add-library-document` +======= +`tg-load-pdf` - yamefutwa, tumia `tg-add-library-document` +`tg-load-text` - yamefutwa, tumia `tg-add-library-document` +>>>>>>> 82edf2d (New md files from RunPod) + +**Amri za utawala/uchunguzi** (hiari, kipaumbele cha chini): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +Haya yanaweza kuwa maboresho kwenye amri iliyopo badala ya zana tofauti. + +#### Masuala ya Mabadiliko ya Vipimo vya API + +Vipimo vya OpenAPI (`specs/api/paths/librarian.yaml`) vinahitaji mabadiliko kwa: + +**Utendaji mpya:** + +<<<<<<< HEAD +`begin-upload` - Anzisha kipindi cha kupakia kwa sehemu +======= +`begin-upload` - Anzisha kipindi cha kupakia sehemu +>>>>>>> 82edf2d (New md files from RunPod) +`upload-chunk` - Pakia sehemu moja +`complete-upload` - Kamilisha kupakia +`abort-upload` - Ghairi kupakia +`get-upload-status` - Angalia maendeleo ya kupakia +`list-uploads` - Orodha ya kupakia ambayo hayaja kamili kwa mtumiaji +`stream-document` - Kuchukua hati kwa njia ya utiririshaji +`add-child-document` - Hifadhi maandishi yaliyotolewa (ya ndani) +`list-children` - Orodha ya hati za chini (ya msimamizi) + +**Utendaji uliorekebishwa:** + +`list-documents` - Ongeza parameter `include-children` + +<<<<<<< HEAD +**Muundo mpya:** +======= +**Vipimo vipya:** +>>>>>>> 82edf2d (New md files from RunPod) + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**Mabadiliko ya vipimo vya WebSocket** (`specs/websocket/`): + +Nakala utendaji wa REST kwa wateja wa WebSocket, na kuwezesha +<<<<<<< HEAD +maendeleo ya muda halisi wakati wa kupakia. +======= +maendeleo ya wakati halisi wakati wa kupakia. +>>>>>>> 82edf2d (New md files from RunPod) + +#### Mambo ya Kuzingatia ya Uzoefu wa Mtumiaji + +Mabadiliko ya vipimo vya API yanawezesha maboresho ya upande wa mbele: + +**Kiolesura cha maendeleo ya kupakia:** +Pampu ya maendeleo ya kuonyesha sehemu zilizopakwa +Muda uliokadiri wa kupakia +Uwezo wa kusitisha/kuendeleza + +**Kupona kwa makosa:** +<<<<<<< HEAD +Chaguo la "Endeleza kupakia" kwa kupakia ambacho kimekatika +Orodha ya kupakia ambayo hayaja kamili wakati wa kuunganisha tena + +**Ushughulikiaji wa faili kubwa:** +Uchunguzi wa ukubwa wa faili kwenye upande wa mteja +Kupakia kwa sehemu kiotomatiki kwa faili kubwa +======= +Chaguo la "endelea kupakia" kwa kupakia ambacho kimekatika +Orodha ya kupakia ambayo hayaja kamili wakati wa kuunganisha tena + +**Usimamizi wa faili kubwa:** +Uchunguzi wa ukubwa wa faili kwenye upande wa mteja +Kupakia kiotomatiki kwa sehemu kwa faili kubwa +>>>>>>> 82edf2d (New md files from RunPod) +Maelezo wazi wakati wa kupakia kwa muda mrefu + +Maboresho haya ya uzoefu wa mtumiaji yanahitaji kazi ya upande wa mbele inayong'wa na vipimo vya API vilivyoboreshwa. diff --git a/docs/tech-specs/large-document-loading.tr.md b/docs/tech-specs/large-document-loading.tr.md new file mode 100644 index 00000000..57aaf172 --- /dev/null +++ b/docs/tech-specs/large-document-loading.tr.md @@ -0,0 +1,992 @@ +--- +layout: default +title: "Büyük Belge Yükleme Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Büyük Belge 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'e büyük belgelerin yüklenmesi sırasında ortaya çıkan ölçeklenebilirlik ve kullanıcı deneyimi sorunlarını ele almaktadır. Mevcut mimari, belge yüklemeyi tek bir atomik işlem olarak ele almaktadır, bu da boru hattının çeşitli noktalarında bellek yüklenmesine neden olmakta ve kullanıcılara herhangi bir geri bildirim veya kurtarma seçeneği sunmamaktadır. + +Bu uygulama, aşağıdaki kullanım senaryolarına yöneliktir: + + +1. **Büyük PDF İşleme**: Belleği tüketmeden yüzlerce megabayt boyutunda PDF dosyalarını yükleyin ve işleyin. + +2. **Devam Eden Yüklemeler**: Kesintiye uğrayan yüklemelerin, baştan başlamak yerine, durdurulduğu yerden devam etmesini sağlayın. + +3. **İlerleme Geri Bildirimi**: Kullanıcılara yükleme ve işleme sürecinin gerçek zamanlı görünürlüğünü sağlayın. + +4. **Bellek Verimli İşleme**: Belgeleri, tüm dosyaları bellekte tutmadan, akış halinde işleyin. + + + ## Hedefler + + +**Artımlı Yükleme**: REST ve WebSocket üzerinden parçalı belge yüklemeyi destekleyin. +**Devam Eden Aktarımlar**: Kesintiye uğrayan yüklemelerden kurtarmayı sağlayın. +**İlerleme Görünürlüğü**: İstemcilere yükleme/işleme sürecinin ilerleme durumunu geri bildirin. +**Bellek Verimliliği**: Boru hattının tamamında tam belge tamponlamayı ortadan kaldırın. +**Geriye Dönük Uyumluluk**: Mevcut, küçük belge iş akışlarının değişmeden devam etmesini sağlayın. +**Akış İşleme**: PDF kod çözme ve metin parçalama işlemleri, akışlar üzerinde gerçekleştirilir. + +## Arka Plan + + +### Mevcut Mimari + +Belge gönderme işlemi, aşağıdaki yolu izlemektedir: + +1. **İstemci**, belgeyi REST (`POST /api/v1/librarian`) veya WebSocket üzerinden gönderir. +2. **API Ağ Geçidi**, base64 ile kodlanmış belge içeriği içeren eksiksiz isteği alır. +3. **LibrarianRequestor**, isteği Pulsar mesajına dönüştürür. +4. **Librarian Hizmeti**, mesajı alır, belgeyi belleğe kodlar. +5. **BlobStore**, belgeyi Garage/S3'e yükler. +6. **Cassandra**, nesne referansı ile birlikte meta verileri depolar. +7. İşleme için: belge S3'ten alınır, kodlanır, parçalara ayrılır - hepsi bellekte. + +Önemli dosyalar: +REST/WebSocket girişi: `trustgraph-flow/trustgraph/gateway/service.py` +Librarian çekirdeği: `trustgraph-flow/trustgraph/librarian/librarian.py` +Blob depolama: `trustgraph-flow/trustgraph/librarian/blob_store.py` +Cassandra tabloları: `trustgraph-flow/trustgraph/tables/library.py` +API şeması: `trustgraph-base/trustgraph/schema/services/library.py` + +### Mevcut Sınırlamalar + +Mevcut tasarımın, çeşitli birikimli bellek ve kullanıcı deneyimi sorunları bulunmaktadır: + +1. **Atomik Yükleme İşlemi**: Tüm belge, + tek bir istekte iletilmelidir. Büyük belgeler, bağlantı başarısız olursa geri alma mekanizması olmadan, ilerleme göstergesi olmayan uzun süreli istekler gerektirir. + + +2. **API Tasarımı**: Hem REST hem de WebSocket API'leri, + tüm belgeyi tek bir mesajda bekler. Şema (`LibrarianRequest`), tüm base64 ile kodlanmış belgeyi içeren tek bir `content` + alanına sahiptir. + +3. **Kütüphaneci Belleği**: Kütüphaneci hizmeti, belgeyi S3'e yüklemeden önce tüm belgeyi belleğe aktarır. 500MB'lık bir PDF için, bu, işlem belleğinde 500MB+'yi tutmak anlamına gelir. + 500MB+ işlem belleğinde tutmak anlamına gelir. + + +4. **PDF Kod Çözücü Belleği**: İşleme başladığında, PDF kod çözücü, metni çıkarmak için tüm PDF'yi belleğe yükler. PyPDF ve benzeri kütüphaneler genellikle belgenin tamamına erişim gerektirir. + + + +5. **Parçalayıcı Belleği**: Metin parçalayıcı, çıkarılan tamamlanmış metni alır ve parçalar oluştururken bunu bellekte tutar. + + +**Bellek Kullanımı Örneği** (500MB PDF): +Gateway: ~700MB (base64 kodlama ek yükü) +Librarian: ~500MB (çözülmüş baytlar) +PDF Çözücü: ~500MB + çıkarma arabellekleri +Parçalayıcı: çıkarılan metin (değişken, potansiyel olarak 100MB+) + +Tek bir büyük belge için toplam maksimum bellek kullanımı 2GB'ı aşabilir. + +## Teknik Tasarım + +### Tasarım İlkeleri + +1. **API Arayüzü**: Tüm istemci etkileşimi, librarian API'si üzerinden gerçekleşir. İstemciler, + temelindeki S3/Garage depolamaya doğrudan erişemez veya bu depolama hakkında bilgi sahibi değildir. + +2. **S3 Çoklu Parça Yükleme**: Temelde standart S3 çoklu parça yükleme özelliğini kullanın. + Bu, S3 uyumlu sistemlerde (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2, vb.) yaygın olarak desteklenir ve taşınabilirliği sağlar. + +3. **Atomik Tamamlama**: S3 çoklu parça yüklemeleri doğası gereği atomiktir; yüklenen + parçalar, `CompleteMultipartUpload` çağrılana kadar görünmez. Geçici + dosyalar veya yeniden adlandırma işlemleri gerekmez. + +4. **Takip Edilebilir Durum**: Yükleme oturumları Cassandra'da takip edilir, bu da + tamamlanmamış yüklemeler hakkında görünürlük sağlar ve devam ettirme özelliğini etkinleştirir. + +### Parçalı Yükleme Akışı + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +Müşteri, S3 ile doğrudan etkileşimde bulunmaz. Kütüphaneci, parçalı yükleme API'miz ile S3 çok parçalı işlemler arasında dahili olarak çeviri yapar. + +### Kütüphaneci API İşlemleri +### Kütüphaneci API İşlemleri + +#### `begin-upload` + +Parçalı bir yükleme oturumu başlatın. + +İstek: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +Yanıt: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +Kütüphaneci: +1. Benzersiz bir `upload_id` ve `object_id` oluşturur (blob depolama için UUID). +2. S3'ü `CreateMultipartUpload` ile çağırır, `s3_upload_id`'i alır. +3. Cassandra'da oturum kaydını oluşturur. +4. `upload_id`'ı istemciye döndürür. + +#### `upload-chunk` + +Tek bir bölüm yükleyin. + +İstek: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +Yanıt: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +Kütüphaneci: +1. `upload_id` ile oturumu arar. +2. Mülkiyeti doğrular (kullanıcı, oturum oluşturucuyu eşleştirmelidir). +3. Parça verileriyle S3'ü `UploadPart` ile çağırır, `etag` alır. +4. Parça indeksini ve etiketini kullanarak oturum kaydını günceller. +5. İlerleme durumunu istemciye döndürür. + +Başarısız parçalar tekrar denenebilir - aynı `chunk-index`'ı tekrar gönderin. + +#### `complete-upload` + +Yüklemeyi tamamlayın ve belgeyi oluşturun. + +İstek: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +Yanıt: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +Kütüphaneci: +1. Oturumu kontrol eder, tüm parçaların alındığından emin olur. +2. Parça etiketleriyle birlikte S3'ü `CompleteMultipartUpload` ile çağırır (S3 parçaları dahili olarak birleştirir - kütüphaneci için bellek maliyeti sıfırdır). + 3. Cassandra'da, meta veriler ve nesne referansı ile birlikte bir belge kaydı oluşturur. +4. Yükleme oturumu kaydını siler. +5. Belge kimliğini müşteriye döndürür. + + +#### `abort-upload` + +Devam eden bir yüklemeyi iptal et. + +İstek: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +Kütüphaneci: +1. Parçaları temizlemek için S3 `AbortMultipartUpload`'ı çağırır. +2. Oturum kaydını Cassandra'dan siler. + +#### `get-upload-status` + +Bir yüklemenin durumunu sorgula (devam ettirme özelliği için). + +İstek: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +Yanıt: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +Bir kullanıcı için eksik yüklemeleri listele. + +İstek: +```json +{ + "operation": "list-uploads" +} +``` + +Yanıt: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### Yükleme Oturum Depolama + +Cassandra'da devam eden yüklemeleri takip edin: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**TTL Davranışı:** +Oturumlar, tamamlanmadığı takdirde 24 saat sonra sona erer. +Cassandra TTL'si dolduğunda, oturum kaydı silinir. +Yalnız kalmış S3 parçaları, S3 yaşam döngüsü politikası tarafından temizlenir (kovada yapılandırılır). + +### Hata Yönetimi ve Atomiklik + +**Parça yükleme hatası:** +İstemci, başarısız olan parçayı tekrar dener (aynı `upload_id` ve `chunk-index`). +S3 `UploadPart`, aynı parça numarası için idempotent'tir. +Oturum, hangi parçaların başarılı olduğunu takip eder. + +**İstemci, yükleme sırasında bağlantıyı keser:** +Oturum, Cassandra'da alınan parçalarla birlikte kalır. +İstemci, eksik olanları görmek için `get-upload-status`'ı çağırabilir. +Yalnızca eksik parçaları yükleyerek devam edin ve ardından `complete-upload`'ı çağırın. + +**Tamamlanmış yükleme hatası:** +S3 `CompleteMultipartUpload` atomiktir - ya tamamen başarılı olur ya da başarısız olur. +Başarısızlık durumunda, parçalar kalır ve istemci `complete-upload`'ı tekrar deneyebilir. +Hiçbir kısmi belge görünmez. + +**Oturumun sona ermesi:** +Cassandra TTL, oturum kaydını 24 saat sonra siler. +S3 kova yaşam döngüsü politikası, tamamlanmamış çok parçalı yüklemeleri temizler. +Manuel temizliğe gerek yoktur. + +### S3 Çok Parçalı Atomiklik + +S3 çok parçalı yüklemeler, yerleşik atomiklik sağlar: + +1. **Parçalar görünmezdir:** Yüklenen parçalar, nesne olarak erişilemez. + Bunlar yalnızca tamamlanmamış bir çok parçalı yüklemenin parçaları olarak vardır. + +2. **Atomik tamamlama:** `CompleteMultipartUpload` ya başarılı olur (nesne + atomik olarak görünür) ya da başarısız olur (nesne oluşturulmaz). Herhangi bir kısmi durum yoktur. + +3. **Yeniden adlandırmaya gerek yoktur:** Son nesne anahtarı, + `CreateMultipartUpload` zamanında belirtilir. Parçalar doğrudan bu anahtara birleştirilir. + +4. **Sunucu tarafı birleştirme:** S3, parçaları dahili olarak birleştirir. Kütüphaneci + parçaları asla tekrar okumaz - belgenin boyutundan bağımsız olarak sıfır bellek yükü. + +### BlobStore Uzantıları + +**Dosya:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +Çok parçalı yükleme yöntemleri ekleyin: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### Parça Boyutu Hususları + +**S3 minimumu**: Parça başına 5 MB (son parça hariç) +**S3 maksimumu**: Bir yükleme başına 10.000 parça +**Pratik varsayılan**: 5 MB'lık parçalar + 500 MB'lık bir belge = 100 parça + 5 GB'lık bir belge = 1.000 parça +**İlerleme hassasiyeti**: Daha küçük parçalar = daha hassas ilerleme güncellemeleri +**Ağ verimliliği**: Daha büyük parçalar = daha az sayıda istek + +Parça boyutu, belirli sınırlar içinde (5 MB - 100 MB) istemci tarafından yapılandırılabilir. + +### Belge İşleme: Akışlı Alma + +Yükleme akışı, belgelerin depolamaya verimli bir şekilde aktarılmasını sağlar. İşleme akışı, belgelerin tamamını belleğe yüklemeden, belgelerin çıkarılmasını ve parçalara ayrılmasını sağlar. + + + +#### Tasarım İlkesi: İçerik Değil, Tanımlayıcı + +Şu anda, işleme başlatıldığında, belge içeriği Pulsar mesajları aracılığıyla akar. Bu, tüm belgelerin belleğe yüklenmesine neden olur. Bunun yerine: + + +Pulsar mesajları yalnızca **belge tanımlayıcısını** taşır +İşleyiciler, belge içeriğini doğrudan kütüphaneden alırlar +Alma işlemi, bir **geçici dosyaya akış şeklinde** gerçekleşir +Belgeye özgü ayrıştırma (PDF, metin vb.), bellek arabellekleri yerine dosyalarla çalışır + +Bu, kütüphanenin belge yapısına bağımlı olmamasını sağlar. PDF ayrıştırma, metin +çıkarma ve diğer biçime özgü mantık, ilgili kodlayıcılarda kalır. + +#### İşleme Akışı + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### Kütüphaneci Akış API'si + +Bir akışlı belge alma işlemi ekleyin: + +**`stream-document`** + +İstek: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +Yanıt: Akışlı ikili veri parçaları (tek bir yanıt değil). + +REST API için, bu, `Transfer-Encoding: chunked` ile bir akışlı yanıt döndürür. + +İç hizmetler arası iletişimler (işlemci ile kütüphaneci), şu şekilde olabilir: +İmza yoluyla doğrudan S3 akışı (eğer iç ağ izin veriyorsa) +Hizmet protokolü üzerinden parçalı yanıtlar +Özel bir akış uç noktası + +Temel gereksinim: Veri, kütüphaneci tarafından asla tamamen tamponlanmadan, parçalar halinde akmalıdır. + +#### PDF Kod Çözücü Değişiklikleri + +**Mevcut uygulama** (bellek yoğun): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**Yeni uygulama** (geçici dosya, kademeli): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +Bellek profili: +Geçici dosya diskte: PDF'nin boyutu (disk ucuzdur) +Bellekte: bir seferde bir sayfanın metni +Maksimum bellek: sınırlı, belge boyutundan bağımsız + +#### Metin Belgesi Kod Çözücü Değişiklikleri + +Düz metin belgeleri için, daha da basit - geçici dosyaya ihtiyaç yok: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +Metin belgeleri, geçici bir dosyaya ihtiyaç duymadan doğrudan akış halinde iletilebilir, çünkü bunlar +doğrusal bir yapıya sahiptir. + +#### Akış Tabanlı Parçalama Entegrasyonu + +Parçalayıcı, metin (sayfalar veya paragraflar)den oluşan bir yineleyici alır ve +parçaları kademeli olarak üretir: + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### Uçtan Uca İşlem Hattı + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +Hiçbir noktada, tam belge veya tam çıkarılmış metin bellekte tutulmaz. + +#### Geçici Dosya Hususları + +**Konum:** Sistem geçici dizinini kullanın (`/tmp` veya eşdeğeri). +Sanallaştırılmış dağıtımlar için, geçici dizinin yeterli alana sahip olduğundan ve mümkünse hızlı depolama üzerinde olduğundan emin olun. + + +**Temizleme:** Temizlemenin, istisnalar olsa bile, sağlanması için bağlam yöneticileri (`with tempfile...`) kullanın. + + +**Eşzamanlı işleme:** Her işleme görevi kendi geçici dosyasına sahiptir. +Paralel belge işleme arasında herhangi bir çakışma olmaz. + +**Disk alanı:** Geçici dosyalar, kısa ömürlüdür (işlem süresi boyunca). +500MB'lık bir PDF için, işleme sırasında 500MB geçici alana ihtiyaç vardır. Disk alanı sınırlıysa, boyut sınırı yükleme sırasında uygulanabilir. + + +### Birlikte Çalışan İşlem Arayüzü: Alt Belgeler + +PDF çıkarma ve metin belge işleme, aynı +aşağı akış hattına (parçalayıcı → gömüler → depolama) beslenmelidir. Bunu, tutarlı bir "ID'ye göre alma" arayüzüyle sağlamak için, çıkarılan metin blokları, "librarian"a alt belgeler olarak geri kaydedilir. + + + +#### Alt Belgelerle İşlem Akışı + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +Parçalayıcı, tek bir standart arayüze sahiptir: +Bir belge kimliğini alın (Pulsar aracılığıyla) +Kütüphaneden içeriği akış olarak alın +Bunu parçalara ayırın + +Bu, kimliğin neye atıfta bulunduğunu bilmez veya umursamaz: +Kullanıcı tarafından yüklenen bir metin belgesi +Bir PDF sayfasından çıkarılan bir metin bloğu +Herhangi bir gelecekteki belge türü + +#### Alt Belge Meta Verileri + +Belge şemasını, ana/alt ilişkilerini izlemek için genişletin: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**Belge türleri:** + +| `document_type` | Açıklama | +|-----------------|-------------| +| `source` | Kullanıcı tarafından yüklenen belge (PDF, metin, vb.) | +| `extracted` | Kaynak bir belgeden türetilmiş (örneğin, PDF sayfa metni) | + +**Meta veri alanları:** + +| Alan | Kaynak Belge | Çıkarılan Alt Belge | +|-------|-----------------|-----------------| +| `id` | kullanıcı tarafından sağlanan veya oluşturulan | oluşturulan (örneğin, `{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | ana belge kimliği | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`, vb. | `text/plain` | +| `title` | kullanıcı tarafından sağlanan | oluşturulan (örneğin, "Rapor.pdf'nin 3. sayfası") | +| `user` | kimliği doğrulanmış kullanıcı | ana belge ile aynı | + +#### Alt Belgeler için Kütüphaneci API'si + +**Alt belgeler oluşturma** (içerik, pdf-extractor tarafından kullanılır): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +Küçük boyutlu, çıkarılmış metinler için (tipik bir sayfa metni < 100KB), tek seferlik yükleme kabul edilebilir. Çok büyük metin çıkarımları için, parçalı yükleme kullanılabilir. + +**Alt belgelerin listelenmesi** (hata ayıklama/yönetim için): + + + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +Yanıt: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### Kullanıcı Arayüzü Davranışı + +**`list-documents` varsayılan davranış:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +Yalnızca en üst düzey (kaynak) belgeler, kullanıcının belge listesinde görünür. +Alt belgeler, varsayılan olarak filtrelenir. + +**İsteğe bağlı "çocukları-dahil-et" bayrağı** (yönetici/hata ayıklama için): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### Kaskad Sıralı Silme + +Bir üst belge silindiğinde, tüm alt belgelerin de silinmesi gerekir: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### Depolama Hususları + +Çıkarılan metin blokları, yinelenen içerik oluşturur: +Orijinal PDF, "Garage" (Depo) içinde saklanır. +Her sayfa için çıkarılan metin de "Garage" içinde saklanır. + +Bu denge şunları sağlar: +**Tutarlı bir parçalama arayüzü**: Parçalayıcı her zaman ID'ye göre veri alır. +**Devam ettirme/yeniden deneme**: PDF'i yeniden çıkarmadan, parçalama aşamasında yeniden başlatılabilir. +**Hata ayıklama**: Çıkarılan metin incelenebilir. +**Sorumlulukların ayrılması**: PDF çıkarıcı ve parçalayıcı bağımsız hizmetlerdir. + +200 sayfalık ve sayfa başına ortalama 5KB metin içeren 500MB'lık bir PDF için: +PDF depolama: 500MB +Çıkarılan metin depolama: ~1MB toplam +Ek yük: ihmal edilebilir + +#### PDF Çıkarıcı Çıktısı + +pdf-çıkarıcı, bir belgeyi işledikten sonra: + +1. PDF'i "librarian" (kütüphaneci) üzerinden geçici bir dosyaya aktarır. +2. Metni sayfa sayfa çıkarır. +3. Her sayfa için, çıkarılan metni "librarian" aracılığıyla bir alt belge olarak saklar. +4. Alt belge ID'lerini parçalayıcı kuyruğuna gönderir. +ÇIKTI SÖZLEŞMESİ (tam olarak aşağıdaki formatı takip etmelidir): +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +Parçalayıcı, bu alt kimlikleri alır ve bunları, bir kullanıcının yüklediği bir metin belgesini işlerken olduğu gibi aynı şekilde işler. + +### İstemci Güncellemeleri + +#### Python SDK + + +Python SDK'sı (`trustgraph-base/trustgraph/api/library.py`), parçalı yüklemeleri şeffaf bir şekilde işlemelidir. Kamu arayüzü değişmeden kalır: + + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +İçeride, SDK belge boyutunu algılar ve stratejiyi değiştirir: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**İlerleme geri bildirimleri** (isteğe bağlı iyileştirme): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +Bu, kullanıcı arayüzlerinin temel API'yi değiştirmeden yükleme ilerlemesini görüntülemesini sağlar. + +#### Komut Satırı Araçları + +**`tg-add-library-document`** değişmeden çalışmaya devam ediyor: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +İsteğe bağlı bir ilerleme durumu göstergesi eklenebilir: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**Eski araçlar kaldırıldı:** + +`tg-load-pdf` - kullanımdan kaldırıldı, `tg-add-library-document`'i kullanın. +`tg-load-text` - kullanımdan kaldırıldı, `tg-add-library-document`'i kullanın. + +**Yönetici/hata ayıklama komutları** (isteğe bağlı, düşük öncelikli): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +Bunlar, ayrı araçlar yerine mevcut komuttaki bayraklar olabilir. + +#### API Özellik Güncellemeleri + +OpenAPI spesifikasyonu (`specs/api/paths/librarian.yaml`), aşağıdaki güncellemeleri gerektiriyor: + +**Yeni işlemler:** + +`begin-upload` - Parçalı yükleme oturumunu başlat +`upload-chunk` - Tek bir parçayı yükle +`complete-upload` - Yüklemeyi tamamla +`abort-upload` - Yüklemeyi iptal et +`get-upload-status` - Yükleme ilerlemesini sorgula +`list-uploads` - Kullanıcı için tamamlanmamış yüklemeleri listele +`stream-document` - Akışlı belge alma +`add-child-document` - Çıkarılan metni kaydet (iç) +`list-children` - Alt belgeleri listele (yönetici) + +**Değiştirilen işlemler:** + +`list-documents` - `include-children` parametresini ekle + +**Yeni şemalar:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**WebSocket spesifikasyonunda yapılan güncellemeler** (`specs/websocket/`): + +WebSocket istemcileri için REST işlemlerini yansıtın, böylece yükleme sırasında gerçek zamanlı +ilerleme güncellemeleri sağlanır. + +#### Kullanıcı Deneyimi Hususları + +API spesifikasyonundaki güncellemeler, ön yüzdeki iyileştirmelere olanak tanır: + +**Yükleme ilerleme arayüzü:** +Yüklenen parçaları gösteren ilerleme çubuğu +Kalan tahmini süre +Duraklatma/devam ettirme özelliği + +**Hata kurtarma:** +Kesintiye uğramış yüklemeler için "Yüklemeyi devam ettir" seçeneği +Yeniden bağlanırken bekleyen yüklemelerin listesi + +**Büyük dosya işleme:** +İstemci tarafında dosya boyutu tespiti +Büyük dosyalar için otomatik parçalı yükleme +Uzun yüklemeler sırasında net geri bildirim + +Bu kullanıcı deneyimi iyileştirmeleri, güncellenmiş API spesifikasyonu tarafından yönlendirilen ön yüz işleme gerektirir. diff --git a/docs/tech-specs/large-document-loading.zh-cn.md b/docs/tech-specs/large-document-loading.zh-cn.md new file mode 100644 index 00000000..20e29c4d --- /dev/null +++ b/docs/tech-specs/large-document-loading.zh-cn.md @@ -0,0 +1,992 @@ +--- +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. **大型 PDF 处理**: 在不耗尽内存的情况下,上传和处理数百兆字节的 PDF 文件。 + +2. **可恢复的上传**: 允许中断的上传从中断的地方继续,而不是重新开始。 + +3. **进度反馈**: 向用户提供有关上传和处理进度的实时可见性。 + +4. **内存高效处理**: 以流式方式处理文档,而无需将整个文件保存在内存中。 + + + ## 目标 + + +**增量上传**: 支持通过 REST 和 WebSocket 进行分块文档上传。 +**可恢复传输**: 启用从中断的上传中恢复。 +**进度可见性**: 向客户端提供上传/处理进度反馈。 +**内存效率**: 消除整个管道中的完整文档缓冲。 +**向后兼容性**: 现有的小型文档工作流程保持不变。 +**流式处理**: PDF 解码和文本分块操作在流上进行。 + +## 背景 + + +### 当前架构 + +文档提交流程如下: + +1. **客户端** 通过 REST (`POST /api/v1/librarian`) 或 WebSocket 提交文档。 +2. **API 网关** 接收包含 base64 编码的文档内容的完整请求。 +3. **LibrarianRequestor** 将请求转换为 Pulsar 消息。 +4. **Librarian 服务** 接收消息,将文档解码到内存中。 +5. **BlobStore** 将文档上传到 Garage/S3。 +6. **Cassandra** 存储包含对象引用的元数据。 +7. 为了处理:从 S3 中检索文档,解码,分块——所有都在内存中。 + +关键文件: +REST/WebSocket 入口:`trustgraph-flow/trustgraph/gateway/service.py` +Librarian 核心:`trustgraph-flow/trustgraph/librarian/librarian.py` +Blob 存储:`trustgraph-flow/trustgraph/librarian/blob_store.py` +Cassandra 表:`trustgraph-flow/trustgraph/tables/library.py` +API 模式:`trustgraph-base/trustgraph/schema/services/library.py` + +### 当前限制 + +当前设计存在几个相互影响的内存和用户体验问题: + +1. **原子上传操作**: 整个文档必须在一个请求中传输。 + 大型文档需要长时间运行的请求,并且在连接失败时没有进度指示和重试机制。 + + +2. **API 设计**: 无论是 REST 还是 WebSocket API,都期望在单个消息中接收完整的文档。 + 模式 (`LibrarianRequest`) 包含一个 `content` 字段,其中包含整个 base64 编码的文档。 + + +3. **Librarian 内存**: librarian 服务在将文档上传到 S3 之前,将其完全解码到内存中。 + 对于一个 500MB 的 PDF 文件,这意味着需要在进程内存中保留 500MB+。 + + +4. **PDF 解码器内存**: 当处理开始时,PDF 解码器将整个 PDF 文件加载到内存中以提取文本。 + PyPDF 和类似的库通常需要访问整个文档。 + + +5. **分块器内存**: 文本分块器接收完整的提取文本,并在生成块时将其保存在内存中。 + + +**内存影响示例** (500MB PDF): +网关:~700MB (base64 编码开销) +Librarian:~500MB (解码后的字节) +PDF 解码器:~500MB + 提取缓冲区 +分块器:提取的文本 (可变,可能高达 100MB+) + +对于单个大型文档,峰值内存总和可能超过 2GB。 + +## 技术设计 + +### 设计原则 + +1. **API 接口**: 所有客户端交互都通过 librarian API 进行。客户端 + 没有直接访问或了解底层 S3/Garage 存储的权限。 + +2. **S3 多部分上传**: 使用标准的 S3 多部分上传。 + 这在所有兼容 S3 的系统中都得到广泛支持 (AWS S3, MinIO, Garage, + Ceph, DigitalOcean Spaces, Backblaze B2 等),确保可移植性。 + +3. **原子完成**: S3 多部分上传本质上是原子的 - 上传的 + 部分在调用 `CompleteMultipartUpload` 之前是不可见的。不需要临时 + 文件或重命名操作。 + +4. **可跟踪的状态**: 上传会话在 Cassandra 中跟踪,从而 + 提供对未完成上传的可见性,并启用恢复功能。 + +### 分块上传流程 + +``` +Client Librarian API S3/Garage + │ │ │ + │── begin-upload ───────────►│ │ + │ (metadata, size) │── CreateMultipartUpload ────►│ + │ │◄── s3_upload_id ─────────────│ + │◄── upload_id ──────────────│ (store session in │ + │ │ Cassandra) │ + │ │ │ + │── upload-chunk ───────────►│ │ + │ (upload_id, index, data) │── UploadPart ───────────────►│ + │ │◄── etag ─────────────────────│ + │◄── ack + progress ─────────│ (store etag in session) │ + │ ⋮ │ ⋮ │ + │ (repeat for all chunks) │ │ + │ │ │ + │── complete-upload ────────►│ │ + │ (upload_id) │── CompleteMultipartUpload ──►│ + │ │ (parts coalesced by S3) │ + │ │── store doc metadata ───────►│ Cassandra + │◄── document_id ────────────│ (delete session) │ +``` + +客户端从不直接与 S3 交互。 库(librarian)在内部将我们的分块上传 API 转换为 S3 的多部分操作。 + +### Librarian API 操作 +### 图书管理员API操作 + +#### `begin-upload` + +初始化一个分块上传会话。 + +请求: +```json +{ + "operation": "begin-upload", + "document-metadata": { + "id": "doc-123", + "kind": "application/pdf", + "title": "Large Document", + "user": "user-id", + "tags": ["tag1", "tag2"] + }, + "total-size": 524288000, + "chunk-size": 5242880 +} +``` + +响应: +```json +{ + "upload-id": "upload-abc-123", + "chunk-size": 5242880, + "total-chunks": 100 +} +``` + +馆员: +1. 生成一个唯一的 `upload_id` 和 `object_id` (用于对象存储的 UUID) +2. 调用 S3 `CreateMultipartUpload`,接收 `s3_upload_id` +3. 在 Cassandra 中创建会话记录 +4. 将 `upload_id` 返回给客户端 + +#### `upload-chunk` + +上传单个分块。 + +请求: +```json +{ + "operation": "upload-chunk", + "upload-id": "upload-abc-123", + "chunk-index": 0, + "content": "" +} +``` + +响应: +```json +{ + "upload-id": "upload-abc-123", + "chunk-index": 0, + "chunks-received": 1, + "total-chunks": 100, + "bytes-received": 5242880, + "total-bytes": 524288000 +} +``` + +馆员: +1. 通过 `upload_id` 查找会话。 +2. 验证所有权(用户必须与会话创建者匹配)。 +3. 使用块数据调用 S3 `UploadPart`,接收 `etag`。 +4. 使用块索引和 etag 更新会话记录。 +5. 将进度返回给客户端。 + +失败的块可以重试 - 只需要再次发送相同的 `chunk-index`。 + +#### `complete-upload` + +完成上传并创建文档。 + +请求: +```json +{ + "operation": "complete-upload", + "upload-id": "upload-abc-123" +} +``` + +响应: +```json +{ + "document-id": "doc-123", + "object-id": "550e8400-e29b-41d4-a716-446655440000" +} +``` + +馆员: +1. 查找会话,验证是否接收到所有分块。 +2. 使用 part etags 调用 S3 `CompleteMultipartUpload` (S3 内部合并分块,馆员无需消耗内存)。 + 3. 在 Cassandra 中创建文档记录,包含元数据和对象引用。 +4. 删除上传会话记录。 +5. 将文档 ID 返回给客户端。 + + +#### `abort-upload` + +取消正在进行的上传。 + +请求: +```json +{ + "operation": "abort-upload", + "upload-id": "upload-abc-123" +} +``` + +馆员: +1. 调用 S3 `AbortMultipartUpload` 清理部分数据。 +2. 从 Cassandra 中删除会话记录。 + +#### `get-upload-status` + +查询上传状态(用于断点续传功能)。 + +请求: +```json +{ + "operation": "get-upload-status", + "upload-id": "upload-abc-123" +} +``` + +响应: +```json +{ + "upload-id": "upload-abc-123", + "state": "in-progress", + "chunks-received": [0, 1, 2, 5, 6], + "missing-chunks": [3, 4, 7, 8], + "total-chunks": 100, + "bytes-received": 36700160, + "total-bytes": 524288000 +} +``` + +#### `list-uploads` + +获取用户未完成上传的列表。 + +请求: +```json +{ + "operation": "list-uploads" +} +``` + +响应: +```json +{ + "uploads": [ + { + "upload-id": "upload-abc-123", + "document-metadata": { "title": "Large Document", ... }, + "progress": { "chunks-received": 43, "total-chunks": 100 }, + "created-at": "2024-01-15T10:30:00Z" + } + ] +} +``` + +### 上传会话存储 + +在 Cassandra 中跟踪正在进行的上传: + +```sql +CREATE TABLE upload_session ( + upload_id text PRIMARY KEY, + user text, + document_id text, + document_metadata text, -- JSON: title, kind, tags, comments, etc. + s3_upload_id text, -- internal, for S3 operations + object_id uuid, -- target blob ID + total_size bigint, + chunk_size int, + total_chunks int, + chunks_received map, -- chunk_index → etag + created_at timestamp, + updated_at timestamp +) WITH default_time_to_live = 86400; -- 24 hour TTL + +CREATE INDEX upload_session_user ON upload_session (user); +``` + +**TTL 行为:** +如果未完成,会话将在 24 小时后过期。 +当 Cassandra TTL 过期时,会话记录将被删除。 +孤立的 S3 分片由 S3 生命周期策略清理(在桶上配置)。 + +### 故障处理和原子性 + +**分块上传失败:** +客户端重试失败的分块(使用相同的 `upload_id` 和 `chunk-index`)。 +S3 `UploadPart` 对于相同的分片编号是幂等的。 +会话跟踪哪些分块已成功。 + +**客户端在上传过程中断连接:** +会话仍然存在于 Cassandra 中,记录了已接收的分块。 +客户端可以调用 `get-upload-status` 以查看缺少的内容。 +通过仅上传缺失的分块来恢复,然后调用 `complete-upload`。 + +**完整上传失败:** +S3 `CompleteMultipartUpload` 是原子性的 - 要么完全成功,要么完全失败。 +如果失败,分片仍然存在,客户端可以重试 `complete-upload`。 +永远不会出现部分文档。 + +**会话过期:** +Cassandra TTL 在 24 小时后删除会话记录。 +S3 桶生命周期策略清理不完整的多部分上传。 +不需要手动清理。 + +### S3 多部分原子性 + +S3 多部分上传提供了内置的原子性: + +1. **分片不可见:** 上传的分片不能作为对象访问。 + 它们仅作为不完整的多部分上传的分片存在。 + +2. **原子完成:** `CompleteMultipartUpload` 要么成功(对象 + 以原子方式出现),要么失败(未创建对象)。 没有部分状态。 + +3. **无需重命名:** 最终对象键在 + `CreateMultipartUpload` 时指定。 分片直接合并到该键。 + +4. **服务器端合并:** S3 内部合并分片。 库管理员 + 永远不会读取分片 - 无论文档大小如何,都没有内存开销。 + +### BlobStore 扩展 + +**文件:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +添加多部分上传方法: + +```python +class BlobStore: + # Existing methods... + + def create_multipart_upload(self, object_id: UUID, kind: str) -> str: + """Initialize multipart upload, return s3_upload_id.""" + # minio client: create_multipart_upload() + + def upload_part( + self, object_id: UUID, s3_upload_id: str, + part_number: int, data: bytes + ) -> str: + """Upload a single part, return etag.""" + # minio client: upload_part() + # Note: S3 part numbers are 1-indexed + + def complete_multipart_upload( + self, object_id: UUID, s3_upload_id: str, + parts: List[Tuple[int, str]] # [(part_number, etag), ...] + ) -> None: + """Finalize multipart upload.""" + # minio client: complete_multipart_upload() + + def abort_multipart_upload( + self, object_id: UUID, s3_upload_id: str + ) -> None: + """Cancel multipart upload, clean up parts.""" + # minio client: abort_multipart_upload() +``` + +### 分块大小的考量 + +**S3 最小值**: 每个分块 5MB (除了最后一个分块) +**S3 最大值**: 每个上传 10,000 个分块 +**实际默认值**: 5MB 分块 + 500MB 文档 = 100 个分块 + 5GB 文档 = 1,000 个分块 +**进度粒度**: 较小的分块 = 更精细的进度更新 +**网络效率**: 较大的分块 = 更少的网络请求 + +分块大小可以在一定范围内由客户端配置 (5MB - 100MB)。 + +### 文档处理:流式检索 + +上传流程旨在高效地将文档存储到存储系统中。处理流程旨在提取和分块文档,而无需将整个文档加载到内存中。 + + + +#### 设计原则:标识符,而非内容 + +目前,当触发处理时,文档内容通过 Pulsar 消息传递。这会将整个文档加载到内存中。 应该这样做: + + +Pulsar 消息仅携带 **文档标识符** +处理程序直接从 librarian 获取文档内容 +获取过程是 **流式传输到临时文件** +文档特定的解析 (PDF、文本等) 使用文件,而不是内存缓冲区 + +这使得 librarian 不依赖于文档结构。 PDF 解析、文本 +提取和其他特定于格式的逻辑保留在各自的解码器中。 + +#### 处理流程 + +``` +Pulsar PDF Decoder Librarian S3 + │ │ │ │ + │── doc-id ───────────►│ │ │ + │ (processing msg) │ │ │ + │ │ │ │ + │ │── stream-document ──────►│ │ + │ │ (doc-id) │── GetObject ────►│ + │ │ │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (write to temp file) │ │ + │ │◄── chunk ────────────────│◄── stream ───────│ + │ │ (append to temp file) │ │ + │ │ ⋮ │ ⋮ │ + │ │◄── EOF ──────────────────│ │ + │ │ │ │ + │ │ ┌──────────────────────────┐ │ + │ │ │ temp file on disk │ │ + │ │ │ (memory stays bounded) │ │ + │ │ └────────────┬─────────────┘ │ + │ │ │ │ + │ │ PDF library opens file │ + │ │ extract page 1 text ──► chunker │ + │ │ extract page 2 text ──► chunker │ + │ │ ⋮ │ + │ │ close file │ + │ │ delete temp file │ +``` + +#### 图书管理员流式 API + +添加一个流式文档检索操作: + +**`stream-document`** + +请求: +```json +{ + "operation": "stream-document", + "document-id": "doc-123" +} +``` + +响应:流式传输的二进制数据块(不是单个响应)。 + +对于 REST API,这会返回一个带有 `Transfer-Encoding: chunked` 的流式响应。 + +对于内部服务之间的调用(处理器到图书管理员),可能如下: +通过预签名 URL 进行直接 S3 流式传输(如果内部网络允许)。 +通过服务协议进行分块响应。 +一个专用的流式传输端点。 + +关键要求:数据以块的形式流动,永远不会完全缓存在图书管理员中。 + +#### PDF 解码器更改 + +**当前实现**(占用大量内存): + +```python +def decode_pdf(document_content: bytes) -> str: + reader = PdfReader(BytesIO(document_content)) # full doc in memory + text = "" + for page in reader.pages: + text += page.extract_text() # accumulating + return text # full text in memory +``` + +**新实现** (临时文件,增量式): + +```python +def decode_pdf_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield extracted text page by page.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream document to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Open PDF from file (not memory) + reader = PdfReader(tmp.name) + + # Yield pages incrementally + for page in reader.pages: + yield page.extract_text() + + # tmp file auto-deleted on context exit +``` + +内存配置: +临时文件在磁盘上:大小为 PDF 文件的大小(磁盘很便宜) +内存中:一次加载一页的文本 +峰值内存:受限,与文档大小无关 + +#### 文本文档解码器更改 + +对于纯文本文档,更加简单 - 不需要临时文件: + +```python +def decode_text_streaming(doc_id: str, librarian_client) -> Iterator[str]: + """Yield text in chunks as it streams from storage.""" + + buffer = "" + for chunk in librarian_client.stream_document(doc_id): + buffer += chunk.decode('utf-8') + + # Yield complete lines/paragraphs as they arrive + while '\n\n' in buffer: + paragraph, buffer = buffer.split('\n\n', 1) + yield paragraph + '\n\n' + + # Yield remaining buffer + if buffer: + yield buffer +``` + +文本文件可以直接流式传输,无需临时文件,因为它们的结构是线性的。 + + +#### 流式分块集成 + +分块器接收文本的迭代器(页面或段落),并逐步生成块: + + +```python +class StreamingChunker: + def __init__(self, chunk_size: int, overlap: int): + self.chunk_size = chunk_size + self.overlap = overlap + + def process(self, text_stream: Iterator[str]) -> Iterator[str]: + """Yield chunks as text arrives.""" + buffer = "" + + for text_segment in text_stream: + buffer += text_segment + + while len(buffer) >= self.chunk_size: + chunk = buffer[:self.chunk_size] + yield chunk + # Keep overlap for context continuity + buffer = buffer[self.chunk_size - self.overlap:] + + # Yield remaining buffer as final chunk + if buffer.strip(): + yield buffer +``` + +#### 端到端处理流程 + +```python +async def process_document(doc_id: str, librarian_client, embedder): + """Process document with bounded memory.""" + + # Get document metadata to determine type + metadata = await librarian_client.get_document_metadata(doc_id) + + # Select decoder based on document type + if metadata.kind == 'application/pdf': + text_stream = decode_pdf_streaming(doc_id, librarian_client) + elif metadata.kind == 'text/plain': + text_stream = decode_text_streaming(doc_id, librarian_client) + else: + raise UnsupportedDocumentType(metadata.kind) + + # Chunk incrementally + chunker = StreamingChunker(chunk_size=1000, overlap=100) + + # Process each chunk as it's produced + for chunk in chunker.process(text_stream): + # Generate embeddings, store in vector DB, etc. + embedding = await embedder.embed(chunk) + await store_chunk(doc_id, chunk, embedding) +``` + +在任何时候,完整的文档或完整的提取文本都不会保存在内存中。 + +#### 临时文件注意事项 + +**位置:** 使用系统临时目录(`/tmp` 或等效目录)。对于 +容器化部署,请确保临时目录有足够的空间,并且位于快速存储上(如果可能,不要使用网络挂载)。 + + +**清理:** 使用上下文管理器(`with tempfile...`)以确保即使在出现异常时也能进行清理。 + + +**并发处理:** 每个处理任务都有自己的临时文件。 +并行文档处理之间不会发生冲突。 + +**磁盘空间:** 临时文件是短暂存在的(处理过程中的持续时间)。 +对于一个 500MB 的 PDF 文件,在处理过程中需要 500MB 的临时空间。如果磁盘空间受限,可以在上传时强制执行大小限制。 + + +### 统一处理接口:子文档 + +PDF 提取和文本文档处理需要输入到相同的下游流程(分块 → 嵌入 → 存储)。为了实现这一点,并使用一致的“按 ID 检索”接口,提取的文本块被存储回 librarian,作为子文档。 + + + + +#### 使用子文档的处理流程 + +``` +PDF Document Text Document + │ │ + ▼ │ +pdf-extractor │ + │ │ + │ (stream PDF from librarian) │ + │ (extract page 1 text) │ + │ (store as child doc → librarian) │ + │ (extract page 2 text) │ + │ (store as child doc → librarian) │ + │ ⋮ │ + ▼ ▼ +[child-doc-id, child-doc-id, ...] [doc-id] + │ │ + └─────────────────────┬───────────────────────────────┘ + ▼ + chunker + │ + │ (receives document ID) + │ (streams content from librarian) + │ (chunks incrementally) + ▼ + [chunks → embedding → storage] +``` + +分块器具有一个统一的接口: +接收文档 ID(通过 Pulsar) +从 Librarian 流式传输内容 +将其分块 + +它不知道也不关心该 ID 指的是: +用户上传的文本文档 +从 PDF 页面提取的文本块 +任何未来的文档类型 + +#### 子文档元数据 + +扩展文档模式以跟踪父/子关系: + +```sql +-- Add columns to document table +ALTER TABLE document ADD parent_id text; +ALTER TABLE document ADD document_type text; + +-- Index for finding children of a parent +CREATE INDEX document_parent ON document (parent_id); +``` + +**文档类型:** + +| `document_type` | 描述 | +|-----------------|-------------| +| `source` | 用户上传的文档(PDF、文本等) | +| `extracted` | 源自源文档(例如,PDF 页面文本) | + +**元数据字段:** + +| 字段 | 源文档 | 提取的子文档 | +|-------|-----------------|-----------------| +| `id` | 用户提供或生成 | 生成(例如,`{parent-id}-page-{n}`) | +| `parent_id` | `NULL` | 父文档 ID | +| `document_type` | `source` | `extracted` | +| `kind` | `application/pdf`,等等 | `text/plain` | +| `title` | 用户提供 | 生成(例如,“Report.pdf 的第 3 页”) | +| `user` | 经过身份验证的用户 | 与父文档相同 | + +#### 子文档的 Librarian API + +**创建子文档**(内部,由 pdf-extractor 使用): + +```json +{ + "operation": "add-child-document", + "parent-id": "doc-123", + "document-metadata": { + "id": "doc-123-page-1", + "kind": "text/plain", + "title": "Page 1" + }, + "content": "" +} +``` + +对于较小的提取文本(典型页面文本通常小于 100KB),单次上传是可以接受的。对于非常大的文本提取,可以使用分块上传。 + + + +**列出子文档(用于调试/管理):** + +```json +{ + "operation": "list-children", + "parent-id": "doc-123" +} +``` + +响应: +```json +{ + "children": [ + { "id": "doc-123-page-1", "title": "Page 1", "kind": "text/plain" }, + { "id": "doc-123-page-2", "title": "Page 2", "kind": "text/plain" }, + ... + ] +} +``` + +#### 用户可见的行为 + +**`list-documents` 默认行为:** + +```sql +SELECT * FROM document WHERE user = ? AND parent_id IS NULL; +``` + +只有顶层(源)文档才会出现在用户的文档列表中。 +子文档默认会被过滤掉。 + +**可选的包含子文档标志**(用于管理员/调试): + +```json +{ + "operation": "list-documents", + "include-children": true +} +``` + +#### 级联删除 + +当父级文档被删除时,所有子级必须被删除: + +```python +def delete_document(doc_id: str): + # Find all children + children = query("SELECT id, object_id FROM document WHERE parent_id = ?", doc_id) + + # Delete child blobs from S3 + for child in children: + blob_store.delete(child.object_id) + + # Delete child metadata from Cassandra + execute("DELETE FROM document WHERE parent_id = ?", doc_id) + + # Delete parent blob and metadata + parent = get_document(doc_id) + blob_store.delete(parent.object_id) + execute("DELETE FROM document WHERE id = ? AND user = ?", doc_id, user) +``` + +#### 存储注意事项 + +提取的文本块会重复内容: +原始 PDF 文件存储在 Garage 中 +每个页面的提取文本也存储在 Garage 中 + +这种权衡方案可以实现: +**统一的分块接口**: 分块器始终通过 ID 获取数据 +**恢复/重试**: 可以在分块阶段重新启动,而无需重新提取 PDF +**调试**: 可以检查提取的文本 +**职责分离**: PDF 提取器和分块器是独立的服务 + +对于一个 500MB 的 PDF 文件,其中包含 200 页,平均每页 5KB 的文本: +PDF 存储:500MB +提取的文本存储:约 1MB +额外开销:可以忽略不计 + +#### PDF 提取器输出 + +PDF 提取器在处理文档后: + +1. 从 librarian 流式传输 PDF 到临时文件 +2. 逐页提取文本 +3. 对于每一页,将提取的文本作为子文档通过 librarian 存储 +4. 将子文档 ID 发送到分块器队列 + +```python +async def extract_pdf(doc_id: str, librarian_client, output_queue): + """Extract PDF pages and store as child documents.""" + + with tempfile.NamedTemporaryFile(delete=True, suffix='.pdf') as tmp: + # Stream PDF to temp file + for chunk in librarian_client.stream_document(doc_id): + tmp.write(chunk) + tmp.flush() + + # Extract pages + reader = PdfReader(tmp.name) + for page_num, page in enumerate(reader.pages, start=1): + text = page.extract_text() + + # Store as child document + child_id = f"{doc_id}-page-{page_num}" + await librarian_client.add_child_document( + parent_id=doc_id, + document_id=child_id, + kind="text/plain", + title=f"Page {page_num}", + content=text.encode('utf-8') + ) + + # Send to chunker queue + await output_queue.send(child_id) +``` + +分块器接收这些子 ID,并以与处理用户上传的文本文档完全相同的方式处理它们。 +如何处理用户上传的文本文档。 + +### 客户端更新 + +#### Python SDK + +Python SDK (`trustgraph-base/trustgraph/api/library.py`) 应该能够透明地处理分块上传。公共接口保持不变: +分块上传。公共接口保持不变: + +```python +# Existing interface - no change for users +library.add_document( + id="doc-123", + title="Large Report", + kind="application/pdf", + content=large_pdf_bytes, # Can be hundreds of MB + tags=["reports"] +) +``` + +内部,SDK 会检测文档大小并切换策略: + +```python +class Library: + CHUNKED_UPLOAD_THRESHOLD = 2 * 1024 * 1024 # 2MB + + def add_document(self, id, title, kind, content, tags=None, ...): + if len(content) < self.CHUNKED_UPLOAD_THRESHOLD: + # Small document: single operation (existing behavior) + return self._add_document_single(id, title, kind, content, tags) + else: + # Large document: chunked upload + return self._add_document_chunked(id, title, kind, content, tags) + + def _add_document_chunked(self, id, title, kind, content, tags): + # 1. begin-upload + session = self._begin_upload( + document_metadata={...}, + total_size=len(content), + chunk_size=5 * 1024 * 1024 + ) + + # 2. upload-chunk for each chunk + for i, chunk in enumerate(self._chunk_bytes(content, session.chunk_size)): + self._upload_chunk(session.upload_id, i, chunk) + + # 3. complete-upload + return self._complete_upload(session.upload_id) +``` + +**进度回调** (可选的增强功能): + +```python +def add_document(self, ..., on_progress=None): + """ + on_progress: Optional callback(bytes_sent, total_bytes) + """ +``` + +这允许用户界面显示上传进度,而无需更改基本 API。 + +#### 命令行工具 + +**`tg-add-library-document`** 保持不变: + +```bash +# Works transparently for any size - SDK handles chunking internally +tg-add-library-document --file large-report.pdf --title "Large Report" +``` + +可以添加可选的进度显示: + +```bash +tg-add-library-document --file large-report.pdf --title "Large Report" --progress +# Output: +# Uploading: 45% (225MB / 500MB) +``` + +**已移除的旧工具:** + +`tg-load-pdf` - 已过时,请使用 `tg-add-library-document` +`tg-load-text` - 已过时,请使用 `tg-add-library-document` + +**管理员/调试命令**(可选,优先级较低): + +```bash +# List incomplete uploads (admin troubleshooting) +tg-add-library-document --list-pending + +# Resume specific upload (recovery scenario) +tg-add-library-document --resume upload-abc-123 --file large-report.pdf +``` + +这些可能只是现有命令上的标志,而不是单独的工具。 + +#### API 规范更新 + +OpenAPI 规范 (`specs/api/paths/librarian.yaml`) 需要更新以下内容: + +**新操作:** + +`begin-upload` - 初始化分块上传会话 +`upload-chunk` - 上传单个分块 +`complete-upload` - 完成上传 +`abort-upload` - 取消上传 +`get-upload-status` - 查询上传进度 +`list-uploads` - 列出用户未完成的上传 +`stream-document` - 流式文档检索 +`add-child-document` - 存储提取的文本(内部) +`list-children` - 列出子文档(管理员) + +**修改后的操作:** + +`list-documents` - 添加 `include-children` 参数 + +**新的模式:** + +`ChunkedUploadBeginRequest` +`ChunkedUploadBeginResponse` +`ChunkedUploadChunkRequest` +`ChunkedUploadChunkResponse` +`UploadSession` +`UploadProgress` + +**WebSocket 规范更新** (`specs/websocket/`): + +镜像 REST 操作以供 WebSocket 客户端使用,从而实现上传过程的实时 +进度更新。 + +#### 用户体验注意事项 + +API 规范的更新可以实现前端改进: + +**上传进度 UI:** +显示已上传分块的进度条 +剩余预估时间 +暂停/恢复功能 + +**错误恢复:** +中断的上传可以选择“恢复上传” +重新连接时,显示挂起的上传列表 + +**大型文件处理:** +客户端文件大小检测 +大型文件的自动分块上传 +长时间上传时提供清晰的反馈 + +这些用户体验改进需要前端工作,并由更新后的 API 规范提供指导。 diff --git a/docs/tech-specs/logging-strategy.ar.md b/docs/tech-specs/logging-strategy.ar.md new file mode 100644 index 00000000..055e625c --- /dev/null +++ b/docs/tech-specs/logging-strategy.ar.md @@ -0,0 +1,358 @@ +--- +layout: default +title: "استراتيجية تسجيل الأحداث في TrustGraph" +parent: "Arabic (Beta)" +--- + +# استراتيجية تسجيل الأحداث في TrustGraph + +> **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 الوحدة `logging` المضمنة في Python لجميع عمليات التسجيل، مع تكوين مركزي ودمج اختياري مع Loki لتجميع السجلات. يوفر هذا نهجًا موحدًا ومرنًا لتسجيل الأحداث عبر جميع مكونات النظام. + +## التكوين الافتراضي + +### مستوى التسجيل +**المستوى الافتراضي**: `INFO` +**يمكن تكوينه عبر**: وسيط سطر الأوامر `--log-level` +**الخيارات**: `DEBUG`، `INFO`، `WARNING`، `ERROR`، `CRITICAL` + +### وجهات الإخراج +1. **وحدة التحكم (stdout)**: مفعل دائمًا - يضمن التوافق مع البيئات الحاويات. +2. **Loki**: تجميع سجلات مركزي اختياري (مفعل افتراضيًا، ويمكن تعطيله). + +## وحدة التسجيل المركزية + +تتم إدارة جميع تكوينات التسجيل بواسطة الوحدة `trustgraph.base.logging`، والتي توفر: +`add_logging_args(parser)` - يضيف وسيطات سطر الأوامر القياسية لتسجيل الأحداث. +`setup_logging(args)` - يقوم بتكوين التسجيل من الوسائط التي تم تحليلها. + +يتم استخدام هذا الوحدة بواسطة جميع المكونات من جانب الخادم: +الخدمات القائمة على AsyncProcessor +بوابة API +خادم MCP + +## إرشادات التنفيذ + +### 1. تهيئة المسجل + +يجب على كل وحدة إنشاء مسجل خاص بها باستخدام وحدة `__name__` الخاصة بالوحدة: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +اسم المسجل يُستخدم تلقائيًا كعلامة في Loki لتصفية البحث. + +### 2. تهيئة الخدمة + +تتلقى جميع الخدمات من جهة الخادم تلقائيًا تكوين التسجيل من خلال الوحدة المركزية: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Add standard logging arguments (includes Loki configuration) + add_logging_args(parser) + + # Add your service-specific arguments + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Setup logging early in startup + setup_logging(args) + + # Rest of your service initialization + logger = logging.getLogger(__name__) + logger.info("Service starting...") +``` + +### 3. وسيطات سطر الأوامر + +تدعم جميع الخدمات وسيطات التسجيل التالية: + +**مستوى التسجيل:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**تكوين لوكي:** +```bash +--loki-enabled # Enable Loki (default) +--no-loki-enabled # Disable Loki +--loki-url URL # Loki push URL (default: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Optional authentication +--loki-password PASSWORD # Optional authentication +``` + +**أمثلة:** +```bash +# Default - INFO level, Loki enabled +./my-service + +# Debug mode, console only +./my-service --log-level DEBUG --no-loki-enabled + +# Custom Loki server with auth +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. متغيرات البيئة + +تدعم إعدادات Loki استخدام متغيرات البيئة كبدائل: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +تتجاوز وسائط سطر الأوامر قيم المتغيرات البيئية. + +### 5. أفضل الممارسات في التسجيل. + +#### استخدام مستويات التسجيل. +**DEBUG**: معلومات تفصيلية لتشخيص المشكلات (قيم المتغيرات، دخول/خروج الدالة). +**INFO**: رسائل معلومات عامة (بدء الخدمة، تحميل التكوين، مراحل المعالجة). +**WARNING**: رسائل تحذيرية لحالات قد تكون ضارة (ميزات مهملة، أخطاء قابلة للاسترداد). +**ERROR**: رسائل خطأ للمشاكل الخطيرة (عمليات فاشلة، استثناءات). +**CRITICAL**: رسائل حرجة لأعطال النظام التي تتطلب اهتمامًا فوريًا. + +#### تنسيق الرسالة. +```python +# Good - includes context +logger.info(f"Processing document: {doc_id}, size: {doc_size} bytes") +logger.error(f"Failed to connect to database: {error}", exc_info=True) + +# Avoid - lacks context +logger.info("Processing document") +logger.error("Connection failed") +``` + +#### اعتبارات الأداء +```python +# Use lazy formatting for expensive operations +logger.debug("Expensive operation result: %s", expensive_function()) + +# Check log level for very expensive debug operations +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Debug data: {debug_data}") +``` + +### 6. التسجيل المنظم باستخدام لوكي + +بالنسبة للبيانات المعقدة، استخدم التسجيل المنظم مع علامات إضافية لـ Loki: + +```python +logger.info("Request processed", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +تصبح هذه العلامات تصنيفات قابلة للبحث في Loki، بالإضافة إلى التصنيفات التلقائية: +`severity` - مستوى التسجيل (DEBUG، INFO، WARNING، ERROR، CRITICAL) +`logger` - اسم الوحدة (من `__name__`) + +### 7. تسجيل الاستثناءات + +قم دائمًا بتضمين تتبعات المكدس للاستثناءات: + +```python +try: + process_data() +except Exception as e: + logger.error(f"Failed to process data: {e}", exc_info=True) + raise +``` + +### 8. اعتبارات التسجيل غير المتزامن + +يستخدم نظام التسجيل معالجات غير متزامنة ومخزنة مؤقتًا لـ Loki: +الإخراج إلى وحدة التحكم متزامن (سريع) +يتم تخزين إخراج Loki في قائمة انتظار مع مخزن مؤقت مكون من 500 رسالة +يقوم خيط الخلفية بمعالجة إرسال Loki +لا يوجد حظر لرمز التطبيق الرئيسي + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # Logging is thread-safe and won't block async operations + logger.info(f"Starting async operation in task: {asyncio.current_task().get_name()}") +``` + +## التكامل مع Loki + +### البنية التحتية + +يستخدم نظام التسجيل وظائف `QueueHandler` و `QueueListener` المضمنة في Python للتكامل غير المتزامن مع Loki: + +1. **QueueHandler**: يتم وضع السجلات في قائمة انتظار تحتوي على 500 رسالة (غير متزامنة). +2. **Background Thread**: يرسل QueueListener السجلات إلى Loki بشكل غير متزامن. +3. **Graceful Degradation**: إذا كان Loki غير متاح، يستمر التسجيل في وحدة التحكم. + +### التسميات التلقائية + +تتضمن كل سجل يتم إرساله إلى Loki: +`processor`: هوية المعالج (مثل `config-svc`، `text-completion`، `embeddings`). +`severity`: مستوى السجل (DEBUG، INFO، إلخ). +`logger`: اسم الوحدة (مثل `trustgraph.gateway.service`، `trustgraph.agent.react.service`). + +### التسميات المخصصة + +أضف تسميات مخصصة عبر المعامل `extra`: + +```python +logger.info("User action", extra={ + 'tags': { + 'user_id': user_id, + 'action': 'document_upload', + 'collection': collection_name + } +}) +``` + +### الاستعلام عن السجلات في Loki + +```logql +# All logs from a specific processor (recommended - matches Prometheus metrics) +{processor="config-svc"} +{processor="text-completion"} +{processor="embeddings"} + +# Error logs from a specific processor +{processor="config-svc", severity="ERROR"} + +# Error logs from all processors +{severity="ERROR"} + +# Logs from a specific processor with text filter +{processor="text-completion"} |= "Processing" + +# All logs from API gateway +{processor="api-gateway"} + +# Logs from processors matching pattern +{processor=~".*-completion"} + +# Logs with custom tags +{processor="api-gateway"} | json | user_id="12345" +``` + +### التدهور الأنيق + +إذا كان Loki غير متاح أو لم يتم تثبيت `python-logging-loki`: +يتم طباعة رسالة تحذير على وحدة التحكم. +يستمر تسجيل الأحداث في وحدة التحكم بشكل طبيعي. +يستمر التطبيق في العمل. +لا توجد آلية لإعادة المحاولة لاتصال Loki (الفشل السريع، والتدهور الأنيق). + +## الاختبار + +أثناء الاختبار، ضع في اعتبارك استخدام تكوين تسجيل مختلف: + +```python +# In test setup +import logging + +# Reduce noise during tests +logging.getLogger().setLevel(logging.WARNING) + +# Or disable Loki for tests +setup_logging({'log_level': 'WARNING', 'loki_enabled': False}) +``` + +## التكامل مع نظام المراقبة + +### التنسيق القياسي +جميع السجلات تستخدم تنسيقًا متسقًا: +``` +2025-01-09 10:30:45,123 - trustgraph.gateway.service - INFO - Request processed +``` + +مكونات التنسيق: +الطابع الزمني (بتنسيق ISO مع أجزاء من الثانية) +اسم المسجل (مسار الوحدة) +مستوى التسجيل +الرسالة + +### استعلامات Loki للمراقبة + +استعلامات مراقبة شائعة: + +```logql +# Error rate by processor +rate({severity="ERROR"}[5m]) by (processor) + +# Top error-producing processors +topk(5, count_over_time({severity="ERROR"}[1h]) by (processor)) + +# Recent errors with processor name +{severity="ERROR"} | line_format "{{.processor}}: {{.message}}" + +# All agent processors +{processor=~".*agent.*"} |= "exception" + +# Specific processor error count +count_over_time({processor="config-svc", severity="ERROR"}[1h]) +``` + +## اعتبارات الأمان + +**لا تقم أبدًا بتسجيل معلومات حساسة** (كلمات المرور، مفاتيح API، البيانات الشخصية، الرموز) +**قم بتنظيف مدخلات المستخدم** قبل التسجيل +**استخدم قيمًا محجوزة** للحقول الحساسة: `user_id=****1234` +**مصادقة Loki**: استخدم `--loki-username` و `--loki-password` للنشر الآمن +**نقل آمن**: استخدم HTTPS لعنوان URL الخاص بـ Loki في بيئة الإنتاج: `https://loki.prod:3100/loki/api/v1/push` + +## التبعيات + +يتطلب وحدة التسجيل المركزية ما يلي: +`python-logging-loki` - لتكامل Loki (اختياري، مع إمكانية التراجع الآمن في حالة عدم وجوده) + +تم تضمينها بالفعل في `trustgraph-base/pyproject.toml` و `requirements.txt`. + +## مسار الترحيل + +بالنسبة للكود الحالي: + +1. **الخدمات التي تستخدم بالفعل AsyncProcessor**: لا توجد تغييرات مطلوبة، دعم Loki تلقائي +2. **الخدمات التي لا تستخدم AsyncProcessor** (api-gateway, mcp-server): تم تحديثها بالفعل +3. **أدوات سطر الأوامر (CLI)**: خارج نطاق العمل - استمر في استخدام print() أو التسجيل البسيط + +### من print() إلى التسجيل: +```python +# Before +print(f"Processing document {doc_id}") + +# After +logger = logging.getLogger(__name__) +logger.info(f"Processing document {doc_id}") +``` + +## ملخص الإعدادات + +| الوسيط | القيمة الافتراضية | متغير البيئة | الوصف | +|----------|---------|---------------------|-------------| +| `--log-level` | `INFO` | - | مستوى تسجيل وحدة التحكم و Loki | +| `--loki-enabled` | `True` | - | تمكين تسجيل Loki | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | نقطة النهاية لدفع البيانات إلى Loki | +| `--loki-username` | `None` | `LOKI_USERNAME` | اسم المستخدم للمصادقة في Loki | +| `--loki-password` | `None` | `LOKI_PASSWORD` | كلمة المرور للمصادقة في Loki | diff --git a/docs/tech-specs/logging-strategy.es.md b/docs/tech-specs/logging-strategy.es.md new file mode 100644 index 00000000..40a47323 --- /dev/null +++ b/docs/tech-specs/logging-strategy.es.md @@ -0,0 +1,215 @@ +--- +layout: default +title: "Estrategia de Registro de TrustGraph" +parent: "Spanish (Beta)" +--- + +# Estrategia de Registro de TrustGraph + +> **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. + +## Visión general + +TrustGraph utiliza el módulo integrado de Python `logging` para todas las operaciones de registro, con una configuración centralizada y la integración opcional de Loki para la agregación de registros. Esto proporciona un enfoque estandarizado y flexible para el registro en todos los componentes del sistema. + +## Configuración predeterminada + +### Nivel de registro +- **Nivel predeterminado**: `INFO` +- **Configurable a través de**: Argumento de línea de comandos `--log-level` +- **Opciones**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### Destinos de salida +1. **Consola (stdout)**: Siempre habilitado - asegura la compatibilidad con entornos contenedorizados +2. **Loki**: Agregación centralizada de registros opcional (habilitado por defecto, se puede deshabilitar) + +## Módulo de registro centralizado + +Todas las configuraciones de registro se gestionan mediante el módulo `trustgraph.base.logging`, que proporciona: +- `add_logging_args(parser)` - Agrega argumentos de línea de comandos estándar para registro +- `setup_logging(args)` - Configura el registro a partir de los argumentos analizados + +Este módulo se utiliza en todos los componentes del lado del servidor: +- Servicios basados en AsyncProcessor +- API Gateway +- Servidor MCP + +## Guía de implementación + +### 1. Inicialización del registrador + +Cada módulo debe crear su propio registrador utilizando el nombre del módulo: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +El nombre del registrador se utiliza automáticamente como etiqueta en Loki para filtrar y buscar. + +### 2. Inicialización del servicio + +Todos los servicios del lado del servidor obtienen automáticamente la configuración de registro a través del módulo centralizado: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Agrega argumentos estándar de registro (incluida la configuración de Loki) + add_logging_args(parser) + + # Agrega tus argumentos específicos del servicio + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Configura el registro temprano en el inicio + setup_logging(args) + + # Resto de la inicialización del servicio + logger = logging.getLogger(__name__) + logger.info("Servicio iniciado...") +``` + +### 3. Argumentos de línea de comandos + +Todos los servicios admiten estos argumentos de registro: + +**Nivel de registro:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**Configuración de Loki:** +```bash +--loki-enabled # Habilita Loki (predeterminado) +--no-loki-enabled # Deshabilita Loki +--loki-url URL # URL de envío a Loki (predeterminado: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Nombre de usuario opcional de autenticación +--loki-password PASSWORD # Contraseña opcional de autenticación +``` + +**Ejemplos:** +```bash +# Predeterminado - nivel INFO, Loki habilitado +./my-service + +# Modo DEBUG, solo consola +./my-service --log-level DEBUG --no-loki-enabled + +# URL de Loki personalizada con autenticación +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. Variables de entorno + +La configuración de Loki admite los valores predeterminados de las variables de entorno: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +Los argumentos de la línea de comandos tienen prioridad sobre las variables de entorno. + +### 5. Mejores prácticas de registro + +#### Uso de los niveles de registro +- **DEBUG**: Información detallada para diagnosticar problemas (valores de variables, entrada/salida de funciones) +- **INFO**: Mensajes informativos generales (servicio iniciado, configuración cargada, hitos de procesamiento) +- **WARNING**: Mensajes de advertencia para situaciones potencialmente dañinas (características obsoletas, errores recuperables) +- **ERROR**: Mensajes de error para problemas serios (operaciones fallidas, excepciones) +- **CRITICAL**: Mensajes críticos para fallas del sistema que requieren atención inmediata + +#### Formato de mensaje +```python +# Bueno - incluye contexto +logger.info(f"Procesando documento: {doc_id}, tamaño: {doc_size} bytes") +logger.error(f"No se pudo conectar a la base de datos: {error}", exc_info=True) + +# No bueno - carece de contexto +logger.info("Procesando documento") +logger.error("Conexión fallida") +``` + +#### Consideraciones de rendimiento +```python +# Usa la incrustación para operaciones costosas +logger.debug("Resultado de la operación costosa: %s", expensive_function()) + +# Comprueba el nivel de registro para operaciones de depuración muy costosas +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Datos de depuración: {debug_data}") +``` + +#### 6. Registro estructurado con Loki + +Para datos complejos, usa el registro estructurado con etiquetas adicionales para Loki: + +```python +logger.info("Solicitud procesada", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'éxito' + } +}) +``` + +Estas etiquetas se convierten en etiquetas de búsqueda en Loki, además de las etiquetas automáticas: +- `severity` - Nivel de registro (DEBUG, INFO, etc.) +- `logger` - Nombre del módulo (del `__name__`) + +### 7. Registro de excepciones + +Siempre incluye trazas de pila para las excepciones: + +```python +try: + process_data() +except Exception as e: + logger.error(f"No se pudo procesar los datos: {e}", exc_info=True) +``` + +### 8. Dependencias + +El módulo centralizado de registro requiere: +- `python-logging-loki` - Para la integración de Loki (opcional, funciona si falta) + +Ya incluido en `trustgraph-base/pyproject.toml` y `requirements.txt`. + +## Migración + +Para código existente: + +1. **Servicios que ya utilizan AsyncProcessor**: No se necesita cambios, la integración de Loki es automática +2. **Servicios que no utilizan AsyncProcessor** (api-gateway, mcp-server): Ya actualizado +3. **Herramientas de línea de comandos**: Fuera del alcance - continúe usando `print()` o registro simple + +### De `print()` a registro: +```python +# Antes +print(f"Procesando documento {doc_id}") + +# Después +logger = logging.getLogger(__name__) +logger.info(f"Procesando documento {doc_id}") +``` + +## Resumen de configuración + +| Argumento | Predeterminado | Variable de entorno | Descripción | +|---|---|---|---| +| `--log-level` | `INFO` | - | Nivel de registro en la consola y Loki | +| `--loki-enabled` | `True` | - | Habilita el registro de Loki | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | Puntero al API de Loki | +| `--loki-username` | `None` | `LOKI_USERNAME` | Nombre de usuario de autenticación para Loki | +| `--loki-password` | `None` | `LOKI_PASSWORD` | Contraseña de autenticación para Loki | diff --git a/docs/tech-specs/logging-strategy.he.md b/docs/tech-specs/logging-strategy.he.md new file mode 100644 index 00000000..e2f75f3b --- /dev/null +++ b/docs/tech-specs/logging-strategy.he.md @@ -0,0 +1,358 @@ +--- +layout: default +title: "אסטרטגיית רישום (לוגינג) של TrustGraph" +parent: "Hebrew (Beta)" +--- + +# אסטרטגיית רישום (לוגינג) של TrustGraph + +> **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 משתמש במודול `logging` המובנה של Python עבור כל פעולות הרישום, עם תצורה מרכזית ושילוב אופציונלי של Loki לאיסוף יומנים. זה מספק גישה סטנדרטית וגמישה לרישום בכל רכיבי המערכת. + +## תצורה ברירת מחדל + +### רמת רישום +**רמה ברירת מחדל**: `INFO` +**ניתן להגדרה באמצעות**: ארגומנט שורת הפקודה `--log-level` +**אפשרויות**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### יעדי פלט +1. **קונסולה (stdout)**: תמיד מופעלת - מבטיחה תאימות עם סביבות מבוססות קונטיינרים +2. **Loki**: איסוף יומנים מרכזי אופציונלי (מופעל כברירת מחדל, ניתן לביטול) + +## מודול רישום מרכזי + +כל תצורת הרישום מנוהלת על ידי המודול `trustgraph.base.logging`, המספק: +`add_logging_args(parser)` - מוסיף ארגומנטי שורת פקודה סטנדרטיים לרישום +`setup_logging(args)` - מגדיר רישום מארגומנטים מנותחים + +מודול זה משמש את כל רכיבי הצד-שרת: +שירותים מבוססי AsyncProcessor +API Gateway +MCP Server + +## הנחיות יישום + +### 1. אתחול רשומות + +כל מודול צריך ליצור את הרשומות שלו באמצעות המודול `__name__`: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +שם ה-logger משמש באופן אוטומטי כתווית ב-Loki לצורך סינון וחיפוש. + +### 2. אתחול שירות + +כל השירותים בצד השרת מקבלים באופן אוטומטי הגדרות רישום דרך המודול המרכזי: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Add standard logging arguments (includes Loki configuration) + add_logging_args(parser) + + # Add your service-specific arguments + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Setup logging early in startup + setup_logging(args) + + # Rest of your service initialization + logger = logging.getLogger(__name__) + logger.info("Service starting...") +``` + +### 3. ארגומנטים של שורת הפקודה + +כל השירותים תומכים בארגומנטים אלה של רישום: + +**רמת רישום:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**תצורת לוקי:** +```bash +--loki-enabled # Enable Loki (default) +--no-loki-enabled # Disable Loki +--loki-url URL # Loki push URL (default: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Optional authentication +--loki-password PASSWORD # Optional authentication +``` + +**דוגמאות:** +```bash +# Default - INFO level, Loki enabled +./my-service + +# Debug mode, console only +./my-service --log-level DEBUG --no-loki-enabled + +# Custom Loki server with auth +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. משתני סביבה + +תצורת Loki תומכת באפשרויות ברירת מחדל עבור משתני סביבה: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +ארגומנטים משורת הפקודה גוברים על משתני סביבה. + +### 5. שיטות עבודה מומלצות לרישום נתונים + +#### שימוש ברמות רישום +**DEBUG**: מידע מפורט לצורך אבחון בעיות (ערכי משתנים, כניסה/יציאה מפונקציות) +**INFO**: הודעות מידע כלליות (השירות התחיל, תצורה נטענה, נקודות ציון בעיבוד) +**WARNING**: הודעות אזהרה למצבים שעלולים להיות מזיקים (תכונות מיושנות, שגיאות שניתן להתאושש מהן) +**ERROR**: הודעות שגיאה לבעיות חמורות (פעולות שנכשלו, חריגות) +**CRITICAL**: הודעות קריטיות לכשלים במערכת הדורשים התייחסות מיידית + +#### פורמט ההודעה +```python +# Good - includes context +logger.info(f"Processing document: {doc_id}, size: {doc_size} bytes") +logger.error(f"Failed to connect to database: {error}", exc_info=True) + +# Avoid - lacks context +logger.info("Processing document") +logger.error("Connection failed") +``` + +#### שיקולי ביצועים +```python +# Use lazy formatting for expensive operations +logger.debug("Expensive operation result: %s", expensive_function()) + +# Check log level for very expensive debug operations +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Debug data: {debug_data}") +``` + +### 6. רישום מובנה עם לוקי + +עבור נתונים מורכבים, השתמש ברישום מובנה עם תגיות נוספות עבור לוקי: + +```python +logger.info("Request processed", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +תגיות אלו הופכות לתויות הניתנות לחיפוש ב-Loki, בנוסף לתויות אוטומטיות: +`severity` - רמת לוג (DEBUG, INFO, WARNING, ERROR, CRITICAL) +`logger` - שם מודול (מתוך `__name__`) + +### 7. רישום חריגות + +תמיד כללו עקבות מחסנית עבור חריגות: + +```python +try: + process_data() +except Exception as e: + logger.error(f"Failed to process data: {e}", exc_info=True) + raise +``` + +### 8. שיקולים בנושא רישום אסינכרוני + +מערכת הרישום משתמשת במטפלים (handlers) בתור לא חוסמים עבור Loki: +פלט לקונסולה הוא סינכרוני (מהיר) +פלט ל-Loki מוצג בתור עם מאגר של 500 הודעות +ניתוב רקע מטפל בהעברת נתונים ל-Loki +אין חסימה של קוד האפליקציה הראשי + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # Logging is thread-safe and won't block async operations + logger.info(f"Starting async operation in task: {asyncio.current_task().get_name()}") +``` + +## אינטגרציה עם לוקי + +### ארכיטקטורה + +מערכת הרישום משתמשת בפונקציות המובנות של Python, `QueueHandler` ו-`QueueListener`, עבור אינטגרציה לא חוסמת עם לוקי: + +1. **QueueHandler**: הודעות רישום מוכנסות לתור של 500 הודעות (לא חוסם). +2. **Background Thread**: QueueListener שולח הודעות רישום ללוקי באופן אסינכרוני. +3. **Graceful Degradation**: אם לוקי אינו זמין, רישום לקונסולה ממשיך. + +### תגיות אוטומטיות + +כל הודעת רישום שנשלחת ללוקי כוללת: +`processor`: זהות המעבד (לדוגמה, `config-svc`, `text-completion`, `embeddings`). +`severity`: רמת הרישום (DEBUG, INFO, וכו'). +`logger`: שם המודול (לדוגמה, `trustgraph.gateway.service`, `trustgraph.agent.react.service`). + +### תגיות מותאמות אישית + +הוספת תגיות מותאמות אישית באמצעות הפרמטר `extra`: + +```python +logger.info("User action", extra={ + 'tags': { + 'user_id': user_id, + 'action': 'document_upload', + 'collection': collection_name + } +}) +``` + +### שאילתת יומנים ב-Loki + +```logql +# All logs from a specific processor (recommended - matches Prometheus metrics) +{processor="config-svc"} +{processor="text-completion"} +{processor="embeddings"} + +# Error logs from a specific processor +{processor="config-svc", severity="ERROR"} + +# Error logs from all processors +{severity="ERROR"} + +# Logs from a specific processor with text filter +{processor="text-completion"} |= "Processing" + +# All logs from API gateway +{processor="api-gateway"} + +# Logs from processors matching pattern +{processor=~".*-completion"} + +# Logs with custom tags +{processor="api-gateway"} | json | user_id="12345" +``` + +### ניוון מבוקר (Graceful Degradation) + +אם Loki אינו זמין או `python-logging-loki` אינו מותקן: +הודעת אזהרה מוצגת לקונסולה +רישום לקונסולה ממשיך כרגיל +היישום ממשיך לפעול +אין לוגיקה של ניסיון חוזר לחיבור ל-Loki (כשל מהיר, ניוון מבוקר) + +## בדיקות (Testing) + +במהלך הבדיקות, שקלו להשתמש בתצורת רישום שונה: + +```python +# In test setup +import logging + +# Reduce noise during tests +logging.getLogger().setLevel(logging.WARNING) + +# Or disable Loki for tests +setup_logging({'log_level': 'WARNING', 'loki_enabled': False}) +``` + +## אינטגרציה של ניטור + +### פורמט סטנדרטי +כל הרישומים משתמשים בפורמט עקבי: +``` +2025-01-09 10:30:45,123 - trustgraph.gateway.service - INFO - Request processed +``` + +מרכיבי פורמט: +חותמת זמן (פורמט ISO עם מילישניות) +שם הלוגר (נתיב מודול) +רמת לוג +הודעה + +### שאילתות לוקי לניטור + +שאילתות ניטור נפוצות: + +```logql +# Error rate by processor +rate({severity="ERROR"}[5m]) by (processor) + +# Top error-producing processors +topk(5, count_over_time({severity="ERROR"}[1h]) by (processor)) + +# Recent errors with processor name +{severity="ERROR"} | line_format "{{.processor}}: {{.message}}" + +# All agent processors +{processor=~".*agent.*"} |= "exception" + +# Specific processor error count +count_over_time({processor="config-svc", severity="ERROR"}[1h]) +``` + +## שיקולי אבטחה + +**לעולם אין לרשום מידע רגיש** (סיסמאות, מפתחות API, נתונים אישיים, טוקנים) +**לנקות קלט משתמש** לפני רישום +**להשתמש במחזירי מקום** עבור שדות רגישים: `user_id=****1234` +**אימות לוקי:** השתמשו ב-`--loki-username` ו-`--loki-password` עבור פריסות מאובטחות +**העברה מאובטחת:** השתמשו ב-HTTPS עבור כתובת ה-URL של לוקי בסביבת ייצור: `https://loki.prod:3100/loki/api/v1/push` + +## תלויות + +מודול הרישום המרכזי דורש: +`python-logging-loki` - עבור אינטגרציה עם לוקי (אופציונלי, ירידה הדרגתית אם חסר) + +כלול כבר ב-`trustgraph-base/pyproject.toml` ו-`requirements.txt`. + +## נתיב מעבר + +עבור קוד קיים: + +1. **שירותים שכבר משתמשים ב-AsyncProcessor:** אין צורך בשינויים, תמיכה בלוקי היא אוטומטית +2. **שירותים שאינם משתמשים ב-AsyncProcessor** (api-gateway, mcp-server): כבר עודכנו +3. **כלי שורת פקודה:** מחוץ לתחום - המשיכו להשתמש ב-print() או ברישום פשוט + +### מ-print() לרישום: +```python +# Before +print(f"Processing document {doc_id}") + +# After +logger = logging.getLogger(__name__) +logger.info(f"Processing document {doc_id}") +``` + +## סיכום הגדרות + +| ארגומנט | ברירת מחדל | משתנה סביבה | תיאור | +|----------|---------|---------------------|-------------| +| `--log-level` | `INFO` | - | רמת רישום עבור קונסולה ו-Loki | +| `--loki-enabled` | `True` | - | הפעלת רישום Loki | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | נקודת קצה (endpoint) של Loki לשליחה | +| `--loki-username` | `None` | `LOKI_USERNAME` | שם משתמש לאימות ב-Loki | +| `--loki-password` | `None` | `LOKI_PASSWORD` | סיסמה לאימות ב-Loki | diff --git a/docs/tech-specs/logging-strategy.hi.md b/docs/tech-specs/logging-strategy.hi.md new file mode 100644 index 00000000..5b2d85f9 --- /dev/null +++ b/docs/tech-specs/logging-strategy.hi.md @@ -0,0 +1,358 @@ +--- +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. + +## अवलोकन + +ट्रस्टग्राफ सभी लॉगिंग कार्यों के लिए पायथन के अंतर्निहित `logging` मॉड्यूल का उपयोग करता है, जिसमें केंद्रीकृत कॉन्फ़िगरेशन और लॉग एकत्रीकरण के लिए वैकल्पिक लोकी एकीकरण शामिल है। यह सिस्टम के सभी घटकों में लॉगिंग के लिए एक मानकीकृत, लचीला दृष्टिकोण प्रदान करता है। + +## डिफ़ॉल्ट कॉन्फ़िगरेशन + +### लॉगिंग स्तर +**डिफ़ॉल्ट स्तर**: `INFO` +**कॉन्फ़िगरेशन**: `--log-level` कमांड-लाइन तर्क के माध्यम से +**विकल्प**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### आउटपुट गंतव्य +1. **कंसोल (stdout)**: हमेशा सक्षम - कंटेनरीकृत वातावरणों के साथ संगतता सुनिश्चित करता है +2. **लोकी**: वैकल्पिक केंद्रीकृत लॉग एकत्रीकरण (डिफ़ॉल्ट रूप से सक्षम, इसे अक्षम किया जा सकता है) + +## केंद्रीकृत लॉगिंग मॉड्यूल + +सभी लॉगिंग कॉन्फ़िगरेशन को `trustgraph.base.logging` मॉड्यूल द्वारा प्रबंधित किया जाता है, जो निम्नलिखित प्रदान करता है: +`add_logging_args(parser)` - मानक लॉगिंग CLI तर्क जोड़ता है +`setup_logging(args)` - पार्स किए गए तर्कों से लॉगिंग को कॉन्फ़िगर करता है + +इस मॉड्यूल का उपयोग सभी सर्वर-साइड घटकों द्वारा किया जाता है: +AsyncProcessor-आधारित सेवाएं +एपीआई गेटवे +एमसीपी सर्वर + +## कार्यान्वयन दिशानिर्देश + +### 1. लॉगर इनिशियलाइज़ेशन + +प्रत्येक मॉड्यूल को मॉड्यूल के `__name__` का उपयोग करके अपना लॉगर बनाना चाहिए: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +लॉगर का नाम स्वचालित रूप से लोकी में फ़िल्टरिंग और खोज के लिए एक लेबल के रूप में उपयोग किया जाता है। + +### 2. सेवा आरंभिकरण + +सभी सर्वर-साइड सेवाओं को केंद्रीकृत मॉड्यूल के माध्यम से स्वचालित रूप से लॉगिंग कॉन्फ़िगरेशन प्राप्त होता है: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Add standard logging arguments (includes Loki configuration) + add_logging_args(parser) + + # Add your service-specific arguments + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Setup logging early in startup + setup_logging(args) + + # Rest of your service initialization + logger = logging.getLogger(__name__) + logger.info("Service starting...") +``` + +### 3. कमांड-लाइन तर्क + +सभी सेवाएं इन लॉगिंग तर्कों का समर्थन करती हैं: + +**लॉग स्तर:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**लोकी कॉन्फ़िगरेशन:** +```bash +--loki-enabled # Enable Loki (default) +--no-loki-enabled # Disable Loki +--loki-url URL # Loki push URL (default: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Optional authentication +--loki-password PASSWORD # Optional authentication +``` + +**उदाहरण:** +```bash +# Default - INFO level, Loki enabled +./my-service + +# Debug mode, console only +./my-service --log-level DEBUG --no-loki-enabled + +# Custom Loki server with auth +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. पर्यावरण चर + +लोकी कॉन्फ़िगरेशन पर्यावरण चर के उपयोग का समर्थन करता है: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +कमांड-लाइन तर्क पर्यावरण चर से अधिक महत्वपूर्ण होते हैं। + +### 5. लॉगिंग के सर्वोत्तम अभ्यास + +#### लॉग स्तरों का उपयोग +**DEBUG**: समस्याओं के निदान के लिए विस्तृत जानकारी (चर मान, फ़ंक्शन प्रविष्टि/निकास) +**INFO**: सामान्य सूचनात्मक संदेश (सेवा शुरू, कॉन्फ़िगरेशन लोड, प्रसंस्करण मील के पत्थर) +**WARNING**: संभावित रूप से हानिकारक स्थितियों के लिए चेतावनी संदेश (अप्रचलित सुविधाएँ, ठीक होने योग्य त्रुटियाँ) +**ERROR**: गंभीर समस्याओं के लिए त्रुटि संदेश (विफल संचालन, अपवाद) +**CRITICAL**: तत्काल ध्यान देने की आवश्यकता वाले सिस्टम विफलताओं के लिए महत्वपूर्ण संदेश + +#### संदेश प्रारूप +```python +# Good - includes context +logger.info(f"Processing document: {doc_id}, size: {doc_size} bytes") +logger.error(f"Failed to connect to database: {error}", exc_info=True) + +# Avoid - lacks context +logger.info("Processing document") +logger.error("Connection failed") +``` + +#### प्रदर्शन संबंधी विचार +```python +# Use lazy formatting for expensive operations +logger.debug("Expensive operation result: %s", expensive_function()) + +# Check log level for very expensive debug operations +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Debug data: {debug_data}") +``` + +### 6. लोकी के साथ संरचित लॉगिंग + +जटिल डेटा के लिए, लोकी के लिए अतिरिक्त टैग के साथ संरचित लॉगिंग का उपयोग करें: + +```python +logger.info("Request processed", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +ये टैग, स्वचालित लेबल के अतिरिक्त, लोकी में खोज योग्य लेबल बन जाते हैं: +`severity` - लॉग स्तर (डीबग, जानकारी, चेतावनी, त्रुटि, गंभीर) +`logger` - मॉड्यूल का नाम (`__name__` से) + +### 7. अपवाद लॉगिंग + +हमेशा अपवादों के लिए स्टैक ट्रेस शामिल करें: + +```python +try: + process_data() +except Exception as e: + logger.error(f"Failed to process data: {e}", exc_info=True) + raise +``` + +### 8. एसिंक्रोनस लॉगिंग संबंधी विचार + +लॉगिंग सिस्टम लोकी के लिए गैर-ब्लॉकिंग कतार वाले हैंडलर का उपयोग करता है: +कंसोल आउटपुट सिंक्रोनस (तेज़) है +लोकी आउटपुट 500-संदेश बफर के साथ कतारबद्ध है +बैकग्राउंड थ्रेड लोकी ट्रांसमिशन को संभालता है +मुख्य एप्लिकेशन कोड का कोई अवरोधन नहीं + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # Logging is thread-safe and won't block async operations + logger.info(f"Starting async operation in task: {asyncio.current_task().get_name()}") +``` + +## लोकी एकीकरण + +### वास्तुकला + +लॉगिंग सिस्टम, गैर-अवरुद्ध लोकी एकीकरण के लिए पायथन के अंतर्निहित `QueueHandler` और `QueueListener` का उपयोग करता है: + +1. **क्यू हैंडलर**: लॉग को 500 संदेशों की कतार में रखा जाता है (गैर-अवरुद्ध)। +2. **बैकग्राउंड थ्रेड**: क्यू लिसनर एसिंक्रोनस रूप से लोकी को लॉग भेजता है। +3. **सुगम गिरावट**: यदि लोकी अनुपलब्ध है, तो कंसोल लॉगिंग जारी रहती है। + +### स्वचालित लेबल + +लोकी को भेजे गए प्रत्येक लॉग में शामिल हैं: +`processor`: प्रोसेसर पहचान (उदाहरण के लिए, `config-svc`, `text-completion`, `embeddings`) +`severity`: लॉग स्तर (डीबग, जानकारी, आदि) +`logger`: मॉड्यूल नाम (उदाहरण के लिए, `trustgraph.gateway.service`, `trustgraph.agent.react.service`) + +### कस्टम लेबल + +`extra` पैरामीटर के माध्यम से कस्टम लेबल जोड़ें: + +```python +logger.info("User action", extra={ + 'tags': { + 'user_id': user_id, + 'action': 'document_upload', + 'collection': collection_name + } +}) +``` + +### लोकी में लॉग की खोज + +```logql +# All logs from a specific processor (recommended - matches Prometheus metrics) +{processor="config-svc"} +{processor="text-completion"} +{processor="embeddings"} + +# Error logs from a specific processor +{processor="config-svc", severity="ERROR"} + +# Error logs from all processors +{severity="ERROR"} + +# Logs from a specific processor with text filter +{processor="text-completion"} |= "Processing" + +# All logs from API gateway +{processor="api-gateway"} + +# Logs from processors matching pattern +{processor=~".*-completion"} + +# Logs with custom tags +{processor="api-gateway"} | json | user_id="12345" +``` + +### सुचारू रूप से कार्यक्षमता में कमी + +यदि लोकी अनुपलब्ध है या `python-logging-loki` स्थापित नहीं है: +कंसोल पर चेतावनी संदेश प्रदर्शित किया जाता है +कंसोल लॉगिंग सामान्य रूप से जारी रहता है +एप्लिकेशन चलता रहता है +लोकी कनेक्शन के लिए कोई पुनः प्रयास तर्क नहीं (तुरंत विफल, सुचारू रूप से कार्यक्षमता में कमी) + +## परीक्षण + +परीक्षण के दौरान, एक अलग लॉगिंग कॉन्फ़िगरेशन का उपयोग करने पर विचार करें: + +```python +# In test setup +import logging + +# Reduce noise during tests +logging.getLogger().setLevel(logging.WARNING) + +# Or disable Loki for tests +setup_logging({'log_level': 'WARNING', 'loki_enabled': False}) +``` + +## निगरानी एकीकरण + +### मानक प्रारूप +सभी लॉग एक सुसंगत प्रारूप का उपयोग करते हैं: +``` +2025-01-09 10:30:45,123 - trustgraph.gateway.service - INFO - Request processed +``` + +प्रारूप घटक: +टाइमस्टैम्प (मिलीसेकंड के साथ आईएसओ प्रारूप) +लॉगर नाम (मॉड्यूल पथ) +लॉग स्तर +संदेश + +### निगरानी के लिए लोकी प्रश्न + +सामान्य निगरानी प्रश्न: + +```logql +# Error rate by processor +rate({severity="ERROR"}[5m]) by (processor) + +# Top error-producing processors +topk(5, count_over_time({severity="ERROR"}[1h]) by (processor)) + +# Recent errors with processor name +{severity="ERROR"} | line_format "{{.processor}}: {{.message}}" + +# All agent processors +{processor=~".*agent.*"} |= "exception" + +# Specific processor error count +count_over_time({processor="config-svc", severity="ERROR"}[1h]) +``` + +## सुरक्षा संबंधी विचार + +**कभी भी संवेदनशील जानकारी लॉग न करें** (पासवर्ड, एपीआई कुंजियाँ, व्यक्तिगत डेटा, टोकन) +लॉगिंग से पहले **उपयोगकर्ता इनपुट को साफ़ करें** +संवेदनशील फ़ील्ड के लिए **प्लेसहोल्डर का उपयोग करें**: `user_id=****1234` +**लोकी प्रमाणीकरण**: सुरक्षित परिनियोजन के लिए `--loki-username` और `--loki-password` का उपयोग करें +**सुरक्षित परिवहन**: उत्पादन में लोकी यूआरएल के लिए HTTPS का उपयोग करें: `https://loki.prod:3100/loki/api/v1/push` + +## निर्भरताएँ + +केंद्रीकृत लॉगिंग मॉड्यूल को निम्नलिखित की आवश्यकता है: +`python-logging-loki` - लोकी एकीकरण के लिए (वैकल्पिक, यदि अनुपलब्ध हो तो सुचारू गिरावट) + +पहले से ही `trustgraph-base/pyproject.toml` और `requirements.txt` में शामिल है। + +## माइग्रेशन पथ + +मौजूदा कोड के लिए: + +1. **AsyncProcessor का उपयोग कर रहे सेवाएँ**: कोई बदलाव आवश्यक नहीं, लोकी समर्थन स्वचालित है +2. **AsyncProcessor का उपयोग नहीं कर रही सेवाएँ** (api-gateway, mcp-server): पहले से ही अपडेट किया गया है +3. **CLI उपकरण**: दायरे से बाहर - print() या साधारण लॉगिंग का उपयोग जारी रखें + +### print() से लॉगिंग तक: +```python +# Before +print(f"Processing document {doc_id}") + +# After +logger = logging.getLogger(__name__) +logger.info(f"Processing document {doc_id}") +``` + +## कॉन्फ़िगरेशन सारांश + +| तर्क | डिफ़ॉल्ट | पर्यावरण चर | विवरण | +|----------|---------|---------------------|-------------| +| `--log-level` | `INFO` | - | कंसोल और लोकी लॉग स्तर | +| `--loki-enabled` | `True` | - | लोकी लॉगिंग सक्षम करें | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | लोकी पुश एंडपॉइंट | +| `--loki-username` | `None` | `LOKI_USERNAME` | लोकी ऑथ उपयोगकर्ता नाम | +| `--loki-password` | `None` | `LOKI_PASSWORD` | लोकी ऑथ पासवर्ड | diff --git a/docs/tech-specs/logging-strategy.md b/docs/tech-specs/logging-strategy.md index 84f1eac8..40d551a5 100644 --- a/docs/tech-specs/logging-strategy.md +++ b/docs/tech-specs/logging-strategy.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "TrustGraph Logging Strategy" +parent: "Tech Specs" +--- + # TrustGraph Logging Strategy ## Overview diff --git a/docs/tech-specs/logging-strategy.pt.md b/docs/tech-specs/logging-strategy.pt.md new file mode 100644 index 00000000..2ba18638 --- /dev/null +++ b/docs/tech-specs/logging-strategy.pt.md @@ -0,0 +1,358 @@ +--- +layout: default +title: "Estratégia de Registro (Logging) do TrustGraph" +parent: "Portuguese (Beta)" +--- + +# Estratégia de Registro (Logging) do TrustGraph + +> **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 + +O TrustGraph utiliza o módulo `logging` integrado do Python para todas as operações de registro, com configuração centralizada e integração opcional com o Loki para agregação de logs. Isso fornece uma abordagem padronizada e flexível para o registro em todos os componentes do sistema. + +## Configuração Padrão + +### Nível de Registro +**Nível Padrão**: `INFO` +**Configurável via**: argumento de linha de comando `--log-level` +**Opções**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### Destinos de Saída +1. **Console (stdout)**: Sempre habilitado - garante compatibilidade com ambientes conteinerizados. +2. **Loki**: Agregação de logs centralizada opcional (habilitada por padrão, pode ser desabilitada). + +## Módulo de Registro Centralizado + +Toda a configuração de registro é gerenciada pelo módulo `trustgraph.base.logging`, que fornece: +`add_logging_args(parser)` - Adiciona argumentos de linha de comando padrão para registro. +`setup_logging(args)` - Configura o registro a partir de argumentos analisados. + +Este módulo é usado por todos os componentes do lado do servidor: +Serviços baseados em AsyncProcessor. +API Gateway. +Servidor MCP. + +## Diretrizes de Implementação + +### 1. Inicialização do Logger + +Cada módulo deve criar seu próprio logger usando o módulo `__name__`: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +O nome do logger é automaticamente usado como um rótulo no Loki para filtragem e pesquisa. + +### 2. Inicialização do Serviço + +Todos os serviços do lado do servidor recebem automaticamente a configuração de registro através do módulo centralizado: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Add standard logging arguments (includes Loki configuration) + add_logging_args(parser) + + # Add your service-specific arguments + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Setup logging early in startup + setup_logging(args) + + # Rest of your service initialization + logger = logging.getLogger(__name__) + logger.info("Service starting...") +``` + +### 3. Argumentos de Linha de Comando + +Todos os serviços suportam estes argumentos de registro: + +**Nível de Log:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**Configuração do Loki:** +```bash +--loki-enabled # Enable Loki (default) +--no-loki-enabled # Disable Loki +--loki-url URL # Loki push URL (default: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Optional authentication +--loki-password PASSWORD # Optional authentication +``` + +**Exemplos:** +```bash +# Default - INFO level, Loki enabled +./my-service + +# Debug mode, console only +./my-service --log-level DEBUG --no-loki-enabled + +# Custom Loki server with auth +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. Variáveis de Ambiente + +A configuração do Loki suporta a utilização de variáveis de ambiente como valores padrão: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +Os argumentos da linha de comando têm precedência sobre as variáveis de ambiente. + +### 5. Melhores Práticas de Registro (Logging) + +#### Uso dos Níveis de Log +**DEBUG**: Informações detalhadas para diagnosticar problemas (valores de variáveis, entrada/saída de funções) +**INFO**: Mensagens informativas gerais (serviço iniciado, configuração carregada, marcos de processamento) +**WARNING**: Mensagens de aviso para situações potencialmente perigosas (recursos obsoletos, erros recuperáveis) +**ERROR**: Mensagens de erro para problemas graves (operações com falha, exceções) +**CRITICAL**: Mensagens críticas para falhas do sistema que exigem atenção imediata + +#### Formato da Mensagem +```python +# Good - includes context +logger.info(f"Processing document: {doc_id}, size: {doc_size} bytes") +logger.error(f"Failed to connect to database: {error}", exc_info=True) + +# Avoid - lacks context +logger.info("Processing document") +logger.error("Connection failed") +``` + +#### Considerações de Desempenho +```python +# Use lazy formatting for expensive operations +logger.debug("Expensive operation result: %s", expensive_function()) + +# Check log level for very expensive debug operations +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Debug data: {debug_data}") +``` + +### 6. Registro Estruturado com Loki + +Para dados complexos, use o registro estruturado com tags adicionais para o Loki: + +```python +logger.info("Request processed", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +Essas tags se tornam rótulos pesquisáveis no Loki, além de rótulos automáticos: +`severity` - Nível de log (DEBUG, INFO, WARNING, ERROR, CRITICAL) +`logger` - Nome do módulo (de `__name__`) + +### 7. Registro de Exceções + +Sempre inclua rastreamentos de pilha para exceções: + +```python +try: + process_data() +except Exception as e: + logger.error(f"Failed to process data: {e}", exc_info=True) + raise +``` + +### 8. Considerações sobre o Logging Assíncrono + +O sistema de logging utiliza manipuladores enfileirados não bloqueantes para o Loki: +A saída para o console é síncrona (rápida) +A saída para o Loki é enfileirada com um buffer de 500 mensagens +Uma thread em segundo plano gerencia a transmissão para o Loki +Não há bloqueio do código principal da aplicação + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # Logging is thread-safe and won't block async operations + logger.info(f"Starting async operation in task: {asyncio.current_task().get_name()}") +``` + +## Integração com Loki + +### Arquitetura + +O sistema de registro utiliza os recursos nativos de Python `QueueHandler` e `QueueListener` para a integração não bloqueante com o Loki: + +1. **QueueHandler**: Os registros são colocados em uma fila de 500 mensagens (não bloqueante). +2. **Thread em Segundo Plano**: O QueueListener envia os registros para o Loki de forma assíncrona. +3. **Degradação Graciosa**: Se o Loki estiver indisponível, o registro no console continua. + +### Rótulos Automáticos + +Cada registro enviado para o Loki inclui: +`processor`: Identidade do processador (por exemplo, `config-svc`, `text-completion`, `embeddings`). +`severity`: Nível de registro (DEBUG, INFO, etc.). +`logger`: Nome do módulo (por exemplo, `trustgraph.gateway.service`, `trustgraph.agent.react.service`). + +### Rótulos Personalizados + +Adicione rótulos personalizados através do parâmetro `extra`: + +```python +logger.info("User action", extra={ + 'tags': { + 'user_id': user_id, + 'action': 'document_upload', + 'collection': collection_name + } +}) +``` + +### Consultando Logs no Loki + +```logql +# All logs from a specific processor (recommended - matches Prometheus metrics) +{processor="config-svc"} +{processor="text-completion"} +{processor="embeddings"} + +# Error logs from a specific processor +{processor="config-svc", severity="ERROR"} + +# Error logs from all processors +{severity="ERROR"} + +# Logs from a specific processor with text filter +{processor="text-completion"} |= "Processing" + +# All logs from API gateway +{processor="api-gateway"} + +# Logs from processors matching pattern +{processor=~".*-completion"} + +# Logs with custom tags +{processor="api-gateway"} | json | user_id="12345" +``` + +### Degradação Graciosa + +Se o Loki estiver indisponível ou `python-logging-loki` não estiver instalado: +Mensagem de aviso impressa no console +O registro no console continua normalmente +O aplicativo continua em execução +Sem lógica de repetição para a conexão com o Loki (falha rápida, degrade graciosamente) + +## Testes + +Durante os testes, considere usar uma configuração de registro diferente: + +```python +# In test setup +import logging + +# Reduce noise during tests +logging.getLogger().setLevel(logging.WARNING) + +# Or disable Loki for tests +setup_logging({'log_level': 'WARNING', 'loki_enabled': False}) +``` + +## Integração de Monitoramento + +### Formato Padrão +Todos os logs utilizam um formato consistente: +``` +2025-01-09 10:30:45,123 - trustgraph.gateway.service - INFO - Request processed +``` + +Componentes de formatação: +Timestamp (formato ISO com milissegundos) +Nome do logger (caminho do módulo) +Nível de log +Mensagem + +### Consultas Loki para Monitoramento + +Consultas de monitoramento comuns: + +```logql +# Error rate by processor +rate({severity="ERROR"}[5m]) by (processor) + +# Top error-producing processors +topk(5, count_over_time({severity="ERROR"}[1h]) by (processor)) + +# Recent errors with processor name +{severity="ERROR"} | line_format "{{.processor}}: {{.message}}" + +# All agent processors +{processor=~".*agent.*"} |= "exception" + +# Specific processor error count +count_over_time({processor="config-svc", severity="ERROR"}[1h]) +``` + +## Considerações de Segurança + +**Nunca registre informações sensíveis** (senhas, chaves de API, dados pessoais, tokens) +**Sanitize a entrada do usuário** antes de registrar +**Use espaços reservados** para campos sensíveis: `user_id=****1234` +**Autenticação Loki**: Use `--loki-username` e `--loki-password` para implantações seguras +**Transporte seguro**: Use HTTPS para a URL do Loki em produção: `https://loki.prod:3100/loki/api/v1/push` + +## Dependências + +O módulo de registro centralizado requer: +`python-logging-loki` - Para integração com o Loki (opcional, degradação graciosa se ausente) + +Já incluído em `trustgraph-base/pyproject.toml` e `requirements.txt`. + +## Caminho de Migração + +Para código existente: + +1. **Serviços que já usam AsyncProcessor**: Nenhuma alteração necessária, o suporte ao Loki é automático +2. **Serviços que não usam AsyncProcessor** (api-gateway, mcp-server): Já foram atualizados +3. **Ferramentas de linha de comando (CLI)**: Fora do escopo - continue usando print() ou registro simples + +### De print() para registro: +```python +# Before +print(f"Processing document {doc_id}") + +# After +logger = logging.getLogger(__name__) +logger.info(f"Processing document {doc_id}") +``` + +## Resumo da Configuração + +| Argumento | Padrão | Variável de Ambiente | Descrição | +|----------|---------|---------------------|-------------| +| `--log-level` | `INFO` | - | Nível de log do console e do Loki | +| `--loki-enabled` | `True` | - | Habilitar o registro de log do Loki | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | Endpoint de envio do Loki | +| `--loki-username` | `None` | `LOKI_USERNAME` | Nome de usuário de autenticação do Loki | +| `--loki-password` | `None` | `LOKI_PASSWORD` | Senha de autenticação do Loki | diff --git a/docs/tech-specs/logging-strategy.ru.md b/docs/tech-specs/logging-strategy.ru.md new file mode 100644 index 00000000..beeced58 --- /dev/null +++ b/docs/tech-specs/logging-strategy.ru.md @@ -0,0 +1,213 @@ +--- +layout: default +title: "Стратегия логирования TrustGraph" +parent: "Russian (Beta)" +--- + +# Стратегия логирования TrustGraph + +> **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 использует встроенный модуль `logging` Python для всех операций логирования, с централизованной конфигурацией и опциональной интеграцией с Loki для агрегации логов. Это обеспечивает стандартизированный и гибкий подход к логированию для всех компонентов системы. + +## Параметры конфигурации по умолчанию + +### Уровень логирования +- **Уровень по умолчанию**: `INFO` +- **Указывается через**: аргумент командной строки `--log-level` +- **Возможные значения**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### Направления вывода +1. **Консоль (stdout)**: Всегда включено - обеспечивает совместимость с контейнерными средами +2. **Loki**: Опциональная централизованная агрегация логов (включена по умолчанию, может быть отключена) + +## Модуль централизованного логирования + +Вся конфигурация логирования управляется модулем `trustgraph.base.logging`, который предоставляет: +- `add_logging_args(parser)` - Добавляет стандартные аргументы командной строки для логирования +- `setup_logging(args)` - Настраивает логирование на основе предоставленных аргументов + +Этот модуль используется всеми серверными компонентами: +- Сервисы, основанные на AsyncProcessor +- API Gateway +- Сервер MCP + +## Рекомендации по реализации + +### 1. Инициализация логгера + +Каждый модуль должен создавать свой собственный логгер, используя `__name__` модуля: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +Имя логгера автоматически используется как метка в Loki для фильтрации и поиска. + +### 2. Инициализация сервиса + +Все серверные сервисы автоматически получают конфигурацию логирования через централизованный модуль: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Добавляем стандартные аргументы логирования (включая конфигурацию Loki) + add_logging_args(parser) + + # Добавляем свои аргументы для сервиса + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Настраиваем логирование в начале запуска + setup_logging(args) + + # Остальная часть инициализации сервиса + logger = logging.getLogger(__name__) + logger.info("Сервис запущен...") +``` + +### 3. Аргументы командной строки + +Все сервисы поддерживают следующие аргументы логирования: + +**Уровень логирования:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**Конфигурация Loki:** +```bash +--loki-enabled # Включить Loki (по умолчанию) +--no-loki-enabled # Отключить Loki +--loki-url URL # URL для отправки логов в Loki (по умолчанию: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Необязательное имя пользователя для аутентификации +--loki-password PASSWORD # Необязательный пароль для аутентификации +``` + +**Примеры:** +```bash +# По умолчанию - уровень INFO, Loki включен +./my-service + +# Режим отладки, только консоль +./my-service --log-level DEBUG --no-loki-enabled + +# Пользовательский сервер Loki с аутентификацией +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. Переменные окружения + +Конфигурация Loki поддерживает использование переменных окружения: + +``` +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +Аргументы командной строки имеют приоритет над переменными окружения. + +### 5. Рекомендации по логированию + +#### Использование уровней логирования +- **DEBUG**: Детальная информация для диагностики проблем (значения переменных, вход/выход функций) +- **INFO**: Общие информационные сообщения (запуск сервиса, загрузка конфигурации, этапы обработки) +- **WARNING**: Предупреждающие сообщения о потенциально опасных ситуациях (устаревшие функции, восстанавливаемые ошибки) +- **ERROR**: Сообщения об ошибках о серьезных проблемах (неудачные операции, исключения) +- **CRITICAL**: Критические сообщения о системных сбоях, требующих немедленного внимания + +#### Формат сообщений +```python +# Хорошо - включает контекст +logger.info(f"Обработка документа: {doc_id}, размер: {doc_size} байт") +logger.error(f"Не удалось подключиться к базе данных: {error}", exc_info=True) + +# Плохо - не включает контекст +logger.info("Обработка документа") +logger.error("Не удалось подключиться") +``` + +#### Соображения производительности +```python +# Используйте ленивую адресацию для дорогостоящих операций +logger.debug("Результат дорогостоящей операции: %s", expensive_function()) + +# Проверяйте уровень логирования для очень дорогих операций DEBUG +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Данные для отладки: {debug_data}") +``` + +### 6. Структурированное логирование с использованием Loki + +Для сложных данных используйте структурированное логирование с дополнительными метками для Loki: + +```python +logger.info("Запрос обработан", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'успешно' + } +}) +``` + +Эти метки становятся поисковыми метками в Loki, а также автоматически создаваемыми: +- `severity` - Уровень логирования (DEBUG, INFO, WARNING, ERROR, CRITICAL) +- `logger` - Имя модуля (из `__name__`) + +### Зависимости + +Модуль централизованного логирования требует: +- `python-logging-loki` - Для интеграции с Loki (необязательно, функционирует без него) + +Уже включен в `trustgraph-base/pyproject.toml` и `requirements.txt`. + +## Переход + +Для существующего кода: + +1. **Сервисы, уже использующие AsyncProcessor**: Не требуется никаких изменений, интеграция с Loki автоматическая +2. **Сервисы, которые не используют AsyncProcessor** (api-gateway, mcp-server): Уже обновлены +3. **Инструменты командной строки**: Не относится - продолжайте использовать `print()` или простое логирование + +### Переход от `print()` к `logging`: +```python +# Предыдущий код +print(f"Обработка документа {doc_id}") + +# Новый код +import logging +logger = logging.getLogger(__name__) +logger.info(f"Обработка документа {doc_id}") +``` + +## Безопасность + +- **Никогда не логируйте конфиденциальную информацию** (пароли, API-ключи, персональные данные, токены) +- **Фильтруйте пользовательский ввод** перед логированием +- **Используйте плейсхолдеры** для конфиденциальных полей: `user_id=****1234` +- **Используйте аутентификацию** для Loki с помощью `--loki-username` и `--loki-password` в производственной среде +- **Безопасный транспорт**: Используйте HTTPS для URL Loki в производственной среде: `https://loki.prod:3100/loki/api/v1/push` + +## Обзор конфигурации + +| Аргумент | Значение по умолчанию | Переменная окружения | Описание | +|---|---|---|---| +| `--log-level` | `INFO` | - | Уровень логирования в консоли и Loki | +| `--loki-enabled` | `True` | - | Включить логирование Loki | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | URL для отправки логов в Loki | +| `--loki-username` | `None` | `LOKI_USERNAME` | Имя пользователя для аутентификации Loki | +| `--loki-password` | `None` | `LOKI_PASSWORD` | Пароль для аутентификации Loki | diff --git a/docs/tech-specs/logging-strategy.sw.md b/docs/tech-specs/logging-strategy.sw.md new file mode 100644 index 00000000..a4593701 --- /dev/null +++ b/docs/tech-specs/logging-strategy.sw.md @@ -0,0 +1,358 @@ +--- +layout: default +title: "Mbinu ya Uandikaji (Logging) ya TrustGraph" +parent: "Swahili (Beta)" +--- + +# Mbinu ya Uandikaji (Logging) ya TrustGraph + +> **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 + +TrustGraph hutumia moduli iliyojumuishwa ya Python `logging` kwa operesheni zote za uandikaji, pamoja na usanidi uliokatikati na ujumuishaji wa Loki wa hiari kwa ukusanyaji wa matangazo. Hii hutoa mbinu iliyoendeshwa na kikao, inayobadilika kwa uandikaji katika vipengele vyote vya mfumo. + +## Mpangilio Chaguwa + +### Kigezo cha Uandikaji +**Kigezo Chaguwa**: `INFO` +**Inayoweza kusanidiwa kupitia**: hoja ya mstari wa amri `--log-level` +**Chaguo**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### Vituo vya Matokeo +1. **Kikonsoli (stdout)**: Daima inaanzishwa - huhakikisha utangamano na mazingira yaliyofungwa. +2. **Loki**: Ukusanyaji wa matangazo uliokatikati wa hiari (inaanzishwa kwa chaguwa, inaweza kuzimwa). + +## Moduli ya Uandikaji Iliyokatikati + +Mpangilio wote wa uandikaji unadhibitiwa na moduli `trustgraph.base.logging`, ambayo hutoa: +`add_logging_args(parser)` - Inaongeza hoja za kawaida za CLI za uandikaji. +`setup_logging(args)` - Inasanidi uandikaji kutoka kwa hoja zilizochanganuliwa. + +Moduli hii inatumika na vipengele vyote vya upande wa seva: +Huduma zinazotegemea AsyncProcessor +API Gateway +MCP Server + +## Miongozo ya Utendaji + +### 1. Uanzishaji wa Kichunguzi + +Kila moduli inapaswa kuunda kichunguzi chake mwenyewe kwa kutumia moduli ya `__name__`: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +Jina la kichujio hutumika kiotomatiki kama lebo katika Loki kwa ajili ya kuchujua na kutafuta. + +### 2. Uanzishaji wa Huduma + +Huduma zote za upande wa seva hupokea kiotomatiki usanidi wa uandishi wa matukio kupitia moduli ya kituo: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Add standard logging arguments (includes Loki configuration) + add_logging_args(parser) + + # Add your service-specific arguments + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Setup logging early in startup + setup_logging(args) + + # Rest of your service initialization + logger = logging.getLogger(__name__) + logger.info("Service starting...") +``` + +### 3. Vigezo vya Kamba ya Amri + +Huduma zote zinaunga mkono vigezo hivi vya uandishi wa matukio: + +**Kiwango cha Uandishi:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**Mipangilio ya Loki:** +```bash +--loki-enabled # Enable Loki (default) +--no-loki-enabled # Disable Loki +--loki-url URL # Loki push URL (default: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Optional authentication +--loki-password PASSWORD # Optional authentication +``` + +**Mfano:** +```bash +# Default - INFO level, Loki enabled +./my-service + +# Debug mode, console only +./my-service --log-level DEBUG --no-loki-enabled + +# Custom Loki server with auth +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. Vigezo vya Mazingira + +Usanidi wa Loki unaounga mkono utumizi wa vigezo vya mazingira kama chaguo-mbadala: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +Vigezo vya mstari wa amana hupendelewa kuliko vigezo vya mazingira. + +### 5. Mbinu Bora za Uandishi wa Matukio + +#### Matumizi ya Viwango vya Matukio +**DEBUG**: Habari za kina kwa ajili ya utambuzi wa matatizo (maelezo ya vigezo, kuingia/kuacha kazi) +**INFO**: Jumbe za habari za jumla (huduma ilianza, usanidi ulipakuliwa, hatua muhimu za usindikaji) +**WARNING**: Jumbe za onyo kwa hali ambazo zinaweza kuwa hatari (vipengele vilivyomalizwa, makosa yanayoweza kutatuliwa) +**ERROR**: Jumbe za makosa kwa matatizo makubwa (operesheni zilizoendea, ukiukaji) +**CRITICAL**: Jumbe muhimu kwa ajili ya hitilafu za mfumo zinazohitaji uangalifu wa haraka + +#### Muundo wa Jumbe +```python +# Good - includes context +logger.info(f"Processing document: {doc_id}, size: {doc_size} bytes") +logger.error(f"Failed to connect to database: {error}", exc_info=True) + +# Avoid - lacks context +logger.info("Processing document") +logger.error("Connection failed") +``` + +#### Mawazo ya Utendaji +```python +# Use lazy formatting for expensive operations +logger.debug("Expensive operation result: %s", expensive_function()) + +# Check log level for very expensive debug operations +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Debug data: {debug_data}") +``` + +### 6. Uandikaji Maelezo Ulio Pamoja na Muundo Ukitumia Loki + +Kwa data ngumu, tumia uandikaji maelezo uliopangwa na lebo za ziada kwa ajili ya Loki: + +```python +logger.info("Request processed", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +Alama hizi zinakuwa lebo zinazoweza kutafutwa katika Loki, pamoja na lebo za kiotomatiki: +`severity` - Kiwango cha matukio (DEBUG, INFO, WARNING, ERROR, CRITICAL) +`logger` - Jina la moduli (kutoka `__name__`) + +### 7. Uandikaji wa Matukio ya Aina ya Makosa + +Daima jumuisha maandishi ya mfuatano wa mazingira kwa matukio ya aina ya makosa: + +```python +try: + process_data() +except Exception as e: + logger.error(f"Failed to process data: {e}", exc_info=True) + raise +``` + +### 8. Mambo ya Kuzingatia Kuhusu Uandikaji wa Matukio (Logging) ya Aina ya Async + +Mfumo wa uandikaji wa matukio hutumia vichuja (handlers) visivyozuia (non-blocking) vilivyopangwa kwa Loki: +Matokeo ya konseli ni ya aina moja kwa moja (haraka) +Matokeo ya Loki yanapangwa na buffer ya ujumbe 500 +Mfumo wa nyuma hushughulikia usambazaji wa Loki +Hakuna kuzuiliwa kwa msimbo mkuu wa programu + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # Logging is thread-safe and won't block async operations + logger.info(f"Starting async operation in task: {asyncio.current_task().get_name()}") +``` + +## Uunganisho wa Loki + +### Muundo + +Mfumo wa uandikaji matumizi hutumia `QueueHandler` na `QueueListener` zilizojumuishwa katika Python kwa uunganisho wa Loki usiozuia: + +1. **QueueHandler**: Matukio yanawekwa kwenye folyo ya ujumbe 500 (hayazuilii) +2. **Mfululizo wa Nyuma**: QueueListener hutuma matukio kwa Loki kwa njia isiyo ya moja kwa moja +3. **Upunguzaji wa Kawaida**: Ikiwa Loki haipatikani, uandikaji matukio kwenye konsi unaendelea + +### Laha za Otomatiki + +Kila tukio linalotumwa kwa Loki linajumuisha: +`processor`: Kitambulisho cha kichakata (k.m., `config-svc`, `text-completion`, `embeddings`) +`severity`: Kiwango cha matukio (DEBUG, INFO, n.k.) +`logger`: Jina la moduli (k.m., `trustgraph.gateway.service`, `trustgraph.agent.react.service`) + +### Laha za Msingi + +Ongeza laha za msingi kupitia parameter ya `extra`: + +```python +logger.info("User action", extra={ + 'tags': { + 'user_id': user_id, + 'action': 'document_upload', + 'collection': collection_name + } +}) +``` + +### Kuuliza Kumbukumbu katika Loki + +```logql +# All logs from a specific processor (recommended - matches Prometheus metrics) +{processor="config-svc"} +{processor="text-completion"} +{processor="embeddings"} + +# Error logs from a specific processor +{processor="config-svc", severity="ERROR"} + +# Error logs from all processors +{severity="ERROR"} + +# Logs from a specific processor with text filter +{processor="text-completion"} |= "Processing" + +# All logs from API gateway +{processor="api-gateway"} + +# Logs from processors matching pattern +{processor=~".*-completion"} + +# Logs with custom tags +{processor="api-gateway"} | json | user_id="12345" +``` + +### Upunguzaji wa Athari (Graceful Degradation) + +Ikiwa Loki haipatikani au `python-logging-loki` haijafunguliwa: +Ujumbe wa onyo huonyeshwa kwenye konsoli +Uandikaji kwenye konsoli unaendelea kama kawaida +Programu inaendelea kuendeshwa +Hakuna mfumo wa kujaribu tena muunganisho wa Loki (fainda haraka, punguza athari) + +## Majaribio + +Wakati wa majaribio, fikiria kutumia usanidi tofauti wa uandikaji: + +```python +# In test setup +import logging + +# Reduce noise during tests +logging.getLogger().setLevel(logging.WARNING) + +# Or disable Loki for tests +setup_logging({'log_level': 'WARNING', 'loki_enabled': False}) +``` + +## Ufuatiliaji wa Uunganishaji + +### Muundo wa Kawaida +Matumizi yote ya rekodi hutumia muundo unaofuata sheria: +``` +2025-01-09 10:30:45,123 - trustgraph.gateway.service - INFO - Request processed +``` + +Vipengele vya muundo: +Wakati (muundo wa ISO na milisekundi) +Jina la kisajili (njia ya moduli) +Kiwango cha kisajili +Ujumbe + +### Maswali ya Loki kwa Ufuatiliaji + +Maswali ya kawaida ya ufuatiliaji: + +```logql +# Error rate by processor +rate({severity="ERROR"}[5m]) by (processor) + +# Top error-producing processors +topk(5, count_over_time({severity="ERROR"}[1h]) by (processor)) + +# Recent errors with processor name +{severity="ERROR"} | line_format "{{.processor}}: {{.message}}" + +# All agent processors +{processor=~".*agent.*"} |= "exception" + +# Specific processor error count +count_over_time({processor="config-svc", severity="ERROR"}[1h]) +``` + +## Mambo ya Kuzingatia Kuhusu Usalama + +**Usisahirishe kamwe taarifa nyeti** (manenosi, funguo za API, data ya kibinafsi, alama) +**Safisha pembejeo za mtumiaji** kabla ya kuzisajili +**Tumia nafasi za kubadilika** kwa sehemu nyeti: `user_id=****1234` +**Uthibitishaji wa Loki**: Tumia `--loki-username` na `--loki-password` kwa matumizi salama +**Usafiri salama**: Tumia HTTPS kwa URL ya Loki katika mazingira ya uzalishaji: `https://loki.prod:3100/loki/api/v1/push` + +## Utegemezi + +Moduli ya uandikaji matukio ya kituo inahitaji: +`python-logging-loki` - Kwa ujumuishaji wa Loki (hiari, utendaji wa chini ikiwa haipo) + +Tayari imejumuishwa katika `trustgraph-base/pyproject.toml` na `requirements.txt`. + +## Njia ya Uhamishaji + +Kwa programu zilizopo: + +1. **Huduma ambazo tayari zinatumia AsyncProcessor**: Hakuna mabadiliko yanayohitajika, usaidizi wa Loki ni moja kwa moja +2. **Huduma ambazo hazitumii AsyncProcessor** (api-gateway, mcp-server): Tayari zimefanyiwa mabadiliko +3. **Zana za CLI**: Hayajajumuishwa - endelea kutumia print() au uandikaji matukio rahisi + +### Kutoka print() hadi uandikaji matukio: +```python +# Before +print(f"Processing document {doc_id}") + +# After +logger = logging.getLogger(__name__) +logger.info(f"Processing document {doc_id}") +``` + +## Muhtasari wa Usanidi + +| Jina la hoja | Chaguizi | Kigezo cha mazingira | Maelezo | +|----------|---------|---------------------|-------------| +| `--log-level` | `INFO` | - | Kigezo cha uingishaji wa Loki na kituo cha uendeshaji | +| `--loki-enabled` | `True` | - | Wezesha uingishaji wa Loki | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | Kifaa cha utumaji cha Loki | +| `--loki-username` | `None` | `LOKI_USERNAME` | Jina la mtumiaji la uthibitishaji wa Loki | +| `--loki-password` | `None` | `LOKI_PASSWORD` | Nenosiri la uthibitishaji wa Loki | diff --git a/docs/tech-specs/logging-strategy.tr.md b/docs/tech-specs/logging-strategy.tr.md new file mode 100644 index 00000000..dcded9cc --- /dev/null +++ b/docs/tech-specs/logging-strategy.tr.md @@ -0,0 +1,358 @@ +--- +layout: default +title: "TrustGraph Kayıt (Log) Stratejisi" +parent: "Turkish (Beta)" +--- + +# TrustGraph Kayıt (Log) Stratejisi + +> **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ış + +TrustGraph, tüm kayıt işlemlerinde Python'un yerleşik `logging` modülünü kullanır, merkezi yapılandırma ve kayıt toplama için isteğe bağlı Loki entegrasyonuna sahiptir. Bu, sistemin tüm bileşenleri için standartlaştırılmış, esnek bir kayıt yaklaşımı sağlar. + +## Varsayılan Yapılandırma + +### Kayıt Seviyesi +**Varsayılan Seviye**: `INFO` +**Yapılandırılabilir**: `--log-level` komut satırı argümanı aracılığıyla +**Seçenekler**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### Çıkış Hedefleri +1. **Konsol (stdout)**: Her zaman etkindir - konteynerleştirilmiş ortamlarla uyumluluğu sağlar. +2. **Loki**: İsteğe bağlı, merkezi kayıt toplama (varsayılan olarak etkindir, devre dışı bırakılabilir). + +## Merkezi Kayıt Modülü + +Tüm kayıt yapılandırması, aşağıdaki özellikleri sağlayan `trustgraph.base.logging` modülü tarafından yönetilir: +`add_logging_args(parser)` - Standart kayıt komut satırı argümanlarını ekler. +`setup_logging(args)` - Ayrıştırılmış argümanlardan kaydı yapılandırır. + +Bu modül, tüm sunucu tarafı bileşenleri tarafından kullanılır: +AsyncProcessor tabanlı hizmetler +API Ağ Geçidi +MCP Sunucusu + +## Uygulama Yönergeleri + +### 1. Kayıt Oluşturucu Başlatma + +Her modül, modülün `__name__`'ını kullanarak kendi kayıt oluşturucusunu oluşturmalıdır: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +Kayıt günlüğünün adı, Loki'de filtreleme ve arama için otomatik olarak bir etiket olarak kullanılır. + +### 2. Hizmet Başlatma + +Tüm sunucu tarafı hizmetleri, merkezi modül aracılığıyla otomatik olarak günlük yapılandırması alır: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # Add standard logging arguments (includes Loki configuration) + add_logging_args(parser) + + # Add your service-specific arguments + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # Setup logging early in startup + setup_logging(args) + + # Rest of your service initialization + logger = logging.getLogger(__name__) + logger.info("Service starting...") +``` + +### 3. Komut Satırı Argümanları + +Tüm hizmetler bu günlük kaydı argümanlarını destekler: + +**Günlük Seviyesi:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**Loki Yapılandırması:** +```bash +--loki-enabled # Enable Loki (default) +--no-loki-enabled # Disable Loki +--loki-url URL # Loki push URL (default: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # Optional authentication +--loki-password PASSWORD # Optional authentication +``` + +**Örnekler:** +```bash +# Default - INFO level, Loki enabled +./my-service + +# Debug mode, console only +./my-service --log-level DEBUG --no-loki-enabled + +# Custom Loki server with auth +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. Ortam Değişkenleri + +Loki yapılandırması, ortam değişkeni geri dönüşlerini destekler: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +Komut satırı argümanları, ortam değişkenlerine göre önceliklidir. + +### 5. Kayıt (Logging) İçin En İyi Uygulamalar + +#### Kayıt Seviyelerinin Kullanımı +**DEBUG**: Sorunları teşhis etmek için detaylı bilgiler (değişken değerleri, fonksiyon giriş/çıkış) +**INFO**: Genel bilgilendirici mesajlar (hizmet başlatıldı, yapılandırma yüklendi, işlem aşamaları) +**WARNING**: Potansiyel olarak tehlikeli durumlara yönelik uyarı mesajları (kullanımdan kaldırılmış özellikler, düzeltilebilir hatalar) +**ERROR**: Ciddi sorunlara yönelik hata mesajları (başarısız işlemler, istisnalar) +**CRITICAL**: Acil müdahale gerektiren sistem arızalarına yönelik kritik mesajlar + +#### Mesaj Formatı +```python +# Good - includes context +logger.info(f"Processing document: {doc_id}, size: {doc_size} bytes") +logger.error(f"Failed to connect to database: {error}", exc_info=True) + +# Avoid - lacks context +logger.info("Processing document") +logger.error("Connection failed") +``` + +#### Performans Hususları +```python +# Use lazy formatting for expensive operations +logger.debug("Expensive operation result: %s", expensive_function()) + +# Check log level for very expensive debug operations +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"Debug data: {debug_data}") +``` + +### 6. Loki ile Yapılandırılmış Günlüğe Kayıt + +Karmaşık veriler için, Loki için ek etiketlerle yapılandırılmış günlüğe kaydı kullanın: + +```python +logger.info("Request processed", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +Bu etiketler, otomatik etiketlerin yanı sıra, Loki'de aranabilir etiketler haline gelir: +`severity` - Log seviyesi (DEBUG, INFO, WARNING, ERROR, CRITICAL) +`logger` - Modül adı (`__name__`'den) + +### 7. İstisna Kaydı + +İstisnalar için her zaman yığın izlerini ekleyin: + +```python +try: + process_data() +except Exception as e: + logger.error(f"Failed to process data: {e}", exc_info=True) + raise +``` + +### 8. Asenkron Kayıt (Logging) Hususları + +Kayıt sistemi, Loki için engellemeyen, kuyruklu işleyiciler kullanır: +Konsol çıktısı senkron (hızlıdır) +Loki çıktısı, 500 mesajlık bir arabellekle kuyruğa alınır +Arka plan iş parçacığı, Loki iletimini yönetir +Ana uygulama kodunun engellenmesi olmaz + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # Logging is thread-safe and won't block async operations + logger.info(f"Starting async operation in task: {asyncio.current_task().get_name()}") +``` + +## Loki Entegrasyonu + +### Mimari + +Günlük sistemi, engellemeyen Loki entegrasyonu için Python'un yerleşik `QueueHandler` ve `QueueListener` özelliklerini kullanır: + +1. **QueueHandler**: Günlükler, 500 mesajlık bir kuyruğa (engellemesiz) yerleştirilir. +2. **Arka Plan İş Parçacığı**: QueueListener, günlükleri Loki'ye asenkron olarak gönderir. +3. **Usulüne Uygun Bozulma**: Loki kullanılamıyorsa, konsol günlüğü devam eder. + +### Otomatik Etiketler + +Loki'ye gönderilen her günlük şunları içerir: +`processor`: İşlemci kimliği (örneğin, `config-svc`, `text-completion`, `embeddings`) +`severity`: Günlük seviyesi (DEBUG, INFO, vb.) +`logger`: Modül adı (örneğin, `trustgraph.gateway.service`, `trustgraph.agent.react.service`) + +### Özel Etiketler + +Özel etiketleri `extra` parametresi aracılığıyla ekleyin: + +```python +logger.info("User action", extra={ + 'tags': { + 'user_id': user_id, + 'action': 'document_upload', + 'collection': collection_name + } +}) +``` + +### Loki'de Logları Sorgulama + +```logql +# All logs from a specific processor (recommended - matches Prometheus metrics) +{processor="config-svc"} +{processor="text-completion"} +{processor="embeddings"} + +# Error logs from a specific processor +{processor="config-svc", severity="ERROR"} + +# Error logs from all processors +{severity="ERROR"} + +# Logs from a specific processor with text filter +{processor="text-completion"} |= "Processing" + +# All logs from API gateway +{processor="api-gateway"} + +# Logs from processors matching pattern +{processor=~".*-completion"} + +# Logs with custom tags +{processor="api-gateway"} | json | user_id="12345" +``` + +### Zarif Bozulma + +Eğer Loki kullanılamıyorsa veya `python-logging-loki` yüklü değilse: +Uyarı mesajı konsola yazdırılır +Konsol kaydı normal şekilde devam eder +Uygulama çalışmaya devam eder +Loki bağlantısı için tekrar deneme mantığı yoktur (hızlı bir şekilde başarısız olun, zarif bir şekilde bozulun) + +## Test + +Testler sırasında, farklı bir kayıt yapılandırması kullanmayı düşünün: + +```python +# In test setup +import logging + +# Reduce noise during tests +logging.getLogger().setLevel(logging.WARNING) + +# Or disable Loki for tests +setup_logging({'log_level': 'WARNING', 'loki_enabled': False}) +``` + +## İzleme Entegrasyonu + +### Standart Format +Tüm günlükler tutarlı bir formata sahiptir: +``` +2025-01-09 10:30:45,123 - trustgraph.gateway.service - INFO - Request processed +``` + +Biçim öğeleri: +Zaman damgası (milisaniyelerle birlikte ISO formatı) +Kayıt yöneticisi adı (modül yolu) +Kayıt düzeyi +Mesaj + +### İzleme için Loki Sorguları + +Yaygın izleme sorguları: + +```logql +# Error rate by processor +rate({severity="ERROR"}[5m]) by (processor) + +# Top error-producing processors +topk(5, count_over_time({severity="ERROR"}[1h]) by (processor)) + +# Recent errors with processor name +{severity="ERROR"} | line_format "{{.processor}}: {{.message}}" + +# All agent processors +{processor=~".*agent.*"} |= "exception" + +# Specific processor error count +count_over_time({processor="config-svc", severity="ERROR"}[1h]) +``` + +## Güvenlik Hususları + +**Hassas bilgileri asla kaydetmeyin** (şifreler, API anahtarları, kişisel veriler, token'lar) +**Kayıt işleminden önce kullanıcı girişini temizleyin** +**Hassas alanlar için yer tutucular kullanın**: `user_id=****1234` +**Loki kimlik doğrulaması**: Güvenli dağıtımlar için `--loki-username` ve `--loki-password`'i kullanın +**Güvenli taşıma**: Üretimde Loki URL'si için HTTPS kullanın: `https://loki.prod:3100/loki/api/v1/push` + +## Bağımlılıklar + +Merkezi günlük kaydı modülü şunları gerektirir: +`python-logging-loki` - Loki entegrasyonu için (isteğe bağlı, eksikse sorunsuz bir şekilde çalışır) + +Zaten `trustgraph-base/pyproject.toml` ve `requirements.txt` içinde bulunmaktadır. + +## Geçiş Yolu + +Mevcut kod için: + +1. **AsyncProcessor kullanan hizmetler**: Herhangi bir değişiklik gerekmez, Loki desteği otomatik olarak sağlanır +2. **AsyncProcessor kullanmayan hizmetler** (api-gateway, mcp-server): Zaten güncellenmiştir +3. **CLI araçları**: Kapsam dışındadır - print() veya basit günlük kaydını kullanmaya devam edin + +### print()'ten günlük kaydına: +```python +# Before +print(f"Processing document {doc_id}") + +# After +logger = logging.getLogger(__name__) +logger.info(f"Processing document {doc_id}") +``` + +## Yapılandırma Özeti + +| Argüman | Varsayılan Değer | Ortam Değişkeni | Açıklama | +|----------|---------|---------------------|-------------| +| `--log-level` | `INFO` | - | Konsol ve Loki log seviyesi | +| `--loki-enabled` | `True` | - | Loki log kaydını etkinleştir | +| `--loki-url` | `http://loki:3100/loki/api/v1/push` | `LOKI_URL` | Loki push endpoint'i | +| `--loki-username` | `None` | `LOKI_USERNAME` | Loki kimlik doğrulama kullanıcı adı | +| `--loki-password` | `None` | `LOKI_PASSWORD` | Loki kimlik doğrulama parolası | diff --git a/docs/tech-specs/logging-strategy.zh-cn.md b/docs/tech-specs/logging-strategy.zh-cn.md new file mode 100644 index 00000000..17c5650a --- /dev/null +++ b/docs/tech-specs/logging-strategy.zh-cn.md @@ -0,0 +1,231 @@ +--- +layout: default +title: "默认 - INFO 级别,启用 Loki" +parent: "Chinese (Beta)" +--- + +## TrustGraph 日志策略 + +## 概述 + +TrustGraph 使用 Python 内置的 `logging` 模块进行所有日志操作,并具有集中配置以及可选的 Loki 集成,用于日志聚合。 这提供了一种标准且灵活的方式,可在系统的所有组件中进行日志记录。 + +## 默认配置 + +### 日志级别 +- **默认级别**: `INFO` +- **可通过**: `--log-level` 命令行参数配置 +- **选项**: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` + +### 输出目标 +1. **控制台 (stdout)**: 始终启用 - 确保与容器化环境兼容 +2. **Loki**: 可选的集中式日志聚合 (默认启用,可禁用) + +## 集中式日志模块 + +所有日志配置都由 `trustgraph.base.logging` 模块管理,该模块提供: +- `add_logging_args(parser)` - 添加标准的日志 CLI 参数 +- `setup_logging(args)` - 从解析的参数配置日志 + +该模块用于所有服务器端组件: +- 基于 AsyncProcessor 的服务 +- API 网关 +- MCP 服务器 + +## 实现指南 + +### 1. 日志记录器初始化 + +每个模块应使用模块的 `__name__` 创建自己的日志记录器: + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +日志记录器的名称会自动用作在 Loki 中用于过滤和搜索的标签。 + +### 2. 服务初始化 + +所有服务器端服务都通过集中化模块自动获取日志配置: + +```python +from trustgraph.base import add_logging_args, setup_logging +import argparse + +def main(): + parser = argparse.ArgumentParser() + + # 添加标准的日志参数 (包括 Loki 配置) + add_logging_args(parser) + + # 添加您自己的服务特定的参数 + parser.add_argument('--port', type=int, default=8080) + + args = parser.parse_args() + args = vars(args) + + # 提前设置日志 + setup_logging(args) + + # 剩余的服务初始化 + logger = logging.getLogger(__name__) + logger.info("服务开始...") +``` + +### 3. 命令行参数 + +所有服务都支持以下日志参数: + +**日志级别:** +```bash +--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} +``` + +**Loki 配置:** +```bash +--loki-enabled # 启用 Loki (默认) +--no-loki-enabled # 禁用 Loki +--loki-url URL # Loki 推送 URL (默认: http://loki:3100/loki/api/v1/push) +--loki-username USERNAME # 可选身份验证 +--loki-password PASSWORD # 可选身份验证 +``` + +**示例:** +```bash +# 默认 - INFO 级别,启用 Loki + +> **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. +./my-service + +# 调试模式,仅控制台 +./my-service --log-level DEBUG --no-loki-enabled + +# 自定义 Loki 服务器,带身份验证 +./my-service --loki-url http://loki.prod:3100/loki/api/v1/push \ + --loki-username admin --loki-password secret +``` + +### 4. 环境变量 + +Loki 配置支持环境变量的后备: + +```bash +export LOKI_URL=http://loki.prod:3100/loki/api/v1/push +export LOKI_USERNAME=admin +export LOKI_PASSWORD=secret +``` + +命令行参数优先于环境变量。 + +### 5. 日志记录最佳实践 + +#### 日志级别使用 +- **DEBUG**: 用于诊断问题的详细信息 (变量值、函数入口/退出) +- **INFO**: 通用信息消息 (服务启动、配置加载、处理里程碑) +- **WARNING**: 警告消息,用于潜在的危险情况 (弃用功能、可恢复错误) +- **ERROR**: 错误消息,用于严重问题 (失败的操作、异常) +- **CRITICAL**: 关键消息,用于系统故障,需要立即关注 + +#### 消息格式 +```python +# 良好 - 包含上下文 +logger.info(f"处理文档: {doc_id}, 大小: {doc_size} 字节") +logger.error(f"无法连接到数据库: {error}", exc_info=True) + +# 不好 - 缺少上下文 +logger.info("处理文档") +logger.error("连接失败") +``` + +#### 性能考虑 +```python +# 使用延迟格式化进行昂贵的操作 +logger.debug("昂贵操作结果: %s", expensive_function()) + +# 检查日志级别以进行非常昂贵的调试操作 +if logger.isEnabledFor(logging.DEBUG): + debug_data = compute_expensive_debug_info() + logger.debug(f"调试数据: {debug_data}") +``` + +### 6. 使用 Loki 的结构化日志记录 + +对于复杂的结构化数据,可以使用结构化日志记录,并添加额外的标签以供 Loki 使用: + +```python +logger.info("请求已处理", extra={ + 'tags': { + 'request_id': request_id, + 'user_id': user_id, + 'status': 'success' + } +}) +``` + +这些标签将作为 Loki 中的可搜索标签: +- `severity` - 日志级别 (DEBUG, INFO, 等) +- `logger` - 模块名称 (来自 `__name__`) + +### 7. 异常日志记录 + +始终包含异常堆栈跟踪: + +```python +try: + process_data() +except Exception as e: + logger.error(f"无法处理数据: {e}", exc_info=True) + raise +``` + +### 8. 异步日志记录的注意事项 + +日志系统使用非阻塞的队列处理程序进行 Loki 集成: +- 控制台输出是同步的 (快速) +- Loki 输出是异步排队 (500 条消息缓冲区) +- 后台线程处理 Loki 传输 +- 没有阻塞主应用程序代码 + +```python +import asyncio +import logging + +async def async_operation(): + logger = logging.getLogger(__name__) + # 日志记录是线程安全的,不会阻塞异步操作 + logger.info(f"在任务中开始异步操作: {asyncio.current_task().get_name()}") +``` + +## Loki 集成 + +### 架构 + +日志系统使用 Python 内置的 `logging` 模块进行 Loki 集成: +- `python-logging-loki` - 用于 Loki 集成 (可选,如果缺少则回退) + +已经在 `trustgraph-base/pyproject.toml` 和 `requirements.txt` 中包含。 + +### 从 print() 到 logging: +```python +# 之前 +print(f"处理文档 {doc_id}") + +# 之后 +logger = logging.getLogger(__name__) +logger.info(f"处理文档 {doc_id}") +``` + +## 安全注意事项 + +- **永远不要记录敏感信息** (密码、API 密钥、个人数据、令牌) +- **清理用户输入** 之前进行日志记录 +- **使用占位符** 来记录敏感字段: `user_id=****1234` +- **使用 Loki 身份验证**: 对于生产环境,使用 `--loki-username` 和 `--loki-password` +- **安全传输**: 在生产中使用 HTTPS: `https://loki.prod:3100/loki/api/v1/push` + +## 依赖 + +集中式日志模块需要: +- `python-logging-loki` - 用于 Loki 集成 (可选,如果缺失则回退) diff --git a/docs/tech-specs/mcp-tool-arguments.ar.md b/docs/tech-specs/mcp-tool-arguments.ar.md new file mode 100644 index 00000000..870833ed --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.ar.md @@ -0,0 +1,163 @@ +--- +layout: default +title: "مواصفات معاملات أداة MCP" +parent: "Arabic (Beta)" +--- + +# مواصفات معاملات أداة MCP + +> **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. + +## نظرة عامة +**اسم الميزة**: دعم معاملات أداة MCP +**المؤلف**: مساعد كود كلوود +**التاريخ**: 2025-08-21 +**الحالة**: نهائية + +### ملخص تنفيذي + +تمكين عوامل ReACT من استدعاء أدوات MCP (بروتوكول سياق النموذج) مع المعاملات المحددة بشكل صحيح عن طريق إضافة دعم مواصفات المعاملات إلى تكوينات أدوات MCP، على غرار الطريقة التي تعمل بها أدوات القالب الحالية. + +### بيان المشكلة + +في الوقت الحالي، لا يمكن لأدوات MCP في إطار عمل ReACT تحديد المعاملات المتوقعة. تُرجع طريقة `McpToolImpl.get_arguments()` قائمة فارغة، مما يجبر نماذج اللغة الكبيرة (LLMs) على تخمين هيكل المعلمات بناءً على أسماء وأوصاف الأدوات فقط. هذا يؤدي إلى: +- استدعاء أدوات غير موثوق به بسبب تخمين المعلمات +- تجربة مستخدم سيئة عندما تفشل الأدوات بسبب معاملات غير صحيحة +- عدم التحقق من معلمات الأداة قبل التنفيذ +- عدم وجود توثيق لمعلمات الأداة في مطالبات الوكيل + +### الأهداف + +- [ ] السماح بتكوينات أدوات MCP بتحديد المعاملات المتوقعة (الاسم، النوع، الوصف) +- [ ] تحديث مدير الوكيل للكشف عن معاملات أداة MCP لـ LLMs عبر المطالبات +- [ ] الحفاظ على التوافق مع الإصدارات الحالية من تكوينات أدوات MCP +- [ ] دعم التحقق من صحة المعاملات على غرار أدوات القالب + +### الأهداف غير المحققة +- اكتشاف ديناميكي للمعاملات من خوادم MCP (تحسين مستقبلي) +- التحقق من نوع المعاملات بالإضافة إلى الهيكل الأساسي +- مخططات المعاملات المعقدة (الكائنات المتداخلة، المصفوفات) + +## الخلفية والسياق + +### الحالة الحالية +يتم تكوين أدوات MCP في نظام ReACT مع بيانات وصفية قليلة: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance" +} +``` + +تُرجع طريقة `McpToolImpl.get_arguments()` قائمة فارغة، لذلك لا تتلقى LLMs أي إرشادات حول المعاملات في مطالباتها. + +### القيود + +1. **عدم وجود مواصفات للمعاملات**: لا يمكن لأدوات MCP تحديد المعلمات المتوقعة + +2. **تخمين المعلمات بواسطة LLM**: يجب على الوكلاء استنتاج المعلمات من أسماء/وصف الأدوات + +3. **نقص معلومات المطالبة**: لا تعرض مطالبات الوكيل تفاصيل المعاملات لأدوات MCP + +4. **عدم التحقق**: يتم التقاط المعلمات غير الصالحة فقط عند وقت تنفيذ أداة MCP + +### المكونات ذات الصلة +- **trustgraph-flow/agent/react/service.py**: تحميل تكوين الأداة وإنشاء AgentManager +- **trustgraph-flow/agent/react/tools.py**: تنفيذ McpToolImpl +- **trustgraph-flow/agent/react/agent_manager.py**: إنشاء المطالبات بمعاملات الأداة +- **CLI tools**: أدوات سطر الأوامر لإدارة أدوات MCP +- **Workbench**: واجهة المستخدم الخارجية لتكوين أدوات الوكيل + +## المتطلبات + +### المتطلبات الوظيفية + +1. **معاملات أداة MCP**: يجب أن تدعم تكوينات أدوات MCP مصفوفة اختيارية "arguments" مع حقول الاسم والنوع والوصف +2. **الكشف عن المعاملات**: يجب أن تُرجع طريقة `McpToolImpl.get_arguments()` المعاملات المحددة بدلاً من قائمة فارغة +3. **التكامل مع المطالبة**: يجب أن تتضمن المطالبات الخاصة بالوكيل تفاصيل معامل أداة MCP عند تحديد المعاملات +4. **التوافق مع الإصدارات الحالية**: يجب أن تستمر تكوينات أدوات MCP الحالية بدون معاملات في العمل +5. **دعم CLI**: يدعم CLI الحالي `tg-invoke-mcp-tool` المعاملات (مُنفذ بالفعل) + +### المتطلبات غير الوظيفية +1. **التوافق مع الإصدارات الحالية**: لا توجد تغييرات مدمرة في تكوينات أدوات MCP الحالية +2. **الأداء**: عدم وجود تأثير كبير على توليد المطالبات للوكلاء +3. **الاتساق**: يجب أن يطابق معالجة المعاملات أنماط أدوات القالب + +### قصص المستخدم + +1. بصفتي **مطور الوكيل**: أرغب في تحديد معاملات أداة MCP في التكوين حتى تتمكن نماذج اللغة الكبيرة من استدعاء الأدوات بمعلمات صحيحة +2. بصفتي **مستخدم واجهة Workbench**: أرغب في تكوين معاملات أداة MCP في واجهة المستخدم حتى تستخدم الوكلاء الأدوات بشكل صحيح +3. بصفتي **نموذج لغة كبيرة في وكيل ReACT**: أرغب في رؤية مواصفات معامل الأداة في المطالبات حتى أتمكن من توفير المعلمات الصحيحة + +## التصميم + +### الهندسة المعمارية عالية المستوى +لتحقيق التوافق مع أنماط أدوات القالب، قم بتوسيع تكوين أداة MCP عن طريق: +1. إضافة مصفوفة اختيارية "arguments" إلى تكوينات أدوات MCP +2. تعديل `McpToolImpl` لقبول وإرجاع المعاملات المحددة +3. تحديث تحميل تكوين الأداة للتعامل مع معاملات أدوات MCP +4. التأكد من تضمين معلومات معامل أداة MCP في المطالبات + +### مخطط التكوين +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Bank account identifier" + }, + { + "name": "date", + "type": "string", + "description": "Date for balance query (optional, format: YYYY-MM-DD)" + } + ] +} +``` + +### تدفق البيانات +1. **تحميل التكوين**: يتم تحميل تكوين أداة MCP مع المعاملات بواسطة `on_tools_config()` +2. **إنشاء الأداة**: يتم تحليل المعاملات وتمريرها إلى `McpToolImpl` من خلال المُنشئ +3. **توليد المطالبة**: تتلقى LLMs معلومات المعاملات من الأداة، مما يسمح لها بإنشاء مطالبات مناسبة. +4. **تنفيذ الأداة**: يتم تنفيذ أداة MCP باستخدام المعاملات التي تم تمريرها. + +### تأثير الأداء +- **وقت تشغيل ضئيل**: يحدث تحليل المعاملات فقط أثناء تحميل التكوين، وليس لكل طلب +- **حجم المطالبة**: قد تزيد المطالبات الخاصة بالوكيل قليلاً بسبب تضمين تفاصيل معامل أداة MCP. +- **استخدام الذاكرة**: زيادة ضئيلة لتخزين مواصفات المعاملات في كائنات الأداة. + +## الوثائق + +### وثائق المستخدم +- [ ] تحديث دليل تكوين أداة MCP مع أمثلة للمعاملات +- [ ] إضافة مواصفات المعامل إلى نص مساعد أدوات سطر الأوامر +- [ ] إنشاء أمثلة لأنماط معلمات أداة MCP الشائعة + +### وثائق المطور +- [ ] تحديث وثائق فئة `McpToolImpl` +- [ ] إضافة تعليقات توضيحية حول منطق تحليل المعاملات +- [ ] توثيق تدفق المعامل في الهندسة المعمارية للنظام + +## الأسئلة المفتوحة +1. **التحقق من صحة المعاملات**: هل يجب علينا التحقق من أنواع المعاملات/تنسيقاتها بالإضافة إلى التحقق الأساسي من الهيكل؟ +2. **اكتشاف ديناميكي**: هل نريد الاستعلام عن خوادم MCP عن مخططات أدوات بشكل تلقائي؟ + +## البدائل التي تم النظر فيها +1. **اكتشاف مخططات MCP الديناميكية**: الاستعلام عن خوادم MCP عن مخططات أدوات المعامل في وقت التشغيل - تم رفضها بسبب التعقيد ومخاوف الموثوقية +2. **سجل المعاملات المنفصل**: تخزين معاملات أداة MCP في قسم تكوين منفصل - تم رفضه للحفاظ على التوافق مع نهج أدوات القالب +3. **التحقق من نوع المعامل**: التحقق الكامل من مخطط JSON للمعاملات - تم تأجيله للحفاظ على البساطة في التنفيذ الأولي + +## المراجع +- [المواصفات الخاصة ببروتوكول MCP](https://github.com/modelcontextprotocol/spec) +- [تنفيذ أداة MCP](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +- [تنفيذ أداة MCP الحالي](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## الملحق +[أي معلومات إضافية، أو مخططات، أو أمثلة] diff --git a/docs/tech-specs/mcp-tool-arguments.es.md b/docs/tech-specs/mcp-tool-arguments.es.md new file mode 100644 index 00000000..0d389dd8 --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.es.md @@ -0,0 +1,168 @@ +--- +layout: default +title: "Especificación de Argumentos para la Herramienta MCP" +parent: "Spanish (Beta)" +--- + +# Especificación de Argumentos para la Herramienta MCP + +> **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. + +## Visión General +**Nombre de la característica**: Soporte para Argumentos de la Herramienta MCP +**Autor**: Asistente de Código Claude +**Fecha**: 21/08/2025 +**Estado**: Finalizado + +### Resumen Ejecutivo + +Permitir que los agentes ReACT invoquen las herramientas MCP (Protocolo de Contexto del Modelo) con argumentos definidos correctamente, agregando soporte para la especificación de argumentos a las configuraciones de las herramientas MCP, de manera similar a como funcionan actualmente las herramientas de plantillas de prompts. + +### Declaración del Problema + +Actualmente, las herramientas MCP en el marco de agentes ReACT no pueden especificar sus argumentos esperados. El método `McpToolImpl.get_arguments()` devuelve una lista vacía, lo que obliga a los LLMs a adivinar la estructura de parámetros correcta basándose únicamente en los nombres y las descripciones de las herramientas. Esto conduce a: +- Invocaciones de herramientas poco fiables debido a la adivinación de parámetros +- Mala experiencia de usuario cuando las herramientas fallan debido a argumentos incorrectos +- Falta de validación de parámetros de la herramienta antes de la ejecución +- Falta de documentación de parámetros en los prompts del agente + +### Objetivos + +- [ ] Permitir que las configuraciones de las herramientas MCP especifiquen los argumentos esperados (nombre, tipo, descripción) +- [ ] Actualizar el administrador de agentes para exponer los argumentos de las herramientas MCP a los LLMs a través de prompts +- [ ] Mantener la compatibilidad hacia atrás con las configuraciones existentes de las herramientas MCP +- [ ] Soporte para la validación de argumentos similar a las herramientas de plantillas de prompts + +### Objetivos No +- Descubrimiento dinámico de argumentos de los servidores MCP (mejoras futuras) +- Validación de tipos de argumentos más allá de la estructura básica +- Esquemas de argumentos complejos (objetos anidados, arrays) + +## Antecedentes y Contexto + +### Estado Actual +Las herramientas MCP se configuran en el sistema de agente ReACT con metadatos mínimos: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Obtener el saldo de la cuenta bancaria", + "mcp-tool": "get_bank_balance" +} +``` + +El método `McpToolImpl.get_arguments()` devuelve `[]`, lo que significa que los LLMs no reciben ninguna guía de argumentos en sus prompts. + +### Limitaciones + +1. **Sin especificación de argumentos**: Las herramientas MCP no pueden definir parámetros esperados + +2. **Inferencia de parámetros por parte del LLM**: Los agentes deben deducir parámetros a partir de los nombres/descripciones de las herramientas + +3. **Falta de información en el prompt**: Los prompts de los agentes no muestran detalles de los argumentos para las herramientas MCP + +4. **Sin validación**: Los parámetros inválidos solo se detectan en el momento de la ejecución de la herramienta MCP + +### Componentes Relacionados +- **trustgraph-flow/agent/react/service.py**: Carga de la configuración de las herramientas y creación del AgentManager +- **trustgraph-flow/agent/react/tools.py**: Implementación de McpToolImpl +- **trustgraph-flow/agent/react/agent_manager.py**: Generación de prompts con argumentos de las herramientas +- **CLI tools**: Herramientas de línea de comandos para la gestión de herramientas MCP +- **Workbench**: Interfaz de usuario externa para la configuración de las herramientas de los agentes + +## Requisitos + +### Requisitos Funcionales + +1. **Argumentos de la Configuración de la Herramienta MCP**: Las configuraciones de las herramientas MCP **DEBEN** soportar un array opcional de `arguments` con campos de nombre, tipo y descripción +2. **Exposición de Argumentos**: El método `McpToolImpl.get_arguments()` **DEBE** devolver los argumentos configurados en lugar de una lista vacía +3. **Integración en el Prompt**: Los prompts de los agentes **DEBEN** incluir detalles de los argumentos de las herramientas MCP cuando se especifican +4. **Compatibilidad hacia atrás**: Las configuraciones existentes de las herramientas MCP sin argumentos **DEBEN** seguir funcionando +5. **Soporte CLI**: Las herramientas CLI existentes (`tg-invoke-mcp-tool`) soportan argumentos (ya implementado) + +### Requisitos No Funcionales +1. **Compatibilidad hacia atrás**: Sin cambios que rompan con las configuraciones existentes de las herramientas MCP +2. **Rendimiento**: Sin impacto significativo en el rendimiento de la generación de prompts +3. **Consistencia**: El manejo de argumentos **DEBE** seguir los patrones de las herramientas de plantillas de prompts + +### Historias de Usuario + +1. Como **desarrollador de agentes**, quiero especificar argumentos para las herramientas MCP en la configuración, para que los LLMs puedan invocar las herramientas con los parámetros correctos +2. Como **usuario de Workbench**, quiero configurar argumentos para las herramientas MCP en la interfaz de usuario, para que los agentes usen las herramientas correctamente +3. Como **LLM en un agente ReACT**, quiero ver las especificaciones de argumentos de las herramientas en los prompts, para poder proporcionar los parámetros correctos + +## Diseño + +### Arquitectura de Alto Nivel +Extender la configuración de las herramientas MCP para que coincidan con el patrón de las plantillas de prompts, agregando: +1. Un array opcional de `arguments` a las configuraciones de las herramientas MCP +2. Modificar `McpToolImpl` para aceptar y devolver los argumentos configurados +3. Actualizar la carga de la configuración de las herramientas para manejar los argumentos de las herramientas MCP +4. Asegurar que los prompts de los agentes incluyan información sobre los argumentos de las herramientas MCP + +### Esquema de Configuración +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Obtener el saldo de la cuenta bancaria", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Identificador de la cuenta bancaria" + }, + { + "name": "date", + "type": "string", + "description": "Fecha para la consulta de saldo (opcional, formato: YYYY-MM-DD)" + } + ] +} +``` + +### Flujo de Datos +1. **Carga de la configuración**: La configuración de la herramienta MCP con argumentos se carga por `on_tools_config()` +2. **Creación de la herramienta**: Los argumentos se parsean y se pasan a `McpToolImpl` a través del constructor +3. **Generación del prompt**: `agent_manager.py` llama a `tool.arguments` para incluirlos en los prompts de los LLMs +4. **Invocación de la herramienta**: El LLM proporciona los parámetros, que se pasan sin cambios a las herramientas MCP + +## Consideraciones de Seguridad +- **Sin nueva superficie de ataque**: Los argumentos se parsean a partir de las fuentes de configuración existentes sin nuevas entradas +- **Validación de parámetros**: Los argumentos se pasan a las herramientas MCP sin cambios - la validación permanece a nivel de la herramienta MCP +- **Integridad de la configuración**: Las especificaciones de argumentos son parte de la configuración de la herramienta - el mismo modelo de seguridad aplica + +## Impacto en el Rendimiento +- **Sobrehead mínimo**: El análisis de argumentos ocurre solo durante la carga de la configuración, no por solicitud +- **Aumento del tamaño del prompt**: Los prompts del agente incluirán detalles de los argumentos de las herramientas MCP, aumentando ligeramente el uso de tokens +- **Uso de la memoria**: Aumento insignificante para almacenar las especificaciones de argumentos en los objetos de la herramienta + +## Documentación + +### Documentación del Usuario +- [ ] Actualizar la guía de configuración de las herramientas MCP con ejemplos de argumentos +- [ ] Agregar especificación de argumentos a la ayuda de la línea de comandos +- [ ] Crear ejemplos de patrones comunes de argumentos de la herramienta MCP + +### Documentación del Desarrollador +- [ ] Documentar la clase `McpToolImpl` con la lógica de análisis de argumentos +- [ ] Agregar comentarios en el código para la lógica de análisis de argumentos +- [ ] Documentar el flujo de argumentos en la arquitectura del sistema + +## Preguntas Abiertas +1. **Validación de tipos**: ¿Deberíamos validar los tipos/formatos de los argumentos más allá de una verificación básica de estructura? +2. **Descubrimiento dinámico**: ¿Una futura mejora para consultar automáticamente los esquemas de las herramientas MCP de los servidores? + +## Alternativas Consideradas +1. **Descubrimiento dinámico de esquemas MCP**: Consultar los servidores MCP para obtener los esquemas de las herramientas a tiempo de ejecución - rechazado debido a preocupaciones de complejidad y fiabilidad +2. **Registro de argumentos separado**: Almacenar los argumentos de las herramientas MCP en una sección de configuración separada - rechazado por mantener la consistencia con el enfoque de las plantillas de prompts +3. **Validación de tipo**: Validación completa de esquema JSON para los argumentos - aplazado como una mejora futura para mantener la implementación inicial simple + +## Referencias +- [Especificación del Protocolo MCP](https://github.com/modelcontextprotocol/spec) +- [Implementación de las herramientas MCP](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +- [Implementación actual de las herramientas MCP](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## Apéndice +[Cualquier información, diagramas o ejemplos adicionales] diff --git a/docs/tech-specs/mcp-tool-arguments.he.md b/docs/tech-specs/mcp-tool-arguments.he.md new file mode 100644 index 00000000..7fd1788e --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.he.md @@ -0,0 +1,126 @@ +--- +layout: default +title: "מפרט ארגומנטים של כלי MCP" +parent: "Hebrew (Beta)" +--- + +# מפרט ארגומנטים של כלי MCP + +> **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. + +## סקירה כללית +**שם פיצ'ר**: תמיכה בארגומנטים של כלי MCP +**מחבר**: עוזר קוד של Claude +**תאריך**: 2025-08-21 +**סטטוס**: סופי + +### סיכום מנהלים + +לאפשר למייצגי ReACT להפעיל כלי MCP (פרוטוקול הקשר של מודל) עם +ארגומנטים מוגדרים כראוי, על ידי הוספת תמיכה במפרט ארגומנטים +ליצור הגדרות כלי MCP, בדומה לאופן שבו כלי תבנית הנחייה +פועלים כיום. + +### הצגת הבעיה + +כרגע, כלי MCP בתוך מסגרת ה-ReACT אינם יכולים לציין את +הארגומנטים הצפויים שלהם. מתודת `McpToolImpl.get_arguments()` +מחזירה רשימה ריקה, ולכן LLMs חייבים לנחש את המבנה של הפרמטרים +רק על סמך שמות וכותרות כלים. זה גורם ל: +- קריאות כלים לא אמינות עקב ניחוש פרמטרים +- חוויית משתמש גרועה כאשר כלים נכשלים עקב ארגומנטים שגויים +- אי אימות של פרמטרי כלים לפני ביצוע +- אי עליית תיעוד פרמטרים בהנחיית הסוכן + +### מטרות + +- [ ] לאפשר להגדרות כלי MCP לציין ארגומנטים צפויים (שם, סוג, תיאור) +- [ ] לעדכן את מנהל הסוכן כדי לחשוף ארגומנטי כלי MCP ל-LLMs באמצעות הנחיה +- [ ] לשמור על תאימות לאחור להגדרות כלי MCP קיימות +- [ ] לתמוך באימות ארגומנטים בדומה לכלי תבנית הנחיה + +### מטרות לא +- גילוי דינמי של ארגומנטים מהשרתים של MCP (שיפור עתידי) +- אימות סוגי ארגומנט מעבר למבנה בסיסי +- סכימות ארגומנטים מורכבות (אובייקטים מקובצים, מערכים) + +## רקע והקשר + +### מצב נוכחי +כלי MCP מוגדרים במערכת ה-ReACT עם מידע מינימלי: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance" +} +``` + +המתודת `McpToolImpl.get_arguments()` מחזירה `[]`, ולכן LLMs לא מקבלים הדרכה לגבי ארגומנטים בהנחייתם. + +### מגבלות +1. **אין מפרט ארגומנטים**: כלי MCP אינם יכולים להגדיר פרמטרים צפויים +2. **ניחוש פרמטרים על ידי LLM**: הסוכן חייב להסיק פרמטרים משמות/תיאורים של כלים +3. **מידע הנחיה חסר**: הנחיות הסוכן אינן מציגות פרטים לגבי ארגומנטים של כלי MCP +4. **אין אימות**: פרמטרים לא חוקיים מתגלים רק בזמן ביצוע כלי MCP + +### רכיבים קשורים +- **trustgraph-flow/agent/react/service.py**: טעינת הגדרות כלי וליצירת מנהל סוכן +- **trustgraph-flow/agent/react/tools.py**: יישום של McpToolImpl +- **trustgraph-flow/agent/react/agent_manager.py**: יצירת הנחיה עם ארגומנטי כלי +- **trustgraph-cli**: כלים של שורת פקודה לניהול כלי MCP +- **Workbench**: ממשק משתמש חיצוני להגדרת כלי סוכן + +## דרישות + +### דרישות פונקציונליות +1. **הגדרות ארגומנטים של כלי MCP**: הגדרות כלי MCP חייבות לתמוך במערך אופציונלי של `arguments` עם שדות שם, סוג ותיאור +2. **חשיפת ארגומנטים**: `McpToolImpl.get_arguments()` חייב להחזיר את הארגומנטים המוגדרים במקום רשימה ריקה +3. **אינטגרציה עם הנחיה**: הנחיית הסוכן חייבת לכלול פרטים של ארגומנטי כלי MCP כאשר הם מוגדרים +4. **תאימות לאחור**: הגדרות כלי MCP קיימות ללא ארגומנטים חייבות להמשיך לעבוד +5. **תמיכה ב-CLI**: כלי ה-CLI הקיים `tg-invoke-mcp-tool` תומך בארגומנטים (כבר מיושם) + +### דרישות לא פונקציונליות +1. **תאימות לאחור**: ללא שינויים שמשבשים בהגדרות כלי MCP קיימות +2. **ביצועים**: ללא השפעה משמעותית על יצירת הנחיות סוכן +3. **עקביות**: טיפול בארגומנטים חייב להתאים לתבניות של כלי תבנית הנחיה + +### סיפורי משתמש +1. כ**מפתח סוכן**, אני רוצה לציין ארגומנטים של כלי MCP בהגדרות, כך ש-LLMs יוכלו להפעיל כלים עם פרמטרים נכונים +2. כ**משתמש ב-Workbench**, אני רוצה להגדיר ארגומנטים של כלי MCP בממשק ה-UI, כך שהסוכן ישתמש בכלים כראוי +3. כ**LLM בסוכן ReACT**, אני רוצה לראות את המפרט של ארגומנטי כלי בהנחיות, כך שאוכל לספק פרמטרים נכונים + +## עיצוב + +### ארכיטקטורה ברמה גבוהה +להרחיב את הגדרת כלי MCP כך שתתאים לתבנית כלי תבנית הנחיה על ידי: +1. הוספת מערך אופציונלי של `arguments` להגדרות כלי MCP +2. שינוי המחלקה `McpToolImpl` כדי לקבל את הארגומנטים +3. לשמור על התאמה לאחור להגדרות כלי MCP קיימות + +### דוגמה +```python +class McpToolImpl: + def get_arguments(self): + # ... קוד לקבלת ארגומנטים ... + return arguments +``` + +## שאלות פתוחות +1. **אימות ארגומנטים**: האם אמור להיות אימות סוגים/פורמטים של ארגומנט מעבר לבדיקות מבני בסיסיות? +2. **גילוי דינמי**: האם עדיף לשאול את שרתי ה-MCP עבור סכימות כלי באופן אוטומטי? +3. **מבנה ארגומנטים**: האם הארגומנטים צריכים להיות בפורמט מובנה (לדוגמה, JSON)? + +## אפשרויות שנשקלו +1. **גילוי דינמי של סכימת MCP**: לשאול את שרתי ה-MCP עבור סכימות של כלי בזמן ריצה - נדחה עקב מורכבות וחששות לגבי אמינות +2. **רשום ארגומנטים נפרד**: לאחסן את ארגומנטי הכלי בפרטי הגדרה נפרדים - נדחה עקב עקביות עם הגישה של תבנית הנחיה +3. **אימות סוג**: אימות JSON מלא של ארגומנטים - מוחזר כשיפור עתידי כדי לשמור על היישום הראשוני פשוט + +## מקורות +- [מפרט פרוטוקול MCP](https://github.com/modelcontextprotocol/spec) +- [יישום כלי תבנית הנחיה](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +- [יישום כלי MCP נוכחי](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## נספחים +[כל מידע, דיאגרמות או דוגמאות נוספות] diff --git a/docs/tech-specs/mcp-tool-arguments.hi.md b/docs/tech-specs/mcp-tool-arguments.hi.md new file mode 100644 index 00000000..2552212a --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.hi.md @@ -0,0 +1,264 @@ +--- +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-08-21 +**स्थिति**: अंतिम रूप दिया गया + +### कार्यकारी सारांश + +रीएक्ट एजेंटों को उचित रूप से परिभाषित आर्गुमेंट्स के साथ एमसीपी (मॉडल कॉन्टेक्स्ट प्रोटोकॉल) टूल को उपयोग करने की अनुमति दें, +एमसीपी टूल कॉन्फ़िगरेशन में आर्गुमेंट स्पेसिफिकेशन सपोर्ट जोड़कर, उसी तरह जैसे कि प्रॉम्प्ट टेम्पलेट टूल +वर्तमान में काम करते हैं। + +### समस्या विवरण + + +वर्तमान में, रीएक्ट एजेंट फ्रेमवर्क में एमसीपी टूल अपने +अपेक्षित आर्गुमेंट्स को निर्दिष्ट नहीं कर सकते हैं। `McpToolImpl.get_arguments()` विधि +एक खाली सूची लौटाती है, जिससे एलएलएम को केवल टूल नामों और विवरणों के आधार पर सही पैरामीटर संरचना का अनुमान लगाना पड़ता है। +इससे निम्नलिखित समस्याएं होती हैं: +पैरामीटर अनुमान के कारण अविश्वसनीय टूल उपयोग +गलत आर्गुमेंट्स के कारण टूल विफल होने पर खराब उपयोगकर्ता अनुभव +निष्पादन से पहले टूल पैरामीटर का कोई सत्यापन नहीं +एजेंट प्रॉम्प्ट में गायब पैरामीटर दस्तावेज़ + +### लक्ष्य + +[ ] एमसीपी टूल कॉन्फ़िगरेशन को अपेक्षित आर्गुमेंट्स (नाम, प्रकार, विवरण) निर्दिष्ट करने की अनुमति दें। +[ ] एजेंट मैनेजर को एलएलएम को प्रॉम्प्ट के माध्यम से एमसीपी टूल आर्गुमेंट्स को उजागर करने के लिए अपडेट करें। +[ ] मौजूदा एमसीपी टूल कॉन्फ़िगरेशन के साथ पिछड़े अनुकूलता बनाए रखें। +[ ] प्रॉम्प्ट टेम्पलेट टूल के समान आर्गुमेंट सत्यापन का समर्थन करें। + +### गैर-लक्ष्य +एमसीपी सर्वर से गतिशील आर्गुमेंट खोज (भविष्य में सुधार) +बुनियादी संरचना से परे आर्गुमेंट प्रकार सत्यापन +जटिल आर्गुमेंट स्कीमा (नेस्टेड ऑब्जेक्ट, एरे) + +## पृष्ठभूमि और संदर्भ + +### वर्तमान स्थिति +एमसीपी टूल को रीएक्ट एजेंट सिस्टम में न्यूनतम मेटाडेटा के साथ कॉन्फ़िगर किया जाता है: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance" +} +``` + +`McpToolImpl.get_arguments()` विधि `[]` लौटाती है, इसलिए एलएलएम (LLM) अपने प्रॉम्प्ट में किसी भी तर्क मार्गदर्शन को प्राप्त नहीं करते हैं। + +### सीमाएँ + +1. **कोई तर्क विनिर्देश नहीं**: एमसीपी (MCP) उपकरण अपेक्षित मापदंडों को परिभाषित नहीं कर सकते। + पैरामीटर + +2. **एलएलएम पैरामीटर का अनुमान**: एजेंटों को टूल के नामों/वर्णनों से पैरामीटर का अनुमान लगाना होता है। + +3. **गायब प्रॉम्प्ट जानकारी**: एजेंट प्रॉम्प्ट में एमसीपी टूल के लिए किसी भी तर्क विवरण नहीं होते हैं। + + 4. **कोई सत्यापन नहीं**: अमान्य पैरामीटर केवल एमसीपी टूल के निष्पादन समय पर ही पकड़े जाते हैं। + +### संबंधित घटक + **trustgraph-flow/agent/react/service.py**: टूल कॉन्फ़िगरेशन लोडिंग और एजेंटमैनेजर (AgentManager) निर्माण। +**trustgraph-flow/agent/react/tools.py**: McpToolImpl कार्यान्वयन। +**trustgraph-flow/agent/react/agent_manager.py**: टूल तर्कों के साथ प्रॉम्प्ट पीढ़ी। +**trustgraph-cli**: एमसीपी टूल प्रबंधन के लिए सीएलआई (CLI) उपकरण। +**वर्कबेंच (Workbench)**: एजेंट टूल कॉन्फ़िगरेशन के लिए बाहरी यूआई (UI)। + +## आवश्यकताएँ + +### कार्यात्मक आवश्यकताएँ +## आवश्यकताएँ + +### कार्यात्मक आवश्यकताएँ + +1. **MCP टूल कॉन्फ़िगरेशन तर्क**: MCP टूल कॉन्फ़िगरेशन में एक वैकल्पिक `arguments` सरणी होनी चाहिए जिसमें नाम, प्रकार और विवरण फ़ील्ड हों। +2. **तर्क का प्रदर्शन**: `McpToolImpl.get_arguments()` को खाली सूची के बजाय कॉन्फ़िगर किए गए तर्कों को वापस करना चाहिए। +3. **प्रॉम्प्ट एकीकरण**: एजेंट प्रॉम्प्ट में MCP टूल तर्क विवरण शामिल होने चाहिए जब तर्क निर्दिष्ट किए जाते हैं। +4. **पिछला अनुकूलता**: बिना तर्कों वाले मौजूदा MCP टूल कॉन्फ़िगरेशन को भी काम करना जारी रखना चाहिए। +5. **CLI समर्थन**: मौजूदा `tg-invoke-mcp-tool` CLI तर्कों का समर्थन करता है (पहले से लागू)। + +### गैर-कार्यात्मक आवश्यकताएँ +1. **पिछला अनुकूलता**: मौजूदा MCP टूल कॉन्फ़िगरेशन के लिए कोई ब्रेकिंग परिवर्तन नहीं। +2. **प्रदर्शन**: एजेंट प्रॉम्प्ट पीढ़ी पर कोई महत्वपूर्ण प्रदर्शन प्रभाव नहीं। +3. **संगति**: तर्क हैंडलिंग को प्रॉम्प्ट टेम्पलेट टूल पैटर्न से मेल खाना चाहिए। + +### उपयोगकर्ता कहानियां + +1. एक **एजेंट डेवलपर** के रूप में, मैं LLMs को सही मापदंडों के साथ टूल को आमंत्रित करने के लिए MCP टूल तर्कों को कॉन्फ़िगरेशन में निर्दिष्ट करना चाहता हूं। +2. एक **वर्कबेंच उपयोगकर्ता** के रूप में, मैं एजेंटों को सही ढंग से टूल का उपयोग करने के लिए UI में MCP टूल तर्कों को कॉन्फ़िगर करना चाहता हूं। +3. एक **ReACT एजेंट में एक LLM** के रूप में, मैं सही मापदंडों प्रदान करने के लिए प्रॉम्प्ट में टूल तर्क विनिर्देशों को देखना चाहता हूं। + +## डिज़ाइन + +### उच्च-स्तरीय आर्किटेक्चर +MCP टूल कॉन्फ़िगरेशन को प्रॉम्प्ट टेम्पलेट पैटर्न से मिलाने के लिए: +1. MCP टूल कॉन्फ़िगरेशन में एक वैकल्पिक `arguments` सरणी जोड़ें। +2. `McpToolImpl` को कॉन्फ़िगर किए गए तर्कों को स्वीकार करने और वापस करने के लिए संशोधित करें। +3. MCP टूल तर्कों को संभालने के लिए टूल कॉन्फ़िगरेशन लोडिंग को अपडेट करें। +4. सुनिश्चित करें कि एजेंट प्रॉम्प्ट में MCP टूल तर्क जानकारी शामिल है। + +### कॉन्फ़िगरेशन स्कीमा +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Bank account identifier" + }, + { + "name": "date", + "type": "string", + "description": "Date for balance query (optional, format: YYYY-MM-DD)" + } + ] +} +``` + +### डेटा प्रवाह +1. **कॉन्फ़िगरेशन लोडिंग**: एमसीपी टूल कॉन्फ़िगरेशन और तर्क `on_tools_config()` द्वारा लोड किए जाते हैं। +2. **टूल निर्माण**: तर्कों को पार्स किया जाता है और `McpToolImpl` को कंस्ट्रक्टर के माध्यम से पास किया जाता है। +3. **प्रॉम्प्ट जनरेशन**: `agent_manager.py` एलएलएम प्रॉम्प्ट में शामिल करने के लिए `tool.arguments` को कॉल करता है। +4. **टूल इनवोकेशन**: एलएलएम पैरामीटर प्रदान करता है जिन्हें एमसीपी सेवा को बिना किसी बदलाव के पास किया जाता है। + +### एपीआई परिवर्तन +कोई बाहरी एपीआई परिवर्तन नहीं - यह पूरी तरह से आंतरिक कॉन्फ़िगरेशन और तर्क प्रबंधन है। + +### घटक विवरण + +#### घटक 1: service.py (टूल कॉन्फ़िगरेशन लोडिंग) +**उद्देश्य**: एमसीपी टूल कॉन्फ़िगरेशन को पार्स करें और टूल इंस्टेंस बनाएं। +**आवश्यक परिवर्तन**: एमसीपी टूल के लिए तर्क पार्सिंग जोड़ें (प्रॉम्प्ट टूल के समान)। +**नई कार्यक्षमता**: एमसीपी टूल कॉन्फ़िगरेशन से `arguments` सरणी निकालें और `Argument` ऑब्जेक्ट बनाएं। + +#### घटक 2: tools.py (McpToolImpl) +**उद्देश्य**: एमसीपी टूल कार्यान्वयन रैपर। +**आवश्यक परिवर्तन**: कंस्ट्रक्टर में तर्क स्वीकार करें और उन्हें `get_arguments()` से वापस करें। +**नई कार्यक्षमता**: कॉन्फ़िगर किए गए तर्कों को संग्रहीत करें और प्रदर्शित करें, खाली सूची वापस करने के बजाय। + +#### घटक 3: वर्कबेंच (बाहरी रिपॉजिटरी) +**उद्देश्य**: एजेंट टूल को कॉन्फ़िगर करने के लिए यूआई। +**आवश्यक परिवर्तन**: एमसीपी टूल के लिए तर्क विनिर्देश यूआई जोड़ें। +**नई कार्यक्षमता**: उपयोगकर्ताओं को एमसीपी टूल के लिए तर्क जोड़ने/संपादित करने/हटाने की अनुमति दें। + +#### घटक 4: सीएलआई टूल +**उद्देश्य**: कमांड-लाइन टूल प्रबंधन। +**आवश्यक परिवर्तन**: एमसीपी टूल निर्माण/अपडेट कमांड में तर्क विनिर्देश का समर्थन करें। +**नई कार्यक्षमता**: टूल कॉन्फ़िगरेशन कमांड में तर्क पैरामीटर स्वीकार करें। + +## कार्यान्वयन योजना + +### चरण 1: कोर एजेंट फ्रेमवर्क परिवर्तन +[ ] `McpToolImpl` कंस्ट्रक्टर को `arguments` पैरामीटर स्वीकार करने के लिए अपडेट करें। +[ ] `McpToolImpl.get_arguments()` को संग्रहीत तर्कों को वापस करने के लिए बदलें। +[ ] तर्कों को संभालने के लिए `service.py` एमसीपी टूल कॉन्फ़िगरेशन पार्सिंग को संशोधित करें। +[ ] एमसीपी टूल तर्क हैंडलिंग के लिए यूनिट टेस्ट जोड़ें। +[ ] सत्यापित करें कि एजेंट प्रॉम्प्ट में एमसीपी टूल तर्क शामिल हैं। + +### चरण 2: बाहरी टूल समर्थन +[ ] एमसीपी टूल तर्क विनिर्देश का समर्थन करने के लिए सीएलआई टूल को अपडेट करें। +[ ] उपयोगकर्ताओं के लिए तर्क कॉन्फ़िगरेशन प्रारूप का दस्तावेज़ बनाएं। +[ ] एमसीपी टूल तर्क कॉन्फ़िगरेशन का समर्थन करने के लिए वर्कबेंच यूआई को अपडेट करें। +[ ] उदाहरण और दस्तावेज़ जोड़ें। + +### कोड परिवर्तन सारांश +| फ़ाइल | परिवर्तन का प्रकार | विवरण | +|------|------------|-------------| +| `tools.py` | संशोधित | `tools.py` को तर्क स्वीकार करने और संग्रहीत करने के लिए अपडेट करें | +| `service.py` | संशोधित | एमसीपी टूल कॉन्फ़िगरेशन से तर्कों को पार्स करें (पंक्ति 108-113) | +| `test_react_processor.py` | संशोधित | एमसीपी टूल तर्कों के लिए परीक्षण जोड़ें | +| सीएलआई टूल | संशोधित | कमांड में तर्क विनिर्देश का समर्थन करें | +| वर्कबेंच | संशोधित | एमसीपी टूल तर्क कॉन्फ़िगरेशन के लिए यूआई जोड़ें | + +## परीक्षण रणनीति + +### यूनिट टेस्ट +**एमसीपी टूल तर्क पार्सिंग**: परीक्षण करें कि `service.py` एमसीपी टूल कॉन्फ़िगरेशन से तर्कों को सही ढंग से पार्स करता है। +**McpToolImpl तर्क**: परीक्षण करें कि `get_arguments()` कॉन्फ़िगर किए गए तर्कों को वापस करता है, खाली सूची के बजाय। +**पिछला अनुकूलता**: परीक्षण करें कि तर्कों के बिना एमसीपी टूल काम करना जारी रखते हैं (खाली सूची वापस करें)। +**एजेंट प्रॉम्प्ट जनरेशन**: परीक्षण करें कि एजेंट प्रॉम्प्ट में एमसीपी टूल तर्क विवरण शामिल हैं। + +### एकीकरण परीक्षण +**एंड-टू-एंड टूल इनवोकेशन**: एमसीपी टूल आर्गुमेंट्स के साथ टेस्ट एजेंट सफलतापूर्वक टूल को इनवोक कर सकता है। +**कॉन्फ़िगरेशन लोडिंग**: एमसीपी टूल आर्गुमेंट्स के साथ टेस्ट संपूर्ण कॉन्फ़िगरेशन लोडिंग साइकिल। +**क्रॉस-कंपोनेंट**: टेस्ट आर्गुमेंट्स का प्रवाह सही ढंग से कॉन्फ़िगरेशन → टूल क्रिएशन → प्रॉम्प्ट जेनरेशन से होता है। + +### मैनुअल टेस्टिंग +**एजेंट बिहेवियर**: मैन्युअल रूप से सत्यापित करें कि एलएलएम रीएक्ट साइकिल में आर्गुमेंट जानकारी प्राप्त करता है और उसका उपयोग करता है। +**सीएलआई इंटीग्रेशन**: टेस्ट `tg-invoke-mcp-tool` नए आर्गुमेंट-कॉन्फ़िगर किए गए एमसीपी टूल के साथ काम करता है। +**वर्कबेंच इंटीग्रेशन**: टेस्ट यूआई एमसीपी टूल आर्गुमेंट कॉन्फ़िगरेशन का समर्थन करता है। + +## माइग्रेशन और रोलआउट + +### माइग्रेशन रणनीति +माइग्रेशन की आवश्यकता नहीं है - यह पूरी तरह से अतिरिक्त कार्यक्षमता है: +मौजूदा एमसीपी टूल कॉन्फ़िगरेशन जिसमें `arguments` नहीं है, वह बिना किसी बदलाव के काम करना जारी रखता है। +`McpToolImpl.get_arguments()` लेगेसी टूल के लिए खाली सूची लौटाता है। +नए कॉन्फ़िगरेशन वैकल्पिक रूप से `arguments` सरणी शामिल कर सकते हैं। + +### रोलआउट योजना +1. **फेज 1**: डेवलपमेंट/स्टेजिंग में कोर एजेंट फ्रेमवर्क परिवर्तनों को तैनात करें। +2. **फेज 2**: सीएलआई टूल अपडेट और दस्तावेज़ तैनात करें। +3. **फेज 3**: आर्गुमेंट कॉन्फ़िगरेशन के लिए वर्कबेंच यूआई अपडेट तैनात करें। +4. **फेज 4**: मॉनिटरिंग के साथ प्रोडक्शन रोलआउट। + +### रोलबैक योजना +कोर परिवर्तन पिछड़े संगत हैं - कार्यक्षमता के लिए रोलबैक की आवश्यकता नहीं है। +यदि कोई समस्या उत्पन्न होती है, तो एमसीपी टूल कॉन्फ़िगरेशन लोडिंग लॉजिक को वापस करके आर्गुमेंट पार्सिंग को अक्षम करें। +वर्कबेंच और सीएलआई परिवर्तन स्वतंत्र हैं और उन्हें अलग से वापस किया जा सकता है। + +## सुरक्षा संबंधी विचार +**कोई नया अटैक सरफेस नहीं**: आर्गुमेंट्स मौजूदा कॉन्फ़िगरेशन स्रोतों से पार्स किए जाते हैं, जिसमें कोई नया इनपुट नहीं है। +**पैरामीटर सत्यापन**: आर्गुमेंट्स को एमसीपी टूल स्तर पर अपरिवर्तित एमसीपी टूल में पास किया जाता है - सत्यापन एमसीपी टूल स्तर पर रहता है। +**कॉन्फ़िगरेशन अखंडता**: आर्गुमेंट विनिर्देश टूल कॉन्फ़िगरेशन का हिस्सा हैं - समान सुरक्षा मॉडल लागू होता है। + +## प्रदर्शन प्रभाव +**न्यूनतम ओवरहेड**: आर्गुमेंट पार्सिंग केवल कॉन्फ़िगरेशन लोडिंग के दौरान होती है, प्रति-अनुरोध नहीं। +**प्रॉम्प्ट आकार में वृद्धि**: एजेंट प्रॉम्प्ट में एमसीपी टूल आर्गुमेंट विवरण शामिल होंगे, जिससे टोकन उपयोग थोड़ा बढ़ जाएगा। +**मेमोरी उपयोग**: टूल ऑब्जेक्ट में आर्गुमेंट विनिर्देशों को संग्रहीत करने के लिए मामूली वृद्धि। + +## दस्तावेज़ + +### उपयोगकर्ता दस्तावेज़ +[ ] आर्गुमेंट उदाहरणों के साथ एमसीपी टूल कॉन्फ़िगरेशन गाइड को अपडेट करें। +[ ] सीएलआई टूल हेल्प टेक्स्ट में आर्गुमेंट विनिर्देश जोड़ें। +[ ] सामान्य एमसीपी टूल आर्गुमेंट पैटर्न के उदाहरण बनाएं। + +### डेवलपर दस्तावेज़ +[ ] `McpToolImpl` क्लास दस्तावेज़ को अपडेट करें। +[ ] आर्गुमेंट पार्सिंग लॉजिक के लिए इनलाइन टिप्पणियाँ जोड़ें। +[ ] सिस्टम आर्किटेक्चर में आर्गुमेंट प्रवाह का दस्तावेज़ बनाएं। + +## खुले प्रश्न +1. **आर्गुमेंट सत्यापन**: क्या हमें बुनियादी संरचना जांच से परे आर्गुमेंट प्रकार/प्रारूपों को मान्य करना चाहिए? +2. **डायनामिक डिस्कवरी**: एमसीपी सर्वर से टूल स्कीमा को स्वचालित रूप से क्वेरी करने के लिए भविष्य में संवर्द्धन? + +## विचारे गए विकल्प +1. **डायनामिक एमसीपी स्कीमा डिस्कवरी**: रनटाइम पर टूल आर्गुमेंट स्कीमा के लिए एमसीपी सर्वर को क्वेरी करें - जटिलता और विश्वसनीयता संबंधी चिंताओं के कारण अस्वीकृत। +2. **अलग आर्गुमेंट रजिस्ट्री**: एमसीपी टूल आर्गुमेंट को अलग कॉन्फ़िगरेशन अनुभाग में संग्रहीत करें - प्रॉम्प्ट टेम्पलेट दृष्टिकोण के साथ स्थिरता के कारण अस्वीकृत। +3. **टाइप सत्यापन**: आर्गुमेंट के लिए पूर्ण JSON स्कीमा सत्यापन - प्रारंभिक कार्यान्वयन को सरल रखने के लिए भविष्य के संवर्द्धन के रूप में स्थगित। + +## संदर्भ +[एमसीपी प्रोटोकॉल विनिर्देश](https://github.com/modelcontextprotocol/spec) +[प्रॉम्प्ट टेम्पलेट टूल कार्यान्वयन](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +[वर्तमान एमसीपी टूल कार्यान्वयन](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## परिशिष्ट +[कोई भी अतिरिक्त जानकारी, आरेख या उदाहरण] diff --git a/docs/tech-specs/mcp-tool-arguments.md b/docs/tech-specs/mcp-tool-arguments.md index 9b0c8560..bbe8765e 100644 --- a/docs/tech-specs/mcp-tool-arguments.md +++ b/docs/tech-specs/mcp-tool-arguments.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "MCP Tool Arguments Specification" +parent: "Tech Specs" +--- + # MCP Tool Arguments Specification ## Overview diff --git a/docs/tech-specs/mcp-tool-arguments.pt.md b/docs/tech-specs/mcp-tool-arguments.pt.md new file mode 100644 index 00000000..555fb90d --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.pt.md @@ -0,0 +1,264 @@ +--- +layout: default +title: "Especificação de Argumentos da Ferramenta MCP" +parent: "Portuguese (Beta)" +--- + +# Especificação de Argumentos da Ferramenta MCP + +> **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 +**Nome da Funcionalidade**: Suporte a Argumentos da Ferramenta MCP +**Autor**: Claude Code Assistant +**Data**: 2025-08-21 +**Status**: Finalizado + +### Resumo Executivo + +Permitir que agentes ReACT invoquem ferramentas MCP (Protocolo de Contexto do Modelo) com +argumentos definidos de forma adequada, adicionando suporte à especificação de argumentos às +configurações das ferramentas MCP, de forma semelhante a como as ferramentas de modelo de prompt +funcionam atualmente. + +### Declaração do Problema + +Atualmente, as ferramentas MCP no framework do agente ReACT não podem especificar seus +argumentos esperados. O método `McpToolImpl.get_arguments()` retorna +uma lista vazia, forçando os LLMs a adivinhar a estrutura correta de parâmetros +com base apenas nos nomes e descrições das ferramentas. Isso leva a: +Invocação de ferramentas não confiável devido à suposição de parâmetros +Má experiência do usuário quando as ferramentas falham devido a argumentos incorretos +Ausência de validação dos parâmetros da ferramenta antes da execução +Documentação de parâmetros ausente nos prompts do agente + +### Objetivos + +[ ] Permitir que as configurações da ferramenta MCP especifiquem os argumentos esperados (nome, tipo, descrição) +[ ] Atualizar o gerenciador de agentes para expor os argumentos da ferramenta MCP aos LLMs por meio de prompts +[ ] Manter a compatibilidade com versões anteriores com as configurações existentes da ferramenta MCP +[ ] Suportar a validação de argumentos semelhante às ferramentas de modelo de prompt + +### Não Objetivos +Descoberta dinâmica de argumentos a partir de servidores MCP (melhoria futura) +Validação de tipo de argumento além da estrutura básica +Esquemas de argumentos complexos (objetos aninhados, arrays) + +## Contexto e Informações de Base + +### Estado Atual +As ferramentas MCP são configuradas no sistema de agente ReACT com metadados mínimos: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance" +} +``` + +O método `McpToolImpl.get_arguments()` retorna `[]`, portanto, os LLMs não recebem orientação de argumentos em seus prompts. + +### Limitações + +1. **Sem especificação de argumentos**: As ferramentas MCP não podem definir parâmetros esperados. + parâmetros. + +2. **Adivinhação de parâmetros do LLM**: Os agentes devem inferir parâmetros a partir dos nomes/descrições das ferramentas. + +3. **Informações do prompt ausentes**: Os prompts dos agentes não mostram detalhes dos argumentos para as ferramentas MCP. + + 4. **Sem validação**: Parâmetros inválidos são detectados apenas no momento da execução da ferramenta MCP. + +### Componentes Relacionados + **trustgraph-flow/agent/react/service.py**: Carregamento de configuração de ferramentas e criação do AgentManager. +**trustgraph-flow/agent/react/tools.py**: Implementação do McpToolImpl. +**trustgraph-flow/agent/react/agent_manager.py**: Geração de prompts com argumentos de ferramentas. +**trustgraph-cli**: Ferramentas de linha de comando para gerenciamento de ferramentas MCP. +**Workbench**: Interface de usuário externa para configuração de ferramentas de agente. + +## Requisitos + +### Requisitos Funcionais +## Requisitos + +### Requisitos Funcionais + +1. **Argumentos de Configuração da Ferramenta MCP**: As configurações da ferramenta MCP DEVEM suportar um array opcional `arguments` com campos de nome, tipo e descrição. +2. **Exposição de Argumentos**: `McpToolImpl.get_arguments()` DEVE retornar os argumentos configurados em vez de uma lista vazia. +3. **Integração com Prompts**: Os prompts do agente DEVEM incluir detalhes dos argumentos da ferramenta MCP quando os argumentos forem especificados. +4. **Compatibilidade com Versões Anteriores**: As configurações existentes da ferramenta MCP sem argumentos DEVEM continuar a funcionar. +5. **Suporte para CLI**: A CLI existente `tg-invoke-mcp-tool` suporta argumentos (já implementado). + +### Requisitos Não Funcionais +1. **Compatibilidade com Versões Anteriores**: Nenhuma alteração disruptiva para as configurações existentes da ferramenta MCP. +2. **Desempenho**: Nenhum impacto significativo no desempenho da geração de prompts do agente. +3. **Consistência**: O tratamento de argumentos DEVE corresponder aos padrões de ferramentas de modelos de prompt. + +### Histórias de Usuário + +1. Como um **desenvolvedor de agente**, quero especificar argumentos da ferramenta MCP na configuração para que os LLMs possam invocar ferramentas com parâmetros corretos. +2. Como um **usuário da workbench**, quero configurar argumentos da ferramenta MCP na interface do usuário para que os agentes usem as ferramentas corretamente. +3. Como um **LLM em um agente ReACT**, quero ver as especificações dos argumentos da ferramenta nos prompts para que eu possa fornecer parâmetros corretos. + +## Design + +### Arquitetura de Alto Nível +Estenda a configuração da ferramenta MCP para corresponder ao padrão do modelo de prompt, adicionando: +1. Um array opcional `arguments` às configurações da ferramenta MCP. +2. Modificações em `McpToolImpl` para aceitar e retornar argumentos configurados. +3. Atualizações no carregamento da configuração para lidar com os argumentos da ferramenta MCP. +4. Garantir que os prompts do agente incluam informações sobre os argumentos da ferramenta MCP. + +### Esquema de Configuração +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Bank account identifier" + }, + { + "name": "date", + "type": "string", + "description": "Date for balance query (optional, format: YYYY-MM-DD)" + } + ] +} +``` + +### Fluxo de Dados +1. **Carregamento de Configuração**: A configuração da ferramenta MCP, juntamente com seus argumentos, é carregada por `on_tools_config()` +2. **Criação da Ferramenta**: Os argumentos são analisados e passados para `McpToolImpl` através do construtor +3. **Geração de Prompt**: `agent_manager.py` chama `tool.arguments` para incluir nos prompts do LLM +4. **Invocar a Ferramenta**: O LLM fornece parâmetros que são passados para o serviço MCP sem modificação + +### Alterações na API +Não há alterações na API externa - isso é puramente configuração interna e tratamento de argumentos. + +### Detalhes do Componente + +#### Componente 1: service.py (Carregamento de Configuração da Ferramenta) +**Propósito**: Analisar as configurações da ferramenta MCP e criar instâncias da ferramenta +**Alterações Necessárias**: Adicionar análise de argumentos para ferramentas MCP (semelhante às ferramentas de prompt) +**Nova Funcionalidade**: Extrair o array `arguments` da configuração da ferramenta MCP e criar objetos `Argument` + +#### Componente 2: tools.py (McpToolImpl) +**Propósito**: Wrapper de implementação da ferramenta MCP +**Alterações Necessárias**: Aceitar argumentos no construtor e retorná-los de `get_arguments()` +**Nova Funcionalidade**: Armazenar e expor os argumentos configurados em vez de retornar uma lista vazia + +#### Componente 3: Workbench (Repositório Externo) +**Propósito**: Interface do usuário para configurar ferramentas de agente +**Alterações Necessárias**: Adicionar interface do usuário para especificar argumentos para ferramentas MCP +**Nova Funcionalidade**: Permitir que os usuários adicionem/editem/removam argumentos para ferramentas MCP + +#### Componente 4: Ferramentas de Linha de Comando +**Propósito**: Gerenciamento de ferramentas de linha de comando +**Alterações Necessárias**: Suportar a especificação de argumentos nos comandos de criação/atualização da ferramenta MCP +**Nova Funcionalidade**: Aceitar o parâmetro de argumentos nos comandos de configuração da ferramenta + +## Plano de Implementação + +### Fase 1: Alterações no Framework Central do Agente +[ ] Atualizar o construtor de `McpToolImpl` para aceitar o parâmetro `arguments` +[ ] Alterar `McpToolImpl.get_arguments()` para retornar os argumentos armazenados +[ ] Modificar a análise de configuração da ferramenta MCP em `service.py` para lidar com argumentos +[ ] Adicionar testes unitários para o tratamento de argumentos da ferramenta MCP +[ ] Verificar se os prompts do agente incluem os argumentos da ferramenta MCP + +### Fase 2: Suporte para Ferramentas Externas +[ ] Atualizar as ferramentas de linha de comando para suportar a especificação de argumentos da ferramenta MCP +[ ] Documentar o formato de configuração de argumentos para os usuários +[ ] Atualizar a interface do usuário do Workbench para suportar a configuração de argumentos da ferramenta MCP +[ ] Adicionar exemplos e documentação + +### Resumo das Alterações no Código +| Arquivo | Tipo de Alteração | Descrição | +|------|------------|-------------| +| `tools.py` | Modificado | Atualizar McpToolImpl para aceitar e armazenar argumentos | +| `service.py` | Modificado | Analisar argumentos da configuração da ferramenta MCP (linhas 108-113) | +| `test_react_processor.py` | Modificado | Adicionar testes para argumentos da ferramenta MCP | +| Ferramentas de linha de comando | Modificado | Suportar a especificação de argumentos nos comandos | +| Workbench | Modificado | Adicionar interface do usuário para a configuração de argumentos da ferramenta MCP | + +## Estratégia de Teste + +### Testes Unitários +**Análise de Argumentos da Ferramenta MCP**: Testar se `service.py` analisa corretamente os argumentos das configurações da ferramenta MCP +**Argumentos do McpToolImpl**: Testar se `get_arguments()` retorna os argumentos configurados em vez de uma lista vazia +**Compatibilidade com Versões Anteriores**: Testar se as ferramentas MCP sem argumentos continuam a funcionar (retornam uma lista vazia) +**Geração de Prompt do Agente**: Testar se os prompts do agente incluem os detalhes dos argumentos da ferramenta MCP + +### Testes de Integração +**Invocar Ferramenta de Extremo a Extremo**: O agente de teste com argumentos da ferramenta MCP pode invocar ferramentas com sucesso. +**Carregamento de Configuração**: Testar o ciclo completo de carregamento de configuração com argumentos da ferramenta MCP. +**Componentes Cruzados**: Testar se os argumentos fluem corretamente de config → criação de ferramenta → geração de prompt. + +### Testes Manuais +**Comportamento do Agente**: Verificar manualmente se o LLM recebe e usa as informações dos argumentos nos ciclos ReACT. +**Integração com a Linha de Comando**: Testar se tg-invoke-mcp-tool funciona com ferramentas MCP configuradas com novos argumentos. +**Integração com o Workbench**: Testar se a interface do usuário suporta a configuração de argumentos para ferramentas MCP. + +## Migração e Implantação + +### Estratégia de Migração +Não é necessária migração - esta é uma funcionalidade puramente adicional: +As configurações existentes da ferramenta MCP sem `arguments` continuam a funcionar inalteradas. +`McpToolImpl.get_arguments()` retorna uma lista vazia para ferramentas legadas. +Novas configurações podem incluir opcionalmente o array `arguments`. + +### Plano de Implantação +1. **Fase 1**: Implantar as alterações principais do framework do agente para desenvolvimento/staging. +2. **Fase 2**: Implantar as atualizações da ferramenta de linha de comando e a documentação. +3. **Fase 3**: Implantar as atualizações da interface do usuário do Workbench para a configuração de argumentos. +4. **Fase 4**: Implantação em produção com monitoramento. + +### Plano de Reversão +As alterações principais são compatíveis com versões anteriores - nenhuma reversão é necessária para a funcionalidade. +Se surgirem problemas, desative a análise de argumentos revertendo a lógica de carregamento da configuração da ferramenta MCP. +As alterações do Workbench e da linha de comando são independentes e podem ser revertidas separadamente. + +## Considerações de Segurança +**Nenhuma nova superfície de ataque**: Os argumentos são analisados a partir de fontes de configuração existentes, sem novas entradas. +**Validação de parâmetros**: Os argumentos são passados para as ferramentas MCP sem alterações - a validação permanece no nível da ferramenta MCP. +**Integridade da configuração**: As especificações de argumentos fazem parte da configuração da ferramenta - o mesmo modelo de segurança se aplica. + +## Impacto no Desempenho +**Sobrecarga mínima**: A análise de argumentos ocorre apenas durante o carregamento da configuração, não por solicitação. +**Aumento do tamanho do prompt**: Os prompts do agente incluirão detalhes dos argumentos da ferramenta MCP, aumentando ligeiramente o uso de tokens. +**Uso de memória**: Aumento insignificante para armazenar as especificações de argumentos em objetos de ferramenta. + +## Documentação + +### Documentação do Usuário +[ ] Atualizar o guia de configuração da ferramenta MCP com exemplos de argumentos. +[ ] Adicionar a especificação de argumentos ao texto de ajuda da ferramenta de linha de comando. +[ ] Criar exemplos de padrões comuns de argumentos da ferramenta MCP. + +### Documentação para Desenvolvedores +[ ] Atualizar a documentação da classe McpToolImpl. +[ ] Adicionar comentários inline para a lógica de análise de argumentos. +[ ] Documentar o fluxo de argumentos na arquitetura do sistema. + +## Perguntas Abertas +1. **Validação de argumentos**: Devemos validar os tipos/formatos de argumentos além da verificação básica da estrutura? +2. **Descoberta dinâmica**: Uma melhoria futura para consultar os servidores MCP para esquemas de ferramentas automaticamente? + +## Alternativas Consideradas +1. **Descoberta dinâmica do esquema MCP**: Consultar os servidores MCP para esquemas de argumentos em tempo de execução - rejeitado devido à complexidade e preocupações com a confiabilidade. +2. **Registro de argumentos separado**: Armazenar os argumentos da ferramenta MCP em uma seção de configuração separada - rejeitado devido à inconsistência com a abordagem do modelo de prompt. +3. **Validação de tipo**: Validação completa do esquema JSON para argumentos - adiada como uma melhoria futura para manter a implementação inicial simples. + +## Referências +[Especificação do Protocolo MCP](https://github.com/modelcontextprotocol/spec) +[Implementação da Ferramenta do Modelo de Prompt](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +[Implementação Atual da Ferramenta MCP](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## Apêndice +[Quaisquer informações adicionais, diagramas ou exemplos] diff --git a/docs/tech-specs/mcp-tool-arguments.ru.md b/docs/tech-specs/mcp-tool-arguments.ru.md new file mode 100644 index 00000000..63b5d705 --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.ru.md @@ -0,0 +1,128 @@ +--- +layout: default +title: "Спецификация аргументов для инструмента MCP" +parent: "Russian (Beta)" +--- + +# Спецификация аргументов для инструмента MCP + +> **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. + +## Обзор +**Имя функции**: Поддержка аргументов для инструмента MCP +**Автор**: Claude Code Assistant +**Дата**: 21.08.2025 +**Статус**: Завершено + +### Краткое описание + +Позволить агентам ReACT использовать инструменты MCP (Протокол контекста модели) с правильно определенными аргументами, добавив поддержку спецификации аргументов в конфигурацию инструмента MCP, аналогично тому, как работают инструменты с шаблонами запросов. + +### Проблема + +В настоящее время инструменты MCP в фреймворке агента ReACT не могут указывать ожидаемые аргументы. Метод `McpToolImpl.get_arguments()` возвращает пустой список, заставляя LLM угадывать правильную структуру параметров, основываясь только на именах и описаниях инструментов. Это приводит к: +- Ненадежным вызовам инструментов из-за угадывания параметров +- Плохой пользовательской опыту, когда инструменты не работают из-за неправильных аргументов +- Отсутствию проверки параметров инструментов перед выполнением +- Отсутствия документации параметров в запросах агента + +### Цели + +- [ ] Разрешить конфигурации инструментов MCP указывать ожидаемые аргументы (имя, тип, описание) +- [ ] Обновить менеджер агентов, чтобы он предоставлял аргументы инструментов MCP LLM через запросы +- [ ] Сохранить обратную совместимость с существующими конфигурациями инструментов MCP +- [ ] Поддерживать проверку аргументов, аналогичную инструментам с шаблонами запросов + +### Нецелевые области +- Динамическое обнаружение аргументов от серверов MCP (будущее улучшение) +- Проверка типов аргументов за пределами базовой структуры +- Сложные схемы аргументов (вложенные объекты, массивы) + +## Предыстория и контекст + +### Текущее состояние +Инструменты MCP настраиваются в системе агента ReACT с минимальными метаданными: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Получить баланс банковского счета", + "mcp-tool": "get_bank_balance" +} +``` +Метод `McpToolImpl.get_arguments()` возвращает `[]`, поэтому LLM не получают никаких указаний по аргументам в своих запросах. + +### Ограничения + +1. **Отсутствие спецификации аргументов**: Инструменты MCP не могут определять ожидаемые параметры +2. **Угадывание параметров LLM**: Агенты должны выводить параметры из имен/описаний инструментов +3. **Отсутствие информации в запросах**: Запросы агента не содержат деталей аргументов для инструментов MCP +4. **Отсутствие проверки**: Неправильные параметры обнаруживаются только во время выполнения инструмента MCP + +### Связанные компоненты +- **trustgraph-flow/agent/react/service.py**: Загрузка конфигурации инструментов и создание AgentManager +- **trustgraph-flow/agent/react/tools.py**: Реализация McpToolImpl +- **trustgraph-flow/agent/react/agent_manager.py**: Генерация запросов с аргументами инструментов +- **tg-invoke-mcp-tool**: Клиентские инструменты для управления инструментами MCP +- **Workbench**: Внешний UI для конфигурации инструментов агента + +## Требования + +### Функциональные требования + +1. **Конфигурация аргументов для инструмента MCP**: Конфигурации инструментов MCP ДОЛЖНЫ поддерживать необязательный массив `arguments` с полями `name`, `type` и `description` +2. **Предоставление аргументов**: `McpToolImpl.get_arguments()` ДОЛЖЕН возвращать сконфигурированные аргументы, а не пустой список +3. **Интеграция с запросами**: Запросы агента ДОЛЖНЫ содержать детали аргументов инструментов MCP, когда аргументы указаны +4. **Обратная совместимость**: Существующие конфигурации инструментов MCP без аргументов ДОЛЖНЫ продолжать работать +5. **Поддержка CLI**: Существующие CLI инструменты tg-invoke-mcp-tool поддерживают аргументы (уже реализовано) + +### Нефункциональные требования +1. **Обратная совместимость**: Без каких-либо изменений для существующих конфигураций инструментов MCP +2. **Производительность**: Отсутствие существенного влияния на генерацию запросов агента +3. **Согласованность**: Обработка аргументов ДОЛЖНА соответствовать шаблонам инструментов с шаблонами запросов + +### Истории пользователей + +1. Как **разработчик агента**, я хочу указывать аргументы инструментов MCP в конфигурации, чтобы LLM могли вызывать инструменты с правильными параметрами +2. Как **пользователь Workbench**, я хочу настраивать аргументы инструментов MCP в UI, чтобы агенты использовали инструменты правильно +3. Как **LLM в ReACT агенте**, я хочу видеть спецификации аргументов инструментов в запросах, чтобы я мог предоставлять правильные параметры + +## Проектирование + +### Высокоуровневая архитектура +Расширить конфигурацию инструмента MCP, чтобы соответствовать шаблону инструмента с шаблоном запросов, путем: +1. Добавления необязательного массива `arguments` в конфигурацию инструментов MCP +2. Модификации `McpToolImpl` для приема и возврата сконфигурированных аргументов +3. Обновления загрузки конфигурации инструментов для обработки аргументов инструментов MCP +4. Обеспечения включения информации об аргументах инструментов MCP в запросы агента + +### Схема конфигурации +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Bank account identifier" + }, + { + "name": "date", + "type": "string", + "description": "Date for balance query (optional, format: YYYY-MM-DD)" + } + ] +} +``` + +### Поток данных +1. **Загрузка конфигурации**: Конфигурация инструмента MCP с аргументами загружается с помощью `on_tools_config()` +2. **Создание инструмента**: Аргументы парсятся и передаются в `McpToolImpl` через конструктор +3. **Генерация запросов**: `agent_manager.py` вызывает `tool.arguments` для включения в LLM запросы +4. **Вызов инструмента**: LLM предоставляет параметры, которые передаются инструменту MCP без изменений + +### Изменения API +Нет изменений API - это чисто внутренняя конфигурация и обработка аргументов diff --git a/docs/tech-specs/mcp-tool-arguments.sw.md b/docs/tech-specs/mcp-tool-arguments.sw.md new file mode 100644 index 00000000..c69abd0e --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.sw.md @@ -0,0 +1,264 @@ +--- +layout: default +title: "Vipimo vya Majadiliano ya Zana ya MCP" +parent: "Swahili (Beta)" +--- + +# Vipimo vya Majadiliano ya Zana ya MCP + +> **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 +**Jina la Kipengele:** Usaidizi wa Majadiliano ya Zana ya MCP +**Mwandishi:** Claude Code Assistant +**Tarehe:** 2025-08-21 +**Hali:** Imekamilika + +### Muhtasari + +Kuruhusu wakala wa ReACT kuita zana za MCP (Model Context Protocol) kwa +majadiliano yaliyobainishwa vizuri kwa kuongeza usaidizi wa majadiliano katika +usanidi wa zana za MCP, kama vile zana za kiolezo za matangazo +zinavyofanya sasa. + +### Tatizo + +Kwa sasa, zana za MCP katika mfumo wa wakala wa ReACT haziwezi kuainisha +majadiliano yake yanayotarajiwa. Njia ya `McpToolImpl.get_arguments()` hurudisha +orodha tupu, na kuwafanya LLMs (Large Language Models) nadhani muundo sahihi +wa vigezo kulingana na majina na maelezo ya zana pekee. Hii husababisha: +Utendaji usio wa kuaminika wa zana kutokana na nadharia ya vigezo +Uzoefu mbaya wa mtumiaji wakati zana zinashindwa kutokana na majadiliano yasiyo sahihi +Hakuna uthibitishaji wa vigezo vya zana kabla ya utekelezaji +Ukosefu wa maandishi ya vigezo katika matangazo ya wakala + +### Lengo + +[ ] Kuruhusu usanidi wa zana za MCP kuainisha majadiliano yanayotarajiwa (jina, aina, maelezo) +[ ] Kusasisha meneja wa wakala ili kuonyesha majadiliano ya zana za MCP kwa LLMs kupitia matangazo +[ ] Kuhifadhi utangamano na usanidi wa zana za MCP zilizopo +[ ] Kusaidia uthibitishaji wa majadiliano kama vile zana za kiolezo za matangazo + +### Mambo ambayo Hayatarajiwi +Kugundua majadiliano kwa njia ya moja kwa moja kutoka kwa seva za MCP (ongezeko la baadaye) +Uthibitishaji wa aina ya majadiliano zaidi ya muundo wa msingi +Mifumo ngumu ya majadiliano (vitu vilivyojumuishwa, safu) + +## Asili na Mfumo + +### Hali ya Sasa +Zana za MCP zimepangwa katika mfumo wa wakala wa ReACT na metadata ndogo: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance" +} +``` + +Njia `McpToolImpl.get_arguments()` hurudia `[]`, kwa hivyo, mifumo ya lugha kubwa (LLMs) hayapokei mwongozo wowote kuhusu hoja katika maagizo yao. + +### Mapungufu + +1. **Hakuna uainishaji wa hoja**: Vifaa vya MCP haviwezi kufafanua + vigezo. + +2. **Utabiri wa vigezo vya LLM**: Wawakilishi lazima watabiri vigezo kutoka kwa majina/maelezo ya zana. + +3. **Habari ya maagizo inayokosekana**: Maagizo ya wakala yanaonyesha maelezo yoyote kuhusu hoja kwa vifaa vya MCP. + + 4. **Hakuna uthibitisho**: Vigezo visivyofaa hugunduliwa wakati wa utekelezaji wa zana ya MCP. + +### Vipengele Vinavyohusiana + **trustgraph-flow/agent/react/service.py**: Kupakia usanidi wa zana na uundaji wa AgentManager. +**trustgraph-flow/agent/react/tools.py**: Utendaji wa McpToolImpl. +**trustgraph-flow/agent/react/agent_manager.py**: Uundaji wa maagizo pamoja na hoja za zana. +**trustgraph-cli**: Vifaa vya CLI kwa usimamizi wa zana za MCP. +**Workbench**: Kiolesura cha nje cha usanidi wa zana za wakala. + +## Mahitaji + +### Mahitaji ya Kifamilia +## Mahitaji + +### Mahitaji ya Kazi + +1. **Vigezo vya Usanidi wa Zana ya MCP**: Usanidi wa zana za MCP LAZIMA uunga mkono safu ya hiari ya `arguments` yenye nyanja za jina, aina, na maelezo. +2. **Uonyeshaji wa Vigezo**: `McpToolImpl.get_arguments()` INAHITAJIKA kurudisha vigezo vilivyosanidiwa badala ya orodha tupu. +3. **Uunganisho wa Maagizo**: Maagizo ya wakala LAZIMA yajumuise maelezo ya vigezo vya zana ya MCP wakati vigezo vinapotajwa. +4. **Ulinganifu na Mifumo ya Zamani**: Usanidi wa zana za MCP uliopo bila vigezo LAZIMA uendelee kufanya kazi. +5. **Usaidizi wa CLI**: CLI ya `tg-invoke-mcp-tool` iliyopo inasaidia vigezo (tayari imetekelezwa). + +### Mahitaji Yasiyo ya Kazi +1. **Ulinganifu na Mifumo ya Zamani**: Hakuna mabadiliko yoyote yanayoweza kusababisha migogoro kwa usanidi wa zana za MCP uliopo. +2. **Utendaji**: Hakuna athari kubwa ya utendaji kwenye uzalishaji wa maagizo ya wakala. +3. **Ulinganifu**: Usimamizi wa vigezo LAZIMA uangane na mifumo ya zana za kiolezo katika kiolezo cha maagizo. + +### Hadithi za Mtumiaji + +1. Kama **msanidi programu wa wakala**, ninataka kuainisha vigezo vya zana ya MCP katika usanidi ili kwamba mifumo ya LLM iweze kutumia zana na vigezo sahihi. +2. Kama **mtumiaji wa benchi ya kazi**, ninataka kusanidi vigezo vya zana ya MCP katika UI ili kwamba wakala watumie zana vizuri. +3. Kama **mfumo wa LLM katika wakala wa ReACT**, ninataka kuona maelezo ya vigezo vya zana katika maagizo ili kwamba niweze kutoa vigezo sahihi. + +## Muundo + +### Muundo wa Juu +Panua usanidi wa zana ya MCP ili uangane na muundo wa kiolezo cha maagizo kwa: +1. Kuongeza safu ya hiari ya `arguments` kwa usanidi wa zana za MCP. +2. Kubadilisha `McpToolImpl` ili kukubali na kurudisha vigezo vilivyosanidiwa. +3. Kusasisha upakaji wa usanidi ili kushughulikia vigezo vya zana ya MCP. +4. Kuhakikisha kwamba maagizo ya wakala yajumuise taarifa ya vigezo vya zana ya MCP. + +### Mfumo wa Usanidi +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Bank account identifier" + }, + { + "name": "date", + "type": "string", + "description": "Date for balance query (optional, format: YYYY-MM-DD)" + } + ] +} +``` + +### Mtiririko wa Data +1. **Uipakaji wa Usanidi**: Usanidi wa zana ya MCP pamoja na hoja huipakwa na `on_tools_config()` +2. **Uundaji wa Zana**: Hoja huzingatiwa na kupitishwa kwa `McpToolImpl` kupitia kwa konstrukta +3. **Uundaji wa Maagizo**: `agent_manager.py` huita `tool.arguments` ili kujumuishwa katika maagizo ya LLM +4. **Utendaji wa Zana**: LLM hutoa vigezo ambavyo hupitishwa kwa huduma ya MCP bila kubadilishwa + +### Mabadiliko ya API +Hakuna mabadiliko ya API ya nje - hii ni usanidi na usimamizi wa hoja wa ndani tu. + +### Maelezo ya Vipengele + +#### Kipengele 1: service.py (Uipakaji wa Usanidi wa Zana) +**Madhumuni**: Kuchanganua usanidi wa zana za MCP na kuunda mifano ya zana +**Mabadiliko Yanayohitajika**: Ongeza uchanganuzi wa hoja kwa zana za MCP (kama vile zana za maagizo) +**Utendaji Mpya**: Toa safu ya `arguments` kutoka usanidi wa zana ya MCP na uunde vitu vya `Argument` + +#### Kipengele 2: tools.py (McpToolImpl) +**Madhumuni**: Kifungashio cha utekelezaji wa zana ya MCP +**Mabadiliko Yanayohitajika**: Kukubali hoja katika konstrukta na kurejesha hoja hizo kutoka `get_arguments()` +**Utendaji Mpya**: Kuhifadhi na kuonyesha hoja zilizosanidiwa badala ya kurejesha orodha tupu + +#### Kipengele 3: Workbench (Hifadhi Nje) +**Madhumuni**: Kiolesura cha usanidi wa zana za wakala +**Mabadiliko Yanayohitajika**: Ongeza kiolesura cha maelezo ya hoja kwa zana za MCP +**Utendaji Mpya**: Kuruhusu watumiaji kuongeza/kuhariri/kuondoa hoja kwa zana za MCP + +#### Kipengele 4: Zana za CLI +**Madhumuni**: Usimamizi wa zana za mstari wa amri +**Mabadiliko Yanayohitajika**: Kusaidia maelezo ya hoja katika amri za uundaji/kusasisha zana za MCP +**Utendaji Mpya**: Kukubali parameter ya hoja katika amri za usanidi wa zana + +## Mpango wa Utendaji + +### Awamu ya 1: Marekebisho ya Msingi ya Mfumo wa Wakala +[ ] Sasisha konstrukta ya `McpToolImpl` ili kukubali parameter ya `arguments` +[ ] Badilisha `McpToolImpl.get_arguments()` ili irudishe hoja zilizohifadhiwa +[ ] Badilisha usanifuaji wa `service.py` wa zana ya MCP ili kushughulikia hoja +[ ] Ongeza vipimo vya kitengo kwa usimamizi wa hoja za zana ya MCP +[ ] Hakikisha maagizo ya wakala yanajumuisha hoja za zana ya MCP + +### Awamu ya 2: Usaidizi wa Zana za Nje +[ ] Sasisha zana za CLI ili kusaidia vipimo vya hoja za zana ya MCP +[ ] Andika maelezo ya muundo wa usanifuaji wa hoja kwa watumiaji +[ ] Sasisha kiolesura cha Kazi (Workbench) ili kusaidia usanifuaji wa hoja za zana ya MCP +[ ] Ongeza mifano na maandishi + +### Muhtasari wa Marekebisho ya Msimbo +| Faili | Aina ya Marekebisho | Maelezo | +|------|------------|-------------| +| `tools.py` | Imebadilishwa | Sasisha McpToolImpl ili kukubali na kuhifadhi hoja | +| `service.py` | Imebadilishwa | Pata hoja kutoka usanifuaji wa zana ya MCP (mstari wa 108-113) | +| `test_react_processor.py` | Imebadilishwa | Ongeza vipimo kwa hoja za zana ya MCP | +| Zana za CLI | Imebadilishwa | Saidia vipimo vya hoja katika amri | +| Workbench | Imebadilishwa | Ongeza kiolesura kwa usanifuaji wa hoja za zana ya MCP | + +## Mkakati wa Upimaji + +### Vipimo vya Kitengo +**Uchanganuzi wa Hoja za Zana ya MCP**: Hakikisha `service.py` inachanganua hoja vizuri kutoka usanifuaji wa zana ya MCP +**Hoja za McpToolImpl**: Hakikisha `get_arguments()` inarudisha hoja zilizosanifishwa badala ya orodha tupu +**Ulinganishi wa Awali**: Hakikisha zana za MCP bila hoja zinaendelea kufanya kazi (kurudisha orodha tupu) +**Uundaji wa Maagizo ya Wakala**: Hakikisha maagizo ya wakala yanajumuisha maelezo ya hoja za zana ya MCP + +### Vipimo vya Uunganisho +**Uteuzi wa Zana Kamili**: Mfumo wa majaribio unaweza kuendesha zana kwa kutumia hoja za zana za MCP. +**Uipakaji wa Mipangilio**: Jaribu mchakato kamili wa kupakua mipangilio kwa kutumia hoja za zana za MCP. +**Kati ya Vipengele**: Hakikisha hoja zinapitishwa vizuri kutoka kwenye mipangilio hadi katika uundaji wa zana na uundaji wa maagizo. + +### Majaribio ya Kawaida +**Tabia ya Mfumo**: Angalia kwa uangalifu kama mfumo unapokea na kutumia taarifa za hoja katika mzunguko wa ReACT. +**Uunganisho wa CLI**: Jaribu kama `tg-invoke-mcp-tool` inafanya kazi na zana za MCP ambazo zimepangwa na hoja. +**Uunganisho wa Workbench**: Jaribu kama UI inasaidia upangaji wa hoja za zana za MCP. + +## Uhamisho na Uanzishaji + +### Mkakati wa Uhamisho +Hakuna uhamishaji unaohitajika - hii ni kipengele cha ziada: +Mipangilio ya zana za MCP iliyopo ambayo haina `arguments` inaendelea kufanya kazi bila mabadiliko. +`McpToolImpl.get_arguments()` inarudisha orodha tupu kwa zana za zamani. +Mipangilio mipya inaweza kujumuisha `arguments`. + +### Mpango wa Uanzishaji +1. **Awamu ya 1**: Anzisha mabadiliko ya msingi ya mfumo kwenye eneo la maendeleo/maandalizi. +2. **Awamu ya 2**: Anzisha sasisho za zana za CLI na nyaraka. +3. **Awamu ya 3**: Anzisha sasisho za UI za Workbench kwa upangaji wa hoja. +4. **Awamu ya 4**: Uanzishaji wa uzalishaji na ufuatiliaji. + +### Mpango wa Kurudisha Nyuma +Mabadiliko ya msingi yanaambatana na matoleo ya awali - hakuna haja ya kurudisha nyuma kwa utendaji. +Ikiwa matatizo yanajitokeza, zima uchanganuzi wa hoja kwa kurejesha mantiki ya kupakua mipangilio ya zana za MCP. +Mabadiliko ya Workbench na CLI yanaweza kurejeshwa kando. + +## Masuala ya Usalama +**Hakuna eneo jipya la shambulio**: Hoja zinachanganzwa kutoka kwa vyanzo vya mipangilio iliyopo bila pembejeo mpya. +**Uthibitisho wa vigezo**: Hoja huhamishwa kwa zana za MCP bila mabadiliko - uthibitisho unaendelea katika kiwango cha zana za MCP. +**Uadilifu wa mipangilio**: Maelezo ya hoja ni sehemu ya upangaji wa zana - mfumo sawa wa usalama unafanya kazi. + +## Athari za Utendaji +**Uongezeko mdogo**: Uchanganuzi wa hoja hufanyika tu wakati wa kupakua mipangilio, sio kwa kila ombi. +**Kukua kwa saizi ya maagizo**: Maagizo ya mfumo yatajumuisha maelezo ya hoja za zana za MCP, na hivyo kuongeza matumizi ya tokeni. +**Matumizi ya kumbukumbu**: Kuongezeka kwa kiasi kidogo kwa kuhifadhi maelezo ya hoja katika vitu vya zana. + +## Nyaraka + +### Nyaraka za Mtumiaji +[ ] Sasisha mwongozo wa upangaji wa zana za MCP na mifano ya hoja. +[ ] Ongeza maelezo ya hoja kwenye maandishi ya usaidizi wa zana za CLI. +[ ] Unda mifano ya muundo wa kawaida wa hoja za zana za MCP. + +### Nyaraka za Mpelelezi +[ ] Sasisha nyaraka za darasa la `McpToolImpl`. +[ ] Ongeza maelezo ya ndani kwa mantiki ya uchanganuzi wa hoja. +[ ] Andika maelezo ya mtiririko wa hoja katika muundo wa mfumo. + +## Maswali Yaliyofunguliwa +1. **Uthibitisho wa hoja**: Je, tunapaswa kuthibitisha aina/aina za hoja zaidi ya ukaguzi wa muundo wa msingi? +2. **Utafiti wa kiotomatiki**: Uboreshaji wa baadaye wa kuuliza seva za MCP kwa schema za zana kiotomatiki? + +## Mbadala Zilizozingatiwa +1. **Utafiti wa kiotomatiki wa schema ya MCP**: Kuuliza seva za MCP kwa schema za hoja za zana wakati wa utendaji - ilikataliwa kwa sababu ya utata na wasiwasi wa kuegemea. +2. **Usajili wa kando wa hoja**: Kuhifadhi hoja za zana za MCP katika sehemu tofauti ya upangaji - ilikataliwa kwa utangamano na mbinu ya kiolezo ya maagizo. +3. **Uthibitisho wa aina**: Uthibitisho kamili wa schema ya JSON kwa hoja - imeahirishwa kama uboreshaji wa baadaye ili kuendeleza utekelezaji wa awali. + +## Marejeleo +[Maelezo ya Itifaki ya MCP](https://github.com/modelcontextprotocol/spec) +[Utekelezaji wa Zana ya Kiolezo ya Maagizo](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +[Utekelezaji wa Sasa wa Zana ya MCP](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## Toa Maelezo +[Maelezo yoyote ya ziada, michoro, au mifano] diff --git a/docs/tech-specs/mcp-tool-arguments.tr.md b/docs/tech-specs/mcp-tool-arguments.tr.md new file mode 100644 index 00000000..963ab32f --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.tr.md @@ -0,0 +1,264 @@ +--- +layout: default +title: "MCP Aracı Argümanları Belirtimi" +parent: "Turkish (Beta)" +--- + +# MCP Aracı Argümanları Belirtimi + +> **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ış +**Özellik Adı**: MCP Aracı Argümanları Desteği +**Yazar**: Claude Code Assistant +**Tarih**: 2025-08-21 +**Durum**: Tamamlandı + +### Yönetici Özeti + +ReACT ajanlarının, argüman belirtimi desteğini MCP (Model Bağlam Protokolü) araç yapılandırmalarına ekleyerek, +doğru şekilde tanımlanmış argümanlarla MCP araçlarını çağırmasına olanak sağlayın; bu, mevcut istem şablonu araçlarının +nasıl çalıştığına benzer şekilde. + + +### Problem Tanımı + + +Şu anda, ReACT ajan çerçevesindeki MCP araçları, beklenen argümanlarını belirleyememektedir. `McpToolImpl.get_arguments()` metodu +boş bir liste döndürmektedir, bu da LLM'lerin (Büyük Dil Modelleri) yalnızca araç adlarına ve açıklamalarına dayanarak +doğru parametre yapısını tahmin etmesini gerektirmektedir. Bu, aşağıdaki sorunlara yol açmaktadır: +Parametre tahminine bağlı olarak güvenilir olmayan araç çağrıları +Yanlış argümanlar nedeniyle araçların başarısız olması durumunda kötü kullanıcı deneyimi +Yürütmeden önce araç parametrelerinin doğrulanmaması +Ajan istemlerindeki eksik parametre dokümantasyonu + +### Hedefler + +[ ] MCP araç yapılandırmalarının beklenen argümanları (ad, tür, açıklama) belirtmesine izin verin. +[ ] Ajan yöneticisini, MCP araç argümanlarını istemler aracılığıyla LLM'lere sunacak şekilde güncelleyin. +[ ] Mevcut MCP araç yapılandırmalarıyla geriye dönük uyumluluğu koruyun. +[ ] İstem şablonu araçlarına benzer şekilde argüman doğrulamasını destekleyin. + +### Kapsam Dışı Hedefler +MCP sunucularından dinamik argüman keşfi (gelecek iyileştirme) +Temel yapı dışındaki argüman türü doğrulaması +Karmaşık argüman şemaları (iç içe nesneler, diziler) + +## Arka Plan ve Bağlam + +### Mevcut Durum +MCP araçları, ReACT ajan sisteminde minimum düzeyde meta veriyle yapılandırılmaktadır: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance" +} +``` + +`McpToolImpl.get_arguments()` metodu `[]` değerini döndürür, bu nedenle LLM'ler, istemlerinde argüman rehberliği almaz. + +### Sınırlamalar + +1. **Argüman belirtimi yok**: MCP araçları, beklenen + parametreleri tanımlayamaz. + +2. **LLM parametre tahmini**: Ajanlar, parametreleri araç + adlarından/açıklamalarından çıkarım yoluyla belirlemelidir. + +3. **Eksik istem bilgisi**: Ajan istemleri, MCP araçları için argüman + ayrıntılarını göstermez. + +4. **Doğrulama yok**: Geçersiz parametreler, yalnızca MCP araç + yürütme zamanında tespit edilir. + +### İlgili Bileşenler +**trustgraph-flow/agent/react/service.py**: Araç yapılandırması yükleme ve AgentManager oluşturma. +**trustgraph-flow/agent/react/tools.py**: McpToolImpl uygulaması. +**trustgraph-flow/agent/react/agent_manager.py**: Araç argümanlarıyla birlikte istem oluşturma. +**trustgraph-cli**: MCP araç yönetimi için komut satırı araçları. +**Workbench**: Ajan araç yapılandırması için harici kullanıcı arayüzü. + +## Gereksinimler + +### Fonksiyonel Gereksinimler + +1. **MCP Araç Yapılandırma Argümanları**: MCP araç yapılandırmaları, isteğe bağlı bir `arguments` dizisiyle (ad, tür ve açıklama alanları) desteklemelidir. +2. **Argüman Açıklaması**: `McpToolImpl.get_arguments()`, boş bir liste yerine yapılandırılmış argümanları döndürmelidir. +3. **İstem Entegrasyonu**: Ajan istemleri, argümanlar belirtildiğinde MCP araç argümanı ayrıntılarını içermelidir. +4. **Geriye Dönük Uyumluluk**: Argümanlar olmadan mevcut MCP araç yapılandırmaları çalışmaya devam etmelidir. +5. **Komut Satırı Desteği**: Mevcut `tg-invoke-mcp-tool` komut satırı araçları, argümanları destekler (zaten uygulanmıştır). + +### Fonksiyonel Olmayan Gereksinimler +1. **Geriye Dönük Uyumluluk**: Mevcut MCP araç yapılandırmaları için hiçbir bozucu değişiklik olmamalıdır. +2. **Performans**: Ajan istemi oluşturma üzerinde önemli bir performans etkisi olmamalıdır. +3. **Tutarlılık**: Argüman işleme, istem şablonu araç kalıplarıyla eşleşmelidir. + +### Kullanıcı Hikayeleri + +1. Bir **ajan geliştirici** olarak, LLM'lerin doğru parametrelerle araçları çağırması için MCP araç argümanlarını yapılandırmada belirtmek istiyorum. +2. Bir **workbench kullanıcısı** olarak, ajanların araçları doğru şekilde kullanması için MCP araç argümanlarını kullanıcı arayüzünde yapılandırmak istiyorum. +3. Bir **ReACT ajanı içindeki bir LLM** olarak, doğru parametreler sağlamak için istemlerdeki araç argümanı özelliklerini görmek istiyorum. + +## Tasarım + +### Yüksek Seviyeli Mimari +MCP araç yapılandırmasını, istem şablonu kalıbıyla eşleşecek şekilde aşağıdaki adımlarla genişletin: +1. MCP araç yapılandırmalarına isteğe bağlı bir `arguments` dizisi ekleyin. +2. `McpToolImpl`'nin yapılandırılmış argümanları kabul etmesini ve döndürmesini sağlayın. +3. MCP araç argümanlarını işlemek için araç yapılandırması yüklemeyi güncelleyin. +4. Ajan istemlerinin MCP araç argümanı bilgilerini içermesini sağlayın. + +### Yapılandırma Şeması +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "Get bank account balance", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "Bank account identifier" + }, + { + "name": "date", + "type": "string", + "description": "Date for balance query (optional, format: YYYY-MM-DD)" + } + ] +} +``` + +### Veri Akışı +1. **Yapılandırma Yükleme**: `on_tools_config()` ile birlikte MCP aracı yapılandırması yüklenir. +2. **Araç Oluşturma**: Argümanlar ayrıştırılır ve `McpToolImpl`'e oluşturucu aracılığıyla iletilir. +3. **İstem Oluşturma**: `agent_manager.py`, LLM istemlerine dahil etmek için `tool.arguments`'i çağırır. +4. **Araç Çağrısı**: LLM, MCP hizmetine değiştirilmeden parametreler sağlar. + +### API Değişiklikleri +Harici API değişiklikleri yok - bu tamamen içsel yapılandırma ve argüman işleme ile ilgilidir. + +### Bileşen Detayları + +#### Bileşen 1: service.py (Araç Yapılandırma Yükleme) +**Amaç**: MCP araç yapılandırmalarını ayrıştırın ve araç örnekleri oluşturun. +**Gerekli Değişiklikler**: MCP araçları için argüman ayrıştırması ekleyin (istem araçlarına benzer şekilde). +**Yeni İşlevsellik**: MCP araç yapılandırmasından `arguments` dizisini çıkarın ve `Argument` nesneleri oluşturun. + +#### Bileşen 2: tools.py (McpToolImpl) +**Amaç**: MCP araç uygulaması sarmalayıcısı. +**Gerekli Değişiklikler**: Oluşturucuda argümanları kabul edin ve bunları `get_arguments()`'den döndürün. +**Yeni İşlevsellik**: Boş bir liste döndürmek yerine yapılandırılmış argümanları saklayın ve sergileyin. + +#### Bileşen 3: Workbench (Harici Depo) +**Amaç**: Aracılar için kullanıcı arayüzü yapılandırma. +**Gerekli Değişiklikler**: MCP araçları için argüman belirtme kullanıcı arayüzü ekleyin. +**Yeni İşlevsellik**: Kullanıcıların MCP araçları için argümanları eklemesine/düzenlemesine/kaldırmasına izin verin. + +#### Bileşen 4: CLI Araçları +**Amaç**: Komut satırı aracı yönetimi. +**Gerekli Değişiklikler**: MCP araç oluşturma/güncelleme komutlarında argüman belirtimini destekleyin. +**Yeni İşlevsellik**: Araç yapılandırma komutlarında argüman parametresini kabul edin. + +## Uygulama Planı + +### 1. Aşama: Temel Ajan Çerçevesi Değişiklikleri +[ ] `McpToolImpl` oluşturucusunu `arguments` parametresini kabul edecek şekilde güncelleyin. +[ ] `McpToolImpl.get_arguments()`'ın saklanan argümanları döndürmesi için değiştirin. +[ ] `service.py` MCP araç yapılandırma ayrıştırmasını argümanları işleyecek şekilde değiştirin. +[ ] MCP araç argüman işleme için birim testleri ekleyin. +[ ] Ajan istemlerinin MCP araç argümanlarını içerdiğini doğrulayın. + +### 2. Aşama: Harici Araç Desteği +[ ] CLI araçlarını MCP araç argüman belirtimini destekleyecek şekilde güncelleyin. +[ ] Kullanıcılar için argüman yapılandırma biçimini belgeleyin. +[ ] Workbench kullanıcı arayüzünü MCP araç argüman yapılandırmasını destekleyecek şekilde güncelleyin. +[ ] Örnekler ve belgeler ekleyin. + +### Kod Değişiklikleri Özeti +| Dosya | Değişiklik Türü | Açıklama | +|------|------------|-------------| +| `tools.py` | Değiştirildi | `tools.py`'ı argümanları kabul edecek ve saklayacak şekilde güncelleyin | +| `service.py` | Değiştirildi | MCP araç yapılandırmasından argümanları ayrıştırın (satır 108-113) | +| `test_react_processor.py` | Değiştirildi | MCP araç argümanları için testler ekleyin | +| CLI araçları | Değiştirildi | Komutlarda argüman belirtimini destekleyin | +| Workbench | Değiştirildi | MCP araç argüman yapılandırması için bir kullanıcı arayüzü ekleyin | + +## Test Stratejisi + +### Birim Testleri +**MCP Araç Argüman Ayrıştırması**: `service.py`'ın MCP araç yapılandırmalarından argümanları doğru bir şekilde ayrıştırdığını test edin. +**McpToolImpl Argümanları**: `get_arguments()`'ın yapılandırılmış argümanları döndürdüğünü ve boş bir liste döndürmediğini test edin. +**Geriye Dönük Uyumluluk**: Argümanları olmayan MCP araçlarının çalışmaya devam ettiğini (boş bir liste döndürdüğünü) test edin. +**Ajan İstem Oluşturma**: Ajan istemlerinin MCP araç argümanı ayrıntılarını içerdiğini test edin. + +### Entegrasyon Testleri +**Uçtan Uca Araç Çağrısı**: MCP araç argümanlarıyla test aracısı, araçları başarıyla çağırabilir. +**Yapılandırma Yükleme**: MCP araç argümanlarıyla test yapılandırma yükleme döngüsünü tamamlayın. +**Çoklu Bileşen**: Argümanların yapılandırmadan → araç oluşturmaya → istem oluşturmaya doğru doğru şekilde aktarılmasını test edin. + +### Manuel Testler +**Ajan Davranışı**: LLM'nin ReACT döngülerinde argüman bilgilerini alıp kullandığını manuel olarak doğrulayın. +**CLI Entegrasyonu**: `tg-invoke-mcp-tool`'un yeni argüman yapılandırmalı MCP araçlarıyla çalıştığını test edin. +**Çalışma Ortamı Entegrasyonu**: Kullanıcı arayüzünün MCP araç argümanı yapılandırmasını desteklediğini test edin. + +## Göç ve Dağıtım + +### Göç Stratejisi +Göç gerektirmez - bu tamamen ek bir işlevsellik: +``arguments`` içermeyen mevcut MCP araç yapılandırmaları, herhangi bir değişiklik olmadan çalışmaya devam eder. +``McpToolImpl.get_arguments()``, eski araçlar için boş bir liste döndürür. +Yeni yapılandırmalar isteğe bağlı olarak ``arguments`` dizisini içerebilir. + +### Dağıtım Planı +1. **1. Aşama**: Çekirdek ajan çerçevesi değişikliklerini geliştirme/hazırlık ortamına dağıtın. +2. **2. Aşama**: CLI araç güncellemelerini ve belgeleri dağıtın. +3. **3. Aşama**: Argüman yapılandırması için çalışma ortamı kullanıcı arayüzü güncellemelerini dağıtın. +4. **4. Aşama**: İzleme ile üretim dağıtımı. + +### Geri Alma Planı +Çekirdek değişiklikler geriye dönük uyumludur - işlevsellik için geri alma işlemine gerek yoktur. +Sorunlar ortaya çıkarsa, MCP araç yapılandırma yükleme mantığını geri alarak argüman ayrıştırmayı devre dışı bırakın. +Çalışma ortamı ve CLI değişiklikleri bağımsızdır ve ayrı olarak geri alınabilir. + +## Güvenlik Hususları +**Yeni bir saldırı yüzeyi yok**: Argümanlar, yeni girdiler olmadan mevcut yapılandırma kaynaklarından ayrıştırılır. +**Parametre doğrulama**: Argümanlar MCP araçlarına değiştirilmeden iletilir - doğrulama MCP araç seviyesinde kalır. +**Yapılandırma bütünlüğü**: Argüman özellikleri araç yapılandırmasının bir parçasıdır - aynı güvenlik modeli uygulanır. + +## Performans Etkisi +**Minimum ek yük**: Argüman ayrıştırması yalnızca yapılandırma yükleme sırasında, her istekte değil gerçekleşir. +**İstem boyutu artışı**: Ajan istemleri, MCP araç argümanı ayrıntılarını içerecek ve bu da token kullanımını biraz artıracaktır. +**Bellek kullanımı**: Argüman özelliklerinin araç nesnelerinde depolanması için ihmal edilebilir bir artış. + +## Belgeler + +### Kullanıcı Belgeleri +[ ] Argüman örnekleriyle MCP araç yapılandırma kılavuzunu güncelleyin. +[ ] CLI araç yardım metnine argüman belirtimi ekleyin. +[ ] Yaygın MCP araç argümanı kalıplarının örneklerini oluşturun. + +### Geliştirici Belgeleri +[ ] `McpToolImpl` sınıfının belgelerini güncelleyin. +[ ] Argüman ayrıştırma mantığı için iç içe yorumlar ekleyin. +[ ] Sistem mimarisinde argüman akışını belgeleyin. + +## Açık Sorular +1. **Argüman doğrulama**: Temel yapı kontrolünün ötesinde argüman türlerini/formatlarını doğrulamalı mıyız? +2. **Dinamik keşif**: Gelecekte MCP sunucularından araç şemalarını otomatik olarak sorgulamak için bir özellik mi? + +## Göz Önünde Bulundurulan Alternatifler +1. **Dinamik MCP şema keşfi**: Çalışma zamanında araç argüman şemaları için MCP sunucularını sorgulayın - karmaşıklık ve güvenilirlik sorunları nedeniyle reddedildi. +2. **Ayrı argüman kaydı**: MCP araç argümanlarını ayrı bir yapılandırma bölümünde saklayın - başlangıç uygulamasının basit kalması için istem şablonu yaklaşımıyla tutarlılık nedeniyle reddedildi. +3. **Tip doğrulama**: Argümanlar için tam JSON şema doğrulaması - başlangıçta basit bir uygulama sağlamak için gelecekteki bir özellik olarak ertelendi. + +## Referanslar +[MCP Protokolü Özellikleri](https://github.com/modelcontextprotocol/spec) +[İstem Şablonu Araç Uygulaması](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +[Mevcut MCP Araç Uygulaması](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) + +## Ek +[Herhangi bir ek bilgi, diyagram veya örnek] diff --git a/docs/tech-specs/mcp-tool-arguments.zh-cn.md b/docs/tech-specs/mcp-tool-arguments.zh-cn.md new file mode 100644 index 00000000..0de7f22e --- /dev/null +++ b/docs/tech-specs/mcp-tool-arguments.zh-cn.md @@ -0,0 +1,203 @@ +--- +layout: default +title: "MCP 工具参数规范" +parent: "Chinese (Beta)" +--- + +# MCP 工具参数规范 + +> **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. + +## 概述 +**功能名称**: MCP 工具参数支持 +**作者**: Claude 代码助手 +**日期**: 2025-08-21 +**状态**: 最终 + +### 摘要 + +启用 ReACT 代理调用带有正确定义的参数的 MCP (模型上下文协议) 工具,通过在 MCP 工具配置中添加参数规范支持,类似于当前提示模板工具的工作方式。 + +### 问题陈述 + +目前,ReACT 代理框架中的 MCP 工具无法指定其预期的参数。`McpToolImpl.get_arguments()` 方法返回一个空列表,迫使 LLM 仅根据工具名称和描述来猜测正确的参数结构。这会导致: +- 由于参数猜测导致的不可靠工具调用 +- 当工具因错误的参数而失败时,用户体验不佳 +- 在执行之前无法验证工具参数 +- 代理提示中缺少参数文档 + +### 目标 + +- [ ] 允许 MCP 工具配置指定预期的参数(名称、类型、描述) +- [ ] 更新代理管理器,通过提示向 LLM 暴露 MCP 工具参数 +- [ ] 保持与现有 MCP 工具配置的向后兼容性 +- [ ] 支持与提示模板工具类似的参数验证 + +### 不属于目标 +- 从 MCP 服务器动态发现参数(未来增强功能) +- 参数类型验证,超出基本结构 +- 复杂的参数模式(嵌套对象、数组) + +## 背景和上下文 + +### 现状 +MCP 工具在 ReACT 代理系统中配置为具有最小的元数据: +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "获取银行账户余额", + "mcp-tool": "get_bank_balance" +} +``` + +`McpToolImpl.get_arguments()` 方法返回 `[]`,因此 LLM 在提示中不会收到任何参数指导。 + +### 局限性 + +1. **缺少参数指定**: MCP 工具无法定义预期的参数 +2. **LLM 参数猜测**: 代理必须根据工具名称/描述推断参数 +3. **提示信息缺失**: 代理提示中不包含 MCP 工具的参数详情 +4. **无验证**: 无效参数仅在 MCP 工具执行时捕获 + +### 相关组件 +- **trustgraph-flow/agent/react/service.py**: 工具配置加载和 AgentManager 创建 +- **trustgraph-flow/agent/react/tools.py**: McpToolImpl 实现 +- **trustgraph-flow/agent/react/agent_manager.py**: 使用工具参数生成提示 +- **tg-invoke-mcp-tool**: 用于 MCP 工具管理的 CLI 工具 +- **Workbench**: 代理工具配置的外部 UI + +## 要求 + +### 功能要求 + +1. **MCP 工具配置参数**: MCP 工具配置 **必须** 支持一个可选的 `arguments` 数组,包含名称、类型和描述字段 +2. **参数暴露**: `McpToolImpl.get_arguments()` **必须** 返回配置的参数,而不是空列表 +3. **提示集成**: 代理提示 **必须** 在指定有参数时,包含 MCP 工具参数详情 +4. **向后兼容性**: 没有参数的现有 MCP 工具配置 **必须** 保持正常工作 +5. **CLI 支持**: 现有的 `tg-invoke-mcp-tool` CLI 支持参数(已实现) + +### 非功能要求 +1. **向后兼容性**: 现有 MCP 工具配置零中断 +2. **性能**: 代理提示生成没有显著性能影响 +3. **一致性**: 参数处理 **必须** 与提示模板工具模式匹配 + +### 用户故事 + +1. 作为 **代理开发者**,我希望在配置中指定 MCP 工具参数,以便 LLM 可以使用正确的参数调用工具 +2. 作为 **Workbench 用户**,我希望在 UI 中配置 MCP 工具参数,以便代理正确使用工具 +3. 作为 **ReACT 代理中的 LLM**,我希望在提示中看到工具参数规范,以便我可以提供正确的参数 + +## 设计 + +### 高级架构 +通过以下方式,扩展 MCP 工具配置以匹配提示模板模式: +1. 在 MCP 工具配置中添加可选的 `arguments` 数组,包含名称、类型和描述字段 +2. 修改 `McpToolImpl` 以接受和返回配置的参数 +3. 修改工具配置加载以处理 MCP 工具参数 +4. 确保代理提示包含 MCP 工具参数信息 + +### 配置方案 +```json +{ + "type": "mcp-tool", + "name": "get_bank_balance", + "description": "获取银行账户余额", + "mcp-tool": "get_bank_balance", + "arguments": [ + { + "name": "account_id", + "type": "string", + "description": "银行账户标识符" + }, + { + "name": "date", + "type": "string", + "description": "查询余额的日期(可选,格式:YYYY-MM-DD)" + } + ] +} +``` + +### 数据流程 +1. **配置加载**: 使用参数的 MCP 工具配置通过 `on_tools_config()` 加载 +2. **工具创建**: 参数解析并传递给 `McpToolImpl` 通过构造函数 +3. **提示生成**: `agent_manager.py` 调用 `tool.arguments` 以包含在 LLM 提示中 +4. **工具调用**: LLM 提供参数,这些参数传递给 MCP 服务不变 + +### API 更改 +- 无外部 API 更改 - 这是一个纯粹的内部配置和参数处理 + +### 组件详情 + +#### 组件 1: service.py (工具配置加载) +- **目的**: 解析 MCP 工具配置并创建工具实例 +- **更改要求**: 解析 MCP 工具配置中的参数(类似于提示工具) +- **新功能**: 从 MCP 工具配置中提取 `arguments` 数组,并创建 `Argument` 对象 + +#### 组件 2: tools.py (McpToolImpl) +- **目的**: MCP 工具实现包装器 +- **更改要求**: 接受构造函数中的参数并从 `get_arguments()` 中返回 +- **新功能**: 存储并公开配置的参数,而不是返回空列表 + +#### 组件 3: Workbench (外部仓库) +- **目的**: 代理工具配置的 UI +- **更改要求**: 为 MCP 工具添加参数规范 UI +- **新功能**: 允许用户添加/编辑/删除 MCP 工具的参数 + +#### 组件 4: CLI 工具 +- **目的**: 命令列工具管理 +- **更改要求**: 支持在工具创建/更新命令中指定参数 +- **新功能**: 在工具配置命令中接受 `arguments` 参数 + +## 实施计划 + +### 阶段 1: 核心代理框架更改 +- [ ] 更新 `McpToolImpl` 构造函数以接受 `arguments` 参数 +- [ ] 修改 `McpToolImpl.get_arguments()` 以返回存储的参数,而不是空列表 +- [ ] 修改 `service.py` 中的 MCP 工具配置解析以处理参数 +- [ ] 添加 MCP 工具参数的测试 +- [ ] 更新 McpToolImpl 类文档 +- [ ] 添加参数解析逻辑的注释 +- [ ] 更新系统架构中的参数流程文档 + +### 阶段 4: 生产部署 +- 核心更改具有向后兼容性 - 无需回滚,因为功能正常 +- 如果出现问题,请通过回滚 MCP 工具配置加载逻辑来禁用参数解析 +- Workbench 和 CLI 更改是独立的,可以单独回滚 + +## 安全注意事项 +- **没有新的攻击面**: 参数是从现有配置源解析的,没有新的输入 +- **参数验证**: 参数传递给 MCP 工具不变 - 验证在 MCP 工具级别 +- **配置完整性**: 参数规范是工具配置的一部分 - 相同的安全模型适用 + +## 性能影响 +- **极小的开销**: 参数解析仅在配置加载期间发生,而不是请求时 +- **提示大小增加**: 代理提示将包含 MCP 工具参数详情,稍微增加令牌使用量 +- **内存使用**: 存储参数规范在对象中的增加,可以忽略不计 + +## 文档 + +### 用户文档 +- [ ] 更新 MCP 工具配置指南,提供参数示例 +- [ ] 在 CLI 工具的帮助文本中添加参数规范 +- [ ] 创建常见 MCP 工具参数模式的示例 + +### 开发者文档 +- [ ] 更新 `McpToolImpl` 类文档 +- [ ] 添加参数解析逻辑的注释 +- [ ] 文档系统架构中的参数流程 + +## 未解决的问题 +1. **参数验证**: 是否应该在基本结构检查之外验证参数类型/格式? +2. **动态发现**: 将来增强功能,以在运行时自动从 MCP 服务器查询工具模式? + +## 考虑的替代方案 +1. **动态的 MCP 模式发现**: 在运行时查询 MCP 服务器以获取工具参数模式 - 已拒绝,因为它复杂且不可靠 +2. **单独的参数注册表**: 将 MCP 工具参数存储在单独的配置部分中 - 已拒绝,因为与提示模板方法保持一致 +3. **类型验证**: JSON 模式验证参数 - 延迟,以便在初始实现中保持简单 + +## 引用 +- [MCP 协议规范](https://github.com/modelcontextprotocol/spec) +- [提示模板工具实现](./trustgraph-flow/trustgraph/agent/react/service.py#L114-129) +- [当前的 MCP 工具实现](./trustgraph-flow/trustgraph/agent/react/tools.py#L58-86) diff --git a/docs/tech-specs/mcp-tool-bearer-token.ar.md b/docs/tech-specs/mcp-tool-bearer-token.ar.md new file mode 100644 index 00000000..fc2170c1 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.ar.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "مواصفات مصادقة رمز الحامل لأدوات MCP" +parent: "Arabic (Beta)" +--- + +# مواصفات مصادقة رمز الحامل لأدوات MCP + +> **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. + +> **⚠️ هام: مخصص للعملاء ذوي المستأجر الواحد فقط** +> +> تصف هذه المواصفات آلية مصادقة أساسية على مستوى الخدمة لأدوات MCP. إنها **ليست** حلاً كاملاً للمصادقة وليست **مناسبة** لـ: +> - بيئات متعددة المستخدمين +> - عمليات نشر متعددة المستأجرين +> - المصادقة الموحدة +> - نقل سياق المستخدم +> - التفويض لكل مستخدم +> +> توفر هذه الميزة **رمزًا ثابتًا واحدًا لكل أداة MCP**، يتم مشاركته عبر جميع المستخدمين والجلسات. إذا كنت بحاجة إلى مصادقة لكل مستخدم أو لكل مستأجر، فهذه ليست الحل المناسب. + +## نظرة عامة +**اسم الميزة**: دعم رمز الحامل للمصادقة لأدوات MCP +**المؤلف**: مساعد كود كلود +**التاريخ**: 2025-11-11 +**الحالة**: قيد التطوير + +### ملخص تنفيذي + +قم بتمكين تكوينات أدوات MCP لتحديد رموز حامل اختيارية للمصادقة مع خوادم MCP المحمية. يتيح ذلك لـ TrustGraph استدعاء أدوات MCP المستضافة على الخوادم التي تتطلب المصادقة بشكل آمن، دون تعديل وكيل الأداة أو واجهات استدعاء الأداة. + +**هام**: هذه آلية مصادقة أساسية مصممة لسيناريوهات المصادقة من خدمة إلى خدمة، خاصة بالمستأجر الواحد. إنها **ليست** مناسبة لـ: +بيئات متعددة المستخدمين حيث يحتاج المستخدمون المختلفون إلى بيانات اعتماد مختلفة +عمليات نشر متعددة المستأجرين تتطلب عزلًا لكل مستأجر +سيناريوهات المصادقة الموحدة +مصادقة أو تفويض على مستوى المستخدم +إدارة بيانات الاعتماد الديناميكية أو تحديث الرموز + +توفر هذه الميزة رمز حامل ثابتًا على مستوى النظام لكل تكوين أداة MCP، يتم مشاركته عبر جميع المستخدمين واستدعاءات تلك الأداة. + +### بيان المشكلة + +حاليًا، يمكن لأدوات MCP الاتصال فقط بخوادم MCP التي يمكن الوصول إليها للجمهور. تتطلب العديد من عمليات نشر MCP الإنتاجية مصادقة عبر رموز الحامل لأسباب أمنية. بدون دعم المصادقة: +لا يمكن لأدوات MCP الاتصال بخوادم MCP الآمنة +يجب على المستخدمين إما تعريض خوادم MCP للجمهور أو تنفيذ وكلاء عكسيين +لا توجد طريقة موحدة لتمرير بيانات الاعتماد إلى اتصالات MCP +لا يمكن فرض أفضل ممارسات الأمان على نقاط نهاية MCP + +### الأهداف + +[ ] السماح لتكوينات أدوات MCP بتحديد معلمة `auth-token` اختيارية +[ ] تحديث خدمة أداة MCP لاستخدام رموز الحامل عند الاتصال بخوادم MCP +[ ] تحديث أدوات سطر الأوامر لدعم تعيين/عرض رموز المصادقة +[ ] الحفاظ على التوافق مع الإصدارات السابقة لتكوينات MCP غير المصادقة +[ ] توثيق اعتبارات الأمان لتخزين الرموز + +### الأهداف غير المشمولة +تحديث الرموز الديناميكي أو تدفقات OAuth (رموز ثابتة فقط) +تشفير الرموز المخزنة (أمان نظام التكوين خارج النطاق) +طرق مصادقة بديلة (المصادقة الأساسية، مفاتيح API، إلخ.) +التحقق من صحة الرموز أو انتهاء صلاحيتها +**المصادقة لكل مستخدم**: لا تدعم هذه الميزة بيانات اعتماد خاصة بالمستخدم +**عزل متعدد المستأجرين**: لا توفر هذه الميزة إدارة رموز لكل مستأجر +**المصادقة الموحدة**: لا تتكامل هذه الميزة مع موفري الهوية (SSO، OAuth، SAML، إلخ.) +**المصادقة الواعية بالسياق**: لا يتم تمرير الرموز بناءً على سياق المستخدم أو الجلسة + +## الخلفية والسياق + +### الحالة الحالية +يتم تخزين تكوينات أدوات MCP في مجموعة التكوين `mcp` بهذه البنية: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +تتصل خدمة أداة MCP بالخوادم باستخدام `streamablehttp_client(url)` بدون أي رؤوس مصادقة. + +### القيود + +**قيود النظام الحالية:** +1. **لا يوجد دعم للمصادقة:** لا يمكن الاتصال بخوادم MCP المحمية. +2. **تعرض أمني:** يجب أن تكون خوادم MCP متاحة للجمهور أو تستخدم أمان على مستوى الشبكة فقط. +3. **مشكلات النشر في بيئة الإنتاج:** لا يمكن اتباع أفضل الممارسات الأمنية لنقاط نهاية واجهة برمجة التطبيقات. + +**قيود هذا الحل:** +1. **نظام مستأجر واحد فقط:** رمز ثابت واحد لكل أداة MCP، مشترك بين جميع المستخدمين. +2. **لا توجد بيانات اعتماد خاصة بالمستخدم:** لا يمكن المصادقة كمستخدمين مختلفين أو تمرير سياق المستخدم. +3. **لا يوجد دعم للأنظمة متعددة المستأجرين:** لا يمكن عزل بيانات الاعتماد حسب المستأجر أو المؤسسة. +4. **رموز ثابتة فقط:** لا يوجد دعم لتحديث الرموز أو تدويرها أو معالجة انتهاء صلاحيتها. +5. **مصادقة على مستوى الخدمة:** تقوم المصادقة على خدمة TrustGraph، وليس على المستخدمين الفرديين. +6. **سياق أمني مشترك:** تستخدم جميع استدعاءات أداة MCP نفس الاعتماد. + +### مدى ملاءمة حالة الاستخدام + +**✅ حالات الاستخدام المناسبة:** +عمليات نشر TrustGraph ذات المستأجر الواحد. +مصادقة من خدمة إلى خدمة (TrustGraph → خادم MCP). +بيئات التطوير والاختبار. +أدوات MCP الداخلية التي يتم الوصول إليها بواسطة نظام TrustGraph. +السيناريوهات التي يشارك فيها جميع المستخدمين نفس مستوى الوصول إلى أداة MCP. +بيانات اعتماد خدمة ثابتة وطويلة الأجل. + +**❌ حالات الاستخدام غير المناسبة:** +الأنظمة متعددة المستخدمين التي تتطلب مصادقة خاصة بالمستخدم. +عمليات نشر SaaS متعددة المستأجرين مع متطلبات عزل المستأجر. +سيناريوهات المصادقة الموحدة (SSO، OAuth، SAML). +الأنظمة التي تتطلب تمرير سياق المستخدم إلى خوادم MCP. +البيئات التي تحتاج إلى تحديث الرموز ديناميكيًا أو رموز قصيرة الأجل. +التطبيقات التي تحتاج فيها مستخدمون مختلفون إلى مستويات أذونات مختلفة. +متطلبات الامتثال لتسجيلات التدقيق على مستوى المستخدم. + +**مثال على سيناريو مناسب:** +عملية نشر TrustGraph لمنظمة واحدة حيث يستخدم جميع الموظفين نفس أداة MCP الداخلية (على سبيل المثال، البحث في قاعدة بيانات الشركة). يتطلب خادم MCP مصادقة لمنع الوصول الخارجي، ولكن جميع المستخدمين الداخليين لديهم نفس مستوى الوصول. + +**مثال على سيناريو غير مناسب:** +منصة SaaS متعددة المستأجرين لـ TrustGraph حيث يحتاج كل من المستأجر A والمستأجر B إلى الوصول إلى خوادم MCP الخاصة بهم المعزولة ببيانات اعتماد منفصلة. لا يدعم هذا الميزة إدارة الرموز الخاصة بالمستأجر. + +### المكونات ذات الصلة +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: خدمة استدعاء أداة MCP. +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: أداة سطر أوامر لإنشاء/تحديث تكوينات MCP. +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: أداة سطر أوامر لعرض تكوينات MCP. +**مجموعة تطوير البرامج (SDK) لـ MCP بلغة Python**: `streamablehttp_client` من `mcp.client.streamable_http` + +## المتطلبات + +### المتطلبات الوظيفية + +1. **رمز مصادقة تكوين MCP:** يجب أن تدعم تكوينات أداة MCP حقل `auth-token` اختياري. +2. **استخدام رمز مميز:** يجب أن ترسل خدمة أداة MCP رأس `Authorization: Bearer {token}` عند تكوين رمز مميز. +3. **دعم سطر الأوامر:** يجب أن تقبل `tg-set-mcp-tool` معلمة `--auth-token` اختيارية. +4. **عرض الرمز:** يجب أن تشير `tg-show-mcp-tools` إلى متى تم تكوين رمز مميز (تم إخفاءه لأسباب أمنية). +5. **التوافق مع الإصدارات السابقة:** يجب أن تستمر تكوينات أداة MCP الحالية بدون رمز مميز في العمل. + +### المتطلبات غير الوظيفية +1. **التوافق مع الإصدارات السابقة:** لا توجد تغييرات فاصلة للإصدارات لتكوينات أداة MCP الحالية. +2. **الأداء:** لا يوجد تأثير كبير على الأداء على استدعاء أداة MCP. +3. **الأمان:** يتم تخزين الرموز في التكوين (يرجى توثيق الآثار الأمنية). + +### قصص المستخدم + +1. بصفتي **مهندس DevOps**، أريد تكوين رموز مميزة لأدوات MCP حتى أتمكن من تأمين نقاط نهاية خادم MCP. +2. بصفتي **مستخدم سطر أوامر**، أريد تعيين رموز مميزة عند إنشاء أدوات MCP حتى أتمكن من الاتصال بالخوادم المحمية. +3. بصفتي **مسؤول النظام**، أريد أن أرى أي أدوات MCP تم تكوين مصادقة لها حتى أتمكن من تدقيق إعدادات الأمان. + +## التصميم + +### البنية عالية المستوى +قم بتوسيع تكوين وخدمة أداة MCP لدعم مصادقة الرمز المميز: +1. أضف حقل `auth-token` اختياري إلى مخطط تكوين أداة MCP. +2. قم بتعديل خدمة أداة MCP لقراءة الرمز المميز وتمريره إلى عميل HTTP. +3. قم بتحديث أدوات سطر الأوامر لدعم تعيين وعرض الرموز المميزة. +4. قم بتوثيق الاعتبارات الأمنية وأفضل الممارسات. + +### مخطط التكوين + +**المخطط الحالي:** +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**مخطط جديد** (مع رمز مصادقة اختياري): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**وصف الحقول:** +`remote-name` (اختياري): الاسم المستخدم بواسطة خادم MCP (افتراضيًا، مفتاح التكوين) +`url` (إلزامي): عنوان URL لنقطة نهاية خادم MCP +`auth-token` (اختياري): رمز مميز (Bearer token) للمصادقة + +### تدفق البيانات + +1. **تخزين التكوين:** يقوم المستخدم بتشغيل `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123` +2. **تحميل التكوين:** يتلقى خدمة أداة MCP تحديث التكوين عبر استدعاء رد (callback) `on_mcp_config()` +3. **استدعاء الأداة:** عند استدعاء الأداة: + تقرأ الخدمة `auth-token` من التكوين (إذا كان موجودًا) + تقوم بإنشاء قاموس الرؤوس: `{"Authorization": "Bearer {token}"}` + تمرر الرؤوس إلى `streamablehttp_client(url, headers=headers)` + يقوم خادم MCP بالتحقق من صحة الرمز المميز ومعالجة الطلب + +### تغييرات واجهة برمجة التطبيقات (API) +لا توجد تغييرات في واجهة برمجة التطبيقات الخارجية - فقط توسيع مخطط التكوين. + +### تفاصيل المكون + +#### المكون 1: service.py (خدمة أداة MCP) +**الملف:** `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**الغرض:** استدعاء أدوات MCP على الخوادم البعيدة + +**التغييرات المطلوبة** (في طريقة `invoke_tool()`): +1. التحقق من وجود `auth-token` في تكوين `self.mcp_services[name]` +2. إنشاء قاموس الرؤوس مع رأس "Authorization" إذا كان الرمز المميز موجودًا +3. تمرير الرؤوس إلى `streamablehttp_client(url, headers=headers)` + +**الكود الحالي** (الأسطر 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**الكود المُعدَّل**: +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### المكون 2: set_mcp_tool.py (أداة تكوين سطر الأوامر) +**الملف**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**الغرض**: إنشاء/تحديث إعدادات أداة MCP + +**التغييرات المطلوبة**: +1. إضافة وسيطة اختيارية `--auth-token` إلى argparse +2. تضمين `auth-token` في ملف JSON الخاص بالتكوين عند توفره + +**الوسائط الحالية**: +`--id` (مطلوب): معرف أداة MCP +`--remote-name` (اختياري): اسم أداة MCP البعيدة +`--tool-url` (مطلوب): نقطة نهاية عنوان URL لأداة MCP +`-u, --api-url` (اختياري): عنوان URL لواجهة برمجة تطبيقات TrustGraph + +**وسيطة جديدة**: +`--auth-token` (اختياري): رمز مميز للمصادقة + +**تعديل بناء التكوين**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### المكون 3: show_mcp_tools.py (أداة العرض من سطر الأوامر) +**الملف**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**الغرض**: عرض إعدادات أدوات MCP. + +**التغييرات المطلوبة**: +1. إضافة عمود "Auth" إلى جدول الإخراج. +2. عرض "نعم" أو "لا" بناءً على وجود رمز المصادقة. +3. عدم عرض قيمة الرمز الفعلية (لأسباب أمنية). + +**الإخراج الحالي**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**الناتج الجديد**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### المكون 4: التوثيق +**الملف**: `docs/cli/tg-set-mcp-tool.md` + +**التغييرات المطلوبة**: +1. توثيق المعاملة الجديدة `--auth-token` +2. تقديم مثال للاستخدام مع المصادقة +3. توثيق الاعتبارات الأمنية + +## خطة التنفيذ + +### المرحلة الأولى: إنشاء المواصفات الفنية +[x] كتابة مواصفات فنية شاملة توثق جميع التغييرات + +### المرحلة الثانية: تحديث خدمة MCP +[ ] تعديل `invoke_tool()` في `service.py` لقراءة رمز المصادقة من التكوين +[ ] إنشاء قاموس الرؤوس وتمريره إلى `streamablehttp_client` +[ ] الاختبار مع خادم MCP مصادق عليه + +### المرحلة الثالثة: تحديث أدوات سطر الأوامر +[ ] إضافة المعامل `--auth-token` إلى `set_mcp_tool.py` +[ ] تضمين رمز المصادقة في ملف تكوين JSON +[ ] إضافة عمود "المصادقة" إلى إخراج `show_mcp_tools.py` +[ ] اختبار تغييرات أداة سطر الأوامر + +### المرحلة الرابعة: تحديث التوثيق +[ ] توثيق المعامل `--auth-token` في `tg-set-mcp-tool.md` +[ ] إضافة قسم للاعتبارات الأمنية +[ ] تقديم مثال للاستخدام + +### المرحلة الخامسة: الاختبار +[ ] اختبار أن خدمة MCP تقرأ رمز المصادقة وتتصل بنجاح +[ ] اختبار التوافق مع الإصدارات السابقة (الأدوات بدون رمز مصادقة لا تزال تعمل) +[ ] اختبار أن أدوات سطر الأوامر تقبل وتخزن رمز المصادقة بشكل صحيح +[ ] اختبار أن الأمر "عرض" يعرض حالة المصادقة بشكل صحيح + +### ملخص التغييرات في التعليمات البرمجية +| الملف | نوع التغيير | الأسطر | الوصف | +|------|------------|-------|-------------| +| `service.py` | تم التعديل | ~52-66 | إضافة قراءة رمز المصادقة وإنشاء الرؤوس | +| `set_mcp_tool.py` | تم التعديل | ~30-60 | إضافة وسيطة --auth-token وتخزين التكوين | +| `show_mcp_tools.py` | تم التعديل | ~40-70 | إضافة عمود المصادقة للعرض | +| `tg-set-mcp-tool.md` | تم التعديل | متنوع | توثيق المعامل الجديد | + +## استراتيجية الاختبار + +### اختبارات الوحدة +**قراءة رمز المصادقة**: اختبار ما إذا كانت `invoke_tool()` تقرأ رمز المصادقة بشكل صحيح من التكوين +**إنشاء الرؤوس**: اختبار ما إذا كان يتم إنشاء رأس التفويض بشكل صحيح مع البادئة "Bearer" +**التوافق مع الإصدارات السابقة**: اختبار ما إذا كانت الأدوات بدون رمز مصادقة تعمل دون تغيير +**تحليل وسيطات سطر الأوامر**: اختبار ما إذا كانت المعامل `--auth-token` يتم تحليلها بشكل صحيح + +### اختبارات التكامل +**الاتصال المصادق**: اختبار ما إذا كانت خدمة MCP تتصل بخادم مصادق عليه +**نهاية إلى نهاية**: اختبار تدفق سطر الأوامر → تخزين التكوين → استدعاء الخدمة باستخدام رمز المصادقة +**غير مطلوب رمز المصادقة**: اختبار الاتصال بخادم غير مصادق عليه لا يزال يعمل + +### الاختبار اليدوي +**خادم MCP حقيقي**: اختبار مع خادم MCP فعلي يتطلب مصادقة باستخدام رمز "Bearer" +**تدفق سطر الأوامر**: اختبار التدفق الكامل: تعيين الأداة باستخدام رمز مصادقة → استدعاء الأداة → التحقق من النجاح +**إخفاء العرض**: التحقق من أن حالة المصادقة معروضة ولكن قيمة الرمز غير معروضة + +## الترحيل والنشر + +### استراتيجية الترحيل +لا يلزم الترحيل - هذه وظيفة إضافية بحتة: +تكوينات أدوات MCP الحالية بدون `auth-token` تستمر في العمل دون تغيير +يمكن أن تتضمن التكوينات الجديدة اختياريًا حقل `auth-token` +تقبل أدوات سطر الأوامر ولكن لا تتطلب المعامل `--auth-token` + +### خطة النشر +1. **المرحلة 1**: نشر تغييرات الخدمة الأساسية إلى التطوير/التجريب +2. **المرحلة 2**: نشر تحديثات أدوات سطر الأوامر +3. **المرحلة 3**: تحديث التوثيق +4. **المرحلة 4**: النشر في بيئة الإنتاج مع المراقبة + +### خطة التراجع +التغييرات الأساسية متوافقة مع الإصدارات السابقة - لا تتأثر الأدوات الحالية +في حالة ظهور مشكلات، يمكن تعطيل معالجة رمز المصادقة عن طريق إزالة منطق إنشاء الرأس +يمكن التراجع عن تغييرات سطر الأوامر بشكل مستقل + +## اعتبارات الأمان + +### ⚠️ قيد حاسم: مصادقة المستأجر الواحد فقط + +**هذه آلية المصادقة غير مناسبة للبيئات متعددة المستخدمين أو متعددة المستأجرين.** + +**بيانات اعتماد مشتركة**: جميع المستخدمين والاستدعاءات يشاركون نفس الرمز لكل أداة MCP +**لا يوجد سياق مستخدم**: لا يمكن لخادم MCP التمييز بين مستخدمي TrustGraph المختلفين +**عزل المستأجر**: تشارك جميع المستأجرين نفس الاعتماد لكل أداة MCP +**قيود سجل التدقيق**: يسجل خادم MCP جميع الطلبات من نفس الاعتماد +**نطاق الأذونات**: لا يمكن فرض مستويات أذونات مختلفة لمستخدمين مختلفين + +**لا تستخدم هذه الميزة إذا:** +يخدم توزيعة TrustGraph الخاصة بك مؤسسات متعددة (متعددة المستأجرين) +تحتاج إلى تتبع المستخدم الذي قام بالوصول إلى أداة MCP +تتطلب مستخدمون مختلفون مستويات أذونات مختلفة +تحتاج إلى الامتثال لمتطلبات التدقيق على مستوى المستخدم +خادم MCP الخاص بك يفرض حدود معدل أو حصص لكل مستخدم + +**حلول بديلة لسيناريوهات المستخدمين المتعددين/العملاء المتعددين:** +تنفيذ نشر سياق المستخدم من خلال رؤوس مخصصة +نشر مثيلات TrustGraph منفصلة لكل عميل +استخدام عزل على مستوى الشبكة (VPCs، شبكات الخدمات) +تنفيذ طبقة وكيل تتعامل مع المصادقة لكل مستخدم + +### تخزين الرموز المميزة +**مخاطر**: يتم تخزين الرموز المميزة للمصادقة كنص عادي في نظام التكوين + +**تدابير تخفيفية**: +توثيق أن الرموز المميزة مخزنة بدون تشفير +يوصى باستخدام الرموز المميزة قصيرة الأجل كلما أمكن ذلك +يوصى بتطبيق ضوابط وصول مناسبة على تخزين التكوين +ضع في اعتبارك تحسينًا مستقبليًا لتخزين الرموز المميزة المشفرة + +### كشف الرموز المميزة +**مخاطر**: يمكن الكشف عن الرموز المميزة في سجلات أو مخرجات سطر الأوامر + +**تدابير تخفيفية**: +لا تقم بتسجيل قيم الرموز المميزة (قم بتسجيل "تم تكوين المصادقة: نعم/لا" فقط) +يعرض أمر "show" الخاص بسطر الأوامر الحالة "مخفية" فقط، وليس الرمز المميز الفعلي +لا تقم بتضمين الرموز المميزة في رسائل الخطأ + +### أمان الشبكة +**مخاطر**: يتم نقل الرموز المميزة عبر اتصالات غير مشفرة + +**تدابير تخفيفية**: +يوصى بتوثيق استخدام عناوين URL لبروتوكول HTTPS لخوادم MCP +تحذير المستخدمين بشأن مخاطر النقل النصي باستخدام HTTP + +### الوصول إلى التكوين +**مخاطر**: يؤدي الوصول غير المصرح به إلى نظام التكوين إلى كشف الرموز المميزة + +**تدابير تخفيفية**: +قم بتوثيق أهمية تأمين الوصول إلى نظام التكوين +يوصى بمبدأ الامتياز الأقل للوصول إلى التكوين +ضع في اعتبارك تسجيل التدقيق للتغييرات في التكوين (تحسين مستقبلي) + +### بيئات المستخدمين المتعددين +**مخاطر**: في عمليات النشر متعددة المستخدمين، يشارك جميع المستخدمين نفس بيانات اعتماد MCP + +**فهم المخاطر**: +يستخدم كل من المستخدم أ والمستخدم ب نفس الرمز المميز عند الوصول إلى أداة MCP +لا يمكن لخادم MCP التمييز بين مستخدمي TrustGraph المختلفين +لا توجد طريقة لفرض أذونات أو حدود معدل لكل مستخدم +تُظهر سجلات التدقيق على خادم MCP جميع الطلبات من نفس الاعتماد +إذا تم اختراق جلسة مستخدم واحد، يتمتع المهاجم بنفس وصول MCP مثل جميع المستخدمين + +**هذا ليس خطأ - إنه قيد أساسي لهذا التصميم.** + +## التأثير على الأداء +**نفقات عامة ضئيلة**: يضيف بناء الرأس وقت معالجة ضئيل +**تأثير الشبكة**: يضيف رأس HTTP إضافي ~ 50-200 بايت لكل طلب +**استخدام الذاكرة**: زيادة طفيفة لتخزين سلسلة الرمز المميز في التكوين + +## التوثيق + +### وثائق المستخدم +[ ] قم بتحديث `tg-set-mcp-tool.md` باستخدام معلمة `--auth-token` +[ ] أضف قسمًا للاعتبارات الأمنية +[ ] قدم مثالًا للاستخدام باستخدام رمز مميز +[ ] قم بتوثيق آثار تخزين الرمز المميز + +### وثائق المطور +[ ] أضف تعليقات مضمنة للتعامل مع الرمز المميز للمصادقة في `service.py` +[ ] وثق منطق بناء الرأس +[ ] قم بتحديث وثائق مخطط تكوين أداة MCP + +## أسئلة مفتوحة +1. **تشفير الرمز المميز**: هل يجب علينا تنفيذ تخزين مشفر للرموز المميزة في نظام التكوين؟ +2. **تحديث الرمز المميز**: دعم مستقبلي لتدفقات تحديث OAuth أو تدوير الرموز المميزة؟ +3. **طرق مصادقة بديلة**: هل يجب أن ندعم المصادقة الأساسية أو مفاتيح API أو طرق أخرى؟ + +## بدائل تم أخذها في الاعتبار + +1. **متغيرات البيئة للرموز المميزة**: قم بتخزين الرموز المميزة في متغيرات البيئة بدلاً من التكوين + **مرفوض**: يعقد النشر وإدارة التكوين + +2. **مخزن أسرار منفصل**: استخدم نظام إدارة أسرار مخصص + **مؤجل**: خارج نطاق التنفيذ الأولي، ضع في اعتبارك تحسينًا مستقبليًا + +3. **طرق مصادقة متعددة**: دعم الأساسي و API key و OAuth وما إلى ذلك + **مرفوض**: تغطي الرموز المميزة الخاصة بالحامل معظم حالات الاستخدام، حافظ على بساطة التنفيذ الأولي + +4. **تخزين مشفر للرموز المميزة**: قم بتشفير الرموز المميزة في نظام التكوين + **مؤجل**: يعد أمان نظام التكوين مصدر قلق أوسع، وتأجيله إلى عمل مستقبلي + +5. **الرموز المميزة لكل استدعاء**: اسمح بتمرير الرموز المميزة في وقت الاستدعاء + **مرفوض**: ينتهك فصل الاهتمامات، لا ينبغي للوكيل التعامل مع بيانات الاعتماد + +## المراجع +[مواصفات بروتوكول MCP](https://github.com/modelcontextprotocol/spec) +[مصادقة حامل HTTP (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[خدمة أداة MCP الحالية](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[مواصفات وسيطات أداة MCP](./mcp-tool-arguments.md) + +## الملحق + +### مثال للاستخدام + +**إعداد أداة MCP مع المصادقة:** +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**عرض أدوات MCP:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### مثال على الإعدادات + +**مخزنة في نظام الإعدادات:** +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### أفضل الممارسات الأمنية + +1. **استخدام HTTPS**: استخدم دائمًا عناوين URL لبروتوكول HTTPS لخوادم MCP التي تتطلب مصادقة. +2. **الرموز قصيرة الأجل**: استخدم الرموز التي لها تاريخ انتهاء صلاحية كلما أمكن ذلك. +3. **أقل الامتيازات**: امنح الرموز الحد الأدنى من الأذونات المطلوبة. +4. **التحكم في الوصول**: قم بتقييد الوصول إلى نظام التكوين. +5. **تغيير الرموز بشكل دوري**: قم بتغيير الرموز بانتظام. +6. **تسجيل التدقيق**: راقب تغييرات التكوين بحثًا عن أحداث أمنية. diff --git a/docs/tech-specs/mcp-tool-bearer-token.es.md b/docs/tech-specs/mcp-tool-bearer-token.es.md new file mode 100644 index 00000000..909bd0c3 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.es.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "Especificación de autenticación de tokens Bearer para herramientas MCP" +parent: "Spanish (Beta)" +--- + +# Especificación de autenticación de tokens Bearer para herramientas MCP + +> **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. + +> **⚠️ IMPORTANTE: SOLO PARA UN ÚNICO ARREGLO (SINGLE-TENANT)** +> +> Esta especificación describe un **mecanismo básico de autenticación a nivel de servicio** para herramientas MCP. **NO** es una solución de autenticación completa y **NO es adecuada** para: +> - Entornos multiusuario +> - Despliegues multi-inquilino (multi-tenant) +> - Autenticación federada +> - Propagación del contexto del usuario +> - Autorización por usuario +> +> Esta función proporciona **un único token estático por herramienta MCP**, compartido entre todos los usuarios y sesiones. Si necesita autenticación por usuario o por inquilino, esta no es la solución adecuada. + +## Descripción general +**Nombre de la función**: Soporte de autenticación de tokens Bearer para herramientas MCP +**Autor**: Claude Code Assistant +**Fecha**: 2025-11-11 +**Estado**: En desarrollo + +### Resumen ejecutivo + +Permite que las configuraciones de las herramientas MCP especifiquen tokens Bearer opcionales para autenticarse con servidores MCP protegidos. Esto permite que TrustGraph invoque de forma segura las herramientas MCP alojadas en servidores que requieren autenticación, sin modificar las interfaces de invocación de agentes o herramientas. + +**IMPORTANTE**: Este es un mecanismo de autenticación básico diseñado para escenarios de autenticación de servicio a servicio en un único arreglo (single-tenant). **NO** es adecuado para: +Entornos multiusuario donde diferentes usuarios necesitan diferentes credenciales +Despliegues multi-inquilino (multi-tenant) que requieren aislamiento por inquilino +Escenarios de autenticación federada +Autenticación o autorización a nivel de usuario +Gestión dinámica de credenciales o actualización de tokens + +Esta función proporciona un token Bearer estático y a nivel de sistema por configuración de herramienta MCP, compartido entre todos los usuarios e invocaciones de esa herramienta. + +### Declaración del problema + +Actualmente, las herramientas MCP solo pueden conectarse a servidores MCP accesibles públicamente. Muchos despliegues de MCP en producción requieren autenticación mediante tokens Bearer por motivos de seguridad. Sin soporte de autenticación: +Las herramientas MCP no pueden conectarse a servidores MCP protegidos +Los usuarios deben exponer los servidores MCP públicamente o implementar proxies inversos +No existe una forma estandarizada de pasar credenciales a las conexiones MCP +No se pueden aplicar las mejores prácticas de seguridad en los puntos finales de MCP + +### Objetivos + +[ ] Permitir que las configuraciones de las herramientas MCP especifiquen un parámetro opcional `auth-token` +[ ] Actualizar el servicio de la herramienta MCP para usar tokens Bearer al conectarse a servidores MCP +[ ] Actualizar las herramientas de la CLI para admitir la configuración/visualización de tokens de autenticación +[ ] Mantener la compatibilidad con versiones anteriores con configuraciones de MCP sin autenticación +[ ] Documentar las consideraciones de seguridad para el almacenamiento de tokens + +### Objetivos no incluidos +Actualización dinámica de tokens o flujos OAuth (solo tokens estáticos) +Cifrado de tokens almacenados (la seguridad del sistema de configuración está fuera del alcance) +Métodos de autenticación alternativos (autenticación básica, claves API, etc.) +Validación o verificación de la fecha de caducidad de los tokens +**Autenticación por usuario**: Esta función **NO** admite credenciales específicas del usuario +**Aislamiento multi-inquilino (multi-tenant)**: Esta función **NO** proporciona gestión de tokens por inquilino +**Autenticación federada**: Esta función **NO** se integra con proveedores de identidad (SSO, OAuth, SAML, etc.) +**Autenticación con conocimiento del contexto**: Los tokens no se pasan en función del contexto del usuario o la sesión + +## Antecedentes y contexto + +### Estado actual +Las configuraciones de las herramientas MCP se almacenan en el grupo de configuración `mcp` con esta estructura: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +El servicio de la herramienta MCP se conecta a los servidores utilizando `streamablehttp_client(url)` sin ningún encabezado de autenticación. + +### Limitaciones + +**Limitaciones del Sistema Actual:** +1. **Sin soporte de autenticación:** No se puede conectar a servidores MCP protegidos. +2. **Exposición de seguridad:** Los servidores MCP deben ser accesibles públicamente o utilizar solo seguridad a nivel de red. +3. **Problemas de implementación en producción:** No se pueden seguir las mejores prácticas de seguridad para los puntos finales de la API. + +**Limitaciones de Esta Solución:** +1. **Solo para un único inquilino:** Un token estático por herramienta MCP, compartido entre todos los usuarios. +2. **Sin credenciales por usuario:** No se puede autenticar como diferentes usuarios ni pasar el contexto del usuario. +3. **Sin soporte para múltiples inquilinos:** No se pueden aislar las credenciales por inquilino u organización. +4. **Solo tokens estáticos:** No hay soporte para la renovación, rotación o manejo de la expiración de los tokens. +5. **Autenticación a nivel de servicio:** Autentica el servicio TrustGraph, no a usuarios individuales. +6. **Contexto de seguridad compartido:** Todas las invocaciones de una herramienta MCP utilizan la misma credencial. + +### Aplicabilidad del Caso de Uso + +**✅ Casos de Uso Apropiados:** +Implementaciones de TrustGraph de un solo inquilino. +Autenticación de servicio a servicio (TrustGraph → Servidor MCP). +Entornos de desarrollo y pruebas. +Herramientas MCP internas a las que accede el sistema TrustGraph. +Escenarios en los que todos los usuarios comparten el mismo nivel de acceso a la herramienta MCP. +Credenciales de servicio estáticas y de larga duración. + +**❌ Casos de Uso Inapropiados:** +Sistemas multiusuario que requieren autenticación por usuario. +Implementaciones SaaS multiinquilino con requisitos de aislamiento de inquilinos. +Escenarios de autenticación federada (SSO, OAuth, SAML). +Sistemas que requieren la propagación del contexto del usuario a los servidores MCP. +Entornos que necesitan la renovación dinámica de tokens o tokens de corta duración. +Aplicaciones donde diferentes usuarios necesitan diferentes niveles de permisos. +Requisitos de cumplimiento para registros de auditoría a nivel de usuario. + +**Ejemplo de Escenario Apropiado:** +Una implementación de TrustGraph de una sola organización donde todos los empleados utilizan la misma herramienta MCP interna (por ejemplo, búsqueda de bases de datos de la empresa). El servidor MCP requiere autenticación para evitar el acceso externo, pero todos los usuarios internos tienen el mismo nivel de acceso. + +**Ejemplo de Escenario Inapropiado:** +Una plataforma SaaS multiinquilino de TrustGraph donde el inquilino A y el inquilino B necesitan acceder a sus propios servidores MCP aislados con credenciales separadas. Esta función NO admite la administración de tokens por inquilino. + +### Componentes Relacionados +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: Servicio de invocación de la herramienta MCP. +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: Herramienta de línea de comandos para crear/actualizar configuraciones de MCP. +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: Herramienta de línea de comandos para mostrar configuraciones de MCP. +**SDK de Python para MCP**: `streamablehttp_client` de `mcp.client.streamable_http` + +## Requisitos + +### Requisitos Funcionales + +1. **Token de Autenticación de la Configuración de MCP:** Las configuraciones de la herramienta MCP DEBEN admitir un campo opcional `auth-token`. +2. **Uso del Token Bearer:** El servicio de la herramienta MCP DEBE enviar el encabezado `Authorization: Bearer {token}` cuando se configure un token de autenticación. +3. **Soporte de la CLI:** `tg-set-mcp-tool` DEBE aceptar un parámetro opcional `--auth-token`. +4. **Visualización del Token:** `tg-show-mcp-tools` DEBE indicar cuándo se ha configurado un token de autenticación (enmascarado por motivos de seguridad). +5. **Compatibilidad con versiones anteriores:** Las configuraciones de la herramienta MCP existentes sin un token de autenticación DEBEN seguir funcionando. + +### Requisitos No Funcionales +1. **Compatibilidad con versiones anteriores:** No hay cambios disruptivos para las configuraciones de la herramienta MCP existentes. +2. **Rendimiento:** No hay un impacto significativo en el rendimiento de la invocación de la herramienta MCP. +3. **Seguridad:** Los tokens se almacenan en la configuración (documentar las implicaciones de seguridad). + +### Historias de Usuario + +1. Como **ingeniero de DevOps**, quiero configurar tokens de portador para las herramientas MCP para que pueda asegurar los puntos finales del servidor MCP. +2. Como **usuario de la CLI**, quiero establecer tokens de autenticación al crear herramientas MCP para que pueda conectarme a servidores protegidos. +3. Como **administrador del sistema**, quiero ver qué herramientas MCP tienen la autenticación configurada para que pueda auditar la configuración de seguridad. + +## Diseño + +### Arquitectura de Alto Nivel +Extender la configuración y el servicio de la herramienta MCP para admitir la autenticación con token de portador: +1. Agregar un campo opcional `auth-token` al esquema de configuración de la herramienta MCP. +2. Modificar el servicio de la herramienta MCP para leer el token de autenticación y pasarlo al cliente HTTP. +3. Actualizar las herramientas de la CLI para admitir la configuración y visualización de tokens de autenticación. +4. Documentar las consideraciones de seguridad y las mejores prácticas. + +### Esquema de Configuración + +**Esquema Actual:** +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**Nuevo Esquema** (con token de autenticación opcional): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**Descripciones de campos:** +`remote-name` (opcional): Nombre utilizado por el servidor MCP (por defecto, la clave de configuración). +`url` (obligatorio): URL del punto final del servidor MCP. +`auth-token` (opcional): Token de tipo Bearer para la autenticación. + +### Flujo de datos + +1. **Almacenamiento de la configuración:** El usuario ejecuta `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123`. +2. **Carga de la configuración:** El servicio de la herramienta MCP recibe la actualización de la configuración a través de la devolución de llamada `on_mcp_config()`. +3. **Invocación de la herramienta:** Cuando se invoca la herramienta: + El servicio lee `auth-token` de la configuración (si está presente). + Crea un diccionario de encabezados: `{"Authorization": "Bearer {token}"}`. + Pasa los encabezados a `streamablehttp_client(url, headers=headers)`. + El servidor MCP valida el token y procesa la solicitud. + +### Cambios en la API +No hay cambios en la API externa, solo una extensión del esquema de configuración. + +### Detalles del componente + +#### Componente 1: service.py (Servicio de la herramienta MCP) +**Archivo:** `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**Propósito:** Invocar herramientas MCP en servidores remotos. + +**Cambios requeridos** (en el método `invoke_tool()`): +1. Comprobar si `auth-token` está presente en la configuración `self.mcp_services[name]`. +2. Crear un diccionario de encabezados con el encabezado de autorización si existe un token. +3. Pasar los encabezados a `streamablehttp_client(url, headers=headers)`. + +**Código actual** (líneas 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**Código Modificado**: +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### Componente 2: set_mcp_tool.py (Herramienta de Configuración de Línea de Comandos) +**Archivo**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**Propósito**: Crear/actualizar configuraciones de la herramienta MCP. + +**Cambios Requeridos**: +1. Agregar un argumento opcional `--auth-token` a argparse. +2. Incluir `auth-token` en el archivo JSON de configuración cuando se proporciona. + +**Argumentos Actuales**: +`--id` (requerido): Identificador de la herramienta MCP. +`--remote-name` (opcional): Nombre de la herramienta MCP remota. +`--tool-url` (requerido): Punto final de la URL de la herramienta MCP. +`-u, --api-url` (opcional): URL de la API de TrustGraph. + +**Nuevo Argumento**: +`--auth-token` (opcional): Token Bearer para la autenticación. + +**Construcción de Configuración Modificada**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### Componente 3: show_mcp_tools.py (Herramienta de visualización de línea de comandos) +**Archivo**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**Propósito**: Mostrar configuraciones de la herramienta MCP. + +**Cambios requeridos**: +1. Agregar columna "Auth" a la tabla de salida. +2. Mostrar "Sí" o "No" según la presencia de un token de autenticación. +3. No mostrar el valor real del token (seguridad). + +**Salida actual**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**Nueva Salida**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### Componente 4: Documentación +**Archivo**: `docs/cli/tg-set-mcp-tool.md` + +**Cambios Requeridos**: +1. Documentar el nuevo parámetro `--auth-token` +2. Proporcionar un ejemplo de uso con autenticación +3. Documentar las consideraciones de seguridad + +## Plan de Implementación + +### Fase 1: Crear Especificación Técnica +[x] Escribir una especificación técnica completa que documente todos los cambios + +### Fase 2: Actualizar el Servicio MCP Tool +[ ] Modificar `invoke_tool()` en `service.py` para leer el token de autenticación desde la configuración +[ ] Construir un diccionario de encabezados y pasarlo a `streamablehttp_client` +[ ] Probar con un servidor MCP autenticado + +### Fase 3: Actualizar las Herramientas CLI +[ ] Agregar el argumento `--auth-token` a `set_mcp_tool.py` +[ ] Incluir el token de autenticación en la configuración JSON +[ ] Agregar una columna "Auth" a la salida de `show_mcp_tools.py` +[ ] Probar los cambios de la herramienta CLI + +### Fase 4: Actualizar la Documentación +[ ] Documentar el parámetro `--auth-token` en `tg-set-mcp-tool.md` +[ ] Agregar una sección de consideraciones de seguridad +[ ] Proporcionar un ejemplo de uso + +### Fase 5: Pruebas +[ ] Probar que la herramienta MCP se conecta correctamente con el token de autenticación +[ ] Probar la compatibilidad con versiones anteriores (las herramientas sin token de autenticación aún funcionan) +[ ] Probar que las herramientas CLI aceptan y almacenan correctamente el token de autenticación +[ ] Probar que el comando "show" muestra el estado de la autenticación correctamente + +### Resumen de Cambios en el Código +| Archivo | Tipo de Cambio | Líneas | Descripción | +|------|------------|-------|-------------| +| `service.py` | Modificado | ~52-66 | Agregar la lectura del token de autenticación y la construcción de encabezados | +| `set_mcp_tool.py` | Modificado | ~30-60 | Agregar el argumento --auth-token y el almacenamiento en la configuración | +| `show_mcp_tools.py` | Modificado | ~40-70 | Agregar la columna Auth a la visualización | +| `tg-set-mcp-tool.md` | Modificado | Varios | Documentar el nuevo parámetro | + +## Estrategia de Pruebas + +### Pruebas Unitarias +**Lectura del Token de Autenticación**: Probar que `invoke_tool()` lee correctamente el token de autenticación desde la configuración +**Construcción de Encabezados**: Probar que el encabezado de Autorización se construye correctamente con el prefijo Bearer +**Compatibilidad con Versiones Anteriores**: Probar que las herramientas sin token de autenticación funcionan sin cambios +**Análisis de Argumentos de la CLI**: Probar que el argumento `--auth-token` se analiza correctamente + +### Pruebas de Integración +**Conexión Autenticada**: Probar que el servicio de la herramienta MCP se conecta a un servidor autenticado +**De Extremo a Extremo**: Probar el flujo CLI → almacenamiento de configuración → invocación del servicio con el token de autenticación +**Token No Requerido**: Probar que la conexión a un servidor no autenticado aún funciona + +### Pruebas Manuales +**Servidor MCP Real**: Probar con un servidor MCP real que requiere la autenticación con token Bearer +**Flujo de Trabajo de la CLI**: Probar el flujo de trabajo completo: configurar la herramienta con la autenticación → invocar la herramienta → verificar el éxito +**Enmascaramiento de la Autenticación**: Verificar que el estado de la autenticación se muestra, pero el valor del token no se expone + +## Migración e Implementación + +### Estrategia de Migración +No se requiere migración: esta es una funcionalidad puramente adicional: +Las configuraciones existentes de la herramienta MCP que no tienen `auth-token` siguen funcionando sin cambios +Las nuevas configuraciones pueden incluir opcionalmente el campo `auth-token` +Las herramientas CLI aceptan, pero no requieren, el parámetro `--auth-token` + +### Plan de Implementación +1. **Fase 1**: Implementar los cambios principales del servicio en el entorno de desarrollo/pruebas +2. **Fase 2**: Implementar las actualizaciones de las herramientas CLI +3. **Fase 3**: Actualizar la documentación +4. **Fase 4**: Implementación en producción con monitoreo + +### Plan de Reversión +Los cambios principales son compatibles con versiones anteriores: las herramientas existentes no se ven afectadas +Si surgen problemas, el manejo del token de autenticación se puede deshabilitar eliminando la lógica de construcción de encabezados +Los cambios de la CLI son independientes y se pueden revertir por separado + +## Consideraciones de Seguridad + +### ⚠️ Limitación Crítica: Solo Autenticación de Un Solo Inquilino + +**Este mecanismo de autenticación NO es adecuado para entornos multiusuario o multiinquilino.** + +**Credenciales compartidas**: Todos los usuarios e invocaciones comparten el mismo token por herramienta MCP +**Sin contexto de usuario**: El servidor MCP no puede distinguir entre diferentes usuarios de TrustGraph +**Sin aislamiento de inquilinos**: Todos los inquilinos comparten la misma credencial para cada herramienta MCP +**Limitación del registro de auditoría**: El servidor MCP muestra todas las solicitudes de la misma credencial +**Ámbito de permisos**: No se pueden hacer cumplir diferentes niveles de permiso para diferentes usuarios + +**NO use esta función si:** +Su implementación de TrustGraph sirve a múltiples organizaciones (multiinquilino) +Necesita realizar un seguimiento de qué usuario accedió a qué herramienta MCP +Diferentes usuarios requieren diferentes niveles de permiso +Necesita cumplir con los requisitos de auditoría a nivel de usuario +Su servidor MCP aplica límites de velocidad o cuotas por usuario + +**Soluciones alternativas para escenarios multiusuario/multitenant:** +Implementar la propagación del contexto del usuario a través de encabezados personalizados +Implementar instancias de TrustGraph separadas por tenant +Utilizar aislamiento a nivel de red (VPCs, service meshes) +Implementar una capa de proxy que gestione la autenticación por usuario + +### Almacenamiento de tokens +**Riesgo**: Los tokens de autenticación se almacenan en texto plano en el sistema de configuración + +**Mitigación**: +Documentar que los tokens se almacenan sin cifrar +Recomendar el uso de tokens de corta duración siempre que sea posible +Recomendar un control de acceso adecuado en el almacenamiento de la configuración +Considerar una mejora futura para el almacenamiento de tokens cifrados + +### Exposición de tokens +**Riesgo**: Los tokens podrían exponerse en registros o en la salida de la línea de comandos + +**Mitigación**: +No registrar los valores de los tokens (solo registrar "autenticación configurada: sí/no") +El comando "show" de la línea de comandos muestra solo el estado enmascarado, no el token real +No incluir tokens en los mensajes de error + +### Seguridad de la red +**Riesgo**: Los tokens se transmiten a través de conexiones no cifradas + +**Mitigación**: +Documentar la recomendación de utilizar URL HTTPS para los servidores MCP +Advertir a los usuarios sobre el riesgo de transmisión en texto plano con HTTP + +### Acceso a la configuración +**Riesgo**: El acceso no autorizado al sistema de configuración expone los tokens + +**Mitigación**: +Documentar la importancia de asegurar el acceso al sistema de configuración +Recomendar el principio de mínimo privilegio para el acceso a la configuración +Considerar el registro de auditoría para los cambios de configuración (mejora futura) + +### Entornos multiusuario +**Riesgo**: En las implementaciones multiusuario, todos los usuarios comparten las mismas credenciales de MCP + +**Comprensión del riesgo**: +El usuario A y el usuario B utilizan el mismo token al acceder a una herramienta de MCP +El servidor MCP no puede distinguir entre diferentes usuarios de TrustGraph +No hay forma de aplicar permisos o límites de velocidad por usuario +Los registros de auditoría en el servidor MCP muestran todas las solicitudes del mismo identificador +Si la sesión de un usuario se ve comprometida, el atacante tiene el mismo acceso a MCP que todos los usuarios + +**Esto NO es un error; es una limitación fundamental de este diseño.** + +## Impacto en el rendimiento +**Bajo sobrecosto**: La construcción de encabezados agrega un tiempo de procesamiento insignificante +**Impacto en la red**: El encabezado HTTP adicional agrega ~50-200 bytes por solicitud +**Uso de memoria**: Aumento insignificante para almacenar la cadena de token en la configuración + +## Documentación + +### Documentación para el usuario +[ ] Actualizar `tg-set-mcp-tool.md` con el parámetro `--auth-token` +[ ] Agregar una sección de consideraciones de seguridad +[ ] Proporcionar un ejemplo de uso con un token de tipo "bearer" +[ ] Documentar las implicaciones del almacenamiento de tokens + +### Documentación para el desarrollador +[ ] Agregar comentarios en línea para el manejo de tokens de autenticación en `service.py` +[ ] Documentar la lógica de construcción de encabezados +[ ] Actualizar la documentación del esquema de configuración de la herramienta MCP + +## Preguntas abiertas +1. **Cifrado de tokens**: ¿Debemos implementar el almacenamiento de tokens cifrados en el sistema de configuración? +2. **Actualización de tokens**: ¿Soporte futuro para flujos de actualización de OAuth o rotación de tokens? +3. **Métodos de autenticación alternativos**: ¿Debemos admitir la autenticación básica, las claves API u otros métodos? + +## Alternativas consideradas + +1. **Variables de entorno para tokens**: Almacenar tokens en variables de entorno en lugar de en la configuración + **Rechazada**: Complica la implementación y la gestión de la configuración + +2. **Almacén de secretos separado**: Utilizar un sistema de gestión de secretos dedicado + **Aplazada**: Fuera del alcance de la implementación inicial, considerar una mejora futura + +3. **Múltiples métodos de autenticación**: Admitir Basic, API key, OAuth, etc. + **Rechazada**: Los tokens de tipo "bearer" cubren la mayoría de los casos de uso, mantener la implementación inicial simple + +4. **Almacenamiento de tokens cifrado**: Cifrar los tokens en el sistema de configuración + **Aplazada**: La seguridad del sistema de configuración es una preocupación más amplia, posponer a un trabajo futuro + +5. **Tokens por invocación**: Permitir que los tokens se pasen en el momento de la invocación + **Rechazada**: Viola la separación de responsabilidades, el agente no debe manejar las credenciales + +## Referencias +[Especificación del protocolo MCP](https://github.com/modelcontextprotocol/spec) +[Autenticación Bearer HTTP (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[Servicio de la herramienta MCP actual](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[Especificación de argumentos de la herramienta MCP](./mcp-tool-arguments.md) + +## Apéndice + +### Ejemplo de uso + +**Configuración de la herramienta MCP con autenticación:** +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Mostrando herramientas de MCP:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### Ejemplo de configuración + +**Almacenado en el sistema de configuración**: +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### Mejores prácticas de seguridad + +1. **Utilice HTTPS**: Siempre utilice URL HTTPS para los servidores MCP con autenticación +2. **Tokens de corta duración**: Utilice tokens con fecha de caducidad siempre que sea posible +3. **Privilegios mínimos**: Conceda a los tokens los permisos mínimos requeridos +4. **Control de acceso**: Restrinja el acceso al sistema de configuración +5. **Rotación de tokens**: Rote los tokens regularmente +6. **Registro de auditoría**: Supervise los cambios de configuración para detectar eventos de seguridad diff --git a/docs/tech-specs/mcp-tool-bearer-token.he.md b/docs/tech-specs/mcp-tool-bearer-token.he.md new file mode 100644 index 00000000..4cedf327 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.he.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "מפרט אימות טוקן עבור כלי MCP" +parent: "Hebrew (Beta)" +--- + +# מפרט אימות טוקן עבור כלי MCP + +> **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. + +> **⚠️ חשוב: רק עבור סביבות עם משתמש יחיד** +> +> מפרט זה מתאר מנגנון אימות בסיסי ברמת השירות עבור כלי MCP. זה **אינו** פתרון אימות שלם ו**אינו מתאים** עבור: +> - סביבות מרובות משתמשים +> - פריסות מרובות דיירים +> - אימות פדרטיבי +> - העברת הקשר משתמש +> - הרשאה ברמת המשתמש +> +> תכונה זו מספקת **טוקן סטטי אחד לכל כלי MCP**, המשותף לכל המשתמשים והסשנים. אם אתם זקוקים לאימות ברמת המשתמש או הדייר, זו אינה הפתרון הנכון. + +## סקירה כללית +**שם התכונה**: תמיכה באימות טוקן עבור כלי MCP +**כותב**: Claude Code Assistant +**תאריך**: 2025-11-11 +**סטטוס**: בפיתוח + +### תקציר + +אפשר תצורות של כלי MCP לציין טוקנים סטטיים אופציונליים לאימות עם שרתי MCP מוגנים. זה מאפשר ל-TrustGraph להפעיל כלי MCP המאוחסנים בשרתים הדורשים אימות, מבלי לשנות את סוכן או ממשקי הפעלה של הכלי. + +**חשוב**: זוהי מנגנון אימות בסיסי המיועדת לתסריטי אימות בין שירותים בסביבות עם משתמש יחיד. זה **אינו** מתאים עבור: +סביבות מרובות משתמשים שבהן משתמשים שונים צריכים אישורים שונים +פריסות מרובות דיירים הדורשות בידוד לדייר +תרחישי אימות פדרטיביים +אימות או הרשאה ברמת המשתמש +ניהול או רענון אישורים דינמיים + +תכונה זו מספקת טוקן סטטי, ברמת המערכת, עבור כל תצורת כלי MCP, המשותף לכל המשתמשים וההפעלה של כלי זה. + +### הצגת הבעיה + +כיום, כלי MCP יכולים להתחבר רק לשרתי MCP נגישים לציבור. פריסות MCP רבות בייצור דורשות אימות באמצעות טוקנים עבור אבטחה. ללא תמיכה באימות: +כלי MCP לא יכולים להתחבר לשרתי MCP מאובטחים +משתמשים חייבים או לחשוף שרתי MCP לציבור או ליישם שרתי הפוך +אין דרך סטנדרטית להעביר אישורים לחיבורי MCP +לא ניתן לאכוף שיטות עבודה מומלצות לאבטחה בקצוות MCP + +### מטרות + +[ ] לאפשר לתצורות של כלי MCP לציין פרמטר אופציונלי `auth-token` +[ ] לעדכן את שירות כלי MCP כדי להשתמש בטוקנים בעת חיבור לשרתי MCP +[ ] לעדכן כלים בשורת הפקודה לתמיכה בהגדרת/הצגת טוקני אימות +[ ] לשמור על תאימות לאחור עם תצורות MCP ללא אימות +[ ] לתעד שיקולים אבטחתיים עבור אחסון טוקנים + +### לא מטרות +רענון טוקנים דינמי או זרימות OAuth (רק טוקנים סטטיים) +הצפנה של טוקנים המאוחסנים (אבטחת מערכת התצורה אינה בתחום) +שיטות אימות חלופיות (אימות בסיסי, מפתחות API, וכו') +אימות או בדיקת תפוגה של טוקנים +**אימות ברמת המשתמש**: תכונה זו **אינה** תומכת באישורים ספציפיים למשתמש +**בידוד מרובה דיירים**: תכונה זו **אינה** מספקת ניהול טוקנים ברמת הדייר +**אימות פדרטיבי**: תכונה זו **אינה** משתלבת עם ספקי זהות (SSO, OAuth, SAML, וכו') +**אימות מודע הקשר**: טוקנים אינם מועברים בהתבסס על הקשר משתמש או סשן + +## רקע והקשר + +### מצב נוכחי +תצורות של כלי MCP מאוחסנות בקבוצת התצורה `mcp` עם המבנה הבא: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +שירות הכלי MCP מתחבר לשרתים באמצעות `streamablehttp_client(url)` ללא כותרות אימות. + +### מגבלות + +**מגבלות מערכת נוכחיות:** +1. **ללא תמיכה באימות:** לא ניתן להתחבר לשרתי MCP מאובטחים. +2. **חשיפה אבטחתיות:** שרתי MCP חייבים להיות נגישים לציבור או להשתמש באבטחה ברמת הרשת בלבד. +3. **בעיות פריסה בסביבת ייצור:** לא ניתן לעקוב אחר שיטות עבודה מומלצות לאבטחת נקודות קצה של API. + +**מגבלות של פתרון זה:** +1. **מתאים רק למערכת משתמש יחיד:** טוקן סטטי אחד לכל כלי MCP, משותף לכל המשתמשים. +2. **ללא אישורים מבוססי משתמש:** לא ניתן לאמת כמשתמשים שונים או להעביר הקשר משתמש. +3. **ללא תמיכה בריבוי משתמשים:** לא ניתן לבודד אישורים לפי משתמש או ארגון. +4. **טוקנים סטטיים בלבד:** ללא תמיכה בחידוש טוקנים, רוטציה או טיפול בתפוגה. +5. **אימות ברמת השירות:** מאמת את שירות TrustGraph, ולא משתמשים בודדים. +6. **הקשר אבטחה משותף:** כל שימוש בכלי MCP משתמש באותו אישור. + +### התאמת מקרי שימוש + +**✅ מקרי שימוש מתאימים:** +פריסות TrustGraph עם משתמש יחיד. +אימות בין שירותים (TrustGraph → שרת MCP). +סביבות פיתוח ובדיקה. +כלי MCP פנימיים שאליהם ניגש מערכת TrustGraph. +תרחישים שבהם כל המשתמשים חולקים את אותו רמת גישה לכלי MCP. +אישורים שירותיים סטטיים, בעלי אורך חיים ארוך. + +**❌ מקרי שימוש לא מתאימים:** +מערכות מרובות משתמשים הדורשות אימות מבוסס משתמש. +פריסות SaaS מרובות משתמשים עם דרישות בידוד משתמשים. +תרחישי אימות מאוחדים (SSO, OAuth, SAML). +מערכות הדורשות העברת הקשר משתמש לשרתי MCP. +סביבות הזקוקות לחידוש טוקנים דינמי או טוקנים בעלי אורך חיים קצר. +יישומים שבהם משתמשים שונים צריכים רמות הרשאות שונות. +דרישות תאימות לרישומי ביקורת ברמת המשתמש. + +**תרחיש מתאים לדוגמה:** +פריסה של TrustGraph עבור ארגון יחיד שבהם כל העובדים משתמשים באותו כלי MCP פנימי (לדוגמה, שאילתת מסד נתונים של החברה). שרת ה-MCP דורש אימות כדי למנוע גישה חיצונית, אך לכל המשתמשים הפנימיים יש את אותו רמת גישה. + +**תרחיש לא מתאים לדוגמה:** +פלטפורמת SaaS מרובת משתמשים של TrustGraph שבה כל אחד מ-Tenant A ו-Tenant B צריך לגשת לשרתי MCP מבודדים משלהם עם אישורים נפרדים. תכונה זו אינה תומכת בניהול טוקנים ברמת ה-Tenant. + +### רכיבים קשורים +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: שירות הפעלת כלי MCP. +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: כלי שורת פקודה ליצירת/עדכון תצורות MCP. +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: כלי שורת פקודה להצגת תצורות MCP. +**MCP Python SDK**: `streamablehttp_client` מ- `mcp.client.streamable_http` + +## דרישות + +### דרישות פונקציונליות + +1. **טוקן אימות לתצורה של MCP:** תצורות כלי MCP חייבות לתמוך בשדה אופציונלי `auth-token`. +2. **שימוש בטוקן Bearer:** שירות כלי MCP חייב לשלוח כותרת `Authorization: Bearer {token}` כאשר טוקן אימות מוגדר. +3. **תמיכה בשורת הפקודה:** `tg-set-mcp-tool` חייב לקבל פרמטר אופציונלי `--auth-token`. +4. **הצגת טוקן:** `tg-show-mcp-tools` חייב לציין מתי טוקן אימות מוגדר (מוסתר מטעמי אבטחה). +5. **תאימות לאחור:** תצורות כלי MCP קיימות ללא טוקן אימות חייבות להמשיך לעבוד. + +### דרישות לא פונקציונליות +1. **תאימות לאחור:** ללא שינויים משמעותיים עבור תצורות כלי MCP קיימות. +2. **ביצועים:** ללא השפעה משמעותית על ביצועי הפעלת כלי MCP. +3. **אבטחה:** טוקנים המאוחסנים בתצורה (יש להבין את השלכות האבטחה). + +### סיפורי משתמש + +1. כ-**מהנדס DevOps**, אני רוצה להגדיר טוקני Bearer עבור כלי MCP כך שאוכל לאבטח נקודות קצה של שרתי MCP. +2. כ-**משתמש שורת פקודה**, אני רוצה להגדיר טוקני אימות בעת יצירת כלי MCP כך שאוכל להתחבר לשרתים מוגנים. +3. כ-**מנהל מערכת**, אני רוצה לראות אילו כלי MCP מוגדרים עם אימות כך שאוכל לבדוק הגדרות אבטחה. + +## עיצוב + +### ארכיטקטורה ברמה גבוהה +הרחבת תצורת כלי MCP ושירות כדי לתמוך באימות טוקן Bearer: +1. הוספת שדה אופציונלי `auth-token` לתבנית תצורה של כלי MCP. +2. שנה את שירות הכלי MCP כדי לקרוא את הטוקן האימות ולהעביר אותו ללקוח HTTP. +3. עדכן את כלי שורת הפקודה (CLI) כדי לתמוך בהגדרת והצגת טוקני אימות. +4. תעד שיקולי אבטחה ושיטות עבודה מומלצות. + +### סכימת תצורה + +**הסכימה הנוכחית**: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**סכימה חדשה** (עם טוקן אימות אופציונלי): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**תיאורי שדות**: +`remote-name` (אופציונלי): שם המשמש את שרת ה-MCP (ברירת מחדל היא מפתח התצורה) +`url` (חובה): כתובת URL של נקודת הקצה של שרת ה-MCP +`auth-token` (אופציונלי): טוקן Bearer לאימות + +### זרימת נתונים + +1. **אחסון תצורה**: המשתמש מריץ את `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123` +2. **טעינת תצורה**: שירות הכלי ה-MCP מקבל עדכון תצורה באמצעות קריאה חוזרת (callback) של `on_mcp_config()` +3. **הפעלת כלי**: כאשר הכלי מופעל: + השירות קורא את `auth-token` מהתצורה (אם קיים) + יוצר מילון כותרות: `{"Authorization": "Bearer {token}"}` + מעביר את הכותרות ל-`streamablehttp_client(url, headers=headers)` + שרת ה-MCP מאמת את הטוקן ומעבד את הבקשה + +### שינויי API +אין שינויי API חיצוניים - רק הרחבת סכימת התצורה. + +### פרטי רכיב + +#### רכיב 1: service.py (שירות כלי MCP) +**קובץ**: `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**מטרה**: הפעלת כלי MCP על שרתים מרוחקים + +**שינויים נדרשים** (בשיטה `invoke_tool()`): +1. בדוק אם קיים `auth-token` בתצורת `self.mcp_services[name]` +2. בנה מילון כותרות עם כותרת Authorization אם קיים טוקן +3. העבר את הכותרות ל-`streamablehttp_client(url, headers=headers)` + +**קוד נוכחי** (שורות 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**קוד שעבר שינוי:** +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### רכיב 2: set_mcp_tool.py (כלי תצורה דרך שורת הפקודה) +**קובץ**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**מטרה**: יצירת/עדכון תצורות לכלי MCP + +**שינויים נדרשים**: +1. הוספת ארגומנט אופציונלי `--auth-token` ל-argparse +2. הכללת `auth-token` בקובץ JSON של התצורה כאשר הוא מסופק + +**ארגומנטים נוכחיים**: +`--id` (חובה): מזהה של כלי MCP +`--remote-name` (אופציונלי): שם של כלי MCP מרוחק +`--tool-url` (חובה): נקודת קצה של כתובת URL של כלי MCP +`-u, --api-url` (אופציונלי): כתובת URL של ממשק API של TrustGraph + +**ארגומנט חדש**: +`--auth-token` (אופציונלי): טוקן bearer לאימות + +**שינוי בבניית התצורה**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### רכיב 3: show_mcp_tools.py (כלי תצוגה בשורת הפקודה) +**קובץ**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**מטרה**: הצגת תצורות של כלי MCP + +**שינויים נדרשים**: +1. הוספת עמודה "אימות" (Auth) לטבלת הפלט +2. הצגת "כן" או "לא" בהתאם לנוכחות של טוקן אימות +3. אין להציג את ערך הטוקן בפועל (אבטחה) + +**פלט נוכחי**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**פלט חדש**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### רכיב 4: תיעוד +**קובץ**: `docs/cli/tg-set-mcp-tool.md` + +**שינויים נדרשים**: +1. לתעד את הפרמטר החדש `--auth-token` +2. לספק דוגמה לשימוש עם אימות +3. לתעד שיקולי אבטחה + +## תוכנית יישום + +### שלב 1: יצירת מפרט טכני +[x] לכתוב מפרט טכני מקיף המתעד את כל השינויים + +### שלב 2: עדכון שירות כלי MCP +[ ] לשנות את `invoke_tool()` ב-`service.py` כדי לקרוא את auth-token מקובץ התצורה +[ ] לבנות מילון כותרות ולהעביר ל-`streamablehttp_client` +[ ] לבדוק עם שרת MCP מאומת + +### שלב 3: עדכון כלי שורת הפקודה +[ ] להוסיף את הארגומנט `--auth-token` ל-`set_mcp_tool.py` +[ ] לכלול את auth-token בקובץ JSON של התצורה +[ ] להוסיף עמודה "אימות" לפלט של `show_mcp_tools.py` +[ ] לבדוק את השינויים בכלי שורת הפקודה + +### שלב 4: עדכון תיעוד +[ ] לתעד את הפרמטר `--auth-token` ב-`tg-set-mcp-tool.md` +[ ] להוסיף סעיף של שיקולי אבטחה +[ ] לספק דוגמה לשימוש + +### שלב 5: בדיקות +[ ] לבדוק שכלי ה-MCP מתחבר בהצלחה עם auth-token +[ ] לבדוק תאימות לאחור (כלים ללא auth-token עדיין עובדים) +[ ] לבדוק שכלי שורת הפקודה מקבלים ושומרים את auth-token כראוי +[ ] לבדוק שפקודת ה-show מציגה את סטטוס האימות כראוי + +### סיכום שינויים בקוד +| קובץ | סוג שינוי | שורות | תיאור | +|------|------------|-------|-------------| +| `service.py` | שינוי | ~52-66 | הוספת קריאת auth-token ובניית כותרות | +| `set_mcp_tool.py` | שינוי | ~30-60 | הוספת ארגומנט --auth-token ואחסון בתצורה | +| `show_mcp_tools.py` | שינוי | ~40-70 | הוספת עמודה "אימות" לתצוגה | +| `tg-set-mcp-tool.md` | שינוי | שונות | תיעוד פרמטר חדש | + +## אסטרטגיית בדיקות + +### בדיקות יחידה +**קריאת סיסמת אימות**: לבדוק ש-`invoke_tool()` קורא כראוי את סיסמת האימות מקובץ התצורה +**בניית כותרות**: לבדוק שכותרת ה-Authorization נבנית כראוי עם הקידומת Bearer +**תאימות לאחור**: לבדוק שכלי ללא סיסמת אימות עובדים ללא שינוי +**ניתוח ארגומנטים בשורת הפקודה**: לבדוק שהארגומנט `--auth-token` מנותח כראוי + +### בדיקות אינטגרציה +**חיבור מאומת**: בדיקת חיבור שירות כלי MCP לשרת מאומת +**מקיף (End-to-End)**: בדיקת CLI → אחסון תצורה → הפעלת שירות עם טוקן אימות +**טוקן לא נדרש**: בדיקת חיבור לשרת לא מאומת עדיין עובד + +### בדיקות ידניות +**שרת MCP אמיתי**: בדיקה עם שרת MCP אמיתי הדורש אימות באמצעות טוקן +**זרימת עבודה של CLI**: בדיקת זרימת עבודה מלאה: הגדרת כלי עם אימות → הפעלת כלי → אימות הצלחה +**הסתרת תצוגה**: ודאו שמצב האימות מוצג אך ערך הטוקן אינו נחשף + +## מעבר ושילוב + +### אסטרטגיית מעבר +אין צורך במעבר - זו פונקציונליות נוספת בלבד: +תצורות כלי MCP קיימות ללא `auth-token` ממשיכות לעבוד ללא שינוי +ניתן לכלול את השדה `auth-token` בתצורות חדשות, אופציונלית +כלי CLI מקבלים אך אינם דורשים את הפרמטר `--auth-token` + +### תוכנית שילוב +1. **שלב 1**: פריסת שינויים בסיסיים בשירות לסביבות פיתוח/בדיקות +2. **שלב 2**: פריסת עדכוני כלי CLI +3. **שלב 3**: עדכון תיעוד +4. **שלב 4**: שילוב בסביבת ייצור עם ניטור + +### תוכנית חזרה אחורה +השינויים הבסיסיים תואמים לאחור - כלים קיימים אינם מושפעים +אם מתעוררות בעיות, ניתן להשבית את הטיפול בטוקן אימות על ידי הסרת הלוגיקה לבניית כותרות +שינויים ב-CLI הם עצמאיים וניתן לבטל אותם בנפרד + +## שיקולי אבטחה + +### ⚠️ מגבלה קריטית: אימות רק עבור לקוח יחיד + +**מנגנון אימות זה אינו מתאים לסביבות מרובות משתמשים או מרובות לקוחות.** + +**אישורים משותפים**: כל המשתמשים וההפעלה חולקים את אותו טוקן עבור כל כלי MCP +**ללא הקשר משתמש**: שרת ה-MCP אינו יכול להבחין בין משתמשי TrustGraph שונים +**ללא בידוד לקוחות**: כל הלקוחות חולקים את אותו אישור עבור כל כלי MCP +**מגבלת מעקב**: שרת ה-MCP רושם את כל הבקשות מאותו אישור +**היקף הרשאות**: לא ניתן לאכוף רמות הרשאות שונות עבור משתמשים שונים + +**אל תשתמשו בתכונה זו אם:** +הפריסה של TrustGraph שלכם משרתת מספר ארגונים (מרובת לקוחות) +אתם צריכים לעקוב אילו משתמשים גשו לאילו כלי MCP +משתמשים שונים דורשים רמות הרשאות שונות +אתם צריכים לעמוד בדרישות מעקב ברמת המשתמש +שרת ה-MCP שלכם מאכף מגבלות קצב או מכסות ברמת המשתמש + +**פתרונות חלופיים עבור תרחישי משתמשים/לקוחות מרובים:** +הטמעת העברת הקשר משתמש באמצעות כותרות מותאמות אישית +פריסת מופעי TrustGraph נפרדים עבור כל לקוח +שימוש בבידוד ברמת הרשת (VPCs, רשתות שירות) +הטמעת שכבת פרוקסי המטפלת באימות מבוסס משתמש + +### אחסון טוקנים +**סיכון**: טוקנים של אימות מאוחסנים בטקסט רגיל במערכת התצורה + +**הפחתה**: +תיעוד העובדה שטוקנים מאוחסנים ללא הצפנה +המלצה על שימוש בטוקנים קצרי טווח במידת האפשר +המלצה על בקרת גישה מתאימה לאחסון התצורה +שקילת שיפור עתידי לאחסון מוצפן של טוקנים + +### חשיפת טוקנים +**סיכון**: טוקנים עלולים להיחשף ביומני רישום או בפלט של שורת הפקודה + +**הפחתה**: +אין לרשום ערכי טוקנים (לרשום רק "אימות מוגדר: כן/לא") +פקודת ה-CLI להצגה מציגה סטטוס מוסתר בלבד, ולא את הטוקן בפועל +אין לכלול טוקנים בהודעות שגיאה + +### אבטחת רשת +**סיכון**: טוקנים מועברים על גבי חיבורים לא מוצפנים + +**הפחתה**: +המלצה לשימוש בכתובות URL של HTTPS עבור שרתי MCP +אזהרת משתמשים לגבי סיכון השידור בטקסט רגיל עם HTTP + +### גישה לתצורה +**סיכון**: גישה לא מורשית למערכת התצורה חושפת טוקנים + +**הפחתה**: +תיעוד החשיבות של אבטחת גישה למערכת התצורה +המלצה על עקרון ההרשאה המינימלית לגישה לתצורה +שקילת רישום ביקורת עבור שינויים בתצורה (שיפור עתידי) + +### סביבות מרובות משתמשים +**סיכון**: בסביבות מרובות משתמשים, כל המשתמשים חולקים את אותם פרטי כניסה של MCP + +**הבנת הסיכון**: +משתמש א' ומשתמש ב' משתמשים באותו טוקן בעת גישה לכלי MCP +שרת ה-MCP אינו יכול להבחין בין משתמשי TrustGraph שונים +אין דרך לאכוף הרשאות או מגבלות קצב מבוססות משתמש +יומני רישום בשרת ה-MCP מציגים את כל הבקשות מאותה פרטי כניסה +אם הסשן של משתמש אחד נפגע, לתוקף יש את אותה גישה ל-MCP כמו לכל המשתמשים + +**זהו לא באג - זהו מגבלה יסודית של עיצוב זה.** + +## השפעה על ביצועים +**תקורה מינימלית**: בניית כותרת מוסיפה זמן עיבוד זניח +**השפעה על הרשת**: כותרת HTTP נוספת מוסיפה ~50-200 בתים לכל בקשה +**שימוש בזיכרון**: עלייה זניחה עבור אחסון מחרוזת הטוקן בתצורה + +## תיעוד + +### תיעוד למשתמש +[ ] עדכון `tg-set-mcp-tool.md` עם פרמטר `--auth-token` +[ ] הוספת סעיף שיקולי אבטחה +[ ] מתן דוגמה לשימוש עם טוקן bearer +[ ] תיעוד השלכות אחסון טוקנים + +### תיעוד למפתחים +[ ] הוספת הערות שורה לטיפול בטוקן אימות ב-`service.py` +[ ] תיעוד לוגיקת בניית כותרות +[ ] עדכון תיעוד סכימת התצורה של כלי MCP + +## שאלות פתוחות +1. **הצפנת טוקנים**: האם עלינו ליישם אחסון מוצפן של טוקנים במערכת התצורה? +2. **רענון טוקנים**: תמיכה עתידית בזרמי רענון OAuth או סיבוב טוקנים? +3. **שיטות אימות חלופיות**: האם עלינו לתמוך באימות בסיסי, מפתחות API או שיטות אחרות? + +## חלופות שנשקלו + +1. **משתני סביבה עבור טוקנים**: אחסון טוקנים במשתני סביבה במקום בתצורה + **נדחה**: מסבך פריסה וניהול תצורה + +2. **מאגר סודות נפרד**: שימוש במערכת ניהול סודות ייעודית + **נדחה**: מחוץ להיקף היישום הראשוני, לשקול שיפור עתידי + +3. **שיטות אימות מרובות**: תמיכה בסיסי, מפתח API, OAuth וכו'. + **נדחה**: טוקני bearer מכסים את רוב מקרי השימוש, לשמור על יישום ראשוני פשוט + +4. **אחסון מוצפן של טוקנים**: הצפנת טוקנים במערכת התצורה + **נדחה**: אבטחת מערכת התצורה היא דאגה רחבה יותר, לדחות לעבודה עתידית + +5. **טוקנים לכל קריאה**: לאפשר העברת טוקנים בזמן ההפעלה + **נדחה**: מפר את הפרדת האחריות, סוכן לא צריך לטפל באישורים + +## הפניות +[מפרט פרוטוקול MCP](https://github.com/modelcontextprotocol/spec) +[אימות Bearer HTTP (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[כלי שירות MCP נוכחי](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[מפרט ארגומנטים של כלי MCP](./mcp-tool-arguments.md) + +## נספח + +### שימוש לדוגמה +פלט חוזה (יש לעקוב בדיוק אחר הפורמט הבא). +**הגדרת כלי MCP עם אימות:** +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**הצגת כלי MCP:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### דוגמה לתצורה + +**מאוחסן במערכת התצורה:** +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### שיטות עבודה מומלצות לאבטחה + +1. **שימוש ב-HTTPS**: השתמשו תמיד בכתובות HTTPS עבור שרתי MCP עם אימות. +2. **אסימונים קצרי טווח**: השתמשו באסימונים עם תאריך תפוגה כאשר אפשר. +3. **הרשאות מינימליות**: העניקו לאסימונים את ההרשאות המינימליות הנדרשות. +4. **בקרת גישה**: הגבילו את הגישה למערכת התצורה. +5. **החלפת אסימונים**: החליפו אסימונים באופן קבוע. +6. **רישום ביקורת**: עקבו אחר שינויים בתצורה לאירועי אבטחה. diff --git a/docs/tech-specs/mcp-tool-bearer-token.hi.md b/docs/tech-specs/mcp-tool-bearer-token.hi.md new file mode 100644 index 00000000..698835c4 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.hi.md @@ -0,0 +1,562 @@ +--- +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-11-11 +**स्थिति**: विकास के अधीन + +### कार्यकारी सारांश + +एमसीपी टूल कॉन्फ़िगरेशन को सुरक्षित एमसीपी सर्वरों के साथ प्रमाणीकरण के लिए वैकल्पिक बेयरर टोकन निर्दिष्ट करने की अनुमति दें। यह ट्रस्टग्राफ को उन सर्वरों पर होस्ट किए गए एमसीपी टूल को सुरक्षित रूप से आमंत्रित करने की अनुमति देता है जिनके लिए प्रमाणीकरण की आवश्यकता होती है, एजेंट या टूल इनवोकेशन इंटरफेस को संशोधित किए बिना। + +**महत्वपूर्ण**: यह एक बुनियादी प्रमाणीकरण तंत्र है जिसे सिंगल-टेनेन्ट, सेवा-से-सेवा प्रमाणीकरण परिदृश्यों के लिए डिज़ाइन किया गया है। यह निम्नलिखित के लिए **उपयुक्त नहीं** है: +मल्टी-यूजर वातावरण जहां विभिन्न उपयोगकर्ताओं को अलग-अलग क्रेडेंशियल की आवश्यकता होती है +मल्टी-टेनेन्ट परिनियोजन जिसके लिए प्रति-टेनेन्ट अलगाव की आवश्यकता होती है +फेडरेटेड प्रमाणीकरण परिदृश्य +यूजर-स्तरीय प्रमाणीकरण या प्राधिकरण +गतिशील क्रेडेंशियल प्रबंधन या टोकन रीफ़्रेश + +यह सुविधा प्रत्येक एमसीपी टूल कॉन्फ़िगरेशन के लिए एक स्थिर, सिस्टम-व्यापी बेयरर टोकन प्रदान करती है, जो उस टूल के सभी उपयोगकर्ताओं और इनवोकेशन में साझा किया जाता है। + +### समस्या विवरण + +वर्तमान में, एमसीपी टूल केवल सार्वजनिक रूप से सुलभ एमसीपी सर्वरों से जुड़ सकते हैं। कई उत्पादन एमसीपी परिनियोजन सुरक्षा के लिए बेयरर टोकन के माध्यम से प्रमाणीकरण की आवश्यकता होती है। प्रमाणीकरण समर्थन के बिना: +एमसीपी टूल सुरक्षित एमसीपी सर्वरों से कनेक्ट नहीं हो सकते +उपयोगकर्ताओं को या तो एमसीपी सर्वरों को सार्वजनिक रूप से उजागर करना होगा या रिवर्स प्रॉक्सी लागू करना होगा +एमसीपी कनेक्शनों को क्रेडेंशियल पास करने का कोई मानकीकृत तरीका नहीं है +एमसीपी एंडपॉइंट पर सुरक्षा सर्वोत्तम प्रथाओं को लागू नहीं किया जा सकता है + +### लक्ष्य + +[ ] एमसीपी टूल कॉन्फ़िगरेशन को वैकल्पिक `auth-token` पैरामीटर निर्दिष्ट करने की अनुमति दें +[ ] एमसीपी टूल सेवा को एमसीपी सर्वरों से कनेक्ट करते समय बेयरर टोकन का उपयोग करने के लिए अपडेट करें +[ ] CLI टूल को ऑथ टोकन सेट/डिस्प्ले करने के लिए अपडेट करें +[ ] अप्रामाणित एमसीपी कॉन्फ़िगरेशन के साथ बैकवर्ड संगतता बनाए रखें +[ ] टोकन स्टोरेज के लिए सुरक्षा विचारों का दस्तावेजीकरण करें + +### गैर-लक्ष्य +गतिशील टोकन रीफ़्रेश या OAuth प्रवाह (केवल स्थिर टोकन) +संग्रहीत टोकन का एन्क्रिप्शन (कॉन्फ़िगरेशन सिस्टम सुरक्षा दायरे से बाहर है) +वैकल्पिक प्रमाणीकरण विधियाँ (बेसिक ऑथ, एपीआई कुंजियाँ, आदि) +टोकन सत्यापन या समाप्ति जांच +**प्रति-उपयोगकर्ता प्रमाणीकरण**: यह सुविधा उपयोगकर्ता-विशिष्ट क्रेडेंशियल का समर्थन नहीं करती है +**मल्टी-टेनेन्ट अलगाव**: यह सुविधा प्रति-टेनेन्ट टोकन प्रबंधन प्रदान नहीं करती है +**फेडरेटेड प्रमाणीकरण**: यह सुविधा पहचान प्रदाताओं (एसएसओ, OAuth, SAML, आदि) के साथ एकीकृत नहीं होती है +**संदर्भ-जागरूक प्रमाणीकरण**: टोकन उपयोगकर्ता संदर्भ या सत्र के आधार पर पास नहीं किए जाते हैं + +## पृष्ठभूमि और संदर्भ + +### वर्तमान स्थिति +एमसीपी टूल कॉन्फ़िगरेशन `mcp` कॉन्फ़िगरेशन समूह में इस संरचना के साथ संग्रहीत हैं: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +MCP टूल सेवा `streamablehttp_client(url)` का उपयोग करके सर्वरों से कनेक्ट होती है, बिना किसी प्रमाणीकरण हेडर के। + +### सीमाएँ + +**वर्तमान सिस्टम सीमाएँ:** +1. **कोई प्रमाणीकरण समर्थन नहीं:** सुरक्षित MCP सर्वरों से कनेक्ट नहीं किया जा सकता। +2. **सुरक्षा जोखिम:** MCP सर्वर सार्वजनिक रूप से सुलभ होने चाहिए या केवल नेटवर्क-स्तरीय सुरक्षा का उपयोग करना चाहिए। +3. **उत्पादन परिनियोजन मुद्दे:** API एंडपॉइंट्स के लिए सुरक्षा सर्वोत्तम प्रथाओं का पालन नहीं किया जा सकता। + +**इस समाधान की सीमाएँ:** +1. **केवल सिंगल-टेनेन्ट:** प्रत्येक MCP टूल के लिए एक स्थिर टोकन, सभी उपयोगकर्ताओं में साझा। +2. **प्रति-उपयोगकर्ता क्रेडेंशियल्स नहीं:** विभिन्न उपयोगकर्ताओं के रूप में प्रमाणीकरण नहीं किया जा सकता या उपयोगकर्ता संदर्भ नहीं भेजा जा सकता। +3. **कोई मल्टी-टेनेन्ट समर्थन नहीं:** क्रेडेंशियल्स को टेनेन्ट या संगठन द्वारा अलग नहीं किया जा सकता। +4. **केवल स्थिर टोकन:** टोकन रीफ़्रेश, रोटेशन या समाप्ति प्रबंधन का कोई समर्थन नहीं। +5. **सेवा-स्तरीय प्रमाणीकरण:** ट्रस्टग्राफ सेवा को प्रमाणित करता है, व्यक्तिगत उपयोगकर्ताओं को नहीं। +6. **साझा सुरक्षा संदर्भ:** MCP टूल के सभी आह्वान एक ही क्रेडेंशियल का उपयोग करते हैं। + +### उपयोग मामला प्रयोज्यता + +**✅ उपयुक्त उपयोग मामले:** +सिंगल-टेनेन्ट ट्रस्टग्राफ परिनियोजन। +सेवा-से-सेवा प्रमाणीकरण (ट्रस्टग्राफ → MCP सर्वर)। +विकास और परीक्षण वातावरण। +ट्रस्टग्राफ सिस्टम द्वारा एक्सेस किए जाने वाले आंतरिक MCP टूल। +ऐसे परिदृश्य जहां सभी उपयोगकर्ताओं के पास MCP टूल तक समान पहुंच स्तर हो। +स्थिर, लंबे समय तक चलने वाले सेवा क्रेडेंशियल्स। + +**❌ अनुपयुक्त उपयोग मामले:** +प्रति-उपयोगकर्ता प्रमाणीकरण की आवश्यकता वाले मल्टी-यूजर सिस्टम। +टेनेन्ट अलगाव आवश्यकताओं वाले मल्टी-टेनेन्ट SaaS परिनियोजन। +फेडरेटेड प्रमाणीकरण परिदृश्य (SSO, OAuth, SAML)। +ऐसे सिस्टम जिनके लिए MCP सर्वरों पर उपयोगकर्ता संदर्भ का प्रसार आवश्यक है। +ऐसे वातावरण जिन्हें गतिशील टोकन रीफ़्रेश या अल्पकालिक टोकन की आवश्यकता होती है। +ऐसे एप्लिकेशन जहां विभिन्न उपयोगकर्ताओं को अलग-अलग अनुमति स्तरों की आवश्यकता होती है। +उपयोगकर्ता-स्तरीय ऑडिट ट्रेल्स के लिए अनुपालन आवश्यकताएं। + +**उदाहरण उपयुक्त परिदृश्य:** +एक सिंगल-संगठन ट्रस्टग्राफ परिनियोजन जहां सभी कर्मचारी एक ही आंतरिक MCP टूल का उपयोग करते हैं (उदाहरण के लिए, कंपनी डेटाबेस लुकअप)। MCP सर्वर को बाहरी पहुंच को रोकने के लिए प्रमाणीकरण की आवश्यकता होती है, लेकिन सभी आंतरिक उपयोगकर्ताओं के पास समान पहुंच स्तर होता है। + +**उदाहरण अनुपयुक्त परिदृश्य:** +एक मल्टी-टेनेन्ट ट्रस्टग्राफ SaaS प्लेटफ़ॉर्म जहां टेनेन्ट A और टेनेन्ट B को अलग-अलग क्रेडेंशियल्स के साथ अपने स्वयं के अलग-अलग MCP सर्वरों तक पहुंचने की आवश्यकता होती है। यह सुविधा प्रति-टेनेन्ट टोकन प्रबंधन का समर्थन नहीं करती है। + +### संबंधित घटक +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: MCP टूल इनवोकेशन सेवा। +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: MCP कॉन्फ़िगरेशन बनाने/अपडेट करने के लिए CLI टूल। +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: MCP कॉन्फ़िगरेशन प्रदर्शित करने के लिए CLI टूल। +**MCP Python SDK**: `streamablehttp_client` from `mcp.client.streamable_http` + +## आवश्यकताएँ + +### कार्यात्मक आवश्यकताएँ + +1. **MCP कॉन्फ़िगरेशन ऑथ टोकन:** MCP टूल कॉन्फ़िगरेशन को एक वैकल्पिक `auth-token` फ़ील्ड का समर्थन करना चाहिए। +2. **बियरर टोकन उपयोग:** MCP टूल सेवा को `Authorization: Bearer {token}` हेडर भेजना चाहिए जब ऑथ-टोकन कॉन्फ़िगर किया गया हो। +3. **CLI समर्थन:** `tg-set-mcp-tool` को एक वैकल्पिक `--auth-token` पैरामीटर स्वीकार करना चाहिए। +4. **टोकन प्रदर्शन:** `tg-show-mcp-tools` को यह इंगित करना चाहिए कि ऑथ-टोकन कॉन्फ़िगर किया गया है (सुरक्षा के लिए मास्क किया गया)। +5. **पिछला अनुकूलता:** ऑथ-टोकन के बिना मौजूदा MCP टूल कॉन्फ़िगरेशन को काम करना जारी रखना चाहिए। + +### गैर-कार्यात्मक आवश्यकताएँ +1. **पिछला अनुकूलता:** मौजूदा MCP टूल कॉन्फ़िगरेशन के लिए कोई ब्रेकिंग परिवर्तन नहीं। +2. **प्रदर्शन:** MCP टूल इनवोकेशन पर कोई महत्वपूर्ण प्रदर्शन प्रभाव नहीं। +3. **सुरक्षा:** कॉन्फ़िगरेशन में संग्रहीत टोकन (सुरक्षा निहितार्थों का दस्तावेजीकरण करें)। + +### उपयोगकर्ता कहानियाँ + +1. एक **DevOps इंजीनियर** के रूप में, मैं MCP टूल के लिए बियरर टोकन कॉन्फ़िगर करना चाहता हूं ताकि मैं MCP सर्वर एंडपॉइंट्स को सुरक्षित कर सकूं। +2. एक **CLI उपयोगकर्ता** के रूप में, मैं MCP टूल बनाते समय ऑथ टोकन सेट करना चाहता हूं ताकि मैं संरक्षित सर्वरों से कनेक्ट कर सकूं। +3. एक **सिस्टम प्रशासक** के रूप में, मैं यह देखना चाहता हूं कि किन MCP टूल में प्रमाणीकरण कॉन्फ़िगर किया गया है ताकि मैं सुरक्षा सेटिंग्स का ऑडिट कर सकूं। + +## डिज़ाइन + +### उच्च-स्तरीय आर्किटेक्चर +MCP टूल कॉन्फ़िगरेशन और सेवा को बियरर टोकन प्रमाणीकरण का समर्थन करने के लिए विस्तारित करें: +1. MCP टूल कॉन्फ़िगरेशन स्कीमा में एक वैकल्पिक `auth-token` फ़ील्ड जोड़ें। +2. MCP टूल सेवा को ऑथ-टोकन पढ़ने और इसे HTTP क्लाइंट को पास करने के लिए संशोधित करें। +3. ऑथ टोकन सेट करने और प्रदर्शित करने के लिए CLI टूल को अपडेट करें। +4. सुरक्षा विचारों और सर्वोत्तम प्रथाओं का दस्तावेजीकरण करें। + +### कॉन्फ़िगरेशन स्कीमा + +**वर्तमान स्कीमा:** +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**नया स्कीमा** (वैकल्पिक ऑथ-टोकन के साथ): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**फ़ील्ड विवरण:** +`remote-name` (वैकल्पिक): एमसीपी सर्वर द्वारा उपयोग किया जाने वाला नाम (डिफ़ॉल्ट रूप से कॉन्फ़िगरेशन कुंजी) +`url` (आवश्यक): एमसीपी सर्वर एंडपॉइंट यूआरएल +`auth-token` (वैकल्पिक): प्रमाणीकरण के लिए बेयरर टोकन + +### डेटा प्रवाह + +1. **कॉन्फ़िगरेशन संग्रहण:** उपयोगकर्ता `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123` चलाता है +2. **कॉन्फ़िगरेशन लोडिंग:** एमसीपी टूल सेवा `on_mcp_config()` कॉलबैक के माध्यम से कॉन्फ़िगरेशन अपडेट प्राप्त करती है +3. **टूल इनवोकेशन:** जब टूल को बुलाया जाता है: + सेवा कॉन्फ़िगरेशन से `auth-token` पढ़ती है (यदि मौजूद है) + हेडर डिक्ट बनाता है: `{"Authorization": "Bearer {token}"}` + हेडर को `streamablehttp_client(url, headers=headers)` में पास करता है + एमसीपी सर्वर टोकन को मान्य करता है और अनुरोध को संसाधित करता है + +### एपीआई परिवर्तन +कोई बाहरी एपीआई परिवर्तन नहीं - केवल कॉन्फ़िगरेशन स्कीमा एक्सटेंशन। + +### घटक विवरण + +#### घटक 1: service.py (एमसीपी टूल सेवा) +**फ़ाइल:** `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**उद्देश्य:** दूरस्थ सर्वरों पर एमसीपी टूल को इनवोक करना + +**आवश्यक परिवर्तन** (`invoke_tool()` विधि में): +1. `self.mcp_services[name]` कॉन्फ़िगरेशन में `auth-token` की जाँच करें +2. यदि टोकन मौजूद है तो ऑथराइजेशन हेडर के साथ हेडर डिक्ट बनाएं +3. हेडर को `streamablehttp_client(url, headers=headers)` में पास करें + +**वर्तमान कोड** (पंक्तियाँ 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**संशोधित कोड:** +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### घटक 2: set_mcp_tool.py (सीएलआई कॉन्फ़िगरेशन टूल) +**फ़ाइल**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**उद्देश्य**: एमसीपी टूल कॉन्फ़िगरेशन बनाना/अपडेट करना + +**आवश्यक परिवर्तन**: +1. आर्गुमेंटपार्सर में `--auth-token` वैकल्पिक तर्क जोड़ें +2. प्रदान किए जाने पर कॉन्फ़िगरेशन JSON में `auth-token` शामिल करें + +**वर्तमान तर्क**: +`--id` (आवश्यक): एमसीपी टूल पहचानकर्ता +`--remote-name` (वैकल्पिक): रिमोट एमसीपी टूल नाम +`--tool-url` (आवश्यक): एमसीपी टूल यूआरएल एंडपॉइंट +`-u, --api-url` (वैकल्पिक): ट्रस्टग्राफ एपीआई यूआरएल + +**नया तर्क**: +`--auth-token` (वैकल्पिक): प्रमाणीकरण के लिए बेयरर टोकन + +**संशोधित कॉन्फ़िगरेशन निर्माण**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### घटक 3: show_mcp_tools.py (सीएलआई डिस्प्ले टूल) +**फ़ाइल**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**उद्देश्य**: एमसीपी टूल कॉन्फ़िगरेशन प्रदर्शित करना + +**आवश्यक परिवर्तन**: +1. आउटपुट तालिका में "Auth" कॉलम जोड़ें +2. "हाँ" या "नहीं" प्रदर्शित करें, यह इस आधार पर कि क्या auth-token मौजूद है +3. वास्तविक टोकन मान प्रदर्शित न करें (सुरक्षा) + +**वर्तमान आउटपुट**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**नया आउटपुट**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### घटक 4: दस्तावेज़ +**फ़ाइल**: `docs/cli/tg-set-mcp-tool.md` + +**आवश्यक परिवर्तन**: +1. नए `--auth-token` पैरामीटर का दस्तावेज़ बनाएं +2. प्रमाणीकरण के साथ उपयोग का उदाहरण प्रदान करें +3. सुरक्षा संबंधी विचारों का दस्तावेज़ बनाएं + +## कार्यान्वयन योजना + +### चरण 1: तकनीकी विनिर्देश बनाएं +[x] सभी परिवर्तनों का दस्तावेज़ बनाने वाला व्यापक तकनीकी विनिर्देश लिखें + +### चरण 2: MCP टूल सर्विस को अपडेट करें +[ ] `service.py` में `invoke_tool()` को संशोधित करें ताकि कॉन्फ़िगरेशन से auth-token पढ़ा जा सके +[ ] हेडर डिक्ट बनाएं और इसे `streamablehttp_client` में पास करें +[ ] प्रमाणित MCP सर्वर के साथ परीक्षण करें + +### चरण 3: CLI टूल को अपडेट करें +[ ] `set_mcp_tool.py` में `--auth-token` तर्क जोड़ें +[ ] कॉन्फ़िगरेशन JSON में auth-token शामिल करें +[ ] `show_mcp_tools.py` आउटपुट में "Auth" कॉलम जोड़ें +[ ] CLI टूल परिवर्तनों का परीक्षण करें + +### चरण 4: दस्तावेज़ को अपडेट करें +[ ] `tg-set-mcp-tool.md` में `--auth-token` पैरामीटर का दस्तावेज़ बनाएं +[ ] सुरक्षा संबंधी विचारों का अनुभाग जोड़ें +[ ] उपयोग का उदाहरण प्रदान करें + +### चरण 5: परीक्षण +[ ] MCP टूल auth-token के साथ सफलतापूर्वक कनेक्ट होता है +[ ] पिछड़े अनुकूलता का परीक्षण (auth-token के बिना टूल अभी भी काम करते हैं) +[ ] CLI टूल auth-token को स्वीकार और संग्रहीत करते हैं, इसका परीक्षण करें +[ ] "शो" कमांड auth स्थिति को सही ढंग से प्रदर्शित करता है, इसका परीक्षण करें + +### कोड परिवर्तनों का सारांश +| फ़ाइल | परिवर्तन का प्रकार | पंक्तियाँ | विवरण | +|------|------------|-------|-------------| +| `service.py` | संशोधित | ~52-66 | auth-token पढ़ने और हेडर बनाने के लिए जोड़ा गया | +| `set_mcp_tool.py` | संशोधित | ~30-60 | --auth-token तर्क और कॉन्फ़िगरेशन स्टोरेज जोड़ने के लिए | +| `show_mcp_tools.py` | संशोधित | ~40-70 | प्रदर्शन के लिए Auth कॉलम जोड़ने के लिए | +| `tg-set-mcp-tool.md` | संशोधित | विभिन्न | नए पैरामीटर का दस्तावेज़ बनाने के लिए | + +## परीक्षण रणनीति + +### यूनिट परीक्षण +**ऑथ टोकन रीडिंग**: परीक्षण करें कि `invoke_tool()` कॉन्फ़िगरेशन से auth-token को सही ढंग से पढ़ता है या नहीं +**हेडर बिल्डिंग**: परीक्षण करें कि प्राधिकरण हेडर सही ढंग से Bearer उपसर्ग के साथ बनाया गया है या नहीं +**पिछड़ी अनुकूलता**: परीक्षण करें कि auth-token के बिना टूल अपरिवर्तित रूप से काम करते हैं या नहीं +**CLI तर्क पार्सिंग**: परीक्षण करें कि `--auth-token` तर्क को सही ढंग से पार्स किया गया है या नहीं + +### एकीकरण परीक्षण +**प्रमाणित कनेक्शन**: परीक्षण करें कि MCP टूल सर्विस प्रमाणित सर्वर से कनेक्ट होती है या नहीं +**एंड-टू-एंड**: CLI → कॉन्फ़िगरेशन स्टोरेज → auth टोकन के साथ सेवा इनवोकेशन का परीक्षण करें +**टोकन की आवश्यकता नहीं है**: परीक्षण करें कि अनधिकृत सर्वर से कनेक्शन अभी भी काम करता है या नहीं + +### मैनुअल परीक्षण +**वास्तविक MCP सर्वर**: वास्तविक MCP सर्वर के साथ परीक्षण करें जिसके लिए Bearer टोकन प्रमाणीकरण की आवश्यकता होती है +**CLI वर्कफ़्लो**: परीक्षण करें कि टूल को auth के साथ सेट करें → टूल को इनवोक करें → सफलता की पुष्टि करें +**डिस्प्ले मास्किंग**: सत्यापित करें कि auth स्थिति दिखाई जाती है लेकिन टोकन मान प्रदर्शित नहीं होता है + +## माइग्रेशन और रोलआउट + +### माइग्रेशन रणनीति +माइग्रेशन की आवश्यकता नहीं है - यह विशुद्ध रूप से एक अतिरिक्त कार्यक्षमता है: +`auth-token` के बिना मौजूदा MCP टूल कॉन्फ़िगरेशन अपरिवर्तित रूप से काम करना जारी रखते हैं +नए कॉन्फ़िगरेशन वैकल्पिक रूप से `auth-token` फ़ील्ड शामिल कर सकते हैं +CLI टूल `--auth-token` पैरामीटर को स्वीकार करते हैं लेकिन इसकी आवश्यकता नहीं होती है + +### रोलआउट योजना +1. **चरण 1**: विकास/स्टेजिंग पर मुख्य सेवा परिवर्तनों को तैनात करें +2. **चरण 2**: CLI टूल अपडेट तैनात करें +3. **चरण 3**: दस्तावेज़ को अपडेट करें +4. **चरण 4**: निगरानी के साथ उत्पादन रोलआउट + +### रोलबैक योजना +मुख्य परिवर्तन पिछड़े संगत हैं - मौजूदा टूल अप्रभावित हैं +यदि कोई समस्या उत्पन्न होती है, तो auth-token हैंडलिंग को हेडर बिल्डिंग लॉजिक को हटाकर अक्षम किया जा सकता है +CLI परिवर्तन स्वतंत्र हैं और उन्हें अलग से वापस रोल किया जा सकता है + +## सुरक्षा संबंधी विचार + +### ⚠️ महत्वपूर्ण सीमा: केवल सिंगल-टेनेंट प्रमाणीकरण + +**यह प्रमाणीकरण तंत्र मल्टी-यूजर या मल्टी-टेनेंट वातावरण के लिए उपयुक्त नहीं है।** + +**साझा क्रेडेंशियल**: सभी उपयोगकर्ता और इनवोकेशन प्रत्येक MCP टूल के लिए एक ही टोकन साझा करते हैं +**कोई उपयोगकर्ता संदर्भ नहीं**: MCP सर्वर विभिन्न TrustGraph उपयोगकर्ताओं के बीच अंतर नहीं कर सकता है +**कोई किरायेदार अलगाव नहीं**: सभी किरायेदार प्रत्येक MCP टूल के लिए एक ही क्रेडेंशियल साझा करते हैं +**ऑडिट ट्रेल सीमा**: MCP सर्वर लॉग समान क्रेडेंशियल से सभी अनुरोध दिखाते हैं +**अनुमति दायरा**: विभिन्न उपयोगकर्ताओं के लिए विभिन्न अनुमति स्तरों को लागू नहीं किया जा सकता है + +**इस सुविधा का उपयोग न करें यदि:** +आपका TrustGraph परिनियोजन कई संगठनों (मल्टी-टेनेंट) को सेवा प्रदान करता है +आपको यह ट्रैक करने की आवश्यकता है कि किस उपयोगकर्ता ने किस MCP टूल तक पहुंच की +विभिन्न उपयोगकर्ताओं को विभिन्न अनुमति स्तरों की आवश्यकता होती है +आपको उपयोगकर्ता-स्तरीय ऑडिट आवश्यकताओं का अनुपालन करने की आवश्यकता है +आपका MCP सर्वर प्रति-उपयोगकर्ता दर सीमा या कोटा लागू करता है + +**बहु-उपयोगकर्ता/बहु-किरायेदार परिदृश्यों के लिए वैकल्पिक समाधान:** +कस्टम हेडर के माध्यम से उपयोगकर्ता संदर्भ का प्रचार लागू करें +प्रत्येक किरायेदार के लिए अलग-अलग TrustGraph इंस्टेंस तैनात करें +नेटवर्क-स्तरीय अलगाव का उपयोग करें (वीपीसी, सेवा जाल) +एक प्रॉक्सी परत लागू करें जो प्रति-उपयोगकर्ता प्रमाणीकरण को संभालती है + +### टोकन भंडारण +**जोखिम**: टोकन कॉन्फ़िगरेशन सिस्टम में सादे पाठ में संग्रहीत हैं + +**शमन**: +दस्तावेज़ करें कि टोकन एन्क्रिप्टेड के बिना संग्रहीत हैं +जहां संभव हो, कम अवधि के टोकन का उपयोग करने की अनुशंसा करें +कॉन्फ़िगरेशन भंडारण पर उचित पहुंच नियंत्रण का उपयोग करने की अनुशंसा करें +एन्क्रिप्टेड टोकन भंडारण के लिए भविष्य के सुधार पर विचार करें + +### टोकन एक्सपोजर +**जोखिम**: टोकन लॉग या CLI आउटपुट में उजागर हो सकते हैं + +**शमन**: +टोकन मानों को लॉग न करें (केवल "auth कॉन्फ़िगर किया गया: हाँ/नहीं" लॉग करें) +CLI शो कमांड केवल मास्क की स्थिति प्रदर्शित करता है, वास्तविक टोकन नहीं +त्रुटि संदेशों में टोकन शामिल न करें + +### नेटवर्क सुरक्षा +**जोखिम**: टोकन एन्क्रिप्टेड कनेक्शन पर प्रसारित होते हैं + +**शमन**: +MCP सर्वरों के लिए HTTPS URL का उपयोग करने की अनुशंसा करने वाला दस्तावेज़ +HTTP के साथ प्लेनटेक्स्ट ट्रांसमिशन जोखिम के बारे में उपयोगकर्ताओं को चेतावनी दें + +### कॉन्फ़िगरेशन एक्सेस +**जोखिम**: कॉन्फ़िगरेशन सिस्टम तक अनधिकृत पहुंच टोकन को उजागर करती है + +**शमन**: +कॉन्फ़िगरेशन सिस्टम एक्सेस को सुरक्षित करने के महत्व का दस्तावेज़ करें +कॉन्फ़िगरेशन एक्सेस के लिए न्यूनतम विशेषाधिकार के सिद्धांत की अनुशंसा करें +कॉन्फ़िगरेशन परिवर्तनों के लिए ऑडिट लॉगिंग पर विचार करें (भविष्य का सुधार) + +### बहु-उपयोगकर्ता वातावरण +**जोखिम**: बहु-उपयोगकर्ता परिनियोजन में, सभी उपयोगकर्ता समान MCP क्रेडेंशियल्स साझा करते हैं + +**जोखिम को समझना**: +उपयोगकर्ता ए और उपयोगकर्ता बी दोनों एक ही टोकन का उपयोग MCP टूल तक पहुंचने के लिए करते हैं +MCP सर्वर विभिन्न TrustGraph उपयोगकर्ताओं के बीच अंतर नहीं कर सकता है +प्रति-उपयोगकर्ता अनुमतियों या दर सीमाओं को लागू करने का कोई तरीका नहीं है +MCP सर्वर पर ऑडिट लॉग समान क्रेडेंशियल से सभी अनुरोध दिखाते हैं +यदि एक उपयोगकर्ता का सत्र समझौता किया जाता है, तो हमलावर के पास सभी उपयोगकर्ताओं के समान MCP एक्सेस होता है + +**यह कोई बग नहीं है - यह इस डिज़ाइन की एक मूलभूत सीमा है।** + +## प्रदर्शन प्रभाव +**न्यूनतम ओवरहेड**: हेडर निर्माण में नगण्य प्रसंस्करण समय लगता है +**नेटवर्क प्रभाव**: अतिरिक्त HTTP हेडर प्रति अनुरोध लगभग 50-200 बाइट जोड़ता है +**मेमोरी उपयोग**: कॉन्फ़िगरेशन में टोकन स्ट्रिंग को संग्रहीत करने के लिए नगण्य वृद्धि + +## दस्तावेज़ + +### उपयोगकर्ता दस्तावेज़ +[ ] `tg-set-mcp-tool.md` को `--auth-token` पैरामीटर के साथ अपडेट करें +[ ] सुरक्षा विचारों अनुभाग जोड़ें +[ ] बेयरर टोकन के साथ उपयोग के उदाहरण प्रदान करें +[ ] टोकन भंडारण निहितार्थों का दस्तावेज़ करें + +### डेवलपर दस्तावेज़ +[ ] `service.py` में auth टोकन हैंडलिंग के लिए इनलाइन टिप्पणियाँ जोड़ें +[ ] हेडर निर्माण तर्क का दस्तावेज़ करें +[ ] MCP टूल कॉन्फ़िगरेशन स्कीमा दस्तावेज़ को अपडेट करें + +## खुले प्रश्न +1. **टोकन एन्क्रिप्शन**: क्या हमें कॉन्फ़िगरेशन सिस्टम में एन्क्रिप्टेड टोकन भंडारण लागू करना चाहिए? +2. **टोकन रिफ्रेश**: OAuth रिफ्रेश प्रवाह या टोकन रोटेशन के लिए भविष्य का समर्थन? +3. **वैकल्पिक auth विधियाँ**: क्या हमें बेसिक auth, API कुंजियाँ, या अन्य विधियों का समर्थन करना चाहिए? + +## विचारे गए विकल्प + +1. **टोकन के लिए पर्यावरण चर**: कॉन्फ़िगरेशन के बजाय env चर में टोकन संग्रहीत करें + **अस्वीकृत**: परिनियोजन और कॉन्फ़िगरेशन प्रबंधन को जटिल बनाता है + +2. **अलग सीक्रेट स्टोर**: समर्पित सीक्रेट प्रबंधन प्रणाली का उपयोग करें + **स्थगित**: प्रारंभिक कार्यान्वयन के लिए दायरे से बाहर, भविष्य के सुधार पर विचार करें + +3. **एकाधिक auth विधियाँ**: बेसिक, API कुंजी, OAuth, आदि का समर्थन करें + **अस्वीकृत**: बेयरर टोकन अधिकांश उपयोग मामलों को कवर करते हैं, प्रारंभिक कार्यान्वयन को सरल रखें + +4. **एन्क्रिप्टेड टोकन भंडारण**: कॉन्फ़िगरेशन सिस्टम में टोकन एन्क्रिप्ट करें + **स्थगित**: कॉन्फ़िगरेशन सिस्टम सुरक्षा एक व्यापक चिंता है, भविष्य के कार्य पर स्थगित करें + +5. **प्रति-आवाहन टोकन**: टोकन को आह्वान के समय पास करने की अनुमति दें + **अस्वीकृत**: अलगाव के सिद्धांतों का उल्लंघन करता है, एजेंट को क्रेडेंशियल्स को संभालने में नहीं होना चाहिए + +## संदर्भ +[MCP प्रोटोकॉल विनिर्देश](https://github.com/modelcontextprotocol/spec) +[HTTP बेयरर प्रमाणीकरण (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[वर्तमान MCP टूल सेवा](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[MCP टूल तर्क विनिर्देश](./mcp-tool-arguments.md) + +## परिशिष्ट + +### उपयोग उदाहरण + +**एमसीपी टूल को प्रमाणीकरण के साथ स्थापित करना**: +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**एमसीपी उपकरणों को प्रदर्शित करना**: +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### कॉन्फ़िगरेशन का उदाहरण + +**कॉन्फ़िगरेशन प्रणाली में संग्रहीत**: +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### सुरक्षा सर्वोत्तम अभ्यास + +1. **HTTPS का उपयोग करें**: प्रमाणीकरण वाले MCP सर्वरों के लिए हमेशा HTTPS URL का उपयोग करें। +2. **अल्पकालिक टोकन**: जहां संभव हो, समाप्ति तिथि वाले टोकन का उपयोग करें। +3. **न्यूनतम विशेषाधिकार**: टोकन को आवश्यक न्यूनतम अनुमतियाँ प्रदान करें। +4. **पहुंच नियंत्रण**: कॉन्फ़िगरेशन सिस्टम तक पहुंच को प्रतिबंधित करें। +5. **टोकन रोटेशन**: टोकन को नियमित रूप से बदलें। +6. **ऑडिट लॉगिंग**: सुरक्षा घटनाओं के लिए कॉन्फ़िगरेशन परिवर्तनों की निगरानी करें। diff --git a/docs/tech-specs/mcp-tool-bearer-token.md b/docs/tech-specs/mcp-tool-bearer-token.md index f3f75d29..9c87c74f 100644 --- a/docs/tech-specs/mcp-tool-bearer-token.md +++ b/docs/tech-specs/mcp-tool-bearer-token.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "MCP Tool Bearer Token Authentication Specification" +parent: "Tech Specs" +--- + # MCP Tool Bearer Token Authentication Specification > **⚠️ IMPORTANT: SINGLE-TENANT ONLY** diff --git a/docs/tech-specs/mcp-tool-bearer-token.pt.md b/docs/tech-specs/mcp-tool-bearer-token.pt.md new file mode 100644 index 00000000..15c32c9e --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.pt.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "Especificação de Autenticação de Token Bearer para Ferramentas MCP" +parent: "Portuguese (Beta)" +--- + +# Especificação de Autenticação de Token Bearer para Ferramentas MCP + +> **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. + +> **⚠️ IMPORTANTE: APENAS PARA AMBIENTES DE ÚNICO LOCATÁRIO** +> +> Esta especificação descreve um mecanismo de autenticação básico, de nível de serviço, para ferramentas MCP. Não é uma solução de autenticação completa e não é adequada para: +> - Ambientes multiusuário +> - Implantações multi-tenant +> - Autenticação federada +> - Propagação do contexto do usuário +> - Autorização por usuário +> +> Este recurso fornece **um token estático por ferramenta MCP**, compartilhado entre todos os usuários e sessões. Se você precisar de autenticação por usuário ou por tenant, esta não é a solução certa. + +## Visão Geral +**Nome do Recurso**: Suporte para Autenticação de Token Bearer para Ferramentas MCP +**Autor**: Claude Code Assistant +**Data**: 2025-11-11 +**Status**: Em Desenvolvimento + +### Resumo Executivo + +Permite que as configurações de ferramentas MCP especifiquem tokens bearer opcionais para autenticar com servidores MCP protegidos. Isso permite que o TrustGraph invoque ferramentas MCP hospedadas em servidores que exigem autenticação, sem modificar as interfaces de invocação de agentes ou ferramentas. + +**IMPORTANTE**: Este é um mecanismo de autenticação básico projetado para cenários de autenticação de serviço para serviço, de único tenant. Não é adequado para: +Ambientes multiusuário onde diferentes usuários precisam de credenciais diferentes +Implantações multi-tenant que requerem isolamento por tenant +Cenários de autenticação federada +Autenticação ou autorização em nível de usuário +Gerenciamento de credenciais dinâmico ou atualização de tokens + +Este recurso fornece um token bearer estático e de sistema amplo por configuração de ferramenta MCP, compartilhado entre todos os usuários e invocações dessa ferramenta. + +### Declaração do Problema + +Atualmente, as ferramentas MCP só podem se conectar a servidores MCP acessíveis publicamente. Muitas implantações de produção de MCP exigem autenticação por meio de tokens bearer para segurança. Sem suporte de autenticação: +As ferramentas MCP não podem se conectar a servidores MCP protegidos +Os usuários devem expor servidores MCP publicamente ou implementar proxies reversos +Não há uma maneira padronizada de passar credenciais para conexões MCP +As melhores práticas de segurança não podem ser aplicadas aos endpoints MCP + +### Objetivos + +[ ] Permitir que as configurações de ferramentas MCP especifiquem um parâmetro opcional `auth-token` +[ ] Atualizar o serviço de ferramenta MCP para usar tokens bearer ao se conectar a servidores MCP +[ ] Atualizar as ferramentas de linha de comando para suportar a configuração/exibição de tokens de autenticação +[ ] Manter a compatibilidade com versões anteriores com configurações MCP sem autenticação +[ ] Documentar as considerações de segurança para o armazenamento de tokens + +### Não Objetivos +Atualização dinâmica de tokens ou fluxos OAuth (apenas tokens estáticos) +Criptografia de tokens armazenados (a segurança do sistema de configuração está fora do escopo) +Métodos de autenticação alternativos (autenticação básica, chaves de API, etc.) +Validação ou verificação de expiração de tokens +**Autenticação por usuário**: Este recurso NÃO suporta credenciais específicas do usuário +**Isolamento multi-tenant**: Este recurso NÃO fornece gerenciamento de tokens por tenant +**Autenticação federada**: Este recurso NÃO se integra com provedores de identidade (SSO, OAuth, SAML, etc.) +**Autenticação com contexto**: Os tokens não são passados com base no contexto do usuário ou na sessão + +## Contexto e Informações Adicionais + +### Estado Atual +As configurações de ferramentas MCP são armazenadas no grupo de configuração `mcp` com esta estrutura: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +O serviço da ferramenta MCP conecta-se a servidores usando `streamablehttp_client(url)` sem nenhum cabeçalho de autenticação. + +### Limitações + +**Limitações do Sistema Atual:** +1. **Sem suporte para autenticação**: Não é possível conectar-se a servidores MCP protegidos. +2. **Exposição de segurança**: Os servidores MCP devem ser acessíveis publicamente ou usar apenas segurança em nível de rede. +3. **Problemas de implantação em produção**: Não é possível seguir as melhores práticas de segurança para endpoints de API. + +**Limitações desta Solução:** +1. **Apenas para um único tenant**: Um token estático por ferramenta MCP, compartilhado entre todos os usuários. +2. **Sem credenciais por usuário**: Não é possível autenticar-se como diferentes usuários ou passar o contexto do usuário. +3. **Sem suporte para multi-tenant**: Não é possível isolar as credenciais por tenant ou organização. +4. **Apenas tokens estáticos**: Sem suporte para atualização, rotação ou tratamento de expiração de tokens. +5. **Autenticação em nível de serviço**: Autentica o serviço TrustGraph, não usuários individuais. +6. **Contexto de segurança compartilhado**: Todas as invocações de uma ferramenta MCP usam a mesma credencial. + +### Aplicabilidade do Caso de Uso + +**✅ Casos de Uso Adequados:** +Implantações TrustGraph de um único tenant. +Autenticação de serviço para serviço (TrustGraph → Servidor MCP). +Ambientes de desenvolvimento e teste. +Ferramentas MCP internas acessadas pelo sistema TrustGraph. +Cenários em que todos os usuários compartilham o mesmo nível de acesso à ferramenta MCP. +Credenciais de serviço estáticas e de longa duração. + +**❌ Casos de Uso Inadequados:** +Sistemas multiusuário que requerem autenticação por usuário. +Implantações SaaS multi-tenant com requisitos de isolamento de tenant. +Cenários de autenticação federada (SSO, OAuth, SAML). +Sistemas que requerem a propagação do contexto do usuário para os servidores MCP. +Ambientes que precisam de atualização dinâmica de tokens ou tokens de curta duração. +Aplicações em que diferentes usuários precisam de diferentes níveis de permissão. +Requisitos de conformidade para rastreamento de auditoria em nível de usuário. + +**Exemplo de Cenário Adequado:** +Uma implantação TrustGraph de uma única organização em que todos os funcionários usam a mesma ferramenta MCP interna (por exemplo, consulta de banco de dados da empresa). O servidor MCP requer autenticação para evitar acesso externo, mas todos os usuários internos têm o mesmo nível de acesso. + +**Exemplo de Cenário Inadequado:** +Uma plataforma SaaS TrustGraph multi-tenant em que o Tenant A e o Tenant B precisam acessar seus próprios servidores MCP isolados com credenciais separadas. Este recurso NÃO suporta o gerenciamento de tokens por tenant. + +### Componentes Relacionados +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: Serviço de invocação da ferramenta MCP. +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: Ferramenta de linha de comando para criar/atualizar configurações de MCP. +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: Ferramenta de linha de comando para exibir configurações de MCP. +**SDK Python para MCP**: `streamablehttp_client` de `mcp.client.streamable_http` + +## Requisitos + +### Requisitos Funcionais + +1. **Token de Autenticação da Configuração MCP**: As configurações da ferramenta MCP DEVEM suportar um campo opcional `auth-token`. +2. **Uso do Token Bearer**: O serviço da ferramenta MCP DEVE enviar o cabeçalho `Authorization: Bearer {token}` quando um token de autenticação estiver configurado. +3. **Suporte da CLI**: `tg-set-mcp-tool` DEVE aceitar um parâmetro opcional `--auth-token`. +4. **Exibição do Token**: `tg-show-mcp-tools` DEVE indicar quando um token de autenticação está configurado (mascarado por segurança). +5. **Compatibilidade com versões anteriores**: As configurações de ferramentas MCP existentes sem token de autenticação DEVEM continuar a funcionar. + +### Requisitos Não Funcionais +1. **Compatibilidade com versões anteriores**: Nenhuma alteração disruptiva para as configurações de ferramentas MCP existentes. +2. **Desempenho**: Nenhum impacto significativo no desempenho da invocação da ferramenta MCP. +3. **Segurança**: Tokens armazenados na configuração (documentar as implicações de segurança). + +### Histórias de Usuário + +1. Como um **engenheiro de DevOps**, quero configurar tokens bearer para ferramentas MCP para que eu possa proteger os endpoints do servidor MCP. +2. Como um **usuário da CLI**, quero definir tokens de autenticação ao criar ferramentas MCP para que eu possa conectar-me a servidores protegidos. +3. Como um **administrador do sistema**, quero ver quais ferramentas MCP têm a autenticação configurada para que eu possa auditar as configurações de segurança. + +## Design + +### Arquitetura de Alto Nível +Estender a configuração e o serviço da ferramenta MCP para suportar a autenticação por token bearer: +1. Adicionar um campo opcional `auth-token` ao esquema de configuração da ferramenta MCP. +2. Modificar o serviço da ferramenta MCP para ler o token de autenticação e passá-lo para o cliente HTTP. +3. Atualizar as ferramentas da CLI para suportar a definição e a exibição de tokens de autenticação. +4. Documentar as considerações de segurança e as melhores práticas. + +### Esquema de Configuração + +**Esquema Atual**: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**Novo Esquema** (com token de autenticação opcional): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**Descrições dos Campos**: +`remote-name` (opcional): Nome usado pelo servidor MCP (o padrão é a chave de configuração). +`url` (obrigatório): URL do endpoint do servidor MCP. +`auth-token` (opcional): Token Bearer para autenticação. + +### Fluxo de Dados + +1. **Armazenamento de Configuração**: O usuário executa `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123`. +2. **Carregamento da Configuração**: O serviço da ferramenta MCP recebe a atualização da configuração via callback `on_mcp_config()`. +3. **Invocar a Ferramenta**: Quando a ferramenta é invocada: + O serviço lê `auth-token` da configuração (se presente). + Cria um dicionário de cabeçalhos: `{"Authorization": "Bearer {token}"}`. + Passa os cabeçalhos para `streamablehttp_client(url, headers=headers)`. + O servidor MCP valida o token e processa a solicitação. + +### Alterações na API +Nenhuma alteração na API externa - apenas extensão do esquema de configuração. + +### Detalhes do Componente + +#### Componente 1: service.py (Serviço da Ferramenta MCP) +**Arquivo**: `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**Propósito**: Invocar ferramentas MCP em servidores remotos. + +**Alterações Necessárias** (no método `invoke_tool()`): +1. Verificar se `auth-token` está presente em `self.mcp_services[name]` config. +2. Criar um dicionário de cabeçalhos com o cabeçalho Authorization, se o token existir. +3. Passar os cabeçalhos para `streamablehttp_client(url, headers=headers)`. + +**Código Atual** (linhas 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**Código Modificado**: +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### Componente 2: set_mcp_tool.py (Ferramenta de Configuração de Linha de Comando) +**Arquivo**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**Propósito**: Criar/atualizar configurações da ferramenta MCP + +**Alterações Necessárias**: +1. Adicionar argumento opcional `--auth-token` a argparse +2. Incluir `auth-token` na configuração JSON quando fornecido + +**Argumentos Atuais**: +`--id` (obrigatório): Identificador da ferramenta MCP +`--remote-name` (opcional): Nome da ferramenta MCP remota +`--tool-url` (obrigatório): Endpoint da URL da ferramenta MCP +`-u, --api-url` (opcional): URL da API TrustGraph + +**Novo Argumento**: +`--auth-token` (opcional): Token Bearer para autenticação + +**Construção de Configuração Modificada**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### Componente 3: show_mcp_tools.py (Ferramenta de Exibição de Linha de Comando) +**Arquivo**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**Propósito**: Exibir configurações da ferramenta MCP + +**Alterações Necessárias**: +1. Adicionar coluna "Auth" à tabela de saída +2. Exibir "Sim" ou "Não" com base na presença de auth-token +3. Não exibir o valor real do token (segurança) + +**Saída Atual**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**Nova Saída**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### Componente 4: Documentação +**Arquivo**: `docs/cli/tg-set-mcp-tool.md` + +**Alterações Necessárias**: +1. Documentar o novo parâmetro `--auth-token` +2. Fornecer um exemplo de uso com autenticação +3. Documentar as considerações de segurança + +## Plano de Implementação + +### Fase 1: Criar Especificação Técnica +[x] Escrever uma especificação técnica abrangente documentando todas as alterações + +### Fase 2: Atualizar o Serviço MCP Tool +[ ] Modificar `invoke_tool()` em `service.py` para ler o token de autenticação da configuração +[ ] Criar um dicionário de cabeçalhos e passá-lo para `streamablehttp_client` +[ ] Testar com um servidor MCP autenticado + +### Fase 3: Atualizar as Ferramentas CLI +[ ] Adicionar o argumento `--auth-token` a `set_mcp_tool.py` +[ ] Incluir o token de autenticação no arquivo de configuração JSON +[ ] Adicionar a coluna "Auth" à saída de `show_mcp_tools.py` +[ ] Testar as alterações nas ferramentas CLI + +### Fase 4: Atualizar a Documentação +[ ] Documentar o parâmetro `--auth-token` em `tg-set-mcp-tool.md` +[ ] Adicionar uma seção de considerações de segurança +[ ] Fornecer um exemplo de uso + +### Fase 5: Testes +[ ] Testar se a ferramenta MCP se conecta com sucesso usando o token de autenticação +[ ] Testar a compatibilidade com versões anteriores (ferramentas sem token de autenticação ainda funcionam) +[ ] Testar se as ferramentas CLI aceitam e armazenam corretamente o token de autenticação +[ ] Testar se o comando "show" exibe o status de autenticação corretamente + +### Resumo das Alterações no Código +| Arquivo | Tipo de Alteração | Linhas | Descrição | +|------|------------|-------|-------------| +| `service.py` | Modificado | ~52-66 | Adicionar leitura do token de autenticação e construção de cabeçalhos | +| `set_mcp_tool.py` | Modificado | ~30-60 | Adicionar argumento --auth-token e armazenamento na configuração | +| `show_mcp_tools.py` | Modificado | ~40-70 | Adicionar coluna Auth à exibição | +| `tg-set-mcp-tool.md` | Modificado | Várias | Documentar novo parâmetro | + +## Estratégia de Testes + +### Testes Unitários +**Leitura do Token de Autenticação**: Testar se `invoke_tool()` lê corretamente o token de autenticação da configuração +**Construção de Cabeçalhos**: Testar se o cabeçalho de Autorização é construído corretamente com o prefixo Bearer +**Compatibilidade com Versões Anteriores**: Testar se as ferramentas sem token de autenticação funcionam inalteradas +**Análise de Argumentos da CLI**: Testar se o argumento `--auth-token` é analisado corretamente + +### Testes de Integração +**Conexão Autenticada**: Testar se o serviço da ferramenta MCP se conecta a um servidor autenticado +**Teste de Ponta a Ponta**: Testar o fluxo da CLI → armazenamento na configuração → invocação do serviço com o token de autenticação +**Token Não Necessário**: Testar a conexão com um servidor não autenticado ainda funciona + +### Testes Manuais +**Servidor MCP Real**: Testar com um servidor MCP real que requer autenticação com token Bearer +**Fluxo de Trabalho da CLI**: Testar o fluxo de trabalho completo: configurar a ferramenta com autenticação → invocar a ferramenta → verificar o sucesso +**Mascaramento de Autenticação**: Verificar se o status de autenticação é exibido, mas o valor do token não é exposto + +## Migração e Implantação + +### Estratégia de Migração +Não é necessária migração - esta é uma funcionalidade puramente adicional: +As configurações existentes da ferramenta MCP sem `auth-token` continuam a funcionar inalteradas +Novas configurações podem incluir opcionalmente o campo `auth-token` +As ferramentas CLI aceitam, mas não exigem o parâmetro `--auth-token` + +### Plano de Implantação +1. **Fase 1**: Implantar as alterações principais do serviço no desenvolvimento/ambiente de teste +2. **Fase 2**: Implantar as atualizações das ferramentas CLI +3. **Fase 3**: Atualizar a documentação +4. **Fase 4**: Implantação em produção com monitoramento + +### Plano de Reversão +As alterações principais são compatíveis com versões anteriores - as ferramentas existentes não são afetadas +Se surgirem problemas, o tratamento do token de autenticação pode ser desativado removendo a lógica de construção de cabeçalhos +As alterações da CLI são independentes e podem ser revertidas separadamente + +## Considerações de Segurança + +### ⚠️ Limitação Crítica: Apenas Autenticação para um Único Inquilino + +**Este mecanismo de autenticação NÃO é adequado para ambientes multiusuário ou multi-inquilino.** + +**Credenciais compartilhadas**: Todos os usuários e invocações compartilham o mesmo token por ferramenta MCP +**Sem contexto de usuário**: O servidor MCP não pode distinguir entre diferentes usuários do TrustGraph +**Sem isolamento de inquilino**: Todos os inquilinos compartilham a mesma credencial para cada ferramenta MCP +**Limitação do registro de auditoria**: O servidor MCP registra todas as solicitações da mesma credencial +**Escopo de permissão**: Não é possível impor diferentes níveis de permissão para diferentes usuários + +**NÃO use este recurso se:** +Seu deployment do TrustGraph atende a várias organizações (multi-inquilino) +Você precisa rastrear qual usuário acessou qual ferramenta MCP +Diferentes usuários precisam de diferentes níveis de permissão +Você precisa cumprir requisitos de auditoria em nível de usuário +Seu servidor MCP impõe limites de taxa ou cotas por usuário + +**Soluções alternativas para cenários multiusuário/multilocatário:** +Implementar a propagação do contexto do usuário por meio de cabeçalhos personalizados +Implantar instâncias separadas do TrustGraph por locatário +Usar isolamento em nível de rede (VPCs, malhas de serviço) +Implementar uma camada de proxy que lida com a autenticação por usuário + +### Armazenamento de Tokens +**Risco**: Tokens de autenticação armazenados em texto simples no sistema de configuração + +**Mitigação**: +Documentar que os tokens são armazenados sem criptografia +Recomendar o uso de tokens de curta duração sempre que possível +Recomendar controles de acesso adequados no armazenamento de configuração +Considerar uma melhoria futura para o armazenamento de tokens criptografados + +### Exposição de Tokens +**Risco**: Tokens podem ser expostos em logs ou na saída da linha de comando + +**Mitigação**: +Não registrar os valores dos tokens (registrar apenas "autenticação configurada: sim/não") +O comando de exibição da linha de comando mostra apenas o status mascarado, não o token real +Não incluir tokens em mensagens de erro + +### Segurança da Rede +**Risco**: Tokens transmitidos por conexões não criptografadas + +**Mitigação**: +Documentar a recomendação de usar URLs HTTPS para servidores MCP +Alertar os usuários sobre o risco de transmissão em texto simples com HTTP + +### Acesso à Configuração +**Risco**: Acesso não autorizado ao sistema de configuração expõe tokens + +**Mitigação**: +Documentar a importância de proteger o acesso ao sistema de configuração +Recomendar o princípio do menor privilégio para o acesso à configuração +Considerar o registro de auditoria para alterações na configuração (melhoria futura) + +### Ambientes Multiusuário +**Risco**: Em implantações multiusuário, todos os usuários compartilham as mesmas credenciais do MCP + +**Entendendo o Risco**: +O usuário A e o usuário B usam o mesmo token ao acessar uma ferramenta MCP +O servidor MCP não consegue distinguir entre diferentes usuários do TrustGraph +Não há como impor permissões ou limites de taxa por usuário +Os logs de auditoria no servidor MCP mostram todos os pedidos da mesma credencial +Se a sessão de um usuário for comprometida, o invasor terá o mesmo acesso ao MCP que todos os usuários + +**Isso NÃO é um bug - é uma limitação fundamental deste design.** + +## Impacto no Desempenho +**Sobrecarga mínima**: A construção do cabeçalho adiciona um tempo de processamento insignificante +**Impacto na rede**: O cabeçalho HTTP adicional adiciona ~50-200 bytes por solicitação +**Uso de memória**: Aumento insignificante para armazenar a string do token na configuração + +## Documentação + +### Documentação do Usuário +[ ] Atualizar `tg-set-mcp-tool.md` com o parâmetro `--auth-token` +[ ] Adicionar seção de considerações de segurança +[ ] Fornecer exemplo de uso com token de portador +[ ] Documentar as implicações do armazenamento de tokens + +### Documentação para Desenvolvedores +[ ] Adicionar comentários inline para o tratamento de tokens de autenticação em `service.py` +[ ] Documentar a lógica de construção de cabeçalhos +[ ] Atualizar a documentação do esquema de configuração da ferramenta MCP + +## Perguntas Abertas +1. **Criptografia de tokens**: Devemos implementar o armazenamento de tokens criptografados no sistema de configuração? +2. **Atualização de tokens**: Suporte futuro para fluxos de atualização OAuth ou rotação de tokens? +3. **Métodos de autenticação alternativos**: Devemos suportar autenticação básica, chaves de API ou outros métodos? + +## Alternativas Consideradas + +1. **Variáveis de ambiente para tokens**: Armazenar tokens em variáveis de ambiente em vez de configuração + **Rejeitado**: Complica o gerenciamento de implantação e configuração + +2. **Armazenamento de segredos separado**: Usar um sistema dedicado de gerenciamento de segredos + **Adiado**: Fora do escopo da implementação inicial, considerar uma melhoria futura + +3. **Múltiplos métodos de autenticação**: Suportar Basic, API key, OAuth, etc. + **Rejeitado**: Tokens de portador cobrem a maioria dos casos de uso, manter a implementação inicial simples + +4. **Armazenamento de tokens criptografado**: Criptografar tokens no sistema de configuração + **Adiado**: A segurança do sistema de configuração é uma preocupação mais ampla, adiar para trabalhos futuros + +5. **Tokens por invocação**: Permitir que os tokens sejam passados no momento da invocação + **Rejeitado**: Viola a separação de responsabilidades, o agente não deve lidar com credenciais + +## Referências +[Especificação do Protocolo MCP](https://github.com/modelcontextprotocol/spec) +[Autenticação Bearer HTTP (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[Serviço da Ferramenta MCP Atual](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[Especificação de Argumentos da Ferramenta MCP](./mcp-tool-arguments.md) + +## Apêndice + +### Exemplo de Uso + +**Configuração da ferramenta MCP com autenticação**: +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Exibindo ferramentas MCP:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### Exemplo de Configuração + +**Armazenado no sistema de configuração**: +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### Melhores Práticas de Segurança + +1. **Use HTTPS**: Utilize sempre URLs HTTPS para servidores MCP com autenticação. +2. **Tokens de curta duração**: Utilize tokens com data de expiração sempre que possível. +3. **Privilégios mínimos**: Conceda aos tokens as permissões mínimas necessárias. +4. **Controle de acesso**: Restrinja o acesso ao sistema de configuração. +5. **Rotação de tokens**: Rotacione os tokens regularmente. +6. **Registro de auditoria**: Monitore as alterações de configuração para eventos de segurança. diff --git a/docs/tech-specs/mcp-tool-bearer-token.ru.md b/docs/tech-specs/mcp-tool-bearer-token.ru.md new file mode 100644 index 00000000..71147868 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.ru.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "Спецификация аутентификации токенов Bearer для инструментов MCP" +parent: "Russian (Beta)" +--- + +# Спецификация аутентификации токенов Bearer для инструментов MCP + +> **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. + +> **⚠️ ВАЖНО: ТОЛЬКО ДЛЯ ОДНОГО АРЕНДАТОРА** +> +> Эта спецификация описывает **базовый механизм аутентификации на уровне сервиса** для инструментов MCP. Это **НЕ** полное решение для аутентификации и **НЕ подходит** для: +> - Многопользовательских сред +> - Многоарендных развертываний +> - Федеративной аутентификации +> - Распространения контекста пользователя +> - Авторизации на уровне пользователя +> +> Эта функция предоставляет **один статический токен для каждого инструмента MCP**, который используется всеми пользователями и сеансами. Если вам требуется аутентификация на уровне пользователя или арендатора, это не подходящее решение. + +## Обзор +**Название функции**: Поддержка аутентификации токенов Bearer для инструментов MCP +**Автор**: Claude Code Assistant +**Дата**: 2025-11-11 +**Статус**: В разработке + +### Краткое описание + +Позволяет конфигурациям инструментов MCP указывать необязательные токены Bearer для аутентификации с защищенными серверами MCP. Это позволяет TrustGraph безопасно вызывать инструменты MCP, размещенные на серверах, требующих аутентификации, без изменения интерфейсов агента или вызова инструментов. + +**ВАЖНО**: Это базовый механизм аутентификации, предназначенный для сценариев аутентификации от сервиса к сервису в одноарендной среде. Он **НЕ подходит** для: +Многопользовательских сред, где разные пользователи нуждаются в разных учетных данных +Многоарендных развертываний, требующих изоляции на уровне арендатора +Сценариев федеративной аутентификации +Аутентификации или авторизации на уровне пользователя +Динамического управления учетными данными или обновления токенов + +Эта функция предоставляет статический, системный токен Bearer для каждой конфигурации инструмента MCP, который используется всеми пользователями и вызовами этого инструмента. + +### Описание проблемы + +В настоящее время инструменты MCP могут подключаться только к общедоступным серверам MCP. Многие производственные развертывания MCP требуют аутентификации с помощью токенов Bearer для обеспечения безопасности. Без поддержки аутентификации: +Инструменты MCP не могут подключаться к защищенным серверам MCP +Пользователям приходится либо предоставлять доступ к серверам MCP в общедоступном режиме, либо использовать обратные прокси +Нет стандартизированного способа передачи учетных данных для подключений MCP +Невозможно применять лучшие практики безопасности к конечным точкам MCP + +### Цели + +[ ] Разрешить конфигурациям инструментов MCP указывать необязательный параметр `auth-token` +[ ] Обновить сервис инструмента MCP для использования токенов Bearer при подключении к серверам MCP +[ ] Обновить инструменты командной строки для поддержки установки/отображения токенов аутентификации +[ ] Сохранить обратную совместимость с конфигурациями MCP без аутентификации +[ ] Задокументировать соображения безопасности для хранения токенов + +### Не включено +Динамическое обновление токенов или потоки OAuth (только статические токены) +Шифрование хранимых токенов (безопасность системы конфигураций не входит в область) +Альтернативные методы аутентификации (базовая аутентификация, ключи API и т. д.) +Проверка срока действия или истечения срока действия токенов +**Аутентификация на уровне пользователя**: Эта функция **НЕ поддерживает** учетные данные, специфичные для пользователя +**Изоляция на уровне арендатора**: Эта функция **НЕ предоставляет** управление токенами на уровне арендатора +**Федеративная аутентификация**: Эта функция **НЕ интегрируется** с поставщиками идентификации (SSO, OAuth, SAML и т. д.) +**Аутентификация, зависящая от контекста**: Токены не передаются на основе контекста пользователя или сеанса + +## Предыстория и контекст + +### Текущее состояние +Конфигурации инструментов MCP хранятся в группе конфигураций `mcp` со следующей структурой: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +Сервис инструмента MCP подключается к серверам, используя `streamablehttp_client(url)`, без каких-либо заголовков аутентификации. + +### Ограничения + +**Текущие ограничения системы:** +1. **Отсутствие поддержки аутентификации:** Невозможно подключиться к защищенным серверам MCP. +2. **Риски безопасности:** Серверы MCP должны быть общедоступными или использовать только сетевую безопасность. +3. **Проблемы при развертывании в производственной среде:** Невозможно соблюдать лучшие практики безопасности для API-интерфейсов. + +**Ограничения данного решения:** +1. **Только для однопользовательской системы:** Один статический токен для каждого инструмента MCP, общий для всех пользователей. +2. **Отсутствие учетных данных для каждого пользователя:** Невозможно аутентифицироваться как разные пользователи или передавать контекст пользователя. +3. **Отсутствие поддержки многопользовательской системы:** Невозможно изолировать учетные данные по арендатору или организации. +4. **Только статические токены:** Нет поддержки обновления, ротации или обработки истечения срока действия токенов. +5. **Аутентификация на уровне сервиса:** Аутентифицируется сервис TrustGraph, а не отдельные пользователи. +6. **Общий контекст безопасности:** Все вызовы инструмента MCP используют одни и те же учетные данные. + +### Область применения + +**✅ Подходящие сценарии использования:** +Развертывания TrustGraph для одного арендатора. +Аутентификация от сервиса к сервису (TrustGraph → MCP Server). +Среды разработки и тестирования. +Внутренние инструменты MCP, доступные системе TrustGraph. +Сценарии, в которых все пользователи имеют одинаковый уровень доступа к инструменту MCP. +Статические, долгоживущие учетные данные сервиса. + +**❌ Неподходящие сценарии использования:** +Системы с несколькими пользователями, требующие аутентификацию для каждого пользователя. +Многопользовательские SaaS-платформы с требованиями к изоляции арендаторов. +Сценарии федеративной аутентификации (SSO, OAuth, SAML). +Системы, требующие передачу контекста пользователя на серверы MCP. +Среды, требующие динамическое обновление токенов или короткоживущие токены. +Приложения, в которых разные пользователи должны иметь разные уровни разрешений. +Требования соответствия для аудиторских журналов на уровне пользователя. + +**Пример подходящего сценария:** +Развертывание TrustGraph для одной организации, в котором все сотрудники используют один и тот же внутренний инструмент MCP (например, поиск информации в корпоративной базе данных). Сервер MCP требует аутентификации для предотвращения внешнего доступа, но все внутренние пользователи имеют одинаковый уровень доступа. + +**Пример неподходящего сценария:** +Многопользовательская SaaS-платформа TrustGraph, в которой арендатор A и арендатор B должны получать доступ к своим собственным изолированным серверам MCP с отдельными учетными данными. Эта функция НЕ поддерживает управление токенами на уровне арендатора. + +### Связанные компоненты +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: Сервис вызова инструмента MCP. +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: Инструмент командной строки для создания/обновления конфигураций MCP. +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: Инструмент командной строки для отображения конфигураций MCP. +**MCP Python SDK**: `streamablehttp_client` из `mcp.client.streamable_http`. + +## Требования + +### Функциональные требования + +1. **Токен аутентификации для конфигурации MCP:** Конфигурации инструмента MCP ДОЛЖНЫ поддерживать необязательное поле `auth-token`. +2. **Использование токена Bearer:** Сервис инструмента MCP ДОЛЖЕН отправлять заголовок `Authorization: Bearer {token}` при настройке аутентификации. +3. **Поддержка CLI:** `tg-set-mcp-tool` ДОЛЖЕН принимать необязательный параметр `--auth-token`. +4. **Отображение токена:** `tg-show-mcp-tools` ДОЛЖЕН указывать, когда настроена аутентификация (маскируется для безопасности). +5. **Обратная совместимость:** Существующие конфигурации инструмента MCP без аутентификации ДОЛЖНЫ продолжать работать. + +### Нефункциональные требования +1. **Обратная совместимость:** Отсутствие изменений, нарушающих работу существующих конфигураций инструмента MCP. +2. **Производительность:** Отсутствие значительного влияния на производительность вызова инструмента MCP. +3. **Безопасность:** Токены хранятся в конфигурации (учитывайте последствия для безопасности). + +### Пользовательские истории + +1. Как **инженеру DevOps**, я хочу настроить токены Bearer для инструментов MCP, чтобы я мог защитить конечные точки серверов MCP. +2. Как **пользователю CLI**, я хочу устанавливать токены аутентификации при создании инструментов MCP, чтобы я мог подключаться к защищенным серверам. +3. Как **системному администратору**, я хочу видеть, какие инструменты MCP имеют настроенную аутентификацию, чтобы я мог проверять настройки безопасности. + +## Проектирование + +### Архитектура высокого уровня +Расширение конфигурации и сервиса инструмента MCP для поддержки аутентификации с помощью токена Bearer: +1. Добавление необязательного поля `auth-token` в схему конфигурации инструмента MCP. +2. Изменение сервиса инструмента MCP для чтения токена аутентификации и передачи его в HTTP-клиент. +3. Обновление инструментов командной строки для поддержки установки и отображения токенов аутентификации. +4. Документирование соображений безопасности и лучших практик. + +### Схема конфигурации + +**Текущая схема:** +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**Новая схема** (с необязательным токеном авторизации): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**Описание полей**: +`remote-name` (необязательно): Имя, используемое сервером MCP (по умолчанию - ключ конфигурации). +`url` (обязательно): URL-адрес конечной точки сервера MCP. +`auth-token` (необязательно): Токен для аутентификации. + +### Поток данных + +1. **Хранение конфигурации**: Пользователь запускает `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123`. +2. **Загрузка конфигурации**: Сервис инструмента MCP получает обновление конфигурации через обратный вызов `on_mcp_config()`. +3. **Вызов инструмента**: Когда инструмент вызывается: + Сервис считывает `auth-token` из конфигурации (если он присутствует). + Создает словарь заголовков: `{"Authorization": "Bearer {token}"}`. + Передает заголовки в `streamablehttp_client(url, headers=headers)`. + Сервер MCP проверяет токен и обрабатывает запрос. + +### Изменения API +Отсутствуют внешние изменения API - только расширение схемы конфигурации. + +### Детали компонента + +#### Компонент 1: service.py (Сервис инструмента MCP) +**Файл**: `trustgraph-flow/trustgraph/agent/mcp_tool/service.py`. + +**Назначение**: Вызов инструментов MCP на удаленных серверах. + +**Необходимые изменения** (в методе `invoke_tool()`): +1. Проверить наличие `auth-token` в конфигурации `self.mcp_services[name]`. +2. Создать словарь заголовков с заголовком Authorization, если токен существует. +3. Передать заголовки в `streamablehttp_client(url, headers=headers)`. + +**Текущий код** (строки 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**Измененный код**: +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### Компонент 2: set_mcp_tool.py (Инструмент конфигурации командной строки) +**Файл**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**Назначение**: Создание/обновление конфигураций инструмента MCP. + +**Необходимые изменения**: +1. Добавить необязательный аргумент `--auth-token` в argparse. +2. Включить `auth-token` в конфигурационный JSON, если он предоставлен. + +**Текущие аргументы**: +`--id` (обязательный): Идентификатор инструмента MCP. +`--remote-name` (необязательный): Удаленное имя инструмента MCP. +`--tool-url` (обязательный): URL-адрес конечной точки инструмента MCP. +`-u, --api-url` (необязательный): URL-адрес API TrustGraph. + +**Новый аргумент**: +`--auth-token` (необязательный): Токен Bearer для аутентификации. + +**Измененное построение конфигурации**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### Компонент 3: show_mcp_tools.py (Инструмент отображения командной строки) +**Файл**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**Назначение**: Отображение конфигураций инструмента MCP. + +**Необходимые изменения**: +1. Добавить столбец "Auth" в таблицу вывода. +2. Отображать "Да" или "Нет" в зависимости от наличия auth-токена. +3. Не отображать фактическое значение токена (безопасность). + +**Текущий вывод**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**Новый вывод**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### Компонент 4: Документация +**Файл**: `docs/cli/tg-set-mcp-tool.md` + +**Необходимые изменения**: +1. Документировать новый параметр `--auth-token` +2. Предоставить пример использования с аутентификацией +3. Документировать соображения безопасности + +## План реализации + +### Фаза 1: Создание технической спецификации +[x] Написать подробную техническую спецификацию, документирующую все изменения + +### Фаза 2: Обновление сервиса MCP Tool +[ ] Изменить `invoke_tool()` в `service.py` для чтения auth-token из конфигурации +[ ] Создать словарь заголовков и передать его в `streamablehttp_client` +[ ] Протестировать с аутентифицированным сервером MCP + +### Фаза 3: Обновление инструментов командной строки +[ ] Добавить аргумент `--auth-token` в `set_mcp_tool.py` +[ ] Включить auth-token в конфигурационный JSON +[ ] Добавить столбец "Auth" в вывод `show_mcp_tools.py` +[ ] Протестировать изменения в инструментах командной строки + +### Фаза 4: Обновление документации +[ ] Документировать параметр `--auth-token` в `tg-set-mcp-tool.md` +[ ] Добавить раздел "Соображения безопасности" +[ ] Предоставить пример использования + +### Фаза 5: Тестирование +[ ] Проверить, что сервис MCP tool успешно подключается с использованием auth-token +[ ] Проверить обратную совместимость (инструменты без auth-token по-прежнему работают) +[ ] Проверить, что инструменты командной строки правильно принимают и сохраняют auth-token +[ ] Проверить, что команда "show" правильно отображает статус аутентификации + +### Краткое описание изменений в коде +| Файл | Тип изменения | Строки | Описание | +|------|------------|-------|-------------| +| `service.py` | Изменено | ~52-66 | Добавлено чтение auth-token и построение заголовков | +| `set_mcp_tool.py` | Изменено | ~30-60 | Добавлен аргумент --auth-token и хранение в конфигурации | +| `show_mcp_tools.py` | Изменено | ~40-70 | Добавлен столбец Auth в отображение | +| `tg-set-mcp-tool.md` | Изменено | Различные | Документирован новый параметр | + +## Стратегия тестирования + +### Юнит-тесты +**Чтение токена аутентификации**: Проверить, что `invoke_tool()` правильно считывает auth-token из конфигурации +**Построение заголовков**: Проверить, что заголовок Authorization строится правильно с префиксом Bearer +**Обратная совместимость**: Проверить, что инструменты без auth-token работают без изменений +**Разбор аргументов командной строки**: Проверить, что аргумент `--auth-token` разбирается правильно + +### Интеграционные тесты +**Аутентифицированное подключение**: Проверить, что сервис MCP tool подключается к аутентифицированному серверу +**Комплексное тестирование**: Проверить взаимодействие командной строки → хранилище конфигурации → вызов сервиса с auth token +**Подключение без токена**: Проверить, что подключение к неаутентифицированному серверу по-прежнему работает + +### Ручное тестирование +**Реальный сервер MCP**: Проверить с фактическим сервером MCP, требующим аутентификацию с использованием токена bearer +**Рабочий процесс командной строки**: Проверить полный рабочий процесс: настройка инструмента с auth → вызов инструмента → проверка успешного выполнения +**Маскировка отображения**: Убедиться, что статус аутентификации отображается, но значение токена не отображается + +## Миграция и развертывание + +### Стратегия миграции +Миграция не требуется - это чисто дополнительная функциональность: +Существующие конфигурации MCP tool без `auth-token` продолжают работать без изменений +Новые конфигурации могут опционально включать поле `auth-token` +Инструменты командной строки принимают, но не требуют параметр `--auth-token` + +### План развертывания +1. **Фаза 1**: Развернуть основные изменения сервиса в среде разработки/тестирования +2. **Фаза 2**: Развернуть обновления инструментов командной строки +3. **Фаза 3**: Обновить документацию +4. **Фаза 4**: Развертывание в производственной среде с мониторингом + +### План отката +Основные изменения обратно совместимы - существующие инструменты не затронуты +В случае возникновения проблем обработку auth-token можно отключить, удалив логику построения заголовков +Изменения в инструментах командной строки являются независимыми и могут быть отменены отдельно + +## Соображения безопасности + +### ⚠️ Критическое ограничение: Поддержка только однопользовательской аутентификации + +**Этот механизм аутентификации НЕ подходит для многопользовательских или многопользовательских сред.** + +**Общие учетные данные**: Все пользователи и вызовы используют один и тот же токен для каждого инструмента MCP +**Отсутствие контекста пользователя**: Сервер MCP не может различать разных пользователей TrustGraph +**Отсутствие изоляции арендаторов**: Все арендаторы используют одни и те же учетные данные для каждого инструмента MCP +**Ограничение журнала аудита**: Сервер MCP отображает все запросы от одних и тех же учетных данных +**Область разрешений**: Невозможно применять разные уровни разрешений для разных пользователей + +**Не используйте эту функцию, если:** +Ваша развертка TrustGraph обслуживает несколько организаций (многопользовательская среда) +Вам необходимо отслеживать, какой пользователь получил доступ к какому инструменту MCP +Разным пользователям требуются разные уровни разрешений +Вам необходимо соблюдать требования аудита на уровне пользователей +Ваш сервер MCP применяет ограничения скорости или квоты на уровне пользователя + +**Альтернативные решения для сценариев с несколькими пользователями/многопользовательской средой:** +Реализовать распространение контекста пользователя через пользовательские заголовки +Развернуть отдельные экземпляры TrustGraph для каждого арендатора +Использовать сетевую изоляцию (VPCs, service meshes) +Реализовать прокси-слой, который обрабатывает аутентификацию для каждого пользователя + +### Хранение токенов +**Риск**: Токены аутентификации хранятся в открытом виде в системе конфигурации + +**Меры по снижению риска**: +Задокументировать, что токены хранятся без шифрования +Рекомендовать использовать токены с коротким сроком действия, когда это возможно +Рекомендовать надлежащий контроль доступа к хранилищу конфигурации +Рассмотреть возможность будущей реализации для зашифрованного хранения токенов + +### Раскрытие токенов +**Риск**: Токены могут быть раскрыты в журналах или в выходных данных командной строки + +**Меры по снижению риска**: +Не записывать значения токенов в журналы (записывать только "аутентификация настроена: да/нет") +Команда `show` в командной строке отображает только маскированный статус, а не фактический токен +Не включать токены в сообщения об ошибках + +### Сетевая безопасность +**Риск**: Токены передаются по незашифрованным соединениям + +**Меры по снижению риска**: +Рекомендовать использовать HTTPS-URL-адреса для серверов MCP +Предупреждать пользователей о риске передачи данных в открытом виде по протоколу HTTP + +### Доступ к конфигурации +**Риск**: Несанкционированный доступ к системе конфигурации раскрывает токены + +**Меры по снижению риска**: +Подчеркнуть важность защиты доступа к системе конфигурации +Рекомендовать принцип наименьших привилегий для доступа к конфигурации +Рассмотреть возможность ведения журналов аудита для изменений конфигурации (будущая реализация) + +### Многопользовательские среды +**Риск**: В многопользовательских развертываниях все пользователи используют одни и те же учетные данные MCP + +**Понимание риска**: +Пользователь A и пользователь B используют один и тот же токен при доступе к инструменту MCP +Сервер MCP не может различать разных пользователей TrustGraph +Нет возможности применить права доступа или ограничения скорости для каждого пользователя +Журналы аудита на сервере MCP показывают все запросы от одних и тех же учетных данных +Если сессия одного пользователя скомпрометирована, злоумышленник получает тот же доступ к MCP, что и все пользователи + +**Это НЕ ошибка - это фундаментальное ограничение этой архитектуры.** + +## Влияние на производительность +**Минимальные накладные расходы**: Создание заголовка добавляет незначительное время обработки +**Влияние на сеть**: Дополнительный HTTP-заголовок добавляет ~50-200 байт на запрос +**Использование памяти**: Незначительное увеличение объема памяти для хранения строки токена в конфигурации + +## Документация + +### Пользовательская документация +[ ] Обновить `tg-set-mcp-tool.md` с параметром `--auth-token` +[ ] Добавить раздел о соображениях безопасности +[ ] Предоставить пример использования с токеном типа bearer +[ ] Задокументировать последствия хранения токенов + +### Документация для разработчиков +[ ] Добавить встроенные комментарии для обработки токенов аутентификации в `service.py` +[ ] Задокументировать логику создания заголовков +[ ] Обновить документацию схемы конфигурации инструмента MCP + +## Открытые вопросы +1. **Шифрование токенов**: Следует ли нам реализовать зашифрованное хранение токенов в системе конфигурации? +2. **Обновление токенов**: Будущая поддержка потоков OAuth для обновления токенов или ротации токенов? +3. **Альтернативные методы аутентификации**: Следует ли нам поддерживать Basic auth, API-ключи или другие методы? + +## Рассмотренные альтернативы + +1. **Переменные среды для токенов**: Хранить токены в переменных среды вместо конфигурации + **Отклонено**: Усложняет развертывание и управление конфигурацией + +2. **Отдельное хранилище секретов**: Использовать специализированную систему управления секретами + **Отложено**: Выходит за рамки первоначальной реализации, рассмотреть возможность будущей реализации + +3. **Несколько методов аутентификации**: Поддержка Basic, API-ключей, OAuth и т.д. + **Отклонено**: Токены типа bearer охватывают большинство сценариев использования, сохраняем простоту первоначальной реализации + +4. **Зашифрованное хранение токенов**: Шифровать токены в системе конфигурации + **Отложено**: Безопасность системы конфигурации является более широкой проблемой, отложить до будущей работы + +5. **Токены для каждого вызова**: Разрешить передачу токенов во время вызова + **Отклонено**: Нарушает разделение ответственности, агент не должен обрабатывать учетные данные + +## Ссылки +[Спецификация протокола MCP](https://github.com/modelcontextprotocol/spec) +[HTTP Bearer Authentication (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[Текущий сервис инструмента MCP](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[Спецификация аргументов инструмента MCP](./mcp-tool-arguments.md) + +## Приложение + +### Пример использования + +**Настройка инструмента MCP с аутентификацией**: +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Отображение инструментов MCP:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### Пример конфигурации + +**Хранится в системе конфигурации**: +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### Лучшие практики безопасности + +1. **Использование HTTPS**: Всегда используйте HTTPS-адреса для серверов MCP с аутентификацией. +2. **Кратковременные токены**: Используйте токены с истечением срока действия, когда это возможно. +3. **Принцип наименьших привилегий**: Предоставляйте токенам минимально необходимые разрешения. +4. **Контроль доступа**: Ограничьте доступ к системе конфигурации. +5. **Ротация токенов**: Регулярно обновляйте токены. +6. **Журналирование аудита**: Отслеживайте изменения конфигурации для выявления событий безопасности. diff --git a/docs/tech-specs/mcp-tool-bearer-token.sw.md b/docs/tech-specs/mcp-tool-bearer-token.sw.md new file mode 100644 index 00000000..a67ffc92 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.sw.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "MCP Tool Bearer Token Authentication Specification" +parent: "Swahili (Beta)" +--- + +# MCP Tool Bearer Token Authentication 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. + +> **⚠️ MUHIMU: INATUMIWA TU KWA MASHARTI MOJA** +> +> Maelezo haya yanaelezea **mfumo msingi wa uthibitishaji wa kiwango cha huduma** kwa zana za MCP. Haikuwa **suluhisho kamili** la uthibitishaji na **haifai** kwa: +> - Mazingira ya watumiaji wengi +> - Matumizi mengi ya wateja +> - Uthibitishaji uliounganishwa +> - Usambazaji wa muktadha wa mtumiaji +> - Ruhusa kwa kila mtumiaji +> +> Kipengele hiki hutoa **simu moja ya tuli kwa kila zana ya MCP**, ambayo inashirikiwa na watumiaji wote na vipindi vyote. Ikiwa unahitaji uthibitishaji kwa kila mtumiaji au kwa kila mteja, hii si suluhisho sahihi. + +## Maelezo +**Jina la Kipengele**: Usaidizi wa Uthibitishaji wa Simu ya Bearer ya Zana ya MCP +**Mwandishi**: Claude Code Assistant +**Tarehe**: 2025-11-11 +**Hali**: Katika Maendeleo + +### Muhtasari + +Ruhusu usanidi wa zana za MCP kubainisha simu za hiari za bearer kwa uthibitishaji na seva za MCP zilizolindwa. Hii inaruhusu TrustGraph kuita zana za MCP zilizohifadhiwa kwenye seva ambazo zinahitaji uthibitishaji, bila kubadilisha wakala au interfaces za kutumia zana. + +**MUHIMU**: Hii ni mfumo msingi wa uthibitishaji ulioundwa kwa hali za uthibitishaji wa huduma hadi huduma kwa mteja mmoja. Haifai kwa: +Mazingira ya watumiaji wengi ambapo watumiaji tofauti wanahitaji anwani tofauti +Matumizi mengi ya wateja yanayohitaji kutengwa kwa kila mteja +Hali za uthibitishaji zilizounganishwa +Uthibitishaji au ruhusa za kiwango cha mtumiaji +Usimamizi wa anwani ya kipekee au urekebishaji wa simu + +Kipengele hiki hutoa simu ya tuli, ya kimfumo kwa usanidi wa kila zana ya MCP, ambayo inashirikiwa na watumiaji wote na matumizi ya zana hiyo. + +### Tatizo + +Kwa sasa, zana za MCP zinaweza kuunganisha tu kwa seva za MCP zinazopatikana kwa umma. Matumizi mengi ya uzalishaji ya MCP yanahitaji uthibitishaji kupitia simu za bearer kwa usalama. Bila usaidizi wa uthibitishaji: +Zana za MCP haziwezi kuunganisha kwa seva za MCP zilizolindwa +Watumiaji lazima iweze kufungua seva za MCP kwa umma au kutumia viboreshaji vya kurudi nyuma +Hakuna njia iliyoanzishwa ya kupitisha anwani kwa miunganisho ya MCP +Mazoea bora ya usalama hayawezi kutekelezwa kwenye mwisho wa MCP + +### Lengo + +[ ] Ruhusu usanidi wa zana za MCP kubainisha parameter ya `auth-token` ya hiari +[ ] Sasisha huduma ya zana ya MCP ili itumie simu za bearer wakati inapo na seva za MCP +[ ] Sasisha zana za CLI ili kusaidia kuweka/kuonyesha anwani +[ ] Dumishe utangamano wa nyuma na usanidi usio na uthibitishaji wa MCP +[ ] Andika masuala ya usalama ya uhifadhi wa simu + +### Lengo Lisilofikiwa +Urekebishaji wa simu ya kipekee au mtiririko wa OAuth (simu za tuli tu) +Usifungishaji wa simu zilizohifadhiwa (usalama wa mfumo wa usanidi uko nje ya wigo) +Njia zingine za uthibitishaji (uthibitishaji wa Msingi, ufunguo wa API, n.k.) +Uthibitishaji au ukaguzi wa kumalizika wa simu +**Uthibitishaji wa kila mtumiaji**: Kipengele hiki hakisaidii anwani maalum za mtumiaji +**Kutengwa kwa mteja mwingi**: Kipengele hiki hakutoa usimamizi wa simu kwa kila mteja +**Uthibitishaji uliounganishwa**: Kipengele hiki hakujumuisha na watoa utambulisho (SSO, OAuth, SAML, n.k.) +**Uthibitishaji unaohusiana na muktadha**: Simu hazipitishwe kulingana na muktadha wa mtumiaji au kikao + +## Asili na Mfumo + +### Hali ya Sasa +Usanidi wa zana za MCP huhifadhiwa katika kikundi cha usanidi cha `mcp` na muundo huu: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +Huduma ya zana ya MCP inaunganisha na seva kwa kutumia `streamablehttp_client(url)` bila vichwa vya uthibitishaji. + +### Marekebisho + +**Marekebisho ya Sasa ya Mfumo:** +1. **Hakuna usaidizi wa uthibitishaji**: Haiwezi kuunganisha na seva za MCP zilizolindwa. +2. **Ufafanuzi wa usalama**: Seva za MCP lazima ziwe zinapatikana kwa umma au zitumie usalama wa kiwango cha mtandao pekee. +3. **Matatizo ya matumizi katika mazingira ya uzalishaji**: Haiwezi kufuata mbinu bora za usalama kwa vidokezo vya API. + +**Marekebisho ya Suluhisho Hili:** +1. **Kwa watumiaji mmoja tu**: Ishara moja ya tuli kwa kila zana ya MCP, inayoshirikiwa na watumiaji wote. +2. **Hakuna anwani za mtumiaji binafsi**: Haiwezi kuthibitisha kama watumiaji tofauti au kupitisha muktadha wa mtumiaji. +3. **Hakuna usaidizi wa watumiaji wengi**: Haiwezi kutenganisha anwani kwa kila mhakiki au shirika. +4. **Ishara za tuli tu**: Hakuna usaidizi kwa sasisho, mzunguko, au utunzaji wa kumalizika kwa ishara. +5. **Uthibitishaji wa huduma**: Inathibitisha huduma ya TrustGraph, sio watumiaji binafsi. +6. **Muktadha wa usalama unaoshirikiwa**: Matumizi yote ya zana ya MCP hutumia anwani sawa. + +### Ufaa wa Matumizi + +**✅ Matumizi Yanayofaa:** +Uwekaji wa TrustGraph kwa watumiaji mmoja. +Uthibitishaji kutoka kwa huduma hadi huduma (TrustGraph → Seva ya MCP). +Mazingira ya maendeleo na majaribio. +Zana za ndani za MCP zinazopatikana na mfumo wa TrustGraph. +Matukio ambamo watumiaji wote wana kiwango sawa cha ufikiaji wa zana ya MCP. +Anwani za huduma za tuli, za muda mrefu. + +**❌ Matumizi Yasiyofaa:** +Mifumo ya watumiaji wengi inayohitaji uthibitishaji wa kila mtumiaji. +Uwekaji wa SaaS wa watumiaji wengi wenye mahitaji ya kutenganisha kila mhakiki. +Matukio ya uthibitishaji uliounganishwa (SSO, OAuth, SAML). +Mifumo inayohitaji kupitisha muktadha wa mtumiaji kwa seva za MCP. +Mazingira yanayohitaji sasisho za ishara za nguvu au ishara za muda mfupi. +Programu ambamo watumiaji tofauti wanahitaji viwango tofauti vya ruhusa. +Mahitaji ya utiifu kwa njia za ukaguzi za kiwango cha mtumiaji. + +**Mfano wa Matumizi Yanayofaa:** +Uwekaji wa TrustGraph wa shirika moja ambamo wafanyakazi wote hutumia zana sawa ya ndani ya MCP (k.m., utafutaji wa hifadhi ya kampuni). Seva ya MCP inahitaji uthibitishaji ili kuzuia ufikiaji wa nje, lakini watumiaji wote wa ndani wana kiwango sawa cha ufikiaji. + +**Mfano wa Matumizi Yasiyofaa:** +Jukwaa la SaaS la TrustGraph la watumiaji wengi ambamo Mhakiki A na Mhakiki B kila mmoja anahitaji kufikia seva zao zilizotenganishwa za MCP na anwani tofauti. Kipengele hiki hakitumii usimamizi wa anwani wa kila mhakiki. + +### Vipengele Vinavyohusiana +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: Huduma ya utekelezaji wa zana ya MCP. +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: Zana ya CLI ya kuunda/kusasisha mipangilio ya MCP. +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: Zana ya CLI ya kuonyesha mipangilio ya MCP. +**SDK ya Python ya MCP**: `streamablehttp_client` kutoka `mcp.client.streamable_http` + +## Mahitaji + +### Mahitaji ya Kifaa + +1. **Ishara ya Uthibitishaji ya Mipangilio ya MCP**: Mipangilio ya zana ya MCP INAWEZA kuwa na `auth-token`. +2. **Matumizi ya Ishara ya Bearer**: Huduma ya zana ya MCP INAWEZA kutuma `Authorization: Bearer {token}` wakati ishara ya uthibitishaji imewekwa. +3. **Usaidizi wa CLI**: `tg-set-mcp-tool` INAWEZA kukubali parameter ya `--auth-token`. +4. **Uonyesho wa Ishara**: `tg-show-mcp-tools` INAWEZA kuonyesha wakati ishara ya uthibitishaji imewekwa (imeficha kwa usalama). +5. **Ulinganishaji na Mifumo ya Zamani**: Mipangilio ya zana ya MCP iliyopo bila uthibitishaji INAWEZA kuendelea kufanya kazi. + +### Mahitaji Yasiyo ya Kifaa +1. **Ulinganishaji na Mifumo ya Zamani**: Hakuna mabadiliko yoyote yanayoweza kusababisha migogoro kwa mipangilio ya zana ya MCP iliyopo. +2. **Utendaji**: Hakuna athari kubwa ya utendaji kwenye utekelezaji wa zana ya MCP. +3. **Usalama**: Anwani zinaohifadhiwa katika mipangilio (angalia masuala ya usalama). + +### Hadithi za Mtumiaji + +1. Kama **mhandisi wa DevOps**, ningependa kusanidi anwani za bearer kwa zana za MCP ili niweze kulinda vidokezo vya seva za MCP. +2. Kama **mtumiaji wa CLI**, ningependa kuweka anwani za uthibitishaji wakati ninaunda zana za MCP ili niweze kuunganisha na seva zilizolindwa. +3. Kama **mhasibu wa mfumo**, ningependa kuona zana gani za MCP zilizosanidiwa na uthibitishaji ili niweze kukagua mipangilio ya usalama. + +## Muundo + +### Muundo wa Juu +Panua mipangilio ya zana ya MCP na huduma ili kusaidia uthibitishaji wa ishara ya bearer: +1. Ongeza `auth-token` kwenye schema ya mipangilio ya zana ya MCP. +2. Badilisha huduma ya zana ya MCP ili kusoma ishara ya uthibitishaji na kuipitisha kwa mteja wa HTTP. +3. Sasisha zana za CLI ili kusaidia kuweka na kuonyesha anwani za uthibitishaji. +4. Andika masuala ya usalama na mbinu bora. + +### Schema ya Mipangilio + +**Schema ya Sasa**: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**Mfumo Mpya** (na ishara ya uthibitisho ya hiari): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**Maelezo ya Kila Kila Nyanja:** +`remote-name` (hiari): Jina linalotumika na seva ya MCP (linalotumika kiotomatiki kama funguo ya usanidi) +`url` (lazima): URL ya mwisho wa seva ya MCP +`auth-token` (hiari): Alama ya "Bearer" kwa uthibitishaji + +### Mtiririko wa Data + +1. **Hifadhi ya Usanidi:** Mtumiaji huanzisha `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123` +2. **Upakiaji wa Usanidi:** Huduma ya zana ya MCP hupokea sasisho la usanidi kupitia mjumuko wa `on_mcp_config()` +3. **Uanzishaji wa Zana:** Wakati zana inaanzishwa: + Huduma husoma `auth-token` kutoka usanidi (ikiwa ipo) + Huunda kamusi ya vichwa: `{"Authorization": "Bearer {token}"}` + Hutuma vichwa kwa `streamablehttp_client(url, headers=headers)` + Seva ya MCP huangalia alama na kutoa ombi + +### Mabadiliko ya API +Hakuna mabadiliko ya API ya nje - mabadiliko ya muundo wa usanidi tu. + +### Maelezo ya Vipengele + +#### Kipengele 1: service.py (Huduma ya Zana ya MCP) +**Faili:** `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**Lengo:** Kuendesha zana za MCP kwenye seva za mbali + +**Mabadiliko Yanayohitajika** (katika njia ya `invoke_tool()`): +1. Angalia `auth-token` katika usanidi wa `self.mcp_services[name]` +2. Jenga kamusi ya vichwa na kichwa cha "Authorization" ikiwa alama ipo +3. Tuma vichwa kwa `streamablehttp_client(url, headers=headers)` + +**Msimbo Sasa** (mistari 42-89): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**Msimbo Uliorekebishwa**: +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### Sehemu ya 2: set_mcp_tool.py (Zana ya Usanidi wa CLI) +**Faili**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**Madhumuni**: Kuunda/kusasisha usanidi wa zana ya MCP + +**Mabadiliko Yanayohitajika**: +1. Ongeza sajili ya `--auth-token` ya hiari kwa argparse +2. Jumuisha `auth-token` katika JSON ya usanidi wakati inatolewa + +**Sajili za Sasa**: +`--id` (lazima): Kitambulisho cha zana ya MCP +`--remote-name` (ya hiari): Jina la zana ya MCP ya mbali +`--tool-url` (lazima): Ncha ya URL ya zana ya MCP +`-u, --api-url` (ya hiari): URL ya API ya TrustGraph + +**Sajili Mpya**: +`--auth-token` (ya hiari): Alama ya "Bearer" kwa uthibitishaji + +**Ujenzi wa Usanidi Uliobadilishwa**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### Sehemu ya 3: show_mcp_tools.py (Chombo cha Kuonyesha Kwenye Kamba) +**Faili**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**Madhumuni**: Kuonyesha usanidi wa chombo cha MCP + +**Mabadiliko Yanayohitajika**: +1. Ongeza safu ya "Auth" kwenye meza ya pato +2. Onyesha "Ndiyo" au "Hapana" kulingana na uwepo wa ishara ya uthibitishaji (auth-token) +3. Usionyeshe thamani halisi ya ishara (usalama) + +**Pato Lililopo Sasa**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**Pato Jipya**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### Sehemu ya 4: Nyaraka +**Faili**: `docs/cli/tg-set-mcp-tool.md` + +**Mabadiliko Yanayohitajika**: +1. Andika nyaraka kwa parameter mpya ya `--auth-token` +2. Toa mfano wa matumizi na uthibitishaji +3. Andika masuala ya usalama + +## Mpango wa Utendaji + +### Awamu ya 1: Unda Vipimo vya Kisaikolojia +[x] Andika vipimo vya kisaikolojia vya kina ambavyo vinadokeza mabadiliko yote + +### Awamu ya 2: Sasisha Huduma ya Zana ya MCP +[ ] Badilisha `invoke_tool()` katika `service.py` ili kusoma `auth-token` kutoka kwa usanidi +[ ] Jenga kamusi ya vichwa na uipitisha kwa `streamablehttp_client` +[ ] Jaribu na seva ya MCP iliyo na uthibitishaji + +### Awamu ya 3: Sasisha Zana za CLI +[ ] Ongeza hoja ya `--auth-token` kwa `set_mcp_tool.py` +[ ] Jumuisha `auth-token` katika usanidi wa JSON +[ ] Ongeza safu ya "Auth" kwenye pato la `show_mcp_tools.py` +[ ] Jaribu mabadiliko ya zana ya CLI + +### Awamu ya 4: Sasisha Nyaraka +[ ] Andika `--auth-token` katika `tg-set-mcp-tool.md` +[ ] Ongeza sehemu ya masuala ya usalama +[ ] Toa mfano wa matumizi + +### Awamu ya 5: Majaribio +[ ] Jaribu zana ya MCP na `auth-token` inaunganisha kwa ufanisi +[ ] Jaribu utangamano wa nyuma (zana bila `auth-token` zinaendelea kufanya kazi) +[ ] Jaribu zana za CLI hupokea na kuhifadhi `auth-token` kwa usahihi +[ ] Jaribu amri ya "Onyesha" inaonyesha hali ya uthibitishaji kwa usahihi + +### Muhtasari wa Mabadiliko ya Msimbo +| Faili | Aina ya Mabadiliko | Mistari | Maelezo | +|------|------------|-------|-------------| +| `service.py` | Imebadilishwa | ~52-66 | Ongeza usomaji wa `auth-token` na ujenzi wa vichwa | +| `set_mcp_tool.py` | Imebadilishwa | ~30-60 | Ongeza hoja ya `--auth-token` na uhifadhi wa usanidi | +| `show_mcp_tools.py` | Imebadilishwa | ~40-70 | Ongeza safu ya Uthibitishaji kwenye onyesho | +| `tg-set-mcp-tool.md` | Imebadilishwa | Mbalimbali | Andika parameter mpya | + +## Mkakati wa Majaribio + +### Majaribio ya Kitengo +**Usomaji wa Tokeni ya Uthibitishaji**: Jaribu `invoke_tool()` husoma `auth-token` kwa usahihi kutoka kwa usanidi +**Ujenzi wa Vichwa**: Jaribu vichwa vya Ruhusa vinajengwa kwa usahihi na mbele ya `Bearer` +**Utangamano wa Nyuma**: Jaribu zana bila `auth-token` zinafanya kazi bila mabadiliko +**Uchanganuzi wa Hoja ya CLI**: Jaribu hoja ya `--auth-token` inachanganzwa kwa usahihi + +### Majaribio ya Uunganisho +**Uunganisho Ulio na Uthibitishaji**: Jaribu huduma ya zana ya MCP inaunganisha na seva iliyo na uthibitishaji +**Kila kitu**: Jaribu CLI → uhifadhi wa usanidi → utekelezaji wa huduma na `auth token` +**Tokeni Haihitajiki**: Jaribu uunganisho na seva isiyo na uthibitishaji unaendelea kufanya kazi + +### Majaribio ya Kawaida +**Seva Halisi ya MCP**: Jaribu na seva halisi ya MCP inayohitaji uthibitishaji wa `bearer token` +**Mwendo wa CLI**: Jaribu mwendo kamili: weka zana na uthibitishaji → fanya kazi ya zana → thibitisha mafanikio +**Kuficha Kuonyesha**: Thibitisha hali ya uthibitishaji inaonyeshwa lakini thamani ya tokeni haijaonyeshwa + +## Uhamishaji na Utoaji + +### Mkakati wa Uhamishaji +Hakuna uhamishaji unaohitajika - hii ni utendakazi wa ziada: +Usanidi wa zana ya MCP iliyopo bila `auth-token` inaendelea kufanya kazi bila mabadiliko +Usanidi mpya unaweza kujumuisha sehemu ya `auth-token` +Zana za CLI hupokea lakini hazihitaji parameter ya `--auth-token` + +### Mpango wa Utoaji +1. **Awamu ya 1**: Toa mabadiliko ya msingi ya huduma kwa maendeleo/maandalizi +2. **Awamu ya 2**: Toa sasisho za zana za CLI +3. **Awamu ya 3**: Sasisha nyaraka +4. **Awamu ya 4**: Utoaji wa uzalishaji na ufuatiliaji + +### Mpango wa Kurudisha Nyuma +Mabadiliko ya msingi yana utangamano wa nyuma - zana zilizopo hazipatiwa madhara +Ikiwa matatizo yanajitokeza, utunzaji wa `auth-token` unaweza kuzimwa kwa kuondoa mantiki ya ujenzi wa vichwa +Mabadiliko ya zana za CLI ni huru na yanaweza kurejeshwa kando + +## Masuala ya Usalama + +### ⚠️ Kikomo Muhimu: Uthibitishaji wa Mfumo Mmoja Tu + +**Mfumo huu wa uthibitishaji haufai kwa mazingira ya watumiaji wengi au ya wateja wengi.** + +**Anwani zilizoshirikiwa**: Watumiaji wote na matumizi yote huongea tokeni moja kwa kila zana ya MCP +**Hakuna muktadha wa mtumiaji**: Seva ya MCP haiwezi kutofautisha kati ya watumiaji tofauti wa TrustGraph +**Hakuna kutengwa kwa mteja**: Wateja wote huongea anwani sawa kwa kila zana ya MCP +**Kizuia cha ukaguzi**: Seva ya MCP inaonyesha maombi yote kutoka kwa anwani sawa +**Nguvu za idhini**: Haiwezi kutekeleza viwango tofauti vya idhini kwa watumiaji tofauti + +**Usitumie kipengele hiki ikiwa:** +Umechanganya mashirika mengi +Unahitaji uthibitishaji wa mtu binafsi +Unahitaji uthibitishaji wa muda +Unahitaji uthibitishaji wa mteja mmoja + + +**Suluhisho mbadala kwa matukio ya watumiaji wengi/watu wengi:** +Tengeneza usambazaji wa muktadha wa mtumiaji kupitia vichwa maalum +Weka mifumo tofauti ya TrustGraph kwa kila mtoa huduma +Tumia utengano wa kiwango cha mtandao (VPCs, huduma za mtandao) +Tengeneza safu ya wakala inayoshughulikia uthibitishaji wa kila mtumiaji + +### Uhifadhi wa Tokeni +**Hatari**: Tokeni za uthibitishaji zimehifadhiwa kwa maandishi wazi katika mfumo wa usanidi + +**Hatua za kuzuia**: +Andika kwamba tokeni zimehifadhiwa bila usimbaji +Pendekeza kutumia tokeni za muda mfupi inapowezekana +Pendekeza udhibiti sahihi wa ufikiaji kwenye hifadhi ya usanidi +Fikiria uboreshaji wa baadaye kwa uhifadhi uliosimbwa wa tokeni + +### Uonyeshaji wa Tokeni +**Hatari**: Tokeni zinaweza kuonyeshwa katika arifa au pato la CLI + +**Hatua za kuzuia**: +Usiandike maadili ya tokeni (andika tu "uthibitishaji umeanzishwa: ndiyo/hapana") +Amri ya CLI ya kuonyesha inaonyesha hali iliyofichwa tu, sio tokeni halisi +Usijumuishe tokeni katika ujumbe wa hitilafu + +### Usalama wa Mtandao +**Hatari**: Tokeni zinafutwa kupitia miunganisho isiyo salama + +**Hatua za kuzuia**: +Andika pendekezo la kutumia URL za HTTPS kwa seva za MCP +Onya watumiaji kuhusu hatari ya usambazaji wa maandishi wazi na HTTP + +### Ufikiaji wa Usanidi +**Hatari**: Ufikiaji usioidhinishwa kwa mfumo wa usanidi unaoonyesha tokeni + +**Hatua za kuzuia**: +Andika umuhimu wa kuhakikisha ufikiaji wa mfumo wa usanidi +Pendekeza kanuni ya madaraka madogo kwa ufikiaji wa usanidi +Fikiria uandikaji wa matukio kwa mabadiliko ya usanidi (uboresho wa baadaye) + +### Mazingira ya Watumiaji Wengi +**Hatari**: Katika matukio ya watumiaji wengi, watumiaji wote wanashiriki anwani sawa za MCP + +**Kuelewa Hatari**: +Mtumiaji A na Mtumiaji B hutumia tokeni sawa wakati wa kufikia zana ya MCP +Seva ya MCP haiwezi kutofautisha kati ya watumiaji tofauti wa TrustGraph +Hakuna njia ya kutekeleza ruhusa au mipaka ya kiwango cha mtumiaji +Arifa kwenye seva ya MCP zinaonyesha maombi yote kutoka kwa anwani sawa +Ikiwa kikao cha mtumiaji mmoja kimebanwa, mshambuliaji ana ufikiaji sawa wa MCP kama watumiaji wote + +**HII SI hitilafu - ni kikomo cha msingi cha muundo huu.** + +## Athari ya Utendaji +**Mzigo mdogo**: Ujenzi wa kichwa unaongeza muda mdogo wa usindikaji +**Athari ya mtandao**: Kichwa cha ziada cha HTTP huongeza ~50-200 baiti kwa ombi +**Matumizi ya kumbukumbu**: Kuongezeka kwa kiasi kidogo kwa kuhifadhi mnyororo wa tokeni katika usanidi + +## Nyaraka + +### Nyaraka za Mtumiaji +[ ] Sasisha `tg-set-mcp-tool.md` na parameter ya `--auth-token` +[ ] Ongeza sehemu ya mambo ya usalama +[ ] Toa mfano wa matumizi na tokeni ya mfuata +[ ] Andika madhumuni ya uhifadhi wa tokeni + +### Nyaraka za Msanidi Programu +[ ] Ongeza maelezo ya ndani kwa usimamizi wa tokeni ya uthibitishaji katika `service.py` +[ ] Andika mantiki ya ujenzi wa kichwa +[ ] Sasisha nyaraka za schema ya usanidi ya zana ya MCP + +## Maswali ya Funguo +1. **Usimbaji wa tokeni**: Je, tunapaswa kutekeleza uhifadhi uliosimbwa wa tokeni katika mfumo wa usanidi? +2. **Urekebishaji wa tokeni**: Usaidizi wa siku zijazo kwa mtiririko wa OAuth wa urekebishaji au mzunguko wa tokeni? +3. **Njia mbadala za uthibitishaji**: Je, tunapaswa kusaidia uthibitishaji wa Msingi, ufunguo wa API, au mbinu zingine? + +## Mbadala Zilizozingatiwa + +1. **Vigezo vya mazingira kwa tokeni**: Hifadhi tokeni katika vigezo vya mazingira badala ya usanidi + **Ilikataliwa**: Inachanganya usakinishaji na usimamizi wa usanidi + +2. **Hifadhi ya siri tofauti**: Tumia mfumo maalum wa usimamizi wa siri + **Imeahirishwa**: Nje ya upeo wa utekelezaji wa awali, fikiria uboreshaji wa siku zijazo + +3. **Njia nyingi za uthibitishaji**: Kusaidia Msingi, ufunguo wa API, OAuth, n.k. + **Ilikataliwa**: Tokeni za mfuata hufunika matumizi mengi, endeleza utekelezaji wa awali rahisi + +4. **Uhifadhi uliosimbwa wa tokeni**: Simba tokeni katika mfumo wa usanidi + **Imeahirishwa**: Usalama wa mfumo wa usanidi ni suala pana, chelewesha hadi kazi ya baadaye + +5. **Tokeni za kila utendaji**: Ruhusu tokeni kupitishwa wakati wa utendaji + **Ilikataliwa**: Inakiuka utengano wa masuala, wakala haupaswi kushughulikia anwani + +## Marejeleo +[Maelezo ya Protokali ya MCP](https://github.com/modelcontextprotocol/spec) +[Uthibitishaji wa Mfuata wa HTTP (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[Huduma ya Zana ya MCP ya Sasa](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[Maelezo ya Majadilisho ya Zana ya MCP](./mcp-tool-arguments.md) + +## Toa Maelezo + +### Matumizi ya Kifaa + +**Kuanzisha zana ya MCP pamoja na uthibitishaji:** +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Kuonyesha zana za MCP**: +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### Mfano wa Usanidi + +**Imehifadhiwa katika mfumo wa usanidi:** +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### Mbinu Bora za Usalama + +1. **Tumia HTTPS**: Daima tumia anwani za mtandao (URLs) za HTTPS kwa seva za MCP zenye uthibitishaji. +2. **Alama za muda mfupi**: Tumia alama (tokens) zenye muda wa kumalizika unapowezekana. +3. **Haki ndogo zaidi**: Toa alama ruhusa ndogo zaidi zinazohitajika. +4. **Kidhibiti cha ufikiaji**: Punguza ufikiaji kwenye mfumo wa usanidi. +5. **Kubadilisha alama**: Badilisha alama mara kwa mara. +6. **Uandikaji wa matukio**: Fuatilia mabadiliko ya usanidi ili kutambua matukio ya usalama. diff --git a/docs/tech-specs/mcp-tool-bearer-token.tr.md b/docs/tech-specs/mcp-tool-bearer-token.tr.md new file mode 100644 index 00000000..b1932d69 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.tr.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "MCP Aracı Taşıyıcı (Bearer) Token Doğrulama Özelliği Belirtimi" +parent: "Turkish (Beta)" +--- + +# MCP Aracı Taşıyıcı (Bearer) Token Doğrulama Özelliği Belirtimi + +> **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. + +> **⚠️ ÖNEMLİ: YALNIZCA TEK-KİRACI (SINGLE-TENANT) ORTAMLAR İÇİN** +> +> Bu belirtim, MCP araçları için temel, hizmet seviyesinde bir doğrulama mekanizmasını açıklamaktadır. Bu, **TAMAMLANMIŞ** bir doğrulama çözümü değildir ve aşağıdaki durumlar için **UYGUN DEĞİL**: +> - Çok kullanıcılı ortamlar +> - Çok kiracılı (multi-tenant) dağıtımlar +> - Federasyonlu doğrulama +> - Kullanıcı bağlamı yayılımı +> - Kullanıcı bazlı yetkilendirme +> +> Bu özellik, her MCP aracı için **tek bir statik token** sağlar ve bu token tüm kullanıcılar ve oturumlar arasında paylaşılır. Kullanıcı bazlı veya kiracı bazlı doğrulama gerekiyorsa, bu çözüm uygun değildir. + +## Genel Bakış +**Özellik Adı**: MCP Aracı Taşıyıcı (Bearer) Token Doğrulama Desteği +**Yazar**: Claude Code Assistant +**Tarih**: 2025-11-11 +**Durum**: Geliştirme Aşamasında + +### Yönetici Özeti + +MCP araçlarının, korumalı MCP sunucularıyla kimlik doğrulaması yapmak için isteğe bağlı taşıyıcı (bearer) token'lar belirtmesine olanak tanıyın. Bu, TrustGraph'ın, kimlik doğrulaması gerektiren sunucularda barındırılan MCP araçlarını, aracının veya araç çağrı arayüzlerinin değiştirilmesi olmadan güvenli bir şekilde çağırmasını sağlar. + +**ÖNEMLİ**: Bu, tek kiracılı, hizmetten hizmete doğrulama senaryoları için tasarlanmış temel bir doğrulama mekanizmasıdır. Aşağıdaki durumlar için **UYGUN DEĞİL**: +Farklı kullanıcıların farklı kimlik bilgilerine ihtiyaç duyduğu çok kullanıcılı ortamlar +Kiracı başına izolasyon gerektiren çok kiracılı dağıtımlar +Federasyonlu doğrulama senaryoları +Kullanıcı seviyesinde doğrulama veya yetkilendirme +Dinamik kimlik bilgisi yönetimi veya token yenileme + +Bu özellik, her MCP aracı yapılandırması için statik, sistem genelinde bir taşıyıcı (bearer) token sağlar ve bu token, o aracın tüm kullanıcıları ve çağrıları tarafından paylaşılır. + +### Sorun Tanımı + +Şu anda, MCP araçları yalnızca herkese açık olarak erişilebilir MCP sunucularına bağlanabilir. Birçok üretim MCP dağıtımı, güvenlik için taşıyıcı (bearer) token'lar aracılığıyla kimlik doğrulaması gerektirir. Kimlik doğrulama desteği olmadan: +MCP araçları, güvenli MCP sunucularına bağlanamaz +Kullanıcılar ya MCP sunucularını herkese açık hale getirmeli ya da ters vekil (reverse proxy) uygulamalıdır +MCP bağlantılarına kimlik bilgilerini iletmenin standart bir yolu yoktur +MCP uç noktalarında güvenlik en iyi uygulamaları uygulanamaz + +### Hedefler + +[ ] MCP araç yapılandırmalarının isteğe bağlı `auth-token` parametresini belirtmesine izin verin +[ ] MCP araç hizmetini, MCP sunucularına bağlanırken taşıyıcı (bearer) token'ları kullanacak şekilde güncelleyin +[ ] CLI araçlarını, kimlik doğrulama token'larını ayarlama/görüntüleme özelliğini destekleyecek şekilde güncelleyin +[ ] Kimlik doğrulaması olmayan MCP yapılandırmalarıyla geriye dönük uyumluluğu koruyun +[ ] Token depolama için güvenlik hususlarını belgeleyin + +### Hedef Dışı Kalanlar +Dinamik token yenileme veya OAuth akışları (yalnızca statik token'lar) +Depolanmış token'ların şifrelenmesi (yapılandırma sistemi güvenliği kapsam dışındadır) +Alternatif doğrulama yöntemleri (Temel kimlik doğrulama, API anahtarları, vb.) +Token doğrulama veya son kullanma kontrolü +**Kullanıcı başına doğrulama**: Bu özellik, kullanıcıya özel kimlik bilgilerini desteklemez +**Kiracı izolasyonu**: Bu özellik, kiracı başına token yönetimi sağlamaz +**Federasyonlu doğrulama**: Bu özellik, kimlik sağlayıcılarıyla (SSO, OAuth, SAML, vb.) entegre olmaz +**Bağlama duyarlı doğrulama**: Token'lar, kullanıcı bağlamına veya oturuma göre iletilmez + +## Arka Plan ve Bağlam + +### Mevcut Durum +MCP araç yapılandırmaları, `mcp` yapılandırma grubunda aşağıdaki yapıya sahip olarak saklanır: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +MCP aracı hizmeti, `streamablehttp_client(url)` kullanarak sunuculara bağlanır ve herhangi bir kimlik doğrulama başlığı kullanmaz. + +### Sınırlamalar + +**Mevcut Sistem Sınırlamaları:** +1. **Kimlik doğrulama desteği yok:** Güvenli MCP sunucularına bağlanılamaz. +2. **Güvenlik açığı:** MCP sunucuları, yalnızca ağ seviyesinde güvenlik kullanılarak genel olarak erişilebilir olmalıdır. +3. **Üretim dağıtım sorunları:** API uç noktaları için güvenlik en iyi uygulamalarını takip edilemez. + +**Bu Çözümün Sınırlamaları:** +1. **Yalnızca tek kiracı:** Her MCP aracı için tek bir statik belirteç, tüm kullanıcılar arasında paylaşılır. +2. **Kullanıcı başına kimlik bilgileri yok:** Farklı kullanıcılar olarak kimlik doğrulaması yapılamaz veya kullanıcı bağlamı geçirilemez. +3. **Çok kiracılı destek yok:** Kimlik bilgilerini kiracı veya kuruluş başına izole etmek mümkün değildir. +4. **Yalnızca statik belirteçler:** Belirteç yenileme, döndürme veya son kullanma süresi yönetimi desteği yoktur. +5. **Hizmet seviyesi kimlik doğrulaması:** Bireysel kullanıcılar yerine TrustGraph hizmetini doğrular. +6. **Paylaşılan güvenlik bağlamı:** Bir MCP aracının tüm çağrıları aynı kimlik bilgisini kullanır. + +### Kullanım Alanı Uygunluğu + +**✅ Uygun Kullanım Alanları:** +Tek kiracılı TrustGraph dağıtımları +Hizmetten hizmete kimlik doğrulama (TrustGraph → MCP Sunucusu) +Geliştirme ve test ortamları +TrustGraph sistemi tarafından erişilen dahili MCP araçları +Tüm kullanıcıların aynı MCP aracı erişim düzeyini paylaştığı senaryolar +Statik, uzun ömürlü hizmet kimlik bilgileri + +**❌ Uygun Olmayan Kullanım Alanları:** +Kullanıcı başına kimlik doğrulama gerektiren çok kullanıcılı sistemler +Kiracı izolasyonu gereksinimleri olan çok kiracılı SaaS dağıtımları +Federasyon kimlik doğrulama senaryoları (SSO, OAuth, SAML) +MCP sunucularına kullanıcı bağlamının iletilmesi gereken sistemler +Dinamik belirteç yenileme veya kısa ömürlü belirteçler gerektiren ortamlar +Farklı kullanıcıların farklı izin düzeylerine ihtiyaç duyduğu uygulamalar +Kullanıcı seviyesinde denetim izleri için uyumluluk gereksinimleri + +**Örnek Uygun Senaryo:** +Tüm çalışanların aynı dahili MCP aracını (örneğin, şirket veritabanı sorgusu) kullandığı tek organizasyonlu bir TrustGraph dağıtımı. MCP sunucusunun harici erişimi önlemek için kimlik doğrulama gerektirmesi, ancak tüm dahili kullanıcıların aynı erişim düzeyine sahip olması. + +**Örnek Uygun Olmayan Senaryo:** +Kiracı A ve Kiracı B'nin her birinin ayrı kimlik bilgileriyle kendi izole MCP sunucularına erişmesi gereken çok kiracılı bir TrustGraph SaaS platformu. Bu özellik, kiracı başına belirteç yönetimi DEĞİLDİR. + +### İlgili Bileşenler +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: MCP aracı çağrı hizmeti +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: MCP yapılandırmalarını oluşturmak/güncellemek için CLI aracı +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: MCP yapılandırmalarını görüntülemek için CLI aracı +**MCP Python SDK**: `streamablehttp_client` from `mcp.client.streamable_http` + +## Gereksinimler + +### Fonksiyonel Gereksinimler + +1. **MCP Yapılandırma Kimlik Doğrulama Belirteci**: MCP aracı yapılandırmaları, isteğe bağlı bir `auth-token` alanı DESTEKLEMELİDİR. +2. **Bearer Belirteç Kullanımı**: MCP aracı hizmeti, kimlik doğrulama belirteci yapılandırıldığında `Authorization: Bearer {token}` başlığını GÖNDERMELİDİR. +3. **CLI Desteği**: `tg-set-mcp-tool`, isteğe bağlı bir `--auth-token` parametresi KABUL ETMELİDİR. +4. **Belirteç Görüntüleme**: `tg-show-mcp-tools`, kimlik doğrulama belirtecinin yapılandırıldığını GÖSTERMELİDİR (güvenlik için gizlenmiş). +5. **Geriye Dönük Uyumluluk**: Kimlik doğrulama belirteci olmayan mevcut MCP aracı yapılandırmaları çalışmaya DEVAM ETMELİDİR. + +### Fonksiyonel Olmayan Gereksinimler +1. **Geriye Dönük Uyumluluk**: Mevcut MCP aracı yapılandırmaları için hiçbir bozucu değişiklik olmamalıdır. +2. **Performans**: MCP aracı çağrısı üzerinde önemli bir performans etkisi olmamalıdır. +3. **Güvenlik**: Belirteçler yapılandırmada saklanır (güvenlik etkilerini belgeleyin). + +### Kullanıcı Hikayeleri + +1. Bir **DevOps mühendisi** olarak, MCP sunucusu uç noktalarını güvence altına almak için MCP araçları için taşıyıcı belirteçleri yapılandırmak istiyorum. +2. Bir **CLI kullanıcısı** olarak, korumalı sunuculara bağlanabilmem için MCP araçları oluştururken kimlik doğrulama belirteçleri ayarlamak istiyorum. +3. Bir **sistem yöneticisi** olarak, hangi MCP araçlarının kimlik doğrulamasının yapılandırıldığını görmek istiyorum, böylece güvenlik ayarlarını denetleyebilirim. + +## Tasarım + +### Yüksek Seviyeli Mimari +Taşıyıcı belirteç kimlik doğrulaması desteği için MCP aracı yapılandırmasını ve hizmetini genişletin: +1. MCP aracı yapılandırma şemasına isteğe bağlı bir `auth-token` alanı ekleyin. +2. Kimlik doğrulama belirteci yapılandırıldığında, MCP aracı hizmetinin kimlik doğrulama belirteci okuyup HTTP istemcisine iletmesini sağlayın. +3. Kimlik doğrulama belirteçleri ayarlamak ve görüntülemek için CLI araçlarını güncelleyin. +4. Güvenlik hususlarını ve en iyi uygulamaları belgeleyin. + +### Yapılandırma Şeması + +**Mevcut Şema**: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**Yeni Şema** (isteğe bağlı kimlik doğrulama jetonu ile): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**Alan Açıklamaları**: +`remote-name` (isteğe bağlı): MCP sunucusu tarafından kullanılan isim (varsayılan olarak yapılandırma anahtarı) +`url` (gerekli): MCP sunucusu uç noktası URL'si +`auth-token` (isteğe bağlı): Kimlik doğrulama için kullanılan taşıyıcı belirteci + +### Veri Akışı + +1. **Yapılandırma Depolama**: Kullanıcı `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123`'ı çalıştırır +2. **Yapılandırma Yükleme**: MCP aracı hizmeti, `on_mcp_config()` geri çağırması aracılığıyla yapılandırma güncellemelerini alır +3. **Araç Çağrısı**: Araç çağrıldığında: + Hizmet, yapılandırmadan `auth-token`'ı okur (varsa) + Başlıklar sözlüğünü oluşturur: `{"Authorization": "Bearer {token}"}` + Başlıkları `streamablehttp_client(url, headers=headers)`'a iletir + MCP sunucusu belirteci doğrular ve isteği işler + +### API Değişiklikleri +Harici API değişiklikleri yok - yalnızca yapılandırma şeması uzantısı. + +### Bileşen Detayları + +#### Bileşen 1: service.py (MCP Aracı Hizmeti) +**Dosya**: `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**Amaç**: Uzak sunuculardaki MCP araçlarını çağırmak + +**Gerekli Değişiklikler** (`invoke_tool()` yönteminde): +1. `auth-token`'ın `self.mcp_services[name]` yapılandırmasında olup olmadığını kontrol edin +2. Belirteç varsa, Authorization başlığıyla başlıklar sözlüğünü oluşturun +3. Başlıkları `streamablehttp_client(url, headers=headers)`'a iletin + +**Mevcut Kod** (42-89 satırları): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**Değiştirilmiş Kod:** +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### Bileşen 2: set_mcp_tool.py (CLI Yapılandırma Aracı) +**Dosya**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**Amaç**: MCP aracı yapılandırmalarını oluşturma/güncelleme + +**Gerekli Değişiklikler**: +1. `--auth-token` isteğe bağlı argümanı argparse'a ekleyin +2. Sağlandığında, `auth-token`'yi yapılandırma JSON'una dahil edin + +**Mevcut Argümanlar**: +`--id` (gerekli): MCP aracı tanımlayıcısı +`--remote-name` (isteğe bağlı): Uzak MCP aracı adı +`--tool-url` (gerekli): MCP aracı URL uç noktası +`-u, --api-url` (isteğe bağlı): TrustGraph API URL'si + +**Yeni Argüman**: +`--auth-token` (isteğe bağlı): Kimlik doğrulama için taşıyıcı belirteci + +**Değiştirilmiş Yapılandırma Oluşturma**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### Bileşen 3: show_mcp_tools.py (CLI Görüntüleme Aracı) +**Dosya**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**Amaç**: MCP araç yapılandırmalarını görüntülemek + +**Gerekli Değişiklikler**: +1. Çıktı tablosuna "Auth" sütununu ekleyin +2. "auth-token" varlığına bağlı olarak "Evet" veya "Hayır" görüntüleyin +3. Gerçek token değerini görüntülemeyin (güvenlik) + +**Mevcut Çıktı**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**Yeni Çıktı**: +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### Bileşen 4: Belgeler +**Dosya**: `docs/cli/tg-set-mcp-tool.md` + +**Gerekli Değişiklikler**: +1. Yeni `--auth-token` parametresini belgeleyin +2. Kimlik doğrulama ile örnek kullanım sağlayın +3. Güvenlik hususlarını belgeleyin + +## Uygulama Planı + +### Aşama 1: Teknik Özellikleri Oluşturma +[x] Tüm değişiklikleri belgeleyen kapsamlı bir teknik özellik yazın + +### Aşama 2: MCP Araç Hizmetini Güncelleme +[ ] `service.py` içindeki `invoke_tool()`'ı, auth-token'ı yapılandırmadan okumak için değiştirin +[ ] Başlıklar sözlüğünü oluşturun ve `streamablehttp_client`'a iletin +[ ] Kimliği doğrulanmış bir MCP sunucusuyla test edin + +### Aşama 3: CLI Araçlarını Güncelleme +[ ] `set_mcp_tool.py`'e `--auth-token` argümanını ekleyin +[ ] auth-token'ı yapılandırma JSON'unda dahil edin +[ ] `show_mcp_tools.py` çıktısına "Auth" sütununu ekleyin +[ ] CLI araç değişikliklerini test edin + +### Aşama 4: Belgeleri Güncelleme +[ ] `tg-set-mcp-tool.md` içindeki `--auth-token` parametresini belgeleyin +[ ] Güvenlik hususları bölümünü ekleyin +[ ] Örnek kullanım sağlayın + +### Aşama 5: Test +[ ] MCP aracının auth-token ile başarıyla bağlandığını test edin +[ ] Geriye dönük uyumluluğu test edin (auth-token olmadan çalışan araçlar) +[ ] CLI araçlarının auth-token'ı doğru şekilde kabul ettiğini ve depoladığını test edin +[ ] "show" komutunun auth durumunu doğru şekilde gösterdiğini test edin + +### Kod Değişiklikleri Özeti +| Dosya | Değişiklik Türü | Satırlar | Açıklama | +|------|------------|-------|-------------| +| `service.py` | Değiştirildi | ~52-66 | auth-token okuma ve başlık oluşturma ekleyin | +| `set_mcp_tool.py` | Değiştirildi | ~30-60 | --auth-token argümanı ve yapılandırma depolama ekleyin | +| `show_mcp_tools.py` | Değiştirildi | ~40-70 | Görüntüleme için "Auth" sütununu ekleyin | +| `tg-set-mcp-tool.md` | Değiştirildi | Çeşitli | Yeni parametreyi belgeleyin | + +## Test Stratejisi + +### Birim Testleri +**Auth Token Okuma**: `invoke_tool()`'ın auth-token'ı yapılandırmadan doğru şekilde okuduğunu test edin +**Başlık Oluşturma**: Authorization başlığının Bearer öneki ile doğru şekilde oluşturulduğunu test edin +**Geriye Dönük Uyumluluk**: auth-token olmadan çalışan araçların değişmeden çalıştığını test edin +**CLI Argümanı Ayrıştırma**: `--auth-token` argümanının doğru şekilde ayrıştırıldığını test edin + +### Entegrasyon Testleri +**Kimliği Doğrulanmış Bağlantı**: MCP araç hizmetinin kimliği doğrulanmış bir sunucuya bağlandığını test edin +**Uçtan Uca**: CLI → yapılandırma depolama → auth token ile hizmet çağrısını test edin +**Token Gerekli Değil**: Kimliği doğrulanmamış bir sunucuya bağlantının hala çalıştığını test edin + +### Manuel Testler +**Gerçek MCP Sunucusu**: bearer token kimlik doğrulaması gerektiren gerçek bir MCP sunucusuyla test edin +**CLI İş Akışı**: Tam iş akışını test edin: aracı auth ile yapılandır → aracı çağır → başarıyı doğrulayın +**Görüntü Maskeleme**: auth durumunun gösterildiğini ancak token değerinin görünmediğini doğrulayın + +## Göç ve Dağıtım + +### Göç Stratejisi +Göç gerektirmez - bu tamamen ek bir işlevsellik: +`auth-token` içermeyen mevcut MCP araç yapılandırmaları çalışmaya devam eder +Yeni yapılandırmalar isteğe bağlı olarak `auth-token` alanını içerebilir +CLI araçları `--auth-token` parametresini kabul eder, ancak gerektirmez + +### Dağıtım Planı +1. **Aşama 1**: Temel hizmet değişikliklerini geliştirme/hazırlık ortamına dağıtın +2. **Aşama 2**: CLI araç güncellemelerini dağıtın +3. **Aşama 3**: Belgeleri güncelleyin +4. **Aşama 4**: İzleme ile üretim dağıtımı + +### Geri Alma Planı +Temel değişiklikler geriye dönük uyumludur - mevcut araçlar etkilenmez +Sorunlar ortaya çıkarsa, auth-token işleme, başlık oluşturma mantığını kaldırarak devre dışı bırakılabilir +CLI değişiklikleri bağımsızdır ve ayrı olarak geri alınabilir + +## Güvenlik Hususları + +### ⚠️ Kritik Sınırlama: Yalnızca Tek Kiracılı Kimlik Doğrulama + +**Bu kimlik doğrulama mekanizması, çok kullanıcılı veya çok kiracılı ortamlar için UYGUN DEĞİLDİR.** + +**Paylaşılan kimlik bilgiler**: Tüm kullanıcılar ve çağrılar, her MCP aracı için aynı token'ı paylaşır +**Kullanıcı bağlamı yok**: MCP sunucusu, farklı TrustGraph kullanıcıları arasında ayrım yapamaz +**Kiracı yalıtımı yok**: Tüm kiracılar, her MCP aracı için aynı kimlik bilgilerini paylaşır +**Denetim izi sınırlaması**: MCP sunucusu, aynı kimlik bilgilerinden gelen tüm istekleri günlüğe kaydeder +**İzin kapsamı**: Farklı kullanıcılara farklı izin seviyeleri uygulanamaz + +**Bu özelliği KULLANMAYIN eğer:** +TrustGraph dağıtımınız birden fazla kuruluşu (çok kiracılı) hizmet veriyorsa +Hangi kullanıcının hangi MCP aracına eriştiğini izlemeniz gerekiyorsa +Farklı kullanıcıların farklı izin seviyelerine ihtiyacı varsa +Kullanıcı düzeyinde denetim gereksinimlerine uymanız gerekiyorsa +MCP sunucunuz kullanıcı başına hız sınırlamaları veya kotaları uyguluyorsa + +**Çok kullanıcılı/çok kiracılı senaryolar için alternatif çözümler:** +Özel başlıklar aracılığıyla kullanıcı bağlamı yayılımını uygulayın +Her kiracı için ayrı TrustGraph örnekleri dağıtın +Ağ seviyesinde izolasyon kullanın (VPC'ler, hizmet ağları) +Her kullanıcı için kimlik doğrulamayı yöneten bir ara katman uygulayın + +### Token Depolama +**Risk**: Kimlik doğrulama jetonları yapılandırma sisteminde düz metin olarak saklanır + +**Giderilmesi Gereken Durum:** +Jetonların şifrelenmeden saklandığını belgeleyin +Mümkün olduğunda kısa ömürlü jetonlar kullanılması önerin +Yapılandırma depolaması için uygun erişim kontrolü kullanılması önerin +Şifrelenmiş jeton depolama için gelecekteki bir iyileştirmeyi düşünün + +### Jetonun Açığa Çıkarılması +**Risk**: Jetonlar günlüklerde veya CLI çıktısında açığa çıkabilir + +**Giderilmesi Gereken Durum:** +Jeton değerlerini kaydetmeyin (sadece "kimlik doğrulama yapılandırıldı: evet/hayır" kaydını tutun) +CLI göster komutu yalnızca maskelenmiş durumu gösterir, gerçek jetonu göstermez +Jetonları hata mesajlarında dahil etmeyin + +### Ağ Güvenliği +**Risk**: Jetonlar şifrelenmemiş bağlantılar üzerinden iletilir + +**Giderilmesi Gereken Durum:** +MCP sunucuları için HTTPS URL'lerinin kullanılması önerisi belgelendirilmelidir +HTTP ile düz metin iletim riskine ilişkin kullanıcılara uyarı verilmelidir + +### Yapılandırma Erişimi +**Risk**: Yapılandırma sistemine yetkisiz erişim, jetonları açığa çıkarır + +**Giderilmesi Gereken Durum:** +Yapılandırma sistemi erişiminin güvenliğinin önemini belgeleyin +Yapılandırma erişimi için en az ayrıcalık ilkesi önerin +Yapılandırma değişiklikleri için denetim günlüğü almayı düşünün (gelecekteki iyileştirme) + +### Çok Kullanıcılı Ortamlar +**Risk**: Çok kullanıcılı dağıtımlarda, tüm kullanıcılar aynı MCP kimlik bilgilerini paylaşır + +**Riskin Anlaşılması:** +Kullanıcı A ve Kullanıcı B, bir MCP aracını kullanırken aynı jetonu kullanır +MCP sunucusu, farklı TrustGraph kullanıcıları arasında ayrım yapamaz +Kullanıcı başına izinleri veya hız sınırlamalarını uygulama imkanı yoktur +MCP sunucusundaki denetim günlükleri, aynı kimlik bilgilerinden gelen tüm istekleri gösterir +Bir kullanıcının oturumu tehlikeye girerse, saldırganın tüm kullanıcılar kadar aynı MCP erişimi vardır + +**Bu bir hata DEĞİLDİR - bu tasarımın temel bir sınırlamasıdır.** + +## Performans Etkisi +**Minimum ek yük**: Başlık oluşturma, ihmal edilebilir bir işlem süresi ekler +**Ağ etkisi**: Ek HTTP başlığı, istek başına yaklaşık 50-200 bayt ekler +**Bellek kullanımı**: Yapılandırmada jeton dizesini depolamak için ihmal edilebilir bir artış + +## Belgeler + +### Kullanıcı Belgeleri +[ ] `tg-set-mcp-tool.md`'ı `--auth-token` parametresiyle güncelleyin +[ ] Güvenlik hususları bölümü ekleyin +[ ] Bir örnek kullanım senaryosuyla birlikte taşıyıcı jetonu sağlayın +[ ] Jeton depolama etkilerini belgeleyin + +### Geliştirici Belgeleri +[ ] `service.py` içindeki kimlik doğrulama jetonu işleme için satır içi yorumlar ekleyin +[ ] Başlık oluşturma mantığını belgeleyin +[ ] MCP aracı yapılandırma şeması belgelerini güncelleyin + +## Açık Sorular +1. **Jeton şifreleme**: Yapılandırma sisteminde şifrelenmiş jeton depolamayı uygulamalı mıyız? +2. **Jeton yenileme**: OAuth yenileme akışları veya jeton rotasyonu için gelecekteki destek? +3. **Alternatif kimlik doğrulama yöntemleri**: Temel kimlik doğrulama, API anahtarları veya diğer yöntemleri desteklemeli miyiz? + +## Değerlendirilen Alternatifler + +1. **Jetonlar için ortam değişkenleri**: Jetonları yapılandırma yerine ortam değişkenlerinde saklayın + **Reddedildi**: Dağıtımı ve yapılandırma yönetimini karmaşıklaştırır + +2. **Ayrı gizli anahtar deposu**: Özel bir gizli anahtar yönetim sistemi kullanın + **Erteleme**: Başlangıç uygulaması kapsamı dışındadır, gelecekteki bir iyileştirme olarak düşünün + +3. **Çoklu kimlik doğrulama yöntemleri**: Temel, API anahtarı, OAuth vb. destekleyin + **Reddedildi**: Taşıyıcı jetonlar çoğu kullanım durumunu kapsar, başlangıç uygulamasını basit tutun + +4. **Şifrelenmiş jeton depolama**: Jetonları yapılandırma sisteminde şifreleyin + **Erteleme**: Yapılandırma sistemi güvenliği daha geniş bir endişedir, gelecekteki çalışmalara bırakın + +5. **Her çağrı için jetonlar**: Jetonların çağrı zamanında geçirilmesine izin verin + **Reddedildi**: Endişe ayrımını ihlal eder, aracının kimlik bilgilerini işlemesi gerekmez + +## Referanslar +[MCP Protokolü Özellikleri](https://github.com/modelcontextprotocol/spec) +[HTTP Taşıyıcı Kimlik Doğrulaması (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[Mevcut MCP Aracı Hizmeti](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[MCP Aracı Argümanları Özellikleri](./mcp-tool-arguments.md) + +## Ek + +### Örnek Kullanım + +**Kimlik doğrulama ile MCP aracının yapılandırılması:** +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**MCP araçlarını göster:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### Yapılandırma Örneği + +**Yapılandırma sisteminde saklanır**: +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### Güvenlik En İyi Uygulamaları + +1. **HTTPS Kullanımı**: Kimlik doğrulama ile çalışan MCP sunucuları için her zaman HTTPS URL'lerini kullanın. +2. **Kısa Ömürlü Token'lar**: Mümkün olduğunda, son kullanma tarihine sahip token'lar kullanın. +3. **En Az Yetki**: Token'lara, yalnızca gerekli olan minimum izinleri verin. +4. **Erişim Kontrolü**: Yapılandırma sistemine erişimi kısıtlayın. +5. **Token Döndürme**: Token'ları düzenli olarak değiştirin. +6. **Denetim Kayıtları**: Güvenlik olayları için yapılandırma değişikliklerini izleyin. diff --git a/docs/tech-specs/mcp-tool-bearer-token.zh-cn.md b/docs/tech-specs/mcp-tool-bearer-token.zh-cn.md new file mode 100644 index 00000000..6241d156 --- /dev/null +++ b/docs/tech-specs/mcp-tool-bearer-token.zh-cn.md @@ -0,0 +1,562 @@ +--- +layout: default +title: "MCP 工具承载令牌身份验证规范" +parent: "Chinese (Beta)" +--- + +# MCP 工具承载令牌身份验证规范 + +> **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. + +> **⚠️ 重要提示:仅限单租户环境** +> +> 本规范描述了一种用于 MCP 工具的**基本服务级别身份验证机制**。它**不是**一个完整的身份验证解决方案,**不适用于**以下情况: +> - 多用户环境 +> - 多租户部署 +> - 联合身份验证 +> - 用户上下文传播 +> - 基于用户的授权 +> +> 此功能为**每个 MCP 工具提供一个静态令牌**,该令牌在所有用户和会话中共享。 如果您需要基于用户的身份验证或基于租户的身份验证,则此功能不适合您。 + +## 概述 +**功能名称**: MCP 工具承载令牌身份验证支持 +**作者**: Claude 代码助手 +**日期**: 2025-11-11 +**状态**: 正在开发中 + +### 执行摘要 + +允许 MCP 工具配置指定可选的承载令牌,用于对受保护的 MCP 服务器进行身份验证。 这允许 TrustGraph 安全地调用托管在需要身份验证的服务器上的 MCP 工具,而无需修改代理或工具调用接口。 + +**重要提示**: 这是一个基本身份验证机制,旨在用于单租户、服务到服务的身份验证场景。 它**不适用于**以下情况: +需要不同用户凭据的多用户环境 +需要每个租户隔离的多租户部署 +联合身份验证场景 +基于用户的身份验证或授权 +动态凭据管理或令牌刷新 + +此功能为每个 MCP 工具配置提供一个静态、系统范围的承载令牌,该令牌在所有用户和该工具的调用中共享。 + +### 问题陈述 + +目前,MCP 工具只能连接到公共可访问的 MCP 服务器。 许多生产 MCP 部署需要通过承载令牌进行身份验证以提高安全性。 如果没有身份验证支持: +MCP 工具无法连接到受保护的 MCP 服务器 +用户必须要么公开 MCP 服务器,要么实现反向代理 +没有一种标准化的方法将凭据传递给 MCP 连接 +无法在 MCP 终端节点上强制执行安全最佳实践 + +### 目标 + +[ ] 允许 MCP 工具配置指定可选的 `auth-token` 参数 +[ ] 更新 MCP 工具服务,使其在连接到 MCP 服务器时使用承载令牌 +[ ] 更新 CLI 工具以支持设置/显示身份验证令牌 +[ ] 保持与未进行身份验证的 MCP 配置的向后兼容性 +[ ] 记录令牌存储的安全注意事项 + +### 非目标 +动态令牌刷新或 OAuth 流程(仅限静态令牌) +存储令牌的加密(配置系统安全性不在范围之内) +替代身份验证方法(基本身份验证、API 密钥等) +令牌验证或到期检查 +**基于用户的身份验证**: 此功能**不支持**用户特定的凭据 +**多租户隔离**: 此功能**不提供**基于租户的令牌管理 +**联合身份验证**: 此功能**不与**身份提供商(SSO、OAuth、SAML 等)集成 +**基于上下文的身份验证**: 令牌不是基于用户上下文或会话传递的 + +## 背景和上下文 + +### 当前状态 +MCP 工具配置存储在 `mcp` 配置组中,具有以下结构: +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +MCP 工具服务使用 `streamablehttp_client(url)` 连接到服务器,而无需任何身份验证头信息。 + +### 限制 + +**当前系统限制:** +1. **不支持身份验证:** 无法连接到需要身份验证的 MCP 服务器。 +2. **安全风险:** MCP 服务器必须是公开可访问的,或者仅使用网络级别的安全措施。 +3. **生产部署问题:** 无法遵循 API 端点的安全最佳实践。 + +**此解决方案的限制:** +1. **仅支持单租户:** 每个 MCP 工具只有一个静态令牌,所有用户共享该令牌。 +2. **不支持按用户身份验证:** 无法以不同的用户身份进行身份验证,也无法传递用户上下文。 +3. **不支持多租户:** 无法按租户或组织隔离凭据。 +4. **仅支持静态令牌:** 不支持令牌刷新、轮换或过期处理。 +5. **服务级别身份验证:** 仅对 TrustGraph 服务进行身份验证,而不是对单个用户进行身份验证。 +6. **共享安全上下文:** 对 MCP 工具的所有调用都使用相同的凭据。 + +### 使用场景适用性 + +**✅ 适用场景:** +单租户 TrustGraph 部署。 +服务到服务身份验证(TrustGraph → MCP 服务器)。 +开发和测试环境。 +TrustGraph 系统访问的内部 MCP 工具。 +所有用户共享相同 MCP 工具访问级别的场景。 +静态、长期有效的服务凭据。 + +**❌ 不适用场景:** +需要按用户身份验证的多用户系统。 +需要租户隔离的多租户 SaaS 部署。 +联合身份验证场景(SSO、OAuth、SAML)。 +需要将用户上下文传播到 MCP 服务器的系统。 +需要动态令牌刷新或短生命周期的令牌的环境。 +不同的用户需要不同权限级别的应用程序。 +用户级别审计跟踪的合规性要求。 + +**示例适用场景:** +单个组织的 TrustGraph 部署,其中所有员工都使用相同的内部 MCP 工具(例如,公司数据库查询)。MCP 服务器需要身份验证以防止外部访问,但所有内部用户都具有相同的访问级别。 + +**示例不适用场景:** +一个多租户 TrustGraph SaaS 平台,其中租户 A 和租户 B 需要访问各自隔离的 MCP 服务器,并使用不同的凭据。此功能不支持按租户管理令牌。 + +### 相关组件 +**trustgraph-flow/trustgraph/agent/mcp_tool/service.py**: MCP 工具调用服务。 +**trustgraph-cli/trustgraph/cli/set_mcp_tool.py**: 用于创建/更新 MCP 配置的 CLI 工具。 +**trustgraph-cli/trustgraph/cli/show_mcp_tools.py**: 用于显示 MCP 配置的 CLI 工具。 +**MCP Python SDK**: `streamablehttp_client` from `mcp.client.streamable_http` + +## 要求 + +### 功能性要求 + +1. **MCP 配置身份验证令牌:** MCP 工具配置必须支持一个可选的 `auth-token` 字段。 +2. **Bearer 令牌使用:** 当配置了 auth-token 时,MCP 工具服务必须发送 `Authorization: Bearer {token}` 头信息。 +3. **CLI 支持:** `tg-set-mcp-tool` 必须接受一个可选的 `--auth-token` 参数。 +4. **令牌显示:** `tg-show-mcp-tools` 必须指示是否配置了 auth-token(出于安全考虑,已屏蔽)。 +5. **向后兼容性:** 现有不带 auth-token 的 MCP 工具配置必须继续正常工作。 + +### 非功能性要求 +1. **向后兼容性:** 对于现有的 MCP 工具配置,不得有任何破坏性更改。 +2. **性能:** 对 MCP 工具的调用不会产生任何显著的性能影响。 +3. **安全性:** 令牌存储在配置中(请注意安全隐患)。 + +### 用户故事 + +1. 作为 **DevOps 工程师**,我希望配置 MCP 工具的 bearer 令牌,以便我可以保护 MCP 服务器端点。 +2. 作为 **CLI 用户**,我希望在创建 MCP 工具时设置身份验证令牌,以便我可以连接到受保护的服务器。 +3. 作为 **系统管理员**,我希望查看哪些 MCP 工具配置了身份验证,以便我可以审计安全设置。 + +## 设计 + +### 高级架构 +扩展 MCP 工具配置和服务以支持 bearer 令牌身份验证: +1. 向 MCP 工具配置模式添加一个可选的 `auth-token` 字段。 +2. 修改 MCP 工具服务以读取 auth-token 并将其传递给 HTTP 客户端。 +3. 更新 CLI 工具以支持设置和显示身份验证令牌。 +4. 记录安全注意事项和最佳实践。 + +### 配置模式 + +**当前模式:** +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api" +} +``` + +**新的模式**(带可选的认证令牌): +```json +{ + "remote-name": "tool_name", + "url": "http://mcp-server:3000/api", + "auth-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**字段描述**: +`remote-name` (可选): MCP 服务器使用的名称(默认为配置键) +`url` (必需): MCP 服务器端点 URL +`auth-token` (可选): 用于身份验证的 Bearer token + +### 数据流 + +1. **配置存储**: 用户运行 `tg-set-mcp-tool --id my-tool --tool-url http://server/api --auth-token xyz123` +2. **配置加载**: MCP 工具服务通过 `on_mcp_config()` 回调接收配置更新 +3. **工具调用**: 当工具被调用时: + 服务从配置中读取 `auth-token`(如果存在) + 创建 headers 字典:`{"Authorization": "Bearer {token}"}` + 将 headers 传递给 `streamablehttp_client(url, headers=headers)` + MCP 服务器验证 token 并处理请求 + +### API 变更 +没有外部 API 变更,仅为配置模式扩展。 + +### 组件详情 + +#### 组件 1: service.py (MCP 工具服务) +**文件**: `trustgraph-flow/trustgraph/agent/mcp_tool/service.py` + +**目的**: 在远程服务器上调用 MCP 工具 + +**所需变更**(在 `invoke_tool()` 方法中): +1. 检查 `auth-token` 是否在 `self.mcp_services[name]` 配置中 +2. 如果 token 存在,则构建包含 Authorization header 的 headers 字典 +3. 将 headers 传递给 `streamablehttp_client(url, headers=headers)` + +**当前代码**(42-89 行): +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server + async with streamablehttp_client(url) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method +``` + +**修改后的代码**: +```python +async def invoke_tool(self, name, parameters): + try: + if name not in self.mcp_services: + raise RuntimeError(f"MCP service {name} not known") + if "url" not in self.mcp_services[name]: + raise RuntimeError(f"MCP service {name} URL not defined") + + url = self.mcp_services[name]["url"] + + if "remote-name" in self.mcp_services[name]: + remote_name = self.mcp_services[name]["remote-name"] + else: + remote_name = name + + # Build headers with optional bearer token + headers = {} + if "auth-token" in self.mcp_services[name]: + token = self.mcp_services[name]["auth-token"] + headers["Authorization"] = f"Bearer {token}" + + logger.info(f"Invoking {remote_name} at {url}") + + # Connect to a streamable HTTP server with headers + async with streamablehttp_client(url, headers=headers) as ( + read_stream, + write_stream, + _, + ): + # ... rest of method (unchanged) +``` + +#### 组件 2: set_mcp_tool.py (命令行配置工具) +**文件**: `trustgraph-cli/trustgraph/cli/set_mcp_tool.py` + +**目的**: 创建/更新 MCP 工具配置 + +**所需更改**: +1. 向 argparse 添加 `--auth-token` 可选参数 +2. 在提供时,将 `auth-token` 包含在配置 JSON 中 + +**当前参数**: +`--id` (必需): MCP 工具标识符 +`--remote-name` (可选): 远程 MCP 工具名称 +`--tool-url` (必需): MCP 工具 URL 端点 +`-u, --api-url` (可选): TrustGraph API URL + +**新参数**: +`--auth-token` (可选): 用于身份验证的 Bearer token + +**修改后的配置构建**: +```python +# Build configuration object +config = { + "url": args.tool_url, +} + +if args.remote_name: + config["remote-name"] = args.remote_name + +if args.auth_token: + config["auth-token"] = args.auth_token + +# Store configuration +api.config().put([ + ConfigValue(type="mcp", key=args.id, value=json.dumps(config)) +]) +``` + +#### 组件 3:show_mcp_tools.py (命令行显示工具) +**文件**: `trustgraph-cli/trustgraph/cli/show_mcp_tools.py` + +**目的**: 显示 MCP 工具的配置 + +**需要修改的内容**: +1. 在输出表中添加 "Auth" 列 +2. 根据是否存在 auth-token 显示 "是" 或 "否" +3. 不要显示实际的 token 值(出于安全考虑) + +**当前输出**: +``` +ID Remote Name URL +---------- ------------- ------------------------ +my-tool my-tool http://server:3000/api +``` + +**新的输出:** +``` +ID Remote Name URL Auth +---------- ------------- ------------------------ ------ +my-tool my-tool http://server:3000/api Yes +other-tool other-tool http://other:3000/api No +``` + +#### 组件 4:文档 +**文件**: `docs/cli/tg-set-mcp-tool.md` + +**需要修改的内容**: +1. 文档新的 `--auth-token` 参数 +2. 提供带有身份验证的示例用法 +3. 文档安全注意事项 + +## 实施计划 + +### 第一阶段:创建技术规范 +[x] 编写全面的技术规范,记录所有更改 + +### 第二阶段:更新 MCP 工具服务 +[ ] 修改 `invoke_tool()` 中的 `service.py` 以从配置文件读取 auth-token +[ ] 构建 headers 字典并传递给 `streamablehttp_client` +[ ] 使用经过身份验证的 MCP 服务器进行测试 + +### 第三阶段:更新 CLI 工具 +[ ] 向 `set_mcp_tool.py` 添加 `--auth-token` 参数 +[ ] 在配置 JSON 中包含 auth-token +[ ] 向 `show_mcp_tools.py` 的输出添加 "Auth" 列 +[ ] 测试 CLI 工具的更改 + +### 第四阶段:更新文档 +[ ] 在 `tg-set-mcp-tool.md` 中记录 `--auth-token` 参数 +[ ] 添加安全注意事项部分 +[ ] 提供示例用法 + +### 第五阶段:测试 +[ ] 测试 MCP 工具是否能够使用 auth-token 成功连接 +[ ] 测试向后兼容性(没有 auth-token 的工具仍然可以工作) +[ ] 测试 CLI 工具是否能够正确接受和存储 auth-token +[ ] 测试 "show" 命令是否能够正确显示身份验证状态 + +### 代码更改摘要 +| 文件 | 更改类型 | 行数 | 描述 | +|------|------------|-------|-------------| +| `service.py` | 修改 | ~52-66 | 添加 auth-token 读取和 header 构建 | +| `set_mcp_tool.py` | 修改 | ~30-60 | 添加 --auth-token 参数和配置存储 | +| `show_mcp_tools.py` | 修改 | ~40-70 | 向显示添加 Auth 列 | +| `tg-set-mcp-tool.md` | 修改 | 各种 | 文档新的参数 | + +## 测试策略 + +### 单元测试 +**Auth Token 读取**: 测试 `invoke_tool()` 是否能够正确从配置文件读取 auth-token +**Header 构建**: 测试 Authorization header 是否能够使用 Bearer 前缀正确构建 +**向后兼容性**: 测试没有 auth-token 的工具是否能够正常工作 +**CLI 参数解析**: 测试 `--auth-token` 参数是否能够正确解析 + +### 集成测试 +**经过身份验证的连接**: 测试 MCP 工具服务是否能够连接到经过身份验证的服务器 +**端到端**: 测试 CLI → 配置文件存储 → 服务调用,并使用 auth token +**不需要 Token**: 测试连接到未经过身份验证的服务器是否仍然可以工作 + +### 手动测试 +**真实的 MCP 服务器**: 使用需要 bearer token 身份验证的实际 MCP 服务器进行测试 +**CLI 工作流程**: 测试完整的流程:使用 auth 设置工具 → 调用工具 → 验证成功 +**显示屏蔽**: 验证身份验证状态显示,但 token 值不暴露 + +## 迁移和发布 + +### 迁移策略 +不需要迁移 - 这是一个纯粹的附加功能: +现有的 MCP 工具配置,如果没有 `auth-token`,可以继续正常工作 +新的配置可以选择包含 `auth-token` 字段 +CLI 工具接受,但不要求 `--auth-token` 参数 + +### 发布计划 +1. **第一阶段**: 将核心服务更改部署到开发/测试环境 +2. **第二阶段**: 部署 CLI 工具更新 +3. **第三阶段**: 更新文档 +4. **第四阶段**: 生产发布,并进行监控 + +### 回滚计划 +核心更改是向后兼容的 - 现有的工具不受影响 +如果出现问题,可以通过删除 header 构建逻辑来禁用身份验证 token 处理 +CLI 更改是独立的,并且可以单独回滚 + +## 安全注意事项 + +### ⚠️ 关键限制:仅支持单租户身份验证 + +**此身份验证机制不适用于多用户或多租户环境。** + +**共享凭据**: 所有用户和调用都共享每个 MCP 工具的相同 token +**没有用户上下文**: MCP 服务器无法区分不同的 TrustGraph 用户 +**没有租户隔离**: 所有租户共享每个 MCP 工具的相同凭据 +**审计跟踪限制**: MCP 服务器日志显示来自相同凭据的所有请求 +**权限范围**: 无法为不同的用户强制执行不同的权限级别 + +**不要使用此功能,如果:** +您的 TrustGraph 部署服务于多个组织(多租户) +您需要跟踪哪些用户访问了哪些 MCP 工具 +不同的用户需要不同的权限级别 +您需要遵守用户级别的审计要求 +您的 MCP 服务器强制执行每个用户的速率限制或配额 + +**多用户/多租户场景的替代方案:** +通过自定义头部实现用户上下文传播 +为每个租户部署独立的 TrustGraph 实例 +使用网络级别隔离(VPCs、服务网格) +实现一个代理层,该层处理每个用户的身份验证 + +### 令牌存储 +**风险:** 身份验证令牌以明文形式存储在配置系统中 + +**缓解措施:** +记录令牌以明文形式存储 +尽可能推荐使用短寿命令牌 +推荐对配置存储进行适当的访问控制 +考虑未来增强功能,用于加密令牌存储 + +### 令牌泄露 +**风险:** 令牌可能出现在日志或 CLI 输出中 + +**缓解措施:** +不要记录令牌值(仅记录“身份验证已配置:是/否”) +CLI 显示命令仅显示屏蔽状态,不显示实际令牌 +不要将令牌包含在错误消息中 + +### 网络安全 +**风险:** 令牌通过未加密的连接传输 + +**缓解措施:** +记录推荐使用 HTTPS URL 进行 MCP 服务器访问 +警告用户使用 HTTP 传输的明文风险 + +### 配置访问 +**风险:** 未授权访问配置系统会暴露令牌 + +**缓解措施:** +记录保护配置系统访问的重要性 +推荐对配置访问采用最小权限原则 +考虑对配置更改进行审计日志记录(未来增强功能) + +### 多用户环境 +**风险:** 在多用户部署中,所有用户共享相同的 MCP 凭据 + +**风险理解:** +用户 A 和用户 B 在访问 MCP 工具时都使用相同的令牌 +MCP 服务器无法区分不同的 TrustGraph 用户 +没有办法强制执行每个用户的权限或速率限制 +MCP 服务器上的审计日志显示来自相同凭据的所有请求 +如果一个用户的会话被盗,攻击者将拥有与所有用户相同的 MCP 访问权限 + +**这不是一个错误 - 这是一个该设计的基本限制。** + +## 性能影响 +**最小开销:** 头部构建添加了可忽略的处理时间 +**网络影响:** 额外的 HTTP 头部增加了每个请求约 50-200 字节 +**内存使用:** 存储在配置中的令牌字符串会增加可忽略的内存 + +## 文档 + +### 用户文档 +[ ] 使用 `--auth-token` 参数更新 `tg-set-mcp-tool.md` +[ ] 添加安全注意事项部分 +[ ] 提供使用 bearer 令牌的示例 +[ ] 记录令牌存储的影响 + +### 开发人员文档 +[ ] 在 `service.py` 中添加身份验证令牌处理的内联注释 +[ ] 记录头部构建逻辑 +[ ] 更新 MCP 工具配置模式文档 + +## 开放问题 +1. **令牌加密:** 我们是否应该在配置系统中实现加密令牌存储? +2. **令牌刷新:** 未来是否支持 OAuth 刷新流程或令牌轮换? +3. **替代身份验证方法:** 我们是否应该支持 Basic 身份验证、API 密钥或其他方法? + +## 考虑过的替代方案 + +1. **环境变量用于令牌:** 将令牌存储在环境变量中而不是配置中 + **已拒绝:** complicates deployment and configuration management (使部署和配置管理复杂化) + +2. **单独的密钥存储:** 使用专用的密钥管理系统 + **推迟:** Out of scope for initial implementation, consider future enhancement (超出初始实现的范围,考虑未来增强) + +3. **多种身份验证方法:** 支持 Basic、API 密钥、OAuth 等。 + **已拒绝:** Bearer tokens cover most use cases, keep initial implementation simple (Bearer 令牌涵盖大多数用例,保持初始实现的简单性) + +4. **加密令牌存储:** 在配置系统中加密令牌 + **推迟:** Configuration system security is broader concern, defer to future work (配置系统安全是一个更广泛的问题,推迟到未来工作) + +5. **按调用令牌:** 允许在调用时传递令牌 + **已拒绝:** Violates separation of concerns, agent shouldn't handle credentials (违反了关注点分离,代理不应处理凭据) + +## 引用 +[MCP 协议规范](https://github.com/modelcontextprotocol/spec) +[HTTP Bearer 身份验证 (RFC 6750)](https://tools.ietf.org/html/rfc6750) +[Current MCP Tool Service](../trustgraph-flow/trustgraph/agent/mcp_tool/service.py) +[MCP 工具参数规范](./mcp-tool-arguments.md) + +## 附录 + +### 用法示例 + +**设置带有身份验证的 MCP 工具:** +```bash +tg-set-mcp-tool \ + --id secure-tool \ + --tool-url https://secure-server.example.com/mcp \ + --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**展示 MCP 工具:** +```bash +tg-show-mcp-tools + +ID Remote Name URL Auth +----------- ----------- ------------------------------------ ------ +secure-tool secure-tool https://secure-server.example.com/mcp Yes +public-tool public-tool http://localhost:3000/mcp No +``` + +### 配置示例 + +**存储在配置系统中**: +```json +{ + "type": "mcp", + "key": "secure-tool", + "value": "{\"url\": \"https://secure-server.example.com/mcp\", \"auth-token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}" +} +``` + +### 安全最佳实践 + +1. **使用 HTTPS**: 始终为具有身份验证的 MCP 服务器使用 HTTPS URL。 +2. **短生命周期令牌**: 尽可能使用具有过期时间的令牌。 +3. **最小权限**: 授予令牌最低要求的权限。 +4. **访问控制**: 限制对配置系统的访问。 +5. **令牌轮换**: 定期轮换令牌。 +6. **审计日志记录**: 监控配置更改以检测安全事件。 diff --git a/docs/tech-specs/minio-to-s3-migration.ar.md b/docs/tech-specs/minio-to-s3-migration.ar.md new file mode 100644 index 00000000..a75897f5 --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.ar.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "المواصفات الفنية: دعم تخزين متوافق مع S3" +parent: "Arabic (Beta)" +--- + +# المواصفات الفنية: دعم تخزين متوافق مع S3 + +> **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. + +## نظرة عامة + +تستخدم خدمة Librarian تخزين كائنات متوافق مع S3 لتخزين ملفات المستندات. توثق هذه المواصفة التنفيذ الذي يمكّن الدعم لأي نظام تخزين متوافق مع S3 بما في ذلك MinIO و Ceph RADOS Gateway (RGW) و AWS S3 و Cloudflare R2 و DigitalOcean Spaces وغيرها. + +## البنية + +### مكونات التخزين +**تخزين الكائنات (Blob Storage)**: تخزين كائنات متوافق مع S3 عبر مكتبة عميل Python `minio` +**تخزين البيانات الوصفية (Metadata Storage)**: Cassandra (تخزن مطابقة object_id وبيانات وصفية للمستندات) +**المكون المتأثر**: خدمة Librarian فقط +**نمط التخزين**: تخزين هجين مع البيانات الوصفية في Cassandra والمحتوى في تخزين متوافق مع S3 + +### التنفيذ +**المكتبة**: عميل Python `minio` (يدعم أي واجهة برمجة تطبيقات متوافقة مع S3) +**الموقع**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**العمليات**: + `add()` - تخزين كائن بمعرف كائن UUID + `get()` - استرجاع كائن بمعرف الكائن + `remove()` - حذف كائن بمعرف الكائن + `ensure_bucket()` - إنشاء حاوية إذا لم تكن موجودة +**الحاوية (Bucket)**: `library` +**مسار الكائن (Object Path)**: `doc/{object_id}` +**أنواع MIME المدعومة**: `text/plain`، `application/pdf` + +### الملفات الرئيسية +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - تطبيق BlobStore +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - تهيئة BlobStore +3. `trustgraph-flow/trustgraph/librarian/service.py` - تكوين الخدمة +4. `trustgraph-flow/pyproject.toml` - التبعيات (حزمة `minio`) +5. `docs/apis/api-librarian.md` - وثائق API + +## أنظمة التخزين المدعومة + +يعمل هذا التنفيذ مع أي نظام تخزين كائنات متوافق مع S3: + +### تم الاختبار/مدعوم +**Ceph RADOS Gateway (RGW)** - نظام تخزين موزع مع واجهة برمجة تطبيقات S3 (التكوين الافتراضي) +**MinIO** - تخزين كائنات خفيف الوزن ومستضاف ذاتيًا +**Garage** - تخزين S3 متوافق وخفيف الوزن وموزع جغرافيًا + +### يجب أن يعمل (متوافق مع S3) +**AWS S3** - تخزين الكائنات السحابي من Amazon +**Cloudflare R2** - تخزين S3 متوافق من Cloudflare +**DigitalOcean Spaces** - تخزين الكائنات من DigitalOcean +**Wasabi** - تخزين سحابي متوافق مع S3 +**Backblaze B2** - تخزين نسخ احتياطي متوافق مع S3 +أي خدمة أخرى تنفذ واجهة برمجة تطبيقات S3 REST + +## التكوين + +### وسائط سطر الأوامر + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**ملاحظة:** لا تقم بتضمين `http://` أو `https://` في النهاية. استخدم `--object-store-use-ssl` لتمكين HTTPS. + +### متغيرات البيئة (بديل) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### أمثلة + +**بوابة Ceph RADOS (افتراضيًا):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**مينيو:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**مخزن (متوافق مع S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 مع SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## المصادقة + +تتطلب جميع الواجهات الخلفية المتوافقة مع S3 مصادقة AWS Signature Version 4 (أو الإصدار 2): + +**مفتاح الوصول (Access Key)** - مُعرّف عام (مثل اسم المستخدم) +**المفتاح السري (Secret Key)** - مفتاح توقيع خاص (مثل كلمة المرور) + +يتعامل عميل MinIO بلغة Python مع جميع عمليات حساب التوقيع تلقائيًا. + +### إنشاء بيانات الاعتماد + +**لـ MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**لـ Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**لـ AWS S3:** +إنشاء مستخدم IAM مع أذونات S3. +إنشاء مفتاح وصول في وحدة تحكم AWS. + +## اختيار المكتبة: عميل MinIO Python + +**السبب:** +خفيف الوزن (~500 كيلوبايت مقابل ~50 ميجابايت لـ boto3). +متوافق مع S3 - يعمل مع أي نقطة نهاية S3. +واجهة برمجة تطبيقات أبسط من boto3 للعمليات الأساسية. +قيد الاستخدام بالفعل، لا حاجة إلى ترحيل. +تم اختباره بشكل مكثف مع MinIO وأنظمة S3 الأخرى. + +## تنفيذ BlobStore + +**الموقع:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## الفوائد الرئيسية + +1. **لا يوجد اعتماد على مورد واحد** - يعمل مع أي تخزين متوافق مع S3. +2. **خفيف الوزن** - حجم عميل MinIO يبلغ حوالي 500 كيلوبايت فقط. +3. **تكوين بسيط** - يتطلب فقط نقطة النهاية وبيانات الاعتماد. +4. **لا حاجة لنقل البيانات** - بديل مباشر بين الأنظمة الخلفية. +5. **تم اختباره ميدانيًا** - يعمل عميل MinIO مع جميع تطبيقات S3 الرئيسية. + +## حالة التنفيذ + +تم تحديث جميع التعليمات البرمجية لاستخدام أسماء معلمات S3 العامة: + +✅ `blob_store.py` - تم التحديث لقبول `endpoint`، `access_key`، `secret_key`. +✅ `librarian.py` - تم تحديث أسماء المعلمات. +✅ `service.py` - تم تحديث وسيطات سطر الأوامر والتكوين. +✅ تم تحديث الوثائق. + +## التحسينات المستقبلية + +1. **دعم SSL/TLS** - إضافة علامة `--s3-use-ssl` لـ HTTPS. +2. **منطق إعادة المحاولة** - تطبيق تأخير أُسي للأخطاء العابرة. +3. **عناوين URL مؤقتة** - إنشاء عناوين URL مؤقتة للتحميل/التنزيل. +4. **دعم متعدد المناطق** - تكرار الكائنات عبر المناطق. +5. **تكامل CDN** - تقديم الكائنات عبر CDN. +6. **فئات التخزين** - استخدام فئات تخزين S3 لتحسين التكلفة. +7. **سياسات دورة الحياة** - الأرشفة/الحذف التلقائي. +8. **التحكم في الإصدار** - تخزين إصدارات متعددة من الكائنات. + +## المراجع + +عميل MinIO Python: https://min.io/docs/minio/linux/developers/python/API.html +واجهة برمجة تطبيقات Ceph RGW S3: https://docs.ceph.com/en/latest/radosgw/s3/ +مرجع واجهة برمجة تطبيقات S3: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.es.md b/docs/tech-specs/minio-to-s3-migration.es.md new file mode 100644 index 00000000..450ec1d7 --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.es.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "Especificación Técnica: Soporte para Backend de Almacenamiento Compatible con S3" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica: Soporte para Backend de Almacenamiento Compatible con S3 + +> **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 + +El servicio Librarian utiliza almacenamiento de objetos compatible con S3 para el almacenamiento de blobs de documentos. Esta especificación documenta la implementación que permite el soporte para cualquier backend compatible con S3, incluyendo MinIO, Ceph RADOS Gateway (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces, y otros. + +## Arquitectura + +### Componentes de Almacenamiento +**Almacenamiento de Blobs**: Almacenamiento de objetos compatible con S3 a través de la biblioteca de cliente `minio` de Python. +**Almacenamiento de Metadatos**: Cassandra (almacena el mapeo de object_id y los metadatos del documento). +**Componente Afectado**: Solo el servicio Librarian. +**Patrón de Almacenamiento**: Almacenamiento híbrido con metadatos en Cassandra y contenido en almacenamiento compatible con S3. + +### Implementación +**Biblioteca**: Cliente `minio` de Python (soporta cualquier API compatible con S3). +**Ubicación**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**Operaciones**: + `add()` - Almacenar blob con object_id UUID. + `get()` - Recuperar blob por object_id. + `remove()` - Eliminar blob por object_id. + `ensure_bucket()` - Crear bucket si no existe. +**Bucket**: `library` +**Ruta del Objeto**: `doc/{object_id}` +**Tipos MIME Soportados**: `text/plain`, `application/pdf` + +### Archivos Clave +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - Implementación de BlobStore. +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - Inicialización de BlobStore. +3. `trustgraph-flow/trustgraph/librarian/service.py` - Configuración del servicio. +4. `trustgraph-flow/pyproject.toml` - Dependencias (paquete `minio`). +5. `docs/apis/api-librarian.md` - Documentación de la API. + +## Backends de Almacenamiento Soportados + +La implementación funciona con cualquier sistema de almacenamiento de objetos compatible con S3: + +### Probado/Soportado +**Ceph RADOS Gateway (RGW)** - Sistema de almacenamiento distribuido con API S3 (configuración predeterminada). +**MinIO** - Almacenamiento de objetos auto-alojado ligero. +**Garage** - Almacenamiento S3-compatible geo-distribuido ligero. + +### Debería Funcionar (Compatible con S3) +**AWS S3** - Almacenamiento de objetos en la nube de Amazon. +**Cloudflare R2** - Almacenamiento S3-compatible de Cloudflare. +**DigitalOcean Spaces** - Almacenamiento de objetos de DigitalOcean. +**Wasabi** - Almacenamiento en la nube S3-compatible. +**Backblaze B2** - Almacenamiento de respaldo S3-compatible. +Cualquier otro servicio que implemente la API REST S3. + +## Configuración + +### Argumentos de la Línea de Comandos + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**Nota:** No incluya `http://` ni `https://` en el punto final. Use `--object-store-use-ssl` para habilitar HTTPS. + +### Variables de entorno (Alternativa) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### Ejemplos + +**Ceph RADOS Gateway (predeterminado):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**Almacenamiento (compatible con S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 con SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## Autenticación + +Todos los backends compatibles con S3 requieren la autenticación AWS Signature Version 4 (o v2): + +**Clave de acceso** - Identificador público (como nombre de usuario) +**Clave secreta** - Clave de firma privada (como contraseña) + +El cliente de Python de MinIO gestiona automáticamente todos los cálculos de firma. + +### Creación de credenciales + +**Para MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**Para Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**Para AWS S3:** +Crear usuario IAM con permisos de S3 +Generar clave de acceso en la consola de AWS + +## Selección de la biblioteca: Cliente de Python para MinIO + +**Justificación:** +Ligera (~500 KB frente a los ~50 MB de boto3) +Compatible con S3: funciona con cualquier punto final de la API de S3 +API más simple que boto3 para operaciones básicas +Ya en uso, no se necesita migración +Probada en batalla con MinIO y otros sistemas S3 + +## Implementación de BlobStore + +**Ubicación:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## Beneficios Clave + +1. **Sin dependencia de un proveedor** - Funciona con cualquier almacenamiento compatible con S3. +2. **Ligero** - El cliente MinIO tiene un tamaño de aproximadamente 500 KB. +3. **Configuración sencilla** - Solo necesita el punto de acceso y las credenciales. +4. **Sin migración de datos** - Reemplazo directo entre diferentes backends. +5. **Probado en batalla** - El cliente MinIO funciona con todas las principales implementaciones de S3. + +## Estado de la implementación + +Todo el código se ha actualizado para utilizar nombres de parámetros S3 genéricos: + +✅ `blob_store.py` - Actualizado para aceptar `endpoint`, `access_key`, `secret_key` +✅ `librarian.py` - Nombres de parámetros actualizados +✅ `service.py` - Argumentos de la línea de comandos y configuración actualizados +✅ Documentación actualizada + +## Mejoras futuras + +1. **Soporte para SSL/TLS** - Agregar la bandera `--s3-use-ssl` para HTTPS. +2. **Lógica de reintento** - Implementar un reintento exponencial para fallos transitorios. +3. **URLs prefirmadas** - Generar URLs temporales de carga/descarga. +4. **Soporte para múltiples regiones** - Replicar blobs a través de regiones. +5. **Integración con CDN** - Servir blobs a través de una CDN. +6. **Clases de almacenamiento** - Utilizar clases de almacenamiento de S3 para la optimización de costos. +7. **Políticas de ciclo de vida** - Archivado/eliminación automática. +8. **Versionado** - Almacenar múltiples versiones de blobs. + +## Referencias + +Cliente de MinIO para Python: https://min.io/docs/minio/linux/developers/python/API.html +API S3 de Ceph RGW: https://docs.ceph.com/en/latest/radosgw/s3/ +Referencia de la API S3: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.he.md b/docs/tech-specs/minio-to-s3-migration.he.md new file mode 100644 index 00000000..1239e9c6 --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.he.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "Tech Spec: S3-Compatible Storage Backend Support" +parent: "Hebrew (Beta)" +--- + +# Tech Spec: S3-Compatible Storage Backend Support + +> **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 + +השירות Librarian משתמש באחסון אובייקטים תואם ל-S3 לאחסון קבצים. מסמך זה מתאר את היישום המאפשר תמיכה בכל אחסון תואם ל-S3, כולל MinIO, Ceph RADOS Gateway (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces, ואחרים. + +## Architecture + +### Storage Components +**Blob Storage**: אחסון אובייקטים תואם ל-S3 באמצעות `minio` ספריית לקוח Python +**Metadata Storage**: Cassandra (מאחסן מיפוי object_id ונתוני מטא-דאטה של מסמכים) +**Affected Component**: רק השירות Librarian +**Storage Pattern**: אחסון היברידי עם מטא-דאטה ב-Cassandra ותוכן באחסון תואם ל-S3 + +### Implementation +**Library**: `minio` לקוח Python (תומך בכל API תואם ל-S3) +**Location**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**Operations**: + `add()` - שמירת קובץ עם מזהה אובייקט UUID + `get()` - שליפת קובץ לפי מזהה אובייקט + `remove()` - מחיקת קובץ לפי מזהה אובייקט + `ensure_bucket()` - יצירת תיקייה אם היא לא קיימת +**Bucket**: `library` +**Object Path**: `doc/{object_id}` +**Supported MIME Types**: `text/plain`, `application/pdf` + +### Key Files +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - יישום BlobStore +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - אתחול BlobStore +3. `trustgraph-flow/trustgraph/librarian/service.py` - תצורת שירות +4. `trustgraph-flow/pyproject.toml` - תלויות (חבילת `minio`) +5. `docs/apis/api-librarian.md` - תיעוד API + +## Supported Storage Backends + +היישום עובד עם כל מערכת אחסון אובייקטים תואמת ל-S3: + +### Tested/Supported +**Ceph RADOS Gateway (RGW)** - מערכת אחסון מבוזרת עם API של S3 (תצורת ברירת מחדל) +**MinIO** - אחסון אובייקטים קל משקל, הניתן לאירוח עצמי +**Garage** - אחסון S3-תואם, מבוזר גיאוגרפית, קל משקל + +### Should Work (S3-Compatible) +**AWS S3** - אחסון אובייקטים בענן של Amazon +**Cloudflare R2** - אחסון S3-תואם של Cloudflare +**DigitalOcean Spaces** - אחסון אובייקטים של DigitalOcean +**Wasabi** - אחסון בענן S3-תואם +**Backblaze B2** - אחסון גיבוי S3-תואם +כל שירות אחר המיישם את ממשק ה-API של S3 + +## Configuration + +### CLI Arguments + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**הערה:** אל תכללו את `http://` או `https://` בסוף. השתמשו ב-`--object-store-use-ssl` כדי להפעיל HTTPS. + +### משתני סביבה (חלופי) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### דוגמאות + +**שער Ceph RADOS (ברירת מחדל):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**מחסן (תואם S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 עם SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## אימות + +כל השרתים התומכים ב-S3 דורשים אימות AWS Signature Version 4 (או v2): + +**מפתח גישה (Access Key)** - מזהה ציבורי (כמו שם משתמש) +**מפתח סודי (Secret Key)** - מפתח חתימה פרטי (כמו סיסמה) + +לקוח ה-Python של MinIO מטפל בכל חישוב החתימה באופן אוטומטי. + +### יצירת פרטי גישה + +**עבור MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**עבור Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**עבור AWS S3:** +צור משתמש IAM עם הרשאות S3 +צור מפתח גישה בלוח הבקרה של AWS + +## בחירת ספרייה: לקוח Python של MinIO + +**ההצדקה:** +קל משקל (~500KB לעומת ~50MB של boto3) +תואם ל-S3 - עובד עם כל נקודת קצה של ממשק API של S3 +ממשק API פשוט יותר מ-boto3 עבור פעולות בסיסיות +כבר בשימוש, אין צורך בהעברה +נבדק היטב עם MinIO ומערכות S3 אחרות + +## יישום BlobStore + +**מיקום:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## יתרונות מרכזיים + +1. **ללא תלות בספק** - עובד עם כל אחסון התומך ב-S3 +2. **קל משקל** - הלקוח של MinIO הוא בגודל של כ-500KB בלבד +3. **הגדרות פשוטות** - רק נקודת קצה (endpoint) ואישורים +4. **ללא העברת נתונים** - החלפה ישירה בין מערכות אחסון שונות +5. **נבדק ביסודיות** - לקוח MinIO עובד עם כל המימושים העיקריים של S3 + +## סטטוס יישום + +כל הקוד עודכן לשימוש בשמות פרמטרים גנריים של S3: + +✅ `blob_store.py` - עודכן כדי לקבל `endpoint`, `access_key`, `secret_key` +✅ `librarian.py` - עודכנו שמות הפרמטרים +✅ `service.py` - עודכנו ארגומנטים של שורת הפקודה והגדרות +✅ תיעוד עודכן + +## שיפורים עתידיים + +1. **תמיכה ב-SSL/TLS** - הוספת דגל `--s3-use-ssl` עבור HTTPS +2. **לוגיקת ניסיונות חוזרים** - יישום של דחייה אקספוננציאלית עבור כשלים זמניים +3. **כתובות URL חתומות** - יצירת כתובות URL זמניות להעלאה/הורדה +4. **תמיכה בריבוי אזורים** - שכפול קבצים בין אזורים +5. **אינטגרציה עם CDN** - שירות קבצים באמצעות CDN +6. **מדרגי אחסון** - שימוש במדרגי אחסון של S3 למיטוב עלויות +7. **מדיניות מחזור חיים** - ארכיון/מחיקה אוטומטיים +8. **גרסאות** - שמירת גרסאות מרובות של קבצים + +## הפניות + +לקוח MinIO לפייתון: https://min.io/docs/minio/linux/developers/python/API.html +Ceph RGW S3 API: https://docs.ceph.com/en/latest/radosgw/s3/ +מדריך API של S3: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.hi.md b/docs/tech-specs/minio-to-s3-migration.hi.md new file mode 100644 index 00000000..39931fea --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.hi.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "तकनीकी विनिर्देश: S3-संगत स्टोरेज बैकएंड समर्थन" +parent: "Hindi (Beta)" +--- + +# तकनीकी विनिर्देश: S3-संगत स्टोरेज बैकएंड समर्थन + +> **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. + +## अवलोकन + +लाइब्रेरियन सेवा दस्तावेज़ ब्लॉब स्टोरेज के लिए S3-संगत ऑब्जेक्ट स्टोरेज का उपयोग करती है। यह विनिर्देश उस कार्यान्वयन का दस्तावेज़ करता है जो किसी भी S3-संगत बैकएंड के लिए समर्थन को सक्षम करता है, जिसमें MinIO, Ceph RADOS गेटवे (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces और अन्य शामिल हैं। + +## वास्तुकला + +### स्टोरेज घटक +**ब्लॉब स्टोरेज**: `minio` पायथन क्लाइंट लाइब्रेरी के माध्यम से S3-संगत ऑब्जेक्ट स्टोरेज +**मेटाडेटा स्टोरेज**: कैसेंड्रा (ऑब्जेक्ट_आईडी मैपिंग और दस्तावेज़ मेटाडेटा संग्रहीत करता है) +**प्रभावित घटक**: केवल लाइब्रेरियन सेवा +**स्टोरेज पैटर्न**: कैसेंड्रा में मेटाडेटा और S3-संगत स्टोरेज में सामग्री के साथ हाइब्रिड स्टोरेज + +### कार्यान्वयन +**लाइब्रेरी**: `minio` पायथन क्लाइंट (किसी भी S3-संगत API का समर्थन करता है) +**स्थान**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**ऑपरेशन**: + `add()` - UUID ऑब्जेक्ट_आईडी के साथ ब्लॉब संग्रहीत करें + `get()` - ऑब्जेक्ट_आईडी द्वारा ब्लॉब पुनर्प्राप्त करें + `remove()` - ऑब्जेक्ट_आईडी द्वारा ब्लॉब हटाएं + `ensure_bucket()` - यदि मौजूद नहीं है तो बकेट बनाएं +**बकेट**: `library` +**ऑब्जेक्ट पथ**: `doc/{object_id}` +**समर्थित MIME प्रकार**: `text/plain`, `application/pdf` + +### महत्वपूर्ण फाइलें +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - BlobStore कार्यान्वयन +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - BlobStore इनिशियलाइज़ेशन +3. `trustgraph-flow/trustgraph/librarian/service.py` - सेवा कॉन्फ़िगरेशन +4. `trustgraph-flow/pyproject.toml` - निर्भरताएँ (`minio` पैकेज) +5. `docs/apis/api-librarian.md` - एपीआई दस्तावेज़ + +## समर्थित स्टोरेज बैकएंड + +कार्यान्वयन किसी भी S3-संगत ऑब्जेक्ट स्टोरेज सिस्टम के साथ काम करता है: + +### परीक्षण किया गया/समर्थित +**Ceph RADOS गेटवे (RGW)** - S3 API के साथ वितरित स्टोरेज सिस्टम (डिफ़ॉल्ट कॉन्फ़िगरेशन) +**MinIO** - हल्का स्व-होस्टेड ऑब्जेक्ट स्टोरेज +**गैराज** - हल्का जियो-वितरित S3-संगत स्टोरेज + +### काम करना चाहिए (S3-संगत) +**AWS S3** - अमेज़ॅन का क्लाउड ऑब्जेक्ट स्टोरेज +**Cloudflare R2** - Cloudflare का S3-संगत स्टोरेज +**DigitalOcean Spaces** - DigitalOcean का ऑब्जेक्ट स्टोरेज +**Wasabi** - S3-संगत क्लाउड स्टोरेज +**Backblaze B2** - S3-संगत बैकअप स्टोरेज +S3 REST API को लागू करने वाली कोई भी अन्य सेवा + +## कॉन्फ़िगरेशन + +### CLI तर्क + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**ध्यान दें:** अंतिम बिंदु में `http://` या `https://` को शामिल न करें। HTTPS को सक्षम करने के लिए `--object-store-use-ssl` का उपयोग करें। + +### पर्यावरण चर (वैकल्पिक) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### उदाहरण + +**सेफ रेडोस गेटवे (डिफ़ॉल्ट):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**मिनियो:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**गैराज (एस3-संगत):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 एसएसएल के साथ:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## प्रमाणीकरण + +सभी S3-संगत बैकएंड को AWS सिग्नेचर संस्करण 4 (या v2) प्रमाणीकरण की आवश्यकता होती है: + +**एक्सेस कुंजी** - सार्वजनिक पहचानकर्ता (जैसे उपयोगकर्ता नाम) +**सीक्रेट कुंजी** - निजी हस्ताक्षर कुंजी (जैसे पासवर्ड) + +MinIO पायथन क्लाइंट सभी हस्ताक्षर गणना को स्वचालित रूप से संभालता है। + +### क्रेडेंशियल बनाना + +**MinIO के लिए:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**सेफ आरजीडब्ल्यू के लिए:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**AWS S3 के लिए:** +S3 अनुमतियों के साथ एक IAM उपयोगकर्ता बनाएँ। +AWS कंसोल में एक्सेस कुंजी उत्पन्न करें। + +## लाइब्रेरी चयन: MinIO Python क्लाइंट + +**तर्क:** +हल्का (~500KB बनाम boto3 का ~50MB) +S3-संगत - किसी भी S3 API एंडपॉइंट के साथ काम करता है। +बुनियादी कार्यों के लिए boto3 की तुलना में सरल API। +पहले से उपयोग में है, माइग्रेशन की आवश्यकता नहीं है। +MinIO और अन्य S3 सिस्टम के साथ परीक्षण किया गया। + +## BlobStore कार्यान्वयन + +**स्थान:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## मुख्य लाभ + +1. **कोई विक्रेता लॉक-इन नहीं** - किसी भी S3-संगत स्टोरेज के साथ काम करता है। +2. **हल्का** - MinIO क्लाइंट केवल ~500KB है। +3. **सरल कॉन्फ़िगरेशन** - केवल एंडपॉइंट + क्रेडेंशियल। +4. **कोई डेटा माइग्रेशन नहीं** - बैकएंड के बीच ड्रॉप-इन रिप्लेसमेंट। +5. **युद्ध-परीक्षित** - MinIO क्लाइंट सभी प्रमुख S3 कार्यान्वयन के साथ काम करता है। + +## कार्यान्वयन स्थिति + +सभी कोड को जेनेरिक S3 पैरामीटर नामों का उपयोग करने के लिए अपडेट किया गया है: + +✅ `blob_store.py` - `endpoint`, `access_key`, `secret_key` को स्वीकार करने के लिए अपडेट किया गया। +✅ `librarian.py` - पैरामीटर नामों को अपडेट किया गया। +✅ `service.py` - CLI तर्क और कॉन्फ़िगरेशन को अपडेट किया गया। +✅ दस्तावेज़ अपडेट किया गया। + +## भविष्य के सुधार + +1. **SSL/TLS समर्थन** - HTTPS के लिए `--s3-use-ssl` ध्वज जोड़ें। +2. **पुन: प्रयास तर्क** - क्षणिक विफलताओं के लिए घातीय बैकऑफ़ लागू करें। +3. **प्रीसाइंड URL** - अस्थायी अपलोड/डाउनलोड URL उत्पन्न करें। +4. **मल्टी-रीजन समर्थन** - क्षेत्रों में ब्लॉब्स को दोहराएं। +5. **CDN एकीकरण** - CDN के माध्यम से ब्लॉब्स परोसें। +6. **स्टोरेज क्लासेस** - लागत अनुकूलन के लिए S3 स्टोरेज क्लासेस का उपयोग करें। +7. **लाइफसाइकिल नीतियां** - स्वचालित अभिलेखागार/हटाना। +8. **वर्जनिंग** - ब्लॉब्स के कई संस्करणों को संग्रहीत करें। + +## संदर्भ + +MinIO Python क्लाइंट: https://min.io/docs/minio/linux/developers/python/API.html +Ceph RGW S3 API: https://docs.ceph.com/en/latest/radosgw/s3/ +S3 API संदर्भ: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.md b/docs/tech-specs/minio-to-s3-migration.md index 91daf105..e6d52faa 100644 --- a/docs/tech-specs/minio-to-s3-migration.md +++ b/docs/tech-specs/minio-to-s3-migration.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Tech Spec: S3-Compatible Storage Backend Support" +parent: "Tech Specs" +--- + # Tech Spec: S3-Compatible Storage Backend Support ## Overview diff --git a/docs/tech-specs/minio-to-s3-migration.pt.md b/docs/tech-specs/minio-to-s3-migration.pt.md new file mode 100644 index 00000000..64249cb7 --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.pt.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "Especificação Técnica: Suporte a Backend de Armazenamento Compatível com S3" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica: Suporte a Backend de Armazenamento Compatível com S3 + +> **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 + +O serviço Librarian utiliza armazenamento de objetos compatível com S3 para o armazenamento de blobs de documentos. Esta especificação documenta a implementação que permite o suporte a qualquer backend compatível com S3, incluindo MinIO, Ceph RADOS Gateway (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces e outros. + +## Arquitetura + +### Componentes de Armazenamento +**Armazenamento de Blobs**: Armazenamento de objetos compatível com S3 através da biblioteca cliente `minio` Python. +**Armazenamento de Metadados**: Cassandra (armazena o mapeamento object_id e os metadados do documento). +**Componente Afetado**: Apenas o serviço Librarian. +**Padrão de Armazenamento**: Armazenamento híbrido com metadados no Cassandra e conteúdo no armazenamento compatível com S3. + +### Implementação +**Biblioteca**: Cliente `minio` Python (suporta qualquer API compatível com S3). +**Localização**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**Operações**: + `add()` - Armazenar blob com object_id UUID. + `get()` - Recuperar blob por object_id. + `remove()` - Excluir blob por object_id. + `ensure_bucket()` - Criar bucket se não existir. +**Bucket**: `library` +**Caminho do Objeto**: `doc/{object_id}` +**Tipos MIME Suportados**: `text/plain`, `application/pdf` + +### Arquivos Chave +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - Implementação do BlobStore. +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - Inicialização do BlobStore. +3. `trustgraph-flow/trustgraph/librarian/service.py` - Configuração do serviço. +4. `trustgraph-flow/pyproject.toml` - Dependências (pacote `minio`). +5. `docs/apis/api-librarian.md` - Documentação da API. + +## Backends de Armazenamento Suportados + +A implementação funciona com qualquer sistema de armazenamento de objetos compatível com S3: + +### Testados/Suportados +**Ceph RADOS Gateway (RGW)** - Sistema de armazenamento distribuído com API S3 (configuração padrão). +**MinIO** - Armazenamento de objetos auto-hospedado leve. +**Garage** - Armazenamento S3-compatível geo-distribuído leve. + +### Deve Funcionar (Compatível com S3) +**AWS S3** - Armazenamento de objetos em nuvem da Amazon. +**Cloudflare R2** - Armazenamento S3-compatível da Cloudflare. +**DigitalOcean Spaces** - Armazenamento de objetos da DigitalOcean. +**Wasabi** - Armazenamento em nuvem S3-compatível. +**Backblaze B2** - Armazenamento de backup S3-compatível. +Qualquer outro serviço que implemente a API REST S3. + +## Configuração + +### Argumentos da Linha de Comando + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**Observação:** Não inclua `http://` ou `https://` no endpoint. Use `--object-store-use-ssl` para habilitar HTTPS. + +### Variáveis de Ambiente (Alternativa) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### Exemplos + +**Ceph RADOS Gateway (padrão):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**Armazenamento (compatível com S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 com SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## Autenticação + +Todos os backends compatíveis com S3 requerem a autenticação AWS Signature Version 4 (ou v2): + +**Chave de Acesso** - Identificador público (como nome de usuário) +**Chave Secreta** - Chave de assinatura privada (como senha) + +O cliente Python da MinIO gerencia automaticamente todos os cálculos de assinatura. + +### Criando Credenciais + +**Para MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**Para o Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**Para AWS S3:** +Crie um usuário IAM com permissões S3 +Gere uma chave de acesso no Console da AWS + +## Seleção da Biblioteca: Cliente Python MinIO + +**Justificativa:** +Leve (~500KB vs ~50MB do boto3) +Compatível com S3 - funciona com qualquer endpoint de API S3 +API mais simples que o boto3 para operações básicas +Já em uso, não é necessária migração +Testado em batalha com MinIO e outros sistemas S3 + +## Implementação do BlobStore + +**Localização:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## Benefícios Principais + +1. **Sem Dependência de Fornecedor** - Funciona com qualquer armazenamento compatível com S3. +2. **Leve** - O cliente MinIO tem apenas ~500KB. +3. **Configuração Simples** - Apenas endpoint e credenciais. +4. **Sem Migração de Dados** - Substituição direta entre backends. +5. **Testado em Combate** - O cliente MinIO funciona com todas as principais implementações S3. + +## Status da Implementação + +Todo o código foi atualizado para usar nomes de parâmetros S3 genéricos: + +✅ `blob_store.py` - Atualizado para aceitar `endpoint`, `access_key`, `secret_key`. +✅ `librarian.py` - Nomes de parâmetros atualizados. +✅ `service.py` - Argumentos da CLI e configuração atualizados. +✅ Documentação atualizada. + +## Melhorias Futuras + +1. **Suporte SSL/TLS** - Adicionar a flag `--s3-use-ssl` para HTTPS. +2. **Lógica de Repetição** - Implementar retrocesso exponencial para falhas transitórias. +3. **URLs Pré-assinadas** - Gerar URLs temporárias de upload/download. +4. **Suporte Multi-região** - Replicar blobs entre regiões. +5. **Integração CDN** - Servir blobs via CDN. +6. **Classes de Armazenamento** - Usar classes de armazenamento S3 para otimização de custos. +7. **Políticas de Ciclo de Vida** - Arquivamento/exclusão automática. +8. **Versionamento** - Armazenar múltiplas versões de blobs. + +## Referências + +Cliente Python MinIO: https://min.io/docs/minio/linux/developers/python/API.html +API S3 Ceph RGW: https://docs.ceph.com/en/latest/radosgw/s3/ +Referência da API S3: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.ru.md b/docs/tech-specs/minio-to-s3-migration.ru.md new file mode 100644 index 00000000..b7d37a39 --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.ru.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "Технические характеристики: Поддержка хранилища, совместимого с S3" +parent: "Russian (Beta)" +--- + +# Технические характеристики: Поддержка хранилища, совместимого с S3 + +> **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. + +## Обзор + +Сервис Librarian использует объектное хранилище, совместимое с S3, для хранения двоичных данных документов. Этот документ описывает реализацию, которая обеспечивает поддержку любого хранилища, совместимого с S3, включая MinIO, Ceph RADOS Gateway (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces и другие. + +## Архитектура + +### Компоненты хранения +**Хранилище двоичных данных**: Объектное хранилище, совместимое с S3, через `minio` Python клиентскую библиотеку. +**Хранилище метаданных**: Cassandra (хранит сопоставление object_id и метаданные документов). +**Затронутый компонент**: Только сервис Librarian. +**Схема хранения**: Гибридное хранилище с метаданными в Cassandra и содержимым в хранилище, совместимом с S3. + +### Реализация +**Библиотека**: `minio` Python клиент (поддерживает любой API, совместимый с S3). +**Расположение**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**Операции**: + `add()` - Сохранение двоичных данных с object_id в формате UUID. + `get()` - Получение двоичных данных по object_id. + `remove()` - Удаление двоичных данных по object_id. + `ensure_bucket()` - Создание бакета, если он не существует. +**Бакет**: `library` +**Путь к объекту**: `doc/{object_id}` +**Поддерживаемые типы MIME**: `text/plain`, `application/pdf` + +### Основные файлы +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - Реализация BlobStore. +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - Инициализация BlobStore. +3. `trustgraph-flow/trustgraph/librarian/service.py` - Конфигурация сервиса. +4. `trustgraph-flow/pyproject.toml` - Зависимости (пакет `minio`). +5. `docs/apis/api-librarian.md` - Документация API. + +## Поддерживаемые системы хранения + +Реализация работает с любой системой объектного хранения, совместимой с S3: + +### Протестировано/Поддерживается +**Ceph RADOS Gateway (RGW)** - Распределенная система хранения с API S3 (конфигурация по умолчанию). +**MinIO** - Легковесное объектное хранилище для самостоятельного размещения. +**Garage** - Легковесное географически распределенное хранилище, совместимое с S3. + +### Должно работать (совместимо с S3) +**AWS S3** - Облачное объектное хранилище от Amazon. +**Cloudflare R2** - Хранилище от Cloudflare, совместимое с S3. +**DigitalOcean Spaces** - Объектное хранилище от DigitalOcean. +**Wasabi** - Облачное хранилище, совместимое с S3. +**Backblaze B2** - Хранилище резервных копий, совместимое с S3. +Любая другая служба, реализующая REST API S3. + +## Конфигурация + +### Аргументы командной строки + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**Примечание:** Не включайте `http://` или `https://` в конечную точку. Используйте `--object-store-use-ssl` для включения HTTPS. + +### Переменные окружения (Альтернативный способ) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### Примеры + +**Ceph RADOS Gateway (по умолчанию):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**Гараж (совместимый с S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 с использованием SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## Аутентификация + +Все бэкенды, совместимые с S3, требуют аутентификации AWS Signature Version 4 (или v2): + +**Access Key** - Публичный идентификатор (например, имя пользователя) +**Secret Key** - Приватный ключ для подписи (например, пароль) + +Python-клиент MinIO автоматически обрабатывает все вычисления подписи. + +### Создание учетных данных + +**Для MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**Для Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**Для AWS S3:** +Создайте пользователя IAM с разрешениями S3 +Сгенерируйте ключ доступа в консоли AWS + +## Выбор библиотеки: MinIO Python Client + +**Обоснование:** +Легковесная (~500 КБ против ~50 МБ у boto3) +Совместима с S3 - работает с любым конечным пунктом API S3 +Более простой API, чем boto3, для основных операций +Уже используется, не требуется миграция +Проверена в боевых условиях с MinIO и другими системами S3 + +## Реализация BlobStore + +**Расположение:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## Ключевые преимущества + +1. **Отсутствие привязки к конкретному поставщику** - Работает с любым хранилищем, совместимым с S3. +2. **Легковесность** - Клиент MinIO занимает всего около 500 КБ. +3. **Простая настройка** - Только конечная точка и учетные данные. +4. **Отсутствие миграции данных** - Замена между бэкендами без перебоев. +5. **Проверено в боевых условиях** - Клиент MinIO работает со всеми основными реализациями S3. + +## Статус реализации + +Весь код был обновлен для использования общих имен параметров S3: + +✅ `blob_store.py` - Обновлено для приема `endpoint`, `access_key`, `secret_key` +✅ `librarian.py` - Обновлены имена параметров +✅ `service.py` - Обновлены аргументы командной строки и конфигурация +✅ Обновлена документация + +## Планируемые улучшения + +1. **Поддержка SSL/TLS** - Добавить флаг `--s3-use-ssl` для HTTPS. +2. **Логика повторных попыток** - Реализовать экспоненциальную задержку для временных сбоев. +3. **Временные URL-адреса** - Генерировать временные URL-адреса для загрузки/скачивания. +4. **Поддержка нескольких регионов** - Репликация объектов между регионами. +5. **Интеграция с CDN** - Предоставление объектов через CDN. +6. **Классы хранения** - Использование классов хранения S3 для оптимизации затрат. +7. **Политики жизненного цикла** - Автоматическое архивирование/удаление. +8. **Версионирование** - Хранение нескольких версий объектов. + +## Ссылки + +MinIO Python Client: https://min.io/docs/minio/linux/developers/python/API.html +Ceph RGW S3 API: https://docs.ceph.com/en/latest/radosgw/s3/ +S3 API Reference: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.sw.md b/docs/tech-specs/minio-to-s3-migration.sw.md new file mode 100644 index 00000000..57f4cc28 --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.sw.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "Vipimo vya Kisaikolojia: Usaidizi wa Hifadhi Data inayolingana na S3" +parent: "Swahili (Beta)" +--- + +# Vipimo vya Kisaikolojia: Usaidizi wa Hifadhi Data inayolingana na S3 + +> **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 + +Huduma ya Librarian hutumia hifadhi data ya vitu inayolingana na S3 kwa kuhifadhi faili za hati. Haya yanatoa maelezo ya utekelezaji unaoleta uwezo wa kusaidia mfumo wowote wa hifadhi inayolingana na S3, ikiwa ni pamoja na MinIO, Ceph RADOS Gateway (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces, na wengine. + +## Muundo + +### Vipengele vya Uhifadhi +**Hifadhi ya Vitu:** Hifadhi data ya vitu inayolingana na S3 kupitia `minio` maktaba ya mteja ya Python +**Hifadhi ya MetaData:** Cassandra (hufanya kazi ya kuhifadhi uhusiano wa object_id na metadata ya hati) +**Kipengele Kilichohusika:** Huduma ya Librarian pekee +**Mfumo wa Uhifadhi:** Uhifadhi mchanganyiko na metadata katika Cassandra, na yaliyomo katika hifadhi inayolingana na S3 + +### Utendaji +**Maktaba:** `minio` mteja wa Python (inaunga mkono API yoyote inayolingana na S3) +**Mahali:** `trustgraph-flow/trustgraph/librarian/blob_store.py` +**Tendo:** + `add()` - Hifadhi faili kwa kitambulisho cha kipekee (object_id) + `get()` - Rudisha faili kwa kitambulisho cha kipekee (object_id) + `remove()` - Futa faili kwa kitambulisho cha kipekee (object_id) + `ensure_bucket()` - Unda kiasi (bucket) ikiwa haipo +**Kiasi (Bucket):** `library` +**Njia ya Faili:** `doc/{object_id}` +**Aina Zinazoidhinishwa (MIME Types):** `text/plain`, `application/pdf` + +### Faili Muhimu +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - Utendaji wa BlobStore +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - Uanzishaji wa BlobStore +3. `trustgraph-flow/trustgraph/librarian/service.py` - Usanidi wa huduma +4. `trustgraph-flow/pyproject.toml` - Utendakazi (pakiti ya `minio`) +5. `docs/apis/api-librarian.md` - Nyaraka za API + +## Mifumo ya Uhifadhi Inayoungwa Mkono + +Utendaji huu unafanya kazi na mfumo wowote wa hifadhi data ya vitu inayolingana na S3: + +### Imethibitishwa/Inaungwa Mkono +**Ceph RADOS Gateway (RGW)** - Mfumo wa hifadhi usambazwa na API ya S3 (usanidi chaguu) +**MinIO** - Hifadhi data ya vitu nyepesi inayoweza kuendeshwa na wewe mwenyewe +**Garage** - Hifadhi data ya vitu nyepesi inayopaswa kusambazwa kijiografia inayolingana na S3 + +### Inapaswa Kufanya kazi (Inayolingana na S3) +**AWS S3** - Hifadhi data ya vitu ya Amazon kwenye wingu +**Cloudflare R2** - Hifadhi data inayolingana na S3 ya Cloudflare +**DigitalOcean Spaces** - Hifadhi data ya vitu ya DigitalOcean +**Wasabi** - Hifadhi data ya vitu kwenye wingu inayolingana na S3 +**Backblaze B2** - Hifadhi data ya vitu inayolingana na S3 kwa ajili ya chelezo +Huduma yoyote nyingine inayotekeleza API ya S3 REST + +## Usanidi + +### Majadiliano ya CLI + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**Kumbuka:** Usijumuishie `http://` au `https://` katika mwisho. Tumia `--object-store-use-ssl` ili kuwezesha HTTPS. + +### Vigezo vya Mazingira (Mbadala) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### Mifano + +**Lango la RADOS la Ceph (linalolingana na chaguo-msingi):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**Gara (Inayoambatana na S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 na SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## Uthibitisho + +Vifaa vyote vinavyolingana na S3 vinahitaji uthibitisho wa AWS Signature Version 4 (au v2): + +**Ufunguo wa Ufikiaji** - Kitambulisho cha umma (kama jina la mtumiaji) +**Ufunguo Siri** - Ufunguo wa siri wa usaini (kama nenosiri) + +Mteja wa Python wa MinIO hushughulikia hesabu yote ya usaini kiotomatiki. + +### Kuunda Anwani + +**Kwa MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**Kwa Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**Kwa AWS S3:** +Unda mtumiaji wa IAM na ruhusa za S3 +Toa ufunguo wa ufikiaji katika Konsoli ya AWS + +## Chaguo la Klibu: Mteja wa MinIO Python + +**Sababu:** +Nyepesi (~500KB dhidi ya ~50MB ya boto3) +Inafanana na S3 - inafanya kazi na mwisho wowote wa API ya S3 +API rahisi kuliko boto3 kwa operesheni za msingi +Tayari inatumika, hakuna uhamishaji unaohitajika +Imethibitishwa kwa MinIO na mifumo mingine ya S3 + +## Utendaji wa BlobStore + +**Mahali:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## Faida Muhimu + +1. **Hakuna Utegemezi wa Mtoa Huduma** - Inafanya kazi na hifadhi yoyote inayolingana na S3. +2. **Nyepesi** - Mteja wa MinIO ni takriban 500KB. +3. **Uwekaji Rahisi** - Tu mwisho na anwani za kuingia. +4. **Hakuna Uhamishaji wa Data** - Badala ya moja kwa moja kati ya mifumo ya nyuma. +5. **Imethibitishwa katika Vita** - Mteja wa MinIO unafanya kazi na matoleo yote makubwa ya S3. + +## Hali ya Utendaji + +Msimbo wote umeongezwa ili kutumia majina ya vigezo vya S3. + +✅ `blob_store.py` - Imeongezwa ili kukubali `endpoint`, `access_key`, `secret_key` +✅ `librarian.py` - Majina ya vigezo yameongezwa. +✅ `service.py` - Majadiliano ya CLI na usanidi yameongezwa. +✅ Nyaraka zimeongezwa. + +## Maboresho ya Baadaye + +1. **Usaidizi wa SSL/TLS** - Ongeza bendera `--s3-use-ssl` kwa HTTPS. +2. **Mantiki ya Kujaribu Upya** - Tekeleza kuchelewesha kwa eksponensia kwa kushindwa kwa muda mfupi. +3. **Anwani za Muda** - Zunda anwani za muda za kupakia/kupakua. +4. **Usaidizi wa Mikoa Mbalimbali** - Nakili data katika mikoa mbalimbali. +5. **Uunganisho wa CDN** - Toa data kupitia CDN. +6. **Daraja za Hifadhi** - Tumia daraja za hifadhi za S3 kwa uboreshaji wa gharama. +7. **Sera za Maisha** - Hifadhi/ufute data kiotomatiki. +8. **Toleo** - Hifadhi matoleo mengi ya data. + +## Marejeleo + +Mteja wa MinIO wa Python: https://min.io/docs/minio/linux/developers/python/API.html +API ya S3 ya Ceph RGW: https://docs.ceph.com/en/latest/radosgw/s3/ +Marejeleo ya API ya S3: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.tr.md b/docs/tech-specs/minio-to-s3-migration.tr.md new file mode 100644 index 00000000..1cd12b4b --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.tr.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "Teknik Özellikler: S3 Uyumlu Depolama Arka Ucu Desteği" +parent: "Turkish (Beta)" +--- + +# Teknik Özellikler: S3 Uyumlu Depolama Arka Ucu Desteğ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ış + +Librarian hizmeti, belge bloğu depolaması için S3 uyumlu nesne depolamayı kullanır. Bu özellik, MinIO, Ceph RADOS Gateway (RGW), AWS S3, Cloudflare R2, DigitalOcean Spaces ve diğerleri dahil olmak üzere herhangi bir S3 uyumlu arka uç için desteği etkinleştiren uygulamayı belgelemektedir. + +## Mimari + +### Depolama Bileşenleri +**Bloğu Depolama**: `minio` Python istemci kitaplığı aracılığıyla S3 uyumlu nesne depolama +**Metaveri Depolama**: Cassandra (object_id eşlemesini ve belge meta verilerini depolar) +**Etkilenen Bileşen**: Yalnızca Librarian hizmeti +**Depolama Modeli**: Cassandra'da metaveri, S3 uyumlu depolamada içerikle hibrit depolama + +### Uygulama +**Kitaplık**: `minio` Python istemcisi (herhangi bir S3 uyumlu API'yi destekler) +**Konum**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**İşlemler**: + `add()` - UUID object_id ile bloğu kaydet + `get()` - object_id ile bloğu al + `remove()` - object_id ile bloğu sil + `ensure_bucket()` - Yoksa bucket oluştur +**Bucket**: `library` +**Nesne Yolu**: `doc/{object_id}` +**Desteklenen MIME Türleri**: `text/plain`, `application/pdf` + +### Önemli Dosyalar +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - BlobStore uygulaması +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - BlobStore başlatma +3. `trustgraph-flow/trustgraph/librarian/service.py` - Hizmet yapılandırması +4. `trustgraph-flow/pyproject.toml` - Bağımlılıklar (`minio` paketi) +5. `docs/apis/api-librarian.md` - API dokümantasyonu + +## Desteklenen Depolama Arka Uçları + +Bu uygulama, herhangi bir S3 uyumlu nesne depolama sistemiyle çalışır: + +### Test Edildi/Destekleniyor +**Ceph RADOS Gateway (RGW)** - S3 API'sine sahip dağıtılmış depolama sistemi (varsayılan yapılandırma) +**MinIO** - Hafif, kendi kendine barındırılan nesne depolama +**Garage** - Hafif, coğrafi olarak dağıtılmış S3 uyumlu depolama + +### Çalışması Gerekiyor (S3 Uyumlu) +**AWS S3** - Amazon'un bulut nesne depolaması +**Cloudflare R2** - Cloudflare'in S3 uyumlu depolaması +**DigitalOcean Spaces** - DigitalOcean'ın nesne depolaması +**Wasabi** - S3 uyumlu bulut depolama +**Backblaze B2** - S3 uyumlu yedekleme depolama +S3 REST API'sini uygulayan herhangi bir hizmet + +## Yapılandırma + +### CLI Argümanları + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**Not:** `http://` veya `https://`'i uç noktada dahil etmeyin. HTTPS'yi etkinleştirmek için `--object-store-use-ssl`'yi kullanın. + +### Ortam Değişkenleri (Alternatif) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### Örnekler + +**Ceph RADOS Ağ Geçidi (varsayılan):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**Garaj (S3 uyumlu):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 SSL ile:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## Kimlik Doğrulama + +Tüm S3 uyumlu arka uçlar, AWS Signature Version 4 (veya v2) kimlik doğrulamasını gerektirir: + +**Erişim Anahtarı** - Genel tanımlayıcı (kullanıcı adı gibi) +**Gizli Anahtar** - Özel imzalama anahtarı (parola gibi) + +MinIO Python istemcisi, tüm imza hesaplamalarını otomatik olarak yapar. + +### Kimlik Bilgilerini Oluşturma + +**MinIO için:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**Ceph RGW için:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**AWS S3 için:** +S3 izinlerine sahip bir IAM kullanıcısı oluşturun. +AWS Konsolu'nda bir erişim anahtarı oluşturun. + +## Kütüphane Seçimi: MinIO Python İstemcisi + +**Gerekçe:** +Hafif (~500KB, boto3'ün ~50MB'sine kıyasla) +S3 uyumlu - herhangi bir S3 API uç noktasıyla çalışır. +Temel işlemler için boto3'e göre daha basit bir API. +Zaten kullanımda, herhangi bir geçişe gerek yok. +MinIO ve diğer S3 sistemleriyle test edilmiş. + +## BlobStore Uygulaması + +**Konum:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## Temel Avantajlar + +1. **Satıcıya Bağlılık Yok** - Herhangi bir S3 uyumlu depolama ile çalışır. +2. **Hafif** - MinIO istemcisi yaklaşık 500KB'dir. +3. **Basit Yapılandırma** - Sadece uç nokta + kimlik bilgileri gereklidir. +4. **Veri Göçü Yok** - Arka uçlar arasında doğrudan değiştirilebilir. +5. **Kanıtlanmış** - MinIO istemcisi, tüm büyük S3 uygulamalarıyla çalışır. + +## Uygulama Durumu + +Tüm kod, genel S3 parametre adlarını kullanacak şekilde güncellenmiştir: + +✅ `blob_store.py` - `endpoint`, `access_key` ve `secret_key`'ü kabul edecek şekilde güncellendi. +✅ `librarian.py` - Parametre adları güncellendi. +✅ `service.py` - CLI argümanları ve yapılandırma güncellendi. +✅ Belgeler güncellendi. + +## Gelecek Geliştirmeler + +1. **SSL/TLS Desteği** - HTTPS için `--s3-use-ssl` bayrağı eklenecek. +2. **Yeniden Deneme Mantığı** - Geçici hatalar için üstel geri alma uygulanacak. +3. **Önceden İmzalı URL'ler** - Geçici yükleme/indirme URL'leri oluşturulacak. +4. **Çok Bölgeli Destek** - Verileri bölgeler arasında çoğaltılacak. +5. **CDN Entegrasyonu** - Veriler CDN üzerinden sunulacak. +6. **Depolama Sınıfları** - Maliyet optimizasyonu için S3 depolama sınıfları kullanılacak. +7. **Yaşam Döngüsü Politikaları** - Otomatik arşivleme/silme. +8. **Sürümleme** - Verilerin birden fazla sürümü saklanacak. + +## Referanslar + +MinIO Python İstemcisi: https://min.io/docs/minio/linux/developers/python/API.html +Ceph RGW S3 API: https://docs.ceph.com/en/latest/radosgw/s3/ +S3 API Referansı: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/minio-to-s3-migration.zh-cn.md b/docs/tech-specs/minio-to-s3-migration.zh-cn.md new file mode 100644 index 00000000..c4567a2a --- /dev/null +++ b/docs/tech-specs/minio-to-s3-migration.zh-cn.md @@ -0,0 +1,266 @@ +--- +layout: default +title: "技术规范:S3 兼容的存储后端支持" +parent: "Chinese (Beta)" +--- + +# 技术规范:S3 兼容的存储后端支持 + +> **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. + +## 概述 + +Librarian 服务使用 S3 兼容的对象存储来存储文档 Blob。此规范记录了实现,该实现支持任何 S3 兼容的后端,包括 MinIO、Ceph RADOS Gateway (RGW)、AWS S3、Cloudflare R2、DigitalOcean Spaces 等。 + +## 架构 + +### 存储组件 +**Blob 存储**: 通过 `minio` Python 客户端库实现的 S3 兼容对象存储 +**元数据存储**: Cassandra (存储 object_id 映射和文档元数据) +**受影响的组件**: 仅限 Librarian 服务 +**存储模式**: 混合存储,元数据存储在 Cassandra 中,内容存储在 S3 兼容的存储中 + +### 实现 +**库**: `minio` Python 客户端 (支持任何 S3 兼容的 API) +**位置**: `trustgraph-flow/trustgraph/librarian/blob_store.py` +**操作**: + `add()` - 使用 UUID object_id 存储 Blob + `get()` - 根据 object_id 检索 Blob + `remove()` - 根据 object_id 删除 Blob + `ensure_bucket()` - 如果不存在,则创建 Bucket +**Bucket**: `library` +**对象路径**: `doc/{object_id}` +**支持的 MIME 类型**: `text/plain`, `application/pdf` + +### 关键文件 +1. `trustgraph-flow/trustgraph/librarian/blob_store.py` - BlobStore 实现 +2. `trustgraph-flow/trustgraph/librarian/librarian.py` - BlobStore 初始化 +3. `trustgraph-flow/trustgraph/librarian/service.py` - 服务配置 +4. `trustgraph-flow/pyproject.toml` - 依赖项 (`minio` 包) +5. `docs/apis/api-librarian.md` - API 文档 + +## 支持的存储后端 + +此实现适用于任何 S3 兼容的对象存储系统: + +### 已测试/支持 +**Ceph RADOS Gateway (RGW)** - 具有 S3 API 的分布式存储系统 (默认配置) +**MinIO** - 轻量级的自托管对象存储 +**Garage** - 轻量级的分布式 S3 兼容存储 + +### 应该可以工作 (S3 兼容) +**AWS S3** - Amazon 的云对象存储 +**Cloudflare R2** - Cloudflare 的 S3 兼容存储 +**DigitalOcean Spaces** - DigitalOcean 的对象存储 +**Wasabi** - S3 兼容的云存储 +**Backblaze B2** - S3 兼容的备份存储 +任何实现 S3 REST API 的服务 + +## 配置 + +### 命令行参数 + +```bash +librarian \ + --object-store-endpoint \ + --object-store-access-key \ + --object-store-secret-key \ + [--object-store-use-ssl] \ + [--object-store-region ] +``` + +**注意:** 请不要在端点中包含 `http://` 或 `https://`。 使用 `--object-store-use-ssl` 启用 HTTPS。 + +### 环境变量(备选方案) + +```bash +OBJECT_STORE_ENDPOINT= +OBJECT_STORE_ACCESS_KEY= +OBJECT_STORE_SECRET_KEY= +OBJECT_STORE_USE_SSL=true|false # Optional, default: false +OBJECT_STORE_REGION= # Optional +``` + +### 示例 + +**Ceph RADOS 网关(默认):** +```bash +--object-store-endpoint ceph-rgw:7480 \ +--object-store-access-key object-user \ +--object-store-secret-key object-password +``` + +**MinIO:** +```bash +--object-store-endpoint minio:9000 \ +--object-store-access-key minioadmin \ +--object-store-secret-key minioadmin +``` + +**云存储(兼容S3):** +```bash +--object-store-endpoint garage:3900 \ +--object-store-access-key GK000000000000000000000001 \ +--object-store-secret-key b171f00be9be4c32c734f4c05fe64c527a8ab5eb823b376cfa8c2531f70fc427 +``` + +**AWS S3 使用 SSL:** +```bash +--object-store-endpoint s3.amazonaws.com \ +--object-store-access-key AKIAIOSFODNN7EXAMPLE \ +--object-store-secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ +--object-store-use-ssl \ +--object-store-region us-east-1 +``` + +## 身份验证 + +所有兼容 S3 的后端都需要 AWS 签名版本 4(或 v2)身份验证: + +**访问密钥** - 公开标识符(类似于用户名) +**密钥** - 私有签名密钥(类似于密码) + +MinIO Python 客户端会自动处理所有签名计算。 + +### 创建凭证 + +**对于 MinIO:** +```bash +# Use default credentials or create user via MinIO Console +minioadmin / minioadmin +``` + +**适用于 Ceph RGW:** +```bash +radosgw-admin user create --uid="trustgraph" --display-name="TrustGraph Service" +# Returns access_key and secret_key +``` + +**适用于 AWS S3:** +创建具有 S3 权限的 IAM 用户 +在 AWS 控制台中生成访问密钥 + +## 库选择:MinIO Python 客户端 + +**理由:** +轻量级(约 500KB,而 boto3 约为 50MB) +与 S3 兼容,适用于任何 S3 API 端点 +对于基本操作,API 比 boto3 更简单 +已在使用中,无需迁移 +经过 MinIO 和其他 S3 系统的严格测试 + +## BlobStore 实施 + +**位置:** `trustgraph-flow/trustgraph/librarian/blob_store.py` + +```python +from minio import Minio +import io +import logging + +logger = logging.getLogger(__name__) + +class BlobStore: + """ + S3-compatible blob storage for document content. + Supports MinIO, Ceph RGW, AWS S3, and other S3-compatible backends. + """ + + def __init__(self, endpoint, access_key, secret_key, bucket_name, + use_ssl=False, region=None): + """ + Initialize S3-compatible blob storage. + + Args: + endpoint: S3 endpoint (e.g., "minio:9000", "ceph-rgw:7480") + access_key: S3 access key + secret_key: S3 secret key + bucket_name: Bucket name for storage + use_ssl: Use HTTPS instead of HTTP (default: False) + region: S3 region (optional, e.g., "us-east-1") + """ + self.client = Minio( + endpoint=endpoint, + access_key=access_key, + secret_key=secret_key, + secure=use_ssl, + region=region, + ) + + self.bucket_name = bucket_name + + protocol = "https" if use_ssl else "http" + logger.info(f"Connected to S3-compatible storage at {protocol}://{endpoint}") + + self.ensure_bucket() + + def ensure_bucket(self): + """Create bucket if it doesn't exist""" + found = self.client.bucket_exists(bucket_name=self.bucket_name) + if not found: + self.client.make_bucket(bucket_name=self.bucket_name) + logger.info(f"Created bucket {self.bucket_name}") + else: + logger.debug(f"Bucket {self.bucket_name} already exists") + + async def add(self, object_id, blob, kind): + """Store blob in S3-compatible storage""" + self.client.put_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + length=len(blob), + data=io.BytesIO(blob), + content_type=kind, + ) + logger.debug("Add blob complete") + + async def remove(self, object_id): + """Delete blob from S3-compatible storage""" + self.client.remove_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + logger.debug("Remove blob complete") + + async def get(self, object_id): + """Retrieve blob from S3-compatible storage""" + resp = self.client.get_object( + bucket_name=self.bucket_name, + object_name=f"doc/{object_id}", + ) + return resp.read() +``` + +## 关键优势 + +1. **无厂商锁定** - 适用于任何兼容 S3 的存储 +2. **轻量级** - MinIO 客户端仅约 500KB +3. **简单配置** - 仅需端点 + 凭据 +4. **无需数据迁移** - 作为后端之间的直接替代方案 +5. **经过严格测试** - MinIO 客户端与所有主要的 S3 实现兼容 + +## 实现状态 + +所有的代码都已更新为使用通用的 S3 参数名称: + +✅ `blob_store.py` - 更新为接受 `endpoint`, `access_key`, `secret_key` +✅ `librarian.py` - 更新了参数名称 +✅ `service.py` - 更新了 CLI 参数和配置 +✅ 文档已更新 + +## 未来增强功能 + +1. **SSL/TLS 支持** - 添加 `--s3-use-ssl` 标志以支持 HTTPS +2. **重试逻辑** - 针对瞬时错误实现指数级退避 +3. **预签名 URL** - 生成临时上传/下载 URL +4. **多区域支持** - 在区域之间复制数据块 +5. **CDN 集成** - 通过 CDN 提供数据块 +6. **存储类别** - 使用 S3 存储类别进行成本优化 +7. **生命周期策略** - 自动归档/删除 +8. **版本控制** - 存储数据块的多个版本 + +## 参考文献 + +MinIO Python 客户端: https://min.io/docs/minio/linux/developers/python/API.html +Ceph RGW S3 API: https://docs.ceph.com/en/latest/radosgw/s3/ +S3 API 参考: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/docs/tech-specs/more-config-cli.ar.md b/docs/tech-specs/more-config-cli.ar.md new file mode 100644 index 00000000..a7553fda --- /dev/null +++ b/docs/tech-specs/more-config-cli.ar.md @@ -0,0 +1,159 @@ +--- +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. **حذف عنصر التكوين**: إزالة عناصر التكوين المحددة + +## الأهداف + +* **التحكم التفصيلي**: تمكين إدارة عناصر التكوين الفردية بدلاً من العمليات المجمعة +* **قائمة بناءً على النوع**: السماح للمستخدمين باستكشاف عناصر التكوين حسب النوع +* **عمليات عنصر واحد**: توفير أوامر للحصول على/تطبيق/حذف عناصر التكوين الفردية +* **تكامل API**: الاستفادة من واجهة API الحالية للتكوين لجميع العمليات +* **نمط سطر أوامر متسق**: اتباع قواعد TrustGraph CLI الراسخة وأنماطها +* **معالجة الأخطاء**: توفير رسائل خطأ واضحة لعمليات غير صالحة +* **إخراج JSON**: دعم الإخراج المنظم للاستخدام البرمجي +* **التوثيق**: تضمين مساعدة شاملة وأمثلة للاستخدام + +## الخلفية + +يوفر TrustGraph حاليًا إدارة التكوين من خلال واجهة API للتكوين وأمر سطر أوامر واحد `tg-show-config` الذي يعرض التكوين بأكمله. على الرغم من أن هذا يعمل في عرض التكوين، إلا أنه يفتقر إلى قدرات الإدارة التفصيلية. + +تشمل القيود الحالية ما يلي: +* لا توجد طريقة لقائمة عناصر التكوين حسب النوع من سطر الأوامر +* لا يوجد أمر سطر أوامر لاسترداد قيم التكوين المحددة +* لا يوجد أمر سطر أوامر لتعيين عناصر التكوين الفردية +* لا يوجد أمر سطر أوامر لحذف عناصر التكوين المحددة + +تتعالج هذه المواصفات هذه الثغرات من خلال إضافة أربعة أوامر سطر أوامر جديدة التي توفر إدارة التكوين التفصيلية. من خلال الكشف عن عمليات واجهة API للتكوين الفردية من خلال أوامر سطر الأوامر، يمكن لـ TrustGraph: +* تمكين إدارة التكوين المبرمجة +* السماح باستكشاف هيكل التكوين حسب النوع +* دعم تحديثات التكوين المستهدفة +* توفير تحكم دقيق في التكوين + +## التصميم الفني + +### الهندسة المعمارية + +يتطلب التكوين المتقدم لسطر الأوامر المكونات الفنية التالية: + +1. **tg-list-config-items** + * قائمة مفاتيح التكوين لنوع معين + * استدعاء طريقة واجهة API `Config.list(type)` + * إخراج قائمة بمفاتيح التكوين + + وحدة: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + * استرداد عنصر تكوين معين(أو أكثر) + * استدعاء طريقة واجهة API `Config.get([ConfigKey(type, key)])` + * إخراج قيم التكوين بتنسيق JSON + + وحدة: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + * تعيين أو تحديث عنصر تكوين + * استدعاء طريقة واجهة API `Config.put([ConfigValue(type, key, value)])` + * قبول معلمات النوع والمفتاح والقيمة + + وحدة: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + * إزالة عنصر تكوين + * استدعاء طريقة واجهة API `Config.delete([ConfigKey(type, key)])` + * قبول معلمات النوع والمفتاح + + وحدة: `trustgraph.cli.delete_config_item` + +### نماذج البيانات + +#### ConfigKey و ConfigValue + +تستخدم الأوامر هياكل البيانات الموجودة من `trustgraph.api.types`: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +يسمح هذا النهج بما يلي: +* معالجة متسقة للبيانات عبر سطر الأوامر وواجهة API +* عمليات تكوين آمنة من النوع +* تنسيقات إدخال/إخراج منظمة +* التكامل مع واجهة API للتكوين الحالية + +### مواصفات سطر الأوامر + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +* **الغرض**: قائمة بمفاتيح التكوين لنمط معين +* **استدعاء واجهة API**: `Config.list(type)` +* **الإخراج**: + * `text` (افتراضي): مفاتيح التكوين مفصولة بأسطر جديدة + * `json`: مصفوفة JSON من مفاتيح التكوين + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +* **الغرض**: استرداد عنصر التكوين المحدد +* **استدعاء واجهة API**: `Config.get([ConfigKey(type, key)])` +* **الإخراج**: + * `text` (افتراضي): سلسلة خام + * `json`: سلسلة JSON منقذة + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value [--api-url ] +tg-put-config-item --type --key --stdin [--api-url ] +``` +* **الغرض**: تعيين أو تحديث عنصر التكوين +* **استدعاء واجهة API**: `Config.put([ConfigValue(type, key, value)])` +* **خيارات الإدخال**: + * `--value `: قيمة + * `--stdin`: إدخال من stdin +* `--key `: المفتاح +* `--type `: النوع + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --key +``` +* **الغرض**: حذف عنصر التكوين +* `--key `: المفتاح +* `--type `: النوع + +## أسئلة مفتوحة + +* هل يجب أن تدعم الأوامر عمليات دفعة (مفاتيح متعددة) بالإضافة إلى العناصر الفردية؟ +* ما هو تنسيق الإخراج الذي يجب استخدامه لإعادة التأكيد على النجاح؟ +* كيف يجب توثيق/اكتشاف أنواع التكوين للمستخدمين؟ + +## المراجع + +* واجهة API للتكوين: `trustgraph/api/config.py` +* أنماط سطر الأوامر: `trustgraph-cli/trustgraph/cli/show_config.py` +* أنواع البيانات: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.es.md b/docs/tech-specs/more-config-cli.es.md new file mode 100644 index 00000000..02210f90 --- /dev/null +++ b/docs/tech-specs/more-config-cli.es.md @@ -0,0 +1,165 @@ +--- +layout: default +title: "Especificación Técnica de la CLI para Configuración" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de la CLI para Configuración + +> **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 mejoradas de configuración a través de la línea de comandos para TrustGraph, lo que permite a los usuarios gestionar elementos de configuración individuales utilizando comandos CLI granulares. La integración soporta cuatro casos de uso principales: + +1. **Listar Elementos de Configuración**: Mostrar las claves de configuración de un tipo específico. +2. **Obtener Elemento de Configuración**: Recuperar los valores de configuración específicos. +3. **Establecer Elemento de Configuración**: Establecer o actualizar elementos de configuración individuales. +4. **Eliminar Elemento de Configuración**: Eliminar elementos de configuración específicos. + +## Objetivos + +- **Control Granular**: Permitir la gestión de elementos de configuración individuales en lugar de operaciones masivas. +- **Listado Basado en Tipo**: Permitir a los usuarios explorar los elementos de configuración por tipo. +- **Operaciones en Elemento Individual**: Proporcionar comandos para obtener/establecer/eliminar elementos de configuración individuales. +- **Integración con API**: Aprovechar la API de Config existente para todas las operaciones. +- **Patrón CLI Consistente**: Seguir las convenciones y patrones CLI establecidos de TrustGraph. +- **Manejo de Errores**: Proporcionar mensajes de error claros para operaciones inválidas. +- **Salida JSON**: Soporte para salida estructurada para uso programático. +- **Documentación**: Incluir ayuda y ejemplos de uso completos. + +## Antecedentes + +Actualmente, TrustGraph proporciona la gestión de la configuración a través de la API de Config y un único comando de línea de comandos `tg-show-config` que muestra toda la configuración. Si bien esto funciona para la visualización de la configuración, carece de capacidades de gestión granular. + +Las limitaciones actuales incluyen: +- No hay forma de listar los elementos de configuración por tipo desde la línea de comandos. +- No hay ningún comando de línea de comandos para recuperar valores de configuración específicos. +- No hay ningún comando de línea de comandos para establecer elementos de configuración individuales. +- No hay ningún comando de línea de comandos para eliminar elementos de configuración específicos. + +Esta especificación aborda estas lagunas agregando cuatro nuevos comandos de línea de comandos que proporcionan la gestión de configuración granular. Al exponer las operaciones de la API de Config individual a través de comandos CLI, TrustGraph puede: +- Permitir la gestión de la configuración a través de scripts. +- Permitir la exploración de la estructura de la configuración por tipo. +- Soporte para actualizaciones de configuración dirigidas. +- Proporcionar un control granular de la configuración. + +## Diseño Técnico + +### Arquitectura + +La configuración CLI mejorada requiere los siguientes componentes técnicos: + +1. **tg-list-config-items** + - Lista las claves de configuración para un tipo específico. + - Llama al método de API `Config.list(type)`. + - Salida la lista de claves de configuración. + + Módulo: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + - Recupera el(los) elemento(s) de configuración específico(s). + - Llama al método de API `Config.get([ConfigKey(type, key)])`. + - Salida los valores de configuración en formato JSON. + + Módulo: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + - Establece o actualiza un elemento de configuración. + - Llama al método de API `Config.put([ConfigValue(type, key, value)])`. + - Acepta los parámetros de tipo, clave y valor. + + Módulo: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + - Elimina un elemento de configuración. + - Llama al método de API `Config.delete([ConfigKey(type, key)])`. + - Acepta los parámetros de tipo y clave. + + Módulo: `trustgraph.cli.delete_config_item` + +### Modelos de Datos + +#### ConfigKey y ConfigValue + +Los comandos utilizan las estructuras de datos existentes de `trustgraph.api.types`: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +Esto permite: +- Manejo de datos consistente entre la CLI y la API. +- Operaciones de configuración seguras por tipo. +- Formatos de entrada/salida estructurados. +- Integración con la API de Config existente. + +### Especificaciones de la CLI + +#### tg-list-config-items +```bash +tg-list-config-items --type [--formato texto|json] [--url-api ] +``` +- **Propósito**: Listar todas las claves de configuración para un tipo dado. +- **Llamada a la API**: `Config.list(type)` +- **Salida**: + - `texto` (predeterminado): Claves de configuración separadas por nuevas líneas. + - `json`: Array JSON de claves de configuración. + +#### tg-get-config-item +```bash +tg-get-config-item --type --clave [--formato texto|json] [--url-api ] +``` +- **Propósito**: Recuperar el elemento de configuración específico. +- **Llamada a la API**: `Config.get([ConfigKey(type, key)])` +- **Salida**: + - `texto` (predeterminado): Cadena de texto sin comillas ni codificación. + - `json`: Cadena de texto codificada en JSON. + +#### tg-put-config-item +```bash +tg-put-config-item --type --clave --valor [--url-api ] +tg-put-config-item --type --clave --stdin [--url-api ] +``` +- **Propósito**: Establecer o actualizar el elemento de configuración. +- **Llamada a la API**: `Config.put([ConfigValue(type, key, value)])` +- **Opciones de entrada**: + - `--valor`: Valor de cadena proporcionado directamente en la línea de comandos. + - `--stdin`: Leer todo el valor de entrada desde la entrada estándar como el valor del elemento de configuración. +- **Salida**: Confirmación de éxito + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --clave [--url-api ] +``` +- **Propósito**: Eliminar el elemento de configuración. +- **Llamada a la API**: `Config.delete([ConfigKey(type, key)])` +- **Salida**: Confirmación de éxito + +### Detalles de Implementación + +- Se debe usar un formato JSON para la salida de la API. +- Se debe usar un formato de texto sin comillas para la salida de la API. +- Se deben usar los parámetros de línea de comandos para especificar el tipo, la clave y el valor. +- Se debe proporcionar una confirmación de éxito para las operaciones de la línea de comandos. + +## Preguntas Abiertas + +- ¿Deberían los comandos admitir operaciones en lote (múltiples claves) además de elementos individuales? +- ¿Cuál debe ser el formato de salida para las confirmaciones de éxito? +- ¿Cómo deberían descubrir los usuarios los tipos de configuración? + +## Referencias + +- API de Config existente: `trustgraph/api/config.py` +- Patrones de CLI: `trustgraph-cli/trustgraph/cli/show_config.py` +- Tipos de datos: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.he.md b/docs/tech-specs/more-config-cli.he.md new file mode 100644 index 00000000..ad479328 --- /dev/null +++ b/docs/tech-specs/more-config-cli.he.md @@ -0,0 +1,151 @@ +--- +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. **מחיקת פריט תצורה**: הסרת פריטי תצורה ספציפיים + +## יעדים + +- **שליטה מפורטת**: אפשר ניהול של פריטי תצורה בודדים ולא פעולות מקובצות +- **רשימה לפי סוג**: לאפשר למשתמשים לחקור פריטי תצורה לפי סוג +- **פעולות על פריט בודד**: לספק פקודות לקבלת/הגדרה/מחיקה של פריטי תצורה בודדים +- **אינטגרציה של API**: לנצל את ה-API הקיים של התצורה עבור כל הפעולות +- **תבנית שורת פקודה עקבית**: לעקוב אחר התקנות והתבניות הסטנדרטיות של TrustGraph +- **טיפול בשגיאות**: לספק הודעות שגיאה ברורות עבור פעולות לא חוקיות +- **פלט JSON**: תמיכה בפלט מובנה לשימוש תכנותי +- **תיעוד**: לכלול עזרה מקיפה ודוגמאות שימוש + +## רקע + +TrustGraph מספקת כיום ניהול תצורה באמצעות ה-API של התצורה ופקודה בודדת בשם `tg-show-config` המציגה את כל התצורה. אמנם זה עובד לצורך הצגת התצורה, אך הוא חסר יכולות ניהול מפורטות. + +הגבלות נוכחיות כוללות: +- אין דרך לרשום פריטי תצורה לפי סוג מתוך שורת הפקודה +- אין פקודה בשורת הפקודה לקבלת ערכי תצורה ספציפיים +- אין פקודה בשורת הפקודה להגדרת פריטי תצורה בודדים +- אין פקודה בשורת הפקודה למחיקת פריטי תצורה ספציפיים + +מסמך זה מטפל בחוסרים אלה על ידי הוספת ארבע פקודות שורת פקודה חדשות המספקות ניהול תצורה מפורט. על ידי חשיפת פעולות API של התצורה הבודדות דרך פקודות שורת פקודה, TrustGraph יכול: +- לאפשר ניהול תצורה מבוסס תסריט +- לאפשר חקירה של מבנה התצורה לפי סוג +- לתמוך בעדכונים ממוקדי תצורה +- לספק שליטה מפורטת על התצורה + +## עיצוב טכני + +### ארכיטקטורה + +התצורה המשופרת של שורת הפקודה דורשת את הרכיבים הטכניים הבאים: + +1. **tg-list-config-items** + - רשימת מפתחות תצורה עבור סוג ספציפי + - קוראת לשיטת ה-API `Config.list(type)` + - פלט של רשימת מפתחות התצורה + + מודול: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + - השגת פריט תצורה ספציפי(ים) + - קוראת לשיטת ה-API `Config.get(keys)` + - פלט של ערכי התצורה בפורמט JSON + + מודול: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + - הגדרת או עדכון פריט תצורה + - קוראת לשיטת ה-API `Config.put(values)` + - מקבל את פרמטרי הטיפוס, המפתח והערך + + מודול: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + - הסרת פריט תצורה + - קוראת לשיטת ה-API `Config.delete(keys)` + - מקבל את פרמטרי הטיפוס והמפתח + + מודול: `trustgraph.cli.delete_config_item` + +### מודלים של נתונים + +#### ConfigKey ו-ConfigValue + +הפקודות משתמשות במבני נתונים הקיימים מ-`trustgraph.api.types`: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +גישה זו מאפשרת: +- טיפול עקבי בנתונים בכל ה-CLI וה-API +- פעולות תצורה מסוג-יציבות +- פורמטי קלט/פלט מובנים +- שילוב עם ה-API של התצורה הקיים + +### מפרטי פקודות שורת הפקודה + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +- **מטרה**: רשימת מפתחות התצורה עבור סוג נתון +- **קריאה ל-API**: `Config.list(type)` +- **פלט**: + - `text` (ברירת מחדל): מפתחות התצורה מופרדים ברווחים + - `json`: מערך JSON של מפתחות התצורה + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +- **מטרה**: השגת פריט תצורה ספציפי +- **קריאה ל-API**: `Config.get([ConfigKey(type, key)])` +- **פלט**: ערך התצורה + +#### הגדרת פריט תצורה +```bash +tg-put-config-item --type --key --value +``` +- **מטרה**: הגדרת או עדכון פריט תצורה +- **קריאה ל-API**: `Config.put(key, value)` +- **פרמטרים**: + - ``: סוג פריט התצורה (לדוגמה, "prompt", "system-prompt") + - ``: המפתח של פריט התצורה + - ``: הערך של פריט התצורה + +#### מחיקת פריט תצורה +```bash +tg-delete-config-item --type --key +``` +- **מטרה**: הסרת פריט תצורה +- **קריאה ל-API**: `Config.delete(key)` +- **פרמטרים**: + - ``: סוג פריט התצורה + - ``: המפתח של פריט התצורה + +## שאלות פתוחות + +- האם יש לשנות את הפקודות לתמוך בפעולות מקובצות (מפתחות מרובים) בנוסף לפריטים בודדים? +- איזה פורמט פלט צריך להיות בשימוש עבור אישור הצלחה? +- איך המשתמשים יכולים לגלות או לתעד את סוגי התצורה? diff --git a/docs/tech-specs/more-config-cli.hi.md b/docs/tech-specs/more-config-cli.hi.md new file mode 100644 index 00000000..5aec5d4e --- /dev/null +++ b/docs/tech-specs/more-config-cli.hi.md @@ -0,0 +1,203 @@ +--- +layout: default +title: "अधिक कॉन्फ़िगरेशन CLI तकनीकी विनिर्देश" +parent: "Hindi (Beta)" +--- + +```hindi +# अधिक कॉन्फ़िगरेशन 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 के लिए उन्नत कमांड-लाइन कॉन्फ़िगरेशन क्षमताओं का वर्णन करता है, जो उपयोगकर्ताओं को दानेदार CLI कमांड के माध्यम से व्यक्तिगत कॉन्फ़िगरेशन आइटम प्रबंधित करने की अनुमति देता है। यह एकीकरण चार प्राथमिक उपयोग मामलों का समर्थन करता है: + +1. **कॉन्फ़िगरेशन आइटमों की सूची**: किसी विशिष्ट प्रकार की कॉन्फ़िगरेशन कुंजियों का प्रदर्शन करें। +2. **कॉन्फ़िगरेशन आइटम प्राप्त करें**: विशिष्ट कॉन्फ़िगरेशन मान पुनः प्राप्त करें। +3. **कॉन्फ़िगरेशन आइटम सेट करें**: व्यक्तिगत कॉन्फ़िगरेशन आइटम सेट या अपडेट करें। +4. **कॉन्फ़िगरेशन आइटम हटाएं**: विशिष्ट कॉन्फ़िगरेशन आइटम हटाएं। + +## लक्ष्य + +- **बारीक नियंत्रण**: व्यक्तिगत कॉन्फ़िगरेशन आइटमों के प्रबंधन को सक्षम करें, न कि बल्क ऑपरेशनों को। +- **प्रकार-आधारित सूची**: उपयोगकर्ताओं को कॉन्फ़िगरेशन आइटमों को प्रकार के अनुसार ब्राउज़ करने की अनुमति दें। +- **एकल आइटम संचालन**: व्यक्तिगत कॉन्फ़िगरेशन आइटमों के लिए प्राप्त/सेट/हटाने के कमांड प्रदान करें। +- **API एकीकरण**: सभी परिचालनों के लिए मौजूदा कॉन्फ़िगरेशन API का उपयोग करें। +- **संगत CLI पैटर्न**: स्थापित TrustGraph CLI कन्वेंशन और पैटर्न का पालन करें। +- **त्रुटि प्रबंधन**: अमान्य परिचालनों के लिए स्पष्ट त्रुटि संदेश प्रदान करें। +- **JSON आउटपुट**: प्रोग्रामेटिक उपयोग के लिए संरचित आउटपुट का समर्थन करें। +- **प्रलेखन**: व्यापक सहायता और उपयोग उदाहरण शामिल करें। + +## पृष्ठभूमि + +TrustGraph वर्तमान में कॉन्फ़िगरेशन API और एक एकल CLI कमांड `tg-show-config` के माध्यम से कॉन्फ़िगरेशन प्रबंधन प्रदान करता है जो संपूर्ण कॉन्फ़िगरेशन प्रदर्शित करता है। जबकि यह कॉन्फ़िगरेशन देखने के लिए उपयोगी है, यह दानेदार प्रबंधन क्षमताओं की कमी है। + +वर्तमान सीमाएँ शामिल हैं: +- CLI से प्रकार के अनुसार कॉन्फ़िगरेशन आइटमों की सूची बनाने का कोई तरीका नहीं है। +- विशिष्ट कॉन्फ़िगरेशन मान पुनः प्राप्त करने के लिए कोई CLI कमांड नहीं है। +- व्यक्तिगत कॉन्फ़िगरेशन आइटमों को सेट करने के लिए कोई CLI कमांड नहीं है। +- विशिष्ट कॉन्फ़िगरेशन आइटमों को हटाने के लिए कोई CLI कमांड नहीं है। + +यह विनिर्देश इन कमियों को चार नए CLI कमांड जोड़कर संबोधित करता है जो दानेदार कॉन्फ़िगरेशन प्रबंधन प्रदान करते हैं। TrustGraph, CLI कमांड के माध्यम से व्यक्तिगत कॉन्फ़िगरेशन API परिचालनों को उजागर करके: +- स्क्रिप्टेड कॉन्फ़िगरेशन प्रबंधन को सक्षम करें। +- प्रकार के अनुसार कॉन्फ़िगरेशन संरचना की खोज की अनुमति दें। +- लक्षित कॉन्फ़िगरेशन अपडेट का समर्थन करें। +- कॉन्फ़िगरेशन नियंत्रण का महीन स्तर प्रदान करें। + +## तकनीकी डिजाइन + +### आर्किटेक्चर + +उन्नत CLI कॉन्फ़िगरेशन के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है: + +1. **tg-list-config-items** + - एक निर्दिष्ट प्रकार के लिए कॉन्फ़िगरेशन कुंजियों की सूची बनाता है। + - `Config.list(type)` API विधि को कॉल करता है। + - कॉन्फ़िगरेशन कुंजियों की सूची आउटपुट करता है। + + मॉड्यूल: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + - विशिष्ट कॉन्फ़िगरेशन आइटम(ों) को पुनः प्राप्त करता है। + - `Config.get(keys)` API विधि को कॉल करता है। + - कॉन्फ़िगरेशन मानों को JSON प्रारूप में आउटपुट करता है। + + मॉड्यूल: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + - एक कॉन्फ़िगरेशन आइटम सेट या अपडेट करता है। + - `Config.put(values)` API विधि को कॉल करता है। + - प्रकार, कुंजी और मान पैरामीटर स्वीकार करता है। + + मॉड्यूल: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + - एक कॉन्फ़िगरेशन आइटम हटाता है। + - `Config.delete(keys)` API विधि को कॉल करता है। + - प्रकार और कुंजी पैरामीटर स्वीकार करता है। + + मॉड्यूल: `trustgraph.cli.delete_config_item` + +### डेटा मॉडल + +#### ConfigKey और ConfigValue + +कमांड `trustgraph.api.types` से मौजूदा डेटा संरचनाओं का उपयोग करते हैं: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +यह दृष्टिकोण अनुमति देता है: +- CLI और API में सुसंगत डेटा प्रबंधन। +- प्रकार-सुरक्षित कॉन्फ़िगरेशन संचालन। +- संरचित इनपुट/आउटपुट प्रारूप। +- मौजूदा कॉन्फ़िगरेशन API के साथ एकीकरण। + +### CLI कमांड विनिर्देश + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +- **उद्देश्य**: एक दिए गए प्रकार के सभी कॉन्फ़िगरेशन कुंजियों की सूची बनाएं। +- **API कॉल**: `Config.list(type)` +- **आउटपुट**: + - `text` (डिफ़ॉल्ट): कॉन्फ़िगरेशन कुंजियाँ नई पंक्तियों से अलग की गई हैं। + - `json`: कॉन्फ़िगरेशन कुंजियों की JSON सरणी। + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +- **उद्देश्य**: एक विशिष्ट कॉन्फ़िगरेशन आइटम पुनः प्राप्त करें। +- **API कॉल**: `Config.get([ConfigKey(type, key)])` +- **आउटपुट**: + - `text` (डिफ़ॉल्ट): कच्चा स्ट्रिंग मान। + - `json`: JSON-एन्कोडेड स्ट्रिंग मान। + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value [--api-url ] +tg-put-config-item --type --key --stdin [--api-url ] +``` +- **उद्देश्य**: एक कॉन्फ़िगरेशन आइटम सेट करें। +- **API कॉल**: `Config.put(values)` +- **पैरामीटर**: प्रकार, कुंजी और मान। +- **इनपुट**: कमांड लाइन या stdin के माध्यम से। + +#### tg-delete-config-item +```bash +tg-delete-config-item --type prompt --key old-template +``` +- **उद्देश्य**: एक कॉन्फ़िगरेशन आइटम हटाएं। +- **API कॉल**: `Config.delete(keys)` +- **पैरामीटर**: प्रकार और कुंजी। + +## उपयोग उदाहरण + +#### कॉन्फ़िगरेशन आइटमों की सूची +```bash +# प्रॉम्प्ट कुंजियों की सूची (टेक्स्ट प्रारूप) +tg-list-config-items --type prompt +template-1 +template-2 +system-prompt + +# प्रॉम्प्ट कुंजियों की सूची (JSON प्रारूप) +tg-list-config-items --type prompt --format json +["template-1", "template-2", "system-prompt"] +``` + +#### कॉन्फ़िगरेशन आइटम प्राप्त करें +```bash +# प्रॉम्प्ट मान प्राप्त करें (टेक्स्ट प्रारूप) +tg-get-config-item --type prompt --key template-1 +You are a helpful assistant. Please respond to: {query} + +# प्रॉम्प्ट मान प्राप्त करें (JSON प्रारूप) +tg-get-config-item --type prompt --key template-1 --format json +"You are a helpful assistant. Please respond to: {query}" +``` + +#### कॉन्फ़िगरेशन आइटम सेट करें +```bash +# कमांड लाइन से सेट करें +tg-put-config-item --type prompt --key new-template --value "Custom prompt: {input}" + +# फ़ाइल से पाइप के माध्यम से सेट करें +cat ./prompt-template.txt | tg-put-config-item --type prompt --key complex-template --stdin + +# फ़ाइल से रीडायरेक्ट के माध्यम से सेट करें +tg-put-config-item --type prompt --key complex-template --stdin < ./prompt-template.txt + +# कमांड आउटपुट से सेट करें +echo "Generated template: {query}" | tg-put-config-item --type prompt --key auto-template --stdin +``` + +#### कॉन्फ़िगरेशन आइटम हटाएं +```bash +tg-delete-config-item --type prompt --key old-template +``` + +## खुले प्रश्न + +- क्या कमांड एकल आइटमों के अलावा बैच संचालन (एकाधिक कुंजियाँ) का समर्थन करना चाहिए? +- सफलता की पुष्टि के लिए किस आउटपुट प्रारूप का उपयोग किया जाना चाहिए? +- उपयोगकर्ताओं द्वारा कॉन्फ़िगरेशन प्रकारों का दस्तावेजीकरण/खोज कैसे किया जाना चाहिए? + +## संदर्भ + +- मौजूदा कॉन्फ़िगरेशन API: `trustgraph/api/config.py` +- CLI पैटर्न: `trustgraph-cli/trustgraph/cli/show_config.py` +- डेटा प्रकार: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.md b/docs/tech-specs/more-config-cli.md index 6cae9e13..0bcd7be9 100644 --- a/docs/tech-specs/more-config-cli.md +++ b/docs/tech-specs/more-config-cli.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "More Configuration CLI Technical Specification" +parent: "Tech Specs" +--- + # More Configuration CLI Technical Specification ## Overview @@ -276,4 +282,4 @@ tg-delete-config-item --type prompt --key old-template - Existing Config API: `trustgraph/api/config.py` - CLI patterns: `trustgraph-cli/trustgraph/cli/show_config.py` -- Data types: `trustgraph/api/types.py` \ No newline at end of file +- Data types: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.pt.md b/docs/tech-specs/more-config-cli.pt.md new file mode 100644 index 00000000..cc15631b --- /dev/null +++ b/docs/tech-specs/more-config-cli.pt.md @@ -0,0 +1,287 @@ +--- +layout: default +title: "Mais Configurações - Especificação Técnica da Interface de Linha de Comando (CLI)" +parent: "Portuguese (Beta)" +--- + +# Mais Configurações - Especificação Técnica da Interface de Linha de Comando (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. + +## Visão Geral + +Esta especificação descreve as capacidades aprimoradas de configuração por meio da interface de linha de comando para o TrustGraph, permitindo que os usuários gerenciem itens de configuração individuais por meio de comandos de linha de comando granulares. A integração suporta quatro casos de uso primários: + +1. **Listar Itens de Configuração**: Exibir chaves de configuração de um tipo específico +2. **Obter Item de Configuração**: Recuperar valores de configuração específicos +3. **Definir Item de Configuração**: Definir ou atualizar itens de configuração individuais +4. **Excluir Item de Configuração**: Remover itens de configuração específicos + +## Objetivos + +**Controle Granular**: Permitir o gerenciamento de itens de configuração individuais, em vez de operações em lote +**Listagem Baseada em Tipo**: Permitir que os usuários explorem itens de configuração por tipo +**Operações de Item Único**: Fornecer comandos para obter/definir/excluir itens de configuração individuais +**Integração com a API**: Utilizar a API de Configuração existente para todas as operações +**Padrão de CLI Consistente**: Seguir as convenções e padrões de CLI do TrustGraph estabelecidos +**Tratamento de Erros**: Fornecer mensagens de erro claras para operações inválidas +**Saída JSON**: Suportar saída estruturada para uso programático +**Documentação**: Incluir ajuda abrangente e exemplos de uso + +## Contexto + +Atualmente, o TrustGraph fornece gerenciamento de configuração por meio da API de Configuração e um único comando de linha de comando `tg-show-config` que exibe toda a configuração. Embora isso funcione para visualizar a configuração, ele carece de capacidades de gerenciamento granular. + +As limitações atuais incluem: +Não há como listar itens de configuração por tipo a partir da linha de comando +Não há comando de linha de comando para recuperar valores de configuração específicos +Não há comando de linha de comando para definir itens de configuração individuais +Não há comando de linha de comando para excluir itens de configuração específicos + +Esta especificação aborda essas lacunas, adicionando quatro novos comandos de linha de comando que fornecem gerenciamento de configuração granular. Ao expor operações individuais da API de Configuração por meio de comandos de linha de comando, o TrustGraph pode: +Permitir o gerenciamento de configuração por script +Permitir a exploração da estrutura de configuração por tipo +Suportar atualizações de configuração direcionadas +Fornecer controle de configuração granular + +## Design Técnico + +### Arquitetura + +A configuração aprimorada da linha de comando requer os seguintes componentes técnicos: + +1. **tg-list-config-items** + Lista chaves de configuração para um tipo especificado + Chama o método da API Config.list(type) + Exibe a lista de chaves de configuração + + Módulo: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + Recupera um(s) item(ns) de configuração específico(s) + Chama o método da API Config.get(keys) + Exibe os valores de configuração em formato JSON + + Módulo: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + Define ou atualiza um item de configuração + Chama o método da API Config.put(values) + Aceita parâmetros de tipo, chave e valor + + Módulo: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + Remove um item de configuração + Chama o método da API Config.delete(keys) + Aceita parâmetros de tipo e chave + + Módulo: `trustgraph.cli.delete_config_item` + +### Modelos de Dados + +#### ConfigKey e ConfigValue + +Os comandos utilizam as estruturas de dados existentes de `trustgraph.api.types`: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +Esta abordagem permite: +Tratamento de dados consistente entre a interface de linha de comando (CLI) e a API. +Operações de configuração com segurança de tipo. +Formatos de entrada/saída estruturados. +Integração com a API de Configuração existente. + +### Especificações de comandos da CLI + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +**Propósito**: Listar todas as chaves de configuração para um determinado tipo. +**Chamada da API**: `Config.list(type)` +**Saída**: + `text` (padrão): Chaves de configuração separadas por quebras de linha. + `json`: Array JSON de chaves de configuração. + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +**Propósito**: Recuperar um item de configuração específico. +**Chamada da API**: `Config.get([ConfigKey(type, key)])` +**Saída**: + `text` (padrão): Valor de string bruto. + `json`: Valor de string codificado em JSON. + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value [--api-url ] +tg-put-config-item --type --key --stdin [--api-url ] +``` +**Propósito**: Definir ou atualizar um item de configuração. +**Chamada da API**: `Config.put([ConfigValue(type, key, value)])` +**Opções de Entrada**: + `--value`: Valor de string fornecido diretamente na linha de comando. + `--stdin`: Ler o valor da entrada padrão. +**Saída**: Confirmação de sucesso. + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --key [--api-url ] +``` +**Propósito**: Excluir item de configuração +**Chamada da API**: `Config.delete([ConfigKey(type, key)])` +**Saída**: Confirmação de sucesso + +### Detalhes da Implementação + +Todos os comandos seguem o padrão estabelecido da CLI TrustGraph: +Use `argparse` para análise de argumentos da linha de comando +Importe e use `trustgraph.api.Api` para comunicação com o backend +Siga os mesmos padrões de tratamento de erros dos comandos da CLI existentes +Suporte ao parâmetro padrão `--api-url` para configuração do endpoint da API +Forneça texto de ajuda descritivo e exemplos de uso + +#### Tratamento do Formato de Saída + +**Formato de Texto (Padrão)**: +`tg-list-config-items`: Uma chave por linha, texto simples +`tg-get-config-item`: Valor de string bruto, sem aspas ou codificação + +**Formato JSON**: +`tg-list-config-items`: Array de strings `["key1", "key2", "key3"]` +`tg-get-config-item`: Valor de string codificado em JSON `"actual string value"` + +#### Tratamento da Entrada + +**tg-put-config-item** suporta dois métodos de entrada mutuamente exclusivos: +`--value `: Valor de string direto na linha de comando +`--stdin`: Leia toda a entrada da entrada padrão como o valor de configuração +O conteúdo da entrada padrão é lido como texto bruto (preservando novas linhas, espaços em branco, etc.) +Suporta o envio por pipe de arquivos, comandos ou entrada interativa + +## Considerações de Segurança + +**Validação da Entrada**: Todos os parâmetros da linha de comando devem ser validados antes das chamadas da API +**Autenticação da API**: Os comandos herdam os mecanismos de autenticação da API existentes +**Acesso à Configuração**: Os comandos respeitam os controles de acesso à configuração existentes +**Informações de Erro**: As mensagens de erro não devem vazar detalhes confidenciais da configuração + +## Considerações de Desempenho + +**Operações de Item Único**: Os comandos são projetados para itens individuais, evitando a sobrecarga de operações em lote +**Eficiência da API**: As chamadas diretas da API minimizam as camadas de processamento +**Latência da Rede**: Cada comando faz uma chamada de API, minimizando as viagens de ida e volta na rede +**Uso de Memória**: Pegada de memória mínima para operações de item único + +## Estratégia de Teste + +**Testes Unitários**: Teste cada módulo de comando da CLI independentemente +**Testes de Integração**: Teste os comandos da CLI contra a API de Configuração em tempo real +**Testes de Tratamento de Erros**: Verifique o tratamento adequado de erros para entradas inválidas +**Compatibilidade da API**: Garanta que os comandos funcionem com as versões existentes da API de Configuração + +## Plano de Migração + +Nenhuma migração necessária - estes são novos comandos da CLI que complementam a funcionalidade existente: +O comando `tg-show-config` existente permanece inalterado +Novos comandos podem ser adicionados incrementalmente +Nenhuma alteração disruptiva nos fluxos de trabalho de configuração existentes + +## Empacotamento e Distribuição + +Estes comandos serão adicionados ao pacote `trustgraph-cli` existente: + +**Localização do Pacote**: `trustgraph-cli/` +**Arquivos do Módulo**: +`trustgraph-cli/trustgraph/cli/list_config_items.py` +`trustgraph-cli/trustgraph/cli/get_config_item.py` +`trustgraph-cli/trustgraph/cli/put_config_item.py` +`trustgraph-cli/trustgraph/cli/delete_config_item.py` + +**Pontos de Entrada**: Adicionados a `trustgraph-cli/pyproject.toml` na seção `[project.scripts]`: +```toml +tg-list-config-items = "trustgraph.cli.list_config_items:main" +tg-get-config-item = "trustgraph.cli.get_config_item:main" +tg-put-config-item = "trustgraph.cli.put_config_item:main" +tg-delete-config-item = "trustgraph.cli.delete_config_item:main" +``` + +## Tarefas de Implementação + +1. **Criar Módulos CLI**: Implementar os quatro módulos de comando CLI em `trustgraph-cli/trustgraph/cli/` +2. **Atualizar pyproject.toml**: Adicionar novos pontos de entrada de comando em `trustgraph-cli/pyproject.toml` +3. **Documentação**: Criar documentação CLI para cada comando em `docs/cli/` +4. **Testes**: Implementar cobertura de testes abrangente +5. **Integração**: Garantir que os comandos funcionem com a infraestrutura TrustGraph existente +6. **Construção do Pacote**: Verificar se os comandos são instalados corretamente com `pip install trustgraph-cli` + +## Exemplos de Uso + +#### Listar itens de configuração +```bash +# List prompt keys (text format) +tg-list-config-items --type prompt +template-1 +template-2 +system-prompt + +# List prompt keys (JSON format) +tg-list-config-items --type prompt --format json +["template-1", "template-2", "system-prompt"] +``` + +#### Obter item de configuração +```bash +# Get prompt value (text format) +tg-get-config-item --type prompt --key template-1 +You are a helpful assistant. Please respond to: {query} + +# Get prompt value (JSON format) +tg-get-config-item --type prompt --key template-1 --format json +"You are a helpful assistant. Please respond to: {query}" +``` + +#### Definir item de configuração +```bash +# Set from command line +tg-put-config-item --type prompt --key new-template --value "Custom prompt: {input}" + +# Set from file via pipe +cat ./prompt-template.txt | tg-put-config-item --type prompt --key complex-template --stdin + +# Set from file via redirect +tg-put-config-item --type prompt --key complex-template --stdin < ./prompt-template.txt + +# Set from command output +echo "Generated template: {query}" | tg-put-config-item --type prompt --key auto-template --stdin +``` + +#### Excluir item de configuração +```bash +tg-delete-config-item --type prompt --key old-template +``` + +## Perguntas Abertas + +Os comandos devem suportar operações em lote (múltiplas chaves) além de itens individuais? +Qual formato de saída deve ser usado para confirmações de sucesso? +Como os tipos de configuração devem ser documentados/descobertos pelos usuários? + +## Referências + +API de Configuração existente: `trustgraph/api/config.py` +Padrões de CLI: `trustgraph-cli/trustgraph/cli/show_config.py` +Tipos de dados: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.ru.md b/docs/tech-specs/more-config-cli.ru.md new file mode 100644 index 00000000..65fa65f1 --- /dev/null +++ b/docs/tech-specs/more-config-cli.ru.md @@ -0,0 +1,210 @@ +--- +layout: default +title: "Техническая спецификация CLI для конфигурации" +parent: "Russian (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. + +## Обзор + +Эта спецификация описывает расширенные возможности конфигурации через командную строку для TrustGraph, позволяя пользователям управлять отдельными элементами конфигурации с помощью команд CLI с гранулярным уровнем доступа. Интеграция поддерживает четыре основных сценария использования: + +1. **Перечисление элементов конфигурации**: Отображение ключей конфигурации определенного типа +2. **Получение элемента конфигурации**: Получение конкретных значений конфигурации +3. **Установка элемента конфигурации**: Установка или обновление отдельных элементов конфигурации +4. **Удаление элемента конфигурации**: Удаление конкретных элементов конфигурации + +## Цели + +- **Детализированный контроль**: Обеспечение управления отдельными элементами конфигурации, а не пакетными операциями +- **Список по типу**: Предоставление пользователям возможности исследовать элементы конфигурации по типу +- **Операции для отдельных элементов**: Предоставление команд для получения/установки/удаления отдельных элементов конфигурации +- **Интеграция с API**: Использование существующего API для конфигурации для всех операций +- **Единый шаблон CLI**: Соблюдение установленных норм и шаблонов CLI для TrustGraph +- **Обработка ошибок**: Предоставление понятных сообщений об ошибках для некорректных операций +- **Вывод в формате JSON**: Поддержка структурированного вывода для программного использования +- **Документация**: Включение подробной справки и примеров использования + +## Предыстория + +TrustGraph в настоящее время предоставляет управление конфигурацией через API для конфигурации и один командный интерфейс `tg-show-config`, который отображает всю конфигурацию. Хотя это работает для просмотра конфигурации, оно не обеспечивает возможности детального управления. + +Текущие ограничения включают: +- Отсутствие возможности перечисления элементов конфигурации по типу через командную строку +- Отсутствие командной строки для получения конкретных значений конфигурации +- Отсутствие командной строки для установки отдельных элементов конфигурации +- Отсутствие командной строки для удаления отдельных элементов конфигурации + +Эта спецификация решает эти проблемы, добавляя четыре новые команды CLI, которые обеспечивают детальное управление конфигурацией. Предоставляя отдельные операции API через команды CLI, TrustGraph может: +- Обеспечить управление конфигурацией через скрипты +- Предоставить пользователям возможность исследовать структуру конфигурации по типу +- Обеспечить целевые обновления конфигурации +- Обеспечить детальный контроль над конфигурацией + +## Техническое проектирование + +### Архитектура + +Для расширенного CLI необходимо следующее техническое: + +1. **tg-list-config-items** + - Перечисление ключей конфигурации для указанного типа + - Вызов API-метода Config.list(type) + - Вывод списка ключей конфигурации + + Модуль: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + - Получение конкретного элемента конфигурации(й) + - Вызов API-метода Config.get(keys) + - Вывод значений конфигурации в формате JSON + + Модуль: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + - Установка или обновление элемента конфигурации + - Вызов API-метода Config.put(values) + - Прием параметров type, key и value + + Модуль: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + - Удаление элемента конфигурации + - Вызов API-метода Config.delete(keys) + - Прием параметров type и key + + Модуль: `trustgraph.cli.delete_config_item` + +### Модели данных + +#### ConfigKey и ConfigValue + +Команды используют существующие структуры данных из `trustgraph.api.types`: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +Это обеспечивает: +- Последовательную обработку данных в CLI и API +- Типобезопасное управление конфигурацией +- Структурированные форматы ввода/вывода +- Интеграцию с существующим API для конфигурации + +### Спецификации команд CLI + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +- **Назначение**: Отобразить все ключи конфигурации для данного типа +- **API-вызов**: `Config.list(type)` +- **Вывод**: + - `text` (по умолчанию): Ключи конфигурации, разделенные новыми строками + - `json`: Массив строк JSON с ключами конфигурации + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +- **Назначение**: Получить конкретный элемент конфигурации +- **API-вызов**: `Config.get([ConfigKey(type, key)])` +- **Вывод**: + - `text` (по умолчанию): Сырая текстовая строка + - `json`: JSON-кодированная строка значения + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value [--api-url ] +tg-put-config-item --type --key --stdin [--api-url ] +``` +- **Назначение**: Установить или обновить элемент конфигурации +- **API-вызов**: `Config.put([ConfigValue(type, key, value)])` +- **Варианты ввода**: + - `--value <строка>`: Строковое значение, указанное непосредственно в командной строке + - `--stdin`: Чтение всего ввода как значения конфигурации +- **Вывод**: Подтверждение успеха + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --key [--api-url ] +``` +- **Назначение**: Удалить элемент конфигурации +- **API-вызов**: `Config.delete([ConfigKey(type, key)])` +- **Вывод**: Подтверждение успеха + +### Детали реализации + +Все команды следуют установленной схеме CLI для TrustGraph: +- Использование `argparse` для разбора командной строки +- Импорт и использование `trustgraph.api.Api` для взаимодействия с backend +- Соблюдение тех же схем обработки ошибок, что и у существующих CLI +- Поддержка стандартного параметра `--api-url` для настройки URL API +- Предоставление описательного справки и примеров использования + +#### Обработка форматов вывода + +**Текст:** +```bash +tg-list-config-items --type prompt +template-1 +template-2 +system-prompt +``` + +**JSON:** +```bash +tg-list-config-items --type prompt --format json +["template-1", "template-2", "system-prompt"] +``` + +**Текст:** +```bash +tg-get-config-item --type prompt --key template-1 +You are a helpful assistant. Please respond to: {query} +``` + +**JSON:** +```bash +tg-get-config-item --type prompt --key template-1 --format json +"You are a helpful assistant. Please respond to: {query}" +``` + +**Текст:** +```bash +tg-put-config-item --type prompt --key new-template --value "Custom prompt: {input}" +``` + +**JSON:** +```bash +tg-put-config-item --type prompt --key complex-template --stdin < ./prompt-template.txt +``` + +**Текст:** +```bash +tg-delete-config-item --type prompt --key old-template +``` + +## Открытые вопросы + +- Следует ли командам поддерживать пакетные операции (несколько ключей) помимо отдельных элементов? +- Какой формат вывода следует использовать для подтверждений успеха? +- Как следует документировать и узнавать пользователями типы конфигурации? + +## Ссылки + +- Существующий API для конфигурации: `trustgraph/api/config.py` +- Шаблоны CLI: `trustgraph-cli/trustgraph/cli/show_config.py` +- Типы данных: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.sw.md b/docs/tech-specs/more-config-cli.sw.md new file mode 100644 index 00000000..f4f7f3ac --- /dev/null +++ b/docs/tech-specs/more-config-cli.sw.md @@ -0,0 +1,205 @@ +--- +layout: default +title: "Vipimo vya Zusisi vya Amri ya Utekelezaji (CLI)" +parent: "Swahili (Beta)" +--- + +# Vipimo vya Zusisi vya Amri ya Utekelezaji (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. + +## Muhtasari + +Haya yanaeleza uwezo wa ziada wa usanidi wa amri ya utekelezaji (CLI) kwa TrustGraph, ambayo inaruhusu watumiaji kusimamia vipengele vya usanidi kila kimoja kupitia amri mahususi za CLI. Uunganisho huu unaunga mkono matumizi manne makuu: + +1. **Orodha ya Vipengele vya Usanidi**: Kuonyesha funguo za usanidi za aina fulani. +2. **Pata Kipengele cha Usanidi**: Kuchukua maadili maalum ya usanidi. +3. **Weka Kipengele cha Usanidi**: Kuweka au kusasisha vipengele vya usanidi. +4. **Futa Kipengele cha Usanidi**: Kuondoa vipengele vya usanidi. + +## Malengo + +- **Usimamizi Mahususi**: Kuwezesha usimamizi wa vipengele vya usanidi kila kimoja badala ya shughuli za jumla. +- **Orodha Kulingana na Aina**: Kuruhusu watumiaji kuchunguza vipengele vya usanidi kwa aina. +- **Shughuli za Kipengele Kimoja**: Kutoa amri za kupata/kuweka/kufuta vipengele vya usanidi kila kimoja. +- **Uunganisho wa API**: Kutumia API ya Usanidi iliyopo kwa shughuli zote. +- **Mifumo ya Utekelezaji ya Umoja**: Kufuata misingi na mifumo iliyopo ya CLI ya TrustGraph. +- **Usimamizi wa Makosa**: Kutoa ujumbe wazi wa makosa kwa shughuli zisizo halali. +- **Pato la JSON**: Kusaidia pato lililopangwa kwa matumizi ya programu. +- **Wasifu**: Kuweka msaada kamili na mifano ya matumizi. + +## Licha + +Hivi sasa, TrustGraph hutoa usimamizi wa usanidi kupitia API ya Usanidi na amri moja ya CLI, `tg-show-config`, ambayo inaonyesha usanidi wote. Ingawa hii inafaa kwa kuona usanidi, haitoi uwezo wa usimamizi wa kina. + +Hali ya sasa ya kikwazo ni pamoja na: +- Hakuna njia ya kuorodisha vipengele vya usanidi kwa aina kutoka kwa CLI. +- Hakuna amri ya CLI ya kuchukua maadili maalum ya usanidi. +- Hakuna amri ya CLI ya kuweka vipengele vya usanidi kila kimoja. +- Hakuna amri ya CLI ya kufuta vipengele maalum vya usanidi. + +Haya yanaashiria pengo hili kwa kuongeza amri nne mpya za CLI ambazo hutoa usimamizi wa kina wa usanidi. Kwa kufichua shughuli za API ya Usanidi kupitia amri za CLI, TrustGraph inaweza: +- Kuwezesha usimamizi wa usanidi kwa njia ya programu. +- Kuruhusu kuchunguza muundo wa usanidi kwa aina. +- Kusaidia sasisho maalumu ya usanidi. +- Kutoa udhibiti wa kina wa usanidi. + +## Muundo wa Kiufundi + +### Usanifu + +Utekelezaji wa ziada wa usanidi wa CLI unahitaji vipengele hivi vya kiufundi: + +1. **tg-list-config-items** + - Huorodhesha funguo za usanidi kwa aina iliyoelezwa. + - Huita njia ya API `Config.list(type)`. + - Huonyesha orodha ya funguo za usanidi. + + Moduli: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + - Inachukua kipengele(s) maalum(s) cha usanidi. + - Huita njia ya API `Config.get(keys)`. + - Inaonyesha maadili ya usanidi katika umbizo la JSON. + + Moduli: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + - Inaweka au kusasisha kipengele cha usanidi. + - Huita njia ya API `Config.put(values)`. + - Inakubali vigezo vya aina, funguo, na thamani. + + Moduli: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + - Inaondoa kipengele cha usanidi. + - Huita njia ya API `Config.delete(keys)`. + - Inakubali vigezo vya aina na funguo. + + Moduli: `trustgraph.cli.delete_config_item` + +### Mifano ya Data + +#### ConfigKey na ConfigValue + +Amri hizi hutumia miundo ya data iliyopo kutoka `trustgraph.api.types`: + +```python +@dataclasses.dataclass +class ConfigKey: + type : string + key : string + +@dataclasses.dataclass +class ConfigValue: + type : string + key : string + value : string +``` + +Mbinu hii inaruhusu: +- Usimamizi wa data thabiti katika CLI na API. +- Shughuli za usanidi salama za aina. +- Umbizo la pembejeo/patou lililopangwa. +- Uunganisho na API ya Usanidi iliyopo. + +### Maelezo ya Amri ya CLI + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +- **Lengo**: Kuorodisha funguo zote za usanidi kwa aina iliyopewa. +- **Wito wa API**: `Config.list(type)` +- **Pato**: + - `text` (cha kawaida): Funguo za usanidi zilizotenganishwa na mistari mipya. + - `json`: Safu ya JSON ya funguo za usanidi. + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +- **Lengo**: Kuchukua kipengele maalum cha usanidi. +- **Wito wa API**: `Config.get(keys)` +- **Pato**: + - `text` (cha kawaida): Thamani ya usanidi. + - `json`: Thamani ya usanidi katika umbizo la JSON. + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value +``` +- **Lengo**: Kuweka thamani ya usanidi. +- **Wito wa API**: `Config.put(values)` +- **Ingizo**: + - `type`: Aina ya usanidi. + - `key`: Funguo ya usanidi. + - `value`: Thamani ya usanidi. + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --key +``` +- **Lengo**: Kuondoa kipengele cha usanidi. +- **Wito wa API**: `Config.delete(keys)` +- **Ingizo**: + - `type`: Aina ya usanidi. + - `key`: Funguo ya usanidi. + +## Mifano ya Matumizi + +#### Kuorodisha vipengele vya usanidi +```bash +# Kuorodisha funguo za prompt (umbizo la maandishi) +tg-list-config-items --type prompt +template-1 +template-2 +system-prompt + +# Kuorodisha funguo za prompt (umbizo la JSON) +tg-list-config-items --type prompt --format json +["template-1", "template-2", "system-prompt"] +``` + +#### Kupata kipengele cha usanidi +```bash +# Kupata thamani ya prompt (umbizo la maandishi) +tg-get-config-item --type prompt --key template-1 +You are a helpful assistant. Please respond to: {query} + +# Kupata thamani ya prompt (umbizo la JSON) +tg-get-config-item --type prompt --key template-1 --format json +"You are a helpful assistant. Please respond to: {query}" +``` + +#### Kuweka kipengele cha usanidi +```bash +# Kuweka kutoka kwa mstari wa amri +tg-put-config-item --type prompt --key new-template --value "Custom prompt: {input}" + +# Kuweka kutoka kwa faili kupitia bomba +cat ./prompt-template.txt | tg-put-config-item --type prompt --key complex-template --stdin + +# Kuweka kutoka kwa faili kupitia urejeshaji +tg-put-config-item --type prompt --key complex-template --stdin < ./prompt-template.txt + +# Kuweka kutoka kwa pato la amri +echo "Generated template: {query}" | tg-put-config-item --type prompt --key auto-template --stdin +``` + +#### Kufuta kipengele cha usanidi +```bash +tg-delete-config-item --type prompt --key old-template +``` + +## Masuala Yaliyoshindikana + +- Je, amri zinapaswa kusaidia shughuli za kundi (funguo nyingi) pamoja na vipengele vya kimoja? +- Umbizo gani la pato unapaswa kutumika kwa uthibitisho wa mafanikio? +- Jinsi aina za usanidi zinavyoweza kuelekezwa/kuchunguzwa na watumiaji? + +## Marejeleo + +- API ya Usanidi iliyopo: `trustgraph/api/config.py` +- Mfumo wa CLI: `trustgraph-cli/trustgraph/cli/show_config.py` +- Data: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.tr.md b/docs/tech-specs/more-config-cli.tr.md new file mode 100644 index 00000000..60cded81 --- /dev/null +++ b/docs/tech-specs/more-config-cli.tr.md @@ -0,0 +1,287 @@ +--- +layout: default +title: "Daha Fazla Yapılandırma CLI Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Daha Fazla Yapılandırma CLI 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 gelişmiş komut satırı yapılandırma yeteneklerini tanımlar ve kullanıcıların ayrı yapılandırma öğelerini ayrıntılı CLI komutları aracılığıyla yönetmelerini sağlar. Bu entegrasyon, dört birincil kullanım senaryosunu destekler: + +1. **Yapılandırma Öğelerini Listele**: Belirli bir türdeki yapılandırma anahtarlarını görüntüleyin +2. **Yapılandırma Öğesini Al**: Belirli yapılandırma değerlerini alın +3. **Yapılandırma Öğesini Ekle/Güncelle**: Bireysel yapılandırma öğelerini ayarlayın veya güncelleyin +4. **Yapılandırma Öğesini Sil**: Belirli yapılandırma öğelerini kaldırın + +## Hedefler + +**Ayrıntılı Kontrol**: Toplu işlemler yerine bireysel yapılandırma öğelerinin yönetimini sağlayın +**Türe Dayalı Listeleme**: Kullanıcıların yapılandırma öğelerini türe göre incelemesine izin verin +**Tek Öğeli İşlemler**: Bireysel yapılandırma öğelerinin alınması/eklenmesi/güncellenmesi/silinmesi için komutlar sağlayın +**API Entegrasyonu**: Tüm işlemler için mevcut Config API'sini kullanın +**Tutarlı CLI Modeli**: Kuruluş içi TrustGraph CLI kurallarına ve kalıplarına uyun +**Hata Yönetimi**: Geçersiz işlemler için açık hata mesajları sağlayın +**JSON Çıkışı**: Programlı kullanım için yapılandırılmış çıktı desteği sağlayın +**Belgeleme**: Kapsamlı yardım ve kullanım örnekleri ekleyin + +## Arka Plan + +TrustGraph şu anda Config API ve tüm yapılandırmayı görüntüleyen `tg-show-config` adlı tek bir CLI komutu aracılığıyla yapılandırma yönetimini sağlar. Bu, yapılandırmayı görüntülemek için işe yarasa da, ayrıntılı yönetim yetenekleri eksiktir. + +Mevcut sınırlamalar şunlardır: +CLI'den yapılandırma öğelerini türe göre listelemenin bir yolu yok +Belirli yapılandırma değerlerini almak için bir CLI komutu yok +Bireysel yapılandırma öğelerini ayarlamak için bir CLI komutu yok +Belirli yapılandırma öğelerini silmek için bir CLI komutu yok + +Bu özellik, ayrıntılı yapılandırma yönetimi sağlayan dört yeni CLI komutu ekleyerek bu boşlukları giderir. Bireysel Config API işlemlerini CLI komutları aracılığıyla açığa çıkararak TrustGraph şunları yapabilir: +Betik tabanlı yapılandırma yönetimini etkinleştirin +Yapılandırma yapısını türe göre incelemeye izin verin +Hedefli yapılandırma güncellemelerini destekleyin +İnce taneli yapılandırma kontrolü sağlayın + +## Teknik Tasarım + +### Mimari + +Gelişmiş CLI yapılandırması, aşağıdaki teknik bileşenleri gerektirir: + +1. **tg-list-config-items** + Belirtilen bir tür için yapılandırma anahtarlarını listeler + Config.list(type) API yöntemini çağırır + Yapılandırma anahtarlarının listesini çıktı olarak verir + + Modül: `trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + Belirli yapılandırma öğesi(ni) alır + Config.get(keys) API yöntemini çağırır + Yapılandırma değerlerini JSON formatında çıktı olarak verir + + Modül: `trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + Bir yapılandırma öğesini ayarlar veya günceller + Config.put(values) API yöntemini çağırır + Tür, anahtar ve değer parametrelerini kabul eder + + Modül: `trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + Bir yapılandırma öğesini siler + Config.delete(keys) API yöntemini çağırır + Tür ve anahtar parametrelerini kabul eder + + Modül: `trustgraph.cli.delete_config_item` + +### Veri Modelleri + +#### ConfigKey ve ConfigValue + +Bu komutlar, `trustgraph.api.types`'dan mevcut veri yapılarını kullanır: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +Bu yaklaşım şunları sağlar: +CLI ve API'ler arasında tutarlı veri işleme +Tür güvenli yapılandırma işlemleri +Yapılandırılmış girdi/çıktı formatları +Mevcut Config API ile entegrasyon + +### CLI Komut Özellikleri + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +**Amaç**: Belirli bir tür için tüm yapılandırma anahtarlarını listele. +**API Çağrısı**: `Config.list(type)` +**Çıktı**: + `text` (varsayılan): Yeni satırlarla ayrılmış yapılandırma anahtarları. + `json`: Yapılandırma anahtarlarının JSON dizisi. + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +**Amaç**: Belirli bir yapılandırma öğesini almak. +**API Çağrısı**: `Config.get([ConfigKey(type, key)])` +**Çıktı**: + `text` (varsayılan): Ham metin değeri. + `json`: JSON olarak kodlanmış metin değeri. + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value [--api-url ] +tg-put-config-item --type --key --stdin [--api-url ] +``` +**Amaç**: Yapılandırma öğesini ayarlayın veya güncelleyin. +**API Çağrısı**: `Config.put([ConfigValue(type, key, value)])` +**Giriş Seçenekleri**: + `--value`: Değer, doğrudan komut satırından sağlanır. + `--stdin`: Değer, standart girişten okunur. +**Çıktı**: Başarı onayı. + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --key [--api-url ] +``` +**Amaç**: Yapılandırma öğesini silme +**API Çağrısı**: `Config.delete([ConfigKey(type, key)])` +**Çıktı**: Başarı onayı + +### Uygulama Detayları + +Tüm komutlar, mevcut TrustGraph CLI kalıbını izler: +Komut satırı argüman ayrıştırması için `argparse` kullanın +Arka uç iletişimi için `trustgraph.api.Api`'i içe aktarın ve kullanın +Mevcut CLI komutlarındaki aynı hata işleme kalıplarını izleyin +API uç noktası yapılandırması için standart `--api-url` parametresini destekleyin +Açıklayıcı yardım metni ve kullanım örnekleri sağlayın + +#### Çıktı Biçimi İşleme + +**Metin Biçimi (Varsayılan)**: +`tg-list-config-items`: Her satırda bir anahtar, düz metin +`tg-get-config-item`: Ham dize değeri, tırnak veya kodlama yok + +**JSON Biçimi**: +`tg-list-config-items`: `["key1", "key2", "key3"]` dize dizisi +`tg-get-config-item`: JSON ile kodlanmış dize değeri `"actual string value"` + +#### Giriş İşleme + +**tg-put-config-item**, iki karşılıklı olarak münhasır giriş yöntemini destekler: +`--value `: Doğrudan komut satırı dize değeri +`--stdin`: Tüm girdiyi yapılandırma değeri olarak standart girdiden okuyun +stdin içeriği ham metin olarak okunur (satır başları, boşluklar vb. korunur) +Dosyalardan, komutlardan veya etkileşimli girdiden boru hattı desteği + +## Güvenlik Hususları + +**Giriş Doğrulama**: Tüm komut satırı parametreleri, API çağrıları yapılmadan önce doğrulanmalıdır. +**API Kimlik Doğrulama**: Komutlar, mevcut API kimlik doğrulama mekanizmalarını kullanır. +**Yapılandırma Erişimi**: Komutlar, mevcut yapılandırma erişim kontrollerine saygı gösterir. +**Hata Bilgisi**: Hata mesajları, hassas yapılandırma ayrıntılarını ifşa etmemelidir. + +## Performans Hususları + +**Tek Öğeli İşlemler**: Komutlar, toplu işlem yükünü önlemek için tek tek öğeler için tasarlanmıştır. +**API Verimliliği**: Doğrudan API çağrıları, işleme katmanlarını en aza indirir. +**Ağ Gecikmesi**: Her komut, tek bir API çağrısı yapar ve bu da ağ iletişimini en aza indirir. +**Bellek Kullanımı**: Tek öğeli işlemler için minimum bellek kullanımı. + +## Test Stratejisi + +**Birim Testleri**: Her CLI komut modülünü bağımsız olarak test edin. +**Entegrasyon Testleri**: CLI komutlarını canlı Config API'ye karşı test edin. +**Hata Yönetimi Testleri**: Geçersiz girişler için uygun hata yönetimini doğrulayın. +**API Uyumluluğu**: Komutların mevcut Config API sürümleriyle çalıştığından emin olun. + +## Geçiş Planı + +Geçiş gerekli değil - bunlar, mevcut işlevselliği tamamlayan yeni CLI komutlarıdır: +Mevcut `tg-show-config` komutu değişmeden kalır. +Yeni komutlar kademeli olarak eklenebilir. +Mevcut yapılandırma iş akışlarında herhangi bir değişiklik yapılmaz. + +## Paketleme ve Dağıtım + +Bu komutlar, mevcut `trustgraph-cli` paketine eklenecektir: + +**Paket Konumu**: `trustgraph-cli/` +**Modül Dosyaları**: +`trustgraph-cli/trustgraph/cli/list_config_items.py` +`trustgraph-cli/trustgraph/cli/get_config_item.py` +`trustgraph-cli/trustgraph/cli/put_config_item.py` +`trustgraph-cli/trustgraph/cli/delete_config_item.py` + +**Giriş Noktaları**: `trustgraph-cli/pyproject.toml`'a `[project.scripts]` bölümüne eklendi: +```toml +tg-list-config-items = "trustgraph.cli.list_config_items:main" +tg-get-config-item = "trustgraph.cli.get_config_item:main" +tg-put-config-item = "trustgraph.cli.put_config_item:main" +tg-delete-config-item = "trustgraph.cli.delete_config_item:main" +``` + +## Uygulama Görevleri + +1. **CLI Modüllerini Oluşturma**: `trustgraph-cli/trustgraph/cli/` içinde dört CLI komut modülünü uygulayın. +2. **pyproject.toml'yi Güncelleme**: `trustgraph-cli/pyproject.toml`'a yeni komut giriş noktaları ekleyin. +3. **Belgeleme**: `docs/cli/` içindeki her komut için CLI belgelerini oluşturun. +4. **Test**: Kapsamlı test kapsamı uygulayın. +5. **Entegrasyon**: Komutların mevcut TrustGraph altyapısıyla çalıştığından emin olun. +6. **Paket Oluşturma**: Komutların `pip install trustgraph-cli` ile düzgün bir şekilde yüklendiğini doğrulayın. + +## Kullanım Örnekleri + +#### Yapılandırma öğelerini listeleme +```bash +# List prompt keys (text format) +tg-list-config-items --type prompt +template-1 +template-2 +system-prompt + +# List prompt keys (JSON format) +tg-list-config-items --type prompt --format json +["template-1", "template-2", "system-prompt"] +``` + +#### Yapılandırma öğesini al +```bash +# Get prompt value (text format) +tg-get-config-item --type prompt --key template-1 +You are a helpful assistant. Please respond to: {query} + +# Get prompt value (JSON format) +tg-get-config-item --type prompt --key template-1 --format json +"You are a helpful assistant. Please respond to: {query}" +``` + +#### Yapılandırma öğesini ayarlayın +```bash +# Set from command line +tg-put-config-item --type prompt --key new-template --value "Custom prompt: {input}" + +# Set from file via pipe +cat ./prompt-template.txt | tg-put-config-item --type prompt --key complex-template --stdin + +# Set from file via redirect +tg-put-config-item --type prompt --key complex-template --stdin < ./prompt-template.txt + +# Set from command output +echo "Generated template: {query}" | tg-put-config-item --type prompt --key auto-template --stdin +``` + +#### Yapılandırma öğesini sil +```bash +tg-delete-config-item --type prompt --key old-template +``` + +## Açık Sorular + +Komutlar, tek öğelerin yanı sıra toplu işlemleri (çoklu anahtarlar) desteklemeli mi? +Başarı onayları için hangi çıktı formatı kullanılmalıdır? +Konfigürasyon türleri kullanıcılar tarafından nasıl belgelenmeli/keşfedilmelidir? + +## Referanslar + +Mevcut Konfigürasyon API'si: `trustgraph/api/config.py` +CLI kalıpları: `trustgraph-cli/trustgraph/cli/show_config.py` +Veri türleri: `trustgraph/api/types.py` diff --git a/docs/tech-specs/more-config-cli.zh-cn.md b/docs/tech-specs/more-config-cli.zh-cn.md new file mode 100644 index 00000000..973d177a --- /dev/null +++ b/docs/tech-specs/more-config-cli.zh-cn.md @@ -0,0 +1,186 @@ +--- +layout: default +title: "更高级的 CLI 技术规格" +parent: "Chinese (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. + +## 概述 + +该规范描述了 TrustGraph 的增强型命令行配置功能,允许用户通过精细的 CLI 命令来管理单个配置项。 该集成支持四个主要用例: + +1. **列出配置项**: 显示特定类型的配置键 +2. **获取配置项**: 获取特定配置值 +3. **设置配置项**: 设置或更新单个配置项 +4. **删除配置项**: 删除特定配置项 + +## 目标 + +- **精细控制**: 能够管理单个配置项,而不是批量操作 +- **基于类型的列出**: 允许用户按类型探索配置项 +- **单个项操作**: 提供获取/设置/删除单个配置项的命令 +- **API 集成**: 利用现有的 Config API 进行所有操作 +- **一致的 CLI 模式**: 遵循 TrustGraph 的标准 CLI 约定和模式 +- **错误处理**: 提供无效操作的清晰错误消息 +- **JSON 输出**: 支持结构化输出,用于程序化使用 +- **文档**: 包含全面的帮助和用法示例 + +## 背景 + +目前,TrustGraph 通过 Config API 和一个名为 `tg-show-config` 的单一 CLI 命令来管理配置。 该命令显示整个配置。 虽然这对于查看配置有效,但缺乏精细的管理功能。 + +目前存在以下限制: +- 无法从 CLI 列出按类型配置项 +- 没有 CLI 命令用于检索特定配置值 +- 没有 CLI 命令用于设置单个配置项 +- 没有 CLI 命令用于删除特定配置项 + +该规范通过添加四个新的 CLI 命令来解决这些问题,从而提供精细的配置管理。 通过将单个 Config API 操作暴露到 CLI 命令中,TrustGraph 可以: +- 启用脚本化的配置管理 +- 允许用户按类型探索配置结构 +- 支持有针对性的配置更新 +- 提供精细的配置控制 + +## 技术设计 + +### 架构 + +增强的 CLI 配置需要以下技术组件: + +1. **tg-list-config-items** + - 列出指定类型的配置键 + - 调用 Config.list(type) API 方法 + - 输出配置键列表 + + 模块:`trustgraph.cli.list_config_items` + +2. **tg-get-config-item** + - 检索特定配置项 + - 调用 Config.get(keys) API 方法 + - 以 JSON 格式输出配置值 + + 模块:`trustgraph.cli.get_config_item` + +3. **tg-put-config-item** + - 设置或更新配置项 + - 调用 Config.put(values) API 方法 + - 接受类型、键和值参数 + + 模块:`trustgraph.cli.put_config_item` + +4. **tg-delete-config-item** + - 删除配置项 + - 调用 Config.delete(keys) API 方法 + - 接受类型和键参数 + + 模块:`trustgraph.cli.delete_config_item` + +### 数据模型 + +#### ConfigKey 和 ConfigValue + +这些命令使用来自 `trustgraph.api.types` 的现有数据结构: + +```python +@dataclasses.dataclass +class ConfigKey: + type : str + key : str + +@dataclasses.dataclass +class ConfigValue: + type : str + key : str + value : str +``` + +这种方法允许: +- 在 CLI 和 API 中保持数据的一致性 +- 类型安全的配置操作 +- 结构化输入/输出格式 +- 与现有的 Config API 集成 + +### CLI 命令规范 + +#### tg-list-config-items +```bash +tg-list-config-items --type [--format text|json] [--api-url ] +``` +- **目的**: 列出给定类型的所有配置键 +- **API 调用**: `Config.list(type)` +- **输出**: + - `text` (默认): 键按换行分隔 + - `json`: 键的 JSON 数组 + +#### tg-get-config-item +```bash +tg-get-config-item --type --key [--format text|json] [--api-url ] +``` +- **目的**: 获取特定配置项 +- **API 调用**: `Config.get([ConfigKey(type, key)])` +- **输出**: + - `text` (默认): 原始字符串值 + - `json`: JSON 编码的字符串值 + +#### tg-put-config-item +```bash +tg-put-config-item --type --key --value [--api-url ] +tg-put-config-item --type --key --stdin [--api-url ] +``` +- **目的**: 设置或更新配置项 +- **API 调用**: `Config.put([ConfigValue(type, key, value)])` +- **输入选项**: + - `--value <字符串>`: 直接在命令行中提供的字符串值 + - `--stdin`: 从标准输入读取整个输入作为配置值 + - 标准输入读取为原始文本 (保留换行符、空格等) + - 支持通过文件、命令或交互式输入 + +#### tg-delete-config-item +```bash +tg-delete-config-item --type --key [--api-url ] +``` +- **目的**: 删除配置项 +- **API 调用**: `Config.delete([ConfigKey(type, key)])` +- **输出**: 成功确认 + +### 实现细节 + +所有命令都遵循 TrustGraph 的标准 CLI 模式: +- 使用 `argparse` 进行命令行参数解析 +- 导入和使用 `trustgraph.api.Api` 进行后端通信 +- 遵循现有 CLI 命令的相同错误处理模式 +- 支持标准 `--api-url` 参数,用于配置 API 端点 +- 提供描述性的帮助文本和用法示例 + +#### 输出格式处理 + +**文本格式 (默认)**: +- `tg-list-config-items`: 键按新行分隔,纯文本 +- `tg-get-config-item`: 原始字符串值,无引号或编码 + +**JSON 格式**: +- `tg-list-config-items`: 字符串数组 `["key1", "key2", "key3"]` +- `tg-get-config-item`: JSON 编码的字符串值 `"实际字符串值"` + +#### 输入处理 + +**tg-put-config-item** 支持两种互斥的输入方法: +- `--value <字符串>`: 命令行中的直接字符串值 +- `--stdin`: 从标准输入读取整个输入作为配置值 +- 标准输入读取为原始文本 (保留换行符、空格等) +- 支持通过文件、命令或交互式输入 + +## 安全性 + +- 如果配置项包含敏感信息,如何安全地处理这些信息? +- 如何验证用户输入,以防止恶意攻击? +- 如何控制对配置项的访问权限? + +## 开放问题 + +- 是否应该支持命令以批量操作 (多个键) 之外的单个项? +- 成功确认消息应该使用哪种格式? +- 用户应该如何发现和使用配置类型? diff --git a/docs/tech-specs/multi-tenant-support.ar.md b/docs/tech-specs/multi-tenant-support.ar.md new file mode 100644 index 00000000..b3bcc955 --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.ar.md @@ -0,0 +1,780 @@ +--- +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. + +## نظرة عامة + +تمكين عمليات النشر متعددة المستأجرين عن طريق إصلاح عدم تطابق أسماء المعلمات التي تمنع تخصيص قائمة الانتظار وإضافة معلمات مساحة مفاتيح Cassandra. + +## سياق البنية + +### حل قائمة الانتظار القائم على التدفق + +يستخدم نظام TrustGraph بنية **قائمة انتظار قائمة على التدفق** لحل ديناميكي لقوائم الانتظار، والتي تدعم بشكل طبيعي البيئات متعددة المستأجرين: + +يتم تخزين **تعريفات التدفق** في Cassandra وتحدد أسماء قوائم الانتظار عبر تعريفات الواجهة. +**تستخدم أسماء قوائم الانتظار قوالب** مع متغيرات `{id}` يتم استبدالها بمعرفات مثيلات التدفق. +**تقوم الخدمات بحل قوائم الانتظار ديناميكيًا** عن طريق البحث عن تكوينات التدفق في وقت الطلب. +**يمكن لكل مستأجر أن يكون لديه تدفقات فريدة** بأسماء قوائم انتظار مختلفة، مما يوفر عزلًا. + +مثال لتعريف واجهة التدفق: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +عندما يبدأ المستأجر أ سير العمل `tenant-a-prod` ويبدأ المستأجر ب سير العمل `tenant-b-prod`، فإنهم يحصلون تلقائيًا على قوائم انتظار معزولة: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**الخدمات المصممة بشكل صحيح لدعم تعدد المستأجرين:** +✅ **إدارة المعرفة (الأساسيات)** - تحل ديناميكيًا قوائم الانتظار من تكوين سير العمل الذي يتم تمريره في الطلبات. + +**الخدمات التي تحتاج إلى إصلاحات:** +🔴 **خدمة التكوين** - عدم تطابق اسم المعلمة يمنع تخصيص قائمة الانتظار. +🔴 **خدمة أمين المكتبة** - مواضيع إدارة التخزين المبرمجة بشكل ثابت (موضحة أدناه). +🔴 **جميع الخدمات** - لا يمكن تخصيص مساحة مفتاح Cassandra. + +## بيان المشكلة + +### المشكلة رقم 1: عدم تطابق اسم المعلمة في AsyncProcessor +**يعرف سطر الأوامر:** `--config-queue` (تسمية غير واضحة) +**يقوم Argparse بتحويلها إلى:** `config_queue` (في قاموس المعلمات) +**يبحث الكود عن:** `config_push_queue` +**النتيجة:** يتم تجاهل المعلمة، وتعود إلى القيمة الافتراضية `persistent://tg/config/config`. +**التأثير:** يؤثر على أكثر من 32 خدمة ترث من AsyncProcessor. +**يمنع:** لا يمكن لنشر تعدد المستأجرين استخدام قوائم انتظار تكوين خاصة بالمستأجر. +**الحل:** إعادة تسمية معلمة سطر الأوامر إلى `--config-push-queue` من أجل الوضوح (تغيير كاسر مقبول نظرًا لأن الميزة معطلة حاليًا). + +### المشكلة رقم 2: عدم تطابق اسم المعلمة في خدمة التكوين +**يعرف سطر الأوامر:** `--push-queue` (تسمية غامضة) +**يقوم Argparse بتحويلها إلى:** `push_queue` (في قاموس المعلمات) +**يبحث الكود عن:** `config_push_queue` +**النتيجة:** يتم تجاهل المعلمة. +**التأثير:** لا يمكن لخدمة التكوين استخدام قائمة انتظار دفع مخصصة. +**الحل:** إعادة تسمية معلمة سطر الأوامر إلى `--config-push-queue` من أجل الاتساق والوضوح (تغيير كاسر مقبول). + +### المشكلة رقم 3: مساحة مفتاح Cassandra مبرمجة بشكل ثابت +**الحالي:** مساحة المفتاح مبرمجة بشكل ثابت كـ `"config"`، `"knowledge"`، `"librarian"` في خدمات مختلفة. +**النتيجة:** لا يمكن تخصيص مساحة المفتاح لنشر تعدد المستأجرين. +**التأثير:** خدمات التكوين والأساسيات وأمين المكتبة. +**يمنع:** لا يمكن لعدة مستأجرين استخدام مساحات مفاتيح Cassandra منفصلة. + +### المشكلة رقم 4: بنية إدارة المجموعات ✅ مكتمل +**السابق:** تم تخزين المجموعات في مساحة مفاتيح Cassandra الخاصة بأمين المكتبة عبر جدول مجموعات منفصل. +**السابق:** استخدم أمين المكتبة 4 مواضيع إدارة تخزين مبرمجة بشكل ثابت لتنسيق إنشاء/حذف المجموعة: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**المشاكل (تم حلها):** + لا يمكن تخصيص المواضيع المبرمجة بشكل ثابت لنشر تعدد المستأجرين. + تنسيق غير متزامن معقد بين أمين المكتبة و 4+ خدمات تخزين. + جدول منفصل وبنية تحتية لإدارة. + قوائم انتظار طلب/استجابة غير دائمة للعمليات الهامة. +**الحل المنفذ:** تم نقل المجموعات إلى تخزين خدمة التكوين، واستخدام دفع التكوين للتوزيع. +**الحالة:** تم نقل جميع خلفيات التخزين إلى النمط `CollectionConfigHandler`. + +## الحل + +تعالج هذه المواصفات المشكلات رقم 1 و 2 و 3 و 4. + +### الجزء الأول: إصلاح عدم تطابق اسم المعلمة + +#### التغيير 1: فئة AsyncProcessor الأساسية - إعادة تسمية معلمة سطر الأوامر +**الملف:** `trustgraph-base/trustgraph/base/async_processor.py` +**السطر:** 260-264 + +**الحالي:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**ثابت:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**السبب:** +تسمية أوضح وأكثر تفصيلاً. +تتطابق مع اسم المتغير الداخلي `config_push_queue`. +التغيير قد يكون مؤثراً، ولكن هذا مقبول لأن الميزة غير فعالة حاليًا. +لا حاجة لتغيير أي كود في `params.get()` - فهو يبحث بالفعل عن الاسم الصحيح. + +#### التغيير الثاني: خدمة التكوين - إعادة تسمية معلمة سطر الأوامر +**الملف:** `trustgraph-flow/trustgraph/config/service/service.py` +**السطر:** 276-279 + +**الحالي:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**ثابت:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**السبب:** +تسمية أوضح - "config-push-queue" أكثر وضوحًا من مجرد "push-queue". +يتطابق مع اسم المتغير الداخلي `config_push_queue`. +متسق مع معلمة `--config-push-queue` الخاصة بـ AsyncProcessor. +التغيير غير المتوافق مقبول نظرًا لأن الميزة غير وظيفية حاليًا. +لا حاجة لتغيير التعليمات البرمجية في params.get() - فهو يبحث بالفعل عن الاسم الصحيح. + +### الجزء الثاني: إضافة معلمات مساحة مفاتيح Cassandra + +#### التغيير الثالث: إضافة معلمة مساحة المفاتيح إلى وحدة cassandra_config +**الملف:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**إضافة وسيط سطر الأوامر** (في دالة `add_cassandra_args()`): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**إضافة دعم لمتغيرات البيئة** (في الدالة `resolve_cassandra_config()`): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**تحديث قيمة الإرجاع** لـ `resolve_cassandra_config()`: +حاليًا، تُرجع: `(hosts, username, password)` +التغيير إلى إرجاع: `(hosts, username, password, keyspace)` + +**السبب:** +يتوافق مع نمط تكوين Cassandra الحالي +متاح لجميع الخدمات عبر `add_cassandra_args()` +يدعم كل من تكوين سطر الأوامر ومتغيرات البيئة + +#### التغيير الرابع: خدمة التكوين - استخدام مفاتيح مساحة المفاتيح المعلمة +**الملف:** `trustgraph-flow/trustgraph/config/service/service.py` + +**السطر 30** - إزالة اسم مساحة المفاتيح الثابت: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**السطور من 69 إلى 73** - تحديث آلية حل مشاكل إعدادات كاساندرا: + +**الحالي:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**ثابت:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**السبب:** +يحافظ على التوافق مع الإصدارات السابقة باستخدام "config" كإعداد افتراضي. +يسمح بالتجاوز عبر `--cassandra-keyspace` أو `CASSANDRA_KEYSPACE`. + +#### التغيير 5: الخدمات الأساسية/خدمة المعرفة - استخدام مفاتيح مساحة معلمات. +**الملف:** `trustgraph-flow/trustgraph/cores/service.py` + +**السطر 37** - إزالة مفتاح مساحة مُبرمج بشكل ثابت: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**تحديث آلية حل إعدادات كاساندرا** (في نفس الموقع مثل خدمة الإعدادات): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### التغيير 6: خدمة أمين المكتبة - استخدام مفاتيح مساحة معلمات. +**الملف:** `trustgraph-flow/trustgraph/librarian/service.py` + +**السطر 51** - إزالة اسم مساحة المفاتيح المبرمج بشكل ثابت: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**تحديث آلية حل إعدادات Cassandra** (في نفس الموقع مثل خدمة الإعدادات): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### الجزء الثالث: ترحيل إدارة المجموعات إلى خدمة التكوين + +#### نظرة عامة +ترحيل المجموعات من مساحة مفاتيح Cassandra librarian إلى تخزين خدمة التكوين. هذا يلغي مواضيع إدارة التخزين المضمنة ويبسط البنية باستخدام آلية دفع التكوين الحالية للتوزيع. + +#### البنية الحالية +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### العمارة الجديدة +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### التغيير 7: مدير المجموعة - استخدام واجهة برمجة تطبيقات خدمة التكوين +**الملف:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**إزالة:** +استخدام `LibraryTableStore` (الأسطر 33، 40-41) +تهيئة منتجي إدارة التخزين (الأسطر 86-140) +طريقة `on_storage_response` (الأسطر 400-430) +تتبع `pending_deletions` (الأسطر 57، 90-96، والاستخدام في جميع أنحاء البرنامج) + +**إضافة:** +عميل خدمة التكوين لإجراء مكالمات واجهة برمجة التطبيقات (نمط الطلب/الاستجابة) + +**إعداد عميل التكوين:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**تعديل `list_collections` (الأسطر من 145 إلى 180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**تعديل `update_collection` (الأسطر من 182 إلى 312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**تعديل `delete_collection` (الأسطر من 314 إلى 398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**تنسيق بيانات التعريف للمجموعة:** +يتم تخزينها في جدول التكوين كـ: `class='collections', key='user:collection'` +القيمة هي بيانات تعريف المجموعة (CollectionMetadata) مُسلسلة بصيغة JSON (بدون حقول الطابع الزمني) +الحقول: `user`، `collection`، `name`، `description`، `tags` +مثال: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### التغيير 8: خدمة أمين المكتبة - إزالة بنية إدارة التخزين +**الملف:** `trustgraph-flow/trustgraph/librarian/service.py` + +**إزالة:** +منتجي إدارة التخزين (الأسطر 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +مستهلك الاستجابة للتخزين (الأسطر 192-201) +معالج `on_storage_response` (الأسطر 467-473) + +**تعديل:** +تهيئة CollectionManager (الأسطر 215-224) - إزالة معلمات منتج التخزين + +**ملاحظة:** تظل واجهة برمجة التطبيقات الخارجية للمجموعة دون تغيير: +`list-collections` +`update-collection` +`delete-collection` + +#### التغيير 9: إزالة جدول المجموعات من LibraryTableStore +**الملف:** `trustgraph-flow/trustgraph/tables/library.py` + +**حذف:** +عبارة CREATE لجدول المجموعات (الأسطر 114-127) +عبارات Collections المُعدة (الأسطر 205-240) +جميع طرق المجموعة (الأسطر 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**السبب:** +يتم الآن تخزين المجموعات في جدول التكوين +التغيير غير المتوافق مقبول - لا توجد حاجة لنقل البيانات +يبسط خدمة أمين المكتبة بشكل كبير + +#### التغيير 10: خدمات التخزين - إدارة المجموعة المستندة إلى التكوين ✅ تم + +**الحالة:** تم ترحيل جميع خدمات التخزين الـ 11 لاستخدام `CollectionConfigHandler`. + +**الخدمات المتأثرة (11 خدمة إجمالاً):** +تضمينات المستندات: milvus, pinecone, qdrant +تضمينات الرسم البياني: milvus, pinecone, qdrant +تخزين الكائنات: cassandra +تخزين الثلاثيات: cassandra, falkordb, memgraph, neo4j + +**الملفات:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**نمط التنفيذ (جميع الخدمات):** + +1. **سجل معالج التكوين في `__init__`:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **تنفيذ معالج التهيئة:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **تهيئة المجموعات المعروفة عند بدء التشغيل:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **إعادة هيكلة طرق المعالجة الحالية:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **إزالة البنية التحتية لإدارة التخزين:** + إزالة الإعداد والتشغيل `self.storage_request_consumer`. + إزالة الإعداد `self.storage_response_producer`. + إزالة طريقة الموزع `on_storage_management`. + إزالة المقاييس لإدارة التخزين. + إزالة الاستيرادات: `StorageManagementRequest`، `StorageManagementResponse`. + +**اعتبارات خاصة بالخلفية:** + +**مخازن المتجهات (Milvus, Pinecone, Qdrant):** تتبع `(user, collection)` المنطقية في `known_collections`، ولكن قد يتم إنشاء مجموعات خلفية متعددة لكل بُعد. استمر في نمط الإنشاء الكسول. يجب أن تزيل عمليات الحذف جميع المتغيرات الأبعاد. + +**Cassandra Objects:** المجموعات هي خصائص الصفوف، وليست هياكل. تتبع معلومات على مستوى مساحة المفاتيح. + +**مخازن الرسوم البيانية (Neo4j, Memgraph, FalkorDB):** استعلام عن عقد `CollectionMetadata` عند بدء التشغيل. إنشاء/حذف عقد البيانات الوصفية عند المزامنة. + +**Cassandra Triples:** استخدم واجهة برمجة التطبيقات `KnowledgeGraph` لعمليات المجموعة. + +**نقاط التصميم الرئيسية:** + +**الاتساق النهائي:** لا يوجد آلية طلب/استجابة، يتم بث دفع التكوين. +**التكرار:** يجب أن تكون جميع عمليات الإنشاء/الحذف آمنة لإعادة المحاولة. +**معالجة الأخطاء:** سجل الأخطاء ولكن لا تقاطع تحديثات التكوين. +**التعافي الذاتي:** ستعيد العمليات الفاشلة المحاولة في دفع التكوين التالي. +**تنسيق مفتاح المجموعة:** `"user:collection"` في `config["collections"]`. + +#### التغيير 11: تحديث مخطط المجموعة - إزالة الطوابع الزمنية +**الملف:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**تعديل CollectionMetadata (الأسطر 13-21):** +إزالة الحقول `created_at` و `updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**تعديل طلب إدارة المجموعة (الأسطر من 25 إلى 47):** +إزالة حقول الطابع الزمني: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**السبب:** +لا تضيف الطوابع الزمنية قيمة للمجموعات. +خدمة التكوين تحتفظ بآلية تتبع الإصدار الخاصة بها. +تبسط المخطط وتقلل التخزين. + +#### فوائد ترحيل خدمة التكوين + +1. ✅ **تقضي على مواضيع إدارة التخزين المضمنة بشكل ثابت** - تحل مشكلة المستخدمين المتعددين. +2. ✅ **تنسيق أبسط** - لا يوجد انتظار غير متزامن معقد لـ 4+ استجابات للتخزين. +3. ✅ **الاتساق النهائي** - تقوم خدمات التخزين بالتحديث بشكل مستقل عبر دفع التكوين. +4. ✅ **موثوقية أفضل** - دفع تكوين دائم مقابل طلب/استجابة غير دائمة. +5. ✅ **نموذج تكوين موحد** - يتم التعامل مع المجموعات على أنها تكوين. +6. ✅ **تقلل التعقيد** - تزيل حوالي 300 سطر من كود التنسيق. +7. ✅ **جاهزة لدعم المستخدمين المتعددين** - تدعم التكوين بالفعل عزل المستخدمين عبر مساحة المفاتيح. +8. ✅ **تتبع الإصدار** - توفر آلية إصدار خدمة التكوين مسار تدقيق. + +## ملاحظات التنفيذ + +### التوافق مع الإصدارات السابقة + +**تغييرات في المعلمات:** +إعادة تسمية معلمات سطر الأوامر هي تغييرات جذرية ولكنها مقبولة (الميزة غير وظيفية حاليًا). +تعمل الخدمات بدون معلمات (تستخدم القيم الافتراضية). +تم الحفاظ على مساحات المفاتيح الافتراضية: "config" و "knowledge" و "librarian". +قائمة الانتظار الافتراضية: `persistent://tg/config/config` + +**إدارة المجموعات:** +**تغيير جذري:** تمت إزالة جدول المجموعات من مساحة مفاتيح librarian. +**لا يتم توفير ترحيل للبيانات** - مقبول لهذه المرحلة. +واجهة برمجة تطبيقات المجموعة الخارجية لم تتغير (عمليات القائمة/التحديث/الحذف). +تم تبسيط تنسيق بيانات تعريف المجموعة (تمت إزالة الطوابع الزمنية). + +### متطلبات الاختبار + +**اختبار المعلمات:** +1. تحقق من أن المعلمة `--config-push-queue` تعمل على خدمة graph-embeddings. +2. تحقق من أن المعلمة `--config-push-queue` تعمل على خدمة text-completion. +3. تحقق من أن المعلمة `--config-push-queue` تعمل على خدمة التكوين. +4. تحقق من أن المعلمة `--cassandra-keyspace` تعمل لخدمة التكوين. +5. تحقق من أن المعلمة `--cassandra-keyspace` تعمل لخدمة cores. +6. تحقق من أن المعلمة `--cassandra-keyspace` تعمل لخدمة librarian. +7. تحقق من أن الخدمات تعمل بدون معلمات (تستخدم القيم الافتراضية). +8. تحقق من نشر متعدد المستخدمين باستخدام أسماء قوائم الانتظار ومساحات المفاتيح المخصصة. + +**اختبار إدارة المجموعات:** +9. تحقق من العملية `list-collections` عبر خدمة التكوين. +10. تحقق من أن `update-collection` تقوم بإنشاء/تحديث في جدول التكوين. +11. تحقق من أن `delete-collection` تقوم بإزالة من جدول التكوين. +12. تحقق من أن دفع التكوين يتم تشغيله عند تحديث المجموعات. +13. تحقق من أن تصفية العلامات تعمل مع التخزين المستند إلى التكوين. +14. تحقق من أن عمليات المجموعة تعمل بدون حقول الطوابع الزمنية. + +### مثال النشر متعدد المستخدمين +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## تحليل الأثر + +### الخدمات المتأثرة بالتغيير 1-2 (إعادة تسمية معلمة سطر الأوامر) +جميع الخدمات التي ترث من AsyncProcessor أو FlowProcessor: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (جميع المزودين) +extract-* (جميع أدوات الاستخراج) +query-* (جميع خدمات الاستعلام) +retrieval-* (جميع خدمات استرجاع المعلومات) +storage-* (جميع خدمات التخزين) +وأكثر من 20 خدمة أخرى + +### الخدمات المتأثرة بالتغييرات 3-6 (مساحة مفاتيح Cassandra) +config-service +cores-service +librarian-service + +### الخدمات المتأثرة بالتغييرات 7-11 (إدارة المجموعات) + +**التغييرات الفورية:** +librarian-service (collection_manager.py, service.py) +tables/library.py (إزالة جدول المجموعات) +schema/services/collection.py (إزالة الطابع الزمني) + +**التغييرات المكتملة (التغيير 10):** ✅ +جميع خدمات التخزين (11 إجمالاً) - تم ترحيلها إلى دفع التكوين لتحديثات المجموعة عبر `CollectionConfigHandler` +تم إزالة مخطط إدارة التخزين من `storage.py` + +## اعتبارات مستقبلية + +### نموذج مساحة مفاتيح خاصة بالمستخدم + +تستخدم بعض الخدمات **مساحات مفاتيح خاصة بالمستخدم** ديناميكيًا، حيث يحصل كل مستخدم على مساحة مفاتيح Cassandra خاصة به: + +**الخدمات التي تستخدم مساحات مفاتيح خاصة بالمستخدم:** +1. **خدمة استعلام الثلاثيات** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + تستخدم `keyspace=query.user` +2. **خدمة استعلام الكائنات** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + تستخدم `keyspace=self.sanitize_name(user)` +3. **الوصول المباشر إلى الرسم البياني المعرفي** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + المعلمة الافتراضية `keyspace="trustgraph"` + +**الحالة:** هذه **غير معدلة** في هذا المواصفات. + +**مراجعة مستقبلية مطلوبة:** +تقييم ما إذا كانت نموذج مساحة مفاتيح خاصة بالمستخدم تخلق مشاكل عزل المستأجر +ضع في اعتبارك ما إذا كانت عمليات النشر متعددة المستأجرين تحتاج إلى أنماط بادئة لمساحة مفاتيح (مثل `tenant_a_user1`) +مراجعة للاحتمالية المحتملة لتصادم معرف المستخدم عبر المستأجرين +تقييم ما إذا كانت مساحة مفاتيح مشتركة واحدة لكل مستأجر مع عزل الصفوف المستند إلى المستخدم هي الأفضل + +**ملاحظة:** هذا لا يمنع التنفيذ متعدد المستأجرين الحالي ولكنه يجب مراجعته قبل عمليات نشر متعددة المستأجرين في الإنتاج. + +## مراحل التنفيذ + +### المرحلة 1: إصلاحات المعلمات (التغييرات 1-6) +إصلاح تسمية المعلمة `--config-push-queue` +إضافة دعم المعلمة `--cassandra-keyspace` +**النتيجة:** تم تمكين قائمة الانتظار متعددة المستأجرين وتكوين مساحة المفاتيح + +### المرحلة 2: ترحيل إدارة المجموعة (التغييرات 7-9، 11) +ترحيل تخزين المجموعة إلى خدمة التكوين +إزالة جدول المجموعات من librarian +تحديث مخطط المجموعة (إزالة الطوابع الزمنية) +**النتيجة:** يلغي إدارة التخزين المضمنة، ويبسط librarian + +### المرحلة 3: تحديثات خدمة التخزين (التغيير 10) ✅ مكتمل +تم تحديث جميع خدمات التخزين لاستخدام دفع التكوين للمجموعات عبر `CollectionConfigHandler` +تمت إزالة البنية التحتية لطلبات واستجابات إدارة التخزين +تمت إزالة تعريفات المخطط القديمة +**النتيجة:** تم تحقيق إدارة المجموعة المستندة إلى التكوين بالكامل + +## المراجع +مشكلة GitHub: https://github.com/trustgraph-ai/trustgraph/issues/582 +الملفات ذات الصلة: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.es.md b/docs/tech-specs/multi-tenant-support.es.md new file mode 100644 index 00000000..c41f5462 --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.es.md @@ -0,0 +1,780 @@ +--- +layout: default +title: "Especificación técnica: Soporte para entornos multi-inquilino" +parent: "Spanish (Beta)" +--- + +# Especificación técnica: Soporte para entornos multi-inquilino + +> **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 + +Habilite implementaciones multi-inquilino corrigiendo las discrepancias en los nombres de los parámetros que impiden la personalización de la cola y agregando la parametrización del espacio de claves de Cassandra. + +## Contexto de la arquitectura + +### Resolución de colas basada en flujos + +El sistema TrustGraph utiliza una **arquitectura basada en flujos** para la resolución dinámica de colas, lo que inherentemente admite la multi-inquilinización: + +Las **definiciones de flujo** se almacenan en Cassandra y especifican los nombres de las colas a través de definiciones de interfaz. +Los **nombres de las colas utilizan plantillas** con variables `{id}` que se reemplazan con los ID de las instancias de flujo. +Los **servicios resuelven dinámicamente las colas** buscando las configuraciones de flujo en el momento de la solicitud. +**Cada inquilino puede tener flujos únicos** con diferentes nombres de cola, lo que proporciona aislamiento. + +Ejemplo de definición de interfaz de flujo: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +Cuando el inquilino A inicia el flujo `tenant-a-prod` y el inquilino B inicia el flujo `tenant-b-prod`, automáticamente obtienen colas aisladas: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**Servicios diseñados correctamente para la multi-inquilinización:** +✅ **Knowledge Management (núcleos)** - Resuelve dinámicamente las colas a partir de la configuración del flujo que se pasa en las solicitudes. + +**Servicios que necesitan correcciones:** +🔴 **Config Service** - La falta de coincidencia en el nombre del parámetro impide la personalización de la cola. +🔴 **Librarian Service** - Temas de gestión de almacenamiento codificados (se discute a continuación). +🔴 **Todos los servicios** - No se puede personalizar el keyspace de Cassandra. + +## Declaración del problema + +### Problema #1: Falta de coincidencia en el nombre del parámetro en AsyncProcessor +**CLI define:** `--config-queue` (nombre poco claro) +**Argparse convierte a:** `config_queue` (en el diccionario de parámetros) +**El código busca:** `config_push_queue` +**Resultado:** El parámetro se ignora, por defecto a `persistent://tg/config/config` +**Impacto:** Afecta a más de 32 servicios que heredan de AsyncProcessor. +**Bloquea:** Los despliegues multi-inquilinos no pueden usar colas de configuración específicas del inquilino. +**Solución:** Cambiar el nombre del parámetro de la CLI a `--config-push-queue` para mayor claridad (el cambio importante es aceptable, ya que la función actualmente está rota). + +### Problema #2: Falta de coincidencia en el nombre del parámetro en Config Service +**CLI define:** `--push-queue` (nombre ambiguo) +**Argparse convierte a:** `push_queue` (en el diccionario de parámetros) +**El código busca:** `config_push_queue` +**Resultado:** El parámetro se ignora. +**Impacto:** El servicio de configuración no puede usar una cola de envío personalizada. +**Solución:** Cambiar el nombre del parámetro de la CLI a `--config-push-queue` para mayor coherencia y claridad (el cambio importante es aceptable). + +### Problema #3: Keyspace de Cassandra codificado +**Actual:** El keyspace está codificado como `"config"`, `"knowledge"`, `"librarian"` en varios servicios. +**Resultado:** No se puede personalizar el keyspace para los despliegues multi-inquilinos. +**Impacto:** Servicios de configuración, núcleos y bibliotecario. +**Bloquea:** Múltiples inquilinos no pueden usar keyspaces de Cassandra separados. + +### Problema #4: Arquitectura de gestión de colecciones ✅ COMPLETADO +**Anterior:** Las colecciones se almacenaban en el keyspace de Cassandra del bibliotecario a través de una tabla de colecciones separada. +**Anterior:** El bibliotecario utilizaba 4 temas de gestión de almacenamiento codificados para coordinar la creación/eliminación de colecciones: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**Problemas (Resueltos):** + Los temas codificados no se podían personalizar para los despliegues multi-inquilinos. + Coordinación asíncrona compleja entre el bibliotecario y 4 o más servicios de almacenamiento. + Infraestructura de tabla y gestión de Cassandra separada. + Colas de solicitud/respuesta no persistentes para operaciones críticas. +**Solución implementada:** Se migraron las colecciones al almacenamiento del servicio de configuración, se utiliza el envío de configuración para la distribución. +**Estado:** Todos los backends de almacenamiento se han migrado al patrón `CollectionConfigHandler`. + +## Solución + +Esta especificación aborda los problemas #1, #2, #3 y #4. + +### Parte 1: Corregir las faltas de coincidencia en el nombre del parámetro + +#### Cambio 1: Clase base AsyncProcessor - Cambiar el nombre del parámetro de la CLI +**Archivo:** `trustgraph-base/trustgraph/base/async_processor.py` +**Línea:** 260-264 + +**Actual:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**Fijo:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**Justificación:** +Nombres más claros y explícitos. +Coincide con el nombre de la variable interna `config_push_queue`. +El cambio es aceptable ya que la función actualmente no está operativa. +No se necesita ningún cambio en el código de params.get() - ya busca el nombre correcto. + +#### Cambio 2: Servicio de Configuración - Renombrar Parámetro de la Interfaz de Línea de Comandos +**Archivo:** `trustgraph-flow/trustgraph/config/service/service.py` +**Línea:** 276-279 + +**Actual:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Fijo:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Justificación:** +Nombres más claros: "config-push-queue" es más explícito que simplemente "push-queue". +Coincide con el nombre de la variable interna `config_push_queue`. +Consistente con el parámetro `--config-push-queue` de AsyncProcessor. +El cambio es aceptable ya que la función actualmente no está operativa. +No se necesita ningún cambio en el código en params.get() - ya busca el nombre correcto. + +### Parte 2: Agregar la parametrización del espacio de claves de Cassandra + +#### Cambio 3: Agregar el parámetro de espacio de claves al módulo cassandra_config +**Archivo:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**Agregar argumento de la línea de comandos** (en la función `add_cassandra_args()`): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**Agregar soporte para variables de entorno** (en la función `resolve_cassandra_config()`): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**Actualizar el valor de retorno** de `resolve_cassandra_config()`: +Actualmente devuelve: `(hosts, username, password)` +Cambiar para que devuelva: `(hosts, username, password, keyspace)` + +**Justificación:** +Coherente con el patrón de configuración de Cassandra existente +Disponible para todos los servicios a través de `add_cassandra_args()` +Admite la configuración mediante la línea de comandos y variables de entorno + +#### Cambio 4: Servicio de Configuración - Utilizar Espacios de Claves Parametrizados +**Archivo:** `trustgraph-flow/trustgraph/config/service/service.py` + +**Línea 30** - Eliminar el espacio de claves codificado de forma rígida: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**Líneas 69-73** - Actualización de la resolución de la configuración de Cassandra: + +**Actual:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**Fijo:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**Justificación:** +Mantiene la compatibilidad con versiones anteriores, utilizando "config" como valor predeterminado. +Permite la sobrescritura a través de `--cassandra-keyspace` o `CASSANDRA_KEYSPACE`. + +#### Cambio 5: Servicio de Conocimiento (Cores) - Utilizar Espacios de Claves Parametrizados +**Archivo:** `trustgraph-flow/trustgraph/cores/service.py` + +**Línea 37** - Eliminar el espacio de claves codificado de forma rígida: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**Actualización de la resolución de la configuración de Cassandra** (ubicación similar a la del servicio de configuración): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### Cambio 6: Servicio de Bibliotecario - Utilizar Claves de Espacio de Claves Parametrizadas +**Archivo:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Línea 51** - Eliminar el espacio de claves codificado de forma rígida: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**Actualización de la resolución de la configuración de Cassandra** (ubicación similar a la del servicio de configuración): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### Parte 3: Migrar la gestión de colecciones al servicio de configuración + +#### Resumen +Migrar las colecciones del espacio de claves de Cassandra librarian al almacenamiento del servicio de configuración. Esto elimina los temas de gestión de almacenamiento codificados de forma rígida y simplifica la arquitectura utilizando el mecanismo de envío de configuración existente para la distribución. + +#### Arquitectura actual +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### Nueva Arquitectura +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### Cambio 7: Administrador de Colecciones - Utilizar la API del Servicio de Configuración +**Archivo:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**Eliminar:** +Uso de `LibraryTableStore` (Líneas 33, 40-41) +Inicialización de productores de gestión de almacenamiento (Líneas 86-140) +Método `on_storage_response` (Líneas 400-430) +Seguimiento de `pending_deletions` (Líneas 57, 90-96 y uso en todo el código) + +**Añadir:** +Cliente del servicio de configuración para llamadas a la API (patrón de solicitud/respuesta) + +**Configuración del Cliente:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**Modificar `list_collections` (Líneas 145-180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**Modificar `update_collection` (Líneas 182-312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**Modificar `delete_collection` (Líneas 314-398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**Formato de Metadatos de Colección:** +Almacenado en la tabla de configuración como: `class='collections', key='user:collection'` +El valor es una instancia de CollectionMetadata serializada en formato JSON (sin campos de marca de tiempo) +Campos: `user`, `collection`, `name`, `description`, `tags` +Ejemplo: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### Cambio 8: Servicio de Bibliotecario - Eliminar la Infraestructura de Gestión de Almacenamiento +**Archivo:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Eliminar:** +Productores de gestión de almacenamiento (Líneas 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +Consumidor de respuesta de almacenamiento (Líneas 192-201) +Controlador `on_storage_response` (Líneas 467-473) + +**Modificar:** +Inicialización de CollectionManager (Líneas 215-224) - eliminar los parámetros del productor de almacenamiento + +**Nota:** La API externa de colecciones permanece sin cambios: +`list-collections` +`update-collection` +`delete-collection` + +#### Cambio 9: Eliminar la Tabla de Colecciones de LibraryTableStore +**Archivo:** `trustgraph-flow/trustgraph/tables/library.py` + +**Eliminar:** +Sentencia CREATE de la tabla de colecciones (Líneas 114-127) +Sentencias preparadas de colecciones (Líneas 205-240) +Todos los métodos de colección (Líneas 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**Justificación:** +Las colecciones ahora se almacenan en la tabla de configuración +El cambio importante es aceptable: no se necesita migración de datos +Simplifica significativamente el servicio de bibliotecario + +#### Cambio 10: Servicios de Almacenamiento - Gestión de Colecciones Basada en Configuración ✅ COMPLETADO + +**Estado:** Todos los 11 backends de almacenamiento se han migrado para usar `CollectionConfigHandler`. + +**Servicios Afectados (11 en total):** +Incrustaciones de documentos: milvus, pinecone, qdrant +Incrustaciones de grafos: milvus, pinecone, qdrant +Almacenamiento de objetos: cassandra +Almacenamiento de triples: cassandra, falkordb, memgraph, neo4j + +**Archivos:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**Patrón de Implementación (todos los servicios):** + +1. **Registrar el controlador de configuración en `__init__`:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **Implementar el manejador de configuración:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **Inicializar colecciones conocidas al inicio:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **Refactorizar los métodos de manejo existentes:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **Eliminar la infraestructura de administración de almacenamiento:** + Eliminar la configuración y el inicio de `self.storage_request_consumer` + Eliminar la configuración de `self.storage_response_producer` + Eliminar el método de despachador de `on_storage_management` + Eliminar las métricas para la administración de almacenamiento + Eliminar las importaciones: `StorageManagementRequest`, `StorageManagementResponse` + +**Consideraciones específicas del backend:** + +**Almacenes de vectores (Milvus, Pinecone, Qdrant):** Realizar un seguimiento de `(user, collection)` lógico en `known_collections`, pero puede crear múltiples colecciones de backend por dimensión. Continuar con el patrón de creación perezosa. Las operaciones de eliminación deben eliminar todas las variantes de dimensión. + +**Objetos Cassandra:** Las colecciones son propiedades de fila, no estructuras. Realizar un seguimiento de la información a nivel de keyspace. + +**Almacenes de grafos (Neo4j, Memgraph, FalkorDB):** Consultar nodos `CollectionMetadata` al inicio. Crear/eliminar nodos de metadatos durante la sincronización. + +**Triples de Cassandra:** Utilizar la API `KnowledgeGraph` para las operaciones de colección. + +**Puntos clave de diseño:** + +**Consistencia eventual:** No hay mecanismo de solicitud/respuesta, el empuje de configuración se transmite. +**Idempotencia:** Todas las operaciones de creación/eliminación deben ser seguras para reintentar. +**Manejo de errores:** Registrar los errores, pero no bloquear las actualizaciones de configuración. +**Autocuración:** Las operaciones fallidas se volverán a intentar en el siguiente empuje de configuración. +**Formato de clave de colección:** `"user:collection"` en `config["collections"]` + +#### Cambio 11: Actualizar el esquema de la colección: eliminar las marcas de tiempo +**Archivo:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**Modificar CollectionMetadata (líneas 13-21):** +Eliminar los campos `created_at` y `updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**Modificar CollectionManagementRequest (líneas 25-47):** +Eliminar campos de marca de tiempo: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**Justificación:** +Las marcas de tiempo no aportan valor a las colecciones. +El servicio de configuración mantiene su propio seguimiento de versiones. +Simplifica el esquema y reduce el almacenamiento. + +#### Beneficios de la migración del servicio de configuración + +1. ✅ **Elimina los temas de gestión de almacenamiento codificados de forma rígida** - Soluciona el bloqueo de multi-inquilino. +2. ✅ **Coordinación más sencilla** - No hay esperas asíncronas complejas para 4 o más respuestas de almacenamiento. +3. ✅ **Consistencia eventual** - Los servicios de almacenamiento se actualizan de forma independiente a través de la configuración. +4. ✅ **Mayor fiabilidad** - Configuración persistente frente a solicitud/respuesta no persistente. +5. ✅ **Modelo de configuración unificado** - Las colecciones se tratan como configuración. +6. ✅ **Reduce la complejidad** - Elimina aproximadamente 300 líneas de código de coordinación. +7. ✅ **Listo para multi-inquilino** - La configuración ya admite el aislamiento de inquilinos a través de espacios de claves. +8. ✅ **Seguimiento de versiones** - El mecanismo de versión del servicio de configuración proporciona un registro de auditoría. + +## Notas de implementación + +### Compatibilidad con versiones anteriores + +**Cambios de parámetros:** +Los cambios de nombre de los parámetros de la CLI son cambios importantes, pero aceptables (la función actualmente no está operativa). +Los servicios funcionan sin parámetros (utilizan los valores predeterminados). +Los espacios de claves predeterminados se conservan: "config", "knowledge", "librarian". +Cola predeterminada: `persistent://tg/config/config` + +**Gestión de colecciones:** +**Cambio importante:** La tabla de colecciones se elimina del espacio de claves de librarian. +**No se proporciona migración de datos** - aceptable para esta fase. +La API externa de colecciones no cambia (operaciones de lista, actualización y eliminación). +El formato de los metadatos de la colección se simplifica (se eliminan las marcas de tiempo). + +### Requisitos de prueba + +**Pruebas de parámetros:** +1. Verificar que el parámetro `--config-push-queue` funciona en el servicio graph-embeddings. +2. Verificar que el parámetro `--config-push-queue` funciona en el servicio text-completion. +3. Verificar que el parámetro `--config-push-queue` funciona en el servicio de configuración. +4. Verificar que el parámetro `--cassandra-keyspace` funciona para el servicio de configuración. +5. Verificar que el parámetro `--cassandra-keyspace` funciona para el servicio cores. +6. Verificar que el parámetro `--cassandra-keyspace` funciona para el servicio librarian. +7. Verificar que los servicios funcionan sin parámetros (utiliza los valores predeterminados). +8. Verificar la implementación multi-inquilino con nombres de cola y espacios de claves personalizados. + +**Pruebas de gestión de colecciones:** +9. Verificar la operación `list-collections` a través del servicio de configuración. +10. Verificar que `update-collection` crea/actualiza en la tabla de configuración. +11. Verificar que `delete-collection` elimina de la tabla de configuración. +12. Verificar que se activa la propagación de la configuración cuando se actualizan las colecciones. +13. Verificar que el filtrado de etiquetas funciona con el almacenamiento basado en la configuración. +14. Verificar que las operaciones de la colección funcionan sin campos de marca de tiempo. + +### Ejemplo de implementación multi-inquilino +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## Análisis de Impacto + +### Servicios Afectados por el Cambio 1-2 (Renombramiento de Parámetro de la CLI) +Todos los servicios que heredan de AsyncProcessor o FlowProcessor: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (todos los proveedores) +extract-* (todos los extractores) +query-* (todos los servicios de consulta) +retrieval-* (todos los servicios RAG) +storage-* (todos los servicios de almacenamiento) +Y más de 20 servicios + +### Servicios Afectados por los Cambios 3-6 (Espacio de Claves de Cassandra) +config-service +cores-service +librarian-service + +### Servicios Afectados por los Cambios 7-11 (Gestión de Colecciones) + +**Cambios Inmediatos:** +librarian-service (collection_manager.py, service.py) +tables/library.py (eliminación de la tabla de colecciones) +schema/services/collection.py (eliminación de la marca de tiempo) + +**Cambios Completados (Cambio 10):** ✅ +Todos los servicios de almacenamiento (11 en total) - migrados a la configuración push para las actualizaciones de colecciones a través de `CollectionConfigHandler` +Esquema de gestión de almacenamiento eliminado de `storage.py` + +## Consideraciones Futuras + +### Modelo de Espacio de Claves por Usuario + +Algunos servicios utilizan **espacios de claves por usuario** dinámicamente, donde cada usuario obtiene su propio espacio de claves de Cassandra: + +**Servicios con espacios de claves por usuario:** +1. **Servicio de Consulta de Triples** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + Utiliza `keyspace=query.user` +2. **Servicio de Consulta de Objetos** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + Utiliza `keyspace=self.sanitize_name(user)` +3. **Acceso Directo al Gráfico de Conocimiento** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + Parámetro predeterminado `keyspace="trustgraph"` + +**Estado:** Estos **no se modifican** en esta especificación. + +**Revisión Futura Requerida:** +Evaluar si el modelo de espacio de claves por usuario crea problemas de aislamiento de inquilinos +Considerar si las implementaciones multi-inquilino necesitan patrones de prefijos de espacio de claves (por ejemplo, `tenant_a_user1`) +Revisar posibles colisiones de ID de usuario entre inquilinos +Evaluar si un espacio de claves compartido único por inquilino con aislamiento de filas basado en el usuario es preferible + +**Nota:** Esto no bloquea la implementación multi-inquilino actual, pero debe revisarse antes de las implementaciones multi-inquilino de producción. + +## Fases de Implementación + +### Fase 1: Correcciones de Parámetros (Cambios 1-6) +Corregir el nombre del parámetro `--config-push-queue` +Agregar soporte para el parámetro `--cassandra-keyspace` +**Resultado:** Configuración de cola y espacio de claves multi-inquilino habilitada + +### Fase 2: Migración de la Gestión de Colecciones (Cambios 7-9, 11) +Migrar el almacenamiento de colecciones al servicio de configuración +Eliminar la tabla de colecciones de librarian +Actualizar el esquema de colecciones (eliminar marcas de tiempo) +**Resultado:** Elimina la gestión de almacenamiento codificada, simplifica librarian + +### Fase 3: Actualizaciones del Servicio de Almacenamiento (Cambio 10) ✅ COMPLETADO +Se actualizaron todos los servicios de almacenamiento para usar la configuración push para las colecciones a través de `CollectionConfigHandler` +Se eliminó la infraestructura de solicitud/respuesta de gestión de almacenamiento +Se eliminaron las definiciones de esquema heredadas +**Resultado:** Se logró una gestión de colecciones basada en configuración completa + +## Referencias +Problema de GitHub: https://github.com/trustgraph-ai/trustgraph/issues/582 +Archivos relacionados: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.he.md b/docs/tech-specs/multi-tenant-support.he.md new file mode 100644 index 00000000..1f07a72f --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.he.md @@ -0,0 +1,780 @@ +--- +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. + +## סקירה כללית + +אפשר ריבוי פריסות דיירים על ידי תיקון חוסר התאמות בשמות הפרמטרים שמונע התאמה אישית של תורים, והוספת פרמטריזציה של מרחבי מפתחות Cassandra. + +## הקשר ארכיטקטוני + +### פתרון תורים מבוסס זרימה + +מערכת TrustGraph משתמשת בארכיטקטורה **מבוססת זרימה** לפתרון דינמי של תורים, התומכת באופן מובנה בריבוי דיירים: + +**הגדרות זרימה** מאוחסנות ב-Cassandra ומציינות שמות תורים באמצעות הגדרות ממשק. +**שמות התורים משתמשים בתבניות** עם משתנים `{id}` שמוחלפים במזהי מופעי זרימה. +**השירותים פותרים באופן דינמי את התורים** על ידי חיפוש תצורות זרימה בזמן בקשה. +**לכל דייר יכולות להיות זרימות ייחודיות** עם שמות תורים שונים, המספקות בידוד. + +דוגמה להגדרת ממשק זרימה: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +כאשר שוכר א מתחיל זרימה `tenant-a-prod` ושוכר ב מתחיל זרימה `tenant-b-prod`, הם באופן אוטומטי מקבלים תורים מבודדים: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**שירותים המעוצבים כראוי עבור ריבוי שוכרים:** +✅ **ניהול ידע (ליבה)** - פותר באופן דינמי תורים מהגדרת הזרימה המועברת בבקשות + +**שירותים הדורשים תיקונים:** +🔴 **שירות תצורה** - חוסר התאמה בשם הפרמטר מונע התאמה אישית של תורים +🔴 **שירות ספרית** - נושאים של ניהול אחסון מקודדים (נדון בהמשך) +🔴 **כל השירותים** - לא ניתן להתאים אישית את מרחב המפתחות של Cassandra + +## הצהרת בעיה + +### בעיה #1: חוסר התאמה בשם פרמטר ב-AsyncProcessor +**הגדרות CLI:** `--config-queue` (שם לא ברור) +**Argparse ממיר ל:** `config_queue` (במילון הפרמטרים) +**הקוד מחפש:** `config_push_queue` +**תוצאה:** הפרמטר מתעלם, ברירת מחדל ל-`persistent://tg/config/config` +**השפעה:** משפיע על כל 32+ שירותים היורשים מ-AsyncProcessor +**חוסם:** פריסות מרובות שוכרים לא יכולות להשתמש בתורי תצורה ספציפיים לשוכר +**פתרון:** לשנות את שם הפרמטר ב-CLI ל-`--config-push-queue` לצורך בהירות (שינוי שבירה מקובל מכיוון שהתכונה שבורה כרגע) + +### בעיה #2: חוסר התאמה בשם פרמטר בשירות התצורה +**הגדרות CLI:** `--push-queue` (שם מעורפל) +**Argparse ממיר ל:** `push_queue` (במילון הפרמטרים) +**הקוד מחפש:** `config_push_queue` +**תוצאה:** הפרמטר מתעלם +**השפעה:** שירות התצורה לא יכול להשתמש בתור דחיפה מותאם אישית +**פתרון:** לשנות את שם הפרמטר ב-CLI ל-`--config-push-queue` לצורך עקביות ובהירות (שינוי שבירה מקובל) + +### בעיה #3: מרחב מפתחות Cassandra מקודד +**נוכחי:** מרחב המפתחות מקודד כ-`"config"`, `"knowledge"`, `"librarian"` בשירותים שונים +**תוצאה:** לא ניתן להתאים אישית את מרחב המפתחות עבור פריסות מרובות שוכרים +**השפעה:** שירותי תצורה, ליבה וספריה +**חוסם:** מספר שוכרים לא יכולים להשתמש במרחבי מפתחות Cassandra נפרדים + +### בעיה #4: ארכיטקטורת ניהול אוספים ✅ הושלם +**קודם:** אוספים שמורים במרחב המפתחות של Cassandra של הספריה באמצעות טבלת אוספים נפרדת +**קודם:** הספריה השתמשה ב-4 נושאים מקודדים לניהול אחסון לתאם יצירה/מחיקה של אוספים: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**בעיות (טופלו):** + נושאים מקודדים לא ניתן להתאים אישית עבור פריסות מרובות שוכרים + תיאום אסינכרוני מורכב בין הספריה לבין 4+ שירותי אחסון + טבלה נפרדת ותשתית ניהול + תורי בקשה/תגובה לא מתמידים עבור פעולות קריטיות +**פתרון מיושם:** העברנו אוספים לשירות האחסון של התצורה, השתמשנו בדחיפה של תצורה להפצה +**סטטוס:** כל בסיסי האחסון עברו לדפוס `CollectionConfigHandler` + +## פתרון + +מפרט זה מתייחס לבעיות #1, #2, #3 ו-#4. + +### חלק 1: תיקון חוסר התאמה בשמות פרמטרים + +#### שינוי 1: מחלקת בסיס AsyncProcessor - שינוי שם פרמטר CLI +**קובץ:** `trustgraph-base/trustgraph/base/async_processor.py` +**שורה:** 260-264 + +**נוכחי:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**קבוע:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**הסבר:** +שם ברור וחד יותר +תואם לשם המשתנה הפנימי `config_push_queue` +שינוי משמעותי מקובל מכיוון שהפיצ'ר אינו פעיל כרגע +אין צורך בשינוי קוד בפונקציה params.get() - היא כבר מחפשת את השם הנכון + +#### שינוי 2: שירות תצורה - שינוי שם פרמטר שורת הפקודה +**קובץ:** `trustgraph-flow/trustgraph/config/service/service.py` +**שורה:** 276-279 + +**נוכחי:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**קבוע:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**הסבר:** +שמות ברורים יותר - "config-push-queue" מפורט יותר מ-"push-queue" בלבד. +תואם לשם המשתנה הפנימי `config_push_queue`. +עקבי עם הפרמטר `--config-push-queue` של AsyncProcessor. +שינוי שעלול לשבור תאימות מקובל מכיוון שהפיצ'ר אינו פונקציונלי כרגע. +אין צורך בשינוי קוד בפונקציה params.get() - היא כבר מחפשת את השם הנכון. + +### חלק 2: הוספת פרמטריזציה של Keyspace של Cassandra + +#### שינוי 3: הוספת פרמטר Keyspace למודול cassandra_config +**קובץ:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**הוספת ארגומנט שורת פקודה** (בפונקציה `add_cassandra_args()`): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**הוספת תמיכה במשתני סביבה** (בפונקציה `resolve_cassandra_config()`): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**עדכון ערך ההחזרה** של `resolve_cassandra_config()`: +כרגע מחזיר: `(hosts, username, password)` +לשנות כך שיחזיר: `(hosts, username, password, keyspace)` + +**הצדקה:** +עקבי עם תבנית התצורה הקיימת של Cassandra +זמין לכל השירותים דרך `add_cassandra_args()` +תומך בתצורה הן דרך שורת הפקודה והן דרך משתני סביבה + +#### שינוי 4: שירות תצורה - שימוש במפתחות מרחב (Keyspace) מוגדרים +**קובץ:** `trustgraph-flow/trustgraph/config/service/service.py` + +**שורה 30** - הסרת שם מרחב (Keyspace) מקודד: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**שורות 69-73** - עדכון פתרון תצורת Cassandra: + +**נוכחי:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**קבוע:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**הסבר:** +שומר על תאימות לאחור עם "config" כברירת מחדל. +מאפשר ביטול באמצעות `--cassandra-keyspace` או `CASSANDRA_KEYSPACE`. + +#### שינוי 5: שירות ליבה/ידע - שימוש במרחבי מפתחות מוגדרים +**קובץ:** `trustgraph-flow/trustgraph/cores/service.py` + +**שורה 37** - הסרת מרחב מפתחות מקודד: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**עדכון פתרון תצורת Cassandra** (במיקום דומה לשירות התצורה): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### שינוי 6: שירות סוכן מידע - שימוש במפתחות פרמטריים +**קובץ:** `trustgraph-flow/trustgraph/librarian/service.py` + +**שורה 51** - הסרת מרחב מפתחות מקודד: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**עדכון פתרון תצורת Cassandra** (במיקום דומה לשירות התצורה): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### חלק 3: העברת ניהול אוספים לשירות התצורה + +#### סקירה כללית +העברת אוספים ממערכת ה-Cassandra librarian keyspace לאחסון בשירות התצורה. פעולה זו מבטלת נושאים מובנים לניהול אחסון ומפשטת את הארכיטקטורה על ידי שימוש במנגנון הדחיפה הקיים של התצורה לצורך הפצה. + +#### ארכיטקטורה נוכחית +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### ארכיטקטורה חדשה +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### שינוי 7: מנהל אוספים - שימוש ב-API של שירות התצורה +**קובץ:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**הסרה:** +שימוש ב-`LibraryTableStore` (שורות 33, 40-41) +אתחול מפיקי ניהול אחסון (שורות 86-140) +שיטה `on_storage_response` (שורות 400-430) +מעקב `pending_deletions` (שורות 57, 90-96 ושימוש לאורך כל הקוד) + +**הוספה:** +לקוח שירות תצורה עבור קריאות API (תבנית בקשה/תגובה) + +**הגדרת לקוח תצורה:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**שנה את `list_collections` (שורות 145-180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**שנה את `update_collection` (שורות 182-312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**שנה את `delete_collection` (שורות 314-398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**פורמט מטא-דאטה לאוספים:** +נשמר בטבלת התצורה כ: `class='collections', key='user:collection'` +הערך הוא CollectionMetadata ממוין ב-JSON (ללא שדות תאריך ושעה) +שדות: `user`, `collection`, `name`, `description`, `tags` +דוגמה: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### שינוי 8: שירות הספרייה - הסרת תשתית ניהול אחסון +**קובץ:** `trustgraph-flow/trustgraph/librarian/service.py` + +**הסרה:** +מפיקי ניהול אחסון (שורות 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +צרכן תגובות אחסון (שורות 192-201) +מטפל `on_storage_response` (שורות 467-473) + +**שינוי:** +אתחול CollectionManager (שורות 215-224) - הסרת פרמטרים של מפיק אחסון + +**הערה:** ממשק ה-API החיצוני לאוספים נשאר ללא שינוי: +`list-collections` +`update-collection` +`delete-collection` + +#### שינוי 9: הסרת טבלת האוספים מ-LibraryTableStore +**קובץ:** `trustgraph-flow/trustgraph/tables/library.py` + +**מחיקה:** +הצהרת CREATE של טבלת האוספים (שורות 114-127) +הצהרות מוכנות של האוספים (שורות 205-240) +כל שיטות האוספים (שורות 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**הצדקה:** +האוספים כעת מאוחסנים בטבלת התצורה +שינוי שמשפיע על השינויים - אין צורך בהעברת נתונים +מפשט את שירות הספרייה באופן משמעותי + +#### שינוי 10: שירותי אחסון - ניהול אוספים מבוסס תצורה ✅ הושלם + +**סטטוס:** כל 11 ה-backends של האחסון עברו לשימוש ב-`CollectionConfigHandler`. + +**שירותים מושפעים (סה"כ 11):** +הטמעות מסמכים: milvus, pinecone, qdrant +הטמעות גרפים: milvus, pinecone, qdrant +אחסון אובייקטים: cassandra +אחסון משולשות: cassandra, falkordb, memgraph, neo4j + +**קבצים:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**תבנית יישום (לכל השירותים):** + +1. **רישום מטפל תצורה ב-`__init__`:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **יישום מנהל תצורה:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **אתחול אוספים ידועים בעת ההפעלה:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **שכתוב של שיטות טיפול קיימות:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **הסרת תשתית ניהול אחסון:** + הסרת הגדרות והתחלה של `self.storage_request_consumer` + הסרת הגדרות של `self.storage_response_producer` + הסרת שיטת ה-dispatcher של `on_storage_management` + הסרת מדדים לניהול אחסון + הסרת יבוא: `StorageManagementRequest`, `StorageManagementResponse` + +**שיקולים ספציפיים ל-Backend:** + +**מאגרי וקטורים (Milvus, Pinecone, Qdrant):** לעקוב אחר `(user, collection)` לוגי ב-`known_collections`, אך ייתכן שייווצרו מספר אוספים ב-backend עבור כל מימד. להמשיך בדפוס היצירה המאוחרת. פעולות מחיקה חייבות להסיר את כל הווריאציות של המימד. + +**Cassandra Objects:** אוספים הם מאפייני שורות, ולא מבנים. לעקוב אחר מידע ברמת ה-keyspace. + +**מאגרי גרפים (Neo4j, Memgraph, FalkorDB):** לשאול צמתים של `CollectionMetadata` בעת ההפעלה. ליצור/למחוק צמתי מטא-נתונים בעת הסנכרון. + +**Cassandra Triples:** להשתמש ב-API של `KnowledgeGraph` עבור פעולות אוסף. + +**נקודות עיצוב מרכזיות:** + +**עקביות בסופו של דבר:** אין מנגנון בקשה/תגובה, דחיפת תצורה משודרת +**אידמפוטנטיות:** כל פעולות היצירה/מחיקה חייבות להיות בטוחות לניסיון חוזר +**טיפול בשגיאות:** לרשום שגיאות אך לא לחסום עדכוני תצורה +**ריפוי עצמי:** פעולות שנכשלו ינסו שוב בדחיפת התצורה הבאה +**פורמט מפתח אוסף:** `"user:collection"` ב-`config["collections"]` + +#### שינוי 11: עדכון סכימת האוסף - הסרת חותמות זמן +**קובץ:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**שינוי CollectionMetadata (שורות 13-21):** +להסיר את השדות `created_at` ו-`updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**שינוי ב-CollectionManagementRequest (שורות 25-47):** +הסרת שדות חותמת זמן: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**ההצדקה:** +חותמות זמן אינן מוסיפות ערך לאוספים +שירות התצורה שומר על מעקב גרסאות משלו +מפשט את הסכימה ומקטין את נפח האחסון + +#### יתרונות של מעבר לשירות התצורה + +1. ✅ **מבטל נושאים של ניהול אחסון מקודדים קשות** - פותר את החסימה של ריבוי דיירים +2. ✅ **תיאום פשוט יותר** - אין המתנה אסינכרונית מורכבת לתגובות של 4+ שירותי אחסון +3. ✅ **עקביות בסופו של דבר** - שירותי האחסון מתעדכנים באופן עצמאי באמצעות דחיפה של תצורה +4. ✅ **אמינות טובה יותר** - דחיפה קבועה של תצורה לעומת בקשה/תגובה לא קבועה +5. ✅ **מודל תצורה מאוחד** - אוספים מטופלים כתצורה +6. ✅ **מפחית מורכבות** - מסיר כ-300 שורות של קוד תיאום +7. ✅ **מוכן לריבוי דיירים** - התצורה כבר תומכת בבידוד דיירים באמצעות מרחבי מפתחות +8. ✅ **מעקב גרסאות** - מנגנון גרסאות של שירות התצורה מספק תיעוד ביקורת + +## הערות יישום + +### תאימות לאחור + +**שינויים בפרמטרים:** +שינויי שמות של פרמטרים בשורת הפקודה הם שינויים שוברים אך מקובלים (התכונה אינה פונקציונלית כרגע) +השירותים עובדים ללא פרמטרים (משתמשים בברירות המחדל) +מרחבי מפתחות ברירת מחדל נשמרו: "config", "knowledge", "librarian" +תור ברירת מחדל: `persistent://tg/config/config` + +**ניהול אוספים:** +**שינוי שובר:** הטבלה של האוספים הוסרה מממרחב המפתחות של librarian +**לא סופקה העברת נתונים** - מקובל לשלב זה +ממשק API חיצוני לאוספים לא השתנה (פעולות רשימה/עדכון/מחיקה) +פורמט מטא-נתונים של אוספים פושט (הוסרו חותמות זמן) + +### דרישות בדיקה + +**בדיקת פרמטרים:** +1. ודאו שהפרמטר `--config-push-queue` עובד בשירות graph-embeddings +2. ודאו שהפרמטר `--config-push-queue` עובד בשירות text-completion +3. ודאו שהפרמטר `--config-push-queue` עובד בשירות התצורה +4. ודאו שהפרמטר `--cassandra-keyspace` עובד עבור שירות התצורה +5. ודאו שהפרמטר `--cassandra-keyspace` עובד עבור שירות cores +6. ודאו שהפרמטר `--cassandra-keyspace` עובד עבור שירות librarian +7. ודאו שהשירותים עובדים ללא פרמטרים (משתמשים בברירות המחדל) +8. ודאו פריסה מרובת דיירים עם שמות תורים ומרחבי מפתחות מותאמים אישית + +**בדיקת ניהול אוספים:** +9. ודאו את הפעולה `list-collections` באמצעות שירות התצורה +10. ודאו ש-`update-collection` יוצר/מעדכן בטבלת התצורה +11. ודאו ש-`delete-collection` מסיר מטבלת התצורה +12. ודאו שדחיפה של תצורה מופעלת בעת עדכונים של אוספים +13. ודאו שסינון תגים עובד עם אחסון מבוסס תצורה +14. ודאו שפעולות על אוספים עובדות ללא שדות חותמות זמן + +### דוגמה לפריסה מרובת דיירים +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## ניתוח השפעה + +### שירותים המושפעים משינוי 1-2 (שינוי שם פרמטר CLI) +כל השירותים היורשים מ-AsyncProcessor או FlowProcessor: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (כל הספקיות) +extract-* (כל ה-extractors) +query-* (כל שירותי השאילתות) +retrieval-* (כל שירותי ה-RAG) +storage-* (כל שירותי האחסון) +ועוד 20+ שירותים + +### שירותים המושפעים משינויים 3-6 (Keyspace של Cassandra) +config-service +cores-service +librarian-service + +### שירותים המושפעים משינויים 7-11 (ניהול אוספים) + +**שינויים מיידיים:** +librarian-service (collection_manager.py, service.py) +tables/library.py (הסרת טבלת אוספים) +schema/services/collection.py (הסרת חותמת זמן) + +**שינויים שהושלמו (שינוי 10):** ✅ +כל שירותי האחסון (11 בסך הכל) - עברו ל-config push לעדכוני אוספים דרך `CollectionConfigHandler` +סכימת ניהול האחסון הוסרה מ-`storage.py` + +## שיקולים עתידיים + +### מודל Keyspace מבוסס משתמש + +חלק מהשירותים משתמשים באופן דינמי ב-**keyspace מבוסס משתמש**, כאשר לכל משתמש יש את ה-keyspace של Cassandra שלו: + +**שירותים עם keyspace מבוסס משתמש:** +1. **Triples Query Service** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + משתמש ב-`keyspace=query.user` +2. **Objects Query Service** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + משתמש ב-`keyspace=self.sanitize_name(user)` +3. **KnowledgeGraph Direct Access** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + פרמטר ברירת מחדל `keyspace="trustgraph"` + +**סטטוס:** אלה **לא משתנים** במפרט זה. + +**נדרשת בדיקה עתידית:** +להעריך האם מודל ה-keyspace מבוסס משתמש יוצר בעיות בידוד שוכרים +לשקול האם פריסות מרובות שוכרים צריכות דפוסי קידומת keyspace (לדוגמה, `tenant_a_user1`) +לבדוק לגבי התנגשות פוטנציאלית של מזהי משתמש בין שוכרים +להעריך האם keyspace משותף יחיד לכל שוכר עם בידוד שורות מבוסס משתמש עדיף + +**הערה:** זה לא חוסם את יישום הריבוי שוכרים הנוכחי, אך יש לבדוק אותו לפני פריסות ריבוי שוכרים לייצור. + +## שלבי יישום + +### שלב 1: תיקוני פרמטרים (שינויים 1-6) +לתקן את שם הפרמטר `--config-push-queue` +להוסיף תמיכה בפרמטר `--cassandra-keyspace` +**תוצאה:** תצורה של תור ו-keyspace מרובי שוכרים מופעלת + +### שלב 2: הגירת ניהול אוספים (שינויים 7-9, 11) +להגר את אחסון האוספים לשירות התצורה +להסיר את טבלת האוספים מ-librarian +לעדכן את סכימת האוספים (להסיר חותמות זמן) +**תוצאה:** מבטלת את נושאי ניהול האחסון המקודדים קשות, מפשטת את librarian + +### שלב 3: עדכוני שירותי אחסון (שינוי 10) ✅ הושלם +עדכנו את כל שירותי האחסון להשתמש ב-config push עבור אוספים דרך `CollectionConfigHandler` +הסרנו את תשתית הבקשות/תגובות לניהול אחסון +הסרנו הגדרות סכימה מיושנות +**תוצאה:** השגת ניהול אוספים מבוסס תצורה מלא + +## הפניות +GitHub Issue: https://github.com/trustgraph-ai/trustgraph/issues/582 +קבצים קשורים: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.hi.md b/docs/tech-specs/multi-tenant-support.hi.md new file mode 100644 index 00000000..737ed86c --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.hi.md @@ -0,0 +1,780 @@ +--- +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. + +## अवलोकन + +पैरामीटर नाम विसंगतियों को ठीक करके मल्टी-टेनेंट परिनियोजन सक्षम करें जो कतार अनुकूलन को रोकते हैं, और कैसेंड्रा कीस्पेस पैरामीटराइज़ेशन जोड़ें। + +## आर्किटेक्चर संदर्भ + +### फ्लो-आधारित कतार समाधान + +ट्रस्टग्राफ सिस्टम गतिशील कतार समाधान के लिए एक **फ्लो-आधारित आर्किटेक्चर** का उपयोग करता है, जो स्वाभाविक रूप से मल्टी-टेनेंसी का समर्थन करता है: + +**फ्लो परिभाषाएँ** कैसेंड्रा में संग्रहीत हैं और इंटरफ़ेस परिभाषाओं के माध्यम से कतार नामों को निर्दिष्ट करती हैं। +**कतार नाम टेम्प्लेट का उपयोग करते हैं** जिसमें `{id}` चर होते हैं जिन्हें फ्लो इंस्टेंस आईडी के साथ प्रतिस्थापित किया जाता है। +**सेवाएँ गतिशील रूप से कतारों को हल करती हैं** अनुरोध समय पर फ्लो कॉन्फ़िगरेशन की खोज करके। +**प्रत्येक किरायेदार के पास अलग-अलग कतार नामों के साथ अद्वितीय फ्लो हो सकते हैं**, जो अलगाव प्रदान करते हैं। + +फ्लो इंटरफ़ेस परिभाषा का उदाहरण: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +जब किरायेदार ए प्रवाह `tenant-a-prod` शुरू करता है और किरायेदार बी प्रवाह `tenant-b-prod` शुरू करता है, तो उन्हें स्वचालित रूप से अलग-अलग कतारें मिलती हैं: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**मल्टी-टेनेंसी के लिए सही ढंग से डिज़ाइन की गई सेवाएं:** +✅ **नॉलेज मैनेजमेंट (कोर)** - अनुरोधों में पारित प्रवाह कॉन्फ़िगरेशन से कतारों को गतिशील रूप से हल करता है + +**जिन सेवाओं को ठीक करने की आवश्यकता है:** +🔴 **कॉन्फ़िग सर्विस** - पैरामीटर नाम बेमेल होने से कतार अनुकूलन में बाधा आती है +🔴 **लाइब्रेरियन सर्विस** - हार्डकोडेड स्टोरेज मैनेजमेंट टॉपिक (नीचे चर्चा की गई है) +🔴 **सभी सेवाएं** - कैसेंड्रा कीस्पेस को अनुकूलित नहीं किया जा सकता है + +## समस्या विवरण + +### मुद्दा #1: एसिंक्रोनसप्रोसेसर में पैरामीटर नाम बेमेल +**CLI द्वारा परिभाषित:** `--config-queue` (अस्पष्ट नामकरण) +**Argparse द्वारा रूपांतरण:** `config_queue` (पैरामीटर डिक्ट में) +**कोड द्वारा खोजा गया:** `config_push_queue` +**परिणाम:** पैरामीटर को अनदेखा किया जाता है, डिफ़ॉल्ट रूप से `persistent://tg/config/config` +**प्रभाव:** 32 से अधिक सेवाओं पर प्रभाव पड़ता है जो AsyncProcessor से विरासत में मिली हैं +**बाधा:** मल्टी-टेनेंट डिप्लॉयमेंट किरायेदार-विशिष्ट कॉन्फ़िग कतारों का उपयोग नहीं कर सकते हैं +**समाधान:** स्पष्टता के लिए CLI पैरामीटर का नाम बदलकर `--config-push-queue` करें (ब्रेकिंग चेंज स्वीकार्य है क्योंकि सुविधा वर्तमान में टूटी हुई है) + +### मुद्दा #2: कॉन्फ़िग सर्विस में पैरामीटर नाम बेमेल +**CLI द्वारा परिभाषित:** `--push-queue` (अस्पष्ट नामकरण) +**Argparse द्वारा रूपांतरण:** `push_queue` (पैरामीटर डिक्ट में) +**कोड द्वारा खोजा गया:** `config_push_queue` +**परिणाम:** पैरामीटर को अनदेखा किया जाता है +**प्रभाव:** कॉन्फ़िग सर्विस कस्टम पुश कतार का उपयोग नहीं कर सकती है +**समाधान:** स्थिरता और स्पष्टता के लिए CLI पैरामीटर का नाम बदलकर `--config-push-queue` करें (ब्रेकिंग चेंज स्वीकार्य है) + +### मुद्दा #3: हार्डकोडेड कैसेंड्रा कीस्पेस +**वर्तमान:** विभिन्न सेवाओं में कीस्पेस को हार्डकोडेड के रूप में `"config"`, `"knowledge"`, `"librarian"` के रूप में परिभाषित किया गया है +**परिणाम:** मल्टी-टेनेंट डिप्लॉयमेंट के लिए कीस्पेस को अनुकूलित नहीं किया जा सकता है +**प्रभाव:** कॉन्फ़िग, कोर और लाइब्रेरियन सेवाएं +**बाधा:** कई किरायेदार अलग-अलग कैसेंड्रा कीस्पेस का उपयोग नहीं कर सकते हैं + +### मुद्दा #4: कलेक्शन मैनेजमेंट आर्किटेक्चर ✅ पूर्ण +**पिछला:** कलेक्शन को लाइब्रेरियन कीस्पेस में एक अलग कलेक्शन टेबल के माध्यम से संग्रहीत किया जाता था +**पिछला:** लाइब्रेरियन ने कलेक्शन बनाने/हटाने के लिए 4 हार्डकोडेड स्टोरेज मैनेजमेंट टॉपिक का उपयोग किया: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**समस्याएं (हल की गई):** + हार्डकोडेड टॉपिक को मल्टी-टेनेंट डिप्लॉयमेंट के लिए अनुकूलित नहीं किया जा सकता था + लाइब्रेरियन और 4+ स्टोरेज सेवाओं के बीच जटिल एसिंक्रोनस समन्वय + अलग कैसेंड्रा टेबल और प्रबंधन अवसंरचना + महत्वपूर्ण कार्यों के लिए गैर-स्थायी अनुरोध/प्रतिक्रिया कतारें +**कार्यान्वित समाधान:** कलेक्शन को कॉन्फ़िग सर्विस स्टोरेज में माइग्रेट किया गया, वितरण के लिए कॉन्फ़िग पुश का उपयोग किया गया +**स्थिति:** सभी स्टोरेज बैकएंड को `CollectionConfigHandler` पैटर्न में माइग्रेट किया गया है + +## समाधान + +यह विनिर्देश मुद्दों #1, #2, #3 और #4 को संबोधित करता है। + +### भाग 1: पैरामीटर नाम बेमेल को ठीक करें + +#### परिवर्तन 1: AsyncProcessor बेस क्लास - CLI पैरामीटर का नाम बदलें +**फ़ाइल:** `trustgraph-base/trustgraph/base/async_processor.py` +**पंक्ति:** 260-264 + +**वर्तमान:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**निश्चित:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**तर्क:** +अधिक स्पष्ट और विस्तृत नामकरण +आंतरिक चर नाम से मेल खाता है `config_push_queue` +परिवर्तन स्वीकार्य है क्योंकि सुविधा वर्तमान में गैर-कार्यात्मक है +params.get() में कोई कोड परिवर्तन आवश्यक नहीं है - यह पहले से ही सही नाम की तलाश करता है + +#### परिवर्तन 2: कॉन्फ़िगरेशन सेवा - CLI पैरामीटर का नाम बदलें +**फ़ाइल:** `trustgraph-flow/trustgraph/config/service/service.py` +**पंक्ति:** 276-279 + +**वर्तमान:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**निश्चित:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**तर्क:** +अधिक स्पष्ट नामकरण - "config-push-queue" केवल "push-queue" से अधिक स्पष्ट है। +आंतरिक चर नाम `config_push_queue` से मेल खाता है। +AsyncProcessor के `--config-push-queue` पैरामीटर के साथ संगत। +परिवर्तन स्वीकार्य है क्योंकि सुविधा वर्तमान में गैर-कार्यात्मक है। +params.get() में कोई कोड परिवर्तन आवश्यक नहीं है - यह पहले से ही सही नाम की तलाश करता है। + +### भाग 2: कैसेंड्रा कीस्पेस पैरामीटराइज़ेशन जोड़ें + +#### परिवर्तन 3: cassandra_config मॉड्यूल में कीस्पेस पैरामीटर जोड़ें +**फ़ाइल:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**CLI तर्क जोड़ें** (`add_cassandra_args()` फ़ंक्शन में): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**पर्यावरण चर समर्थन जोड़ें** (फ़ंक्शन `resolve_cassandra_config()` में): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**`resolve_cassandra_config()` का रिटर्न वैल्यू अपडेट करें:** +वर्तमान में रिटर्न करता है: `(hosts, username, password)` +बदलने पर रिटर्न करेगा: `(hosts, username, password, keyspace)` + +**तर्क:** +मौजूदा कैसेंड्रा कॉन्फ़िगरेशन पैटर्न के अनुरूप +`add_cassandra_args()` के माध्यम से सभी सेवाओं के लिए उपलब्ध +CLI और पर्यावरण चर कॉन्फ़िगरेशन दोनों का समर्थन करता है + +#### परिवर्तन 4: कॉन्फ़िगरेशन सर्विस - पैरामीटराइज़्ड कीस्पेस का उपयोग करें +**फ़ाइल:** `trustgraph-flow/trustgraph/config/service/service.py` + +**पंक्ति 30** - हार्डकोडेड कीस्पेस हटाएं: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**पंक्तियाँ 69-73** - कैसेंड्रा कॉन्फ़िगरेशन रिज़ॉल्यूशन को अपडेट करें: + +**वर्तमान:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**निश्चित:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**तर्क:** +"config" को डिफ़ॉल्ट के रूप में रखते हुए पिछली अनुकूलता बनाए रखता है। +`--cassandra-keyspace` या `CASSANDRA_KEYSPACE` के माध्यम से ओवरराइड करने की अनुमति देता है। + +#### परिवर्तन 5: कोर/नॉलेज सर्विस - पैरामीटराइज़्ड कीस्पेस का उपयोग करें। +**फ़ाइल:** `trustgraph-flow/trustgraph/cores/service.py` + +**पंक्ति 37** - हार्डकोडेड कीस्पेस को हटाएँ: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**कैसेंड्रा कॉन्फ़िगरेशन रिज़ॉल्यूशन को अपडेट करें** (कॉन्फ़िगरेशन सेवा के समान स्थान पर): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### परिवर्तन 6: लाइब्रेरियन सेवा - पैरामीटराइज़्ड कीस्पेस का उपयोग करें +**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/service.py` + +**पंक्ति 51** - हार्डकोडेड कीस्पेस हटाएं: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**कैसेंड्रा कॉन्फ़िगरेशन रिज़ॉल्यूशन को अपडेट करें** (कॉन्फ़िगरेशन सेवा के समान स्थान पर): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### भाग 3: संग्रह प्रबंधन को कॉन्फ़िगरेशन सेवा में स्थानांतरित करें + +#### अवलोकन +संग्रहों को कैसेंड्रा लाइब्रेरियन कीस्पेस से कॉन्फ़िगरेशन सेवा भंडारण में स्थानांतरित करें। यह हार्ड-कोडेड भंडारण प्रबंधन विषयों को समाप्त करता है और मौजूदा कॉन्फ़िगरेशन पुश तंत्र का उपयोग करके वितरण के लिए वास्तुकला को सरल बनाता है। + +#### वर्तमान वास्तुकला +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### नई वास्तुकला +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### परिवर्तन 7: संग्रह प्रबंधक - कॉन्फ़िगरेशन सेवा एपीआई का उपयोग करें +**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**हटाएं:** +`LibraryTableStore` का उपयोग (पंक्तियाँ 33, 40-41) +स्टोरेज प्रबंधन उत्पादकों का आरंभीकरण (पंक्तियाँ 86-140) +`on_storage_response` विधि (पंक्तियाँ 400-430) +`pending_deletions` ट्रैकिंग (पंक्तियाँ 57, 90-96, और पूरे में उपयोग) + +**जोड़ें:** +एपीआई कॉल के लिए कॉन्फ़िगरेशन सेवा क्लाइंट (अनुरोध/प्रतिक्रिया पैटर्न) + +**कॉन्फ़िगरेशन क्लाइंट सेटअप:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**`list_collections` को संशोधित करें (पंक्तियाँ 145-180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**`update_collection` को संशोधित करें (पंक्तियाँ 182-312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**`delete_collection` में संशोधन करें (पंक्तियाँ 314-398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**संग्रह मेटाडेटा प्रारूप:** +कॉन्फ़िगरेशन तालिका में इस प्रकार संग्रहीत: `class='collections', key='user:collection'` +मान JSON-सीरियलाइज़्ड CollectionMetadata है (समय-मुद्रांकन फ़ील्ड के बिना) +फ़ील्ड: `user`, `collection`, `name`, `description`, `tags` +उदाहरण: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### परिवर्तन 8: लाइब्रेरियन सेवा - स्टोरेज मैनेजमेंट इंफ्रास्ट्रक्चर को हटाएं +**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/service.py` + +**हटाएं:** +स्टोरेज मैनेजमेंट प्रोड्यूसर (पंक्ति 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +स्टोरेज रिस्पांस कंज्यूमर (पंक्ति 192-201) +`on_storage_response` हैंडलर (पंक्ति 467-473) + +**संशोधित करें:** +CollectionManager इनिशियलाइज़ेशन (पंक्ति 215-224) - स्टोरेज प्रोड्यूसर पैरामीटर हटाएं + +**ध्यान दें:** बाहरी संग्रह एपीआई अपरिवर्तित रहता है: +`list-collections` +`update-collection` +`delete-collection` + +#### परिवर्तन 9: LibraryTableStore से Collections टेबल को हटाएं +**फ़ाइल:** `trustgraph-flow/trustgraph/tables/library.py` + +**हटाएं:** +Collections टेबल CREATE स्टेटमेंट (पंक्ति 114-127) +Collections तैयार स्टेटमेंट (पंक्ति 205-240) +सभी संग्रह विधियाँ (पंक्ति 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**तर्क:** +संग्रह अब कॉन्फ़िगरेशन तालिका में संग्रहीत हैं। +परिवर्तन स्वीकार्य है - डेटा माइग्रेशन की आवश्यकता नहीं है। +लाइब्रेरियन सेवा को काफी सरल बनाता है। + +#### परिवर्तन 10: स्टोरेज सेवाएं - कॉन्फ़िगरेशन-आधारित संग्रह प्रबंधन ✅ पूर्ण + +**स्थिति:** सभी 11 स्टोरेज बैकएंड को `CollectionConfigHandler` का उपयोग करने के लिए माइग्रेट किया गया है। + +**प्रभावित सेवाएं (कुल 11):** +दस्तावेज़ एम्बेडिंग: मिलवस, पाइनकोन, क्यूड्रांट +ग्राफ एम्बेडिंग: मिलवस, पाइनकोन, क्यूड्रांट +ऑब्जेक्ट स्टोरेज: कैसेंड्रा +ट्रिपल स्टोरेज: कैसेंड्रा, फाल्कोडीबी, मेमग्राफ, नियो4जे + +**फाइलें:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**कार्यान्वयन पैटर्न (सभी सेवाएं):** + +1. **`__init__` में कॉन्फ़िगरेशन हैंडलर पंजीकृत करें:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **कॉन्फ़िगरेशन हैंडलर को लागू करें:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **प्रारंभ में ज्ञात संग्रहों को आरंभीकृत करें:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **मौजूदा हैंडलर विधियों को पुनर्गठित करें:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **भंडारण प्रबंधन अवसंरचना को हटाएं:** + `self.storage_request_consumer` सेटअप और प्रारंभ को हटाएं + `self.storage_response_producer` सेटअप को हटाएं + `on_storage_management` डिस्पैचर विधि को हटाएं + भंडारण प्रबंधन के लिए मेट्रिक्स को हटाएं + इम्पोर्ट को हटाएं: `StorageManagementRequest`, `StorageManagementResponse` + +**बैकएंड-विशिष्ट विचार:** + +**वेक्टर स्टोर (मिलवस, पाइनकोन, क्यूड्रांट):** `known_collections` में लॉजिकल `(user, collection)` को ट्रैक करें, लेकिन प्रत्येक आयाम के लिए कई बैकएंड संग्रह बनाए जा सकते हैं। आलसी निर्माण पैटर्न जारी रखें। हटाने के कार्यों को सभी आयाम वेरिएंट को हटाना चाहिए। + +**कैसेंड्रा ऑब्जेक्ट्स:** संग्रह पंक्ति गुण हैं, संरचनाएं नहीं। कीस्पेस-स्तरीय जानकारी को ट्रैक करें। + +**ग्राफ स्टोर (नियो4जे, मेमग्राफ, फाल्कोर्डबी):** स्टार्टअप पर `CollectionMetadata` नोड्स को क्वेरी करें। सिंक पर मेटाडेटा नोड्स बनाएं/हटाएं। + +**कैसेंड्रा ट्रिपल्स:** संग्रह संचालन के लिए `KnowledgeGraph` एपीआई का उपयोग करें। + +**मुख्य डिज़ाइन बिंदु:** + +**अंतिम स्थिरता:** कोई अनुरोध/प्रतिक्रिया तंत्र नहीं, कॉन्फ़िगरेशन पुश प्रसारित किया जाता है +**अपरिवर्तनीयता:** सभी निर्माण/हटाने के संचालन को पुनः प्रयास करना सुरक्षित होना चाहिए +**त्रुटि प्रबंधन:** त्रुटियों को लॉग करें लेकिन कॉन्फ़िगरेशन अपडेट को अवरुद्ध न करें +**स्व-सुधार:** विफल संचालन अगले कॉन्फ़िगरेशन पुश पर पुनः प्रयास करेंगे +**संग्रह कुंजी प्रारूप:** `config["collections"]` में `"user:collection"` + +#### परिवर्तन 11: संग्रह स्कीमा अपडेट करें - टाइमस्टैम्प हटाएं +**फ़ाइल:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**संग्रहMetadata (पंक्ति 13-21) को संशोधित करें:** +`created_at` और `updated_at` फ़ील्ड को हटाएं: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**कलेक्शनमैनेजमेंट रिक्वेस्ट में बदलाव (पंक्ति 25-47):** +टाइमस्टैम्प फ़ील्ड हटाएं: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**तर्क:** +टाइमस्टैम्प संग्रह के लिए कोई मूल्य नहीं जोड़ते हैं। +कॉन्फ़िगरेशन सेवा अपनी संस्करण ट्रैकिंग बनाए रखती है। +स्कीमा को सरल बनाता है और भंडारण को कम करता है। + +#### कॉन्फ़िगरेशन सेवा माइग्रेशन के लाभ + +1. ✅ **हार्डकोडेड स्टोरेज प्रबंधन विषयों को समाप्त करता है** - मल्टी-टेनेंट अवरोध को हल करता है। +2. ✅ **सरल समन्वय** - 4+ स्टोरेज प्रतिक्रियाओं के लिए कोई जटिल एसिंक्रोनस प्रतीक्षा नहीं। +3. ✅ **अंतिम स्थिरता** - स्टोरेज सेवाएं कॉन्फ़िगरेशन पुश के माध्यम से स्वतंत्र रूप से अपडेट करती हैं। +4. ✅ **बेहतर विश्वसनीयता** - गैर-स्थायी अनुरोध/प्रतिक्रिया के विपरीत, लगातार कॉन्फ़िगरेशन पुश। +5. ✅ **एकीकृत कॉन्फ़िगरेशन मॉडल** - संग्रह को कॉन्फ़िगरेशन के रूप में माना जाता है। +6. ✅ **जटिलता को कम करता है** - ~300 लाइनों के समन्वय कोड को हटाता है। +7. ✅ **मल्टी-टेनेंट के लिए तैयार** - कॉन्फ़िगरेशन पहले से ही कीस्पेस के माध्यम से किरायेदार अलगाव का समर्थन करता है। +8. ✅ **संस्करण ट्रैकिंग** - कॉन्फ़िगरेशन सेवा संस्करण तंत्र ऑडिट ट्रेल प्रदान करता है। + +## कार्यान्वयन नोट्स + +### पिछड़ा संगतता + +**पैरामीटर परिवर्तन:** +CLI पैरामीटर का नाम बदलना एक ब्रेकिंग परिवर्तन है लेकिन स्वीकार्य है (फ़ीचर वर्तमान में गैर-कार्यात्मक है)। +सेवाएं पैरामीटर के बिना काम करती हैं (डिफ़ॉल्ट का उपयोग करें)। +डिफ़ॉल्ट कीस्पेस संरक्षित हैं: "config", "knowledge", "librarian" +डिफ़ॉल्ट कतार: `persistent://tg/config/config` + +**संग्रह प्रबंधन:** +**ब्रेकिंग परिवर्तन:** लाइब्रेरियन कीस्पेस से संग्रह तालिका हटा दी गई है। +**कोई डेटा माइग्रेशन प्रदान नहीं किया गया है** - इस चरण के लिए स्वीकार्य है। +बाहरी संग्रह API अपरिवर्तित है (सूची/अपडेट/हटाने के संचालन)। +संग्रह मेटाडेटा प्रारूप को सरल बनाया गया है (टाइमस्टैम्प हटा दिए गए हैं)। + +### परीक्षण आवश्यकताएँ + +**पैरामीटर परीक्षण:** +1. सत्यापित करें कि `--config-push-queue` पैरामीटर ग्राफ-एम्बेडिंग सेवा पर काम करता है। +2. सत्यापित करें कि `--config-push-queue` पैरामीटर टेक्स्ट-कंप्लीशन सेवा पर काम करता है। +3. सत्यापित करें कि `--config-push-queue` पैरामीटर कॉन्फ़िगरेशन सेवा पर काम करता है। +4. सत्यापित करें कि `--cassandra-keyspace` पैरामीटर कॉन्फ़िगरेशन सेवा के लिए काम करता है। +5. सत्यापित करें कि `--cassandra-keyspace` पैरामीटर कोर सेवा के लिए काम करता है। +6. सत्यापित करें कि `--cassandra-keyspace` पैरामीटर लाइब्रेरियन सेवा के लिए काम करता है। +7. सत्यापित करें कि सेवाएं पैरामीटर के बिना काम करती हैं (डिफ़ॉल्ट का उपयोग करती हैं)। +8. कस्टम कतार नामों और कीस्पेस के साथ मल्टी-टेनेंट परिनियोजन सत्यापित करें। + +**संग्रह प्रबंधन परीक्षण:** +9. कॉन्फ़िगरेशन सेवा के माध्यम से `list-collections` ऑपरेशन सत्यापित करें। +10. सत्यापित करें कि `update-collection` कॉन्फ़िगरेशन तालिका में बनाता/अपडेट करता है। +11. सत्यापित करें कि `delete-collection` कॉन्फ़िगरेशन तालिका से हटाता है। +12. सत्यापित करें कि संग्रह अपडेट पर कॉन्फ़िगरेशन पुश ट्रिगर होता है। +13. सत्यापित करें कि कॉन्फ़िगरेशन-आधारित स्टोरेज के साथ टैग फ़िल्टरिंग काम करता है। +14. सत्यापित करें कि संग्रह ऑपरेशन टाइमस्टैम्प फ़ील्ड के बिना काम करते हैं। + +### मल्टी-टेनेंट परिनियोजन उदाहरण +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## प्रभाव विश्लेषण + +### परिवर्तन 1-2 से प्रभावित सेवाएं (CLI पैरामीटर का नाम बदलना) +सभी सेवाएं जो AsyncProcessor या FlowProcessor से विरासत में मिली हैं: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (सभी प्रदाता) +extract-* (सभी एक्सट्रैक्टर) +query-* (सभी क्वेरी सेवाएं) +retrieval-* (सभी RAG सेवाएं) +storage-* (सभी स्टोरेज सेवाएं) +और 20+ से अधिक सेवाएं + +### परिवर्तन 3-6 से प्रभावित सेवाएं (कैसेंड्रा कीस्पेस) +config-service +cores-service +librarian-service + +### परिवर्तन 7-11 से प्रभावित सेवाएं (संग्रह प्रबंधन) + +**तत्काल परिवर्तन:** +librarian-service (collection_manager.py, service.py) +tables/library.py (संग्रह तालिका को हटाना) +schema/services/collection.py (टाइमस्टैम्प को हटाना) + +**पूरे हुए परिवर्तन (परिवर्तन 10):** ✅ +सभी स्टोरेज सेवाएं (कुल 11) - संग्रह अपडेट के लिए कॉन्फ़िगरेशन पुश के माध्यम से `CollectionConfigHandler` में माइग्रेट किया गया +`storage.py` से स्टोरेज प्रबंधन स्कीमा को हटाया गया + +## भविष्य के विचार + +### प्रति-उपयोगकर्ता कीस्पेस मॉडल + +कुछ सेवाएं **प्रति-उपयोगकर्ता कीस्पेस** गतिशील रूप से उपयोग करती हैं, जहां प्रत्येक उपयोगकर्ता का अपना कैसेंड्रा कीस्पेस होता है: + +**प्रति-उपयोगकर्ता कीस्पेस वाली सेवाएं:** +1. **ट्रिपल्स क्वेरी सर्विस** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + `keyspace=query.user` का उपयोग करता है +2. **ऑब्जेक्ट्स क्वेरी सर्विस** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + `keyspace=self.sanitize_name(user)` का उपयोग करता है +3. **नॉलेज ग्राफ डायरेक्ट एक्सेस** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + डिफ़ॉल्ट पैरामीटर `keyspace="trustgraph"` + +**स्थिति:** ये इस विनिर्देश में **बदले नहीं गए** हैं। + +**भविष्य की समीक्षा आवश्यक:** +मूल्यांकन करें कि क्या प्रति-उपयोगकर्ता कीस्पेस मॉडल किरायेदार अलगाव के मुद्दे बनाता है +इस पर विचार करें कि क्या मल्टी-टेनेन्ट डिप्लॉयमेंट को कीस्पेस उपसर्ग पैटर्न (जैसे, `tenant_a_user1`) की आवश्यकता है +किरायेदारों में संभावित उपयोगकर्ता आईडी टकराव के लिए समीक्षा करें +मूल्यांकन करें कि क्या प्रति किरायेदार एकल साझा कीस्पेस उपयोगकर्ता-आधारित पंक्ति अलगाव के साथ अधिक उपयुक्त है + +**नोट:** यह वर्तमान मल्टी-टेनेन्ट कार्यान्वयन को अवरुद्ध नहीं करता है, लेकिन उत्पादन मल्टी-टेनेन्ट डिप्लॉयमेंट से पहले इसकी समीक्षा की जानी चाहिए। + +## कार्यान्वयन चरण + +### चरण 1: पैरामीटर सुधार (परिवर्तन 1-6) +`--config-push-queue` पैरामीटर नामकरण को ठीक करें +`--cassandra-keyspace` पैरामीटर समर्थन जोड़ें +**परिणाम:** मल्टी-टेनेन्ट कतार और कीस्पेस कॉन्फ़िगरेशन सक्षम + +### चरण 2: संग्रह प्रबंधन माइग्रेशन (परिवर्तन 7-9, 11) +संग्रह स्टोरेज को कॉन्फ़िगरेशन सेवा में माइग्रेट करें +लाइब्रेरियन से संग्रह तालिका को हटा दें +संग्रह स्कीमा को अपडेट करें (टाइमस्टैम्प हटाएं) +**परिणाम:** हार्डकोडेड स्टोरेज प्रबंधन विषयों को समाप्त करता है, लाइब्रेरियन को सरल बनाता है + +### चरण 3: स्टोरेज सर्विस अपडेट (परिवर्तन 10) ✅ पूर्ण +सभी स्टोरेज सेवाओं को `CollectionConfigHandler` के माध्यम से संग्रह के लिए कॉन्फ़िगरेशन पुश का उपयोग करने के लिए अपडेट किया गया +स्टोरेज प्रबंधन अनुरोध/प्रतिक्रिया बुनियादी ढांचे को हटा दिया गया +विरासत स्कीमा परिभाषाओं को हटा दिया गया +**परिणाम:** कॉन्फ़िगरेशन-आधारित संग्रह प्रबंधन प्राप्त हुआ + +## संदर्भ +GitHub मुद्दा: https://github.com/trustgraph-ai/trustgraph/issues/582 +संबंधित फाइलें: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.md b/docs/tech-specs/multi-tenant-support.md index dc0555c1..19328ec0 100644 --- a/docs/tech-specs/multi-tenant-support.md +++ b/docs/tech-specs/multi-tenant-support.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Technical Specification: Multi-Tenant Support" +parent: "Tech Specs" +--- + # Technical Specification: Multi-Tenant Support ## Overview diff --git a/docs/tech-specs/multi-tenant-support.pt.md b/docs/tech-specs/multi-tenant-support.pt.md new file mode 100644 index 00000000..5010a350 --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.pt.md @@ -0,0 +1,780 @@ +--- +layout: default +title: "Especificação Técnica: Suporte para Multi-Tenancy" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica: Suporte para Multi-Tenancy + +> **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 + +Habilite implantações multi-tenant corrigindo incompatibilidades de nomes de parâmetros que impedem a personalização da fila e adicionando parametrização do keyspace do Cassandra. + +## Contexto da Arquitetura + +### Resolução de Filas Baseada em Fluxo + +O sistema TrustGraph usa uma **arquitetura baseada em fluxo** para a resolução dinâmica de filas, que suporta inerentemente o multi-tenancy: + +As **Definições de Fluxo** são armazenadas no Cassandra e especificam os nomes das filas por meio de definições de interface. +**Os nomes das filas usam modelos** com variáveis `{id}` que são substituídas pelos IDs das instâncias de fluxo. +**Os serviços resolvem dinamicamente as filas** consultando as configurações de fluxo no momento da solicitação. +**Cada tenant pode ter fluxos únicos** com nomes de fila diferentes, proporcionando isolamento. + +Exemplo de definição de interface de fluxo: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +Quando o tenant A inicia o fluxo `tenant-a-prod` e o tenant B inicia o fluxo `tenant-b-prod`, eles automaticamente recebem filas isoladas: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**Serviços corretamente projetados para multi-tenancy:** +✅ **Knowledge Management (cores)** - Resolve dinamicamente as filas a partir da configuração do fluxo passada nas requisições + +**Serviços que precisam de correções:** +🔴 **Config Service** - Incompatibilidade no nome do parâmetro impede a personalização da fila +🔴 **Librarian Service** - Tópicos de gerenciamento de armazenamento codificados (discutido abaixo) +🔴 **Todos os Serviços** - Não é possível personalizar o keyspace do Cassandra + +## Declaração do Problema + +### Problema #1: Incompatibilidade no Nome do Parâmetro no AsyncProcessor +**CLI define:** `--config-queue` (nomeação pouco clara) +**Argparse converte para:** `config_queue` (no dicionário de parâmetros) +**Código procura por:** `config_push_queue` +**Resultado:** O parâmetro é ignorado, usa o valor padrão de `persistent://tg/config/config` +**Impacto:** Afeta todos os 32+ serviços que herdam do AsyncProcessor +**Bloqueia:** Impossibilita o uso de filas de configuração específicas do tenant em implantações multi-tenant +**Solução:** Renomear o parâmetro da CLI para `--config-push-queue` para maior clareza (alteração disruptiva aceitável, já que o recurso está atualmente com defeito) + +### Problema #2: Incompatibilidade no Nome do Parâmetro no Config Service +**CLI define:** `--push-queue` (nomeação ambígua) +**Argparse converte para:** `push_queue` (no dicionário de parâmetros) +**Código procura por:** `config_push_queue` +**Resultado:** O parâmetro é ignorado +**Impacto:** O Config service não pode usar uma fila de push personalizada +**Solução:** Renomear o parâmetro da CLI para `--config-push-queue` para consistência e clareza (alteração disruptiva aceitável) + +### Problema #3: Keyspace do Cassandra Codificado +**Atual:** Keyspace codificado como `"config"`, `"knowledge"`, `"librarian"` em vários serviços +**Resultado:** Impossibilita a personalização do keyspace para implantações multi-tenant +**Impacto:** Serviços Config, cores e librarian +**Bloqueia:** Múltiplos tenants não podem usar keyspaces separados do Cassandra + +### Problema #4: Arquitetura de Gerenciamento de Coleções ✅ CONCLUÍDO +**Anterior:** Coleções armazenadas no keyspace do librarian do Cassandra em uma tabela de coleções separada +**Anterior:** O librarian usava 4 tópicos de gerenciamento de armazenamento codificados para coordenar a criação/exclusão de coleções: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**Problemas (Resolvidos):** + Tópicos codificados não podiam ser personalizados para implantações multi-tenant + Coordenação assíncrona complexa entre o librarian e 4+ serviços de armazenamento + Tabela separada do Cassandra e infraestrutura de gerenciamento + Filas de requisição/resposta não persistentes para operações críticas +**Solução Implementada:** Migrou as coleções para o armazenamento do serviço de configuração, usa push de configuração para distribuição +**Status:** Todos os backends de armazenamento migrados para o padrão `CollectionConfigHandler` + +## Solução + +Esta especificação aborda os problemas #1, #2, #3 e #4. + +### Parte 1: Corrigir Incompatibilidades no Nome do Parâmetro + +#### Alteração 1: Classe Base AsyncProcessor - Renomear Parâmetro da CLI +**Arquivo:** `trustgraph-base/trustgraph/base/async_processor.py` +**Linha:** 260-264 + +**Atual:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**Corrigido:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**Justificativa:** +Nomenclatura mais clara e explícita +Coincide com o nome da variável interna `config_push_queue` +Mudança disruptiva aceitável, já que a funcionalidade está atualmente inativa +Não é necessária nenhuma alteração no código em params.get() - ele já procura pelo nome correto + +#### Mudança 2: Serviço de Configuração - Renomear Parâmetro da CLI +**Arquivo:** `trustgraph-flow/trustgraph/config/service/service.py` +**Linha:** 276-279 + +**Atual:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Corrigido:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Justificativa:** +Nomes mais claros - "config-push-queue" é mais explícito do que apenas "push-queue". +Compatível com o nome da variável interna `config_push_queue`. +Consistente com o parâmetro `--config-push-queue` do AsyncProcessor. +Mudança disruptiva aceitável, já que o recurso está atualmente inativo. +Nenhuma alteração de código necessária em params.get() - ele já procura pelo nome correto. + +### Parte 2: Adicionar Parametrização do Keyspace do Cassandra + +#### Mudança 3: Adicionar Parâmetro de Keyspace ao Módulo cassandra_config +**Arquivo:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**Adicionar argumento de linha de comando** (na função `add_cassandra_args()`): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**Adicionar suporte para variáveis de ambiente** (na função `resolve_cassandra_config()`): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**Atualizar o valor de retorno** de `resolve_cassandra_config()`: +Atualmente retorna: `(hosts, username, password)` +Alterar para retornar: `(hosts, username, password, keyspace)` + +**Justificativa:** +Consistente com o padrão de configuração existente do Cassandra +Disponível para todos os serviços via `add_cassandra_args()` +Suporta configuração via linha de comando e variáveis de ambiente + +#### Mudança 4: Serviço de Configuração - Usar Keyspace Parametrizados +**Arquivo:** `trustgraph-flow/trustgraph/config/service/service.py` + +**Linha 30** - Remover o keyspace codificado: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**Linhas 69-73** - Atualização da resolução da configuração do Cassandra: + +**Atual:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**Corrigido:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**Justificativa:** +Mantém a compatibilidade com versões anteriores, utilizando "config" como padrão. +Permite a substituição através de `--cassandra-keyspace` ou `CASSANDRA_KEYSPACE`. + +#### Mudança 5: Cores/Serviço de Conhecimento - Utilizar Chaves de Espaço de Chaves Parametrizadas +**Arquivo:** `trustgraph-flow/trustgraph/cores/service.py` + +**Linha 37** - Remover o espaço de chaves codificado: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**Atualização da resolução de configuração do Cassandra** (localização semelhante ao serviço de configuração): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### Mudança 6: Serviço de Bibliotecário - Use Chaves de Espaço de Chaves Parametrizadas +**Arquivo:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Linha 51** - Remova a chave de espaço de chaves codificada: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**Atualização da resolução de configuração do Cassandra** (localização semelhante ao serviço de configuração): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### Parte 3: Migrar o Gerenciamento de Coleções para o Serviço de Configuração + +#### Visão Geral +Migrar as coleções do keyspace do Cassandra librarian para o armazenamento do serviço de configuração. Isso elimina os tópicos de gerenciamento de armazenamento codificados e simplifica a arquitetura, utilizando o mecanismo de push de configuração existente para distribuição. + +#### Arquitetura Atual +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### Nova Arquitetura +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### Mudança 7: Gerenciador de Coleções - Usar API do Serviço de Configuração +**Arquivo:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**Remover:** +Uso de `LibraryTableStore` (Linhas 33, 40-41) +Inicialização de produtores de gerenciamento de armazenamento (Linhas 86-140) +Método `on_storage_response` (Linhas 400-430) +Rastreamento de `pending_deletions` (Linhas 57, 90-96 e uso em todo o código) + +**Adicionar:** +Cliente do serviço de configuração para chamadas de API (padrão de solicitação/resposta) + +**Configuração do Cliente:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**Modificar `list_collections` (Linhas 145-180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**Modificar `update_collection` (Linhas 182-312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**Modificar `delete_collection` (Linhas 314-398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**Formato de Metadados de Coleção:** +Armazenado na tabela de configuração como: `class='collections', key='user:collection'` +O valor é uma CollectionMetadata serializada em JSON (sem campos de timestamp) +Campos: `user`, `collection`, `name`, `description`, `tags` +Exemplo: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### Mudança 8: Serviço de Bibliotecário - Remover a Infraestrutura de Gerenciamento de Armazenamento +**Arquivo:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Remover:** +Produtores de gerenciamento de armazenamento (Linhas 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +Consumidor de resposta de armazenamento (Linhas 192-201) +Manipulador `on_storage_response` (Linhas 467-473) + +**Modificar:** +Inicialização do CollectionManager (Linhas 215-224) - remover os parâmetros do produtor de armazenamento + +**Observação:** A API externa de coleções permanece inalterada: +`list-collections` +`update-collection` +`delete-collection` + +#### Mudança 9: Remover a Tabela de Coleções do LibraryTableStore +**Arquivo:** `trustgraph-flow/trustgraph/tables/library.py` + +**Excluir:** +Instrução CREATE da tabela de coleções (Linhas 114-127) +Prepared statements de coleções (Linhas 205-240) +Todos os métodos de coleção (Linhas 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**Justificativa:** +As coleções agora são armazenadas na tabela de configuração +Mudança disruptiva aceitável - nenhuma migração de dados necessária +Simplifica significativamente o serviço de bibliotecário + +#### Mudança 10: Serviços de Armazenamento - Gerenciamento de Coleção Baseado em Configuração ✅ CONCLUÍDO + +**Status:** Todos os 11 backends de armazenamento foram migrados para usar `CollectionConfigHandler`. + +**Serviços Afetados (11 no total):** +Embeddings de documentos: milvus, pinecone, qdrant +Embeddings de grafos: milvus, pinecone, qdrant +Armazenamento de objetos: cassandra +Armazenamento de triplas: cassandra, falkordb, memgraph, neo4j + +**Arquivos:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**Padrão de Implementação (todos os serviços):** + +1. **Registrar o manipulador de configuração em `__init__`:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **Implementar o gerenciador de configuração:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **Inicialize as coleções conhecidas na inicialização:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **Refatore os métodos de tratamento existentes:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **Remover a infraestrutura de gerenciamento de armazenamento:** + Remover a configuração e inicialização de `self.storage_request_consumer` + Remover a configuração de `self.storage_response_producer` + Remover o método de dispatcher de `on_storage_management` + Remover as métricas para o gerenciamento de armazenamento + Remover as importações: `StorageManagementRequest`, `StorageManagementResponse` + +**Considerações Específicas para o Backend:** + +**Bancos de dados vetoriais (Milvus, Pinecone, Qdrant):** Rastrear a lógica `(user, collection)` em `known_collections`, mas pode criar múltiplas coleções de backend por dimensão. Continuar o padrão de criação preguiçosa. As operações de exclusão devem remover todas as variantes de dimensão. + +**Cassandra Objects:** As coleções são propriedades de linha, não estruturas. Rastrear informações no nível do keyspace. + +**Bancos de dados de grafos (Neo4j, Memgraph, FalkorDB):** Consultar nós `CollectionMetadata` na inicialização. Criar/excluir nós de metadados na sincronização. + +**Cassandra Triples:** Usar a API `KnowledgeGraph` para operações de coleção. + +**Pontos-Chave do Design:** + +**Consistência eventual:** Não há mecanismo de solicitação/resposta, o envio de configuração é transmitido. +**Idempotência:** Todas as operações de criação/exclusão devem ser seguras para serem repetidas. +**Tratamento de erros:** Registrar erros, mas não bloquear as atualizações de configuração. +**Autorreparação:** As operações com falha serão repetidas na próxima atualização de configuração. +**Formato da chave da coleção:** `"user:collection"` em `config["collections"]` + +#### Mudança 11: Atualizar o Esquema da Coleção - Remover Timestamps +**Arquivo:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**Modificar CollectionMetadata (Linhas 13-21):** +Remover os campos `created_at` e `updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**Modificar CollectionManagementRequest (linhas 25-47):** +Remover campos de timestamp: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**Justificativa:** +Os carimbos de data e hora não agregam valor para coleções. +O serviço de configuração mantém seu próprio rastreamento de versão. +Simplifica o esquema e reduz o armazenamento. + +#### Benefícios da Migração do Serviço de Configuração + +1. ✅ **Elimina tópicos de gerenciamento de armazenamento codificados** - Resolve o bloqueio multi-inquilino. +2. ✅ **Coordenação mais simples** - Sem espera assíncrona complexa por 4 ou mais respostas de armazenamento. +3. ✅ **Consistência eventual** - Os serviços de armazenamento são atualizados independentemente por meio de push de configuração. +4. ✅ **Melhor confiabilidade** - Push de configuração persistente versus solicitação/resposta não persistente. +5. ✅ **Modelo de configuração unificado** - Coleções tratadas como configuração. +6. ✅ **Reduz a complexidade** - Remove aproximadamente 300 linhas de código de coordenação. +7. ✅ **Pronto para multi-inquilino** - A configuração já suporta o isolamento de inquilinos por meio de keyspace. +8. ✅ **Rastreamento de versão** - O mecanismo de versão do serviço de configuração fornece um histórico de auditoria. + +## Notas de Implementação + +### Compatibilidade com versões anteriores + +**Alterações de parâmetros:** +As alterações de nome dos parâmetros da CLI são alterações disruptivas, mas aceitáveis (o recurso atualmente não está funcional). +Os serviços funcionam sem parâmetros (use os padrões). +Keyspaces padrão preservados: "config", "knowledge", "librarian". +Fila padrão: `persistent://tg/config/config` + +**Gerenciamento de coleções:** +**Alteração disruptiva:** A tabela de coleções foi removida do keyspace librarian. +**Nenhuma migração de dados fornecida** - aceitável para esta fase. +A API de coleção externa não foi alterada (operações de listagem, atualização e exclusão). +O formato de metadados da coleção foi simplificado (os carimbos de data e hora foram removidos). + +### Requisitos de teste + +**Teste de parâmetros:** +1. Verificar se o parâmetro `--config-push-queue` funciona no serviço graph-embeddings. +2. Verificar se o parâmetro `--config-push-queue` funciona no serviço text-completion. +3. Verificar se o parâmetro `--config-push-queue` funciona no serviço de configuração. +4. Verificar se o parâmetro `--cassandra-keyspace` funciona para o serviço de configuração. +5. Verificar se o parâmetro `--cassandra-keyspace` funciona para o serviço cores. +6. Verificar se o parâmetro `--cassandra-keyspace` funciona para o serviço librarian. +7. Verificar se os serviços funcionam sem parâmetros (usa os padrões). +8. Verificar a implantação multi-inquilino com nomes de fila e keyspace personalizados. + +**Teste de gerenciamento de coleções:** +9. Verificar a operação `list-collections` por meio do serviço de configuração. +10. Verificar se `update-collection` cria/atualiza na tabela de configuração. +11. Verificar se `delete-collection` remove da tabela de configuração. +12. Verificar se o push de configuração é acionado em atualizações de coleção. +13. Verificar se a filtragem de tags funciona com armazenamento baseado em configuração. +14. Verificar se as operações de coleção funcionam sem campos de carimbo de data e hora. + +### Exemplo de implantação multi-inquilino +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## Análise de Impacto + +### Serviços Afetados pela Alteração 1-2 (Renomeação de Parâmetro da CLI) +Todos os serviços que herdam de AsyncProcessor ou FlowProcessor: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (todos os provedores) +extract-* (todos os extractors) +query-* (todos os serviços de consulta) +retrieval-* (todos os serviços RAG) +storage-* (todos os serviços de armazenamento) +E mais 20 serviços + +### Serviços Afetados pelas Alterações 3-6 (Keyspace do Cassandra) +config-service +cores-service +librarian-service + +### Serviços Afetados pelas Alterações 7-11 (Gerenciamento de Coleções) + +**Alterações Imediatas:** +librarian-service (collection_manager.py, service.py) +tables/library.py (remoção da tabela de coleções) +schema/services/collection.py (remoção do timestamp) + +**Alterações Concluídas (Alteração 10):** ✅ +Todos os serviços de armazenamento (11 no total) - migrados para o push de configuração para atualizações de coleções via `CollectionConfigHandler` +Esquema de gerenciamento de armazenamento removido de `storage.py` + +## Considerações Futuras + +### Modelo de Keyspace por Usuário + +Alguns serviços usam **keyspaces por usuário** dinamicamente, onde cada usuário recebe seu próprio keyspace do Cassandra: + +**Serviços com keyspaces por usuário:** +1. **Triples Query Service** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + Usa `keyspace=query.user` +2. **Objects Query Service** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + Usa `keyspace=self.sanitize_name(user)` +3. **KnowledgeGraph Direct Access** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + Parâmetro padrão `keyspace="trustgraph"` + +**Status:** Estes **não são modificados** nesta especificação. + +**Revisão Futura Necessária:** +Avaliar se o modelo de keyspace por usuário cria problemas de isolamento de locatários +Considerar se as implementações multi-locatário precisam de padrões de prefixo de keyspace (por exemplo, `tenant_a_user1`) +Revisar para possíveis colisões de ID de usuário entre locatários +Avaliar se um keyspace compartilhado único por locatário com isolamento de linha baseado em usuário é preferível + +**Observação:** Isso não impede a implementação multi-locatário atual, mas deve ser revisado antes das implementações multi-locatário de produção. + +## Fases de Implementação + +### Fase 1: Correções de Parâmetros (Alterações 1-6) +Corrigir a nomenclatura do parâmetro `--config-push-queue` +Adicionar suporte ao parâmetro `--cassandra-keyspace` +**Resultado:** Configuração de fila e keyspace multi-locatário habilitada + +### Fase 2: Migração do Gerenciamento de Coleções (Alterações 7-9, 11) +Migrar o armazenamento de coleções para o serviço de configuração +Remover a tabela de coleções do librarian +Atualizar o esquema de coleção (remover timestamps) +**Resultado:** Elimina tópicos de gerenciamento de armazenamento codificados, simplifica o librarian + +### Fase 3: Atualizações do Serviço de Armazenamento (Alteração 10) ✅ CONCLUÍDA +Atualizados todos os serviços de armazenamento para usar o push de configuração para coleções via `CollectionConfigHandler` +Removida a infraestrutura de solicitação/resposta de gerenciamento de armazenamento +Removidas as definições de esquema legadas +**Resultado:** Gerenciamento de coleções baseado em configuração completo alcançado + +## Referências +GitHub Issue: https://github.com/trustgraph-ai/trustgraph/issues/582 +Arquivos Relacionados: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.ru.md b/docs/tech-specs/multi-tenant-support.ru.md new file mode 100644 index 00000000..c8f9de8d --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.ru.md @@ -0,0 +1,780 @@ +--- +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. + +## Обзор + +Обеспечьте поддержку многопользовательской среды, устранив несоответствия в именах параметров, которые препятствуют настройке очередей, и добавив параметризацию пространства ключей Cassandra. + +## Контекст архитектуры + +### Разрешение очередей на основе потоков + +Система TrustGraph использует **архитектуру на основе потоков** для динамического разрешения очередей, что изначально поддерживает многопользовательскую среду: + +**Определения потоков** хранятся в Cassandra и указывают имена очередей через определения интерфейсов. +**Имена очередей используют шаблоны** с переменными `{id}`, которые заменяются идентификаторами экземпляров потоков. +**Сервисы динамически разрешают очереди**, получая конфигурации потоков в момент запроса. +**Каждый пользователь может иметь уникальные потоки** с разными именами очередей, что обеспечивает изоляцию. + +Пример определения интерфейса потока: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +Когда арендатор A запускает поток `tenant-a-prod`, а арендатор B запускает поток `tenant-b-prod`, они автоматически получают изолированные очереди: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**Сервисы, правильно разработанные для многоарендности:** +✅ **Knowledge Management (основные компоненты)** - Динамически определяет очереди из конфигурации потока, передаваемой в запросах + +**Сервисы, требующие исправления:** +🔴 **Config Service** - Несоответствие имен параметров препятствует настройке очереди +🔴 **Librarian Service** - Жестко заданные темы управления хранилищем (описано ниже) +🔴 **Все сервисы** - Невозможно настроить пространство ключей Cassandra + +## Описание проблемы + +### Проблема #1: Несоответствие имен параметров в AsyncProcessor +**CLI определяет:** `--config-queue` (неясное наименование) +**Argparse преобразует в:** `config_queue` (в словаре параметров) +**Код ищет:** `config_push_queue` +**Результат:** Параметр игнорируется, используется значение по умолчанию `persistent://tg/config/config` +**Влияние:** Затрагивает все 32+ сервиса, наследующие от AsyncProcessor +**Препятствует:** Многоарендные развертывания не могут использовать очереди, специфичные для арендатора +**Решение:** Переименовать параметр CLI в `--config-push-queue` для ясности (разрыв обратной совместимости допустим, так как функция в настоящее время не работает) + +### Проблема #2: Несоответствие имен параметров в Config Service +**CLI определяет:** `--push-queue` (двусмысленное наименование) +**Argparse преобразует в:** `push_queue` (в словаре параметров) +**Код ищет:** `config_push_queue` +**Результат:** Параметр игнорируется +**Влияние:** Сервис Config не может использовать пользовательскую очередь отправки +**Решение:** Переименовать параметр CLI в `--config-push-queue` для согласованности и ясности (разрыв обратной совместимости допустим) + +### Проблема #3: Жестко заданное пространство ключей Cassandra +**Текущее состояние:** Пространство ключей жестко задано как `"config"`, `"knowledge"`, `"librarian"` в различных сервисах +**Результат:** Невозможно настроить пространство ключей для многоарендных развертываний +**Влияние:** Сервисы Config, основные компоненты и Librarian +**Препятствует:** Несколько арендаторов не могут использовать отдельные пространства ключей Cassandra + +### Проблема #4: Архитектура управления коллекциями ✅ ВЫПОЛНЕНО +**Предыдущее состояние:** Коллекции хранились в пространстве ключей Cassandra Librarian через отдельную таблицу коллекций +**Предыдущее состояние:** Librarian использовал 4 жестко заданные темы управления хранилищем для координации создания/удаления коллекций: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**Проблемы (решены):** + Жестко заданные темы не могли быть настроены для многоарендных развертываний + Сложная асинхронная координация между Librarian и 4+ сервисами хранения + Отдельная таблица Cassandra и инфраструктура управления + Непостоянные очереди запросов/ответов для критических операций +**Решение реализовано:** Коллекции были перенесены в хранилище сервиса Config, используется отправка Config для распространения +**Статус:** Все хранилища были перенесены на шаблон `CollectionConfigHandler` + +## Решение + +Эта спецификация решает проблемы #1, #2, #3 и #4. + +### Часть 1: Исправление несоответствий имен параметров + +#### Изменение 1: Базовый класс AsyncProcessor - Переименование параметра CLI +**Файл:** `trustgraph-base/trustgraph/base/async_processor.py` +**Строка:** 260-264 + +**Текущее состояние:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**Исправлено:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**Обоснование:** +Более понятное и явное наименование +Соответствует внутреннему имени переменной `config_push_queue` +Изменение, нарушающее обратную совместимость, допустимо, поскольку функция в настоящее время не функционирует +Не требуется изменение кода в params.get() - он уже ищет правильное имя + +#### Изменение 2: Сервис конфигурации - Переименование параметра командной строки +**Файл:** `trustgraph-flow/trustgraph/config/service/service.py` +**Строка:** 276-279 + +**Текущее:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Исправлено:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Обоснование:** +Более понятное наименование - "config-push-queue" более явно, чем просто "push-queue". +Соответствует внутреннему имени переменной `config_push_queue`. +Соответствует параметру `--config-push-queue` класса AsyncProcessor. +Изменение, нарушающее обратную совместимость, допустимо, поскольку функция в настоящее время не работает. +Не требуется изменение кода в params.get() - он уже ищет правильное имя. + +### Часть 2: Добавление параметризации пространства ключей Cassandra + +#### Изменение 3: Добавление параметра пространства ключей в модуль cassandra_config +**Файл:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**Добавление аргумента командной строки** (в функции `add_cassandra_args()`): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**Добавить поддержку переменных окружения** (в функции `resolve_cassandra_config()`): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**Обновить возвращаемое значение** `resolve_cassandra_config()`: +В настоящее время возвращает: `(hosts, username, password)` +Изменить, чтобы возвращалось: `(hosts, username, password, keyspace)` + +**Обоснование:** +Соответствует существующей схеме конфигурации Cassandra +Доступно всем сервисам через `add_cassandra_args()` +Поддерживает конфигурацию как через командную строку, так и через переменные окружения + +#### Изменение 4: Сервис конфигурации - Использование параметризованных пространств ключей +**Файл:** `trustgraph-flow/trustgraph/config/service/service.py` + +**Строка 30** - Удалить жестко закодированное пространство ключей: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**Строки 69-73** - Обновление разрешения конфигурации Cassandra: + +**Текущая версия:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**Исправлено:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**Обоснование:** +Обеспечивает обратную совместимость с "config" в качестве значения по умолчанию. +Позволяет переопределить значение с помощью `--cassandra-keyspace` или `CASSANDRA_KEYSPACE`. + +#### Изменение 5: Основные компоненты/Сервис знаний - Использование параметризованных пространств ключей. +**Файл:** `trustgraph-flow/trustgraph/cores/service.py` + +**Строка 37** - Удалить жестко закодированное пространство ключей: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**Обновление разрешения конфигурации Cassandra** (в том же месте, что и служба конфигурации): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### Изменение 6: Сервис библиотекаря - Использование параметризованных пространств ключей. +**Файл:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Строка 51** - Удалить жестко закодированное пространство ключей: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**Обновление разрешения конфигурации Cassandra** (в том же месте, что и служба конфигурации): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### Часть 3: Перенос управления коллекциями в службу конфигураций + +#### Обзор +Перенесите коллекции из пространства ключей Cassandra librarian в хранилище службы конфигураций. Это устраняет жестко закодированные темы управления хранилищем и упрощает архитектуру, используя существующий механизм распространения конфигураций. + +#### Текущая архитектура +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### Новая архитектура +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### Изменение 7: Менеджер коллекций - Использование API сервиса конфигурации +**Файл:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**Удалить:** +Использование `LibraryTableStore` (строки 33, 40-41) +Инициализация производителей управления хранилищем (строки 86-140) +Метод `on_storage_response` (строки 400-430) +Отслеживание `pending_deletions` (строки 57, 90-96 и использование во всем коде) + +**Добавить:** +Клиент сервиса конфигурации для вызовов API (шаблон запрос/ответ) + +**Настройка клиента конфигурации:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**Изменить `list_collections` (строки 145-180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**Изменить `update_collection` (строки 182-312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**Изменить `delete_collection` (строки 314-398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**Формат метаданных коллекции:** +Хранится в таблице конфигурации как: `class='collections', key='user:collection'` +Значение является JSON-сериализованным объектом CollectionMetadata (без полей времени). +Поля: `user`, `collection`, `name`, `description`, `tags` +Пример: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### Изменение 8: Сервис Librarian - Удаление инфраструктуры управления хранилищем +**Файл:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Удалить:** +Модули-производители управления хранилищем (строки 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +Потребитель ответов хранилища (строки 192-201) +Обработчик `on_storage_response` (строки 467-473) + +**Изменить:** +Инициализация CollectionManager (строки 215-224) - удалить параметры модуля-производителя хранилища + +**Примечание:** Внешний API для коллекций остается неизменным: +`list-collections` +`update-collection` +`delete-collection` + +#### Изменение 9: Удаление таблицы Collections из LibraryTableStore +**Файл:** `trustgraph-flow/trustgraph/tables/library.py` + +**Удалить:** +Оператор CREATE для таблицы Collections (строки 114-127) +Подготовленные операторы для Collections (строки 205-240) +Все методы для работы с коллекциями (строки 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**Обоснование:** +Коллекции теперь хранятся в таблице конфигурации. +Изменение, требующее обновления, приемлемо - миграция данных не требуется. +Значительно упрощает сервис Librarian. + +#### Изменение 10: Сервисы хранения - Управление коллекциями на основе конфигурации ✅ ВЫПОЛНЕНО + +**Статус:** Все 11 хранилищ были перенесены на использование `CollectionConfigHandler`. + +**Затронутые сервисы (всего 11):** +Векторные представления документов: milvus, pinecone, qdrant +Векторные представления графов: milvus, pinecone, qdrant +Объектное хранилище: cassandra +Хранилище троек: cassandra, falkordb, memgraph, neo4j + +**Файлы:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**Шаблон реализации (для всех сервисов):** + +1. **Зарегистрировать обработчик конфигурации в `__init__`:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **Реализовать обработчик конфигурации:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **Инициализация известных коллекций при запуске:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **Рефакторинг существующих методов обработчиков:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **Удаление инфраструктуры управления хранилищем:** + Удалить настройку и запуск `self.storage_request_consumer` + Удалить настройку `self.storage_response_producer` + Удалить метод диспетчера `on_storage_management` + Удалить метрики для управления хранилищем + Удалить импорты: `StorageManagementRequest`, `StorageManagementResponse` + +**Особенности, специфичные для бэкенда:** + +**Векторные хранилища (Milvus, Pinecone, Qdrant):** Отслеживать логическую `(user, collection)` в `known_collections`, но может создавать несколько бэкенд-коллекций для каждой размерности. Продолжить использование ленивой схемы создания. Операции удаления должны удалять все варианты размерностей. + +**Объекты Cassandra:** Коллекции являются свойствами строк, а не структурами. Отслеживать информацию на уровне пространства ключей. + +**Графовые хранилища (Neo4j, Memgraph, FalkorDB):** Запрашивать узлы `CollectionMetadata` при запуске. Создавать/удалять метаданные узлов при синхронизации. + +**Тройки Cassandra:** Использовать API `KnowledgeGraph` для операций с коллекциями. + +**Основные принципы проектирования:** + +**Итоговая согласованность:** Отсутствует механизм запрос/ответ, конфигурация распространяется широковещанием. +**Идемпотентность:** Все операции создания/удаления должны быть безопасными для повторной попытки. +**Обработка ошибок:** Регистрировать ошибки, но не блокировать обновления конфигурации. +**Самовосстановление:** Неудачные операции будут повторены при следующем распространении конфигурации. +**Формат ключа коллекции:** `"user:collection"` в `config["collections"]` + +#### Изменение 11: Обновление схемы коллекции - Удаление временных меток +**Файл:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**Изменить CollectionMetadata (строки 13-21):** +Удалить поля `created_at` и `updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**Изменить класс CollectionManagementRequest (строки 25-47):** +Удалить поля временной метки: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**Обоснование:** +Временные метки не добавляют ценности для коллекций. +Сервис конфигурации самостоятельно отслеживает версии. +Упрощает схему и уменьшает объем хранения. + +#### Преимущества миграции на сервис конфигурации + +1. ✅ **Устраняет жестко закодированные темы управления хранилищем** - Решает проблему многопользовательской среды. +2. ✅ **Более простая координация** - Нет сложного асинхронного ожидания ответов от 4+ хранилищ. +3. ✅ **В конечном итоге согласованность** - Сервисы хранения обновляются независимо с помощью push-конфигурации. +4. ✅ **Более высокая надежность** - Постоянная push-конфигурация против неперсистентного запроса/ответа. +5. ✅ **Унифицированная модель конфигурации** - Коллекции рассматриваются как конфигурация. +6. ✅ **Уменьшает сложность** - Удаляет около 300 строк кода для координации. +7. ✅ **Готовность к многопользовательской среде** - Конфигурация уже поддерживает изоляцию пользователей с помощью пространств ключей. +8. ✅ **Отслеживание версий** - Механизм версионирования сервиса конфигурации обеспечивает аудит. + +## Замечания по реализации + +### Обратная совместимость + +**Изменения параметров:** +Переименование параметров командной строки является серьезным изменением, но допустимо (функция в настоящее время не работает). +Сервисы работают без параметров (используются значения по умолчанию). +Значения по умолчанию для пространств ключей сохранены: "config", "knowledge", "librarian". +Значение по умолчанию для очереди: `persistent://tg/config/config` + +**Управление коллекциями:** +**Серьезное изменение:** Таблица коллекций удалена из пространства ключей librarian. +**Миграция данных не предусмотрена** - приемлемо для этой фазы. +Внешний API для коллекций не изменен (операции list/update/delete). +Формат метаданных коллекций упрощен (временные метки удалены). + +### Требования к тестированию + +**Тестирование параметров:** +1. Проверить, работает ли параметр `--config-push-queue` для сервиса graph-embeddings. +2. Проверить, работает ли параметр `--config-push-queue` для сервиса text-completion. +3. Проверить, работает ли параметр `--config-push-queue` для сервиса конфигурации. +4. Проверить, работает ли параметр `--cassandra-keyspace` для сервиса конфигурации. +5. Проверить, работает ли параметр `--cassandra-keyspace` для сервиса cores. +6. Проверить, работает ли параметр `--cassandra-keyspace` для сервиса librarian. +7. Проверить, работают ли сервисы без параметров (используются значения по умолчанию). +8. Проверить развертывание в многопользовательской среде с использованием пользовательских имен очередей и пространств ключей. + +**Тестирование управления коллекциями:** +9. Проверить операцию `list-collections` через сервис конфигурации. +10. Проверить, создает ли `update-collection` записи/обновления в таблице конфигурации. +11. Проверить, удаляет ли `delete-collection` записи из таблицы конфигурации. +12. Проверить, запускается ли push-конфигурации при обновлениях коллекций. +13. Проверить, работает ли фильтрация по тегам с использованием хранилища на основе конфигурации. +14. Проверить, работают ли операции с коллекциями без полей временных меток. + +### Пример развертывания в многопользовательской среде +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## Анализ влияния + +### Сервисы, затронутые изменением 1-2 (Переименование параметра CLI) +Все сервисы, наследующие AsyncProcessor или FlowProcessor: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (все провайдеры) +extract-* (все экстракторы) +query-* (все сервисы запросов) +retrieval-* (все сервисы RAG) +storage-* (все сервисы хранения) +И еще 20+ сервисов + +### Сервисы, затронутые изменениями 3-6 (Keyspace Cassandra) +config-service +cores-service +librarian-service + +### Сервисы, затронутые изменениями 7-11 (Управление коллекциями) + +**Немедленные изменения:** +librarian-service (collection_manager.py, service.py) +tables/library.py (удаление таблицы collections) +schema/services/collection.py (удаление метки времени) + +**Выполненные изменения (изменение 10):** ✅ +Все сервисы хранения (всего 11) - перенесены на push-конфигурацию для обновлений коллекций через `CollectionConfigHandler` +Схема управления хранилищем удалена из `storage.py` + +## Будущие соображения + +### Модель keyspace на уровне пользователя + +Некоторые сервисы динамически используют **keyspace на уровне пользователя**, когда каждый пользователь получает свой собственный keyspace Cassandra: + +**Сервисы с keyspace на уровне пользователя:** +1. **Сервис запросов Triple** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + Использует `keyspace=query.user` +2. **Сервис запросов объектов** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + Использует `keyspace=self.sanitize_name(user)` +3. **Прямой доступ к графу знаний** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + Параметр по умолчанию `keyspace="trustgraph"` + +**Статус:** Эти параметры **не изменяются** в этой спецификации. + +**Требуется дальнейший анализ:** +Оценить, создает ли модель keyspace на уровне пользователя проблемы изоляции арендаторов +Рассмотреть, нужны ли многопользовательским развертываниям префиксы keyspace (например, `tenant_a_user1`) +Проверить на потенциальные конфликты идентификаторов пользователей между арендаторами +Оценить, является ли единый общий keyspace на арендатора с изоляцией строк на уровне пользователя более предпочтительным + +**Примечание:** Это не блокирует текущую многопользовательскую реализацию, но должно быть рассмотрено перед производственными многопользовательскими развертываниями. + +## Этапы реализации + +### Этап 1: Исправление параметров (изменения 1-6) +Исправить именование параметра `--config-push-queue` +Добавить поддержку параметра `--cassandra-keyspace` +**Результат:** Многопользовательская очередь и конфигурация keyspace включены + +### Этап 2: Миграция управления коллекциями (изменения 7-9, 11) +Перенести хранение коллекций в сервис конфигурации +Удалить таблицу collections из librarian +Обновить схему коллекций (удалить метки времени) +**Результат:** Устраняет жестко закодированные темы управления хранилищем, упрощает librarian + +### Этап 3: Обновления сервисов хранения (изменение 10) ✅ ВЫПОЛНЕНО +Обновлены все сервисы хранения для использования push-конфигурации для коллекций через `CollectionConfigHandler` +Удалена инфраструктура запросов/ответов управления хранилищем +Удалены устаревшие определения схемы +**Результат:** Достигнуто полное управление коллекциями на основе конфигурации + +## Ссылки +GitHub Issue: https://github.com/trustgraph-ai/trustgraph/issues/582 +Связанные файлы: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.sw.md b/docs/tech-specs/multi-tenant-support.sw.md new file mode 100644 index 00000000..d6eb96ca --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.sw.md @@ -0,0 +1,780 @@ +--- +layout: default +title: "Maelezo ya Kiufundi: Usaidizi wa Matumizi Mbalimbali (Multi-Tenant)" +parent: "Swahili (Beta)" +--- + +# Maelezo ya Kiufundi: Usaidizi wa Matumizi Mbalimbali (Multi-Tenant) + +> **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 + +Wezesha matumizi mbalimbali kwa kurekebisha kutofautiana kwa majina ya vigezo ambavyo huuzuia utengenezaji wa folyo (queue) na kwa kuongeza utaratibu wa kuweka vigezo kwa Cassandra. + +## Mfumo wa Uendeshaji + +### Utatuzi wa Folyo Kulingana na Mchakato + +Mfumo wa TrustGraph hutumia **mfumo wa usanifu unaozingatia mchakato** (flow-based architecture) kwa utatuzi wa folyo, ambao kwa asili unao na uwezo wa kuunga mkono matumizi mbalimbali: + +**Maelezo ya Mchakato** (Flow Definitions) huhifadhiwa katika Cassandra na yanaeleza majina ya folyo kupitia maelezo ya kiungo (interface). +**Majina ya folyo hutumia vipengele** (templates) na vigezo vya `{id}` ambavyo hubadilishwa na kitambulisho cha mfano wa mchakato. +**Huduma zinatatua folyo kwa njia ya moja kwa moja** kwa kutafuta mipangilio ya mchakato wakati wa ombi. +**Kila mtumiaji anaweza kuwa na mchakato wake wa kipekee** na majina tofauti ya folyo, ambayo hutoa upekee. + +Kielelezo cha maelezo ya kiungo ya mchakato: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +Wakati mwendeshaji A anaanza mtiririko `tenant-a-prod` na mwendeshaji B anaanza mtiririko `tenant-b-prod`, wanapata moja kwa moja folyo zisizo na muunganisho: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**Huduma zilizoundwa vizuri kwa utumiaji wa wateja wengi:** +✅ **Usimamizi wa Maarifa (msingi)** - Inatatua moja kwa moja folyo kutoka usanidi wa mtiririko uliopitishwa katika ombi. + +**Huduma zinazohitaji marekebisho:** +🔴 **Huduma ya Usanidi** - Utangamano wa jina la parameter unazuia utengenezaji wa folyo +🔴 **Huduma ya Maktaba** - Mada ya uhifadhi iliyopangwa (iliyozungumzwa hapa chini) +🔴 **Huduma Zote** - Haiwezi kubadilisha nafasi ya Cassandra + +## Taarifa ya Tatizo + +### Tatizo #1: Utangamano wa Jina la Parameter katika AsyncProcessor +**CLI inafafanua:** `--config-queue` (jina lisilo wazi) +**Argparse inabadilisha kuwa:** `config_queue` (katika kamusi ya params) +**Msimu unatafuta:** `config_push_queue` +**Matokeo:** Parameter inakwama, inarudisha `persistent://tg/config/config` +**Athari:** Huathiri huduma zote 32+ zinazorithi kutoka kwa AsyncProcessor +**Inazuia:** Uwekaji wa wateja wengi hauna uwezo wa kutumia folyo maalum za mteja +**Suluhisho:** Badilisha parameter ya CLI kuwa `--config-push-queue` kwa uwazi (mabadiliko ya kuvunja yanakubalika kwani kipengele hicho kwa sasa kimevunjika) + +### Tatizo #2: Utangamano wa Jina la Parameter katika Huduma ya Usanidi +**CLI inafafanua:** `--push-queue` (jina lisilo wazi) +**Argparse inabadilisha kuwa:** `push_queue` (katika kamusi ya params) +**Msimu unatafuta:** `config_push_queue` +**Matokeo:** Parameter inakwama +**Athari:** Huduma ya usanidi haiwezi kutumia folyo ya kushinikiza maalum +**Suluhisho:** Badilisha parameter ya CLI kuwa `--config-push-queue` kwa utangamano na uwazi (mabadiliko ya kuvunja yanakubalika) + +### Tatizo #3: Nafasi ya Cassandra Iliyopangwa +**Sasa:** Nafasi ya Cassandra imepangwa kama `"config"`, `"knowledge"`, `"librarian"` katika huduma mbalimbali +**Matokeo:** Haiwezi kubadilisha nafasi ya utumiaji wa wateja wengi +**Athari:** Huduma za usanidi, msingi, na maktaba +**Inazuia:** Wateja wengi hawawezi kutumia nafasi tofauti za Cassandra + +### Tatizo #4: Usanidi wa Usimamizi wa Mkusanyiko ✅ IMEKAMILIKA +**Hapo awali:** Mkusanyiko ulihifadhiwa katika nafasi ya maktaba ya Cassandra kupitia meza tofauti ya mkusanyiko +**Hapo awali:** Maktaba ilitumia mada 4 zilizopangwa za usimamizi wa uhifadhi ili kuratibu uundaji/ufutaji wa mkusanyiko: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**Matatizo (Yaliyoshughulikiwa):** + Mada iliyopangwa haikuweza kubadilishwa kwa utumiaji wa wateja wengi + Uratibu wa async tata kati ya maktaba na huduma 4+ za uhifadhi + Meza tofauti ya Cassandra na miundombinu ya usimamizi + Folyo za ombi/jibu zisizo na uhai kwa operesheni muhimu +**Suluhisho Liliofanywa:** Kuhamishia mkusanyiko kwenye uhifadhi wa huduma ya usanidi, tumia kushinikiza usanidi kwa usambazaji +**Hali:** Uhifadhi wote wa nyuma umehamishwa kwenye mtindo wa `CollectionConfigHandler` + +## Suluhisho + +Hii inahusu Matatizo #1, #2, #3, na #4. + +### Sehemu ya 1: Marekebisho ya Utangamano wa Jina la Parameter + +#### Mabadiliko ya 1: Darasa la Msingi la AsyncProcessor - Badilisha Jina la Parameter ya CLI +**Faili:** `trustgraph-base/trustgraph/base/async_processor.py` +**Laini:** 260-264 + +**Sasa:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**Imara:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**Sababu:** +Majina wazi na ya dhahiri zaidi +Inafanana na jina la ndani la `config_push_queue` +Mabadiliko yanayoweza kusababisha migogoro yanafaa kwani kipengele hivi sasa hakifanyi kazi +Hakuna mabadiliko ya msimbo yanayohitajika katika params.get() - tayari inatafuta jina sahihi + +#### Mabadiliko ya 2: Huduma ya Usanidi - Badilisha Jina la Paramu ya CLI +**Faili:** `trustgraph-flow/trustgraph/config/service/service.py` +**Laini:** 276-279 + +**Sasa:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Imara:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Sababu:** +Majina wazi zaidi - "config-push-queue" yanaeleza zaidi kuliko "push-queue" tu. +Inalingana na jina la ndani `config_push_queue`. +Inafanana na parameter ya `--config-push-queue` ya AsyncProcessor. +Mabadiliko yanayoweza kusababisha migogoro yanafaa kwani kipengele hicho kwa sasa hakifanyi kazi. +Hakuna mabadiliko ya msimbo yanayohitajika katika params.get() - tayari inatafuta jina sahihi. + +### Sehemu ya 2: Ongeza Uwekaji wa Vigezo vya Keyspace ya Cassandra + +#### Mabadiliko ya 3: Ongeza Parameter ya Keyspace kwenye Moduli ya cassandra_config +**Faili:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**Ongeza hoja ya CLI** (katika kazi ya `add_cassandra_args()`): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**Ongeza utumiaji wa vigezo vya mazingira** (katika kitendwa `resolve_cassandra_config()`): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**Sasisha thamani ya kurudiwa** ya `resolve_cassandra_config()`: +Hivi sasa inarudisha: `(hosts, username, password)` +Badilisha ili irudishe: `(hosts, username, password, keyspace)` + +**Sababu:** +Inafanana na mtindo uliopo wa usanidi wa Cassandra +Inapatikana kwa huduma zote kupitia `add_cassandra_args()` +Inasaidia usanidi wa CLI na wa vigezo vya mazingira + +#### Mabadiliko ya 4: Huduma ya Usanidi - Tumia Vipengele Vilivyobadilishwa +**Faili:** `trustgraph-flow/trustgraph/config/service/service.py` + +**Laini ya 30** - Ondoa jina la keyspace lililokodishwa: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**Mishale 69-73** - Sasisha utatuzi wa usanidi wa Cassandra: + +**Sasa:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**Imara:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**Sababu:** +Inahifadhi utangamano na "config" kama chaguo-msingi. +Inaruhusu kubadilishwa kupitia `--cassandra-keyspace` au `CASSANDRA_KEYSPACE`. + +#### Mabadiliko ya 5: Huduma za Msingi/Huduma ya Maarifa - Tumia Vipengele vya Kubadilika vya Nafasi ya Kuhifadhia +**Faili:** `trustgraph-flow/trustgraph/cores/service.py` + +**Laini ya 37** - Ondoa jina la nafasi ya kuhifadhia lililopangwa: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**Sasisha utatuzi wa usanidi wa Cassandra** (katika eneo sawa kama huduma ya usanidi): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### Mabadiliko ya 6: Huduma ya Maktaba - Tumia Vipengele Vilivyobadilika +**Faili:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Laini ya 51** - Ondoa jina la eneo la kuhifadhi data lililopangwa: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**Sasisha utatuzi wa usanidi wa Cassandra** (katika eneo sawa na huduma ya usanidi): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### Sehemu ya 3: Hamisha Usimamizi wa Mkusanyiko hadi Huduma ya Usanidi + +#### Muhtasari +Hamisha mkusanyiko kutoka kwa nafasi ya kuhifadhi "Cassandra librarian" hadi uhifadhi wa huduma ya usanidi. Hii huondoa mada za usimamizi wa uhifadhi zilizopangwa mapema na hurahisisha usanifu kwa kutumia mfumo uliopo wa usambazaji wa usanidi. + +#### Usanifu wa Sasa +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### Usanifu Mpya +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### Mabadiliko ya 7: Msimamizi wa Mkusanyiko - Tumia API ya Huduma ya Usanidi +**Faili:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**Ondoa:** +Matumizi ya `LibraryTableStore` (Mistari 33, 40-41) +Uanzishaji wa watengenezaji wa usimamizi wa hifadhi (Mistari 86-140) +Njia ya `on_storage_response` (Mistari 400-430) +Ufuatiliaji wa `pending_deletions` (Mistari 57, 90-96, na matumizi katika maeneo mengine) + +**Ongeza:** +Mteja wa huduma ya usanidi kwa simu za API (mfumo wa ombi/jibu) + +**Uwekaji wa Mteja wa Usanidi:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**Badilisha `list_collections` (Mistari 145-180):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**Badilisha `update_collection` (Mistari 182-312):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**Badilisha `delete_collection` (Mistari 314-398):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**Muundo wa Meta Data ya Mkusanyiko:** +Hifadhiwa katika jedwali la usanidi kama: `class='collections', key='user:collection'` +Thamani ni CollectionMetadata iliyopigwa muundo wa JSON (bila mashamba ya wakati) +Mashamba: `user`, `collection`, `name`, `description`, `tags` +Mfano: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### Mabadiliko ya 8: Huduma ya Maktaba - Ondoa Miundombinu ya Usimamizi wa Uhifadhi +**Faili:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Ondoa:** +Wafalme wa usimamizi wa uhifadhi (Mistari 173-190): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +Mfumo wa matumizi ya majibu ya uhifadhi (Mistari 192-201) +Msimamizi `on_storage_response` (Mistari 467-473) + +**Badilisha:** +Uanzishaji wa CollectionManager (Mistari 215-224) - ondoa vigezo vya mtayarishaji wa uhifadhi + +**Kumbuka:** API ya nje ya mkusanyiko inabaki bila kubadilika: +`list-collections` +`update-collection` +`delete-collection` + +#### Mabadiliko ya 9: Ondoa Jedwali la Mkusanyiko kutoka LibraryTableStore +**Faili:** `trustgraph-flow/trustgraph/tables/library.py` + +**Futa:** +Kauli ya kuunda jedwali la Mkusanyiko (Mistari 114-127) +Maneno yaliyotayarishwa ya Mkusanyiko (Mistari 205-240) +Mbinu zote za mkusanyiko (Mistari 578-717): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**Mazingatio:** +Mkusanyiko sasa huhifadhiwa kwenye meza ya usanidi. +Mabadiliko yanayoweza kusababisha migogoro yanayokubalika - hakuna uhamisho wa data unaohitajika. +Inarahisisha huduma ya "librarian" kwa kiasi kikubwa. + +#### Mabadiliko ya 10: Huduma za Uhifadhi - Usimamizi wa Mkusanyiko Kulingana na Usanidi ✅ IMEKAMILIKA + +**Hali:** Vifaa vyote 11 vya uhifadhi vimehamishwa ili kutumia `CollectionConfigHandler`. + +**Huduma Zinazoathirika (jumla ya 11):** +Uingizaji wa hati: milvus, pinecone, qdrant +Uingizaji wa grafu: milvus, pinecone, qdrant +Uhifadhi wa vitu: cassandra +Uhifadhi wa "triples": cassandra, falkordb, memgraph, neo4j + +**Faili:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**Mfumo wa Utendaji (huduma zote):** + +1. **Jisajili "config handler" katika `__init__`:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **Teleza kidhibiti cha usanidi:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **Anzisha kukusanya data inayojulikana wakati wa kuanza:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **Kuboresha mbinu zilizopo za utendaji:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **Ondoa miundomino ya usimamizi wa hifadhi:** + Ondoa usanidi na uanzishaji wa `self.storage_request_consumer` + Ondoa usanidi wa `self.storage_response_producer` + Ondoa njia ya utaratibu wa `on_storage_management` + Ondoa vipimo (metrics) vya usimamizi wa hifadhi + Ondoa uingizaji (imports): `StorageManagementRequest`, `StorageManagementResponse` + +**Mazingatio Maalum ya Seva ya Nyuma (Backend):** + +**Vihifadhi vya data (Vector stores) (Milvus, Pinecone, Qdrant):** Fuatilia `(user, collection)` ya kimantiki katika `known_collections`, lakini inaweza kuunda mkusanyiko mwingi wa seva ya nyuma kwa kila kipimo. Endeleza mtindo wa uundaji wa polepole. Operesheni za kufuta lazima iondoe matoleo yote ya kipimo. + +**Cassandra Objects:** Mikusanyiko ni sifa za mstari, sio muundo. Fuatilia taarifa za kiwango cha keyspace. + +**Vihifadhi vya grafu (Graph stores) (Neo4j, Memgraph, FalkorDB):** Tafuta nodi za `CollectionMetadata` wakati wa kuanza. Unda/futa nodi za metadata wakati wa kusawazisha. + +**Cassandra Triples:** Tumia API ya `KnowledgeGraph` kwa operesheni za mkusanyiko. + +**Mambo Muhimu ya Ubunifu:** + +**Ulinganifu wa muda (Eventual consistency):** Hakuna utaratibu wa ombi/jibu, utaratibu wa kusukuma usanidi hutangazwa +**Ulinganifu (Idempotency):** Operesheni zote za kuunda/kufuta lazima ziwe salama kufanywa tena +**Usimamizi wa makosa (Error handling):** Leta makosa lakini usizuie sasisho za usanidi +**Kujirejesha (Self-healing):** Operesheni ambazo zimefeli zitajaribu tena wakati wa sasisho la usanidi lijayo +**Muundo wa ufunguo wa mkusanyiko (Collection key format):** `"user:collection"` katika `config["collections"]` + +#### Mabadiliko ya 11: Sasisha Mpango wa Mkusaniko - Ondoa Alama za Muda (Timestamps) +**Faili:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**Badilisha CollectionMetadata (Mistari 13-21):** +Ondoa sehemu za `created_at` na `updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**Badilisha `CollectionManagementRequest` (Mistari 25-47):** +Ondoa sehemu za wakati: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**Sababu:** +Wakati (Timestamps) havi faida kwa makusanyo. +Huduma ya usanidi (config) inadhibiti ufuatiliaji wake wa toleo. +Inarahisisha muundo na kupunguza uhifadhi. + +#### Faida za Uhamishaji wa Huduma ya Usanidi + +1. ✅ **Inaondoa masuala ya usimamizi wa uhifadhi yaliyopangwa awali** - Inatatua kizuizi cha wateja wengi. +2. ✅ **Uratibu rahisi zaidi** - Hakuna utaratibu ngumu wa kusubiri majibu kutoka kwa huduma 4+ za uhifadhi. +3. ✅ **Ulinganifu wa muda** - Huduma za uhifadhi husasishwa kwa kujitegemea kupitia utaratibu wa usanidi. +4. ✅ **Uaminifu bora zaidi** - Uratibu wa kudumu wa usanidi dhidi ya ombi/jibu lisilo la kudumu. +5. ✅ **Mfumo wa usanidi uliounganishwa** - Makusanyo yanatibiwa kama usanidi. +6. ✅ **Inapunguza utata** - Inondoa mistari ~300 ya nambari ya uratibu. +7. ✅ **Inafaa kwa wateja wengi** - Usanidi tayari una msaada wa kutenganisha wateja kupitia nafasi. +8. ✅ **Ufuatiliaji wa toleo** - Mfumo wa toleo wa huduma ya usanidi hutoa kumbukumbu ya uhakiki. + +## Maelezo ya Utendaji + +### Utangamano wa Nyuma + +**Mabadiliko ya Vigezo:** +Mabadiliko ya majina ya vigezo vya CLI ni mabadiliko ambayo yanaweza kusababisha matatizo lakini yanapokelewa (kipengele hapo kwa sasa hakifanyi kazi). +Huduma zinafanya kazi bila vigezo (tumia chaguo-msingi). +Nafasi chaguo-msingi zimehifadhiwa: "config", "knowledge", "librarian". +Kichefuchefu chaguo-msingi: `persistent://tg/config/config` + +**Usimamizi wa Makusanyo:** +**Mabadiliko ambayo yanaweza kusababisha matatizo:** Jedwali la makusanyo limeondolewa kutoka kwa nafasi ya "librarian". +**Hakuna uhamishaji wa data unaotolewa** - inakubalika kwa hatua hii. +API ya makusanyo ya nje haijabadilika (operesheni za kuorodhesha/kusasisha/kufuta). +Muundo wa metadata ya makusanyo umeboreshwa (wakati umeondolewa). + +### Mahitaji ya Majaribio + +**Majaribio ya Vigezo:** +1. Thibitisha kwamba kiparamu `--config-push-queue` hufanya kazi kwenye huduma ya "graph-embeddings". +2. Thibitisha kwamba kiparamu `--config-push-queue` hufanya kazi kwenye huduma ya "text-completion". +3. Thibitisha kwamba kiparamu `--config-push-queue` hufanya kazi kwenye huduma ya usanidi. +4. Thibitisha kwamba kiparamu `--cassandra-keyspace` hufanya kazi kwa huduma ya usanidi. +5. Thibitisha kwamba kiparamu `--cassandra-keyspace` hufanya kazi kwa huduma ya "cores". +6. Thibitisha kwamba kiparamu `--cassandra-keyspace` hufanya kazi kwa huduma ya "librarian". +7. Thibitisha kwamba huduma zinafanya kazi bila vigezo (zinatumia chaguo-msingi). +8. Thibitisha uwekaji wa wateja wengi na majina ya kichefuchefu na nafasi maalum. + +**Majaribio ya Usimamizi wa Makusanyo:** +9. Thibitisha operesheni `list-collections` kupitia huduma ya usanidi. +10. Thibitisha kwamba `update-collection` huunda/kusasisha kwenye jedwali la usanidi. +11. Thibitisha kwamba `delete-collection` huondoa kutoka kwenye jedwali la usanidi. +12. Thibitisha kwamba utaratibu wa "config push" huwashwa wakati wa sasisho za makusanyo. +13. Thibitisha kwamba utaratibu wa kuchujwa wa lebo hufanya kazi na uhifadhi unaotegemea usanidi. +14. Thibitisha kwamba operesheni za makusanyo hufanya kazi bila sehemu za wakati. + +### Mfano wa Uwekaji wa Wateja Wengi +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## Uchambuzi wa Athari + +### Huduma Zinazoathiriwa na Mabadiliko 1-2 (Kubadilisha Jina la Paramu ya CLI) +Huduma zote zinazorithi kutoka kwa AsyncProcessor au FlowProcessor: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (wote watoa huduma) +extract-* (wote waangamizi) +query-* (huduma zote za kuulizia) +retrieval-* (huduma zote za RAG) +storage-* (huduma zote za kuhifadhi) +Na huduma zingine 20+ + +### Huduma Zinazoathiriwa na Mabadiliko 3-6 (Nafasi ya Cassandra) +config-service +cores-service +librarian-service + +### Huduma Zinazoathiriwa na Mabadiliko 7-11 (Usimamizi wa Mkusanyiko) + +**Mabadiliko ya Mara Moja:** +librarian-service (collection_manager.py, service.py) +tables/library.py (ondoa meza ya mkusanyiko) +schema/services/collection.py (ondoa alama ya muda) + +**Mabadiliko Yaliyokamilika (Mabadiliko ya 10):** ✅ +Huduma zote za kuhifadhi (jumla ya 11) - zimehamishwa kwa utaratibu wa kusukuma usanidi kwa mkusanyiko kupitia `CollectionConfigHandler` +Mfumo wa usimamizi wa kuhifadhi umeondolewa kutoka `storage.py` + +## Mambo ya Kuzingatia ya Baadaye + +### Mfumo wa Nafasi ya Mtumiaji Kila Mmoja + +Huduma zingine hutumia **nafasi za mtumiaji kila mmoja** kwa njia ya moja kwa moja, ambapo kila mtumiaji hupata nafasi yake mwenyewe ya Cassandra: + +**Huduma zenye nafasi za mtumiaji kila mmoja:** +1. **Huduma ya Uulizia ya Triples** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + Inatumia `keyspace=query.user` +2. **Huduma ya Uulizia ya Vitabu** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + Inatumia `keyspace=self.sanitize_name(user)` +3. **Ufikiaji wa Moja kwa Moja wa KnowledgeGraph** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + Paramu ya chaguo-msingi `keyspace="trustgraph"` + +**Hali:** Hizi **hazibadiliki** katika maelezo haya. + +**Hakikisha Upya wa Baadaye:** +Tathmini ikiwa mfumo wa nafasi ya mtumiaji kila mmoja huunda masuala ya kutenganisha wateja +Fikiria ikiwa usambazaji wa wateja mbalimbali unahitaji muundo wa mbele ya nafasi (k.m., `tenant_a_user1`) +Angalia uwezekano wa migongano ya kitambulisho cha mtumiaji kati ya wateja +Tathmini ikiwa nafasi moja iliyoshirikiwa kwa kila mteja na kutenganisha mstari kwa msingi wa mtumiaji ni bora + +**Kumbuka:** Hii haizuie utekelezaji wa sasa wa wateja mbalimbali lakini inapaswa kukaguliwa kabla ya utekelezaji wa wateja mbalimbali wa uzalishaji. + +## Awamu za Utendaji + +### Awamu ya 1: Marekebisho ya Paramu (Mabadiliko 1-6) +Marekebisho ya jina la paramu `--config-push-queue` +Ongeza msaada wa paramu `--cassandra-keyspace` +**Matokeo:** Mpangilio wa folyo na nafasi ya wateja mbalimbali umeanzishwa + +### Awamu ya 2: Uhamishaji wa Usimamizi wa Mkusanyiko (Mabadiliko 7-9, 11) +Hamisha uhifadhi wa mkusanyiko kwa huduma ya usanidi +Ondoa meza ya mkusanyiko kutoka kwa librarian +Sasisha mfumo wa mkusanyiko (ondoa alama za muda) +**Matokeo:** Huondoa mada zilizokota za usimamizi wa uhifadhi, hurahisisha librarian + +### Awamu ya 3: Masasisho ya Huduma ya Uhifadhi (Mabadiliko ya 10) ✅ IMEKAMILIKA +Zesasisha huduma zote za kuhifadhi ili zitumie utaratibu wa kusukuma usanidi kwa mkusanyiko kupitia `CollectionConfigHandler` +Ondoa miundombinu ya ombi/jibu la usimamizi wa uhifadhi +Ondoa ufafanuzi wa zamani wa mfumo +**Matokeo:** Usimamizi kamili wa mkusanyiko unaotegemea usanidi umefikiwa + +## Marejeleo +GitHub Issue: https://github.com/trustgraph-ai/trustgraph/issues/582 +Faili Zinazohusiana: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.tr.md b/docs/tech-specs/multi-tenant-support.tr.md new file mode 100644 index 00000000..b7d524a7 --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.tr.md @@ -0,0 +1,780 @@ +--- +layout: default +title: "Teknik Özellikler: Çok Kiracılı Destek" +parent: "Turkish (Beta)" +--- + +# Teknik Özellikler: Çok Kiracılı Destek + +> **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ış + +Kuyumuzu özelleştirmeyi engelleyen parametre adı eşleşmezliklerini düzelterek ve Cassandra anahtar alanı parametrelemesini ekleyerek çok kiracılı dağıtımları etkinleştirin. + +## Mimari Bağlam + +### Akış Tabanlı Kuyruk Çözümlemesi + +TrustGraph sistemi, dinamik kuyruk çözümlemesi için **akış tabanlı bir mimari** kullanır ve bu, doğal olarak çok kiracılığı destekler: + +**Akış Tanımları**, Cassandra'da saklanır ve arayüz tanımları aracılığıyla kuyruk adlarını belirtir. +**Kuyruk adları**, akış örneği kimlikleriyle değiştirilen `{id}` değişkenlerine sahip **şablonlar** kullanır. +**Hizmetler**, istek zamanında akış yapılandırmalarını arayarak **kuyrukları dinamik olarak çözümler**. +**Her kiracı, farklı kuyruk adlarına sahip benzersiz akışlara sahip olabilir**, bu da izolasyon sağlar. + +Örnek akış arayüz tanımı: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +Kiracı A, `tenant-a-prod` akışını başlatığında ve kiracı B, `tenant-b-prod` akışını başlattığında, otomatik olarak izole edilmiş kuyruklar elde ederler: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**Çoklu kiracılığa doğru şekilde tasarlanmış hizmetler:** +✅ **Bilgi Yönetimi (çekirdekler)** - İsteğe eklenen akış yapılandırmasından kuyrukları dinamik olarak çözer. + +**Düzeltilmesi gereken hizmetler:** +🔴 **Yapılandırma Hizmeti** - Parametre adı eşleşmezliği, kuyruk özelleştirmesini engeller. +🔴 **Kütüphaneci Hizmeti** - Sabit kodlanmış depolama yönetimi konuları (aşağıda açıklanmıştır). +🔴 **Tüm Hizmetler** - Cassandra anahtar alanını özelleştiremezsiniz. + +## Sorun Tanımı + +### Sorun #1: AsyncProcessor'daki Parametre Adı Eşleşmezliği +**CLI tanımları:** `--config-queue` (belirsiz adlandırma) +**Argparse'ın dönüştürdüğü:** `config_queue` (params sözlüğünde) +**Kodun aradığı:** `config_push_queue` +**Sonuç:** Parametre göz ardı edilir ve varsayılan olarak `persistent://tg/config/config` olur. +**Etkisi:** AsyncProcessor'dan türeyen 32'den fazla hizmeti etkiler. +**Engeller:** Çoklu kiracılı dağıtımlar, kiracıya özel yapılandırma kuyruklarını kullanamaz. +**Çözüm:** CLI parametresinin adını `--config-push-queue` olarak değiştirerek netliği artırın (özellik şu anda bozuk olduğundan, bozucu değişiklik kabul edilebilir). + +### Sorun #2: Yapılandırma Hizmetindeki Parametre Adı Eşleşmezliği +**CLI tanımları:** `--push-queue` (belirsiz adlandırma) +**Argparse'ın dönüştürdüğü:** `push_queue` (params sözlüğünde) +**Kodun aradığı:** `config_push_queue` +**Sonuç:** Parametre göz ardı edilir. +**Etkisi:** Yapılandırma hizmeti, özel bir push kuyruğunu kullanamaz. +**Çözüm:** CLI parametresinin adını `--config-push-queue` olarak değiştirerek tutarlılığı ve netliği artırın (bozucu değişiklik kabul edilebilir). + +### Sorun #3: Sabit Kodlanmış Cassandra Anahtar Alanı +**Mevcut durum:** Anahtar alanı, çeşitli hizmetlerde `"config"`, `"knowledge"`, `"librarian"` olarak sabit kodlanmıştır. +**Sonuç:** Çoklu kiracılı dağıtımlar için anahtar alanı özelleştirilemez. +**Etkisi:** Yapılandırma, çekirdek ve kütüphaneci hizmetleri. +**Engeller:** Birden fazla kiracı, ayrı Cassandra anahtar alanlarını kullanamaz. + +### Sorun #4: Koleksiyon Yönetimi Mimarisi ✅ TAMAMLANDI +**Önceki durum:** Koleksiyonlar, ayrı koleksiyon tablosu aracılığıyla Cassandra kütüphaneci anahtar alanında depolanıyordu. +**Önceki durum:** Kütüphaneci, koleksiyon oluşturma/silme işlemini koordine etmek için 4 sabit kodlanmış depolama yönetimi konusunu kullanıyordu: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**Sorunlar (Çözüldü):** + Sabit kodlanmış konular, çoklu kiracılı dağıtımlar için özelleştirilemezdi. + Kütüphaneci ile 4+ depolama hizmeti arasında karmaşık asenkron koordinasyon. + Ayrı bir Cassandra tablosu ve yönetim altyapısı. + Kritik işlemler için kalıcı olmayan istek/yanıt kuyrukları. +**Uygulanan Çözüm:** Koleksiyonları yapılandırma hizmeti depolamasına taşıdık, dağıtım için yapılandırma push'u kullandık. +**Durum:** Tüm depolama arka uçları `CollectionConfigHandler` modeline taşınmıştır. + +## Çözüm + +Bu özellik, Sorunlar #1, #2, #3 ve #4'ü ele alır. + +### 1. Bölüm: Parametre Adı Eşleşmezliklerini Düzeltme + +#### Değişiklik 1: AsyncProcessor Temel Sınıfı - CLI Parametresinin Adını Değiştirme +**Dosya:** `trustgraph-base/trustgraph/base/async_processor.py` +**Satır:** 260-264 + +**Mevcut:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**Sabit:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**Gerekçe:** +Daha açık, daha kesin bir adlandırma +İç değişken adıyla eşleşiyor: `config_push_queue` +Özellik şu anda çalışmadığı için, bu bir değişikliktir ve kabul edilebilir. +params.get() içinde herhangi bir kod değişikliğine gerek yok; zaten doğru adı arıyor. + +#### Değişiklik 2: Konfigürasyon Servisi - CLI Parametresinin Yeniden Adlandırılması +**Dosya:** `trustgraph-flow/trustgraph/config/service/service.py` +**Satır:** 276-279 + +**Mevcut:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Sabit:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**Gerekçe:** +Daha anlaşılır bir adlandırma - "config-push-queue", sadece "push-queue"den daha açık. +İç değişken adıyla eşleşiyor: `config_push_queue` +AsyncProcessor'ın `--config-push-queue` parametresiyle tutarlı. +Özellik şu anda çalışmadığı için değişiklik kabul edilebilir. +params.get() içinde herhangi bir kod değişikliğine gerek yok - zaten doğru adı arıyor. + +### 2. Bölüm: Cassandra Keyspace Parametrelendirmesi + +#### 3. Değişiklik: cassandra_config Modülüne Keyspace Parametresi Ekle +**Dosya:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**CLI argümanı ekle** (`add_cassandra_args()` fonksiyonunda): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**Ortam değişkeni desteği ekleyin** (`resolve_cassandra_config()` fonksiyonunda): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**`resolve_cassandra_config()`'nin dönüş değerini güncelleyin:** +Şu anda döndürüyor: `(hosts, username, password)` +Aşağıdaki değeri döndürmesi için değiştirin: `(hosts, username, password, keyspace)` + +**Gerekçe:** +Mevcut Cassandra yapılandırma kalıbıyla tutarlı +`add_cassandra_args()` aracılığıyla tüm hizmetlere erişilebilir +Hem CLI hem de ortam değişkeni yapılandırmasını destekler + +#### Değişiklik 4: Yapılandırma Hizmeti - Parametreli Keyspace Kullanımı +**Dosya:** `trustgraph-flow/trustgraph/config/service/service.py` + +**30. Satır** - Sabit kodlanmış keyspace'i kaldırın: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**69-73 satırları** - Cassandra yapılandırma çözümlemesi güncellendi: + +**Mevcut:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**Sabit:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**Gerekçe:** +"config" varsayılan olarak kullanılarak geriye dönük uyumluluk sağlanır. +`--cassandra-keyspace` veya `CASSANDRA_KEYSPACE` ile geçersiz kılınabilir. + +#### Değişiklik 5: Cores/Bilgi Hizmeti - Parametreleştirilmiş Anahtar Alanı Kullanımı +**Dosya:** `trustgraph-flow/trustgraph/cores/service.py` + +**Satır 37** - Sabit kodlanmış anahtar alanını kaldırın: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**Cassandra yapılandırma çözümlemesi güncellendi** (yapılandırma hizmetiyle benzer konumda): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### Değişiklik 6: Kütüphaneci Hizmeti - Parametreleştirilmiş Anahtar Alanı Kullanımı +**Dosya:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Satır 51** - Sabit kodlanmış anahtar alanını kaldır: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**Cassandra yapılandırma çözümlemesi güncellendi** (yapılandırma hizmetiyle benzer konumda): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### 3. Bölüm: Koleksiyon Yönetimini Config Servisine Taşıma + +#### Genel Bakış +Koleksiyonları Cassandra librarian anahtar alanından config servisi depolama alanına taşıyın. Bu, sabit kodlanmış depolama yönetimi konularını ortadan kaldırır ve dağıtım için mevcut config push mekanizmasını kullanarak mimariyi basitleştirir. + +#### Mevcut Mimari +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### Yeni Mimari +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### Değişiklik 7: Koleksiyon Yöneticisi - Config Hizmeti API'sini Kullanın +**Dosya:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**Kaldırılacaklar:** +`LibraryTableStore` kullanımı (33, 40-41 satırları) +Depolama yönetimi üreticilerinin başlatılması (86-140 satırları) +`on_storage_response` metodu (400-430 satırları) +`pending_deletions` takibi (57, 90-96 satırları ve tüm kullanım alanları) + +**Eklenecekler:** +API çağrıları için Config hizmeti istemcisi (istek/yanıt kalıbı) + +**Config İstemcisi Kurulumu:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**`list_collections`'ı Değiştirin (145-180. satırlar):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**`update_collection`'yi değiştirin (182-312. satırlar):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**`delete_collection`'ı Değiştirin (314-398. satırlar):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**Koleksiyon Meta Veri Formatı:** +`config` tablosunda şu şekilde saklanır: `class='collections', key='user:collection'` +Değer, zaman damgası alanları olmadan JSON olarak seri hale getirilmiş `CollectionMetadata`'dır. +Alanlar: `user`, `collection`, `name`, `description`, `tags` +Örnek: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### 8. Değişiklik: Kütüphane Hizmeti - Depolama Yönetimi Altyapısını Kaldır +**Dosya:** `trustgraph-flow/trustgraph/librarian/service.py` + +**Kaldır:** +Depolama yönetimi üreticileri (173-190. satırlar): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +Depolama yanıt tüketici (192-201. satırlar) +`on_storage_response` işleyici (467-473. satırlar) + +**Değiştir:** +`CollectionManager` başlatma (215-224. satırlar) - depolama üretici parametrelerini kaldır + +**Not:** Harici koleksiyon API'si değişmeden kalır: +`list-collections` +`update-collection` +`delete-collection` + +#### 9. Değişiklik: Koleksiyonlar Tablosunu `LibraryTableStore`'dan Kaldır +**Dosya:** `trustgraph-flow/trustgraph/tables/library.py` + +**Sil:** +Koleksiyonlar tablosu `CREATE` ifadesi (114-127. satırlar) +Koleksiyonlar için hazırlanmış ifadeler (205-240. satırlar) +Tüm koleksiyon metotları (578-717. satırlar): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**Gerekçe:** +Koleksiyonlar artık `config` tablosunda saklanıyor +Uyumluluk bozan bir değişiklik kabul edilebilir - veri taşıma işlemine gerek yok +Kütüphane hizmetini önemli ölçüde basitleştirir + +#### 10. Değişiklik: Depolama Hizmetleri - Yapılandırmaya Dayalı Koleksiyon Yönetimi ✅ TAMAMLANDI + +**Durum:** 11 depolama arka ucunun tamamı, `CollectionConfigHandler`'ı kullanmak üzere güncellendi. + +**Etkilenen Hizmetler (toplam 11):** +Belge gömülüleri: milvus, pinecone, qdrant +Grafik gömülüleri: milvus, pinecone, qdrant +Nesne depolama: cassandra +Üçlü depolama: cassandra, falkordb, memgraph, neo4j + +**Dosyalar:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**Uygulama Deseni (tüm hizmetler):** + +1. **Yapılandırma işleyiciyi `__init__` içinde kaydedin:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **Yapılandırma yöneticisini uygulayın:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **Başlangıçta bilinen koleksiyonları başlatın:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **Mevcut işleyici metotları yeniden düzenleyin:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **Depolama yönetimi altyapısını kaldırın:** + `self.storage_request_consumer` kurulumunu ve başlatmayı kaldırın + `self.storage_response_producer` kurulumunu kaldırın + `on_storage_management` dağıtıcı yöntemini kaldırın + Depolama yönetimi için metrikleri kaldırın + Aşağıdaki import'ları kaldırın: `StorageManagementRequest`, `StorageManagementResponse` + +**Arka Uç Özel Hususlar:** + +**Vektör depoları (Milvus, Pinecone, Qdrant):** `known_collections` içinde mantıksal `(user, collection)`'ı takip edin, ancak her boyut için birden fazla arka uç koleksiyonu oluşturabilir. Tembel oluşturma modeline devam edin. Silme işlemleri, tüm boyut varyantlarını kaldırmalıdır. + +**Cassandra Nesneleri:** Koleksiyonlar, yapılar değil, satır özellikleridir. Veritabanı seviyesindeki bilgileri takip edin. + +**Grafik depoları (Neo4j, Memgraph, FalkorDB):** Başlangıçta `CollectionMetadata` düğümlerini sorgulayın. Senkronizasyon sırasında meta veri düğümlerini oluşturun/silin. + +**Cassandra Üçlüleri:** Koleksiyon işlemleri için `KnowledgeGraph` API'sini kullanın. + +**Temel Tasarım Noktaları:** + +**Son tutarlılık:** İstek/yanıt mekanizması yoktur, yapılandırma itmesi yayınlanır +**Tekrarlanabilirlik:** Tüm oluşturma/silme işlemleri, yeniden denenmek üzere güvenli olmalıdır +**Hata işleme:** Hataları günlüğe kaydedin, ancak yapılandırma güncellemelerini engellemeyin +**Kendini iyileştirme:** Başarısız işlemler, bir sonraki yapılandırma itmesinde yeniden denenecektir +**Koleksiyon anahtar biçimi:** `config["collections"]` içinde `"user:collection"` + +#### Değişiklik 11: Koleksiyon Şemasını Güncelle - Zaman Damgalarını Kaldır +**Dosya:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**CollectionMetadata'ı değiştirin (Satırlar 13-21):** +Aşağıdaki alanları kaldırın: `created_at` ve `updated_at`: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**CollectionManagementRequest'i Değiştir (25-47. satırlar):** +Zaman damgası alanlarını kaldır: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**Gerekçe:** +Zaman damgaları, koleksiyonlar için değer katmaz. +Yapılandırma hizmeti, kendi sürüm takibini yapar. +Şemayı basitleştirir ve depolama alanını azaltır. + +#### Yapılandırma Hizmeti Geçişinin Faydaları + +1. ✅ **Sabit kodlanmış depolama yönetimi konularını ortadan kaldırır** - Çok kiracılı sorunu çözer. +2. ✅ **Daha basit koordinasyon** - 4 veya daha fazla depolama yanıtı için karmaşık asenkron beklemeler olmaz. +3. ✅ **Sonunda tutarlılık** - Depolama hizmetleri, yapılandırma itme yoluyla bağımsız olarak güncellenir. +4. ✅ **Daha iyi güvenilirlik** - Kalıcı yapılandırma itme, kalıcı olmayan istek/yanıt yerine. +5. ✅ **Birleşik yapılandırma modeli** - Koleksiyonlar, yapılandırma olarak ele alınır. +6. ✅ **Karmaşıklığı azaltır** - Yaklaşık 300 satır koordinasyon kodunu kaldırır. +7. ✅ **Çok kiracılı için hazır** - Yapılandırma, anahtar alanı aracılığıyla zaten kiracı izolasyonunu destekler. +8. ✅ **Sürüm takibi** - Yapılandırma hizmeti sürüm mekanizması, denetim izi sağlar. + +## Uygulama Notları + +### Geriye Dönük Uyumluluk + +**Parametre Değişiklikleri:** +CLI parametrelerinin yeniden adlandırılması, bozucu değişikliklerdir ancak kabul edilebilir (özellik şu anda çalışmıyor). +Hizmetler parametreler olmadan çalışır (varsayılanları kullanır). +Varsayılan anahtar alanları korunur: "config", "knowledge", "librarian". +Varsayılan kuyruk: `persistent://tg/config/config` + +**Koleksiyon Yönetimi:** +**Bozucu değişiklik:** Koleksiyon tablosu, "librarian" anahtar alanından kaldırılmıştır. +**Veri geçişi sağlanmamıştır** - bu aşama için kabul edilebilir. +Harici koleksiyon API'si değişmemiştir (listeleme/güncelleme/silme işlemleri). +Koleksiyon meta veri biçimi basitleştirilmiştir (zaman damgaları kaldırılmıştır). + +### Test Gereksinimleri + +**Parametre Testi:** +1. `--config-push-queue` parametresinin "graph-embeddings" hizmetinde çalıştığını doğrulayın. +2. `--config-push-queue` parametresinin "text-completion" hizmetinde çalıştığını doğrulayın. +3. `--config-push-queue` parametresinin yapılandırma hizmetinde çalıştığını doğrulayın. +4. `--cassandra-keyspace` parametresinin yapılandırma hizmeti için çalıştığını doğrulayın. +5. `--cassandra-keyspace` parametresinin "cores" hizmeti için çalıştığını doğrulayın. +6. `--cassandra-keyspace` parametresinin "librarian" hizmeti için çalıştığını doğrulayın. +7. Hizmetlerin parametreler olmadan çalıştığını (varsayılanları kullandığını) doğrulayın. +8. Özel kuyruk adları ve anahtar alanı ile çok kiracılı dağıtımı doğrulayın. + +**Koleksiyon Yönetimi Testi:** +9. `list-collections` işlemini yapılandırma hizmeti aracılığıyla doğrulayın. +10. `update-collection`'ın yapılandırma tablosunda oluşturulduğunu/güncellendiğini doğrulayın. +11. `delete-collection`'ın yapılandırma tablosundan kaldırıldığını doğrulayın. +12. Koleksiyon güncellemelerinde yapılandırma itmesinin tetiklendiğini doğrulayın. +13. Etiket filtrelemenin yapılandırma tabanlı depolama ile çalıştığını doğrulayın. +14. Koleksiyon işlemlerinin zaman damgası alanları olmadan çalıştığını doğrulayın. + +### Çok Kiracılı Dağıtım Örneği +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## Etki Analizi + +### 1-2 Değişikliklerinden Etkilenen Hizmetler (CLI Parametre Adı Değişikliği) +AsyncProcessor veya FlowProcessor'dan türeyen tüm hizmetler: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (tüm sağlayıcılar) +extract-* (tüm çıkarıcılar) +query-* (tüm sorgu hizmetleri) +retrieval-* (tüm RAG hizmetleri) +storage-* (tüm depolama hizmetleri) +Ve 20'den fazla hizmet daha + +### 3-6 Değişikliklerinden Etkilenen Hizmetler (Cassandra Keyspace) +config-service +cores-service +librarian-service + +### 7-11 Değişikliklerinden Etkilenen Hizmetler (Koleksiyon Yönetimi) + +**Hızlı Uygulanacak Değişiklikler:** +librarian-service (collection_manager.py, service.py) +tables/library.py (collections tablosunun kaldırılması) +schema/services/collection.py (zaman damgası kaldırma) + +**Tamamlanan Değişiklikler (Değişiklik 10):** ✅ +Tüm depolama hizmetleri (toplam 11) - `CollectionConfigHandler` üzerinden koleksiyon güncellemeleri için yapılandırma itme işlemine geçirildi +Depolama yönetimi şeması `storage.py`'dan kaldırıldı + +## Gelecek Hususlar + +### Kullanıcı Başına Keyspace Modeli + +Bazı hizmetler, her kullanıcının kendi Cassandra keyspace'ine sahip olduğu **kullanıcı başına keyspace**'leri dinamik olarak kullanır: + +**Kullanıcı başına keyspace kullanan hizmetler:** +1. **Triples Sorgu Hizmeti** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + `keyspace=query.user` kullanır +2. **Objects Sorgu Hizmeti** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + `keyspace=self.sanitize_name(user)` kullanır +3. **KnowledgeGraph Doğrudan Erişim** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + Varsayılan parametre `keyspace="trustgraph"` + +**Durum:** Bu, bu belirtimde **değiştirilmemiştir**. + +**Gelecekte İnceleme Gerekli:** +Kullanıcı başına keyspace modelinin kiracı izolasyonu sorunlarına neden olup olmadığını değerlendirin +Çok kiracılı dağıtımların keyspace önek kalıplarına (örneğin, `tenant_a_user1`) ihtiyaç duyup duymadığını düşünün +Kiracılar arasında potansiyel kullanıcı kimliği çakışmalarını gözden geçirin +Tek, paylaşılan keyspace'in, kullanıcı tabanlı satır izolasyonu ile birlikte daha mı tercih edilebilir olduğunu değerlendirin + +**Not:** Bu, mevcut çok kiracılı uygulamayı engellemez, ancak üretim çok kiracılı dağıtımlardan önce incelenmelidir. + +## Uygulama Aşamaları + +### Aşama 1: Parametre Düzeltmeleri (Değişiklikler 1-6) +`--config-push-queue` parametre adlandırmasını düzeltin +`--cassandra-keyspace` parametre desteğini ekleyin +**Sonuç:** Çok kiracılı kuyruk ve keyspace yapılandırması etkinleştirildi + +### Aşama 2: Koleksiyon Yönetimi Geçişi (Değişiklikler 7-9, 11) +Koleksiyon depolamasını yapılandırma hizmetine geçirin +librarian'dan koleksiyon tablosunu kaldırın +Koleksiyon şemasını güncelleyin (zaman damgalarını kaldırın) +**Sonuç:** Sabit kodlu depolama yönetimi konuları ortadan kaldırılır, librarian basitleştirilir + +### Aşama 3: Depolama Hizmeti Güncellemeleri (Değişiklik 10) ✅ TAMAMLANDI +Tüm depolama hizmetlerini koleksiyonlar için yapılandırma itme işlemine almak için güncelleyin `CollectionConfigHandler` +Depolama yönetimi istek/yanıt altyapısını kaldırın +Eski şema tanımlarını kaldırın +**Sonuç:** Tamamen yapılandırmaya dayalı koleksiyon yönetimi elde edildi + +## Referanslar +GitHub Sorunu: https://github.com/trustgraph-ai/trustgraph/issues/582 +İlgili Dosyalar: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/multi-tenant-support.zh-cn.md b/docs/tech-specs/multi-tenant-support.zh-cn.md new file mode 100644 index 00000000..8350c9f3 --- /dev/null +++ b/docs/tech-specs/multi-tenant-support.zh-cn.md @@ -0,0 +1,780 @@ +--- +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. + +## 概述 + +通过修复参数名称不匹配的问题,从而解决阻止队列自定义的问题,并添加 Cassandra 键空间参数化,以实现多租户部署。 + +## 架构上下文 + +### 基于流的队列解析 + +TrustGraph 系统使用**基于流的架构**进行动态队列解析,该架构本质上支持多租户: + +**流定义**存储在 Cassandra 中,并通过接口定义指定队列名称。 +**队列名称使用模板**,其中包含 `{id}` 变量,这些变量会被替换为流实例 ID。 +**服务在请求时动态解析队列**,通过查找流配置。 +**每个租户可以拥有独特的流**,具有不同的队列名称,从而提供隔离。 + +示例流接口定义: +```json +{ + "interfaces": { + "triples-store": "persistent://tg/flow/triples-store:{id}", + "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}" + } +} +``` + +当租户 A 启动流程 `tenant-a-prod`,而租户 B 启动流程 `tenant-b-prod` 时,它们会自动获得隔离的队列: +`persistent://tg/flow/triples-store:tenant-a-prod` +`persistent://tg/flow/triples-store:tenant-b-prod` + +**为多租户设计的服务:** +✅ **知识管理 (核心)** - 动态解析从请求中传递的流程配置中的队列 + +**需要修复的服务:** +🔴 **配置服务** - 参数名称不匹配,无法自定义队列 +🔴 **图书管理员服务** - 预定义的存储管理主题(见下文) +🔴 **所有服务** - 无法自定义 Cassandra keyspace + +## 问题描述 + +### 问题 #1:AsyncProcessor 中的参数名称不匹配 +**CLI 定义:** `--config-queue` (命名不明确) +**Argparse 转换:** `config_queue` (在 params 字典中) +**代码查找:** `config_push_queue` +**结果:** 参数被忽略,默认为 `persistent://tg/config/config` +**影响:** 影响所有 32 多个从 AsyncProcessor 继承的服务 +**问题:** 多租户部署无法使用租户特定的配置队列 +**解决方案:** 将 CLI 参数重命名为 `--config-push-queue`,以提高清晰度(可以接受破坏性更改,因为该功能当前已损坏) + +### 问题 #2:配置服务中的参数名称不匹配 +**CLI 定义:** `--push-queue` (命名模糊) +**Argparse 转换:** `push_queue` (在 params 字典中) +**代码查找:** `config_push_queue` +**结果:** 参数被忽略 +**影响:** 配置服务无法使用自定义推送队列 +**解决方案:** 将 CLI 参数重命名为 `--config-push-queue`,以提高一致性和清晰度(可以接受破坏性更改) + +### 问题 #3:预定义的 Cassandra Keyspace +**当前:** Keyspace 在各种服务中硬编码为 `"config"`、`"knowledge"`、`"librarian"` +**结果:** 无法为多租户部署自定义 keyspace +**影响:** 配置、核心和图书管理员服务 +**问题:** 多个租户无法使用单独的 Cassandra keyspace + +### 问题 #4:集合管理架构 ✅ 已完成 +**之前:** 集合存储在图书管理员 keyspace 中的单独的集合表中 +**之前:** 图书管理员使用 4 个硬编码的存储管理主题来协调集合创建/删除: + `vector_storage_management_topic` + `object_storage_management_topic` + `triples_storage_management_topic` + `storage_management_response_topic` +**问题(已解决):** + 无法为多租户部署自定义硬编码主题 + 图书管理员和 4 个或更多存储服务之间的复杂异步协调 + 单独的 Cassandra 表和管理基础设施 + 关键操作的非持久性请求/响应队列 +**已实施的解决方案:** 将集合迁移到配置服务存储,使用配置推送进行分发 +**状态:** 所有存储后端已迁移到 `CollectionConfigHandler` 模式 + +## 解决方案 + +此规范解决了问题 #1、#2、#3 和 #4。 + +### 第一部分:修复参数名称不匹配 + +#### 更改 1:AsyncProcessor 基类 - 重命名 CLI 参数 +**文件:** `trustgraph-base/trustgraph/base/async_processor.py` +**行:** 260-264 + +**当前:** +```python +parser.add_argument( + '--config-queue', + default=default_config_queue, + help=f'Config push queue {default_config_queue}', +) +``` + +**已修复:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_queue, + help=f'Config push queue (default: {default_config_queue})', +) +``` + +**理由:** +命名更清晰、更明确 +与内部变量名 `config_push_queue` 匹配 +允许进行重大更改,因为该功能目前不可用 +params.get() 不需要任何代码更改,因为它已经查找正确的名称 + +#### 更改 2:配置服务 - 重命名 CLI 参数 +**文件:** `trustgraph-flow/trustgraph/config/service/service.py` +**行:** 276-279 + +**当前:** +```python +parser.add_argument( + '--push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**固定:** +```python +parser.add_argument( + '--config-push-queue', + default=default_config_push_queue, + help=f'Config push queue (default: {default_config_push_queue})' +) +``` + +**理由:** +更清晰的命名 - "config-push-queue" 比仅仅 "push-queue" 更明确。 +与内部变量名 `config_push_queue` 匹配。 +与 AsyncProcessor 的 `--config-push-queue` 参数一致。 +即使是重大更改,也是可以接受的,因为该功能目前不可用。 +params.get() 中不需要任何代码更改 - 它已经查找正确的名称。 + +### 第二部分:添加 Cassandra 键空间参数化 + +#### 更改 3:向 cassandra_config 模块添加键空间参数 +**文件:** `trustgraph-base/trustgraph/base/cassandra_config.py` + +**添加 CLI 参数**(在 `add_cassandra_args()` 函数中): +```python +parser.add_argument( + '--cassandra-keyspace', + default=None, + help='Cassandra keyspace (default: service-specific)' +) +``` + +**添加环境变量支持** (在 `resolve_cassandra_config()` 函数中): +```python +keyspace = params.get( + "cassandra_keyspace", + os.environ.get("CASSANDRA_KEYSPACE") +) +``` + +**更新 `resolve_cassandra_config()` 的返回值:** +当前返回:`(hosts, username, password)` +更改为返回:`(hosts, username, password, keyspace)` + +**理由:** +与现有的 Cassandra 配置模式一致 +通过 `add_cassandra_args()` 可供所有服务使用 +支持 CLI 和环境变量配置 + +#### 变更 4:配置服务 - 使用参数化 Keyspace +**文件:** `trustgraph-flow/trustgraph/config/service/service.py` + +**第 30 行** - 移除硬编码的 Keyspace: +```python +# DELETE THIS LINE: +keyspace = "config" +``` + +**第69-73行** - 更新 Cassandra 配置解析: + +**当前:** +```python +cassandra_host, cassandra_username, cassandra_password = \ + resolve_cassandra_config(params) +``` + +**已修复:** +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="config") +``` + +**原因:** +保持与默认值为 "config" 的配置向后兼容。 +允许通过 `--cassandra-keyspace` 或 `CASSANDRA_KEYSPACE` 进行覆盖。 + +#### 变更 5:核心/知识服务 - 使用参数化键空间 +**文件:** `trustgraph-flow/trustgraph/cores/service.py` + +**第 37 行** - 移除硬编码的键空间: +```python +# DELETE THIS LINE: +keyspace = "knowledge" +``` + +**更新 Cassandra 配置解析**(位置类似于配置服务): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="knowledge") +``` + +#### 变更 6:图书管理员服务 - 使用参数化键空间 +**文件:** `trustgraph-flow/trustgraph/librarian/service.py` + +**第 51 行** - 移除硬编码的键空间: +```python +# DELETE THIS LINE: +keyspace = "librarian" +``` + +**更新 Cassandra 配置解析**(位置与配置服务类似): +```python +cassandra_host, cassandra_username, cassandra_password, keyspace = \ + resolve_cassandra_config(params, default_keyspace="librarian") +``` + +### 第三部分:将集合管理迁移到配置服务 + +#### 概述 +将集合从 Cassandra librarian 键空间迁移到配置服务存储。这消除了硬编码的存储管理主题,并通过使用现有的配置推送机制进行分发,简化了架构。 + +#### 当前架构 +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Cassandra Collections Table (librarian keyspace) + ↓ + Broadcast to 4 Storage Management Topics (hardcoded) + ↓ + Wait for 4+ Storage Service Responses + ↓ + Response to Gateway +``` + +#### 新架构 +``` +API Request → Gateway → Librarian Service + ↓ + CollectionManager + ↓ + Config Service API (put/delete/getvalues) + ↓ + Cassandra Config Table (class='collections', key='user:collection') + ↓ + Config Push (to all subscribers on config-push-queue) + ↓ + All Storage Services receive config update independently +``` + +#### 变更 7:集合管理器 - 使用配置服务 API +**文件:** `trustgraph-flow/trustgraph/librarian/collection_manager.py` + +**移除:** +`LibraryTableStore` 的使用(第 33 行,第 40-41 行) +存储管理生产者初始化(第 86-140 行) +`on_storage_response` 方法(第 400-430 行) +`pending_deletions` 跟踪(第 57 行,第 90-96 行,以及整个使用过程) + +**添加:** +用于 API 调用的配置服务客户端(请求/响应模式) + +**配置客户端设置:** +```python +# In __init__, add config request/response producers/consumers +from trustgraph.schema.services.config import ConfigRequest, ConfigResponse + +# Producer for config requests +self.config_request_producer = Producer( + client=pulsar_client, + topic=config_request_queue, + schema=ConfigRequest, +) + +# Consumer for config responses (with correlation ID) +self.config_response_consumer = Consumer( + taskgroup=taskgroup, + client=pulsar_client, + flow=None, + topic=config_response_queue, + subscriber=f"{id}-config", + schema=ConfigResponse, + handler=self.on_config_response, +) + +# Tracking for pending config requests +self.pending_config_requests = {} # request_id -> asyncio.Event +``` + +**修改 `list_collections` (第145-180行):** +```python +async def list_collections(self, user, tag_filter=None, limit=None): + """List collections from config service""" + # Send getvalues request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='getvalues', + type='collections', + ) + + # Send request and wait for response + response = await self.send_config_request(request) + + # Parse collections from response + collections = [] + for key, value_json in response.values.items(): + if ":" in key: + coll_user, collection = key.split(":", 1) + if coll_user == user: + metadata = json.loads(value_json) + collections.append(CollectionMetadata(**metadata)) + + # Apply tag filtering in-memory (as before) + if tag_filter: + collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)] + + # Apply limit + if limit: + collections = collections[:limit] + + return collections + +async def send_config_request(self, request): + """Send config request and wait for response""" + event = asyncio.Event() + self.pending_config_requests[request.id] = event + + await self.config_request_producer.send(request) + await event.wait() + + return self.pending_config_requests.pop(request.id + "_response") + +async def on_config_response(self, message, consumer, flow): + """Handle config response""" + response = message.value() + if response.id in self.pending_config_requests: + self.pending_config_requests[response.id + "_response"] = response + self.pending_config_requests[response.id].set() +``` + +**修改 `update_collection` (第182-312行):** +```python +async def update_collection(self, user, collection, name, description, tags): + """Update collection via config service""" + # Create metadata + metadata = CollectionMetadata( + user=user, + collection=collection, + name=name, + description=description, + tags=tags, + ) + + # Send put request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='put', + type='collections', + key=f'{user}:{collection}', + value=json.dumps(metadata.to_dict()), + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config update failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and create collections +``` + +**修改 `delete_collection` (第314-398行):** +```python +async def delete_collection(self, user, collection): + """Delete collection via config service""" + # Send delete request to config service + request = ConfigRequest( + id=str(uuid.uuid4()), + operation='delete', + type='collections', + key=f'{user}:{collection}', + ) + + response = await self.send_config_request(request) + + if response.error: + raise RuntimeError(f"Config delete failed: {response.error.message}") + + # Config service will trigger config push automatically + # Storage services will receive update and delete collections +``` + +**集合元数据格式:** +存储在配置表中,格式为:`class='collections', key='user:collection'` +值是 JSON 序列化的 CollectionMetadata (不包含时间戳字段) +字段:`user`, `collection`, `name`, `description`, `tags` +示例:`class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'` + +#### 变更 8: Librarian Service - 移除存储管理基础设施 +**文件:** `trustgraph-flow/trustgraph/librarian/service.py` + +**移除:** +存储管理生产者 (173-190 行): + `vector_storage_management_producer` + `object_storage_management_producer` + `triples_storage_management_producer` +存储响应消费者 (192-201 行) +`on_storage_response` 处理程序 (467-473 行) + +**修改:** +CollectionManager 初始化 (215-224 行) - 移除存储生产者参数 + +**注意:** 外部集合 API 保持不变: +`list-collections` +`update-collection` +`delete-collection` + +#### 变更 9: 从 LibraryTableStore 中移除 Collections 表 +**文件:** `trustgraph-flow/trustgraph/tables/library.py` + +**删除:** +Collections 表的 CREATE 语句 (114-127 行) +Collections 预处理语句 (205-240 行) +所有集合方法 (578-717 行): + `ensure_collection_exists` + `list_collections` + `update_collection` + `delete_collection` + `get_collection` + `create_collection` + +**原因:** +集合现在存储在配置表中 +这是一个破坏性变更,但无需数据迁移 +显著简化了 librarian service + +#### 变更 10: 存储服务 - 基于配置的集合管理 ✅ 已完成 + +**状态:** 所有 11 个存储后端都已迁移到使用 `CollectionConfigHandler`。 + +**受影响的服务 (总共 11 个):** +文档嵌入: milvus, pinecone, qdrant +图嵌入: milvus, pinecone, qdrant +对象存储: cassandra +三元组存储: cassandra, falkordb, memgraph, neo4j + +**文件:** +`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py` +`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py` +`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py` +`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py` +`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py` +`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py` + +**实现模式 (所有服务):** + +1. **在 `__init__` 中注册配置处理程序:** +```python +# Add after AsyncProcessor initialization +self.register_config_handler(self.on_collection_config) +self.known_collections = set() # Track (user, collection) tuples +``` + +2. **实现配置处理器:** +```python +async def on_collection_config(self, config, version): + """Handle collection configuration updates""" + logger.info(f"Collection config version: {version}") + + if "collections" not in config: + return + + # Parse collections from config + # Key format: "user:collection" in config["collections"] + config_collections = set() + for key in config["collections"].keys(): + if ":" in key: + user, collection = key.split(":", 1) + config_collections.add((user, collection)) + + # Determine changes + to_create = config_collections - self.known_collections + to_delete = self.known_collections - config_collections + + # Create new collections (idempotent) + for user, collection in to_create: + try: + await self.create_collection_internal(user, collection) + self.known_collections.add((user, collection)) + logger.info(f"Created collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to create {user}/{collection}: {e}") + + # Delete removed collections (idempotent) + for user, collection in to_delete: + try: + await self.delete_collection_internal(user, collection) + self.known_collections.discard((user, collection)) + logger.info(f"Deleted collection: {user}/{collection}") + except Exception as e: + logger.error(f"Failed to delete {user}/{collection}: {e}") +``` + +3. **初始化启动时的已知集合:** +```python +async def start(self): + """Start the processor""" + await super().start() + await self.sync_known_collections() + +async def sync_known_collections(self): + """Query backend to populate known_collections set""" + # Backend-specific implementation: + # - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern + # - Cassandra: Query keyspaces or collection metadata + # - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes + pass +``` + +4. **重构现有的处理方法:** +```python +# Rename and remove response sending: +# handle_create_collection → create_collection_internal +# handle_delete_collection → delete_collection_internal + +async def create_collection_internal(self, user, collection): + """Create collection (idempotent)""" + # Same logic as current handle_create_collection + # But remove response producer calls + # Handle "already exists" gracefully + pass + +async def delete_collection_internal(self, user, collection): + """Delete collection (idempotent)""" + # Same logic as current handle_delete_collection + # But remove response producer calls + # Handle "not found" gracefully + pass +``` + +5. **移除存储管理基础设施:** + 移除 `self.storage_request_consumer` 的配置和启动 + 移除 `self.storage_response_producer` 的配置 + 移除 `on_storage_management` 的调度器方法 + 移除存储管理的指标 + 移除导入:`StorageManagementRequest`, `StorageManagementResponse` + +**后端特定注意事项:** + +**向量存储 (Milvus, Pinecone, Qdrant):** 跟踪 `(user, collection)` 在 `known_collections` 中的逻辑,但可能会为每个维度创建多个后端集合。继续采用延迟创建模式。删除操作必须删除所有维度变体。 + +**Cassandra Objects:** 集合是行属性,而不是结构。跟踪键空间级别的信息。 + +**图数据库 (Neo4j, Memgraph, FalkorDB):** 启动时查询 `CollectionMetadata` 节点。在同步时创建/删除元数据节点。 + +**Cassandra 三元组:** 使用 `KnowledgeGraph` API 进行集合操作。 + +**关键设计要点:** + +**最终一致性:** 没有请求/响应机制,配置推送是广播的 +**幂等性:** 所有创建/删除操作都必须可以安全重试 +**错误处理:** 记录错误,但不要阻止配置更新 +**自愈:** 失败的操作将在下一次配置推送时重试 +**集合键格式:** `"user:collection"` 在 `config["collections"]` 中 + +#### 变更 11:更新集合模式 - 移除时间戳 +**文件:** `trustgraph-base/trustgraph/schema/services/collection.py` + +**修改 CollectionMetadata (第 13-21 行):** +移除 `created_at` 和 `updated_at` 字段: +```python +class CollectionMetadata(Record): + user = String() + collection = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() +``` + +**修改 CollectionManagementRequest (第 25-47 行):** +移除时间戳字段: +```python +class CollectionManagementRequest(Record): + operation = String() + user = String() + collection = String() + timestamp = String() + name = String() + description = String() + tags = Array(String()) + # Remove: created_at = String() + # Remove: updated_at = String() + tag_filter = Array(String()) + limit = Integer() +``` + +**Rationale:** +Timestamps don't add value for collections +Config service maintains its own version tracking +Simplifies schema and reduces storage + +#### Benefits of Config Service Migration + +1. ✅ **Eliminates hardcoded storage management topics** - Solves multi-tenant blocker +2. ✅ **Simpler coordination** - No complex async waiting for 4+ storage responses +3. ✅ **Eventual consistency** - Storage services update independently via config push +4. ✅ **Better reliability** - Persistent config push vs non-persistent request/response +5. ✅ **Unified configuration model** - Collections treated as configuration +6. ✅ **Reduces complexity** - Removes ~300 lines of coordination code +7. ✅ **Multi-tenant ready** - Config already supports tenant isolation via keyspace +8. ✅ **Version tracking** - Config service version mechanism provides audit trail + +## Implementation Notes + +### Backward Compatibility + +**Parameter Changes:** +CLI parameter renames are breaking changes but acceptable (feature currently non-functional) +Services work without parameters (use defaults) +Default keyspaces preserved: "config", "knowledge", "librarian" +Default queue: `persistent://tg/config/config` + +**Collection Management:** +**Breaking change:** Collections table removed from librarian keyspace +**No data migration provided** - acceptable for this phase +External collection API unchanged (list/update/delete operations) +Collection metadata format simplified (timestamps removed) + +### Testing Requirements + +**Parameter Testing:** +1. Verify `--config-push-queue` parameter works on graph-embeddings service +2. Verify `--config-push-queue` parameter works on text-completion service +3. Verify `--config-push-queue` parameter works on config service +4. Verify `--cassandra-keyspace` parameter works for config service +5. Verify `--cassandra-keyspace` parameter works for cores service +6. Verify `--cassandra-keyspace` parameter works for librarian service +7. Verify services work without parameters (uses defaults) +8. Verify multi-tenant deployment with custom queue names and keyspace + +**Collection Management Testing:** +9. Verify `list-collections` operation via config service +10. Verify `update-collection` creates/updates in config table +11. Verify `delete-collection` removes from config table +12. Verify config push is triggered on collection updates +13. Verify tag filtering works with config-based storage +14. Verify collection operations work without timestamp fields + +### Multi-Tenant Deployment Example +```bash +# Tenant: tg-dev +graph-embeddings \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config + +config-service \ + -p pulsar+ssl://broker:6651 \ + --pulsar-api-key \ + --config-push-queue persistent://tg-dev/config/config \ + --cassandra-keyspace tg_dev_config +``` + +## 影响分析 + +### 受变更 1-2 影响的服务 (CLI 参数重命名) +所有继承自 AsyncProcessor 或 FlowProcessor 的服务: +config-service +cores-service +librarian-service +graph-embeddings +document-embeddings +text-completion-* (所有提供者) +extract-* (所有提取器) +query-* (所有查询服务) +retrieval-* (所有 RAG 服务) +storage-* (所有存储服务) +还有 20 多个服务 + +### 受变更 3-6 影响的服务 (Cassandra Keyspace) +config-service +cores-service +librarian-service + +### 受变更 7-11 影响的服务 (集合管理) + +**即时变更:** +librarian-service (collection_manager.py, service.py) +tables/library.py (删除 collections 表) +schema/services/collection.py (删除时间戳) + +**已完成的变更 (变更 10):** ✅ +所有存储服务 (共 11 个) - 已迁移到配置推送,用于通过 `CollectionConfigHandler` 更新集合 +存储管理模式已从 `storage.py` 中移除 + +## 未来考虑 + +### 基于用户的 Keyspace 模式 + +一些服务使用 **基于用户的 Keyspace** 动态模式,其中每个用户都拥有自己的 Cassandra Keyspace: + +**使用基于用户的 Keyspace 的服务:** +1. **三元组查询服务** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`) + 使用 `keyspace=query.user` +2. **对象查询服务** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`) + 使用 `keyspace=self.sanitize_name(user)` +3. **知识图谱直接访问** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`) + 默认参数 `keyspace="trustgraph"` + +**状态:** 这些 **未进行修改**,在本规范中。 + +**需要未来审查:** +评估基于用户的 Keyspace 模式是否会产生租户隔离问题 +考虑是否需要为多租户部署使用 Keyspace 前缀模式 (例如,`tenant_a_user1`) +审查是否存在用户 ID 在租户之间的冲突 +评估是否更倾向于使用单个共享 Keyspace,每个租户使用基于用户的行隔离 + +**注意:** 这不会阻止当前的 multi-tenant 实现,但在进行生产 multi-tenant 部署之前应进行审查。 + +## 实施阶段 + +### 第一阶段:参数修复 (变更 1-6) +修复 `--config-push-queue` 参数命名 +添加 `--cassandra-keyspace` 参数支持 +**结果:** 启用了 multi-tenant 队列和 Keyspace 配置 + +### 第二阶段:集合管理迁移 (变更 7-9, 11) +将集合存储迁移到配置服务 +从 librarian 中删除 collections 表 +更新集合模式 (删除时间戳) +**结果:** 消除硬编码的存储管理主题,简化 librarian + +### 第三阶段:存储服务更新 (变更 10) ✅ 已完成 +所有存储服务已更新为使用配置推送进行集合管理,通过 `CollectionConfigHandler` +移除了存储管理请求/响应基础设施 +移除了旧的模式定义 +**结果:** 实现了基于配置的集合管理 + +## 引用 +GitHub Issue: https://github.com/trustgraph-ai/trustgraph/issues/582 +相关文件: + `trustgraph-base/trustgraph/base/async_processor.py` + `trustgraph-base/trustgraph/base/cassandra_config.py` + `trustgraph-base/trustgraph/schema/core/topic.py` + `trustgraph-base/trustgraph/schema/services/collection.py` + `trustgraph-flow/trustgraph/config/service/service.py` + `trustgraph-flow/trustgraph/cores/service.py` + `trustgraph-flow/trustgraph/librarian/service.py` + `trustgraph-flow/trustgraph/librarian/collection_manager.py` + `trustgraph-flow/trustgraph/tables/library.py` diff --git a/docs/tech-specs/neo4j-user-collection-isolation.ar.md b/docs/tech-specs/neo4j-user-collection-isolation.ar.md new file mode 100644 index 00000000..df2620a5 --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.ar.md @@ -0,0 +1,198 @@ +--- +layout: default +title: "دعم عزل المستخدم/المجموعة في Neo4j" +parent: "Arabic (Beta)" +--- + +# دعم عزل المستخدم/المجموعة في Neo4j + +> **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. + +## بيان المشكلة + +تفتقر آلية تخزين الاستعلامات الثلاثية الحالية في Neo4j إلى عزل المستخدم/المجموعة، مما يؤدي إلى مشكلة أمنية متعددة المستأجرين. يتم تخزين جميع الثلاثيات في نفس مساحة الرسم البياني دون أي آلية لمنع المستخدمين من الوصول إلى بيانات مستخدمين آخرين أو مزج المجموعات. + +على عكس الأنظمة الخلفية الأخرى للتخزين في TrustGraph: +- **Cassandra**: تستخدم مساحات مفاتيح منفصلة لكل مستخدم وجداول لكل مجموعة. +- **مخازن المتجهات** (Milvus, Qdrant, Pinecone): تستخدم مساحات أسماء خاصة بالمجموعة. +- **Neo4j**: تشارك حاليًا جميع البيانات في رسم بياني واحد (ثغرة أمنية). + +## البنية الحالية + +### نموذج البيانات +- **العقد:** تسمية `:Node` مع خاصية `uri`، تسمية `:Literal` مع خاصية `value`. +- **العلاقات:** تسمية `:Rel` مع خاصية `uri`. +- **الفهارس:** `Node.uri`, `Literal.value`, `Rel.uri`. + +### تدفق الرسائل +- تحتوي رسائل `Triples` على الحقول `metadata.user` و `metadata.collection`. +- تتلقى خدمة التخزين معلومات المستخدم/المجموعة ولكنها تتجاهلها. +- تتوقع خدمة الاستعلام `user` و `collection` في `TriplesQueryRequest` ولكنها تتجاهلهما. + +### المشكلة الأمنية الحالية +```cypher +# يمكن لأي مستخدم الاستعلام عن أي بيانات - لا يوجد عزل +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## الحل المقترح: التصفية المستندة إلى الخصائص (موصى بها) + +### نظرة عامة +إضافة خصائص `user` و `collection` إلى جميع العقد والعلاقات، ثم تصفية جميع العمليات بناءً على هذه الخصائص. يوفر هذا النهج عزلًا قويًا مع الحفاظ على مرونة الاستعلام والتوافق مع الإصدارات السابقة. + +### تغييرات نموذج البيانات + +#### هيكل العقدة المحسّن +```cypher +// كيانات العقد +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// كيانات حرفية +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### هيكل العلاقة المحسّن +```cypher +// العلاقات مع خصائص المستخدم/المجموعة +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### الفهارس المحدثة +```cypher +// فهارس مركبة للتصفية الفعالة +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// الحفاظ على الفهارس الحالية للتوافق مع الإصدارات السابقة (اختياري) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### تنفيذ الخطة + +### المرحلة 1: الأساس (الأسبوع 1) +1. [ ] تحديث خدمة التخزين لقبول وتخزين خصائص المستخدم/المجموعة. +2. [ ] إضافة فهارس مركبة للتصفية الفعالة. +3. [ ] تنفيذ طبقة توافق مع الإصدارات السابقة. +4. [ ] إنشاء اختبارات وحدة للوظائف الجديدة. + +### المرحلة 2: تحديثات الاستعلام (الأسبوع 2) +1. [ ] تحديث جميع أنماط الاستعلام لتشمل عوامل تصفية المستخدم/المجموعة. +2. [ ] إضافة التحقق من صحة الاستعلامات وعناصر التحكم الأمنية. +3. [ ] تحديث اختبارات التكامل. +4. [ ] اختبار الأداء مع الاستعلامات المفلترة. + +### المرحلة 3: الترحيل والنشر (الأسبوع 3) +1. [ ] إنشاء نصوص ترحيل للبيانات لمثيل Neo4j الحالي. +2. [ ] وثائق النشر والتعليمات البرمجية التشغيلية. +3. [ ] المراقبة والتنبيه لانتهاكات العزل. +4. [ ] اختبار شامل مع سيناريوهات متعددة للمستخدمين/المجموعات. + +### المرحلة 4: التقوية (الأسبوع 4) +1. [ ] إزالة وضع التوافق مع الإصدارات القديمة. +2. [ ] إضافة تسجيل تدقيق شامل. +3. [ ] مراجعة أمنية واختبار اختراق. +4. [ ] تحسين الأداء. + +### استراتيجية الاختبار + +### اختبارات الوحدة +```python +def test_user_collection_isolation(): + # تخزين ثلاثيات لمستخدم1/مجموعة1 + processor.store_triples(triples_user1_coll1) + + # تخزين ثلاثيات لمستخدم2/مجموعة2 + processor.store_triples(triples_user2_coll2) + + # يجب أن تعرض الاستعلامات كمستخدم1 فقط بيانات مستخدم1 + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # يجب أن تعرض الاستعلامات كمستخدم2 فقط بيانات مستخدم2 + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### اختبارات التكامل +- سيناريوهات متعددة المستخدمين مع بيانات متداخلة. +- استعلامات عبر مجموعات (يجب أن تفشل). +- اختبارات الترحيل مع البيانات الحالية. +- معايير أداء مع مجموعات بيانات كبيرة. + +### اختبارات الأمان +- محاولة الاستعلام عن بيانات مستخدمين آخرين. +- هجمات SQL injection على معلمات المستخدم/المجموعة. +- التحقق من العزل الكامل في ظل أنماط استعلام مختلفة. + +### اعتبارات الأداء + +### استراتيجية الفهرس +- فهارس مركبة على `(user, collection, uri)` للتصفية المثلى. +- ضع في اعتبارك الفهارس الجزئية إذا كانت بعض المجموعات أكبر بكثير. +- مراقبة استخدام الفهرس وأداء الاستعلام. + +### تحسين الاستعلام +- استخدم EXPLAIN للتحقق من استخدام الفهرس في الاستعلامات المفلترة. +- ضع في اعتبارك تخزين نتائج الاستعلام مؤقتًا للبيانات التي يتم الوصول إليها بشكل متكرر. +- قم بتوصيف استخدام الذاكرة مع عدد كبير من المستخدمين/المجموعات. + +### قابلية التوسع +- تخلق كل مجموعة مستخدم/مجموعة جزيرة بيانات منفصلة. +- مراقبة حجم قاعدة البيانات واستخدام مجموعة الاتصال. +- ضع في اعتبارك استراتيجيات التوسع الأفقي إذا لزم الأمر. + +### الأمن والامتثال + +### ضمانات العزل +- **الفيزيائية**: جميع بيانات المستخدم مخزنة مع خصائص مستخدم/مجموعة صريحة. +- **المنطقية**: يتم تصفية جميع الاستعلامات بواسطة سياق المستخدم/المجموعة. +- **التحكم في الوصول**: التحقق من الصحة على مستوى الخدمة يمنع الوصول غير المصرح به. + +### متطلبات التدقيق +- تسجيل جميع عمليات الوصول إلى البيانات مع سياق المستخدم/المجموعة. +- تتبع أنشطة الترحيل وحركات البيانات. +- المراقبة بحثًا عن محاولات انتهاك العزل. + +### اعتبارات الامتثال +- GDPR: القدرة المحسنة على تحديد موقع بيانات المستخدم وحذفها. +- SOC2: ضوابط واضحة لعزل المستأجر والوصول. +- HIPAA: عزل قوي للمستأجر لبيانات الرعاية الصحية. + +### المخاطر والتخفيف + +| المخاطر | التأثير | الاحتمالية | التخفيف | +|------|--------|------------|------------| +| الاستعلام المفقود لعامل تصفية المستخدم/المجموعة | مرتفع | متوسط | التحقق الإلزامي، اختبار شامل | +| تدهور الأداء | متوسط | منخفض | تحسين الفهرس، توصيف الاستعلام | +| تلف بيانات الترحيل | مرتفع | منخفض | استراتيجية النسخ الاحتياطي، إجراءات التراجع | +| استعلامات معقدة متعددة المجموعات | متوسط | متوسط | توثيق أنماط الاستعلام، توفير أمثلة | + +### معايير النجاح + +1. **الأمان**: صفر من عمليات الوصول إلى بيانات المستخدم عبر المستخدمين في الإنتاج. +2. **الأداء**: أقل من 10٪ من تأثير أداء الاستعلام مقارنة بالاستعلامات غير المفلترة. +3. **الترحيل**: تم ترحيل 100٪ من البيانات الحالية بنجاح بدون فقدان. +4. **سهولة الاستخدام**: تعمل جميع أنماط الاستعلام الموجودة مع سياق المستخدم/المجموعة. +5. **الامتثال**: سجل تدقيق شامل لعمليات الوصول إلى بيانات المستخدم/المجموعة. + +## الخلاصة + +يوفر النهج القائم على التصفية المستندة إلى الخصائص أفضل توازن بين الأمان والأداء وقابلية الصيانة لإضافة عزل المستخدم/المجموعة إلى Neo4j. إنه يتماشى مع أنماط متعددة المستأجرين الحالية في TrustGraph مع الاستفادة من نقاط قوة Neo4j في استعلامات الرسم البياني والفهرسة. + +تضمن هذه الحل أن يلبي الخلفية Neo4 لـ TrustGraph نفس معايير الأمان مثل الأنظمة الخلفية الأخرى للتخزين، مما يمنع ثغرات أمنية لعزل البيانات مع الحفاظ على المرونة وقوة استعلامات الرسم البياني. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.es.md b/docs/tech-specs/neo4j-user-collection-isolation.es.md new file mode 100644 index 00000000..04809e08 --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.es.md @@ -0,0 +1,217 @@ +--- +layout: default +title: "Soporte de aislamiento de usuarios/colecciones en Neo4j" +parent: "Spanish (Beta)" +--- + +# Soporte de aislamiento de usuarios/colecciones en Neo4j + +> **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. + +## Declaración del problema + +La implementación actual de almacenamiento y consulta de triples en Neo4j carece de aislamiento de usuarios/colecciones, lo que genera una vulnerabilidad de seguridad para entornos multi-inquilinos. Todos los triples se almacenan en el mismo espacio de grafo sin ningún mecanismo para evitar que los usuarios accedan a los datos de otros usuarios o mezclen colecciones. + +A diferencia de otros backends de almacenamiento en TrustGraph: +- **Cassandra**: Utiliza espacios de claves y tablas separados por usuario y colección +- **Almacenes vectoriales** (Milvus, Qdrant, Pinecone): Utilizan espacios de nombres específicos de la colección +- **Neo4j**: Actualmente comparte todos los datos en un único grafo (vulnerabilidad de seguridad) + +## Arquitectura actual + +### Modelo de datos +- **Nodos**: Etiqueta `:Node` con propiedad `uri`, etiqueta `:Literal` con propiedad `value` +- **Relaciones**: Etiqueta `:Rel` con propiedad `uri` +- **Índices**: `Node.uri`, `Literal.value`, `Rel.uri` + +### Flujo de mensajes +- Los mensajes `Triples` contienen los campos `metadata.user` y `metadata.collection` +- El servicio de almacenamiento recibe la información del usuario/colección, pero la ignora +- El servicio de consulta espera `user` y `collection` en `TriplesQueryRequest`, pero los ignora + +### Problema de seguridad actual +```cypher +# Cualquier usuario puede consultar cualquier dato - sin aislamiento +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## Solución propuesta: Filtrado basado en propiedades (Recomendado) + +### Descripción general +Añadir las propiedades `user` y `collection` a todos los nodos y relaciones, y luego filtrar todas las operaciones por estas propiedades. Este enfoque proporciona un fuerte aislamiento manteniendo la flexibilidad de consulta y la compatibilidad con versiones anteriores. + +### Cambios en el modelo de datos + +#### Estructura de nodos mejorada +```cypher +// Entidades de nodo +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// Entidades de literal +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### Estructura de relaciones mejorada +```cypher +// Relaciones con propiedades user/collection +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### Índices actualizados +```cypher +// Índices compuestos para un filtrado eficiente +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// Mantener índices existentes para la compatibilidad con versiones anteriores (opcional) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### Cambios de implementación + +#### Servicio de almacenamiento (`write.py`) + +**Código actual:** +```python +def create_node(self, uri): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, database_=self.db, + ).summary +``` + +**Código actualizado:** +```python +def create_node(self, uri, user, collection): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri, user: $user, collection: $collection})", + uri=uri, user=user, collection=collection, database_=self.db, + ).summary +``` + +#### Función query +```python +def query_triples(self, query): + # Implementar lógica para filtrar por usuario y colección en la consulta + # Por ejemplo, reemplazar 'user' y 'collection' en la consulta + # Usar la función de ejecución de consultas de Neo4j para reemplazar + # los marcadores de posición con los valores del usuario y la colección + # y luego ejecutar la consulta. + # Ejemplo (pseudocódigo): + # resultado = neo4j.execute_query(query.replace("user", self.user), self.collection) + # return resultado + pass +``` + +#### Función store_triples +```python +def store_triples(self, triples): + # Implementar lógica para almacenar triples con las propiedades user y collection + # Por ejemplo, añadir las propiedades user y collection a los nodos al crear + # nuevos nodos y relaciones. + pass +``` + +### Pruebas + +### Pruebas unitarias +```python +def test_user_collection_isolation(): + # Almacenar triples para user1/collection1 + processor.store_triples(triples_user1_coll1) + + # Almacenar triples para user2/collection2 + processor.store_triples(triples_user2_coll2) + + # Consultar como user1 solo debería devolver datos de user1/collection1 + resultados = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(resultados) + + # Consultar como user2 solo debería devolver datos de user2/collection2 + resultados = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(resultados) +``` + +### Pruebas de integración +- Escenarios de múltiples usuarios con datos superpuestos +- Consultas de cross-colección (deberían fallar) +- Pruebas de migración con datos existentes +- Pruebas de rendimiento con grandes conjuntos de datos + +### Pruebas de seguridad +- Intentar consultar datos de otros usuarios +- Ataques de inyección SQL en parámetros de usuario/colección +- Verificar el aislamiento completo bajo diferentes patrones de consulta + +## Consideraciones de rendimiento + +### Estrategia de índice +- Índices compuestos en `(user, collection, uri)` para un filtrado óptimo +- Considerar índices parciales si algunas colecciones son mucho más grandes +- Supervisar el uso y el rendimiento de los índices + +### Optimización de consultas +- Utilizar EXPLAIN para verificar el uso de índices en las consultas filtradas +- Considerar el almacenamiento en caché de resultados para datos accedidos con frecuencia +- Perfilar el uso de memoria con un gran número de usuarios/colecciones + +### Escalabilidad +- Cada combinación de usuario/colección crea islas de datos separadas +- Supervisar el tamaño de la base de datos y el uso de la piscina de conexiones +- Considerar estrategias de escalado horizontal si es necesario + +## Seguridad y cumplimiento + +### Garantías de aislamiento de datos +- **Físico**: Todos los datos del usuario almacenados con propiedades de usuario/colección explícitas +- **Lógico**: Todas las consultas filtradas por contexto de usuario/colección +- **Control de acceso**: Validación a nivel de servicio para evitar el acceso no autorizado + +### Requisitos de auditoría +- Registrar todos los accesos de datos con contexto de usuario/colección +- Rastrear las actividades de migración y los movimientos de datos +- Supervisar los intentos de violar el aislamiento + +### Consideraciones de cumplimiento +- GDPR: Mayor capacidad para localizar y eliminar datos específicos del usuario +- SOC2: Claros controles de aislamiento de datos y acceso +- HIPAA: Fuerte aislamiento de inquilinos para datos de atención médica + +## Riesgos y mitigaciones + +| Riesgo | Impacto | Probabilidad | Mitigación | +|------|--------|------------|------------| +| Consulta sin filtro de usuario/colección | Alto | Medio | Validación obligatoria, pruebas exhaustivas | +| Degradación del rendimiento | Medio | Bajo | Optimización del índice, perfilado de consultas | +| Corrupción de datos durante la migración | Alto | Bajo | Estrategia de copia de seguridad, procedimientos de reversión | +| Complejidad de consultas multi-colección | Medio | Medio | Documentar los patrones de consulta, proporcionar ejemplos | + +## Criterios de éxito + +1. **Seguridad**: Cero acceso de datos cruzado de usuarios en producción +2. **Rendimiento**: <10% de impacto en el rendimiento de las consultas en comparación con las consultas no filtradas +3. **Migración**: 100% de los datos existentes migrados sin pérdida de datos +4. **Usabilidad**: Todos los patrones de consulta existentes funcionan con contexto de usuario/colección +5. **Cumplimiento**: Rastro de auditoría completo del acceso de datos de usuario/colección + +## Conclusión + +El enfoque de filtrado basado en propiedades proporciona el mejor equilibrio de seguridad, rendimiento y mantenibilidad para añadir aislamiento de usuarios/colecciones a Neo4j. Se alinea con los patrones de multi-inquilinos existentes de TrustGraph al tiempo que aprovecha las fortalezas de Neo4j en la consulta y el indexado de grafos. + +Esta solución garantiza que el backend de Neo4j de TrustGraph cumpla con los mismos estándares de seguridad que otros backends de almacenamiento, evitando las vulnerabilidades de aislamiento de datos al tiempo que mantiene la flexibilidad y el poder de las consultas de grafos. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.he.md b/docs/tech-specs/neo4j-user-collection-isolation.he.md new file mode 100644 index 00000000..a2100e8f --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.he.md @@ -0,0 +1,196 @@ +--- +layout: default +title: "תמיכה ביסודות משתמשים/מערכות ב-Neo4j" +parent: "Hebrew (Beta)" +--- + +# תמיכה ביסודות משתמשים/מערכות ב-Neo4j + +> **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. + +## הצגת הבעיה + +המימוש הנוכחי של אחסון שאילתות ב-Neo4j סובל מחוסר ביסודות משתמשים/מערכות, מה שיוצר בעיות אבטחה במצב רב-משתמשים. כל השלישים מאוחסנים במרחב גרף אחד ללא מנגנון למניעת משתמשים מגישה לנתונים של משתמשים אחרים או מיזוג מערכות. + +בניגוד למערכות אחסון אחרות ב-TrustGraph: +- **Cassandra**: משתמשת במרחבי מפתחות נפרדים לכל משתמש וטבלאות לכל מערכת +- **אחסון וקטורי** (Milvus, Qdrant, Pinecone): משתמשים בשמות מרחבים ספציפיים למערכות +- **Neo4j**: כיום, משתמשת בכל הנתונים במרחב גרף אחד (פגיעות אבטחה) + +## ארכיטקטורה נוכחית + +### מודל נתונים +- **צמתים**: תוויות `:Node` עם תכונה `uri`, תוויות `:Literal` עם תכונה `value` +- **קשרים**: תוויות `:Rel` עם תכונת `uri` +- **אינדקסים**: `Node.uri`, `Literal.value`, `Rel.uri` + +### זרימת הודעות +- הודעות `Triples` מכילות שדות `metadata.user` ו-`metadata.collection` +- שירות האחסון מקבל מידע על משתמשים/מערכות אך מתעלם ממנו +- שירות השאילתות מצפה לשדות `user` ו-`collection` בבקשת `TriplesQueryRequest` אך מתעלם מהם + +### בעיית אבטחה נוכחית +```cypher +# כל משתמש יכול לשאול כל נתונים - אין ביסודות +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## פתרון מוצע: סינון מבוסס תכונות (מומלץ) + +### סקירה כללית +הוסף תכונות `user` ו-`collection` לכל הצמתים והקשרים, ואז לסנן את כל הפעולות לפי התכונות הללו. גישה זו מספקת ביסודות חזקות תוך שמירה על גמישות שאילתות והתאמה לגרסאות קודמות. + +### שינויים במודל נתונים + +#### מבנה צומת משופר +```cypher +// ישויות צומת +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// ישויות Literal +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### מבנה קשר משופר +```cypher +// קשרים עם תכונות משתמש/מערכת +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### אינדקסים מעודכנים +```cypher +// אינדקסים משולבים לסינון יעיל +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// שמירה על אינדקסים קיימים לאחור התאמה (אופציונלי) +``` + +## תוכנית יישום + +### שלב 1: יסודות (שבוע 1) +1. [ ] עדכן את שירות האחסון לקבל ולשמור תכונות משתמש/מערכת +2. [ ] הוסף אינדקסים משולבים לביצוע שאילתות מיטבי +3. [ ] יישם שכבת התאמה לגרסאות קודמות +4. [ ] צור בדיקות יחידה לפונקציונליות החדשה + +### שלב 2: עדכוני שאילתות (שבוע 2) +1. [ ] עדכן את כל דפוסי השאילתות כדי לכלול סינון משתמש/מערכת +2. [ ] הוסף אימות שאילתות ובקרת אבטחה +3. [ ] עדכן בדיקות אינטגרציה +4. [ ] בדיקות ביצוע עם שאילתות מסוננות + +### שלב 3: העברה והפצה (שבוע 3) +1. [ ] צור סקריפטים להעברת נתונים עבור מופעי Neo4j קיימים +2. [ ] תיעוד והוראות הפעלה +3. [ ] ניטור והתראות על הפרות ביסודות +4. [ ] בדיקות סיום עם מספר משתמשים/מערכות + +### שלב 4: חיזוק (שבוע 4) +1. [ ] הסר את מצב ההתאמה לגרסאות קודמות +2. [ ] הוסף רישום ביקורת מקיף +3. [ ] ביקורת אבטחה וגישה +4. [ ] בדיקות ביצוע + +## אסטרטגיית בדיקה + +### בדיקות יחידה +```python +def test_user_collection_isolation(): + # שמור שליש עבור משתמש1/מערכת1 + processor.store_triples(triples_user1_coll1) + + # שמור שליש עבור משתמש2/מערכת2 + processor.store_triples(triples_user2_coll2) + + # שאילת משתמש1 צריך רק להחזיר את הנתונים של משתמש1 + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # שאילת משתמש2 צריך רק להחזיר את הנתונים של משתמש2 + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### בדיקות אינטגרציה +- תרחישים רב-משתמשים עם נתונים חופפים +- שאילתות בין מערכות (צריכות להיכשל) +- בדיקות העברה עם נתונים קיימים +- ביצועים - שורה עם מערכות נתונים גדולות + +### בדיקות אבטחה +- ניסיון לשאול נתונים של משתמשים אחרים +- התקפות SQL על פרמטרים של משתמש/מערכת +- אימות של ביסודות תחת דפוסי שאילתות שונים + +## שיקולי ביצועים + +### אסטרטגיית אינדקס +- אינדקסים משולבים על `(user, collection, uri)` לביצוע שאילתות מיטבי +- שקול אינדקסים חלקיים אם יש למערכות רבות יותר גודל גדול +- עקוב אחר שימוש באינדקס וביצוע שאילתות + +### אופטימיזציה של שאילתות +- השתמש ב-EXPLAIN כדי לוודא שימוש באינדקס בשאילתות מסוננות +- שקול אחסון תוצאות שאילתות לשימוש חוזר +- פרופיל שימוש בזיכרון עם מספר משתמשים/מערכות גדולים + +### סקלאביליות +- כל מערכת משתמשים/מערכת יוצרת איזולציה נפרדת של נתונים +- עקוב אחר גודל מסד הנתונים ושימוש בבריאת חיבורים +- שקול אסטרטגיות סקלאביליות אופקיות במידת הצורך + +## אבטחה ותאימות + +### ביסודות נתונים +- **פיזי**: כל הנתונים של משתמש מאוחסנים עם תכונות משתמש/מערכת ספציפיות +- **לוגי**: כל השאילתות מסוננות על ידי הקשר משתמש/מערכת +- **בקרה**: שכבת שירות מאמתת גישה + +### דרישות ביקורת +- רשום את כל גישה לנתונים עם הקשר משתמש/מערכת +- עקוב אחר פעילויות העברה +- עקוב אחר ניסיונות הפרות ביסודות + +### שיקולים תאימות +- GDPR: יכולת טובה יותר למצוא ולמחוק נתונים ספציפיים למשתמשים +- SOC2: בקרה בסיסית וגישה של משתמשים +- HIPAA: ביסודות חזקים עבור נתונים בתחום הבריאות + +## סיכונים ותיקונים + +| סיכון | השפעה | הסתברות | תיקון | +|------|--------|------------|------------| +| שאילתות חסרות סינון משתמש/מערכת | גבוה | בינונית | אימות חובה, בדיקות מקיפות | +| ירידה בביצועים | בינונית | נמוכה | אופטימיזציה של אינדקס, פרופיל שאילתות | +| אובדן נתונים בהעברה | גבוה | נמוכה | אסטרטגיית גיבוי, פרוצדורות שלבים אחורה | +| קשיים בהתאמה לגרסאות קודמות | בינונית | בינונית | תוכנית יישום, תיעוד | +| קשיים בביצוע שאילתות מורכבות | בינונית | בינונית | תיעוד דפוסי שאילתות | + +## קריטריוני הצלחה + +1. **אבטחה**: אין גישה בין משתמשים בייצור +2. **ביצועים**: <10% השפעה על ביצועי השאילתות בהשוואה לשאילתות לא מסוננות +3. **העברה**: 100% נתונים קיימים מוצלחים בהעברה ללא אובדן +4. **שימושיות**: כל דפוסי השאילתות הקיימים עובדים עם הקשר משתמש/מערכת +5. **תאימות**: תיעוד מלא של גישה לנתונים מבוסס משתמש/מערכת + +## מסקנה + +הגישה המבוססת על תכונות מספקת את האיזון הטוב ביותר של אבטחה, ביצועים וקלות תחזוקה להוספת ביסודות משתמשים/מערכות ב-Neo4j. היא תואמת עם דפוסי הרב-משתמשים הקיימים ב-TrustGraph תוך ניצול החוזקות של Neo4j בשאילתות גרפים ואינדקסים. + +פתרון זה מבטיח שהבסיס של ה-Neo4j ב-TrustGraph עומד בסטנדרטים אבטחיים כמו מערכות אחסון אחרות, ומספק ביסודות תוך שמירה על גמישות וגודל שאילתות. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.hi.md b/docs/tech-specs/neo4j-user-collection-isolation.hi.md new file mode 100644 index 00000000..44752502 --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.hi.md @@ -0,0 +1,367 @@ +--- +layout: default +title: "नियो4जे उपयोगकर्ता/संग्रह अलगाव समर्थन" +parent: "Hindi (Beta)" +--- + +# नियो4जे उपयोगकर्ता/संग्रह अलगाव समर्थन + +> **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. + +## समस्या विवरण + +नियो4जे का त्रिगुट भंडारण और क्वेरी कार्यान्वयन वर्तमान में उपयोगकर्ता/संग्रह अलगाव की कमी रखता है, जो एक बहु-किरायेदारी सुरक्षा समस्या पैदा करता है। सभी त्रिगुट एक ही ग्राफ स्पेस में संग्रहीत होते हैं, बिना किसी ऐसी तंत्र के जो उपयोगकर्ताओं को अन्य उपयोगकर्ताओं के डेटा तक पहुंचने या संग्रहों को मिलाने से रोकता हो। + +ट्रस्टग्राफ में अन्य स्टोरेज बैकएंड के विपरीत: +**कैसेंड्रा**: प्रत्येक उपयोगकर्ता के लिए अलग-अलग कीस्पेस और प्रत्येक संग्रह के लिए टेबल का उपयोग करता है। +**वेक्टर स्टोर** (मिलवस, क्यूड्रांट, पाइनकोन): संग्रह-विशिष्ट नेमस्पेस का उपयोग करते हैं। +**नियो4जे**: वर्तमान में सभी डेटा को एक ही ग्राफ में साझा करता है (सुरक्षा भेद्यता)। + +## वर्तमान आर्किटेक्चर + +### डेटा मॉडल +**नोड्स**: `:Node` लेबल के साथ `uri` प्रॉपर्टी, `:Literal` लेबल के साथ `value` प्रॉपर्टी। +**रिलेशनशिप्स**: `:Rel` लेबल के साथ `uri` प्रॉपर्टी। +**इंडेक्स**: `Node.uri`, `Literal.value`, `Rel.uri`। + +### संदेश प्रवाह +`Triples` संदेशों में `metadata.user` और `metadata.collection` फ़ील्ड होते हैं। +स्टोरेज सेवा उपयोगकर्ता/संग्रह जानकारी प्राप्त करती है लेकिन इसे अनदेखा करती है। +क्वेरी सेवा `TriplesQueryRequest` में `user` और `collection` की अपेक्षा करती है लेकिन उन्हें अनदेखा करती है। + +### वर्तमान सुरक्षा समस्या +```cypher +# Any user can query any data - no isolation +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## प्रस्तावित समाधान: प्रॉपर्टी-आधारित फ़िल्टरिंग (अनुशंसित) + +### अवलोकन +सभी नोड्स और संबंधों में `user` और `collection` प्रॉपर्टीज़ जोड़ें, और फिर सभी ऑपरेशन्स को इन प्रॉपर्टीज़ के आधार पर फ़िल्टर करें। यह दृष्टिकोण मजबूत अलगाव प्रदान करता है, जबकि क्वेरी लचीलापन और पिछड़े अनुकूलता को बनाए रखता है। + +### डेटा मॉडल परिवर्तन + +#### उन्नत नोड संरचना +```cypher +// Node entities +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// Literal entities +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### उन्नत संबंध संरचना +```cypher +// Relationships with user/collection properties +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### अद्यतित अनुक्रमणिकाएँ +```cypher +// Compound indexes for efficient filtering +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// Maintain existing indexes for backwards compatibility (optional) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### कार्यान्वयन में परिवर्तन + +#### स्टोरेज सर्विस (`write.py`) + +**वर्तमान कोड:** +```python +def create_node(self, uri): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, database_=self.db, + ).summary +``` + +**अद्यतित कोड:** +```python +def create_node(self, uri, user, collection): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri, user: $user, collection: $collection})", + uri=uri, user=user, collection=collection, database_=self.db, + ).summary +``` + +**बेहतर `store_triples` विधि:** +```python +async def store_triples(self, message): + user = message.metadata.user + collection = message.metadata.collection + + for t in message.triples: + self.create_node(t.s.value, user, collection) + + if t.o.is_uri: + self.create_node(t.o.value, user, collection) + self.relate_node(t.s.value, t.p.value, t.o.value, user, collection) + else: + self.create_literal(t.o.value, user, collection) + self.relate_literal(t.s.value, t.p.value, t.o.value, user, collection) +``` + +#### क्वेरी सर्विस (`service.py`) + +**वर्तमान कोड:** +```python +records, summary, keys = self.io.execute_query( + "MATCH (src:Node {uri: $src})-[rel:Rel {uri: $rel}]->(dest:Node) " + "RETURN dest.uri as dest", + src=query.s.value, rel=query.p.value, database_=self.db, +) +``` + +**अद्यतित कोड:** +```python +records, summary, keys = self.io.execute_query( + "MATCH (src:Node {uri: $src, user: $user, collection: $collection})-" + "[rel:Rel {uri: $rel, user: $user, collection: $collection}]->" + "(dest:Node {user: $user, collection: $collection}) " + "RETURN dest.uri as dest", + src=query.s.value, rel=query.p.value, + user=query.user, collection=query.collection, + database_=self.db, +) +``` + +### माइग्रेशन रणनीति + +#### चरण 1: नए डेटा में गुण जोड़ें +1. स्टोरेज सर्विस को अपडेट करें ताकि नए त्रिगुणों में उपयोगकर्ता/संग्रह गुण जोड़े जा सकें। +2. पिछली अनुकूलता बनाए रखें, क्योंकि प्रश्नों में गुणों की आवश्यकता नहीं होगी। +3. मौजूदा डेटा सुलभ रहेगा, लेकिन अलग नहीं होगा। + +#### चरण 2: मौजूदा डेटा का माइग्रेशन +```cypher +// Migrate existing nodes (requires default user/collection assignment) +MATCH (n:Node) WHERE n.user IS NULL +SET n.user = 'legacy_user', n.collection = 'default_collection'; + +MATCH (n:Literal) WHERE n.user IS NULL +SET n.user = 'legacy_user', n.collection = 'default_collection'; + +MATCH ()-[r:Rel]->() WHERE r.user IS NULL +SET r.user = 'legacy_user', r.collection = 'default_collection'; +``` + +#### चरण 3: अलगाव को लागू करना +1. क्वेरी सेवा को अपडेट करें ताकि उपयोगकर्ता/संग्रह फ़िल्टरिंग की आवश्यकता हो +2. उचित उपयोगकर्ता/संग्रह संदर्भ के बिना क्वेरी को अस्वीकार करने के लिए सत्यापन जोड़ें +3. पुराने डेटा एक्सेस पथ को हटा दें + +### सुरक्षा संबंधी विचार + +#### क्वेरी सत्यापन +```python +async def query_triples(self, query): + # Validate user/collection parameters + if not query.user or not query.collection: + raise ValueError("User and collection must be specified") + + # All queries must include user/collection filters + # ... rest of implementation +``` + +#### पैरामीटर इंजेक्शन को रोकना +केवल पैरामीटराइज़्ड क्वेरी का उपयोग करें। +उपयोगकर्ता/संग्रह मूल्यों को स्वीकृत पैटर्न के विरुद्ध मान्य करें। +Neo4j प्रॉपर्टी नाम आवश्यकताओं के लिए सैनिटाइजेशन पर विचार करें। + +#### ऑडिट ट्रेल +```python +logger.info(f"Query executed - User: {query.user}, Collection: {query.collection}, " + f"Pattern: {query.s}/{query.p}/{query.o}") +``` + +## वैकल्पिक दृष्टिकोणों पर विचार + +### विकल्प 2: लेबल-आधारित अलगाव + +**दृष्टिकोण**: गतिशील लेबल का उपयोग करें जैसे `User_john_Collection_prod` + +**लाभ:** +लेबल फ़िल्टरिंग के माध्यम से मजबूत अलगाव +लेबल इंडेक्स के साथ कुशल क्वेरी प्रदर्शन +स्पष्ट डेटा पृथक्करण + +**नुकसान:** +Neo4j में लेबल की संख्या पर व्यावहारिक सीमाएं हैं (~1000) +जटिल लेबल नाम पीढ़ी और सैनिटाइजेशन +जब आवश्यक हो तो संग्रहों में क्वेरी करना मुश्किल होता है + +**कार्यान्वयन उदाहरण:** +```cypher +CREATE (n:Node:User_john_Collection_prod {uri: "http://example.com/entity"}) +MATCH (n:User_john_Collection_prod) WHERE n:Node RETURN n +``` + +### विकल्प 3: प्रति-उपयोगकर्ता डेटाबेस + +**दृष्टिकोण**: प्रत्येक उपयोगकर्ता या उपयोगकर्ता/संग्रह संयोजन के लिए अलग-अलग Neo4j डेटाबेस बनाएं। + +**लाभ:** +पूर्ण डेटा अलगाव +क्रॉस-संदूषण का कोई जोखिम नहीं +प्रति-उपयोगकर्ता स्वतंत्र स्केलिंग + +**नुकसान:** +संसाधन ओवरहेड (प्रत्येक डेटाबेस मेमोरी का उपयोग करता है) +जटिल डेटाबेस जीवनचक्र प्रबंधन +Neo4j कम्युनिटी एडिशन डेटाबेस सीमाएं +उपयोगकर्ताओं के बीच विश्लेषण करना मुश्किल + +### विकल्प 4: समग्र कुंजी रणनीति + +**दृष्टिकोण**: सभी URIs और मानों को उपयोगकर्ता/संग्रह जानकारी के साथ उपसर्ग करें। + +**लाभ:** +मौजूदा प्रश्नों के साथ संगत +सरल कार्यान्वयन +कोई स्कीमा परिवर्तन आवश्यक नहीं + +**नुकसान:** +URI प्रदूषण डेटा अर्थशास्त्र को प्रभावित करता है +कम कुशल प्रश्न (स्ट्रिंग उपसर्ग मिलान) +RDF/सिमेंटिक वेब मानकों का उल्लंघन + +**कार्यान्वयन उदाहरण:** +```python +def make_composite_uri(uri, user, collection): + return f"usr:{user}:col:{collection}:uri:{uri}" +``` + +## कार्यान्वयन योजना + +### चरण 1: आधार (सप्ताह 1) +1. [ ] स्टोरेज सेवा को उपयोगकर्ता/संग्रह गुणों को स्वीकार करने और संग्रहीत करने के लिए अपडेट करें। +2. [ ] कुशल क्वेरी के लिए कंपाउंड इंडेक्स जोड़ें। +3. [ ] पिछड़े अनुकूलता परत लागू करें। +4. [ ] नई कार्यक्षमता के लिए यूनिट परीक्षण बनाएं। + +### चरण 2: क्वेरी अपडेट (सप्ताह 2) +1. [ ] सभी क्वेरी पैटर्न को उपयोगकर्ता/संग्रह फ़िल्टर शामिल करने के लिए अपडेट करें। +2. [ ] क्वेरी सत्यापन और सुरक्षा जांच जोड़ें। +3. [ ] एकीकरण परीक्षण अपडेट करें। +4. [ ] फ़िल्टर किए गए प्रश्नों के साथ प्रदर्शन परीक्षण। + +### चरण 3: माइग्रेशन और परिनियोजन (सप्ताह 3) +1. [ ] मौजूदा Neo4j उदाहरणों के लिए डेटा माइग्रेशन स्क्रिप्ट बनाएं। +2. [ ] परिनियोजन दस्तावेज़ और रनबुक। +3. [ ] अलगाव उल्लंघनों के लिए निगरानी और अलर्ट। +4. [ ] कई उपयोगकर्ताओं/संग्रहों के साथ एंड-टू-एंड परीक्षण। + +### चरण 4: मजबूती (सप्ताह 4) +1. [ ] विरासत अनुकूलता मोड हटाएं। +2. [ ] व्यापक ऑडिट लॉगिंग जोड़ें। +3. [ ] सुरक्षा समीक्षा और प्रवेश परीक्षण। +4. [ ] प्रदर्शन अनुकूलन। + +## परीक्षण रणनीति + +### यूनिट परीक्षण +```python +def test_user_collection_isolation(): + # Store triples for user1/collection1 + processor.store_triples(triples_user1_coll1) + + # Store triples for user2/collection2 + processor.store_triples(triples_user2_coll2) + + # Query as user1 should only return user1's data + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # Query as user2 should only return user2's data + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### एकीकरण परीक्षण (एकीकरण परीक्षण) +मल्टी-यूजर परिदृश्य जिसमें ओवरलैपिंग डेटा शामिल है +क्रॉस-कलेक्शन क्वेरी (विफल होनी चाहिए) +मौजूदा डेटा के साथ माइग्रेशन परीक्षण +बड़े डेटासेट के साथ प्रदर्शन बेंचमार्क + +### सुरक्षा परीक्षण (सुरक्षा परीक्षण) +अन्य उपयोगकर्ताओं के डेटा को क्वेरी करने का प्रयास +उपयोगकर्ता/कलेक्शन पैरामीटर पर SQL इंजेक्शन-शैली के हमले +विभिन्न क्वेरी पैटर्न के तहत पूर्ण अलगाव को सत्यापित करें + +## प्रदर्शन संबंधी विचार (प्रदर्शन संबंधी विचार) + +### इंडेक्स रणनीति (इंडेक्स रणनीति) +इष्टतम फ़िल्टरिंग के लिए `(user, collection, uri)` पर कंपाउंड इंडेक्स +यदि कुछ संग्रह बहुत बड़े हैं तो आंशिक इंडेक्स पर विचार करें +इंडेक्स उपयोग और क्वेरी प्रदर्शन की निगरानी करें + +### क्वेरी अनुकूलन (क्वेरी अनुकूलन) +फ़िल्टर किए गए क्वेरी में इंडेक्स उपयोग को सत्यापित करने के लिए EXPLAIN का उपयोग करें +बार-बार एक्सेस किए जाने वाले डेटा के लिए क्वेरी परिणाम कैशिंग पर विचार करें +बड़ी संख्या में उपयोगकर्ताओं/संग्रहों के साथ मेमोरी उपयोग को प्रोफाइल करें + +### मापनीयता (मापनीयता) +प्रत्येक उपयोगकर्ता/संग्रह संयोजन अलग-अलग डेटा द्वीप बनाता है +डेटाबेस आकार और कनेक्शन पूल उपयोग की निगरानी करें +यदि आवश्यक हो तो क्षैतिज स्केलिंग रणनीतियों पर विचार करें + +## सुरक्षा और अनुपालन (सुरक्षा और अनुपालन) + +### डेटा अलगाव गारंटी (डेटा अलगाव गारंटी) +**भौतिक**: सभी उपयोगकर्ता डेटा स्पष्ट उपयोगकर्ता/संग्रह गुणों के साथ संग्रहीत होते हैं +**तार्किक**: सभी क्वेरी उपयोगकर्ता/संग्रह संदर्भ द्वारा फ़िल्टर की जाती हैं +**पहुंच नियंत्रण**: सेवा-स्तरीय सत्यापन अनधिकृत पहुंच को रोकता है + +### ऑडिट आवश्यकताएँ (ऑडिट आवश्यकताएँ) +उपयोगकर्ता/संग्रह संदर्भ के साथ सभी डेटा एक्सेस को लॉग करें +माइग्रेशन गतिविधियों और डेटा मूवमेंट को ट्रैक करें +अलगाव उल्लंघन के प्रयासों की निगरानी करें + +### अनुपालन संबंधी विचार (अनुपालन संबंधी विचार) +जीडीपीआर: उपयोगकर्ता-विशिष्ट डेटा को खोजने और हटाने की बेहतर क्षमता +एसओसी2: स्पष्ट डेटा अलगाव और पहुंच नियंत्रण +एचआईपीएए: स्वास्थ्य सेवा डेटा के लिए मजबूत किरायेदार अलगाव + +## जोखिम और निवारण (जोखिम और निवारण) + +| जोखिम | प्रभाव | संभावना | निवारण | +|------|--------|------------|------------| +| क्वेरी में उपयोगकर्ता/संग्रह फ़िल्टर गुम है | उच्च | मध्यम | अनिवार्य सत्यापन, व्यापक परीक्षण +| प्रदर्शन में गिरावट | मध्यम | कम | इंडेक्स अनुकूलन, क्वेरी प्रोफाइलिंग +| माइग्रेशन डेटा भ्रष्टाचार | उच्च | कम | बैकअप रणनीति, रोलबैक प्रक्रियाएं +| जटिल मल्टी-कलेक्शन क्वेरी | मध्यम | मध्यम | क्वेरी पैटर्न को दस्तावेज़ करें, उदाहरण प्रदान करें + +## सफलता मानदंड (सफलता मानदंड) + +1. **सुरक्षा**: उत्पादन में क्रॉस-यूजर डेटा एक्सेस शून्य +2. **प्रदर्शन**: अनफ़िल्टर किए गए क्वेरी की तुलना में <10% क्वेरी प्रदर्शन प्रभाव +3. **माइग्रेशन**: 100% मौजूदा डेटा बिना किसी नुकसान के सफलतापूर्वक माइग्रेट किया गया +4. **उपयोगिता**: सभी मौजूदा क्वेरी पैटर्न उपयोगकर्ता/संग्रह संदर्भ के साथ काम करते हैं +5. **अनुपालन**: उपयोगकर्ता/संग्रह डेटा एक्सेस का पूर्ण ऑडिट ट्रेल + +## निष्कर्ष (निष्कर्ष) + +संपत्ति-आधारित फ़िल्टरिंग दृष्टिकोण उपयोगकर्ता/संग्रह अलगाव को Neo4j में जोड़ने के लिए सुरक्षा, प्रदर्शन और रखरखाव के बीच सबसे अच्छा संतुलन प्रदान करता है। यह Neo4j की ग्राफ क्वेरी और इंडेक्सिंग में ताकत का लाभ उठाते हुए TrustGraph के मौजूदा मल्टी-टेनेंसी पैटर्न के साथ संरेखित है। + +यह समाधान सुनिश्चित करता है कि TrustGraph का Neo4j बैकएंड अन्य स्टोरेज बैकएंड के समान सुरक्षा मानकों को पूरा करता है, जिससे डेटा अलगाव कमजोरियों को रोका जा सकता है, जबकि ग्राफ क्वेरी की लचीलापन और शक्ति को बनाए रखा जा सकता है। diff --git a/docs/tech-specs/neo4j-user-collection-isolation.md b/docs/tech-specs/neo4j-user-collection-isolation.md index 62623c07..e515a2a4 100644 --- a/docs/tech-specs/neo4j-user-collection-isolation.md +++ b/docs/tech-specs/neo4j-user-collection-isolation.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Neo4j User/Collection Isolation Support" +parent: "Tech Specs" +--- + # Neo4j User/Collection Isolation Support ## Problem Statement @@ -356,4 +362,4 @@ def test_user_collection_isolation(): The property-based filtering approach provides the best balance of security, performance, and maintainability for adding user/collection isolation to Neo4j. It aligns with TrustGraph's existing multi-tenancy patterns while leveraging Neo4j's strengths in graph querying and indexing. -This solution ensures TrustGraph's Neo4j backend meets the same security standards as other storage backends, preventing data isolation vulnerabilities while maintaining the flexibility and power of graph queries. \ No newline at end of file +This solution ensures TrustGraph's Neo4j backend meets the same security standards as other storage backends, preventing data isolation vulnerabilities while maintaining the flexibility and power of graph queries. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.pt.md b/docs/tech-specs/neo4j-user-collection-isolation.pt.md new file mode 100644 index 00000000..d9557fe0 --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.pt.md @@ -0,0 +1,367 @@ +--- +layout: default +title: "Suporte para Isolamento de Usuário/Coleção no Neo4j" +parent: "Portuguese (Beta)" +--- + +# Suporte para Isolamento de Usuário/Coleção no Neo4j + +> **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. + +## Declaração do Problema + +A implementação atual de armazenamento e consulta de triplas do Neo4j carece de isolamento de usuário/coleção, o que cria um problema de segurança de multi-inquilinato. Todas as triplas são armazenadas no mesmo espaço de grafo sem nenhum mecanismo para impedir que os usuários acessem os dados de outros usuários ou misturem coleções. + +Ao contrário de outros backends de armazenamento no TrustGraph: +**Cassandra**: Usa key spaces separados por usuário e tabelas por coleção. +**Armazenamentos vetoriais** (Milvus, Qdrant, Pinecone): Usam namespaces específicos para cada coleção. +**Neo4j**: Atualmente compartilha todos os dados em um único grafo (vulnerabilidade de segurança). + +## Arquitetura Atual + +### Modelo de Dados +**Nós**: Rótulo `:Node` com propriedade `uri`, rótulo `:Literal` com propriedade `value`. +**Relacionamentos**: Rótulo `:Rel` com propriedade `uri`. +**Índices**: `Node.uri`, `Literal.value`, `Rel.uri`. + +### Fluxo de Mensagens +Mensagens `Triples` contêm campos `metadata.user` e `metadata.collection`. +O serviço de armazenamento recebe informações de usuário/coleção, mas as ignora. +O serviço de consulta espera `user` e `collection` em `TriplesQueryRequest`, mas os ignora. + +### Problema de Segurança Atual +```cypher +# Any user can query any data - no isolation +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## Solução Proposta: Filtragem Baseada em Propriedades (Recomendada) + +### Visão Geral +Adicione as propriedades `user` e `collection` a todos os nós e relacionamentos, e então filtre todas as operações por essas propriedades. Essa abordagem fornece um forte isolamento, mantendo a flexibilidade da consulta e a compatibilidade com versões anteriores. + +### Alterações no Modelo de Dados + +#### Estrutura de Nó Aprimorada +```cypher +// Node entities +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// Literal entities +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### Estrutura de Relacionamento Aprimorada +```cypher +// Relationships with user/collection properties +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### Índices Atualizados +```cypher +// Compound indexes for efficient filtering +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// Maintain existing indexes for backwards compatibility (optional) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### Alterações na Implementação + +#### Serviço de Armazenamento (`write.py`) + +**Código Atual:** +```python +def create_node(self, uri): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, database_=self.db, + ).summary +``` + +**Código Atualizado:** +```python +def create_node(self, uri, user, collection): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri, user: $user, collection: $collection})", + uri=uri, user=user, collection=collection, database_=self.db, + ).summary +``` + +**Método `store_triples` aprimorado:** +```python +async def store_triples(self, message): + user = message.metadata.user + collection = message.metadata.collection + + for t in message.triples: + self.create_node(t.s.value, user, collection) + + if t.o.is_uri: + self.create_node(t.o.value, user, collection) + self.relate_node(t.s.value, t.p.value, t.o.value, user, collection) + else: + self.create_literal(t.o.value, user, collection) + self.relate_literal(t.s.value, t.p.value, t.o.value, user, collection) +``` + +#### Serviço de Consulta (`service.py`) + +**Código Atual:** +```python +records, summary, keys = self.io.execute_query( + "MATCH (src:Node {uri: $src})-[rel:Rel {uri: $rel}]->(dest:Node) " + "RETURN dest.uri as dest", + src=query.s.value, rel=query.p.value, database_=self.db, +) +``` + +**Código Atualizado:** +```python +records, summary, keys = self.io.execute_query( + "MATCH (src:Node {uri: $src, user: $user, collection: $collection})-" + "[rel:Rel {uri: $rel, user: $user, collection: $collection}]->" + "(dest:Node {user: $user, collection: $collection}) " + "RETURN dest.uri as dest", + src=query.s.value, rel=query.p.value, + user=query.user, collection=query.collection, + database_=self.db, +) +``` + +### Estratégia de Migração + +#### Fase 1: Adicionar Propriedades a Novos Dados +1. Atualizar o serviço de armazenamento para adicionar propriedades de usuário/coleção a novas triplas. +2. Manter a compatibilidade com versões anteriores, não exigindo propriedades nas consultas. +3. Os dados existentes permanecem acessíveis, mas não isolados. + +#### Fase 2: Migrar Dados Existentes +```cypher +// Migrate existing nodes (requires default user/collection assignment) +MATCH (n:Node) WHERE n.user IS NULL +SET n.user = 'legacy_user', n.collection = 'default_collection'; + +MATCH (n:Literal) WHERE n.user IS NULL +SET n.user = 'legacy_user', n.collection = 'default_collection'; + +MATCH ()-[r:Rel]->() WHERE r.user IS NULL +SET r.user = 'legacy_user', r.collection = 'default_collection'; +``` + +#### Fase 3: Impor Isolamento +1. Atualizar o serviço de consulta para exigir filtragem por usuário/coleção. +2. Adicionar validação para rejeitar consultas sem o contexto adequado de usuário/coleção. +3. Remover caminhos de acesso a dados legados. + +### Considerações de Segurança + +#### Validação de Consulta +```python +async def query_triples(self, query): + # Validate user/collection parameters + if not query.user or not query.collection: + raise ValueError("User and collection must be specified") + + # All queries must include user/collection filters + # ... rest of implementation +``` + +#### Prevenção de Injeção de Parâmetros +Use exclusivamente consultas parametrizadas +Valide os valores do usuário/coleção em relação a padrões permitidos +Considere a sanitização para os requisitos de nomes de propriedades do Neo4j + +#### Rastreamento de Auditoria +```python +logger.info(f"Query executed - User: {query.user}, Collection: {query.collection}, " + f"Pattern: {query.s}/{query.p}/{query.o}") +``` + +## Abordagens Alternativas Consideradas + +### Opção 2: Isolamento Baseado em Rótulos + +**Abordagem**: Utilize rótulos dinâmicos como `User_john_Collection_prod` + +**Vantagens:** +Forte isolamento através da filtragem de rótulos +Desempenho de consulta eficiente com índices de rótulos +Separação clara de dados + +**Desvantagens:** +O Neo4j possui limites práticos no número de rótulos (aproximadamente 1000) +Geração e sanitização complexas de nomes de rótulos +Difícil consultar entre coleções quando necessário + +**Exemplo de Implementação:** +```cypher +CREATE (n:Node:User_john_Collection_prod {uri: "http://example.com/entity"}) +MATCH (n:User_john_Collection_prod) WHERE n:Node RETURN n +``` + +### Opção 3: Banco de Dados por Usuário + +**Abordagem**: Criar bancos de dados Neo4j separados para cada usuário ou combinação de usuário/coleção. + +**Vantagens:** +Isolamento completo de dados +Sem risco de contaminação cruzada +Escalonamento independente por usuário + +**Desvantagens:** +Sobrecarga de recursos (cada banco de dados consome memória) +Gerenciamento complexo do ciclo de vida do banco de dados +Limites do banco de dados da Edição Community do Neo4j +Análise entre usuários difícil + +### Opção 4: Estratégia de Chave Composta + +**Abordagem**: Prefixar todos os URIs e valores com informações do usuário/coleção. + +**Vantagens:** +Compatível com consultas existentes +Implementação simples +Não requer alterações no esquema + +**Desvantagens:** +A poluição de URIs afeta a semântica dos dados +Consultas menos eficientes (correspondência de prefixo de string) +Viola padrões RDF/web semântico + +**Exemplo de Implementação:** +```python +def make_composite_uri(uri, user, collection): + return f"usr:{user}:col:{collection}:uri:{uri}" +``` + +## Plano de Implementação + +### Fase 1: Fundação (Semana 1) +1. [ ] Atualizar o serviço de armazenamento para aceitar e armazenar propriedades de usuário/coleção +2. [ ] Adicionar índices compostos para consultas eficientes +3. [ ] Implementar uma camada de compatibilidade retroativa +4. [ ] Criar testes unitários para novas funcionalidades + +### Fase 2: Atualizações de Consulta (Semana 2) +1. [ ] Atualizar todos os padrões de consulta para incluir filtros de usuário/coleção +2. [ ] Adicionar validação de consulta e verificações de segurança +3. [ ] Atualizar testes de integração +4. [ ] Testes de desempenho com consultas filtradas + +### Fase 3: Migração e Implantação (Semana 3) +1. [ ] Criar scripts de migração de dados para instâncias Neo4j existentes +2. [ ] Documentação de implantação e manuais de operação +3. [ ] Monitoramento e alertas para violações de isolamento +4. [ ] Testes de ponta a ponta com vários usuários/coleções + +### Fase 4: Reforço (Semana 4) +1. [ ] Remover o modo de compatibilidade legado +2. [ ] Adicionar registro de auditoria abrangente +3. [ ] Revisão de segurança e testes de penetração +4. [ ] Otimização de desempenho + +## Estratégia de Testes + +### Testes Unitários +```python +def test_user_collection_isolation(): + # Store triples for user1/collection1 + processor.store_triples(triples_user1_coll1) + + # Store triples for user2/collection2 + processor.store_triples(triples_user2_coll2) + + # Query as user1 should only return user1's data + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # Query as user2 should only return user2's data + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### Testes de Integração +Cenários multiusuário com dados sobrepostos +Consultas entre coleções (devem falhar) +Testes de migração com dados existentes +Testes de desempenho com grandes conjuntos de dados + +### Testes de Segurança +Tentativa de consultar dados de outros usuários +Ataques de injeção de SQL em parâmetros de usuário/coleção +Verificar o isolamento completo sob vários padrões de consulta + +## Considerações de Desempenho + +### Estratégia de Indexação +Índices compostos em `(user, collection, uri)` para filtragem otimizada +Considere índices parciais se algumas coleções forem muito maiores +Monitore o uso de índices e o desempenho das consultas + +### Otimização de Consultas +Use EXPLAIN para verificar o uso de índices em consultas filtradas +Considere o cache de resultados de consulta para dados acessados com frequência +Monitore o uso de memória com um grande número de usuários/coleções + +### Escalabilidade +Cada combinação de usuário/coleção cria ilhas de dados separadas +Monitore o tamanho do banco de dados e o uso do pool de conexões +Considere estratégias de escalabilidade horizontal, se necessário + +## Segurança e Conformidade + +### Garantias de Isolamento de Dados +**Físico**: Todos os dados do usuário armazenados com propriedades explícitas de usuário/coleção +**Lógico**: Todas as consultas filtradas pelo contexto de usuário/coleção +**Controle de Acesso**: A validação no nível do serviço impede o acesso não autorizado + +### Requisitos de Auditoria +Registre todo o acesso a dados com o contexto de usuário/coleção +Rastreie atividades de migração e movimentação de dados +Monitore tentativas de violação de isolamento + +### Considerações de Conformidade +GDPR: Capacidade aprimorada de localizar e excluir dados específicos do usuário +SOC2: Isolamento claro de dados e controles de acesso +HIPAA: Forte isolamento de locatários para dados de saúde + +## Riscos e Mitigações + +| Risco | Impacto | Probabilidade | Mitigação | +|------|--------|------------|------------| +| Consulta sem o filtro de usuário/coleção | Alto | Médio | Validação obrigatória, testes abrangentes | +| Degradação de desempenho | Médio | Baixo | Otimização de índice, análise de desempenho | +| Corrupção de dados durante a migração | Alto | Baixo | Estratégia de backup, procedimentos de reversão | +| Consultas complexas entre várias coleções | Médio | Médio | Documente padrões de consulta, forneça exemplos | + +## Critérios de Sucesso + +1. **Segurança**: Zero acesso a dados de outros usuários em produção +2. **Desempenho**: Impacto de <10% no desempenho da consulta em comparação com consultas não filtradas +3. **Migração**: 100% dos dados existentes migrados com sucesso e sem perda +4. **Usabilidade**: Todos os padrões de consulta existentes funcionam com o contexto de usuário/coleção +5. **Conformidade**: Rastreamento completo de acesso a dados de usuário/coleção + +## Conclusão + +A abordagem de filtragem baseada em propriedades oferece o melhor equilíbrio entre segurança, desempenho e manutenção para adicionar o isolamento de usuário/coleção ao Neo4j. Ela se alinha aos padrões de multilocação existentes do TrustGraph, aproveitando os pontos fortes do Neo4j em consultas de grafos e indexação. + +Esta solução garante que o backend do Neo4j do TrustGraph atenda aos mesmos padrões de segurança de outros backends de armazenamento, prevenindo vulnerabilidades de isolamento de dados, mantendo a flexibilidade e o poder das consultas de grafos. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.ru.md b/docs/tech-specs/neo4j-user-collection-isolation.ru.md new file mode 100644 index 00000000..49252c62 --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.ru.md @@ -0,0 +1,223 @@ +--- +layout: default +title: "Поддержка изоляции пользователя/коллекции в Neo4j" +parent: "Russian (Beta)" +--- + +# Поддержка изоляции пользователя/коллекции в Neo4j + +> **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. + +## Формулировка проблемы + +Текущая реализация хранения и запросов в Neo4j не обеспечивает изоляцию пользователя/коллекции, что создает проблему безопасности многопользовательской среды. Все тройки хранятся в одном графе без каких-либо механизмов для предотвращения доступа пользователей к данным других пользователей или смешения коллекций. + +В отличие от других бэкендов хранения в TrustGraph: +- **Cassandra**: использует отдельные пространства ключей для каждого пользователя и таблицы для каждой коллекции. +- **Vector-хранилища** (Milvus, Qdrant, Pinecone): используют пространства имен, специфичные для коллекции. +- **Neo4j**: в настоящее время все данные хранятся в одном графе (уязвимость для безопасности). + +## Текущая архитектура + +### Модель данных +- **Узлы**: метка `:Node` с свойством `uri`, метка `:Literal` с свойством `value` +- **Отношения**: метка `:Rel` с свойством `uri` +- **Индексы**: `Node.uri`, `Literal.value`, `Rel.uri` + +### Поток сообщений +- Сообщения `Triples` содержат поля `metadata.user` и `metadata.collection` +- Сервис хранения получает информацию о пользователе/коллекции, но игнорирует ее +- Сервис запросов ожидает `user` и `collection` в `TriplesQueryRequest`, но игнорирует их + +### Текущая проблема безопасности +```cypher +# Любой пользователь может запросить любые данные - нет изоляции +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## Предлагаемое решение: Фильтрация на основе свойств (Рекомендуется) + +### Обзор +Добавьте свойства `user` и `collection` ко всем узлам и отношениям, а затем фильтруйте все операции по этим свойствам. Этот подход обеспечивает надежную изоляцию, сохраняя при этом гибкость запросов и обратную совместимость. + +### Изменения в модели данных + +#### Улучшенная структура узла +```cypher +// Узел +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// Литеральные сущности +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### Улучшенная структура отношений +```cypher +// Отношения с свойствами user/collection +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### Обновленные индексы +```cypher +// Комплексные индексы для эффективного фильтра +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// Сохранение существующих индексов для обратной совместимости (необязательно) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### Изменения в реализации + +#### Сервис хранения (`write.py`) + +**Текущий код:** +```python +def create_node(self, uri): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, database_=self.db, + ).summary +``` + +**Обновленный код:** +```python +def create_node(self, uri, user, collection): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, user=user, collection=collection, database_=self.db, + ).summary +``` + +#### Сервис запросов +- Добавьте фильтры для user и collection в запросы, чтобы обеспечить изоляцию. + +### План реализации + +### Этап 1: Основа (Неделя 1) +1. [ ] Обновление сервиса хранения для приема и хранения свойств user/collection +2. [ ] Создание комплексных индексов для эффективного запроса +3. [ ] Реализация обратной совместимости +4. [ ] Создание модульных тестов для новой функциональности + +### Этап 2: Обновление запросов (Неделя 2) +1. [ ] Обновление всех шаблонов запросов для включения фильтров user/collection +2. [ ] Добавление валидации запросов и мер безопасности +3. [ ] Обновление интеграционных тестов +4. [ ] Тестирование производительности с запросами, отфильтрованными + +### Этап 3: Миграция и развертывание (Неделя 3) +1. [ ] Создание скриптов миграции для существующих экземпляров Neo4j +2. [ ] Документация и руководства по развертыванию +3. [ ] Мониторинг и оповещения об изоляции +4. [ ] Тестирование конвейера + +### Этап 4: Усиление (Неделя 4) +1. [ ] Удаление режима обратной совместимости +2. [ ] Добавление комплексной журнализации +3. [ ] Проверка безопасности и тестирование на проникновение +4. [ ] Оптимизация производительности + +## Стратегия тестирования + +### Модульные тесты +```python +def test_user_collection_isolation(): + # Храним тройки для user1/collection1 + processor.store_triples(triples_user1_coll1) + + # Храним тройки для user2/collection2 + processor.store_triples(triples_user2_coll2) + + # Запрос как user1 должен возвращать только данные user1 + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # Запрос как user2 должен возвращать только данные user2 + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### Интеграционные тесты +- Сценарии многопользовательского взаимодействия с перекрывающимися данными +- Запросы к перекрестным коллекциям (должны завершаться неудачей) +- Тестирование миграции с существующими данными +- Тестирование производительности с большими наборами данных + +### Тесты безопасности +- Попытки запросить данные других пользователей +- Атаки SQL injection на параметры user/collection +- Проверка полной изоляции при различных шаблонах запросов + +## Соображения производительности + +### Стратегия индексирования +- Комплексные индексы на `(user, collection, uri)` для оптимальной фильтрации +- Рассмотрите частичные индексы, если некоторые коллекции значительно больше +- Отслеживайте использование и производительность индекса + +### Оптимизация запросов +- Используйте EXPLAIN для проверки использования индекса в запросах, отфильтрованных по user/collection +- Рассмотрите кэширование результатов запросов для часто используемых данных +- Профилируйте использование памяти с большим количеством пользователей/коллекций + +### Масштабируемость +- Каждая комбинация пользователя/коллекции создает отдельные "острова данных" +- Отслеживайте размер базы данных и использование пула соединений +- Рассмотрите стратегии горизонтального масштабирования, если необходимо + +## Безопасность и соответствие + +### Гарантии изоляции данных +- **Физическая**: Все данные пользователя хранятся с явными свойствами user/collection +- **Логическая**: Все запросы фильтруются по контексту user/collection +- **Контроль доступа**: Уровень сервиса обеспечивает проверку доступа + +### Требования к отчетности +- Отслеживайте доступ к данным с контекстом user/collection +- Отслеживайте активности миграции и перемещения данных +- Мониторинг попыток нарушить изоляцию + +### Соображения соответствия +- GDPR: Улучшенная возможность находить и удалять данные, специфичные для пользователя +- SOC2: Четкая изоляция и контроль доступа +- HIPAA: Сильная изоляция для данных о здравоохранении + +## Риски и смягчающие факторы + +| Риск | Влияние | Вероятность | Смягчение | +|------|--------|------------|------------| +| Отсутствие фильтра user/collection в запросе | Высокий | Средняя | Обязательная валидация, комплексное тестирование | +| Снижение производительности | Средний | Низкая | Оптимизация индекса, профилирование запросов | +| Повреждение данных во время миграции | Высокий | Низкая | Стратегия резервного копирования, процедуры отката | +| Уязвимость для безопасности | Высокий | Низкая | Проверка безопасности, тестирование на проникновение | + +## Критерии успеха + +1. **Безопасность**: Полная изоляция данных между пользователями в производственной среде +2. **Производительность**: <10% влияния на производительность запросов по сравнению с нефильтрованными запросами +3. **Миграция**: 100% данных существующего экземпляра Neo4j успешно мигрированы без потерь +4. **Удобство использования**: Все существующие шаблоны запросов работают с контекстом user/collection +5. **Соответствие**: Полный журнал доступа к данным с контекстом user/collection + +## Заключение + +Предлагаемый подход на основе фильтрации свойств обеспечивает наилучший баланс между безопасностью, производительностью и удобством обслуживания для добавления изоляции пользователя/коллекции в Neo4j. Он соответствует существующим многопользовательским шаблонам TrustGraph, одновременно используя возможности Neo4j в области запросов и индексирования графов. + +Это решение гарантирует, что бэкенд Neo4j TrustGraph соответствует тем же стандартам безопасности, что и другие бэкенды, обеспечивая при этом изоляцию данных, одновременно сохраняя гибкость и мощь запросов графов. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.sw.md b/docs/tech-specs/neo4j-user-collection-isolation.sw.md new file mode 100644 index 00000000..8c942eab --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.sw.md @@ -0,0 +1,192 @@ +--- +layout: default +title: "Usaidizi wa Kuhami Mtumiaji/Mkusanyiko katika Neo4j" +parent: "Swahili (Beta)" +--- + +# Usaidizi wa Kuhami Mtumiaji/Mkusanyiko katika Neo4j + +> **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. + +## Tatizo + +Hifadhi na utekelezaji wa masuala ya Neo4j kwa sasa hutoi ukinzani wa mtumiaji/mkusanyiko, jambo ambalo huunda tatizo la usalama la utendaji wa wateja wengi. Masuala yote yanahifadhiwa katika nafasi moja ya grafu bila njia yoyote ya kuzuia watumiaji kupata data ya watumiaji wengine au kuchanganya mkusanyiko. + +Tofauti na mifumo mingine ya kuhifadhi katika TrustGraph: +- **Cassandra**: Hutumia nafasi tofauti kwa kila mtumiaji na meza kwa kila mkusanyiko. +- **Hifadhi za Vector** (Milvus, Qdrant, Pinecone): Hutumia nafasi maalum kwa kila mkusanyiko. +- **Neo4j**: Kwa sasa, inashiriki data yote katika grafu moja (hatari ya usalama). + +## Muundo wa Sasa + +### Mfano wa Data +- **Nod**: Laini `:Node` na `uri` ya jambo, `:Literal` na `value` ya jambo. +- **Uhusiano**: Laini `:Rel` na `uri` ya jambo. +- **Faharasa**: `Node.uri`, `Literal.value`, `Rel.uri`. + +### Mzunguko wa Ujumbe +- Ujumbe wa `Triples` una `metadata.user` na `metadata.collection` ya jambo. +- Huduma ya kuhifadhi inapokea taarifa za mtumiaji/mkusanyiko lakini inaizaba. +- Huduma ya kuuliza inatarajia `user` na `collection` katika `TriplesQueryRequest` lakini inaizaba. + +### Tatizo la Sasa la Usalama +```cypher +# Mtumiaji wowote anaweza kuuliza data yoyote - hakuna ukinzani +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## Suluhisho Lililopendekezwa: Kuchuja Kulingana na Jambo (Inapendekezwa) + +### Muhtasari +Ongeza `user` na `collection` ya jambo kwenye nodi na uhusiano wote, kisha chuja shughuli zote kwa jambo hizi. Njia hii hutoa ukinzani kamili huku ikiendeleza uwezo wa kuuliza na urafiki na mifumo iliyopo. + +### Mabadiliko ya Mfano wa Data + +#### Muundo Ulioboreshwa wa Nodi +```cypher +// Vitu vya Nodi +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// Vitu vya Literal +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### Muundo Ulioboreshwa wa Uhusiano +```cypher +// Uhusiano na jambo la mtumiaji/mkusanyiko +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### Faharasa Zilizosasishwa +```cypher +// Faharasa za pamoja kwa kuchuja kwa ufanisi +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +``` + +## Mpango wa Utendaji + +### Awamu ya 1: Msingi (Wiki ya 1) +1. [ ] Sasisha huduma ya kuhifadhi ili kukubali na kuhifadhi jambo la mtumiaji/mkusanyiko. +2. [ ] Ongeza faharasa za pamoja kwa kuuliza kwa ufanisi. +3. [ ] Lenga ukinzani wa nyuma. +4. [ ] Unda vipimo vya kitengo kwa utendakazi mpya. + +### Awamu ya 2: Masuala ya Uulizaji (Wiki ya 2) +1. [ ] Sasisha mifumo yote ya kuuliza ili kujumuisha vichujio vya mtumiaji/mkusanyiko. +2. [ ] Ongeza uthibitisho wa kuuliza na udhibiti wa usalama. +3. [ ] Sasisha vipimo vya ujumuishaji. +4. [ ] Vipimo vya utendaji na masuala yaliyofilishwa. + +### Awamu ya 3: Uhamishaji na Uwekaji (Wiki ya 3) +1. [ ] Unda skripti za uhamishaji wa data kwa matukio ya sasa ya Neo4j. +2. [ ] Nyaraka na maelekezo ya uwekaji. +3. [ ] Ufuatiliaji na arifa kwa ukiukaji wa ukinzani. +4. [ ] Vipimo kamili na matukio mengi ya mtumiaji/mkusanyiko. + +### Awamu ya 4: Uimarishaji (Wiki ya 4) +1. [ ] Ondoa hali ya ukinzani wa nyuma. +2. [ ] Ongeza ufuatiliaji kamili. +3. [ ] Mapitio ya usalama na majaribio ya uvamizi. +4. [ ] Uboreshaji wa utendaji. + +## Mikakati ya Ujaribio + +### Vipimo vya Kitengo +```python +def test_user_collection_isolation(): + # Hifadhi masuala kwa mtumiaji 1/mkusanyiko 1 + processor.store_triples(triples_user1_coll1) + + # Hifadhi masuala kwa mtumiaji 2/mkusanyiko 2 + processor.store_triples(triples_user2_coll2) + + # Uulizaje kama mtumiaji 1 unapaswa kurejesha data ya mtumiaji 1 + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # Uulizaje kama mtumiaji 2 unapaswa kurejesha data ya mtumiaji 2 + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### Vipimo vya Ujumuishaji +- Matukio mengi ya mtumiaji na data iliyofanana. +- Masuala ya kati ya mkusanyiko (yanapaswa kushindwa). +- Vipimo vya uhamishaji na data iliyopo. +- Benchi za utendaji na data kubwa. + +### Vipimo vya Usalama +- Jaribu kuuliza data ya watumiaji wengine. +- Mashambulio ya aina ya SQL kwenye vigezo vya mtumiaji/mkusanyiko. +- Thibitisha ukinzani kamili chini ya mifumo tofauti ya kuuliza. + +## Masuala ya Utendaji + +### Mkakati wa Faharasa +- Faharasa za pamoja kwenye `(user, collection, uri)` kwa kuchuja bora. +- Fikiria faharasa za sehemu ikiwa baadhi ya makusanyiko ni makubwa sana. +- Fuatilia matumizi ya faharasa na utendaji wa kuuliza. + +### Uboreshaji wa Uulizaji +- Tumia EXPLAIN ili kuhakikisha matumizi ya faharasa katika masuala yaliyofilishwa. +- Fikiria kuhifadhi matokeo ya kuuliza kwa data inayopatikana mara kwa mara. +- Profaili matumizi ya kumbukumbu na idadi kubwa ya watumiaji/makusanyiko. + +### Urahisi +- Kila mtumiaji/mkusanyiko huunda kisiwa cha data. +- Fuatilia saizi ya hifadhi na matumizi ya kikao. +- Fikiria mikakati ya urahisi wa wima ikiwa inahitajika. + +## Usalama na Uzingatiaji + +### Ahadi za Ukinzani wa Data +- **Kimwili**: Data yote ya mtumiaji iliyohifadhiwa na jambo la mtumiaji/mkusanyiko. +- **Mantiki**: Masuala yote yaliyofilishwa kwa muktadha wa mtumiaji/mkusanyiko. +- **Udhibiti wa Ufikiaji**: Uthibitisho wa kiwango cha huduma unaozuia ufikiaji usioidhinishwa. + +### Mahitaji ya Ufuatiliaji +- Ingiza masuala yote ya data na muktadha wa mtumiaji/mkusanyiko. +- Fuatilia shughuli za uhamishaji na uhamishaji wa data. +- Fuatilia majaribio ya ukiukaji wa ukinzani. + +### Masuala ya Uzingatiaji +- GDPR: Uwezo ulioboreshwa wa kutafuta na kufuta data maalum ya mtumiaji. +- SOC2: Ukinzani wa wateja wengi na udhibiti wa ufikiaji. +- HIPAA: Ukinzani wa mteja kwa data ya afya. + +## Hatari na Kupunguza + +| Hatari | Athari | Uwezekano | Kupunguza | +|------|--------|------------|------------| +| Uulizaji unokosa jambo la mtumiaji/mkusanyiko | Juu | Katikati | Uthibitisho wa lazima, vipimo vya kina | +| Uharibifu wa utendaji | Katikati | Chini | Uboreshaji wa faharasa, profaili ya kuuliza | +| Uharibifu wa data ya uhamishaji | Juu | Chini | Mkakati wa chelezo, taratibu za kurejesha | +| Masuala ya kuuliza ya mkusanyiko mingi | Katikati | Katikati | Nyaraka za mifumo ya kuuliza, toa mifano | + +## Vigezo vya Mafanikio + +1. **Usalama**: Hakuna ufikiaji wa data ya mtumiaji mwingine katika uzalishaji. +2. **Utendaji**: <10% athari ya utendaji kwenye masuala yaliyofilishwa. +3. **Uhamishaji**: 100% ya data iliyopo iliyohama bila kupoteza. +4. **Urahisi**: Masuala yote ya sasa ya kuuliza yanapaswa kufanya kazi na muktadha wa mtumiaji/mkusanyiko. +5. **Uzingatiaji**: Ufuatiliaji kamili wa masuala ya mtumiaji/mkusanyiko. + +## Hitimisho + +Njia ya kuchuja kulingana na jambo hutoa uwiano bora wa usalama, utendaji, na urafiki kwa kuongeza ukinzani wa mtumiaji/mkusanyiko katika Neo4j. Inalingana na mifumo iliyopo ya utendaji wa wateja wengi katika TrustGraph huku ikiendeleza nguvu za Neo4j katika kuuliza na faharasa. + +Suluhisho hili huhakikisha kwamba hifadhi ya Neo4j katika TrustGraph inakidhi viwango sawa vya usalama kama mifumo mingine ya kuhifadhi, ikiepuka udhaifu wa ukinzani wa data huku ikiendeleza uwezo na nguvu ya kuuliza ya grafu. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.tr.md b/docs/tech-specs/neo4j-user-collection-isolation.tr.md new file mode 100644 index 00000000..45e76b56 --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.tr.md @@ -0,0 +1,367 @@ +--- +layout: default +title: "Neo4j Kullanıcı/Koleksiyon İzolasyonu Desteği" +parent: "Turkish (Beta)" +--- + +# Neo4j Kullanıcı/Koleksiyon İzolasyonu Desteğ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. + +## Problem Tanımı + +Mevcut Neo4j üçlü depolama ve sorgu uygulaması, kullanıcı/koleksiyon izolasyonu eksikliği nedeniyle çoklu kiracılık güvenliği sorunlarına yol açmaktadır. Tüm üçlüler, kullanıcıların diğer kullanıcıların verilerine erişmesini veya koleksiyonları karıştırmasını engelleyen herhangi bir mekanizma olmadan aynı grafik alanında saklanmaktadır. + +TrustGraph'taki diğer depolama arka uçlarından farklı olarak: +**Cassandra**: Her kullanıcı için ayrı anahtarlar ve her koleksiyon için tablolar kullanır. +**Vektör depoları** (Milvus, Qdrant, Pinecone): Koleksiyona özgü ad alanlarını kullanır. +**Neo4j**: Şu anda tüm verileri tek bir grafik alanında paylaşır (güvenlik açığı). + +## Mevcut Mimari + +### Veri Modeli +**Düğümler**: `:Node` etiketi ile `uri` özelliği, `:Literal` etiketi ile `value` özelliği. +**İlişkiler**: `:Rel` etiketi ile `uri` özelliği. +**Dizinler**: `Node.uri`, `Literal.value`, `Rel.uri`. + +### Mesaj Akışı +`Triples` mesajları `metadata.user` ve `metadata.collection` alanlarını içerir. +Depolama hizmeti kullanıcı/koleksiyon bilgilerini alır, ancak bunları yoksayar. +Sorgu hizmeti `TriplesQueryRequest` içinde `user` ve `collection`'i bekler, ancak bunları yoksayar. + +### Mevcut Güvenlik Sorunu +```cypher +# Any user can query any data - no isolation +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## Önerilen Çözüm: Özellik Tabanlı Filtreleme (Önerilen) + +### Genel Bakış +Tüm düğümlere ve ilişkilerlere `user` ve `collection` özelliklerini ekleyin, ardından tüm işlemleri bu özelliklere göre filtreleyin. Bu yaklaşım, güçlü bir izolasyon sağlarken sorgu esnekliğini ve geriye dönük uyumluluğu korur. + +### Veri Modeli Değişiklikleri + +#### Gelişmiş Düğüm Yapısı +```cypher +// Node entities +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// Literal entities +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### Gelişmiş İlişki Yapısı +```cypher +// Relationships with user/collection properties +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### Güncellenmiş İndeksler +```cypher +// Compound indexes for efficient filtering +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// Maintain existing indexes for backwards compatibility (optional) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### Uygulama Değişiklikleri + +#### Depolama Hizmeti (`write.py`) + +**Mevcut Kod:** +```python +def create_node(self, uri): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, database_=self.db, + ).summary +``` + +**Güncellenmiş Kod:** +```python +def create_node(self, uri, user, collection): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri, user: $user, collection: $collection})", + uri=uri, user=user, collection=collection, database_=self.db, + ).summary +``` + +**Geliştirilmiş `store_triples` Metodu:** +```python +async def store_triples(self, message): + user = message.metadata.user + collection = message.metadata.collection + + for t in message.triples: + self.create_node(t.s.value, user, collection) + + if t.o.is_uri: + self.create_node(t.o.value, user, collection) + self.relate_node(t.s.value, t.p.value, t.o.value, user, collection) + else: + self.create_literal(t.o.value, user, collection) + self.relate_literal(t.s.value, t.p.value, t.o.value, user, collection) +``` + +#### Sorgu Hizmeti (`service.py`) + +**Mevcut Kod:** +```python +records, summary, keys = self.io.execute_query( + "MATCH (src:Node {uri: $src})-[rel:Rel {uri: $rel}]->(dest:Node) " + "RETURN dest.uri as dest", + src=query.s.value, rel=query.p.value, database_=self.db, +) +``` + +**Güncellenmiş Kod:** +```python +records, summary, keys = self.io.execute_query( + "MATCH (src:Node {uri: $src, user: $user, collection: $collection})-" + "[rel:Rel {uri: $rel, user: $user, collection: $collection}]->" + "(dest:Node {user: $user, collection: $collection}) " + "RETURN dest.uri as dest", + src=query.s.value, rel=query.p.value, + user=query.user, collection=query.collection, + database_=self.db, +) +``` + +### Göç Stratejisi + +#### 1. Aşama: Yeni Verilere Özellikler Ekleme +1. Kullanıcı/koleksiyon özelliklerini yeni üçlülere eklemek için depolama hizmetini güncelleyin. +2. Geriye dönük uyumluluğu korumak için sorgularda özelliklerin gerekli olmaması. +3. Mevcut veriler erişilebilir durumda kalır, ancak izole edilmez. + +#### 2. Aşama: Mevcut Verilerin Taşınması +```cypher +// Migrate existing nodes (requires default user/collection assignment) +MATCH (n:Node) WHERE n.user IS NULL +SET n.user = 'legacy_user', n.collection = 'default_collection'; + +MATCH (n:Literal) WHERE n.user IS NULL +SET n.user = 'legacy_user', n.collection = 'default_collection'; + +MATCH ()-[r:Rel]->() WHERE r.user IS NULL +SET r.user = 'legacy_user', r.collection = 'default_collection'; +``` + +#### 3. Aşama: İzolasyonu Sağlama +1. Sorgu hizmetini, kullanıcı/koleksiyon filtrelemesini gerektirecek şekilde güncelleyin. +2. Doğru kullanıcı/koleksiyon bağlamı olmadan yapılan sorguları reddedecek doğrulama ekleyin. +3. Eski veri erişim yollarını kaldırın. + +### Güvenlik Hususları + +#### Sorgu Doğrulama +```python +async def query_triples(self, query): + # Validate user/collection parameters + if not query.user or not query.collection: + raise ValueError("User and collection must be specified") + + # All queries must include user/collection filters + # ... rest of implementation +``` + +#### Parametre Enjeksiyonunu Önleme +Yalnızca parametreli sorguları kullanın +Kullanıcı/toplam değerlerini izin verilen kalıplara karşı doğrulayın +Neo4j özellik adı gereksinimleri için sanitizasyonu göz önünde bulundurun + +#### Denetim Kaydı +```python +logger.info(f"Query executed - User: {query.user}, Collection: {query.collection}, " + f"Pattern: {query.s}/{query.p}/{query.o}") +``` + +## Alternatif Yaklaşımlar + +### Seçenek 2: Etiket Tabanlı İzolasyon + +**Yaklaşım**: Dinamik etiketler kullanın, örneğin `User_john_Collection_prod` + +**Avantajları:** +Etiket filtreleme yoluyla güçlü izolasyon +Etiket indeksleriyle verimli sorgu performansı +Açık veri ayrımı + +**Dezavantajları:** +Neo4j'nin etiket sayısı konusunda pratik sınırlamaları vardır (~1000'ler) +Karmaşık etiket adı oluşturma ve temizleme +Gerekli olduğunda koleksiyonlar arasında sorgu yapmak zordur + +**Uygulama Örneği:** +```cypher +CREATE (n:Node:User_john_Collection_prod {uri: "http://example.com/entity"}) +MATCH (n:User_john_Collection_prod) WHERE n:Node RETURN n +``` + +### Seçenek 3: Kullanıcı Başına Veritabanı + +**Yaklaşım:** Her kullanıcı veya kullanıcı/koleksiyon kombinasyonu için ayrı Neo4j veritabanları oluşturun. + +**Avantajları:** +Tam veri izolasyonu +Çapraz bulaşma riski yok +Kullanıcı başına bağımsız ölçeklendirme + +**Dezavantajları:** +Kaynak yükü (her veritabanı bellek tüketir) +Karmaşık veritabanı yaşam döngüsü yönetimi +Neo4j Community Edition veritabanı limitleri +Kullanıcılar arası analizler yapmak zordur. + +### Seçenek 4: Bileşik Anahtar Stratejisi + +**Yaklaşım:** Tüm URI'ları ve değerleri kullanıcı/koleksiyon bilgileriyle ön ekleyin. + +**Avantajları:** +Mevcut sorgularla geriye dönük uyumluluk +Basit uygulama +Şema değişiklikleri gerektirmez + +**Dezavantajları:** +URI kirliliği, veri anlamını etkiler +Daha az verimli sorgular (dize ön eki eşleştirme) +RDF/semantik web standartlarını ihlal eder + +**Uygulama Örneği:** +```python +def make_composite_uri(uri, user, collection): + return f"usr:{user}:col:{collection}:uri:{uri}" +``` + +## Uygulama Planı + +### Aşama 1: Temel (1. Hafta) +1. [ ] Depolama hizmetini, kullanıcı/koleksiyon özelliklerini kabul edecek ve saklayacak şekilde güncelleyin. +2. [ ] Verimli sorgulama için bileşik indeksler ekleyin. +3. [ ] Geriye dönük uyumluluk katmanı uygulayın. +4. [ ] Yeni işlevler için birim testleri oluşturun. + +### Aşama 2: Sorgu Güncellemeleri (2. Hafta) +1. [ ] Tüm sorgu kalıplarını, kullanıcı/koleksiyon filtrelerini içerecek şekilde güncelleyin. +2. [ ] Sorgu doğrulaması ve güvenlik kontrolleri ekleyin. +3. [ ] Entegrasyon testlerini güncelleyin. +4. [ ] Filtrelenmiş sorgularla performans testi yapın. + +### Aşama 3: Göç ve Dağıtım (3. Hafta) +1. [ ] Mevcut Neo4j örnekleri için veri geçiş betikleri oluşturun. +2. [ ] Dağıtım belgeleri ve çalıştırma kılavuzları. +3. [ ] İzolasyon ihlalleri için izleme ve uyarı. +4. [ ] Çok sayıda kullanıcı/koleksiyonla uçtan uca testler yapın. + +### Aşama 4: Güçlendirme (4. Hafta) +1. [ ] Eski uyumluluk modunu kaldırın. +2. [ ] Kapsamlı denetim kaydı ekleyin. +3. [ ] Güvenlik incelemesi ve sızma testi. +4. [ ] Performans optimizasyonu. + +## Test Stratejisi + +### Birim Testleri +```python +def test_user_collection_isolation(): + # Store triples for user1/collection1 + processor.store_triples(triples_user1_coll1) + + # Store triples for user2/collection2 + processor.store_triples(triples_user2_coll2) + + # Query as user1 should only return user1's data + results = processor.query_triples(query_user1_coll1) + assert all_results_belong_to_user1_coll1(results) + + # Query as user2 should only return user2's data + results = processor.query_triples(query_user2_coll2) + assert all_results_belong_to_user2_coll2(results) +``` + +### Entegrasyon Testleri +Eş zamanlı veri içeren çok kullanıcılı senaryolar +Koleksiyonlar arası sorgular (başarısız olmalıdır) +Mevcut verilerle yapılan geçiş testleri +Büyük veri kümeleriyle yapılan performans ölçümleri + +### Güvenlik Testleri +Diğer kullanıcıların verilerine erişme girişimleri +Kullanıcı/koleksiyon parametrelerine yönelik SQL enjeksiyonu tarzı saldırılar +Çeşitli sorgu kalıpları altında tam izolasyonu doğrulayın + +## Performans Hususları + +### İndeks Stratejisi +Optimum filtreleme için `(user, collection, uri)` üzerinde birleşik indeksler +Bazı koleksiyonların çok daha büyük olması durumunda, kısmi indeksleri göz önünde bulundurun +İndeks kullanımını ve sorgu performansını izleyin + +### Sorgu Optimizasyonu +Filtrelenmiş sorgularda indeks kullanımını doğrulamak için EXPLAIN'i kullanın +Sık erişilen veriler için sorgu sonucu önbelleklemesini göz önünde bulundurun +Çok sayıda kullanıcı/koleksiyonla bellek kullanımını analiz edin + +### Ölçeklenebilirlik +Her kullanıcı/koleksiyon kombinasyonu, ayrı veri adacıkları oluşturur +Veritabanı boyutunu ve bağlantı havuzu kullanımını izleyin +Gerekirse, yatay ölçeklendirme stratejilerini göz önünde bulundurun + +## Güvenlik ve Uyumluluk + +### Veri İzolasyon Garantileri +**Fiziksel**: Tüm kullanıcı verileri, açık kullanıcı/koleksiyon özellikleri ile saklanır +**Mantıksal**: Tüm sorgular, kullanıcı/koleksiyon bağlamıyla filtrelenir +**Erişim Kontrolü**: Hizmet seviyesindeki doğrulama, yetkisiz erişimi engeller + +### Denetim Gereksinimleri +Tüm veri erişimlerini kullanıcı/koleksiyon bağlamıyla kaydedin +Geçiş etkinliklerini ve veri hareketlerini izleyin +İzolasyon ihlali girişimlerini izleyin + +### Uyumluluk Hususları +GDPR: Kullanıcıya özel verileri bulma ve silme yeteneğinin geliştirilmesi +SOC2: Açık veri izolasyonu ve erişim kontrolleri +HIPAA: Sağlık verileri için güçlü kiracı izolasyonu + +## Riskler ve Önlemler + +| Risk | Etki | Olasılık | Önlem | +|------|--------|------------|------------| +| Sorguda eksik kullanıcı/koleksiyon filtresi | Yüksek | Orta | Zorunlu doğrulama, kapsamlı testler | +| Performans düşüşü | Orta | Düşük | İndeks optimizasyonu, sorgu analizi | +| Geçiş sırasında veri bozulması | Yüksek | Düşük | Yedekleme stratejisi, geri alma prosedürleri | +| Karmaşık, koleksiyonlar arası sorgular | Orta | Orta | Sorgu kalıplarını belgeleyin, örnekler sağlayın | + +## Başarı Kriterleri + +1. **Güvenlik**: Üretimde, kullanıcılar arası veri erişiminin sıfır olması +2. **Performans**: Filtrelenmemiş sorgulara kıyasla %10'dan düşük sorgu performans etkisi +3. **Geçiş**: Mevcut verilerin %100'ü, kayıp olmadan başarıyla geçirilmiştir +4. **Kullanılabilirlik**: Tüm mevcut sorgu kalıpları, kullanıcı/koleksiyon bağlamıyla çalışır +5. **Uyumluluk**: Kullanıcı/koleksiyon verilerine yapılan tüm erişimlerin tam denetim kaydı + +## Sonuç + +Özellik tabanlı filtreleme yaklaşımı, Neo4j'ye kullanıcı/koleksiyon izolasyonu eklemek için güvenlik, performans ve bakım açısından en iyi dengeyi sağlar. TrustGraph'ın mevcut çok kiracılık kalıplarıyla uyumludur ve aynı zamanda Neo4j'nin grafik sorgulama ve indeksleme konusundaki güçlü yönlerinden yararlanır. + +Bu çözüm, TrustGraph'ın Neo4j arka ucunun, diğer depolama arka uçları ile aynı güvenlik standartlarını karşılamasını sağlar ve veri izolasyonu güvenlik açıklarını önlerken, grafik sorgularının esnekliğini ve gücünü korur. diff --git a/docs/tech-specs/neo4j-user-collection-isolation.zh-cn.md b/docs/tech-specs/neo4j-user-collection-isolation.zh-cn.md new file mode 100644 index 00000000..2f1345bd --- /dev/null +++ b/docs/tech-specs/neo4j-user-collection-isolation.zh-cn.md @@ -0,0 +1,210 @@ +--- +layout: default +title: "Neo4j 用户/集合隔离支持" +parent: "Chinese (Beta)" +--- + +# Neo4j 用户/集合隔离支持 + +> **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. + +## 问题陈述 + +Neo4j 的三元存储和查询实现目前缺乏用户/集合隔离,从而导致多租户安全问题。所有三元都存储在同一个图空间中,且没有任何机制来防止用户访问其他用户的或混合集合的数据。 + +与 TrustGraph 中的其他存储后端不同: +- **Cassandra**: 使用每个用户和每个集合的单独键空间和表 +- **向量存储**(Milvus、Qdrant、Pinecone): 使用集合特定的命名空间 +- **Neo4j**: 目前共享所有数据在一个图(安全漏洞) + +## 现有架构 + +### 数据模型 +- **节点**: 标签为 `:Node`,具有 `uri` 属性,标签为 `:Literal`,具有 `value` 属性 +- **关系**: 标签为 `:Rel`,具有 `uri` 属性 +- **索引**: `Node.uri`、`Literal.value`、`Rel.uri` + +### 消息流程 +- `Triples` 消息包含 `metadata.user` 和 `metadata.collection` 字段 +- 存储服务接收用户/集合信息,但忽略它们 +- 查询服务期望在 `TriplesQueryRequest` 中包含 `user` 和 `collection`,但忽略它们 + +### 现有安全问题 +```cypher +# 任何用户都可以查询任何数据 - 无隔离 +MATCH (src:Node)-[rel:Rel]->(dest:Node) +RETURN src.uri, rel.uri, dest.uri +``` + +## 建议解决方案:基于属性的过滤(推荐) + +### 概述 +添加所有节点的和关系的 `user` 和 `collection` 属性,然后使用这些属性对所有操作进行过滤。 这种方法在保持查询灵活性和向后兼容性的同时,提供强大的隔离。 + +### 数据模型更改 + +#### 增强的节点结构 +```cypher +// 节点实体 +CREATE (n:Node { + uri: "http://example.com/entity1", + user: "john_doe", + collection: "production_v1" +}) + +// 字面量实体 +CREATE (n:Literal { + value: "literal value", + user: "john_doe", + collection: "production_v1" +}) +``` + +#### 增强的关系结构 +```cypher +// 具有 user/collection 属性的关系 +CREATE (src)-[:Rel { + uri: "http://example.com/predicate1", + user: "john_doe", + collection: "production_v1" +}]->(dest) +``` + +#### 更新的索引 +```cypher +// 用于高效过滤的复合索引 +CREATE INDEX node_user_collection_uri FOR (n:Node) ON (n.user, n.collection, n.uri); +CREATE INDEX literal_user_collection_value FOR (n:Literal) ON (n.user, n.collection, n.value); +CREATE INDEX rel_user_collection_uri FOR ()-[r:Rel]-() ON (r.user, r.collection, r.uri); + +// 保持现有索引以实现向后兼容性(可选) +CREATE INDEX Node_uri FOR (n:Node) ON (n.uri); +CREATE INDEX Literal_value FOR (n:Literal) ON (n.value); +CREATE INDEX Rel_uri FOR ()-[r:Rel]-() ON (r.uri); +``` + +### 实现更改 + +#### 存储服务 (`write.py`) + +**当前代码:** +```python +def create_node(self, uri): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri})", + uri=uri, database_=self.db, + ).summary +``` + +**更新后的代码:** +```python +def create_node(self, uri, user, collection): + summary = self.io.execute_query( + "MERGE (n:Node {uri: $uri, user: $user, collection: $collection})", + uri=uri, user=user, collection=collection, database_=self.db, + ).summary +``` + +**增强的 store_triples 方法:** +```python +async def store_triples(self, message): + user = message.metadata.user + collection = message.metadata.collection + # 存储 triples + # ... +``` + +#### 查询更新 +(此处应包含修改查询模式以包含 user 和 collection 的代码。 示例:`query_user1_coll1 = "MATCH (n)-[:Rel]->(m) WHERE n.user = 'john_doe' AND n.collection = 'production_v1' RETURN n, m"`) + +### 阶段 2:查询更新(第 2 周) +(此处应包含修改查询模式以包含 user 和 collection 的代码。 示例:`query_user1_coll1 = "MATCH (n)-[:Rel]->(m) WHERE n.user = 'john_doe' AND n.collection = 'production_v1' RETURN n, m"`) +1. [ ] 更新所有查询模式,以便包含 user/collection 过滤器 +2. [ ] 添加查询验证和安全检查 +3. [ ] 更新集成测试 +4. [ ] 性能测试,使用过滤后的查询 + +### 阶段 3:迁移和部署(第 3 周) +1. [ ] 创建现有 Neo4j 实例的迁移脚本 +2. [ ] 部署文档和操作手册 +3. [ ] 监控和警报,用于隔离违规 +4. [ ] 端到端测试,使用多个用户/集合 + +### 阶段 4:强化(第 4 周) +1. [ ] 移除兼容性模式 +2. [ ] 添加全面的审计日志 +3. [ ] 安全审查和渗透测试 +4. [ ] 性能优化 + +## 测试策略 + +### 单元测试 +(此处应包含使用 user 和 collection 进行隔离的单元测试示例。 示例:`def test_user_collection_isolation(): ...`) + +### 集成测试 +- 具有重叠数据的多用户场景 +- 跨集合查询(应失败) +- 迁移测试,使用现有数据 +- 性能基准测试,使用大量数据 + +### 安全测试 +- 尝试查询其他用户的 +- 尝试 SQL 注入,利用 user/collection 参数 +- 验证在各种查询模式下是否完全隔离 + +## 性能考虑 + +### 索引策略 +- 使用 `(user, collection, uri)` 的复合索引,以实现最佳过滤 +- 如果某些集合非常大,请考虑使用部分索引 +- 监控索引使用情况和查询性能 + +### 查询优化 +- 使用 EXPLAIN 验证过滤查询是否使用了索引 +- 考虑查询结果缓存,用于频繁访问的数据 +- 剖析与大量用户/集合一起使用时的内存使用情况 + +### 可扩展性 +- 每个用户/集合组合都会创建一个单独的数据岛 +- 监控数据库大小和连接池使用情况 +- 考虑所需的水平扩展策略 + +## 安全与合规 + +### 数据隔离保证 +- **物理**: 所有用户数据都带有明确的用户/集合属性 +- **逻辑**: 所有查询都通过用户/集合上下文过滤 +- **访问控制**: 服务级别的验证防止未经授权的访问 + +### 审计要求 +- 记录所有数据访问,包括用户/集合上下文 +- 跟踪数据移动和迁移活动 +- 监控隔离违规尝试 + +### 合规性考虑 +- GDPR:更好地定位和删除用户特定数据 +- SOC2:清晰的数据隔离和访问控制 +- HIPAA:为医疗数据提供强大的租户隔离 + +## 风险与缓解措施 + +| 风险 | 影响 | 可能性 | 缓解措施 | +|------|--------|------------|------------| +| 缺少用户/集合过滤器 | 高 | 中 | 强制验证,全面测试 | +| 查询性能下降 | 中 | 低 | 索引优化,查询剖析 | +| 迁移数据损坏 | 高 | 低 | 备份策略,回滚程序 | +| 复杂的跨集合查询 | 中 | 中 | 文档查询模式,提供示例 | + +## 成功标准 + +1. **安全性**: 在生产环境中,没有任何跨用户的数据访问 +2. **性能**: 与未过滤的查询相比,影响小于 10% +3. **迁移**: 100% 的现有 Neo4j 数据成功迁移,且没有数据丢失 +4. **可用性**: 所有现有的查询模式都与用户/集合上下文工作 +5. **合规性**: 完整地记录用户/集合数据访问 + +## 结论 + +基于属性的过滤方法,是实现 Neo4j 用户/集合隔离的最佳平衡方案,它既能保证安全性,又能保持查询的灵活性和强大的图查询功能。 + +这个解决方案确保 TrustGraph 的 Neo4j 后端符合其他存储后端的相同安全标准,同时最大限度地发挥图查询和索引的优势。 diff --git a/docs/tech-specs/ontology-extract-phase-2.ar.md b/docs/tech-specs/ontology-extract-phase-2.ar.md new file mode 100644 index 00000000..7ebd5aa8 --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.ar.md @@ -0,0 +1,769 @@ +--- +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. + +**الحالة**: مسودة +**المؤلف**: جلسة التحليل بتاريخ 2025-12-03 +**مرتبط بـ**: `ontology.md`، `ontorag.md` + +## نظرة عامة + +يحدد هذا المستند التناقضات الموجودة في نظام استخراج المعرفة الحالي القائم على علم الوجود ويقترح إعادة هيكلة لتحسين أداء نماذج اللغة الكبيرة وتقليل فقدان المعلومات. + +## التنفيذ الحالي + +### كيف يعمل الآن + +1. **تحميل علم الوجود** (`ontology_loader.py`) + يقوم بتحميل ملف JSON الخاص بعلم الوجود باستخدام مفاتيح مثل `"fo/Recipe"`، `"fo/Food"`، `"fo/produces"` + تتضمن معرفات الفئات بادئة مساحة الاسم في المفتاح نفسه. + مثال من `food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **بناء المطالبة** (`extract.py:299-307`، `ontology-prompt.md`) + يتلقى النموذج `classes`، `object_properties`، `datatype_properties` (قواميس). + يتكرر النموذج: `{% for class_id, class_def in classes.items() %}` + يرى نموذج اللغة الكبيرة (LLM): `**fo/Recipe**: A Recipe is a combination...` + يوضح تنسيق الإخراج النموذجي: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **تحليل الاستجابة** (`extract.py:382-428`) + يتوقع مصفوفة JSON: `[{"subject": "...", "predicate": "...", "object": "..."}]` + يتحقق من الصحة مقابل مجموعة فرعية من علم الوجود. + يوسع الـ URIs عبر `expand_uri()` (extract.py:473-521) + +4. **توسيع الـ URI** (`extract.py:473-521`) + يتحقق مما إذا كانت القيمة موجودة في قاموس `ontology_subset.classes`. + إذا تم العثور عليها، يتم استخراج الـ URI من تعريف الفئة. + إذا لم يتم العثور عليها، يتم إنشاء الـ URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### مثال تدفق البيانات + +**JSON لعلم الوجود → المحمل → المطالبة:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**نموذج اللغة الكبير → المحلل → الإخراج:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## المشكلات التي تم تحديدها + +### 1. **أمثلة غير متسقة في التعليمات** + +**المشكلة**: قالب التعليمات يعرض معرفات الفئات مع بادئات (`fo/Recipe`) ولكن الإخراج النموذجي يستخدم أسماء فئات بدون بادئات (`Recipe`). + +**الموقع**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**التأثير:** يتلقى نموذج اللغة الكبير إشارات متضاربة حول التنسيق الذي يجب استخدامه. + +### 2. **فقدان المعلومات في توسيع عنوان URL** + +**المشكلة:** عندما يقوم نموذج اللغة الكبير بإرجاع أسماء الفئات غير المسبوقة بعد المثال، لا يمكن لـ `expand_uri()` العثور عليها في قاموس الأونطولوجيا ويقوم بإنشاء عناوين URI احتياطية، مما يؤدي إلى فقدان عناوين URI الأصلية الصحيحة. + +**الموقع:** `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**التأثير:** +عنوان URI الأصلي: `http://purl.org/ontology/fo/Recipe` +عنوان URI المُنشأ: `https://trustgraph.ai/ontology/food#Recipe` +فقدان المعنى الدلالي، مما يعيق التوافقية. + +### 3. **تنسيق مثيل الكيان الغامض** + +**المشكلة:** لا توجد إرشادات واضحة حول تنسيق عنوان URI لمثيل الكيان. + +**أمثلة في التعليمات:** +`"recipe:cornish-pasty"` (بادئة تشبه مساحة الاسم) +`"ingredient:flour"` (بادئة مختلفة) + +**السلوك الفعلي** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**التأثير**: يجب على نموذج اللغة الكبير تخمين اتفاقية البادئات بدون أي سياق دلالي. + +### 4. **لا توجد إرشادات حول بادئات النطاقات**. + +**المشكلة**: يحتوي ملف JSON الخاص بالدلالة على تعريفات النطاقات (السطر 10-25 في food.ontology): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +ولكن هذه العناصر لا يتم إرسالها أبدًا إلى نموذج اللغة الكبير (LLM). نموذج اللغة الكبير لا يعرف: +ما الذي تعنيه كلمة "fo" +ما هو البادئة التي يجب استخدامها للكائنات +أي مساحة اسم تنطبق على أي عناصر + +### 5. **التسميات غير المستخدمة في المطالبة** + +**المشكلة:** كل فئة لديها `rdfs:label` حقول (مثل `{"value": "Recipe", "lang": "en-gb"}`)، ولكن قالب المطالبة لا يستخدمها. + +**الحالي:** يعرض فقط `class_id` و `comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**متاح ولكنه غير مستخدم:** +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**التأثير**: يمكن أن يوفر أسماءً قابلة للقراءة من قبل الإنسان جنبًا إلى جنب مع المعرفات التقنية. + +## الحلول المقترحة + +### الخيار أ: التوحيد إلى معرفات غير مُسبقة + +**النهج**: إزالة البادئات من معرفات الفئات قبل عرضها لنظام LLM. + +**التغييرات**: +1. تعديل `build_extraction_variables()` لتحويل المفاتيح: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. تحديث مثال المطالبة ليتطابق (يستخدم بالفعل أسماء غير مسبوقة). + +3. تعديل `expand_uri()` للتعامل مع كلا التنسيقين: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**المزايا:** +أنظف وأكثر قابلية للقراءة من قبل البشر. +تتوافق مع أمثلة المطالبات الحالية. +تعمل نماذج اللغات الكبيرة بشكل أفضل مع الرموز الأبسط. + +**العيوب:** +تعارض أسماء الفئات إذا كانت هناك العديد من الأنطولوجيات لها نفس اسم الفئة. +تفقد معلومات مساحة الاسم. +تتطلب منطقًا احتياطيًا للبحث. + +### الخيار ب: استخدام المعرفات الكاملة المسبوقة باستمرار + +**الطريقة:** تحديث الأمثلة لاستخدام المعرفات المسبوقة التي تتطابق مع ما هو موضح في قائمة الفئات. + +**التغييرات:** +1. تحديث مثال المطالبة (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. أضف شرحًا لمساحة الاسم إلى التعليمات: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. احتفظ بـ `expand_uri()` كما هو (يعمل بشكل صحيح عند العثور على تطابقات). + +**المزايا:** +اتساق الإدخال والإخراج. +عدم وجود فقدان للمعلومات. +يحافظ على دلالات مساحة الاسم. +يعمل مع العديد من الأنطولوجيات. + +**العيوب:** +رموز أكثر تفصيلاً لنظام LLM. +يتطلب من نظام LLM تتبع البادئات. + +### الخيار ج: هجين - عرض كل من التسمية والمعرف + +**النهج:** قم بتحسين المطالبة لعرض كل من التسميات المقروءة من قبل الإنسان والمعرفات التقنية. + +**التغييرات:** +1. تحديث قالب المطالبة: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + الناتج النموذجي: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. تعليمات التحديث: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**المزايا:** +الأوضح لنماذج اللغة الكبيرة (LLM) +يحافظ على جميع المعلومات +يوضح بشكل صريح ما يجب استخدامه + +**العيوب:** +طلب أطول +قالب أكثر تعقيدًا + +## النهج المطبق + +**تنسيق مبسط للعلاقة بين الكيانات والخصائص** - يحل محل التنسيق القديم القائم على الثلاثيات تمامًا. + +تم اختيار النهج الجديد لأنه: + +1. **لا يوجد فقدان للمعلومات**: يتم الحفاظ على عناوين URI الأصلية بشكل صحيح. +2. **منطق أبسط**: لا توجد حاجة إلى أي تحويل، تعمل عمليات البحث المباشرة في القواميس. +3. **أمان مساحة الاسم**: يتعامل مع العديد من الأنطولوجيات دون حدوث تعارضات. +4. **الصحة الدلالية**: يحافظ على الدلالات الخاصة بـ RDF/OWL. + +## التنفيذ مكتمل + +### ما تم بناؤه: + +1. **قالب طلب جديد** (`prompts/ontology-extract-v2.txt`) + ✅ أقسام واضحة: أنواع الكيانات، العلاقات، الخصائص. + ✅ مثال باستخدام معرفات النوع الكاملة (`fo/Recipe`، `fo/has_ingredient`). + ✅ تعليمات لاستخدام المعرفات الدقيقة من المخطط. + ✅ تنسيق JSON جديد مع مصفوفات الكيانات/العلاقات/الخصائص. + +2. **تسوية الكيانات** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - يحول الأسماء إلى تنسيق آمن لـ URI. + ✅ `normalize_type_identifier()` - يتعامل مع الشرطات المائلة في الأنواع (`fo/Recipe` → `fo-recipe`). + ✅ `build_entity_uri()` - ينشئ عناوين URI فريدة باستخدام زوج (الاسم، النوع). + ✅ `EntityRegistry` - يتتبع الكيانات لتجنب التكرار. + +3. **محلل JSON** (`simplified_parser.py`) + ✅ يحلل التنسيق الجديد: `{entities: [...], relationships: [...], attributes: [...]}`. + ✅ يدعم أسماء الحقول بتنسيق kebab-case و snake_case. + ✅ يُرجع فئات بيانات منظمة. + ✅ معالجة أخطاء سلسة مع التسجيل. + +4. **محول الثلاثيات** (`triple_converter.py`) + ✅ `convert_entity()` - ينشئ ثلاثيات النوع + التسمية تلقائيًا. + ✅ `convert_relationship()` - يربط عناوين URI للكيانات عبر الخصائص. + ✅ `convert_attribute()` - يضيف القيم الحرفية. + ✅ يبحث عن عناوين URI الكاملة من تعريفات الأنطولوجيا. + +5. **المعالج الرئيسي المحدث** (`extract.py`) + ✅ تمت إزالة كود الاستخراج القديم القائم على الثلاثيات. + ✅ تمت إضافة `extract_with_simplified_format()`. + ✅ يستخدم الآن التنسيق المبسط الجديد فقط. + ✅ يستدعي الطلب بمعرف `extract-with-ontologies-v2`. + +## حالات الاختبار + +### الاختبار 1: الحفاظ على عنوان URI +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### الاختبار 2: التصادم متعدد الأنطولوجيا +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### الاختبار رقم 3: تنسيق مثيل الكيان +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## أسئلة مفتوحة + +1. **هل يجب أن تستخدم حالات الكيانات بادئات النطاق؟** + الحالي: `"recipe:cornish-pasty"` (عشوائي) + بديل: استخدام بادئة الأونطولوجيا `"fo:cornish-pasty"`؟ + بديل: بدون بادئة، التوسع في URI `"cornish-pasty"` → URI كامل؟ + +2. **كيفية التعامل مع النطاق/المدى في المطالبة؟** + يعرض حاليًا: `(Recipe → Food)` + هل يجب أن يكون: `(fo/Recipe → fo/Food)`؟ + +3. **هل يجب علينا التحقق من صحة قيود النطاق/المدى؟** + ملاحظة TODO في extract.py:470 + سيكتشف المزيد من الأخطاء ولكنه أكثر تعقيدًا + +4. **ماذا عن الخصائص العكسية والتكافؤات؟** + تحتوي الأونطولوجيا على `owl:inverseOf`، `owl:equivalentClass` + لا يتم استخدامه حاليًا في الاستخراج + هل يجب أن يتم استخدامه؟ + +## مقاييس النجاح + +✅ عدم وجود فقدان لمعلومات URI (100٪ للحفاظ على URIs الأصلية) +✅ تنسيق إخراج LLM يطابق تنسيق الإدخال +✅ لا توجد أمثلة غامضة في المطالبة +✅ اجتياز الاختبارات مع العديد من الأونطولوجيات +✅ تحسين جودة الاستخراج (يتم قياسه بالنسبة المئوية للثلاثيات الصالحة) + +## نهج بديل: تنسيق استخراج مبسط + +### الفلسفة + +بدلاً من مطالبة LLM بفهم دلالات RDF/OWL، اطلب منه فعل ما هو جيد فيه: **العثور على الكيانات والعلاقات في النص**. + +دع الكود يتعامل مع بناء URI، وتحويل RDF، والشؤون الرسمية للويب الدلالي. + +### مثال: تصنيف الكيانات + +**النص المدخل:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**مخطط علم الوجود (يُعرض على نموذج اللغة الكبير):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**ماذا يُرجع نموذج اللغة الكبير (JSON بسيط):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**ما الذي ينتجه الكود (ثلاثيات RDF):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### المزايا + +1. **نموذج اللغة الكبير (LLM) لا يحتاج إلى:** + فهم بناء جمل URI + اختراع بادئات المعرفات (`recipe:`، `ingredient:`) + معرفة عن `rdf:type` أو `rdfs:label` + إنشاء معرفات الويب الدلالي + +2. **نموذج اللغة الكبير (LLM) يحتاج فقط إلى:** + العثور على الكيانات في النص + ربطها بفئات علم الوجود + استخراج العلاقات والسمات + +3. **الكود يتعامل مع:** + تطبيع وبناء URI + توليد ثلاثيات RDF + تعيين تسميات تلقائيًا + إدارة مساحات الأسماء + +### لماذا هذا أفضل + +**موجه أبسط** = تقليل الارتباك = تقليل الأخطاء +**معرفات متسقة** = الكود يتحكم في قواعد التطبيع +**تسميات مُولدة تلقائيًا** = لا توجد ثلاثيات rdfs:label مفقودة +**يركز نموذج اللغة الكبير على الاستخراج** = وهو ما يتقنه بالفعل + +### مثال: علاقات الكيانات + +**النص المدخل:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**مخطط علم الوجود (معروض للنموذج اللغوي الكبير):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**ماذا يُرجع نموذج اللغة الكبير (JSON بسيط):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**ما الذي ينتجه الكود (ثلاثيات RDF):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**النقاط الرئيسية:** +تقوم نماذج اللغة الكبيرة بإرجاع أسماء الكيانات باللغة الطبيعية: `"Cornish pasty"`، `"beef"`، `"potatoes"` +تتضمن نماذج اللغة الكبيرة أنواعًا لتوضيح المعنى: `subject-type`، `object-type` +تستخدم نماذج اللغة الكبيرة اسم العلاقة من المخطط: `"has_ingredient"` +تستخدم الشيفرة معرّفات متسقة باستخدام (الاسم، النوع): `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +تبحث الشيفرة عن عنوان URI للعلاقة من علم الوجود: `fo/has_ingredient` → عنوان URI الكامل +دائمًا ما تحصل المجموعة نفسها (الاسم، النوع) على نفس عنوان URI (إزالة التكرار) + +### مثال: التمييز بين أسماء الكيانات + +**المشكلة:** يمكن أن يشير نفس الاسم إلى أنواع مختلفة من الكيانات. + +**حالة واقعية:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**كيف يتم التعامل معها:** + +يقوم نموذج اللغة الكبير بإرجاع كليهما ككيانات منفصلة: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**حل التعليمات البرمجية:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**لماذا هذا يعمل:** +يتم تضمين النوع في جميع المراجع (الكيانات، والعلاقات، والسمات). +يستخدم الكود `(name, type)` كـ "مجموعة" (tuple) كمفتاح للبحث. +لا يوجد غموض، ولا توجد تعارضات. + +### مثال: سمات الكيان + +**النص المدخل:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**مخطط علم الوجود (يُعرض على نموذج اللغة الكبير):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**ماذا يُرجع نموذج اللغة الكبير (JSON بسيط):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**ما الذي ينتجه الكود (ثلاثيات RDF):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**النقاط الرئيسية:** +يستخرج نموذج اللغة الكبير القيم الحرفية: `"4-6 people"`، `"45 minutes"` +يتضمن نموذج اللغة الكبير نوع الكيان لتوضيح المعنى: `entity-type` +يستخدم نموذج اللغة الكبير اسم الخاصية من المخطط: `"serves"`، `"preparation_time"` +يبحث الكود عن عنوان URI للخاصية من خصائص نوع البيانات في علم الوجود. +**الكائن هو قيمة حرفية** (`is_uri=False`)، وليس مرجع URI. +تظل القيم كنص طبيعي، ولا تحتاج إلى تطبيع. + +**الفرق عن العلاقات:** +العلاقات: كل من الموضوع والمفعول به هما كيانات (URIs). +الخصائص: الموضوع هو كيان (URI)، والمفعول به هو قيمة حرفية (نص/رقم). + +### مثال كامل: الكيانات + العلاقات + الخصائص + +**النص المدخل:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**ماذا يُرجع نموذج اللغة الكبير:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**النتيجة:** تم توليد 11 ثلاثية RDF: +3 ثلاثيات لنوع الكيان (rdf:type) +3 ثلاثيات لملصق الكيان (rdfs:label) - تلقائي +2 ثلاثية للعلاقة (has_ingredient) +1 ثلاثية للخاصية (serves) + +كل ذلك من خلال استخلاص بسيط وسهل من اللغة الطبيعية بواسطة نموذج اللغة الكبير! + +## المراجع + +التنفيذ الحالي: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +قالب التعليمات: `ontology-prompt.md` +حالات الاختبار: `tests/unit/test_extract/test_ontology/` +مثال على علم الوجود: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.es.md b/docs/tech-specs/ontology-extract-phase-2.es.md new file mode 100644 index 00000000..a57133a9 --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.es.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "Extracción de Conocimiento Ontológico - Fase 2, Refactorización" +parent: "Spanish (Beta)" +--- + +# Extracción de Conocimiento Ontológico - Fase 2, Refactorización + +> **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**: Sesión de Análisis 2025-12-03 +**Relacionado**: `ontology.md`, `ontorag.md` + +## Resumen + +Este documento identifica inconsistencias en el sistema actual de extracción de conocimiento basado en ontologías y propone una refactorización para mejorar el rendimiento de los LLM y reducir la pérdida de información. + +## Implementación Actual + +### Cómo Funciona Actualmente + +1. **Carga de la Ontología** (`ontology_loader.py`) + Carga el archivo JSON de la ontología con claves como `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` + Los ID de las clases incluyen el prefijo del espacio de nombres en la clave. + Ejemplo de `food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **Construcción del prompt** (`extract.py:299-307`, `ontology-prompt.md`) + La plantilla recibe diccionarios `classes`, `object_properties`, `datatype_properties` + La plantilla itera: `{% for class_id, class_def in classes.items() %}` + El LLM ve: `**fo/Recipe**: A Recipe is a combination...` + El formato de salida de ejemplo muestra: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **Análisis de la respuesta** (`extract.py:382-428`) + Espera un array JSON: `[{"subject": "...", "predicate": "...", "object": "..."}]` + Valida contra un subconjunto de la ontología + Expande los URIs mediante `expand_uri()` (extract.py:473-521) + +4. **Expansión de URIs** (`extract.py:473-521`) + Comprueba si el valor está en el diccionario `ontology_subset.classes` + Si se encuentra, extrae el URI de la definición de la clase + Si no se encuentra, construye el URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### Ejemplo de flujo de datos + +**JSON de la ontología → Loader → Prompt:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**LLM → Analizador → Salida:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## Problemas Identificados + +### 1. **Ejemplos Inconsistentes en la Instrucción** + +**Problema**: La plantilla de la instrucción muestra ID de clase con prefijos (`fo/Recipe`) pero la salida de ejemplo utiliza nombres de clase sin prefijos (`Recipe`). + +**Ubicación**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**Impacto**: El modelo de lenguaje (LLM) recibe señales contradictorias sobre qué formato utilizar. + +### 2. **Pérdida de información en la expansión de URI** + +**Problema**: Cuando el LLM devuelve nombres de clase sin prefijo, siguiendo el ejemplo, `expand_uri()` no puede encontrarlos en el diccionario de ontología y construye URI de respaldo, perdiendo los URI originales correctos. + +**Ubicación**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**Impacto:** +URI original: `http://purl.org/ontology/fo/Recipe` +URI construido: `https://trustgraph.ai/ontology/food#Recipe` +Significado semántico perdido, interrumpe la interoperabilidad. + +### 3. **Formato ambiguo de instancia de entidad** + +**Problema:** No hay una guía clara sobre el formato de la URI de la instancia de entidad. + +**Ejemplos en la solicitud:** +`"recipe:cornish-pasty"` (prefijo similar a un espacio de nombres) +`"ingredient:flour"` (prefijo diferente) + +**Comportamiento real** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**Impacto**: El modelo de lenguaje debe adivinar la convención de prefijos sin contexto ontológico. + +### 4. **Sin Guía de Prefijos de Espacio de Nombres** + +**Problema**: El archivo JSON de la ontología contiene definiciones de espacios de nombres (líneas 10-25 en food.ontology): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +Pero estas líneas nunca se muestran al LLM. El LLM no sabe: +Qué significa "fo" +Qué prefijo usar para las entidades +A qué espacio de nombres se aplica a qué elementos + +### 5. **Etiquetas No Utilizadas en el Prompt** + +**Problema**: Cada clase tiene campos `rdfs:label` (por ejemplo, `{"value": "Recipe", "lang": "en-gb"}`), pero la plantilla del prompt no los utiliza. + +**Actual**: Muestra solo `class_id` y `comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**Disponible pero no utilizado**: +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**Impacto**: Podría proporcionar nombres legibles por humanos junto con identificadores técnicos. + +## Soluciones propuestas + +### Opción A: Normalizar a identificadores sin prefijos + +**Enfoque**: Eliminar los prefijos de los identificadores de clase antes de mostrarlos al LLM. + +**Cambios**: +1. Modificar `build_extraction_variables()` para transformar las claves: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. Actualizar el ejemplo de la instrucción para que coincida (ya utiliza nombres sin prefijos). + +3. Modificar `expand_uri()` para que gestione ambos formatos: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**Ventajas:** +Más limpio, más legible para los humanos. +Coincide con ejemplos de prompts existentes. +Los LLM funcionan mejor con tokens más simples. + +**Desventajas:** +Colisiones de nombres de clase si múltiples ontologías tienen el mismo nombre de clase. +Pierde la información del espacio de nombres. +Requiere lógica de respaldo para las búsquedas. + +### Opción B: Utilizar IDs con Prefijos Completos de Forma Consistente + +**Enfoque:** Actualizar los ejemplos para utilizar IDs con prefijos que coincidan con lo que se muestra en la lista de clases. + +**Cambios:** +1. Actualizar el ejemplo del prompt (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. Agregar una explicación del espacio de nombres a la instrucción: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. Mantener `expand_uri()` tal cual (funciona correctamente cuando se encuentran coincidencias). + +**Ventajas**: +Consistencia entre entrada y salida. +Sin pérdida de información. +Preserva la semántica del espacio de nombres. +Funciona con múltiples ontologías. + +**Desventajas**: +Tokens más verbosos para el LLM. +Requiere que el LLM rastree los prefijos. + +### Opción C: Híbrida: Mostrar tanto la etiqueta como el ID. + +**Enfoque**: Mejorar el prompt para mostrar tanto las etiquetas legibles por humanos como los ID técnicos. + +**Cambios**: +1. Actualizar la plantilla del prompt: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + Ejemplo de salida: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. Instrucciones de actualización: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**Ventajas**: +Más claro para los modelos de lenguaje (LLM). +Preserva toda la información. +Explícito sobre qué usar. + +**Desventajas**: +Requiere un prompt más largo. +Plantilla más compleja. + +## Enfoque Implementado + +**Formato Simplificado de Entidad-Relación-Atributo** - reemplaza completamente el formato basado en triples anterior. + +El nuevo enfoque se eligió porque: + +1. **Sin Pérdida de Información**: Los URI originales se conservan correctamente. +2. **Lógica Más Simple**: No se necesita transformación, las búsquedas directas en diccionarios funcionan. +3. **Seguridad de Espacios de Nombres**: Maneja múltiples ontologías sin colisiones. +4. **Corrección Semántica**: Mantiene la semántica RDF/OWL. + +## Implementación Completada + +### Lo que se Construyó: + +1. **Nueva Plantilla de Prompt** (`prompts/ontology-extract-v2.txt`) + ✅ Secciones claras: Tipos de Entidad, Relaciones, Atributos. + ✅ Ejemplo utilizando identificadores de tipo completos (`fo/Recipe`, `fo/has_ingredient`). + ✅ Instrucciones para usar los identificadores exactos del esquema. + ✅ Nuevo formato JSON con matrices de entidades/relaciones/atributos. + +2. **Normalización de Entidades** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - Convierte los nombres a un formato seguro para URI. + ✅ `normalize_type_identifier()` - Maneja las barras diagonales en los tipos (`fo/Recipe` → `fo-recipe`). + ✅ `build_entity_uri()` - Crea URI únicos utilizando la tupla (nombre, tipo). + ✅ `EntityRegistry` - Realiza un seguimiento de las entidades para la eliminación de duplicados. + +3. **Analizador JSON** (`simplified_parser.py`) + ✅ Analiza el nuevo formato: `{entities: [...], relationships: [...], attributes: [...]}` + ✅ Admite nombres de campo en formato kebab-case y snake_case. + ✅ Devuelve clases de datos estructuradas. + ✅ Manejo de errores con registro. + +4. **Convertidor de Triples** (`triple_converter.py`) + ✅ `convert_entity()` - Genera automáticamente triples de tipo + etiqueta. + ✅ `convert_relationship()` - Conecta los URI de las entidades a través de propiedades. + ✅ `convert_attribute()` - Agrega valores literales. + ✅ Busca URI completos a partir de las definiciones de la ontología. + +5. **Procesador Principal Actualizado** (`extract.py`) + ✅ Se eliminó el código antiguo de extracción basado en triples. + ✅ Se agregó el método `extract_with_simplified_format()`. + ✅ Ahora utiliza exclusivamente el nuevo formato simplificado. + ✅ Llama al indicador con el ID `extract-with-ontologies-v2`. + +## Casos de Prueba + +### Prueba 1: Preservación de URI +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### Prueba 2: Colisión Multi-Ontología +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### Prueba 3: Formato de Instancia de Entidad +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## Preguntas Abiertas + +1. **¿Deben las instancias de entidades usar prefijos de espacio de nombres?** + Actual: `"recipe:cornish-pasty"` (arbitrario) + Alternativa: ¿Usar prefijo de ontología `"fo:cornish-pasty"`? + Alternativa: Sin prefijo, expandir en URI `"cornish-pasty"` → URI completa? + +2. **¿Cómo manejar el dominio/rango en el prompt?** + Actualmente muestra: `(Recipe → Food)` + ¿Debería ser: `(fo/Recipe → fo/Food)`? + +3. **¿Debemos validar las restricciones de dominio/rango?** + TODO comentario en extract.py:470 + Detectaría más errores pero sería más complejo + +4. **¿Qué tal las propiedades inversas y las equivalencias?** + La ontología tiene `owl:inverseOf`, `owl:equivalentClass` + Actualmente no se utilizan en la extracción + ¿Deberían usarse? + +## Métricas de Éxito + +✅ Pérdida de información de URI cero (100% de preservación de los URI originales) +✅ El formato de salida del LLM coincide con el formato de entrada +✅ No hay ejemplos ambiguos en el prompt +✅ Las pruebas pasan con múltiples ontologías +✅ Calidad de extracción mejorada (medida por el porcentaje de triples válidos) + +## Enfoque Alternativo: Formato de Extracción Simplificado + +### Filosofía + +En lugar de pedirle al LLM que comprenda la semántica de RDF/OWL, pídele que haga lo que hace bien: **encontrar entidades y relaciones en el texto**. + +Deje que el código se encargue de la construcción de URI, la conversión de RDF y las formalidades de la web semántica. + +### Ejemplo: Clasificación de Entidades + +**Texto de entrada:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**Esquema de Ontología (mostrado al LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**Lo que el LLM devuelve (JSON simple):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**¿Qué código produce (triples RDF):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### Beneficios + +1. **El LLM no necesita:** + Entender la sintaxis de URI + Inventar prefijos de identificadores (`recipe:`, `ingredient:`) + Conocer `rdf:type` o `rdfs:label` + Construir identificadores de la web semántica + +2. **El LLM solo necesita:** + Encontrar entidades en el texto + Mapearlas a clases de ontología + Extraer relaciones y atributos + +3. **El código se encarga de:** + Normalización y construcción de URI + Generación de triples RDF + Asignación automática de etiquetas + Gestión de espacios de nombres + +### ¿Por qué esto funciona mejor? + +**Indicación más simple** = menos confusión = menos errores +**IDs consistentes** = el código controla las reglas de normalización +**Etiquetas generadas automáticamente** = no faltan triples rdfs:label +**El LLM se centra en la extracción** = en lo que realmente es bueno + +### Ejemplo: Relaciones de Entidades + +**Texto de entrada:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**Esquema de Ontología (mostrado al LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**Lo que el LLM devuelve (JSON simple):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**¿Qué código produce (triples RDF):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**Puntos clave:** +El modelo de lenguaje (LLM) devuelve nombres de entidades en lenguaje natural: `"Cornish pasty"`, `"beef"`, `"potatoes"` +El LLM incluye tipos para disambiguar: `subject-type`, `object-type` +El LLM utiliza el nombre de la relación del esquema: `"has_ingredient"` +El código deriva IDs consistentes utilizando (nombre, tipo): `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +El código busca el URI de la relación en la ontología: `fo/has_ingredient` → URI completo +La misma tupla (nombre, tipo) siempre obtiene el mismo URI (desduplicación) + +### Ejemplo: Disambiguación del nombre de la entidad + +**Problema:** El mismo nombre puede referirse a diferentes tipos de entidad. + +**Caso real:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**Cómo se gestiona:** + +El modelo de lenguaje grande (LLM) devuelve ambos como entidades separadas: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**Resolución de código:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**¿Por qué funciona esto?:** +El tipo se incluye en TODAS las referencias (entidades, relaciones, atributos). +El código utiliza la tupla `(name, type)` como clave de búsqueda. +No hay ambigüedad, no hay colisiones. + +### Ejemplo: Atributos de Entidad + +**Texto de entrada:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**Esquema de Ontología (mostrado al LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**Lo que el LLM devuelve (JSON simple):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**¿Qué código produce (triples RDF):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**Puntos Clave:** +El LLM extrae valores literales: `"4-6 people"`, `"45 minutes"` +El LLM incluye el tipo de entidad para la desambiguación: `entity-type` +El LLM utiliza el nombre del atributo del esquema: `"serves"`, `"preparation_time"` +El código busca el URI del atributo de las propiedades del tipo de datos de la ontología +**El objeto es literal** (`is_uri=False`), no una referencia de URI +Los valores permanecen como texto natural, no se necesita normalización + +**Diferencia con las Relaciones:** +Relaciones: tanto el sujeto como el objeto son entidades (URIs) +Atributos: el sujeto es una entidad (URI), el objeto es un valor literal (cadena/número) + +### Ejemplo Completo: Entidades + Relaciones + Atributos + +**Texto de Entrada:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**Lo que el LLM devuelve:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**Resultado:** Se generaron 11 triples RDF: +3 triples de tipo de entidad (rdf:type) +3 triples de etiqueta de entidad (rdfs:label) - automático +2 triples de relación (has_ingredient) +1 triple de atributo (serves) + +¡Todo proviene de extracciones simples y en lenguaje natural realizadas por el LLM! + +## Referencias + +Implementación actual: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +Plantilla de prompt: `ontology-prompt.md` +Casos de prueba: `tests/unit/test_extract/test_ontology/` +Ontología de ejemplo: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.he.md b/docs/tech-specs/ontology-extract-phase-2.he.md new file mode 100644 index 00000000..413af4af --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.he.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "חילוץ ידע מתוך אונטולוגיות - שלב 2, שיפור מחדש" +parent: "Hebrew (Beta)" +--- + +# חילוץ ידע מתוך אונטולוגיות - שלב 2, שיפור מחדש + +> **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-12-03 +**קשור**: `ontology.md`, `ontorag.md` + +## סקירה כללית + +מסמך זה מזהה אי-התאמות במערכת הנוכחית לחילוץ ידע המבוססת על אונטולוגיות, ומציע שיפור מחדש כדי לשפר את הביצועים של מודלי שפה גדולים (LLM) ולהפחית אובדן מידע. + +## יישום נוכחי + +### איך זה עובד כרגע + +1. **טעינת אונטולוגיה** (`ontology_loader.py`) + טוען קובץ JSON של אונטולוגיה עם מפתחות כמו `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` + מזהי מחלקות כוללים את הקידומת של מרחב השמות במפתח עצמו + דוגמה מ-`food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **בניית הנחיה** (`extract.py:299-307`, `ontology-prompt.md`) + התבנית מקבלת מילונים `classes`, `object_properties`, `datatype_properties` + התבנית חוזרת: `{% for class_id, class_def in classes.items() %}` + מודל השפה (LLM) רואה: `**fo/Recipe**: A Recipe is a combination...` + פורמט פלט לדוגמה מציג: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **ניתוח תגובה** (`extract.py:382-428`) + מצפה למערך JSON: `[{"subject": "...", "predicate": "...", "object": "..."}]` + מאמת מול תת-אונטולוגיה + מרחיב URI באמצעות `expand_uri()` (extract.py:473-521) + +4. **הרחבת URI** (`extract.py:473-521`) + בודק אם הערך נמצא במילון `ontology_subset.classes` + אם נמצא, מחלץ את ה-URI מההגדרה של המחלקה + אם לא נמצא, בונה את ה-URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### דוגמה לזרימת נתונים + +**JSON של אונטולוגיה → Loader → Prompt:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**מודל שפה גדול → מנתח → פלט:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## בעיות שזוהו + +### 1. **דוגמאות לא עקביות בהנחיה** + +**בעיה**: תבנית ההנחיה מציגה מזהי מחלקות עם קידומות (`fo/Recipe`) אך הפלט לדוגמה משתמש בשמות מחלקות ללא קידומות (`Recipe`). + +**מיקום**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**השפעה**: מודל השפה הגדול (LLM) מקבל אותות סותרים לגבי הפורמט שיש להשתמש בו. + +### 2. **אובדן מידע בהרחבת כתובות URL** + +**בעיה**: כאשר מודל השפה הגדול (LLM) מחזיר שמות מחלקות ללא קידומת, בהתאם לדוגמה, `expand_uri()` לא יכול למצוא אותם במילון האונטולוגיה ויוצר כתובות URL חלופיות, ובכך מאבד את כתובות ה-URL המקוריות הנכונות. + +**מיקום**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**השפעה:** +URI מקורי: `http://purl.org/ontology/fo/Recipe` +URI שנוצר: `https://trustgraph.ai/ontology/food#Recipe` +אובדן משמעות סמנטית, פוגע בתאימות. + +### 3. **פורמט לא ברור של מופעי ישויות** + +**בעיה:** אין הנחיות ברורות לגבי פורמט ה-URI של מופעי ישויות. + +**דוגמאות בהנחיה:** +`"recipe:cornish-pasty"` (קידומת הדומה לשם מרחב) +`"ingredient:flour"` (קידומת שונה) + +**התנהגות בפועל** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**השפעה**: מודל שפה גדול (LLM) חייב לנחש את מוסכמות הקידומת ללא הקשר אונטולוגי. + +### 4. **הנחיות לגבי קידומות מרחבי שמות חסרות** + +**בעיה**: קובץ ה-JSON של האונטולוגיה מכיל הגדרות מרחבי שמות (שורות 10-25 בקובץ food.ontology): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +אבל השורות האלה לעולם אינן מוצגות למודל השפה הגדול (LLM). מודל השפה הגדול אינו יודע: +מה המשמעות של "fo" +איזה קידומת להשתמש עבור ישויות +לאיזה מרחב שם מתייחס כל אלמנט + +### 5. **תוויות שאינן משמשות בפרומפט** + +**בעיה**: לכל מחלקה יש שדות `rdfs:label` (לדוגמה, `{"value": "Recipe", "lang": "en-gb"}`), אבל תבנית הפרומפט אינה משתמשת בהם. + +**מצב נוכחי**: מציג רק `class_id` ו-`comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**זמין אך לא בשימוש:** +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**השפעה:** יכול לספק שמות קריאים לבני אדם לצד מזהים טכניים. + +## פתרונות מוצעים + +### אפשרות א': נרמול למזהים ללא קידומת + +**גישה:** הסרת קידומות ממזהי מחלקות לפני הצגתם למודל LLM. + +**שינויים:** +1. שנה את `build_extraction_variables()` כדי לשנות מפתחות: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. עדכון דוגמת ההנחיה כך שתתאים (כבר משתמשת בשמות ללא קידומת). + +3. שינוי `expand_uri()` כדי לטפל בשני הפורמטים: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**יתרונות:** +נקי יותר, קריא יותר לבני אדם +תואם לדוגמאות קיימות של הנחיות +מודלי שפה גדולים (LLMs) עובדים טוב יותר עם טוקנים פשוטים יותר + +**חסרונות:** +התנגשויות בשמות מחלקות אם למספר אונטולוגיות יש אותו שם מחלקה +מאבד מידע על מרחב השמות +דורש לוגיקה חלופית עבור חיפושים + +### אפשרות ב': שימוש עקבי במזהים עם קידומת מלאה + +**גישה:** עדכון הדוגמאות לשימוש במזהים עם קידומת התואמים למה שמוצג ברשימת המחלקות. + +**שינויים:** +1. עדכון דוגמת הנחיה (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. הוספת הסבר על מרחב הnamespaces להנחיה: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. שמרו על `expand_uri()` כפי שהוא (עובד כראוי כאשר נמצאו התאמות). + +**יתרונות:** +עקביות בין קלט לפלט. +ללא אובדן מידע. +שומר על סמנטיקת מרחבי השמות. +עובד עם מרובות אונטולוגיות. + +**חסרונות:** +טוקנים מילוליים יותר עבור מודל שפה גדול (LLM). +דורש ממודל השפה הגדול (LLM) לעקוב אחר קידומות. + +### אפשרות ג': היברידית - הצגת תווית ומזהה כאחד. + +**גישה:** שיפור ההנחיה להצגת תוויות קריאות אנוש ומזהים טכניים. + +**שינויים:** +1. עדכון תבנית ההנחיה: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + פלט לדוגמה: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. הוראות עדכון: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**יתרונות:** +הבהרה עבור מודלי שפה גדולים (LLM) +שומר על כל המידע +מפרט במפורש מה להשתמש + +**חסרונות:** +הנחיה ארוכה יותר +תבנית מורכבת יותר + +## גישה מיושמת + +**פורמט פשוט של ישות-קשר-תכונה** - מחליף לחלוטין את הפורמט המבוסס על שלישיות הישן. + +הגישה החדשה נבחרה מכיוון: + +1. **ללא אובדן מידע:** כתובות URI מקוריות נשמרות כהלכה +2. **לוגיקה פשוטה יותר:** אין צורך בטרנספורמציה, חיפושים ישירים במילון עובדים +3. **בטיחות מרחבי שמות:** מטפל במספר אונטולוגיות ללא התנגשויות +4. **נכונות סמנטית:** שומר על סמנטיקה של RDF/OWL + +## יישום הושלם + +### מה נבנה: + +1. **תבנית הנחיה חדשה** (`prompts/ontology-extract-v2.txt`) + ✅ חלקים ברורים: סוגי ישויות, קשרים, תכונות + ✅ דוגמה תוך שימוש במזהים מלאים של סוגים (`fo/Recipe`, `fo/has_ingredient`) + ✅ הוראות לשימוש במזהים מדויקים מהסכימה + ✅ פורמט JSON חדש עם מערכים של ישויות/קשרים/תכונות + +2. **נרמול ישויות** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - ממיר שמות לפורמט בטוח ל-URI + ✅ `normalize_type_identifier()` - מטפל בסלאשים בסוגים (`fo/Recipe` → `fo-recipe`) + ✅ `build_entity_uri()` - יוצר כתובות URI ייחודיות באמצעות טאפל (שם, סוג) + ✅ `EntityRegistry` - עוקב אחר ישויות לצורך הסרה כפולה + +3. **מנתח JSON** (`simplified_parser.py`) + ✅ מנתח את הפורמט החדש: `{entities: [...], relationships: [...], attributes: [...]}` + ✅ תומך בשמות שדות בפורמט kebab-case ו-snake_case + ✅ מחזיר מחלקות נתונים מובנות + ✅ טיפול בשגיאות בצורה חלקה עם רישום + +4. **ממיר שלישיות** (`triple_converter.py`) + ✅ `convert_entity()` - מייצר באופן אוטומטי שלישיות של סוג + תווית + ✅ `convert_relationship()` - מחבר כתובות URI של ישויות באמצעות מאפיינים + ✅ `convert_attribute()` - מוסיף ערכים מילוליים + ✅ מחפש כתובות URI מלאות מהגדרות האונטולוגיה + +5. **מעבד ראשי מעודכן** (`extract.py`) + ✅ הסר קוד חילוץ ישן מבוסס על שלישיות + ✅ הוסף שיטה `extract_with_simplified_format()` + ✅ משתמש כעת אך ורק בפורמט הפשוט החדש + ✅ קורא להנחיה עם מזהה `extract-with-ontologies-v2` + +## מקרי בדיקה + +### בדיקה 1: שימור כתובות URI +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### מבחן 2: התנגשות בין מרובי אונטולוגיות +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### מבחן 3: פורמט של מופע ישות +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## שאלות פתוחות + +1. **האם יש להשתמש בתוספות מרחב שם עבור מופעי ישויות?** + נוכחי: `"recipe:cornish-pasty"` (שרירותי) + חלופה: להשתמש בתוסף אוֹנוֹטוֹלוֹגיה `"fo:cornish-pasty"`? + חלופה: ללא תוסף, להרחיב ב-URI `"cornish-pasty"` → URI מלא? + +2. **כיצד לטפל בתחום/טווח בפרומפט?** + מוצג כעת: `(Recipe → Food)` + האם זה צריך להיות: `(fo/Recipe → fo/Food)`? + +3. **האם עלינו לאמת אילוצי תחום/טווח?** + הערה TODO ב-extract.py:470 + יתפוס יותר שגיאות אך מורכב יותר + +4. **מה לגבי תכונות הפוכות ושקילות?** + לאוֹנוֹטוֹלוֹגיה יש `owl:inverseOf`, `owl:equivalentClass` + לא בשימוש כרגע בחילוץ + האם הם צריכים להיות בשימוש? + +## מדדי הצלחה + +✅ אפס אובדן מידע URI (שימור של 100% מה-URIs המקוריים) +✅ פורמט הפלט של ה-LLM תואם לפורמט הקלט +✅ אין דוגמאות מעורפלות בפרומפט +✅ הבדיקות עוברות עם אוֹנוֹטוֹלוֹגיות מרובות +✅ שיפור באיכות החילוץ (נמדד על ידי אחוז משולשות חוקיות) + +## גישה חלופית: פורמט חילוץ מפושט + +### פילוסופיה + +במקום לבקש מה-LLM להבין סמנטיקה של RDF/OWL, לבקש ממנו לעשות את מה שהוא טוב בו: **למצוא ישויות ויחסים בטקסט**. + +תן לקוד לטפל בבניית URI, המרת RDF ופורמליות של רשת סמנטית. + +### דוגמה: סיווג ישויות + +**טקסט קלט:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**סכימת אונטולוגיה (מוצגת למודל שפה גדול):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**מה שהמודל השפה הגדול מחזיר (JSON פשוט):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**מה הקוד מייצר (משולשי RDF):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### יתרונות + +1. **מודל שפה גדול (LLM) לא צריך:** + להבין תחביר URI + להמציא קידומות מזהות (`recipe:`, `ingredient:`) + לדעת על `rdf:type` או `rdfs:label` + לבנות מזהי רשת סמנטית + +2. **מודל שפה גדול (LLM) צריך רק:** + למצוא ישויות בטקסט + למפות אותן למחלקות אונטולוגיה + לחלץ קשרים ומאפיינים + +3. **הקוד מטפל ב:** + נרמול ובניית URI + יצירת משולשות RDF + הקצאת תוויות אוטומטית + ניהול מרחבי שמות + +### למה זה עובד טוב יותר + +**שאילתה פשוטה יותר** = פחות בלבול = פחות שגיאות +**מזהים עקביים** = הקוד שולט בכללי הנרמול +**תוויות שנוצרו אוטומטית** = אין משולשות rdfs:label חסרות +**מודל שפה גדול מתמקד בחילוץ** = במה שהוא באמת טוב + +### דוגמה: קשרי ישויות + +**טקסט קלט:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**סכימת אונטולוגיה (מוצגת למודל שפה גדול):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**מה שהמודל השפה הגדול מחזיר (JSON פשוט):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**מה הקוד מייצר (משולשי RDF):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**נקודות עיקריות:** +מודל שפה גדול (LLM) מחזיר שמות של ישויות בשפה טבעית: `"Cornish pasty"`, `"beef"`, `"potatoes"` +מודל שפה גדול (LLM) כולל סוגים כדי להבהיר: `subject-type`, `object-type` +מודל שפה גדול (LLM) משתמש בשם היחס מהסכימה: `"has_ingredient"` +הקוד מייצר מזהים עקביים באמצעות (שם, סוג): `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +הקוד מחפש את ה-URI של היחס מהאונטולוגיה: `fo/has_ingredient` → URI מלא +אותה טופל (שם, סוג) תמיד מקבל את אותו ה-URI (הסרה כפילות) + +### דוגמה: הבחנה בין שמות של ישויות + +**בעיה:** אותו שם יכול להתייחס לסוגי ישויות שונים. + +**מקרה אמיתי:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**כיצד זה מטופל:** + +מודל שפה גדול (LLM) מחזיר את שניהם כיחידות נפרדות: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**פתרון קוד:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**מדוע זה עובד:** +הסוג כלול בכל ההפניות (ישויות, קשרים, תכונות) +הקוד משתמש בטופל `(name, type)` כמפתח חיפוש +אין דו-משמעות, אין התנגשויות + +### דוגמה: תכונות של ישויות + +**טקסט קלט:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**סכימת אונטולוגיה (מוצגת למודל שפה גדול):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**מה שהמודל השפה הגדול מחזיר (JSON פשוט):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**מה הקוד מייצר (משולשים RDF):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**נקודות עיקריות:** +מודל שפה גדול (LLM) מחלץ ערכים מילוליים: `"4-6 people"`, `"45 minutes"` +מודל שפה גדול (LLM) כולל סוג ישות לצורך הבחנה: `entity-type` +מודל שפה גדול (LLM) משתמש בשם תכונה מהסכימה: `"serves"`, `"preparation_time"` +הקוד מחפש את ה-URI של התכונה ממאפייני סוג הנתונים של האונטולוגיה +**האובייקט הוא מילולי** (`is_uri=False`), ולא הפניה ל-URI +הערכים נשארים כטקסט רגיל, אין צורך בנרמול + +**ההבדל מיחסים:** +יחסים: גם הנושא וגם האובייקט הם ישויות (URIs) +תכונות: הנושא הוא ישות (URI), האובייקט הוא ערך מילולי (מחרוזת/מספר) + +### דוגמה מלאה: ישויות + יחסים + תכונות + +**טקסט קלט:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**מה מודל שפה גדול מחזיר:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**תוצאה:** נוצרו 11 משולשים של RDF: +3 משולשים מסוג ישות (rdf:type) +3 משולשים של תווית ישות (rdfs:label) - אוטומטי +2 משולשים של קשר (has_ingredient) +משולש אחד של תכונה (serves) + +הכל נוצר מחילוץ פשוט משפה טבעית על ידי מודל השפה הגדול! + +## הפניות + +יישום נוכחי: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +תבנית הנחיה: `ontology-prompt.md` +מקרים בדיקה: `tests/unit/test_extract/test_ontology/` +אונטולוגיה לדוגמה: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.hi.md b/docs/tech-specs/ontology-extract-phase-2.hi.md new file mode 100644 index 00000000..9152ee95 --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.hi.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "ऑन्टोलॉजी ज्ञान निष्कर्षण - चरण 2 का पुनर्गठन" +parent: "Hindi (Beta)" +--- + +# ऑन्टोलॉजी ज्ञान निष्कर्षण - चरण 2 का पुनर्गठन + +> **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-12-03 +**संबंधित**: `ontology.md`, `ontorag.md` + +## अवलोकन + +यह दस्तावेज़ वर्तमान ऑन्टोलॉजी-आधारित ज्ञान निष्कर्षण प्रणाली में मौजूद विसंगतियों की पहचान करता है और एलएलएम प्रदर्शन को बेहतर बनाने और सूचना हानि को कम करने के लिए एक पुनर्गठन का प्रस्ताव करता है। + +## वर्तमान कार्यान्वयन + +### यह वर्तमान में कैसे काम करता है + +1. **ऑन्टोलॉजी लोडिंग** (`ontology_loader.py`) + `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` जैसे कुंजियों के साथ ऑन्टोलॉजी JSON लोड करता है। + क्लास आईडी में नामस्थान उपसर्ग स्वयं कुंजी में शामिल होता है। + `food.ontology` से उदाहरण: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **प्रॉम्प्ट निर्माण** (`extract.py:299-307`, `ontology-prompt.md`) + टेम्पलेट को `classes`, `object_properties`, `datatype_properties` डिक्ट प्राप्त होते हैं। + टेम्पलेट पुनरावृति करता है: `{% for class_id, class_def in classes.items() %}` + एलएलएम देखता है: `**fo/Recipe**: A Recipe is a combination...` + उदाहरण आउटपुट प्रारूप दर्शाता है: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **प्रतिक्रिया पार्सिंग** (`extract.py:382-428`) + JSON सरणी की अपेक्षा है: `[{"subject": "...", "predicate": "...", "object": "..."}]` + यह एक उप-शब्दकोष के विरुद्ध मान्य है। + `expand_uri()` के माध्यम से URI का विस्तार (extract.py:473-521) + +4. **URI विस्तार** (`extract.py:473-521`) + जांच करता है कि क्या मान `ontology_subset.classes` डिक्शनरी में है। + यदि पाया जाता है, तो क्लास परिभाषा से URI निकालता है। + यदि नहीं मिला, तो URI का निर्माण करता है: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### डेटा प्रवाह उदाहरण + +**शब्दकोष JSON → लोडर → प्रॉम्प्ट:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**एलएलएम → पार्सर → आउटपुट:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## पहचाने गए मुद्दे + +### 1. **प्रॉम्प्ट में असंगत उदाहरण** + +**समस्या**: प्रॉम्प्ट टेम्पलेट क्लास आईडी को उपसर्गों (`fo/Recipe`) के साथ दिखाता है, लेकिन उदाहरण आउटपुट में उपसर्ग रहित क्लास नाम (`Recipe`) का उपयोग किया गया है। + +**स्थान**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**प्रभाव**: एलएलएम को किस प्रारूप का उपयोग करना है, इसके बारे में विरोधाभासी संकेत प्राप्त होते हैं। + +### 2. **यूआरआई विस्तार में सूचना का नुकसान** + +**समस्या**: जब एलएलएम उदाहरण के बाद बिना उपसर्ग वाले क्लास नामों को लौटाता है, तो `expand_uri()` उन्हें ऑन्टोलॉजी डिक्शनरी में नहीं ढूंढ पाता है और डिफ़ॉल्ट यूआरआई बनाता है, जिससे मूल सही यूआरआई खो जाते हैं। + +**स्थान**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**प्रभाव:** +मूल यूआरआई: `http://purl.org/ontology/fo/Recipe` +निर्मित यूआरआई: `https://trustgraph.ai/ontology/food#Recipe` +अर्थ संबंधी जानकारी खो जाती है, इससे अंतर-क्षमता बाधित होती है। + +### 3. **अस्पष्ट इकाई उदाहरण प्रारूप** + +**समस्या:** इकाई उदाहरण यूआरआई प्रारूप के बारे में कोई स्पष्ट मार्गदर्शन नहीं है। + +**प्रॉम्प्ट में उदाहरण:** +`"recipe:cornish-pasty"` (नेमस्पेस जैसा उपसर्ग) +`"ingredient:flour"` (एक अलग उपसर्ग) + +**वास्तविक व्यवहार** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**प्रभाव**: एलएलएम को किसी भी संदर्भ के बिना उपसर्ग सम्मेलन का अनुमान लगाना होगा। + +### 4. **कोई नेमस्पेस उपसर्ग मार्गदर्शन नहीं** + +**समस्या**: ऑन्टोलॉजी JSON में नेमस्पेस परिभाषाएँ हैं (food.ontology में पंक्ति 10-25): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +लेकिन ये जानकारी कभी भी एलएलएम (LLM) तक नहीं पहुंचती। एलएलएम को यह नहीं पता: +"fo" का क्या मतलब है +एंटिटीज के लिए किस उपसर्ग का उपयोग करना है +कौन सा नेमस्पेस किस तत्व पर लागू होता है + +### 5. **प्रॉम्प्ट में उपयोग नहीं किए गए लेबल** + +**समस्या**: प्रत्येक क्लास में `rdfs:label` फ़ील्ड होते हैं (उदाहरण के लिए, `{"value": "Recipe", "lang": "en-gb"}`), लेकिन प्रॉम्प्ट टेम्पलेट इनका उपयोग नहीं करता है। + +**वर्तमान**: केवल `class_id` और `comment` दिखाता है। +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**उपलब्ध लेकिन अप्रयुक्त**: +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**प्रभाव**: यह तकनीकी आईडी के साथ पठनीय नाम प्रदान कर सकता है। + +## प्रस्तावित समाधान + +### विकल्प ए: उपसर्ग रहित आईडी में मानकीकरण + +**दृष्टिकोण**: एलएलएम को दिखाने से पहले क्लास आईडी से उपसर्ग हटाएं। + +**परिवर्तन**: +1. `build_extraction_variables()` को बदलने के लिए: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. उदाहरण प्रॉम्प्ट को अपडेट करें ताकि वह मेल खाए (यह पहले से ही बिना उपसर्ग वाले नामों का उपयोग करता है)। + +3. `expand_uri()` को दोनों प्रारूपों को संभालने के लिए संशोधित करें: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**लाभ:** +अधिक स्पष्ट, अधिक मानव-पठनीय +मौजूदा प्रॉम्प्ट उदाहरणों से मेल खाता है +एलएलएम सरल टोकन के साथ बेहतर काम करते हैं + +**नुकसान:** +यदि कई ऑन्टोलॉजी में समान क्लास नाम है तो क्लास नाम टकराव हो सकता है +नेमस्पेस जानकारी खो जाती है +लुकअप के लिए फॉलबैक लॉजिक की आवश्यकता होती है + +### विकल्प बी: पूर्ण उपसर्ग आईडी का लगातार उपयोग करें + +**दृष्टिकोण:** उदाहरणों को अपडेट करें ताकि वे क्लास सूची में दिखाए गए उपसर्ग आईडी से मेल खाएं। + +**परिवर्तन:** +1. प्रॉम्प्ट उदाहरण अपडेट करें (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. प्रॉम्प्ट में नेमस्पेस स्पष्टीकरण जोड़ें: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. `expand_uri()` को वैसे ही रखें (जब मिलान पाया जाता है तो यह ठीक से काम करता है)। + +**लाभ:** +इनपुट = आउटपुट स्थिरता +कोई जानकारी हानि नहीं +नेमस्पेस सिमेंटिक्स को संरक्षित करता है +कई ऑन्टोलॉजी के साथ काम करता है + +**नुकसान:** +एलएलएम के लिए अधिक विस्तृत टोकन +एलएलएम को उपसर्गों को ट्रैक करने की आवश्यकता होती है + +### विकल्प सी: हाइब्रिड - लेबल और आईडी दोनों दिखाएं + +**दृष्टिकोण:** प्रॉम्प्ट को इस तरह से बेहतर बनाएं कि मानव-पठनीय लेबल और तकनीकी आईडी दोनों दिखाए जाएं। + +**परिवर्तन:** +1. प्रॉम्प्ट टेम्पलेट को अपडेट करें: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + उदाहरण आउटपुट: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. अपडेट निर्देश: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**लाभ:** +एलएलएम (LLM) के लिए सबसे स्पष्ट। +सभी जानकारी को संरक्षित करता है। +यह स्पष्ट करता है कि क्या उपयोग करना है। + +**नुकसान:** +लंबा प्रॉम्प्ट। +अधिक जटिल टेम्पलेट। + +## कार्यान्वित दृष्टिकोण + +**सरलीकृत इकाई-संबंध-विशेषता प्रारूप** - पुराने ट्रिपल-आधारित प्रारूप को पूरी तरह से बदल देता है। + +इस नए दृष्टिकोण को इसलिए चुना गया क्योंकि: + +1. **कोई जानकारी हानि नहीं:** मूल यूआरआई (URI) सही ढंग से संरक्षित हैं। +2. **सरल तर्क:** किसी रूपांतरण की आवश्यकता नहीं है, सीधे डिक्ट (dict) लुकअप काम करते हैं। +3. **नेमस्पेस सुरक्षा:** टकराव के बिना कई ऑन्टोलॉजी (ontology) को संभालता है। +4. **सिमेंटिक (semantic) शुद्धता:** आरडीएफ/ओडब्ल्यूएल (RDF/OWL) सिमेंटिक्स को बनाए रखता है। + +## कार्यान्वयन पूर्ण + +### क्या बनाया गया: + +1. **नया प्रॉम्प्ट टेम्पलेट** (`prompts/ontology-extract-v2.txt`) + ✅ स्पष्ट अनुभाग: इकाई प्रकार, संबंध, विशेषताएँ। + ✅ पूर्ण प्रकार पहचानकर्ताओं का उपयोग करके उदाहरण (`fo/Recipe`, `fo/has_ingredient`)। + ✅ स्कीमा (schema) से सटीक पहचानकर्ताओं का उपयोग करने के निर्देश। + ✅ संस्थाओं/संबंधों/विशेषताओं के सरणियों के साथ नया JSON प्रारूप। + +2. **एंटिटी नॉर्मलाइजेशन** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - नामों को URI-सुरक्षित प्रारूप में परिवर्तित करता है + ✅ `normalize_type_identifier()` - प्रकारों में स्लैश को संभालता है (`fo/Recipe` → `fo-recipe`) + ✅ `build_entity_uri()` - (नाम, प्रकार) टपल का उपयोग करके अद्वितीय URI बनाता है + ✅ `EntityRegistry` - डुप्लिकेट से बचने के लिए एंटिटीज को ट्रैक करता है + +3. **JSON पार्सर** (`simplified_parser.py`) + ✅ नए प्रारूप को पार्स करता है: `{entities: [...], relationships: [...], attributes: [...]}` + ✅ केबाब-केस और स्नेक_केस फ़ील्ड नामों का समर्थन करता है + ✅ संरचित डेटाक्लासेस लौटाता है + ✅ लॉगिंग के साथ त्रुटि प्रबंधन + +4. **ट्रिपल कन्वर्टर** (`triple_converter.py`) + ✅ `convert_entity()` - स्वचालित रूप से प्रकार + लेबल त्रिक उत्पन्न करता है। + ✅ `convert_relationship()` - एंटिटी यूआरआई को गुणों के माध्यम से जोड़ता है। + ✅ `convert_attribute()` - शाब्दिक मान जोड़ता है। + ✅ ऑन्टोलॉजी परिभाषाओं से पूर्ण यूआरआई की खोज करता है। + +5. **अपडेटेड मुख्य प्रोसेसर** (`extract.py`) + ✅ पुराने ट्रिपल-आधारित निष्कर्षण कोड को हटा दिया गया। + ✅ `extract_with_simplified_format()` विधि जोड़ी गई। + ✅ अब केवल नए सरलीकृत प्रारूप का उपयोग करता है। + ✅ `extract-with-ontologies-v2` आईडी के साथ प्रॉम्प्ट को कॉल करता है। + +## परीक्षण मामले + +### परीक्षण 1: यूआरआई संरक्षण +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### परीक्षण 2: बहु-ऑन्टोलॉजी टकराव +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### परीक्षण 3: इकाई उदाहरण प्रारूप +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## खुले प्रश्न + +1. **क्या एंटिटी इंस्टेंस में नेमस्पेस उपसर्गों का उपयोग किया जाना चाहिए?** + वर्तमान: `"recipe:cornish-pasty"` (यादृच्छिक) + वैकल्पिक: क्या हमें ऑन्टोलॉजी उपसर्ग `"fo:cornish-pasty"` का उपयोग करना चाहिए? + वैकल्पिक: कोई उपसर्ग नहीं, URI में विस्तार करें `"cornish-pasty"` → पूर्ण URI? + +2. **प्रॉम्प्ट में डोमेन/रेंज को कैसे संभालें?** + वर्तमान में दिखाता है: `(Recipe → Food)` + क्या इसे `(fo/Recipe → fo/Food)` होना चाहिए? + +3. **क्या हमें डोमेन/रेंज बाधाओं को मान्य करना चाहिए?** + TODO टिप्पणी extract.py:470 पर + यह अधिक त्रुटियों को पकड़ लेगा लेकिन अधिक जटिल होगा + +4. **उलटा गुण और तुल्यता के बारे में क्या?** + ऑन्टोलॉजी में `owl:inverseOf`, `owl:equivalentClass` है + वर्तमान में निष्कर्षण में उपयोग नहीं किया जाता है + क्या उन्हें उपयोग किया जाना चाहिए? + +## सफलता मेट्रिक्स + +✅ शून्य URI जानकारी हानि (मूल URIs का 100% संरक्षण) +✅ LLM आउटपुट प्रारूप इनपुट प्रारूप से मेल खाता है +✅ प्रॉम्प्ट में कोई अस्पष्ट उदाहरण नहीं +✅ कई ऑन्टोलॉजी के साथ परीक्षण पास होते हैं +✅ बेहतर निष्कर्षण गुणवत्ता (वैध ट्रिपल % द्वारा मापा गया) + +## वैकल्पिक दृष्टिकोण: सरलीकृत निष्कर्षण प्रारूप + +### दर्शन + +LLM से RDF/OWL सिमेंटिक्स को समझने के बजाय, उससे वह कार्य करवाएं जिसमें वह अच्छा है: **पाठ में एंटिटीज और संबंधों को ढूंढना।** + +URI निर्माण, RDF रूपांतरण और सिमेंटिक वेब औपचारिकताएं कोड द्वारा संभाली जाएं। + +### उदाहरण: एंटिटी वर्गीकरण + +**इनपुट टेक्स्ट:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**ऑन्टोलॉजी स्कीमा (एलएलएम को दिखाया गया):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**एलएलएम क्या लौटाता है (सरल JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**कोड क्या उत्पन्न करता है (आरडीएफ ट्रिपल्स):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### लाभ + +1. **एलएलएम को इसकी आवश्यकता नहीं है:** + यूआरआई सिंटैक्स को समझना + पहचानकर्ता उपसर्गों का आविष्कार करना (`recipe:`, `ingredient:`) + `rdf:type` या `rdfs:label` के बारे में जानना + सिमेंटिक वेब पहचानकर्ताओं का निर्माण करना + +2. **एलएलएम को केवल इसकी आवश्यकता है:** + पाठ में संस्थाओं को खोजना + उन्हें ऑन्टोलॉजी कक्षाओं में मैप करना + संबंधों और विशेषताओं को निकालना + +3. **कोड द्वारा संभाला जाता है:** + यूआरआई सामान्यीकरण और निर्माण + आरडीएफ ट्रिपल पीढ़ी + स्वचालित लेबल असाइनमेंट + नेमस्पेस प्रबंधन + +### यह बेहतर क्यों है + +**सरल प्रॉम्प्ट** = कम भ्रम = कम त्रुटियां +**संगत आईडी** = कोड सामान्यीकरण नियमों को नियंत्रित करता है +**स्वचालित रूप से उत्पन्न लेबल** = कोई छूटी हुई rdfs:label ट्रिपल नहीं +**एलएलएम निष्कर्षण पर केंद्रित है** = जो कि वास्तव में इसकी क्षमता है + +### उदाहरण: इकाई संबंध + +**इनपुट टेक्स्ट:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**ऑन्टोलॉजी स्कीमा (एलएलएम को दिखाया गया):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**एलएलएम क्या लौटाता है (सरल JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**कोड क्या उत्पन्न करता है (आरडीएफ ट्रिपल्स):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**मुख्य बातें:** +एलएलएम प्राकृतिक भाषा में इकाई नामों को लौटाता है: `"Cornish pasty"`, `"beef"`, `"potatoes"` +एलएलएम अस्पष्टता को दूर करने के लिए प्रकारों को शामिल करता है: `subject-type`, `object-type` +एलएलएम स्कीमा से संबंध नाम का उपयोग करता है: `"has_ingredient"` +कोड (नाम, प्रकार) का उपयोग करके सुसंगत आईडी प्राप्त करता है: `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +कोड ऑन्टोलॉजी से संबंध यूआरआई को देखता है: `fo/has_ingredient` → पूर्ण यूआरआई +समान (नाम, प्रकार) टपल हमेशा समान यूआरआई प्राप्त करता है (डुप्लिकेट हटाने)। + +### उदाहरण: इकाई नाम का अस्पष्टता निवारण + +**समस्या:** एक ही नाम अलग-अलग इकाई प्रकारों को संदर्भित कर सकता है। + +**वास्तविक दुनिया का मामला:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**यह कैसे संभाला जाता है:** + +एलएलएम दोनों को अलग-अलग इकाइयों के रूप में लौटाता है: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**कोड समाधान:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**यह क्यों काम करता है:** +प्रकार सभी संदर्भों (इकाइयों, संबंधों, विशेषताओं) में शामिल है। +कोड `(name, type)` टपल को लुकअप कुंजी के रूप में उपयोग करता है। +कोई अस्पष्टता नहीं, कोई टकराव नहीं। + +### उदाहरण: इकाई विशेषताएँ + +**इनपुट टेक्स्ट:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**ऑन्टोलॉजी स्कीमा (एलएलएम को दिखाया गया):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**एलएलएम क्या लौटाता है (सरल JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**कोड क्या उत्पन्न करता है (आरडीएफ ट्रिपल्स):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**मुख्य बातें:** +एलएलएम शाब्दिक मानों को निकालता है: `"4-6 people"`, `"45 minutes"` +एलएलएम अस्पष्टता को दूर करने के लिए इकाई प्रकार को शामिल करता है: `entity-type` +एलएलएम स्कीमा से विशेषता नाम का उपयोग करता है: `"serves"`, `"preparation_time"` +कोड ऑन्टोलॉजी डेटाटाइप गुणों से विशेषता यूआरआई को देखता है +**ऑब्जेक्ट शाब्दिक है** (`is_uri=False`), कोई यूआरआई संदर्भ नहीं है +मान प्राकृतिक पाठ के रूप में रहते हैं, किसी सामान्यीकरण की आवश्यकता नहीं है + +**संबंधों से अंतर:** +संबंध: विषय और वस्तु दोनों इकाइयाँ (यूआरआई) हैं +विशेषताएँ: विषय इकाई (यूआरआई) है, वस्तु शाब्दिक मान (स्ट्रिंग/संख्या) है + +### संपूर्ण उदाहरण: इकाइयाँ + संबंध + विशेषताएँ + +**इनपुट टेक्स्ट:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**एलएलएम क्या लौटाता है:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**परिणाम:** 11 आरडीएफ त्रिगुण उत्पन्न हुए: +3 इकाई प्रकार त्रिगुण (rdf:type) +3 इकाई लेबल त्रिगुण (rdfs:label) - स्वचालित +2 संबंध त्रिगुण (has_ingredient) +1 विशेषता त्रिगुण (serves) + +ये सभी एलएलएम द्वारा सरल, प्राकृतिक भाषा निष्कर्षण से प्राप्त हुए! + +## संदर्भ + +वर्तमान कार्यान्वयन: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +प्रॉम्प्ट टेम्पलेट: `ontology-prompt.md` +परीक्षण मामले: `tests/unit/test_extract/test_ontology/` +उदाहरण ऑन्टोलॉजी: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.md b/docs/tech-specs/ontology-extract-phase-2.md index ac1a0543..24eae437 100644 --- a/docs/tech-specs/ontology-extract-phase-2.md +++ b/docs/tech-specs/ontology-extract-phase-2.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Ontology Knowledge Extraction - Phase 2 Refactor" +parent: "Tech Specs" +--- + # Ontology Knowledge Extraction - Phase 2 Refactor **Status**: Draft diff --git a/docs/tech-specs/ontology-extract-phase-2.pt.md b/docs/tech-specs/ontology-extract-phase-2.pt.md new file mode 100644 index 00000000..613fdd29 --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.pt.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "Extração de Conhecimento de Ontologias - Fase 2 de Refatoração" +parent: "Portuguese (Beta)" +--- + +# Extração de Conhecimento de Ontologias - Fase 2 de Refatoração + +> **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**: Sessão de Análise 2025-12-03 +**Relacionado**: `ontology.md`, `ontorag.md` + +## Visão Geral + +Este documento identifica inconsistências no sistema atual de extração de conhecimento baseado em ontologias e propõe uma refatoração para melhorar o desempenho do LLM e reduzir a perda de informações. + +## Implementação Atual + +### Como Funciona Atualmente + +1. **Carregamento da Ontologia** (`ontology_loader.py`) + Carrega o arquivo JSON da ontologia com chaves como `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` + Os IDs das classes incluem o prefixo do namespace na própria chave + Exemplo de `food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **Construção do Prompt** (`extract.py:299-307`, `ontology-prompt.md`) + O modelo recebe os dicionários `classes`, `object_properties`, `datatype_properties` + O modelo itera: `{% for class_id, class_def in classes.items() %}` + O LLM vê: `**fo/Recipe**: A Recipe is a combination...` + O formato de saída de exemplo mostra: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **Análise da Resposta** (`extract.py:382-428`) + Espera um array JSON: `[{"subject": "...", "predicate": "...", "object": "..."}]` + Valida em relação a um subconjunto da ontologia + Expande URIs via `expand_uri()` (extract.py:473-521) + +4. **Expansão de URIs** (`extract.py:473-521`) + Verifica se o valor está no dicionário `ontology_subset.classes` + Se encontrado, extrai o URI da definição da classe + Se não encontrado, constrói o URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### Exemplo de Fluxo de Dados + +**JSON da Ontologia → Loader → Prompt:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**LLM → Parser → Output:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## Problemas Identificados + +### 1. **Exemplos Inconsistentes no Prompt** + +**Problema**: O modelo de prompt mostra IDs de classe com prefixos (`fo/Recipe`), mas a saída de exemplo usa nomes de classe sem prefixo (`Recipe`). + +**Localização**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**Impacto**: O LLM recebe sinais conflitantes sobre qual formato usar. + +### 2. **Perda de Informação na Expansão de URIs** + +**Problema**: Quando o LLM retorna nomes de classe sem prefixo, seguindo o exemplo, `expand_uri()` não consegue encontrá-los no dicionário de ontologias e constrói URIs de fallback, perdendo os URIs originais corretos. + +**Localização**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**Impacto:** +URI original: `http://purl.org/ontology/fo/Recipe` +URI construído: `https://trustgraph.ai/ontology/food#Recipe` +Perda de significado semântico, quebra a interoperabilidade + +### 3. **Formato Ambíguo de Instância de Entidade** + +**Problema:** Não há orientação clara sobre o formato do URI da instância de entidade. + +**Exemplos no prompt:** +`"recipe:cornish-pasty"` (prefixo semelhante a um namespace) +`"ingredient:flour"` (prefixo diferente) + +**Comportamento real** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**Impacto**: O modelo de linguagem deve adivinhar a convenção de prefixo sem contexto ontológico. + +### 4. **Sem Orientação de Prefixo de Namespace** + +**Problema**: O JSON da ontologia contém definições de namespace (linha 10-25 em food.ontology): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +Mas estas informações nunca são transmitidas para o LLM. O LLM não sabe: +O que "fo" significa +Qual prefixo usar para entidades +Qual namespace se aplica a quais elementos + +### 5. **Rótulos Não Utilizados no Prompt** + +**Problema**: Cada classe tem campos `rdfs:label` (por exemplo, `{"value": "Recipe", "lang": "en-gb"}`), mas o modelo de prompt não os utiliza. + +**Atual**: Mostra apenas `class_id` e `comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**Disponível, mas não utilizado**: +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**Impacto**: Poderia fornecer nomes legíveis para humanos, juntamente com IDs técnicos. + +## Soluções Propostas + +### Opção A: Normalizar para IDs sem Prefixo + +**Abordagem**: Remover os prefixos dos IDs de classe antes de exibi-los para o LLM. + +**Alterações**: +1. Modificar `build_extraction_variables()` para transformar chaves: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. Atualizar o exemplo de prompt para corresponder (já usa nomes sem prefixo). + +3. Modificar `expand_uri()` para lidar com ambos os formatos: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**Prós:** +Mais limpo, mais legível para humanos +Compatível com exemplos de prompts existentes +Modelos de linguagem grandes (LLMs) funcionam melhor com tokens mais simples + +**Contras:** +Colisões de nomes de classe se múltiplas ontologias tiverem o mesmo nome de classe +Perde informações de namespace +Requer lógica de fallback para pesquisas + +### Opção B: Usar IDs com Prefixo Completo Consistentemente + +**Abordagem:** Atualizar exemplos para usar IDs com prefixo correspondentes ao que é mostrado na lista de classes. + +**Mudanças:** +1. Atualizar exemplo de prompt (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. Adicionar explicação do namespace ao prompt: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. Mantenha `expand_uri()` como está (funciona corretamente quando as correspondências são encontradas). + +**Prós:** +Consistência entre entrada e saída. +Sem perda de informação. +Preserva a semântica do namespace. +Funciona com múltiplas ontologias. + +**Contras:** +Tokens mais verbosos para o LLM. +Requer que o LLM rastreie os prefixos. + +### Opção C: Híbrida - Mostrar Tanto o Rótulo quanto o ID + +**Abordagem:** Aprimorar o prompt para mostrar tanto os rótulos legíveis por humanos quanto os IDs técnicos. + +**Alterações:** +1. Atualizar o modelo do prompt: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + Exemplo de saída: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. Instruções de atualização: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**Prós**: +Mais claro para LLM +Preserva todas as informações +Explícito sobre o que usar + +**Contras**: +Prompt mais longo +Modelo mais complexo + +## Abordagem Implementada + +**Formato Simplificado de Entidade-Relacionamento-Atributo** - substitui completamente o formato antigo baseado em triplas. + +A nova abordagem foi escolhida porque: + +1. **Nenhuma Perda de Informação**: URIs originais preservados corretamente +2. **Lógica Mais Simples**: Nenhuma transformação necessária, pesquisas diretas em dicionários funcionam +3. **Segurança de Namespace**: Lida com múltiplas ontologias sem colisões +4. **Correção Semântica**: Mantém a semântica RDF/OWL + +## Implementação Completa + +### O Que Foi Construído: + +1. **Novo Modelo de Prompt** (`prompts/ontology-extract-v2.txt`) + ✅ Seções claras: Tipos de Entidade, Relacionamentos, Atributos + ✅ Exemplo usando identificadores de tipo completos (`fo/Recipe`, `fo/has_ingredient`) + ✅ Instruções para usar identificadores exatos do esquema + ✅ Novo formato JSON com arrays de entidades/relacionamentos/atributos + +2. **Normalização de Entidade** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - Converte nomes para formato seguro para URI + ✅ `normalize_type_identifier()` - Lida com barras em tipos (`fo/Recipe` → `fo-recipe`) + ✅ `build_entity_uri()` - Cria URIs únicos usando a tupla (nome, tipo) + ✅ `EntityRegistry` - Rastreia entidades para desduplicação + +3. **Analisador JSON** (`simplified_parser.py`) + ✅ Analisa o novo formato: `{entities: [...], relationships: [...], attributes: [...]}` + ✅ Suporta nomes de campos em kebab-case e snake_case + ✅ Retorna dataclasses estruturadas + ✅ Tratamento de erros elegante com registro + +4. **Conversor de Triplas** (`triple_converter.py`) + ✅ `convert_entity()` - Gera automaticamente triplas de tipo + rótulo + ✅ `convert_relationship()` - Conecta URIs de entidade via propriedades + ✅ `convert_attribute()` - Adiciona valores literais + ✅ Consulta URIs completos a partir de definições de ontologia + +5. **Processador Principal Atualizado** (`extract.py`) + ✅ Removeu o código antigo de extração baseado em triplas + ✅ Adicionado método `extract_with_simplified_format()` + ✅ Agora usa exclusivamente o novo formato simplificado + ✅ Chama o prompt com o ID `extract-with-ontologies-v2` + +## Casos de Teste + +### Teste 1: Preservação de URI +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### Teste 2: Colisão Multi-Ontologia +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### Teste 3: Formato de Instância de Entidade +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## Perguntas Abertas + +1. **As instâncias de entidades devem usar prefixos de namespace?** + Atual: `"recipe:cornish-pasty"` (arbitrário) + Alternativa: Usar o prefixo da ontologia `"fo:cornish-pasty"`? + Alternativa: Sem prefixo, expandir no URI `"cornish-pasty"` → URI completo? + +2. **Como lidar com o domínio/alcance no prompt?** + Atualmente mostra: `(Recipe → Food)` + Deveria ser: `(fo/Recipe → fo/Food)`? + +3. **Devemos validar as restrições de domínio/alcance?** + TODO: comentário em extract.py:470 + Detectaria mais erros, mas seria mais complexo + +4. **O que dizer das propriedades inversas e equivalências?** + A ontologia tem `owl:inverseOf`, `owl:equivalentClass` + Não está atualmente sendo usado na extração + Deveria estar? + +## Métricas de Sucesso + +✅ Perda zero de informações de URI (100% de preservação dos URIs originais) +✅ O formato de saída do LLM corresponde ao formato de entrada +✅ Nenhum exemplo ambíguo no prompt +✅ Os testes passam com múltiplas ontologias +✅ Qualidade de extração aprimorada (medida pela porcentagem de triplas válidas) + +## Abordagem Alternativa: Formato de Extração Simplificado + +### Filosofia + +Em vez de pedir ao LLM para entender a semântica RDF/OWL, peça para ele fazer o que ele faz de melhor: **encontrar entidades e relacionamentos no texto**. + +Deixe que o código lide com a construção de URIs, a conversão RDF e as formalidades da web semântica. + +### Exemplo: Classificação de Entidades + +**Texto de Entrada:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**Esquema de Ontologia (mostrado ao LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**O que o LLM retorna (JSON simples):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**O que o Código Produz (Triplas RDF):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### Benefícios + +1. **O LLM não precisa de:** + Entender a sintaxe de URI + Inventar prefixos de identificadores (`recipe:`, `ingredient:`) + Saber sobre `rdf:type` ou `rdfs:label` + Construir identificadores da web semântica + +2. **O LLM precisa apenas de:** + Encontrar entidades no texto + Mapeá-las para classes de ontologia + Extrair relacionamentos e atributos + +3. **O código lida com:** + Normalização e construção de URI + Geração de triplas RDF + Atribuição automática de rótulos + Gerenciamento de namespaces + +### Por que Isso Funciona Melhor + +**Prompt mais simples** = menos confusão = menos erros +**IDs consistentes** = o código controla as regras de normalização +**Rótulos gerados automaticamente** = sem triplas rdfs:label ausentes +**O LLM se concentra na extração** = o que ele realmente faz bem + +### Exemplo: Relacionamentos de Entidades + +**Texto de entrada:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**Esquema de Ontologia (mostrado ao LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**O que o LLM retorna (JSON simples):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**O que o Código Produz (Triplas RDF):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**Pontos-chave:** +O LLM retorna nomes de entidades em linguagem natural: `"Cornish pasty"`, `"beef"`, `"potatoes"` +O LLM inclui tipos para disambiguar: `subject-type`, `object-type` +O LLM usa o nome da relação do esquema: `"has_ingredient"` +O código deriva IDs consistentes usando (nome, tipo): `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +O código pesquisa o URI da relação na ontologia: `fo/has_ingredient` → URI completo +A mesma tupla (nome, tipo) sempre obtém o mesmo URI (desduplicação) + +### Exemplo: Desambiguação de Nomes de Entidades + +**Problema:** O mesmo nome pode se referir a diferentes tipos de entidade. + +**Caso real:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**Como é tratado:** + +O LLM retorna ambos como entidades separadas: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**Resolução de Código:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**Por que isso funciona:** +O tipo está incluído em TODAS as referências (entidades, relacionamentos, atributos). +O código usa a tupla `(name, type)` como chave de pesquisa. +Sem ambiguidades, sem colisões. + +### Exemplo: Atributos de Entidade + +**Texto de entrada:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**Esquema de Ontologia (mostrado ao LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**O que o LLM retorna (JSON simples):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**O que o Código Produz (Triplas RDF):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**Pontos-chave:** +O LLM extrai valores literais: `"4-6 people"`, `"45 minutes"` +O LLM inclui o tipo de entidade para desambiguação: `entity-type` +O LLM usa o nome do atributo do esquema: `"serves"`, `"preparation_time"` +O código pesquisa o URI do atributo a partir das propriedades do tipo de dados da ontologia +**O objeto é literal** (`is_uri=False`), não uma referência de URI +Os valores permanecem como texto natural, sem necessidade de normalização + +**Diferença em relação a Relacionamentos:** +Relacionamentos: tanto o sujeito quanto o objeto são entidades (URIs) +Atributos: o sujeito é uma entidade (URI), o objeto é um valor literal (string/número) + +### Exemplo Completo: Entidades + Relacionamentos + Atributos + +**Texto de Entrada:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**O que o LLM retorna:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**Resultado:** 11 triplas RDF geradas: +3 triplas de tipo de entidade (rdf:type) +3 triplas de rótulo de entidade (rdfs:label) - automático +2 triplas de relacionamento (has_ingredient) +1 tripla de atributo (serves) + +Tudo isso a partir de extrações simples e em linguagem natural pelo LLM! + +## Referências + +Implementação atual: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +Modelo de prompt: `ontology-prompt.md` +Casos de teste: `tests/unit/test_extract/test_ontology/` +Ontologia de exemplo: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.ru.md b/docs/tech-specs/ontology-extract-phase-2.ru.md new file mode 100644 index 00000000..20fbe1d3 --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.ru.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "Извлечение знаний из онтологий - Фаза 2, рефакторинг" +parent: "Russian (Beta)" +--- + +# Извлечение знаний из онтологий - Фаза 2, рефакторинг + +> **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-12-03 +**Связанные**: `ontology.md`, `ontorag.md` + +## Обзор + +Этот документ выявляет несоответствия в текущей системе извлечения знаний на основе онтологий и предлагает рефакторинг для повышения производительности LLM и снижения потери информации. + +## Текущая реализация + +### Как это работает сейчас + +1. **Загрузка онтологии** (`ontology_loader.py`) + Загружает JSON-файл онтологии с ключами, такими как `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` + Идентификаторы классов включают префикс пространства имен в самом ключе + Пример из `food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **Построение запроса** (`extract.py:299-307`, `ontology-prompt.md`) + Шаблон получает словари `classes`, `object_properties`, `datatype_properties` + Шаблон выполняет итерацию: `{% for class_id, class_def in classes.items() %}` + LLM видит: `**fo/Recipe**: A Recipe is a combination...` + Пример формата вывода показывает: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **Разбор ответа** (`extract.py:382-428`) + Ожидается массив JSON: `[{"subject": "...", "predicate": "...", "object": "..."}]` + Проверка на соответствие подмножеству онтологии + Расширение URI с помощью `expand_uri()` (extract.py:473-521) + +4. **Расширение URI** (`extract.py:473-521`) + Проверяет, присутствует ли значение в словаре `ontology_subset.classes` + Если найдено, извлекает URI из определения класса + Если не найдено, создает URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### Пример потока данных + +**JSON онтологии → Загрузчик → Запрос:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**Большая языковая модель → Парсер → Вывод:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## Выявленные проблемы + +### 1. **Несоответствие примеров в запросе** + +**Проблема**: Шаблон запроса показывает идентификаторы классов с префиксами (`fo/Recipe`), но пример вывода использует имена классов без префиксов (`Recipe`). + +**Местоположение**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**Влияние**: LLM получает противоречивые сигналы о том, какой формат использовать. + +### 2. **Потеря информации при расширении URI** + +**Проблема**: Когда LLM возвращает имена классов без префикса, следуя примеру, `expand_uri()` не может найти их в словаре онтологии и создает резервные URI, теряя исходные правильные URI. + +**Местоположение**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**Влияние:** +Исходный URI: `http://purl.org/ontology/fo/Recipe` +Сформированный URI: `https://trustgraph.ai/ontology/food#Recipe` +Семантическое значение потеряно, нарушается совместимость. + +### 3. **Неоднозначный формат экземпляра сущности** + +**Проблема:** Отсутствуют четкие указания относительно формата URI экземпляра сущности. + +**Примеры в запросе:** +`"recipe:cornish-pasty"` (префикс, похожий на пространство имен) +`"ingredient:flour"` (другой префикс) + +**Фактическое поведение** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**Влияние**: LLM должна угадать соглашение о префиксах без контекста онтологии. + +### 4. **Отсутствие рекомендаций по префиксам пространств имен** + +**Проблема**: JSON-файл онтологии содержит определения пространств имен (строки 10-25 в food.ontology): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +Но эти данные никогда не передаются в языковую модель. Языковая модель не знает: +Что означает "fo" +Какой префикс использовать для сущностей +К каким элементам относится какое пространство имен + +### 5. **Метки, не используемые в запросе** + +**Проблема**: У каждого класса есть поля `rdfs:label` (например, `{"value": "Recipe", "lang": "en-gb"}`), но шаблон запроса их не использует. + +**Текущая ситуация**: Отображаются только `class_id` и `comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**Доступно, но не используется**: +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**Влияние**: Может предоставить удобочитаемые имена наряду с техническими идентификаторами. + +## Предлагаемые решения + +### Вариант A: Нормализация до идентификаторов без префиксов + +**Подход**: Удалять префиксы из идентификаторов классов перед отображением LLM. + +**Изменения**: +1. Изменить `build_extraction_variables()` для преобразования ключей: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. Обновить пример запроса, чтобы он соответствовал (уже использует имена без префиксов). + +3. Изменить `expand_uri()` для обработки обоих форматов: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**Преимущества:** +Более понятный и читаемый для человека. +Соответствует существующим примерам запросов. +Большие языковые модели (LLM) лучше работают с более простыми токенами. + +**Недостатки:** +Конфликты имен классов, если несколько онтологий имеют одинаковое имя класса. +Потеря информации о пространстве имен. +Требуется логика обработки исключений для поиска. + +### Вариант B: Использовать полные префиксные идентификаторы последовательно + +**Подход:** Обновить примеры для использования префиксных идентификаторов, соответствующих тем, которые показаны в списке классов. + +**Изменения:** +1. Обновить пример запроса (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. Добавьте объяснение пространства имен в запрос: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. Оставьте `expand_uri()` без изменений (это работает правильно, когда найдены совпадения). + +**Преимущества:** +Согласованность входных и выходных данных. +Отсутствие потери информации. +Сохраняет семантику пространства имен. +Работает с несколькими онтологиями. + +**Недостатки:** +Более многословные токены для LLM. +Требует от LLM отслеживания префиксов. + +### Вариант C: Гибридный - Отображать и метку, и идентификатор. + +**Подход:** Улучшить запрос, чтобы отображать как читаемые человеком метки, так и технические идентификаторы. + +**Изменения:** +1. Обновить шаблон запроса: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + Пример вывода: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. Инструкции по обновлению: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**Преимущества:** +Наиболее понятный формат для больших языковых моделей (LLM). +Сохраняет всю информацию. +Явно указывает, что использовать. + +**Недостатки:** +Более длинный запрос. +Более сложный шаблон. + +## Реализованный подход + +**Упрощенный формат "Сущность-Отношение-Атрибут"** - полностью заменяет старый формат на основе троек. + +Новый подход был выбран, потому что: + +1. **Отсутствие потери информации:** Оригинальные URI сохраняются корректно. +2. **Более простая логика:** Не требуется преобразование, прямые запросы к словарям работают. +3. **Безопасность пространств имен:** Обрабатывает несколько онтологий без конфликтов. +4. **Семантическая корректность:** Сохраняет семантику RDF/OWL. + +## Реализация завершена + +### Что было создано: + +1. **Новый шаблон запроса** (`prompts/ontology-extract-v2.txt`) + ✅ Четкие разделы: Типы сущностей, Отношения, Атрибуты. + ✅ Пример использования полных идентификаторов типов (`fo/Recipe`, `fo/has_ingredient`). + ✅ Инструкции по использованию точных идентификаторов из схемы. + ✅ Новый формат JSON с массивами сущностей/отношений/атрибутов. + +2. **Нормализация сущностей** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - Преобразует имена в формат, безопасный для URI. + ✅ `normalize_type_identifier()` - Обрабатывает слеши в типах (`fo/Recipe` → `fo-recipe`). + ✅ `build_entity_uri()` - Создает уникальные URI, используя кортеж (имя, тип). + ✅ `EntityRegistry` - Отслеживает сущности для исключения дубликатов. + +3. **JSON-парсер** (`simplified_parser.py`) + ✅ Парсит новый формат: `{entities: [...], relationships: [...], attributes: [...]}` + ✅ Поддерживает имена полей в формате kebab-case и snake_case. + ✅ Возвращает структурированные классы данных. + ✅ Корректная обработка ошибок с ведением журнала. + +4. **Тройной преобразователь** (`triple_converter.py`) + ✅ `convert_entity()` - Автоматически генерирует тройки типа + метки. + ✅ `convert_relationship()` - Соединяет URI сущностей через свойства. + ✅ `convert_attribute()` - Добавляет литеральные значения. + ✅ Выполняет поиск полных URI из определений онтологии. + +5. **Обновленный основной процессор** (`extract.py`) + ✅ Удален старый код извлечения на основе троек. + ✅ Добавлен метод `extract_with_simplified_format()`. + ✅ Теперь использует только новый упрощенный формат. + ✅ Вызывает запрос с идентификатором `extract-with-ontologies-v2`. + +## Тестовые примеры + +### Тест 1: Сохранение URI +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### Тест 2: Конфликт между несколькими онтологиями +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### Тест 3: Формат экземпляра сущности +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## Открытые вопросы + +1. **Следует ли экземплярам сущностей использовать префиксы пространств имен?** + Сейчас: `"recipe:cornish-pasty"` (произвольно) + Альтернатива: Использовать префикс онтологии `"fo:cornish-pasty"`? + Альтернатива: Без префикса, расширить в URI `"cornish-pasty"` → полный URI? + +2. **Как обрабатывать область определения/область значений в запросе?** + В настоящее время отображается: `(Recipe → Food)` + Должно ли быть: `(fo/Recipe → fo/Food)`? + +3. **Следует ли нам проверять ограничения области определения/области значений?** + TODO комментарий в extract.py:470 + Это позволило бы выявлять больше ошибок, но было бы сложнее. + +4. **Что касается обратных свойств и эквивалентностей?** + В онтологии есть `owl:inverseOf`, `owl:equivalentClass` + В настоящее время не используются при извлечении. + Следует ли их использовать? + +## Показатели успеха + +✅ Отсутствие потери информации об URI (100% сохранение исходных URI). +✅ Формат вывода LLM соответствует формату входных данных. +✅ Отсутствие неоднозначных примеров в запросе. +✅ Тесты проходят с использованием нескольких онтологий. +✅ Улучшенное качество извлечения (измеряется процентом допустимых троек). + +## Альтернативный подход: Упрощенный формат извлечения + +### Философия + +Вместо того, чтобы просить LLM понимать семантику RDF/OWL, попросите его делать то, что он умеет хорошо: **находить сущности и отношения в тексте**. + +Пусть код занимается построением URI, преобразованием в RDF и формальностями семантической паутины. + +### Пример: Классификация сущностей + +**Исходный текст:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**Схема онтологии (показана LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**Что возвращает большая языковая модель (простой JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**Что генерирует код (тройки RDF):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### Преимущества + +1. **LLM (большая языковая модель) не должна:** + Понимать синтаксис URI + Придумывать префиксы идентификаторов (`recipe:`, `ingredient:`) + Знать о `rdf:type` или `rdfs:label` + Конструировать идентификаторы семантической паутины + +2. **LLM просто должна:** + Находить сущности в тексте + Сопоставлять их с классами онтологии + Извлекать отношения и атрибуты + +3. **Код обрабатывает:** + Нормализацию и построение URI + Генерацию триплетов RDF + Автоматическое присвоение меток + Управление пространствами имен + +### Почему это работает лучше + +**Более простой запрос** = меньше путаницы = меньше ошибок +**Согласованные идентификаторы** = код контролирует правила нормализации +**Автоматически сгенерированные метки** = нет отсутствующих триплетов rdfs:label +**LLM фокусируется на извлечении** = на том, что она действительно хороша + +### Пример: Отношения между сущностями + +**Исходный текст:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**Схема онтологии (показана LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**Что возвращает большая языковая модель (простой JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**Что генерирует код (тройки RDF):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**Основные моменты:** +LLM возвращает имена сущностей на естественном языке: `"Cornish pasty"`, `"beef"`, `"potatoes"` +LLM включает типы для устранения неоднозначности: `subject-type`, `object-type` +LLM использует имя отношения из схемы: `"has_ingredient"` +Код генерирует согласованные идентификаторы, используя (имя, тип): `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +Код ищет URI отношения в онтологии: `fo/has_ingredient` → полный URI +Одна и та же (имя, тип) всегда получает один и тот же URI (дедупликация) + +### Пример: Разрешение неоднозначности имени сущности + +**Проблема:** Одно и то же имя может относиться к разным типам сущностей. + +**Реальный пример:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**Как это обрабатывается:** + +LLM возвращает оба элемента как отдельные сущности: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**Разрешение кода:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**Почему это работает:** +Тип включен во ВСЕ ссылки (сущности, отношения, атрибуты). +Код использует кортеж `(name, type)` в качестве ключа поиска. +Отсутствие неоднозначности, отсутствие конфликтов. + +### Пример: Атрибуты сущности + +**Исходный текст:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**Схема онтологии (показана LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**Что возвращает большая языковая модель (простой JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**Что генерирует код (тройки RDF):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**Основные моменты:** +LLM извлекает строковые значения: `"4-6 people"`, `"45 minutes"` +LLM включает тип сущности для устранения неоднозначности: `entity-type` +LLM использует имя атрибута из схемы: `"serves"`, `"preparation_time"` +Код ищет URI атрибута из свойств типа данных онтологии +**Объект является строковым значением** (`is_uri=False`), а не ссылкой URI +Значения остаются в виде обычного текста, нормализация не требуется + +**Различия с отношениями:** +Отношения: и субъект, и объект являются сущностями (URI) +Атрибуты: субъект является сущностью (URI), объект является строковым значением (строка/число) + +### Полный пример: Сущности + Отношения + Атрибуты + +**Исходный текст:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**Что возвращает большая языковая модель:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**Результат:** Сгенерировано 11 тройных наборов RDF: +3 тройных набора, определяющих тип сущности (rdf:type) +3 тройных набора, определяющих метку сущности (rdfs:label) - автоматически +2 тройных набора, описывающих отношения (has_ingredient) +1 тройной набор, описывающий атрибут (serves) + +Все это получено из простых, естественных текстовых извлечений с помощью LLM! + +## Ссылки + +Текущая реализация: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +Шаблон запроса: `ontology-prompt.md` +Тестовые примеры: `tests/unit/test_extract/test_ontology/` +Пример онтологии: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.sw.md b/docs/tech-specs/ontology-extract-phase-2.sw.md new file mode 100644 index 00000000..89ee8efd --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.sw.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "Dondoo la Maarifa la Ontolojia - Awamu ya 2 ya Urekebishaji" +parent: "Swahili (Beta)" +--- + +# Dondoo la Maarifa la Ontolojia - Awamu ya 2 ya Urekebishaji + +> **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**: Mkutano wa Uchambuzi wa 2025-12-03 +**Inahusiana na**: `ontology.md`, `ontorag.md` + +## Muhtasari + +Hati hii inataja kutofautiana katika mfumo wa sasa wa dondoo la maarifa unaotegemea ontolojia na inapendekeza urekebishaji ili kuboresha utendaji wa LLM na kupunguza upotevu wa habari. + +## Utendaji wa Sasa + +### Inavyofanya Sasa + +1. **Kupakia Ontolojia** (`ontology_loader.py`) + Inapakia JSON ya ontolojia na vitufe kama `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` + Nambari za darasa zina jalizi la nafasi katika kitufe yenyewe + Mfano kutoka `food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **Uundaji wa Maagizo** (`extract.py:299-307`, `ontology-prompt.md`) + Kiolezo kinapokea dictionaries `classes`, `object_properties`, `datatype_properties` + Kiolezo huchanganua: `{% for class_id, class_def in classes.items() %}` + LLM inaona: `**fo/Recipe**: A Recipe is a combination...` + Muundo wa mfano wa matokeo unaonyesha: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **Uchambuzi wa Majibu** (`extract.py:382-428`) + Inatarajia safu ya JSON: `[{"subject": "...", "predicate": "...", "object": "..."}]` + Inathibitisha dhidi ya sehemu ya ontolojia + Inapanua URI kupitia `expand_uri()` (extract.py:473-521) + +4. **Upanuzi wa URI** (`extract.py:473-521`) + Inangalia ikiwa thamani iko katika kamusi `ontology_subset.classes` + Ikiwa imepatikana, inatoa URI kutoka kwenye ufafanuzi wa darasa + Ikiwa haijapatikana, inaunda URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### Mfano wa Mtiririko wa Data + +**Ontolojia ya JSON → Mpakuzi → Ombi:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**LLM → Mfumo wa Uchambuzi → Matokeo:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## Matatizo Yaliyobainika + +### 1. **Mfano Usiofuata Kanuni katika Maagizo** + +**Tatizo**: Kiolezo cha maagizo huonyesha vitambulisho vya darasa na mabainisha (`fo/Recipe`) lakini matokeo ya mfano hutumia majina ya darasa yasiyo na mabainisha (`Recipe`). + +**Mahali**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**Athari**: Mfumo wa lugha (LLM) hupokea ishara tofauti kuhusu muundo ambao unapaswa kutumika. + +### 2. **Upatanishi wa Habari katika Upanuzi wa URI** + +**Tatizo**: Wakati LLM hurudisha majina ya darasa ambayo hayana alama ya mbele, kama ilivyoelezwa katika mfano, `expand_uri()` hayawezi kuyakuta katika kamusi ya ontolojia na huunda URI za dharura, na kusababisha kupoteza URI za asili. + +**Mahali**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**Athari**: +URI asili: `http://purl.org/ontology/fo/Recipe` +URI iliyoundwa: `https://trustgraph.ai/ontology/food#Recipe` +Maana ya kielelezo yamepotea, husababisha kutofanya kazi kwa pamoja. + +### 3. **Muundo Usio Wazi wa Eneo la Kitu** + +**Tatizo**: Hakuna mwongozo wazi kuhusu muundo wa URI ya eneo la kitu. + +**Mfano katika maagizo**: +`"recipe:cornish-pasty"` (kielezi kama kielezi) +`"ingredient:flour"` (kielezi tofauti) + +**Tabia halisi** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**Athari**: Mfumo wa lugha (LLM) lazima ajue mbinu ya kuweka alama (prefixing) bila kuwa na msingi wa elimu (ontology). + +### 4. **Hakuna Maelekezo ya Mbele ya Nafasi (Namespace)** + +**Tatizo**: Faili ya JSON ya elimu ina maelezo ya nafasi (namespace) (kwa mstari wa 10-25 katika food.ontology): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +Lakini mistari hii haionyeshwi kwa mfumo wa lugha (LLM). MFUMO WA LUGHA (LLM) haujua: +Maana ya "fo" +Njia gani ya kutumia kwa vitu +Nafasi gani inayotumika kwa vipengele + +### 5. **Lebo Ambazo Hazitumiki katika Swali** + +**Tatizo**: Kila darasa lina sehemu za `rdfs:label` (k.m., `{"value": "Recipe", "lang": "en-gb"}`), lakini kigezo cha swali haziitumii. + +**Hali ya sasa**: Inaonyesha tu `class_id` na `comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**Inapatikana lakini haitumiki:** +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**Athari**: Inaweza kutoa majina ambayo yanaweza kueleweka kwa binadamu pamoja na vitambulisho vya kiufundi. + +## Suluhisho Zilizopendekezwa + +### Chaguo A: Kuweka Vipengele sawa na Vitambulisho visivyo na Mbele + +**Mbinu**: Ondoa mbele kutoka kwa vitambulisho vya darasa kabla ya kuviwasha kwa mfumo wa akili bandia (LLM). + +**Mabadiliko**: +1. Badilisha `build_extraction_variables()` ili kubadilisha funguo: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. Sasisha mfano wa maagizo ili ufanane (tayari hutumia majina yasiyo na alama). + +3. Badilisha `expand_uri()` ili iweze kushughulikia aina zote mbili: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**Faida:** +Safi zaidi, rahisi zaidi kusoma na kuelewa. +Inafanana na mifano iliyopo ya maagizo. +Mifumo ya lugha kubwa (LLMs) hufanya kazi vizuri zaidi na alama (tokens) rahisi. + +**Hasara:** +Migongano ya majina ya madarasa ikiwa ontolojia nyingi zina jina sawa la darasa. +Inapoteza habari ya nafasi (namespace). +Inahitaji mantiki ya dharura kwa utafutaji. + +### Chaguo B: Tumia Kitambulisho Kamili Chenye Alama (Prefix) kwa Ufanisi + +**Mbinu:** Sasisha mifano ili kutumia kitambulisho chenye alama kinacholingana na kile kinachoonyeshwa katika orodha ya madarasa. + +**Mabadiliko:** +1. Sasisha mfano wa agizo (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. Ongeza maelezo ya nafasi ya kazi kwenye swali: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. Acha `expand_uri()` kama ilivyo (hufanya kazi vizuri wakati mechi zinapopatikana). + +**Faida:** +Ulinganisho kati ya ingizo na pato. +Hakuna upotevu wa habari. +Inahifadhi maana ya nafasi (namespace). +Inafanya kazi na ontolojia nyingi. + +**Hasara:** +Alama (tokens) zaidi kwa LLM. +Inahitaji LLM kufuatilia alama za mbele (prefixes). + +### Chaguo C: Mchanganyiko - Onyesha Lebo na Kitambulisho (ID) + +**Mbinu:** Ongeza maagizo katika swali ili kuonyesha lebo zinazoweza kusomwa na binadamu na kitambulisho (ID) cha kiufundi. + +**Mabadiliko:** +1. Sasisha mfumo wa swali: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + Matokeo ya mfano: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. Maelekezo ya sasisho: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**Faida:** +Inafaa zaidi kwa mifumo ya lugha kubwa (LLM). +Inahifadhi habari yote. +Inaeleza wazi ni nini kinachotakiwa kutumika. + +**Hasara:** +Ombi refu zaidi. +Mfumo mgumu zaidi. + +## Njia Iliyotekelezwa + +**Muundo Ulioboreshwa wa Muhusiano wa Vitu na Sifa** - unaibadilisha kabisa mfumo wa zamani unaotegemea triplet. + +Njia mpya ilichaguliwa kwa sababu: + +1. **Hakuna Upotevu wa Habari:** Anwani za mtandaoni (URIs) za awali zinaendelea kuhifadhiwa kwa usahihi. +2. **Mantiki Rahisi:** Hakuna mabadiliko yanayohitajika, utafutaji wa moja kwa moja wa kamusi unafanya kazi. +3. **Usalama wa Nafasi:** Inashughulikia ontolojia nyingi bila migongano. +4. **Ukweli wa Kisia:** Inahifadhi maana ya RDF/OWL. + +## Utendaji Uliofanyika + +### Kilichojengwa: + +1. **Mfumo Mpya wa Ombi** (`prompts/ontology-extract-v2.txt`) + ✅ Sehemu zilizoelezwa wazi: Aina za Vitu, Mahusiano, Sifa. + ✅ Mfano unaotumia kitambulisho kamili cha aina (`fo/Recipe`, `fo/has_ingredient`). + ✅ Maelekezo ya kutumia kitambulisho halisi kutoka kwa schema. + ✅ Muundo mpya wa JSON na safu za vitu/mahusiano/sifa. + +2. **Urekebishaji wa Vitu** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - Inabadilisha majina kuwa muundo salama wa URI. + ✅ `normalize_type_identifier()` - Inashughulikia alama za upande katika aina (`fo/Recipe` → `fo-recipe`). + ✅ `build_entity_uri()` - Inaunda anwani za kipekee (URIs) kwa kutumia jozi (jina, aina). + ✅ `EntityRegistry` - Inafuatilia vitu ili kuepuka marudia. + +3. **Mchangamizi wa JSON** (`simplified_parser.py`) + ✅ Inachanganua muundo mpya: `{entities: [...], relationships: [...], attributes: [...]}`. + ✅ Inasaidia majina ya sehemu katika muundo wa kebab na muundo wa nyoka. + ✅ Inarudisha madarasa ya data iliyopangwa. + ✅ Usimamizi wa makosa kwa njia nzuri pamoja na uandishi wa matukio. + +4. **Mabadilishaji wa Triplet** (`triple_converter.py`) + ✅ `convert_entity()` - Inaunda triplet za aina + lebo moja kwa moja. + ✅ `convert_relationship()` - Inaunganisha anwani za vitu (URIs) kupitia sifa. + ✅ `convert_attribute()` - Inaongeza maadili ya moja kwa moja. + ✅ Inatafuta anwani kamili kutoka kwa maelezo ya ontolojia. + +5. **Mchakato Mkuu Uliosasishwa** (`extract.py`) + ✅ Imeondoa msimbo wa zamani wa uondoaji wa triplet. + ✅ Imeongeza `extract_with_simplified_format()`. + ✅ Sasa inatumia tu muundo uliorahisishwa. + ✅ Inaitisha ombi na kitambulisho `extract-with-ontologies-v2`. + +## Majaribio + +### Jaribio la 1: Uhifadhi wa URI +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### Mtihani wa 2: Mzozo wa Ontolojia Nyingi +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### Mtihani wa 3: Muundo wa Eneo la Mfano +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## Maswali ya Kufungua + +1. **Je, vipozi vya mifano ya vitu vinapaswa kutumia mbele za nafasi?** + Sasa: `"recipe:cornish-pasty"` (ya hiari) + Mbadala: Je, kutumia mbele ya ontolojia `"fo:cornish-pasty"`? + Mbadala: Hakuna mbele, kupanua katika URI `"cornish-pasty"` → URI kamili? + +2. **Jinsi ya kushughulikia uwanja/jukumu katika swali?** + Kwa sasa inaonyesha: `(Recipe → Food)` + Je, inapaswa kuwa: `(fo/Recipe → fo/Food)`? + +3. **Je, tunapaswa kuthibitisha vikwazo vya uwanja/jukumu?** + TODO maoni katika extract.py:470 + Itakamata makosa zaidi lakini ni ngumu zaidi + +4. **Hebu kuhusu sifa za kinyume na usawa?** + Ontolojia ina `owl:inverseOf`, `owl:equivalentClass` + Hasa haitumiki katika uondoaji + Je, inapaswa kutumika? + +## Viashiria vya Mafanikio + +✅ Hakuna upotevu wa habari ya URI (uhifadhi wa 100% wa URI za awali) +✅ Muundo wa pato la LLM unalingana na muundo wa ingizo +✅ Hakuna mifano ya kusumbua katika swali +✅ Vipimo hufanikiwa na ontolojia nyingi +✅ Ubora wa uondoaji ulioboreshwa (uliofanywa na asilimia ya triple halali) + +## Mbinu Mbadala: Muundo Ulioboreshwa wa Uondoaji + +### Falsafa + +Badala ya kuuliza LLM kuelewa maana ya RDF/OWL, waulize ifanye kile ambacho ni nzuri: **kutafuta vitu na uhusiano katika maandishi**. + +Acha msimbo kushughulikia uundaji wa URI, ubadilishaji wa RDF, na mambo rasmi ya wavuti ya kiakili. + +### Mfano: Uainishaji wa Vitu + +**Maandishi ya Ingizo:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**Muundo wa Ontolojia (unaonyeshwa kwa mfumo wa lugha kubwa):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**Kinachorudishwa na Mfumo wa Lugha Kubwa (JSON Rahisi):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**Ni Nini Ambo Inazalisha (Triple za RDF):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### Faida + +1. **LLM haihitaji:** + Kuelewa sintaksia ya URI + Kuunda mbele za kitambulisho (`recipe:`, `ingredient:`) + Kujua kuhusu `rdf:type` au `rdfs:label` + Kuunda kitambulisho cha mtandao wa maana + +2. **LLM inahitaji tu:** + Kupata vitu katika maandishi + Kuviweka katika madarasa ya ontolojia + Kuchukua uhusiano na sifa + +3. **Msimbo hushughulikia:** + Usanifu na uundaji wa URI + Uzalishaji wa triple za RDF + Uwekaji wa kiotomatiki wa lebo + Usimamizi wa nafasi + +### Kwa Nini Hii Inafanya Vyema + +**Swali rahisi** = uchanganyifu mdogo = makosa machache +**Kitambulisho thabiti** = msimbo udhibiti sheria za usanifu +**Lebo zilizozalishwa kiotomatiki** = hakuna triple za rdfs:label zilizopotea +**LLM inazingatia uondoaji** = ambayo ni jambo ambalo inafaa + +### Mfano: Uhusiano wa Vitu + +**Maandishi ya Ingizo:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**Muundo wa Ontolojia (unaonyeshwa kwa LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**Kinachorudishwa na Mfumo wa Lugha Kubwa (JSON Rahisi):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**Ni Nini Ambo Inazalisha (Triple za RDF):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**Pointi Muhimu:** +LLM hurudia majina ya vitu katika lugha ya asili: `"Cornish pasty"`, `"beef"`, `"potatoes"` +LLM hujumuisha aina ili kufafanua: `subject-type`, `object-type` +LLM hutumia jina la uhusiano kutoka kwa schema: `"has_ingredient"` +Msimbo hutengeneza vitambulisho vinavyolingana kwa kutumia (jina, aina): `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +Msimbo hutafuta URI ya uhusiano kutoka kwa ontolojia: `fo/has_ingredient` → URI kamili +Jozi sawa (jina, aina) daima hupata URI sawa (kuondoa marudia) + +### Mfano: Utambuzi wa Jina la Kitu + +**Tatizo:** Jina lile lile linaweza kurejelea aina tofauti za vitu. + +**Mfano halisi:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**Jinsi Inavyoshughuliwa:** + +Mfumo wa lugha kubwa (LLM) hurudisha yote kama vitu tofauti: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**Suluhisho la Msimbo:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**Kwa Nini Hifanya Kazi:** +Aina (type) imejumuishwa katika marejeleo yote (vitu, uhusiano, sifa). +Msimbo hutumia `(name, type)` kama ufunguo wa utafutaji. +Hakuna ukosefu wa uwazi, hakuna migongano. + +### Mifano: Sifa za Vitu + +**Nakala ya Ingizo:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**Muundo wa Ontolojia (unaonyeshwa kwa LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**Kinachorudishwa na Mfumo wa Lugha Kubwa (JSON Rahisi):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**Ni Nini Ambo Inazalisha (Triple za RDF):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**Pointi Muhimu:** +LLM huchukua maadili halisi: `"4-6 people"`, `"45 minutes"` +LLM hujumuisha aina ya kitu ili kuepusha utofauti: `entity-type` +LLM hutumia jina la sifa kutoka kwa schema: `"serves"`, `"preparation_time"` +Msimbo hutafuta URI ya sifa kutoka kwa sifa za aina ya ontology +**Kitu ni halali** (`is_uri=False`), si rejea la URI +Maadili husalia kama maandishi ya asili, hakuna haja ya urekebishaji + +**Tofauti na Mahusiano:** +Mahusiano: kitu cha kwanza na cha pili ni vitu (URIs) +Sifa: kitu cha kwanza ni kitu (URI), kitu cha pili ni thamani halali (mstari/nambari) + +### Mfano Kamili: Vitu + Mahusiano + Sifa + +**Maandishi ya Ingizo:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**Hili Ni Lile Ambalo Mfumo wa Lugha Kubwa Hurudisha:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**Matokeo:** Triple 11 za RDF zilizoundwa: +Triple 3 za aina ya kitu (rdf:type) +Triple 3 za lebo ya kitu (rdfs:label) - moja kwa moja +Triple 2 za uhusiano (ina_viungo) +Triple 1 ya sifa (inafaa) + +Yote kutoka kwa uundaji rahisi, wa lugha ya asili na mfumo wa akili bandia (LLM)! + +## Marejeleo + +Utaratibu wa sasa: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +Mfumo wa swali: `ontology-prompt.md` +Majaribio: `tests/unit/test_extract/test_ontology/` +Ontolojia ya mfano: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.tr.md b/docs/tech-specs/ontology-extract-phase-2.tr.md new file mode 100644 index 00000000..9ee6546b --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.tr.md @@ -0,0 +1,769 @@ +--- +layout: default +title: "Ontoloji Bilgi Çıkarma - 2. Aşama Yeniden Düzenleme" +parent: "Turkish (Beta)" +--- + +# Ontoloji Bilgi Çıkarma - 2. Aşama Yeniden Düzenleme + +> **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**: Analiz Oturumu 2025-12-03 +**İlgili**: `ontology.md`, `ontorag.md` + +## Genel Bakış + +Bu belge, mevcut ontoloji tabanlı bilgi çıkarma sistemindeki tutarsızlıkları belirlemektedir ve LLM performansını iyileştirmek ve bilgi kaybını azaltmak için bir yeniden düzenleme önermektedir. + +## Mevcut Uygulama + +### Şu Anda Nasıl Çalışıyor + +1. **Ontoloji Yükleme** (`ontology_loader.py`) + `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` gibi anahtarlara sahip ontoloji JSON'unu yükler. + Sınıf kimlikleri, anahtar içinde namespace önekini içerir. + `food.ontology`'dan bir örnek: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **İstem Oluşturma** (`extract.py:299-307`, `ontology-prompt.md`) + Şablon, `classes`, `object_properties`, `datatype_properties` sözlüklerini alır. + Şablon döngüye girer: `{% for class_id, class_def in classes.items() %}` + LLM (Büyük Dil Modeli) şunları görür: `**fo/Recipe**: A Recipe is a combination...` + Örnek çıktı formatı şöyledir: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **Yanıt Ayrıştırma** (`extract.py:382-428`) + JSON dizisi beklenir: `[{"subject": "...", "predicate": "...", "object": "..."}]` + Ontoloji alt kümesine göre doğrulanır. + URI'lar `expand_uri()` aracılığıyla genişletilir (extract.py:473-521). + +4. **URI Genişletme** (`extract.py:473-521`) + Değerin `ontology_subset.classes` sözlüğünde olup olmadığını kontrol eder. + Bulunursa, URI sınıf tanımından çıkarılır. + Bulunmazsa, URI oluşturulur: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### Veri Akışı Örneği + +**Ontoloji JSON → Yükleyici → İstek:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**LLM → Ayrıştırıcı → Çıktı:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## Belirlenen Sorunlar + +### 1. **İstemde Tutarsız Örnekler** + +**Sorun**: İstem şablonu, sınıf kimliklerini öneklerle (`fo/Recipe`) gösterirken, örnek çıktı önek kullanılmayan sınıf adlarını kullanır (`Recipe`). + +**Konum**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**Etki**: LLM, hangi formatı kullanması gerektiği konusunda çelişkili sinyaller alır. + +### 2. **URI Genişletmesinde Bilgi Kaybı** + +**Sorun**: LLM, örneğe uygun olarak önekli olmayan sınıf adları döndürdüğünde, `expand_uri()` bunları ontoloji sözlüğünde bulamaz ve yedek URI'ler oluşturur, böylece orijinal doğru URI'ler kaybolur. + +**Konum**: `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**Etki:** +Orijinal URI: `http://purl.org/ontology/fo/Recipe` +Oluşturulmuş URI: `https://trustgraph.ai/ontology/food#Recipe` +Anlamsal anlam kayboluyor, birlikte çalışabilirlik bozuluyor. + +### 3. **Belirsiz Varlık Örneği Biçimi** + +**Sorun:** Varlık örneği URI biçimi hakkında net bir rehberlik yok. + +**İpuçlarındaki örnekler:** +`"recipe:cornish-pasty"` (namespace benzeri önek) +`"ingredient:flour"` (farklı önek) + +**Gerçek davranış** (extract.py:517-520): +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**Etki**: LLM'nin, herhangi bir ontoloji bağlamı olmadan, önekleme kuralını tahmin etmesi gerekir. + +### 4. **Ada Alanı Önekleri Hakkında Rehberlik Yok** + +**Sorun**: Ontoloji JSON dosyası, ada alanı tanımlarını içerir (food.ontology dosyasının 10-25. satırları): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +Ancak bunlar asla LLM'ye iletilmez. LLM şunları bilmez: +"fo" kelimesinin ne anlama geldiğini +Varlıklar için hangi öneklerin kullanılması gerektiğini +Hangi ad alanının hangi öğelere uygulandığını + +### 5. **İpuçunda Kullanılmayan Etiketler** + +**Sorun**: Her sınıfın `rdfs:label` alanları vardır (örneğin, `{"value": "Recipe", "lang": "en-gb"}`), ancak ipucu şablonu bunları kullanmaz. + +**Mevcut durum**: Sadece `class_id` ve `comment` gösteriliyor. +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**Kullanılabilir ancak kullanılmayan:** +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**Etki**: Teknik kimliklerin yanı sıra insan tarafından okunabilir isimler sağlayabilir. + +## Önerilen Çözümler + +### Seçenek A: Önek Olmayan Kimliklere Normalleştirme + +**Yaklaşım**: Sınıf kimliklerinden önekleri, LLM'ye göstermeden önce kaldırın. + +**Değişiklikler**: +1. `build_extraction_variables()`'ı, anahtarları dönüştürmek için değiştirin: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. İstem örneğini, (zaten önek kullanmayan) mevcut duruma uygun hale getirin. + +3. `expand_uri()`'ı, her iki formatı da işleyebilecek şekilde değiştirin: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**Artıları:** +Daha temiz, daha insan tarafından okunabilir +Mevcut örnek istemlerle eşleşir +Büyük dil modelleri (LLM'ler), daha basit belirteçlerle daha iyi çalışır + +**Eksileri:** +Birden fazla ontolojinin aynı sınıf adına sahip olması durumunda sınıf adı çakışmaları +Ad alanı bilgilerini kaybettirir +Arama işlemlerinde yedekleme mantığı gerektirir + +### B Seçeneği: Tam Önekli Kimlikleri Tutarlı Bir Şekilde Kullanın + +**Yaklaşım:** Örnekleri, sınıf listesinde gösterilenlerle eşleşen önekli kimlikleri kullanacak şekilde güncelleyin. + +**Değişiklikler:** +1. Örnek istemi güncelleyin (ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. İstemde (prompt) ad alanı açıklamasını ekleyin: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. `expand_uri()`'ı olduğu gibi tutun (eşleşmeler bulunduğunda doğru şekilde çalışır). + +**Avantajları:** +Giriş = Çıkış tutarlılığı +Bilgi kaybı yok +Ada alanı semantiğini korur +Birden fazla ontoloji ile çalışır + +**Dezavantajları:** +LLM için daha ayrıntılı belirteçler +LLM'nin önekleri takip etmesini gerektirir + +### Seçenek C: Hibrit - Hem Etiketi Hem de Kimliği Gösterin + +**Yaklaşım:** İnsan tarafından okunabilir etiketleri ve teknik kimlikleri göstermek için istemi geliştirin. + +**Değişiklikler:** +1. İstem şablonunu güncelleyin: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + Örnek çıktı: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. Güncelleme talimatları: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**Avantajları**: +LLM için en anlaşılır olanı +Tüm bilgileri korur +Ne kullanılması gerektiği konusunda açık + +**Dezavantajları**: +Daha uzun bir istem +Daha karmaşık bir şablon + +## Uygulanan Yaklaşım + +**Basitleştirilmiş Varlık-İlişki-Özellik Formatı** - eski üçlü tabanlı formatın tamamen yerini alır. + +Bu yeni yaklaşım aşağıdaki nedenlerle seçilmiştir: + +1. **Bilgi Kaybı Yok**: Orijinal URI'ler doğru şekilde korunur +2. **Daha Basit Mantık**: Dönüştürmeye gerek yoktur, doğrudan sözlük aramaları çalışır +3. **Ad Alanı Güvenliği**: Çakışmalar olmadan birden fazla ontolojiyi işler +4. **Anlamsal Doğruluk**: RDF/OWL semantiğini korur + +## Uygulama Tamamlandı + +### Oluşturulanlar: + +1. **Yeni İstek Şablonu** (`prompts/ontology-extract-v2.txt`) + ✅ Açık bölümler: Varlık Türleri, İlişkiler, Özellikler + ✅ Tam tür tanımlayıcılarını kullanan örnek (`fo/Recipe`, `fo/has_ingredient`) + ✅ Şemadan tam tanımlayıcıları kullanma talimatları + ✅ Varlıklar/ilişkiler/özellikler dizileri içeren yeni JSON formatı + +2. **Varlık Normalizasyonu** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - İsimleri URI'ye uygun formata dönüştürür + ✅ `normalize_type_identifier()` - Türlerdeki eğik çizgileri işler (`fo/Recipe` → `fo-recipe`) + ✅ `build_entity_uri()` - (isim, tür) tuple'ını kullanarak benzersiz URI'ler oluşturur + ✅ `EntityRegistry` - Tekrarlamayı önlemek için varlıkları takip eder + +3. **JSON Ayrıştırıcı** (`simplified_parser.py`) + ✅ Yeni formatı ayrıştırır: `{entities: [...], relationships: [...], attributes: [...]}` + ✅ kebab-case ve snake_case alan adlarını destekler + ✅ Yapılandırılmış veri sınıfları döndürür + ✅ Günlükleme ile zarif hata işleme + +4. **Üçlü Dönüştürücü** (`triple_converter.py`) + ✅ `convert_entity()` - Tür + etiket üçlülerini otomatik olarak oluşturur + ✅ `convert_relationship()` - Varlık URI'lerini özellikler aracılığıyla bağlar + ✅ `convert_attribute()` - Literal değerleri ekler + ✅ Ontoloji tanımlarından tam URI'leri alır + +5. **Güncellenmiş Ana İşlemci** (`extract.py`) + ✅ Eski üçlü tabanlı çıkarma kodunu kaldırdı + ✅ `extract_with_simplified_format()` yöntemini ekledi + ✅ Artık yalnızca yeni, basitleştirilmiş formatı kullanır + ✅ İstemleri `extract-with-ontologies-v2` kimliğiyle çağırır + +## Test Senaryoları + +### Test 1: URI Korunması +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### Test 2: Çoklu Ontoloji Çakışması +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### Test 3: Varlık Örneği Formatı +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## Açık Sorular + +1. **Varlık örnekleri namespace önekleri kullanmalı mı?** + Mevcut durum: `"recipe:cornish-pasty"` (keyfi) + Alternatif: Ontoloji önekini kullanın `"fo:cornish-pasty"`? + Alternatif: Önek yok, URI'da genişletin `"cornish-pasty"` → tam URI? + +2. **Alan/kapsam (domain/range) nasıl işlenmeli?** + Şu anda gösterilen: `(Recipe → Food)` + Şu şekilde olmalı mı: `(fo/Recipe → fo/Food)`? + +3. **Alan/kapsam kısıtlamalarını doğrulamalı mıyız?** + TODO yorumu extract.py:470 satırında + Daha fazla hata yakalanır, ancak daha karmaşık olur + +4. **Ters özellikler ve eşdeğerlikler hakkında ne düşünülmeli?** + Ontolojide `owl:inverseOf`, `owl:equivalentClass` bulunmaktadır + Şu anda çıkarımda kullanılmıyor + Kullanılmalı mı? + +## Başarı Metrikleri + +✅ Sıfır URI bilgisi kaybı (orijinal URI'lerin %100 korunması) +✅ LLM çıktısı formatı, giriş formatıyla eşleşiyor +✅ Girişte belirsiz örnek yok +✅ Birden fazla ontolojiyle testler geçiliyor +✅ İyileştirilmiş çıkarım kalitesi (geçerli üçlü yüzdesi ile ölçülür) + +## Alternatif Yaklaşım: Basitleştirilmiş Çıkarım Formatı + +### Felsefe + +LLM'den RDF/OWL semantiğini anlamasını istemek yerine, LLM'nin iyi olduğu şeyi yapmasını isteyin: **metindeki varlıkları ve ilişkileri bulun**. + +URI oluşturma, RDF'ye dönüştürme ve semantik web formalitelerini kodun halletmesine izin verin. + +### Örnek: Varlık Sınıflandırması + +**Giriş Metni:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**Ontoloji Şeması (LLM'ye gösterilen):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**LLM'nin Döndürdükleri (Basit JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**Kodun Ürettiği Şeyler (RDF Üçlüleri):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### Faydalar + +1. **LLM'nin (Büyük Dil Modeli) yapması gerekmiyor:** + URI sözdizimini anlamak + Tanımlayıcı önekleri oluşturmak (`recipe:`, `ingredient:`) + `rdf:type` veya `rdfs:label` hakkında bilgi sahibi olmak + Semantik web tanımlayıcıları oluşturmak + +2. **LLM'nin sadece yapması gerekiyor:** + Metindeki varlıkları bulmak + Bunları ontoloji sınıflarına eşlemek + İlişkileri ve özellikleri çıkarmak + +3. **Kod şunları yönetir:** + URI normalizasyonu ve oluşturulması + RDF üçlü üretimi + Otomatik etiket ataması + İsim alanı yönetimi + +### Neden Bu Daha İyi Çalışıyor + +**Daha basit istem** = daha az kafa karışıklığı = daha az hata +**Tutarlı kimlikler** = kod, normalizasyon kurallarını kontrol eder +**Otomatik olarak oluşturulan etiketler** = eksik rdfs:label üçlüleri yok +**LLM, çıkarma üzerine odaklanır** = aslında iyi olduğu şey + +### Örnek: Varlık İlişkileri + +**Giriş Metni:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**Ontoloji Şeması (LLM'ye gösterilen):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**LLM'nin Döndürdükleri (Basit JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**Kodun Ürettiği Şeyler (RDF Üçlüleri):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**Önemli Noktalar:** +LLM, doğal dil varlık isimlerini döndürür: `"Cornish pasty"`, `"beef"`, `"potatoes"` +LLM, anlam belirsizliğini gidermek için türleri içerir: `subject-type`, `object-type` +LLM, şemadan ilişki adını kullanır: `"has_ingredient"` +Kod, (isim, tür) kullanarak tutarlı kimlikler türetir: `("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +Kod, ontolojiden ilişki URI'sini arar: `fo/has_ingredient` → tam URI +Aynı (isim, tür) ikilisi her zaman aynı URI'yi alır (çiftleme önleme) + +### Örnek: Varlık İsimlerinin Anlam Belirsizliğinin Giderilmesi + +**Sorun:** Aynı isim, farklı varlık türlerini ifade edebilir. + +**Gerçek dünya örneği:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**Nasıl İşlendiği:** + +LLM, her ikisini de ayrı varlıklar olarak döndürür: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**Kod Çözümleme:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**Neden İşe Yarıyor:** +Tip, TÜM referanslarda (varlıklar, ilişkiler, özellikler) bulunur. +Kod, arama anahtarı olarak `(name, type)` tuple'ını kullanır. +Herhangi bir belirsizlik, herhangi bir çakışma yoktur. + +### Örnek: Varlık Özellikleri + +**Giriş Metni:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**Ontoloji Şeması (LLM'ye gösterilen):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**LLM'nin Döndürdükleri (Basit JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**Kodun Ürettiği Şeyler (RDF Üçlüleri):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**Önemli Noktalar:** +LLM, gerçek değerleri çıkarır: `"4-6 people"`, `"45 minutes"` +LLM, anlam ayrımı için varlık türünü içerir: `entity-type` +LLM, şemadan öznitelik adını kullanır: `"serves"`, `"preparation_time"` +Kod, öznitelik URI'sini ontoloji veri türü özelliklerinden arar +**Nesne bir literaldir** (`is_uri=False`), bir URI referansı değildir +Değerler, doğal metin olarak kalır, normalleştirmeye gerek yoktur + +**İlişkilerden Farkı:** +İlişkiler: hem konu hem de nesne varlıklardır (URI'ler) +Öznitelikler: konu bir varlıktır (URI), nesne bir literal değerdir (dize/sayı) + +### Tam Örnek: Varlıklar + İlişkiler + Öznitelikler + +**Giriş Metni:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**LLM'nin Döndürdükleri:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**Sonuç:** 11 RDF üçlüsü oluşturuldu: +3 varlık türü üçlüsü (rdf:type) +3 varlık etiket üçlüsü (rdfs:label) - otomatik +2 ilişki üçlüsü (has_ingredient) +1 özellik üçlüsü (serves) + +Bunların hepsi, LLM tarafından yapılan basit, doğal dil çıkarımlarından elde edilmiştir! + +## Referanslar + +Mevcut uygulama: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +İstek şablonu: `ontology-prompt.md` +Test senaryoları: `tests/unit/test_extract/test_ontology/` +Örnek ontoloji: `e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology-extract-phase-2.zh-cn.md b/docs/tech-specs/ontology-extract-phase-2.zh-cn.md new file mode 100644 index 00000000..b430aaaf --- /dev/null +++ b/docs/tech-specs/ontology-extract-phase-2.zh-cn.md @@ -0,0 +1,769 @@ +--- +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. + +**状态**: 草稿 +**作者**: 分析会议 2025-12-03 +**相关**: `ontology.md`, `ontorag.md` + +## 概述 + +本文档识别了当前基于本体的知识抽取系统中存在的缺陷,并提出了重构方案,以提高 LLM 的性能并减少信息损失。 + +## 当前实现 + +### 当前工作方式 + +1. **本体加载** (`ontology_loader.py`) + 加载本体 JSON 文件,其中包含键,例如 `"fo/Recipe"`, `"fo/Food"`, `"fo/produces"` + 类 ID 在键本身中包含命名空间前缀 + 示例来自 `food.ontology`: + ```json + "classes": { + "fo/Recipe": { + "uri": "http://purl.org/ontology/fo/Recipe", + "rdfs:comment": "A Recipe is a combination..." + } + } + ``` + +2. **提示构建** (`extract.py:299-307`, `ontology-prompt.md`) + 模板接收 `classes`, `object_properties`, `datatype_properties` 字典 + 模板循环:`{% for class_id, class_def in classes.items() %}` + LLM 看到:`**fo/Recipe**: A Recipe is a combination...` + 示例输出格式如下: + ```json + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} + {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"} + ``` + +3. **响应解析** (`extract.py:382-428`) + 期望接收 JSON 数组: `[{"subject": "...", "predicate": "...", "object": "..."}]` + 验证是否符合本体子集 + 通过 `expand_uri()` 扩展 URI (extract.py:473-521) + +4. **URI 扩展** (`extract.py:473-521`) + 检查值是否在 `ontology_subset.classes` 字典中 + 如果找到,从类定义中提取 URI + 如果未找到,则构建 URI: `f"https://trustgraph.ai/ontology/{ontology_id}#{value}"` + +### 数据流示例 + +**本体 JSON → 加载器 → 提示:** +``` +"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**" +``` + +**LLM → 解析器 → 输出:** +``` +"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI +"fo/Recipe" → found in classes → uses original URI → PRESERVES URI +``` + +## 发现的问题 + +### 1. **提示语中的示例不一致** + +**问题**: 提示模板显示带有前缀的类ID (`fo/Recipe`),但示例输出使用不带前缀的类名 (`Recipe`)。 + +**位置**: `ontology-prompt.md:5-52` + +```markdown +## Ontology Classes: +- **fo/Recipe**: A Recipe is... + +## Example Output: +{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"} +``` + +**影响:** LLM 接收到关于应该使用哪种格式的冲突信号。 + +### 2. **URI 扩展中的信息丢失** + +**问题:** 当 LLM 返回不带前缀的类名,例如示例中的情况时,`expand_uri()` 无法在本体字典中找到它们,而是构造了备用 URI,从而丢失了原始的正确 URI。 + +**位置:** `extract.py:494-500` + +```python +if value in ontology_subset.classes: # Looks for "Recipe" + class_def = ontology_subset.classes[value] # But key is "fo/Recipe" + if isinstance(class_def, dict) and 'uri' in class_def: + return class_def['uri'] # Never reached! +return f"https://trustgraph.ai/ontology/{ontology_id}#{value}" # Fallback +``` + +**影响 (Impact):** +原始 URI: `http://purl.org/ontology/fo/Recipe` +构建的 URI: `https://trustgraph.ai/ontology/food#Recipe` +语义信息丢失,破坏互操作性 + +### 3. **实体实例格式不明确 (Ambiguous Entity Instance Format)** + +**问题 (Issue):** 没有关于实体实例 URI 格式的明确指导。 + +**提示中的示例 (Examples in prompt):** +`"recipe:cornish-pasty"` (类似于命名空间的 前缀) +`"ingredient:flour"` (不同的前缀) + +**实际行为 (Actual behavior) (extract.py:517-520):** +```python +# Treat as entity instance - construct unique URI +normalized = value.replace(" ", "-").lower() +return f"https://trustgraph.ai/{ontology_id}/{normalized}" +``` + +**影响:** LLM 必须在没有任何本体知识的情况下猜测前缀约定。 + +### 4. **没有命名空间前缀的指导** + +**问题:** 本体 JSON 包含命名空间定义(food.ontology 中的第 10-25 行): +```json +"namespaces": { + "fo": "http://purl.org/ontology/fo/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + ... +} +``` + +但是这些内容永远不会传递给大型语言模型。大型语言模型不知道: +"fo" 的含义 +应使用哪个前缀来表示实体 +哪个命名空间适用于哪些元素 + +### 5. **未在提示中使用标签** + +**问题:** 每一个类都有 `rdfs:label` 字段(例如,`{"value": "Recipe", "lang": "en-gb"}`),但提示模板没有使用它们。 + +**当前:** 只显示 `class_id` 和 `comment` +```jinja +- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %} +``` + +**可用但未使用的:** +```python +"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}] +``` + +**影响:** 可以为技术 ID 旁边提供人类可读的名称。 + +## 提出的解决方案 + +### 方案 A:标准化为不带前缀的 ID + +**方法:** 在向 LLM 显示之前,从类 ID 中移除前缀。 + +**变更:** +1. 修改 `build_extraction_variables()` 以转换键: + ```python + classes_for_prompt = { + k.split('/')[-1]: v # "fo/Recipe" → "Recipe" + for k, v in ontology_subset.classes.items() + } + ``` + +2. 将提示示例更新为匹配项(已使用未加前缀的名称)。 + +3. 修改 `expand_uri()` 以处理两种格式: + ```python + # Try exact match first + if value in ontology_subset.classes: + return ontology_subset.classes[value]['uri'] + + # Try with prefix + for prefix in ['fo/', 'rdf:', 'rdfs:']: + prefixed = f"{prefix}{value}" + if prefixed in ontology_subset.classes: + return ontology_subset.classes[prefixed]['uri'] + ``` + +**优点:** +更清晰,更易于人类阅读 +与现有的提示示例相符 +LLM(大型语言模型)在处理更简单的token时效果更好 + +**缺点:** +如果多个本体具有相同的类名,则可能发生类名冲突 +丢失命名空间信息 +需要回退逻辑来执行查找 + +### 选项 B:始终使用完整的带前缀的 ID + +**方法:** 更新示例,使其使用与类列表中显示的前缀 ID 匹配。 + +**更改:** +1. 更新提示示例(ontology-prompt.md:46-52): + ```json + [ + {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"}, + {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"}, + {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"}, + {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"} + ] + ``` + +2. 在提示语中添加命名空间说明: + ```markdown + ## Namespace Prefixes: + - **fo/**: Food Ontology (http://purl.org/ontology/fo/) + - **rdf:**: RDF Schema + - **rdfs:**: RDF Schema + + Use these prefixes exactly as shown when referencing classes and properties. + ``` + +3. 保持 `expand_uri()` 的原样 (当找到匹配项时,它可以正常工作)。 + +**优点:** +输入 = 输出的一致性。 +没有信息损失。 +保留命名空间语义。 +适用于多个本体。 + +**缺点:** +对于 LLM 来说,token 更加冗长。 +需要 LLM 跟踪前缀。 + +### 选项 C:混合 - 同时显示标签和 ID + +**方法:** 增强提示,同时显示人类可读的标签和技术 ID。 + +**更改:** +1. 更新提示模板: + ```jinja + {% for class_id, class_def in classes.items() %} + - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %} + {% endfor %} + ``` + + 示例输出: + ```markdown + - **fo/Recipe** (label: "Recipe"): A Recipe is a combination... + ``` + +2. 更新说明: + ```markdown + When referencing classes: + - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output + - The label (e.g., "Recipe") is for human understanding only + ``` + +**优点 (Pros)**: +对 LLM 最清晰 +保留所有信息 +明确说明应该使用什么 + +**缺点 (Cons)**: +提示更长 +模板更复杂 + +## 实施方法 (Implemented Approach) + +**简化的实体-关系-属性格式** - 完全取代了旧的三元组格式。 + +选择了这种新方法的原因是: + +1. **无信息损失 (No Information Loss)**: 原始 URI 正确保留 +2. **更简单的逻辑 (Simpler Logic)**: 无需转换,可以直接使用字典查找 +3. **命名空间安全 (Namespace Safety)**: 能够处理多个本体而不会发生冲突 +4. **语义正确性 (Semantic Correctness)**: 保持 RDF/OWL 语义 + +## 实施完成 (Implementation Complete) + +### 构建内容 (What Was Built): + +1. **新的提示模板 (New Prompt Template)** (`prompts/ontology-extract-v2.txt`) + ✅ 清晰的章节:实体类型、关系、属性 + ✅ 使用完整类型标识符的示例 (`fo/Recipe`, `fo/has_ingredient`) + ✅ 指示使用模式中确切的标识符 + ✅ 新的 JSON 格式,包含实体/关系/属性数组 + +2. **实体规范化 (Entity Normalization)** (`entity_normalizer.py`) + ✅ `normalize_entity_name()` - 将名称转换为 URI 安全格式 + ✅ `normalize_type_identifier()` - 处理类型中的斜杠 (`fo/Recipe` → `fo-recipe`) + ✅ `build_entity_uri()` - 使用 (名称, 类型) 元组创建唯一 URI + ✅ `EntityRegistry` - 跟踪实体以进行去重 + +3. **JSON 解析器 (JSON Parser)** (`simplified_parser.py`) + ✅ 解析新的格式:`{entities: [...], relationships: [...], attributes: [...]}` + ✅ 支持 kebab-case 和 snake_case 字段名称 + ✅ 返回结构化的数据类 + ✅ 具有优雅的错误处理和日志记录 + +4. **三元组转换器 (Triple Converter)** (`triple_converter.py`) + ✅ `convert_entity()` - 自动生成类型 + 标签三元组 + ✅ `convert_relationship()` - 通过属性连接实体 URI + ✅ `convert_attribute()` - 添加字面值 + ✅ 从本体定义中查找完整的 URI + +5. **更新的主要处理器 (Updated Main Processor)** (`extract.py`) + ✅ 删除了旧的三元组提取代码 + ✅ 添加了 `extract_with_simplified_format()` 方法 + ✅ 现在仅使用新的简化格式 + ✅ 使用 `extract-with-ontologies-v2` ID 调用提示 + +## 测试用例 (Test Cases) + +### 测试 1: URI 保留 (Test 1: URI Preservation) +```python +# Given ontology class +classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}} + +# When LLM returns +llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"} + +# Then expanded URI should be +assert expanded == "http://purl.org/ontology/fo/Recipe" +# Not: "https://trustgraph.ai/ontology/food#Recipe" +``` + +### 测试 2:多本体冲突 +```python +# Given two ontologies +ont1 = {"fo/Recipe": {...}} +ont2 = {"cooking/Recipe": {...}} + +# LLM should use full prefix to disambiguate +llm_output = {"object": "fo/Recipe"} # Not just "Recipe" +``` + +### 测试 3:实体实例格式 +```python +# Given prompt with food ontology +# LLM should create instances like +{"subject": "recipe:cornish-pasty"} # Namespace-style +{"subject": "food:beef"} # Consistent prefix +``` + +## 待解决的问题 + +1. **实体实例是否应该使用命名空间前缀?** + 当前:`"recipe:cornish-pasty"` (任意) + 替代方案:使用本体前缀 `"fo:cornish-pasty"`? + 替代方案:不使用前缀,在 URI 中展开 `"cornish-pasty"` → 完整 URI? + +2. **如何在提示中处理域/范围?** + 当前显示:`(Recipe → Food)` + 应该是:`(fo/Recipe → fo/Food)`? + +3. **是否应该验证域/范围约束?** + TODO 注释在 extract.py:470 + 可以捕获更多错误,但更复杂 + +4. **关于反向属性和等价性?** + 本体有 `owl:inverseOf`,`owl:equivalentClass` + 当前未在提取中使用 + 应该使用吗? + +## 成功指标 + +✅ 零 URI 信息损失(100% 保留原始 URI) +✅ LLM 输出格式与输入格式匹配 +✅ 提示中没有歧义的示例 +✅ 使用多个本体的测试通过 +✅ 提取质量得到改进(通过有效的三元组百分比衡量) + +## 替代方法:简化的提取格式 + +### 理念 + +不要让 LLM 理解 RDF/OWL 语义,而是让它做擅长的事情:**在文本中查找实体和关系**。 + +让代码处理 URI 构造、RDF 转换和语义网规范。 + +### 示例:实体分类 + +**输入文本:** +``` +Cornish pasty is a traditional British pastry filled with meat and vegetables. +``` + +**本体模式(显示给LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food +``` + +**LLM 返回的内容(简单 JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + } + ] +} +``` + +**生成的代码(RDF 三元组):** +```python +# 1. Normalize entity name + type to ID (type prevents collisions) +entity_id = "recipe-cornish-pasty" # normalize("Cornish pasty", "Recipe") +entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty" + +# Note: Same name, different type = different URI +# "Cornish pasty" (Recipe) → recipe-cornish-pasty +# "Cornish pasty" (Food) → food-cornish-pasty + +# 2. Generate triples +triples = [ + # Type triple + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + # Label triple (automatic) + Triple( + s=Value(value=entity_uri, is_uri=True), + p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True), + o=Value(value="Cornish pasty", is_uri=False) + ) +] +``` + +### 优点 + +1. **LLM 不需要:** + 理解 URI 语法 + 编造标识符前缀 (`recipe:`, `ingredient:`) + 了解 `rdf:type` 或 `rdfs:label` + 构建语义网标识符 + +2. **LLM 只需要:** + 在文本中找到实体 + 将它们映射到本体类 + 提取关系和属性 + +3. **代码负责:** + URI 规范化和构建 + RDF 三元组生成 + 自动标签分配 + 命名空间管理 + +### 为什么这样更好 + +**更简单的提示** = 减少困惑 = 更少的错误 +**一致的 ID** = 代码控制规范化规则 +**自动生成的标签** = 没有遗漏的 rdfs:label 三元组 +**LLM 专注于提取** = 这是它擅长的事情 + +### 示例:实体关系 + +**输入文本:** +``` +Cornish pasty is a traditional British pastry filled with beef and potatoes. +``` + +**本体模式(显示给LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method +- Food: A food is something that can be eaten +- Ingredient: An ingredient combines a quantity and a food + +## Relationships: +- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient) +- food: Relates an ingredient to the food that is required (Ingredient → Food) +``` + +**LLM 返回的内容(简单 JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ] +} +``` + +**生成的代码(RDF 三元组):** +```python +# Normalize entity names to URIs +cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty" +beef_uri = "https://trustgraph.ai/food/beef" +potatoes_uri = "https://trustgraph.ai/food/potatoes" + +# Look up relation URI from ontology +has_ingredient_uri = "http://purl.org/ontology/fo/ingredients" # from fo/has_ingredient + +triples = [ + # Entity type triples (as before) + Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"), + Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"), + + Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=beef_uri, p=rdfs_label, o="beef"), + + Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"), + Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"), + + # Relationship triples + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=beef_uri, is_uri=True) + ), + Triple( + s=Value(value=cornish_pasty_uri, is_uri=True), + p=Value(value=has_ingredient_uri, is_uri=True), + o=Value(value=potatoes_uri, is_uri=True) + ) +] +``` + +**关键点:** +LLM 返回自然语言实体名称:`"Cornish pasty"`, `"beef"`, `"potatoes"` +LLM 包含类型信息以消除歧义:`subject-type`, `object-type` +LLM 使用模式中的关系名称:`"has_ingredient"` +代码使用 (名称, 类型) 推导一致的 ID:`("Cornish pasty", "Recipe")` → `recipe-cornish-pasty` +代码从本体中查找关系 URI:`fo/has_ingredient` → 完整 URI +相同的 (名称, 类型) 元组始终获得相同的 URI (去重) + +### 示例:实体名称消除歧义 + +**问题:** 相同的名称可能指不同的实体类型。 + +**实际案例:** +``` +"Cornish pasty" can be: +- A Recipe (instructions for making it) +- A Food (the dish itself) +``` + +**处理方式:** + +LLM 将两者都以独立的实体返回: +```json +{ + "entities": [ + {"entity": "Cornish pasty", "type": "Recipe"}, + {"entity": "Cornish pasty", "type": "Food"} + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "produces", + "object": "Cornish pasty", + "object-type": "Food" + } + ] +} +``` + +**代码解析:** +```python +# Different types → different URIs +recipe_uri = normalize("Cornish pasty", "Recipe") +# → "https://trustgraph.ai/food/recipe-cornish-pasty" + +food_uri = normalize("Cornish pasty", "Food") +# → "https://trustgraph.ai/food/food-cornish-pasty" + +# Relationship connects them correctly +triple = Triple( + s=recipe_uri, # The Recipe + p="http://purl.org/ontology/fo/produces", + o=food_uri # The Food +) +``` + +**原理:** +类型包含在所有引用中(实体、关系、属性)。 +代码使用 `(name, type)` 元组作为查找键。 +没有歧义,没有冲突。 + +### 示例:实体属性 + +**输入文本:** +``` +This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare. +``` + +**本体模式(显示给LLM):** +```markdown +## Entity Types: +- Recipe: A recipe is a combination of ingredients and a method + +## Attributes: +- serves: Indicates what the recipe is intended to serve (Recipe → text) +- preparation_time: Time needed to prepare the recipe (Recipe → text) +``` + +**LLM 返回的内容(简单 JSON):** +```json +{ + "entities": [ + { + "entity": "Cornish pasty recipe", + "type": "Recipe" + } + ], + "attributes": [ + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4-6 people" + }, + { + "entity": "Cornish pasty recipe", + "entity-type": "Recipe", + "attribute": "preparation_time", + "value": "45 minutes" + } + ] +} +``` + +**生成的代码(RDF 三元组):** +```python +# Normalize entity name to URI +recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe" + +# Look up attribute URIs from ontology +serves_uri = "http://purl.org/ontology/fo/serves" # from fo/serves +prep_time_uri = "http://purl.org/ontology/fo/preparation_time" # from fo/preparation_time + +triples = [ + # Entity type triple + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdf_type, is_uri=True), + o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True) + ), + + # Label triple (automatic) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=rdfs_label, is_uri=True), + o=Value(value="Cornish pasty recipe", is_uri=False) + ), + + # Attribute triples (objects are literals, not URIs) + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=serves_uri, is_uri=True), + o=Value(value="4-6 people", is_uri=False) # Literal value! + ), + Triple( + s=Value(value=recipe_uri, is_uri=True), + p=Value(value=prep_time_uri, is_uri=True), + o=Value(value="45 minutes", is_uri=False) # Literal value! + ) +] +``` + +**关键点:** +LLM 提取字面值:`"4-6 people"`, `"45 minutes"` +LLM 包含实体类型以消除歧义:`entity-type` +LLM 使用来自模式的属性名称:`"serves"`, `"preparation_time"` +代码从本体数据类型属性中查找属性 URI +**对象是字面值** (`is_uri=False`),而不是 URI 引用 +值保持为自然文本,无需进行任何标准化 + +**与关系的差异:** +关系:主语和宾语都是实体(URI) +属性:主语是实体(URI),宾语是字面值(字符串/数字) + +### 完整示例:实体 + 关系 + 属性 + +**输入文本:** +``` +Cornish pasty is a savory pastry filled with beef and potatoes. +This recipe serves 4 people. +``` + +**LLM 返回的内容:** +```json +{ + "entities": [ + { + "entity": "Cornish pasty", + "type": "Recipe" + }, + { + "entity": "beef", + "type": "Food" + }, + { + "entity": "potatoes", + "type": "Food" + } + ], + "relationships": [ + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "beef", + "object-type": "Food" + }, + { + "subject": "Cornish pasty", + "subject-type": "Recipe", + "relation": "has_ingredient", + "object": "potatoes", + "object-type": "Food" + } + ], + "attributes": [ + { + "entity": "Cornish pasty", + "entity-type": "Recipe", + "attribute": "serves", + "value": "4 people" + } + ] +} +``` + +**结果:** 生成了 11 个 RDF 三元组: +3 个实体类型三元组 (rdf:type) +3 个实体标签三元组 (rdfs:label) - 自动 +2 个关系三元组 (has_ingredient) +1 个属性三元组 (serves) + +所有内容均由 LLM 通过简单的、自然的语言提取得出! + +## 参考文献 + +当前实现:`trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` +提示模板:`ontology-prompt.md` +测试用例:`tests/unit/test_extract/test_ontology/` +示例本体:`e2e/test-data/food.ontology` diff --git a/docs/tech-specs/ontology.ar.md b/docs/tech-specs/ontology.ar.md new file mode 100644 index 00000000..2bca0eab --- /dev/null +++ b/docs/tech-specs/ontology.ar.md @@ -0,0 +1,179 @@ +--- +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. توفر الأنطولوجيا نماذج معرفية رسمية تحدد الفئات والخصائص والعلاقات، مما يدعم قدرات الاستدلال والاستنتاج. يستخدم النظام تنسيقًا مستوحى من OWL، والذي يمثل على نطاق واسع مفاهيم OWL/RDFS، مع تحسينه لتلبية متطلبات TrustGraph. + +**اتفاقية التسمية:** يستخدم هذا المشروع نمط "kebab-case" لجميع المعرفات (مفاتيح التكوين، ونقاط نهاية واجهة برمجة التطبيقات، وأسماء الوحدات، إلخ) بدلاً من نمط "snake_case". + +## الأهداف + +- **إدارة الفئات والخصائص:** تحديد فئات تشبه OWL مع خصائص ومجالات ونطاقات وقيود النوع. +- **دعم دلالي غني:** تمكين خصائص RDFS/OWL شاملة بما في ذلك التسميات ودعم لغات متعددة والقيود الرسمية. +- **دعم أنطولوجيا متعددة:** السماح لعدة أنطولوجيا بالوجود والتفاعل مع بعضها البعض. +- **التحقق والاستدلال:** ضمان توافق الأنطولوجيا مع معايير تشبه OWL مع التحقق من الاتساق ودعم الاستدلال. +- **التوافق مع المعايير:** دعم الاستيراد/التصدير بتنسيقات قياسية (Turtle، RDF/XML، OWL/XML) مع الحفاظ على التحسين الداخلي. + +## الخلفية + +يخزن نظام TrustGraph الأنطولوجيا كعناصر تكوين في نظام مرن من المفاتيح والقيم. على الرغم من أن التنسيق مستوحى من OWL (Web Ontology Language)، إلا أنه مُحسَّن لحالات الاستخدام المحددة لـ TrustGraph ولا يلتزم بشكل صارم بجميع مواصفات OWL. + +تُمكّن الأنطولوجيا في TrustGraph: +- تعريف أنواع الكائنات الرسمية وخصائصها. +- تحديد نطاقات وقيود أنواع الخصائص. +- الاستدلال والاستنتاج المنطقي. +- علاقات معقدة وقيود التعددية. +- دعم لغات متعددة للترجمة. + +## هيكل الأنطولوجيا + +### تخزين التكوين + +يتم تخزين الأنطولوجيا كعناصر تكوين بالنمط التالي: +- **النوع:** `ontology` +- **المفتاح:** معرف الأنطولوجيا الفريد (على سبيل المثال، `natural-world`، `domain-model`). +- **القيمة:** الأنطولوجيا بأكملها بتنسيق JSON. + +### هيكل JSON + +يتكون تنسيق JSON للأنطولوجيا من أربعة أقسام رئيسية: + +#### 1. البيانات الوصفية (Metadata) + +يحتوي على معلومات إدارية ووصفية حول الأنطولوجيا: + +```json +{ + "metadata": { + "name": "العالم الطبيعي", + "description": "أنطولوجيا تغطي النظام الطبيعي", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**الحقول:** +- `name`: الاسم القابل للقراءة البشرية للأنطولوجيا. +- `description`: وصف موجز لغرض الأنطولوجيا. +- `version`: رقم الإصدار الدلالي. +- `created`: طابع زمني ISO 8601 للإعداد. +- `modified`: طابع زمني ISO 8601 للتعديل الأخير. +- `creator`: معرف المستخدم/النظام الذي قام بإنشاء الأنطولوجيا. +- `namespace`: عنوان URI الأساسي لعناصر الأنطولوجيا. +- `imports`: مصفوفة من عناوين URI للأنطولوجيا المستوردة. + +#### 2. الفئات (Classes) + +تحدد أنواع الكائنات والعلاقات الهرمية بينها: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "حيوان", "lang": "en"}], + "rdfs:comment": "حيوان", + "rdfs:subClassOf": "lifeform", + "owl:equivalentClass": ["cat", "dog"], + "owl:disjointWith": ["cat"] + }, + "lifeform": { + "uri": "http://trustgraph.ai/ontologies/natural-world#lifeform", + "type": "owl:Class", + "rdfs:label": [{"value": "كائن حي", "lang": "en"}], + "rdfs:comment": "كائن حي" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "قط", "lang": "en"}], + "rdfs:comment": "قط", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "كلب", "lang": "en"}], + "rdfs:comment": "كلب", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + } +} +``` + +#### 3. الخصائص (Object Properties) + +تحدد العلاقات بين الفئات: + +```json +{ + "objectProperties": {} +} +``` + +#### 4. خصائص البيانات (Data Properties) + +تحدد الخصائص التي تربط الكائنات ببيانات: + +```json +{ + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "عدد الأرجل", "lang": "en"}], + "rdfs:comment": "عدد أرجل الحيوان", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +## قواعد التحقق + +### التحقق الهيكلي + +1. **اتساق URI:** يجب أن تتبع جميع عناوين URI النمط `{namespace}#{identifier}`. +2. **هرمية الفئات:** لا توجد علاقات إرثية دائرية في `rdfs:subClassOf`. +3. **نطاقات وقيود أنواع الخصائص:** يجب أن تشير إلى فئات موجودة أو أنواع XSD صالحة. +4. **فئات متباينة:** لا يمكن أن تكون فئة فرعية من فئة أخرى. +5. **خصائص عكسية:** يجب أن تكون ثنائية الاتجاه إذا تم تحديدها. + +### التحقق الدلالي + +1. **معرفات فريدة:** يجب أن تكون معرّفات الفئات والخصائص فريدة داخل أنطولوجيا واحدة. +2. **علامات اللغة:** يجب أن تتبع تنسيق علامة اللغة BCP 47. +3. **قيود التعددية:** يجب أن يكون `minCardinality` ≤ `maxCardinality` عند تحديد كليهما. +4. **خصائص وظيفية:** لا يمكن أن يكون لها `maxCardinality` > 1. + +## دعم تنسيق الاستيراد/التصدير + +في حين أن التنسيق الداخلي هو JSON، يدعم النظام التحويل إلى/من تنسيقات الأنطولوجيا القياسية: + +- **Turtle (.ttl):** تسلسل RDF مضغوط. +- **RDF/XML (.rdf، .owl):** تنسيق W3C قياسي. +- **OWL/XML (.owx):** تنسيق XML خاص بـ OWL. +- **JSON-LD (.jsonld):** JSON للبيانات المرتبطة. + +## المراجع + +- [OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +- [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) +- [XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) +- [BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.es.md b/docs/tech-specs/ontology.es.md new file mode 100644 index 00000000..a50b50ca --- /dev/null +++ b/docs/tech-specs/ontology.es.md @@ -0,0 +1,277 @@ +--- +layout: default +title: "Especificación Técnica de la Estructura de Ontologías" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de la Estructura de Ontologías + +> **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 la estructura y el formato de las ontologías dentro del sistema TrustGraph. Las ontologías proporcionan modelos de conocimiento formales que definen clases, propiedades y relaciones, lo que permite capacidades de razonamiento e inferencia. El sistema utiliza un formato de configuración inspirado en OWL que representa ampliamente los conceptos de OWL/RDFS, al tiempo que está optimizado para los requisitos de TrustGraph. + +**Convención de Nombres**: Este proyecto utiliza kebab-case para todos los identificadores (claves de configuración, puntos finales de la API, nombres de módulos, etc.) en lugar de snake_case. + +## Objetivos + +- **Gestión de Clases y Propiedades**: Definir clases similares a OWL con propiedades, dominios, rangos y restricciones de tipo. +- **Soporte Semántico Avanzado**: Permitir propiedades completas de RDFS/OWL, incluyendo etiquetas, soporte multilingüe y restricciones formales. +- **Soporte para Múltiples Ontologías**: Permitir que múltiples ontologías coexistan e interactúen. +- **Validación y Razonamiento**: Asegurar que las ontologías cumplan con estándares similares a OWL, con verificación de consistencia y soporte de inferencia. +- **Compatibilidad con Estándares**: Soporte de importación/exportación en formatos estándar (Turtle, RDF/XML, OWL/XML) al tiempo que se mantiene la optimización interna. + +## Antecedentes + +TrustGraph almacena ontologías como elementos de configuración en un sistema flexible de clave-valor. Si bien el formato está inspirado en OWL (Web Ontology Language), está optimizado para los casos de uso específicos de TrustGraph y no se adhiere estrictamente a todas las especificaciones de OWL. + +Las ontologías en TrustGraph permiten: +- Definición de tipos de objetos formales y sus propiedades. +- Especificación de dominios, rangos y restricciones de tipo de propiedades. +- Razonamiento e inferencia lógicos. +- Relaciones complejas y restricciones de cardinalidad. +- Soporte multilingüe para la internacionalización. + +## Estructura de la Ontología + +### Almacenamiento de la Configuración + +Las ontologías se almacenan como elementos de configuración con el siguiente patrón: +- **Tipo**: `ontology` +- **Clave**: Identificador de ontología único (por ejemplo, `natural-world`, `domain-model`). +- **Valor**: Ontología completa en formato JSON. + +### Estructura JSON + +El formato JSON de la ontología consta de cuatro secciones principales: + +#### 1. Metadatos + +Contiene información administrativa y descriptiva sobre la ontología: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**Campos:** +- `name`: Nombre legible por humanos de la ontología. +- `description`: Descripción breve del propósito de la ontología. +- `version`: Número de versión semántico. +- `created`: Marca de tiempo ISO 8601 de creación. +- `modified`: Marca de tiempo ISO 8601 de última modificación. +- `creator`: Identificador del usuario/sistema que creó. +- `namespace`: URI base para elementos de la ontología. +- `imports`: Matriz de URIs de ontologías importadas. + +#### 2. Clases + +Define los tipos de objetos y sus relaciones jerárquicas: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform", + "owl:equivalentClass": ["creature"], + "owl:disjointWith": ["plant"], + "dcterms:identifier": "ANI-001" + } + } +} +``` + +**Propiedades soportadas:** +- `uri`: URI completa de la clase. +- `type`: Siempre `"owl:Class"`. +- `rdfs:label`: Matriz de etiquetas con etiquetas de idioma. +- `rdfs:comment`: Descripción de la clase. +- `rdfs:subClassOf`: Identificador de la clase padre (herencia simple). +- `owl:equivalentClass`: Lista de clases equivalentes. +- `owl:disjointWith`: Lista de clases disjuntas. +- `dcterms:identifier`: Identificador de la clase. + +#### 3. Propiedades de Objetos + +Define las relaciones entre las clases: + +```json +{ + "objectProperties": { + "hasPart": { + "uri": "http://trustgraph.ai/ontologies/natural-world#hasPart", + "type": "owl:ObjectProperty", + "rdfs:label": [{"value": "hasPart", "lang": "en"}], + "rdfs:comment": "Represents a part-whole relationship", + "domain": "lifeform", + "range": "lifeform" + } + } +} +``` + +**Propiedades soportadas:** +- `uri`: URI completa de la propiedad de objeto. +- `type`: Siempre `"owl:ObjectProperty"`. +- `rdfs:label`: Matriz de etiquetas con etiquetas de idioma. +- `rdfs:comment`: Descripción de la propiedad de objeto. +- `domain`: Clase de dominio de la propiedad de objeto. +- `range`: Clase de rango de la propiedad de objeto. + +#### 4. Propiedades de Datos + +Define las características de las clases: + +```json +{ + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +**Propiedades soportadas:** +- `uri`: URI completa de la propiedad de datos. +- `type`: Siempre `"owl:DatatypeProperty"`. +- `rdfs:label`: Matriz de etiquetas con etiquetas de idioma. +- `rdfs:comment`: Descripción de la propiedad de datos. +- `rdfs:range`: Tipo de datos de la propiedad de datos. +- `rdfs:domain`: Clase de dominio de la propiedad de datos. + +### Estructura JSON + +El formato JSON de la ontología consta de cuatro secciones principales: + +#### 1. Metadatos + +Contiene información administrativa y descriptiva sobre la ontología: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**Campos:** +- `name`: Nombre legible por humanos de la ontología. +- `description`: Descripción breve del propósito de la ontología. +- `version`: Número de versión semántico. +- `created`: Marca de tiempo ISO 8601 de creación. +- `modified`: Marca de tiempo ISO 8601 de última modificación. +- `creator`: Identificador del usuario/sistema que creó. +- `namespace`: URI base para elementos de la ontología. +- `imports`: Matriz de URIs de ontologías importadas. + +#### 2. Clases + +Define los tipos de objetos y sus relaciones jerárquicas: + +```json +{ + "classes": { + "lifeform": { + "uri": "http://trustgraph.ai/ontologies/natural-world#lifeform", + "type": "owl:Class", + "rdfs:label": [{"value": "Lifeform", "lang": "en"}], + "rdfs:comment": "A living thing" + }, + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "Cat", "lang": "en"}], + "rdfs:comment": "A cat", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "Dog", "lang": "en"}], + "rdfs:comment": "A dog", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + }, + "objectProperties": {}, + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +## Reglas de Validación + +### Validación Estructural + +1. **Consistencia de URI**: Todos los URIs deben seguir el patrón `{namespace}#{identifier}`. +2. **Jerarquía de Clases**: No debe haber herencia circular en `rdfs:subClassOf`. +3. **Dominios/Rangos de Propiedades**: Deben referenciar clases existentes o tipos XSD válidos. +4. **Clases Disjuntas**: No pueden ser subclases entre sí. +5. **Propiedades Inversas**: Deben ser bidireccionales si se especifican. + +### Validación Semántica + +1. **Identificadores Únicos**: Los identificadores de clase y propiedad deben ser únicos dentro de una ontología. +2. **Etiquetas de Idioma**: Deben seguir el formato de etiqueta de idioma BCP 47. +3. **Restricciones de Cardinalidad**: `minCardinality` ≤ `maxCardinality` cuando ambos están especificados. +4. **Propiedades Funcionales**: No pueden tener `maxCardinality` > 1. + +## Soporte de Formato de Importación/Exportación + +Si bien el formato interno es JSON, el sistema admite la conversión a/desde formatos de ontología estándar: + +- **Turtle (.ttl)**: Serialización RDF compacta. +- **RDF/XML (.rdf, .owl)**: Formato estándar de W3C. +- **OWL/XML (.owx)**: Formato XML específico de OWL. +- **JSON-LD (.jsonld)**: JSON para Linked Data. + +## Referencias + +- [OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +- [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) +- [XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) +- [BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.he.md b/docs/tech-specs/ontology.he.md new file mode 100644 index 00000000..2634b7f1 --- /dev/null +++ b/docs/tech-specs/ontology.he.md @@ -0,0 +1,208 @@ +--- +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. אונטולוגיות מספקות מודלים פורמליים של ידע המגדירים מחלקות, תכונות ויחסים, ומאפשרים יכולות של הסקה והסקת מסקנות. המערכת משתמשת בפורמט תצורה השואב השראה מ-OWL, ומייצג באופן כללי מושגי OWL/RDFS תוך התאמה לדרישות של TrustGraph. + +**נוהל שמות:** הפרויקט משתמש בפורמט "קאב-קייז" (kebab-case) לכל המזהים (מפתחות תצורה, נקודות קצה של API, שמות מודולים, וכו') במקום "סנקה_קייז" (snake_case). + +## מטרות + +- **ניהול מחלקות ותכונות:** הגדרת מחלקות "דו-צורתיות" עם תכונות, תחומים, טווחי ערכים ומגבלות סוג +- **תמיכה סמנטית עשירה:** אפשרות לתכונות RDFS/OWL מקיפות, כולל תוויות, תמיכה רב-לשונית ומגבלות פורמליות +- **תמיכה באונטולוגיות מרובות:** אפשרות לאונטולוגיות מרובות להתקיים ולפעול יחד +- **אימות והסקה:** הבטחת עמידה של האונטולוגיות בתקנים דמויי-OWL תוך בדיקות עקביות ותמיכה בהסקה +- **תאימות לתקנים:** תמיכה בייבוא/ייצוא בפורמטים סטנדרטיים (Turtle, RDF/XML, OWL/XML) תוך שמירה על אופטימיזציה פנימית + +## רקע + +TrustGraph מאחסן אונטולוגיות כפריטים תצורה במערכת מבוססת מפתח-ערך גמישה. למרות שהפורמט מושפע מ-OWL (שפת אונטולוגיה ווב), הוא מותאם במיוחד לשימושים הספציפיים של TrustGraph ואינו עומד במלואן בכל המפרטים של OWL. + +אונטולוגיות ב-TrustGraph מאפשרות: +- הגדרה של סוגי אובייקט פורמליים והתכונות שלהם +- הגדרה של תחומים, טווחי ערכים ומגבלות סוג +- הסקה וסקת מסקנות +- יחסים מורכבים ומגבלות כמותיות +- תמיכה רב-לשונית לבינלאומיות + +## מבנה אונטולוגי + +### אחסון תצורה + +אונטולוגיות מאוחסנות כפריטי תצורה עם התבנית הבאה: +- **סוג:** `ontology` +- **מפתח:** מזהה אונטולוגי ייחודי (למשל, `natural-world`, `domain-model`) +- **ערך:** האונטולוגיה השלמה בפורמט JSON + +### מבנה JSON + +פורמט ה-JSON של האונטולוגיה מורכב מארבעה חלקים עיקריים: + +#### 1. מטא-נתונים + +מכיל מידע ניהולי ותיאורי על האונטולוגיה: + +```json +{ + "metadata": { + "name": "העולם הטבעי", + "description": "אונטולוגיה המכסה את הסדר הטבעי", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "משתמש נוכחי", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**שדות:** +- `name`: שם אנושי של האונטולוגיה +- `description`: תיאור קצר של מטרת האונטולוגיה +- `version`: מספר גרסה סמנטי +- `created`: תאריך ושעה של יצירה בפורמט ISO 8601 +- `modified`: תאריך ושעה של העדכון האחרון בפורמט ISO 8601 +- `creator`: מזהה המשתמש/מערכת שיוצרת +- `namespace`: URI בסיסי עבור אלמנטי האונטולוגיה +- `imports`: מערך של URI של אונטולוגיות ייבוא + +#### 2. מחלקות + +מגדיר סוגי אובייקט ויחסים היררכיים: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "בעל חיים", + "rdfs:subClassOf": "lifeform" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "Cat", "lang": "en"}], + "rdfs:comment": "חתול", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "Dog", "lang": "en"}], + "rdfs:comment": "כלב", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + } +} +``` + +#### 3. תכונות + +מגדיר יחסים בין מחלקות: + +```json +{ + "objectProperties": {}, + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "ספירת הרגלי הבעל חיים", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +#### 4. קובץ JSON לדוגמה (סגנון) + +```json +{ + "metadata": { + "name": "אונטולוגיית בעלי חיים", + "version": "1.0", + "description": "אונטולוגיה המגדירה סוגי בעלי חיים", + "created": "2024-01-01T00:00:00Z", + "modified": "2024-01-01T00:00:00Z", + "creator": "המשתמש" + }, + "classes": { + "בעל חיים": { + "uri": "http://example.com/animals#Animal", + "type": "owl:Class", + "rdfs:label": { + "value": "בעל חיים", + "lang": "en" + } + }, + "חתול": { + "uri": "http://example.com/animals#Cat", + "type": "owl:Class", + "rdfs:label": { + "value": "חתול", + "lang": "en" + }, + "rdfs:subClassOf": "בעל חיים" + }, + "כלב": { + "uri": "http://example.com/animals#Dog", + "type": "owl:Class", + "rdfs:label": { + "value": "כלב", + "lang": "en" + }, + "rdfs:subClassOf": "בעל חיים", + "owl:disjointWith": [ + "חתול" + ] + } + }, + "properties": { + "hasBody": { + "type": "owl:ObjectProperty", + "domain": "בעל חיים", + "range": "http://example.com/things#Body" + } + } +} +``` + +## כללי אימות + +### אימות מבני + +1. **עקביות URI:** כל ה-URI צריכים להיות בפורמט `{namespace}#{identifier}` +2. **היררכיית מחלקות:** אין ירושה מעגלית ב-`rdfs:subClassOf` +3. **תחומים/טווח תכונות:** צריכים להתייחס למחלקות קיימות או לסוגי XSD תקינים +4. **מחלקות חופפות:** לא יכולות להיות תחת מחלקות אחרות +5. **תכונות דו-כיוניות:** אם מצוינות, חייבות להיות דו-כיוניות + +### אימות סמנטי + +1. **מזהים ייחודיים:** מזהי מחלקות ותכונות צריכים להיות ייחודיים באונטולוגיה +2. **תוויות שפה:** צריכות להיות בפורמט BCP 47 +3. **מגבלות כמותיות:** `minCardinality` ≤ `maxCardinality` כאשר שניהם מצוינים +4. **תכונות פונקציונליות:** לא צריכות להכיל `maxCardinality` > 1 + +## תמיכה בפורמט ייבוא/ייצוא + +למרות שהפורמט הפנימי הוא JSON, המערכת תומכת בהמרה בין פורמטים סטנדרטיים של אונטולוגיות: + +- **Turtle (.ttl)** - פורמט RDF קומפקטי +- **RDF/XML (.rdf, .owl)** - פורמט W3C סטנדרטי +- **OWL/XML (.owx)** - פורמט OWL ספציפי ל-XML +- **JSON-LD (.jsonld)** - JSON עבור נתונים מקושרים diff --git a/docs/tech-specs/ontology.hi.md b/docs/tech-specs/ontology.hi.md new file mode 100644 index 00000000..36f8fd5e --- /dev/null +++ b/docs/tech-specs/ontology.hi.md @@ -0,0 +1,188 @@ +--- +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. + +## अवलोकन + +यह विनिर्देश ट्रस्टग्राफ सिस्टम के भीतर ऑन्टोलॉजी की संरचना और प्रारूप का वर्णन करता है। ऑन्टोलॉजी औपचारिक ज्ञान मॉडल प्रदान करते हैं जो क्लास, गुण और संबंधों को परिभाषित करते हैं, और तर्क और अनुमान क्षमताओं का समर्थन करते हैं। सिस्टम एक OWL-प्रेरित कॉन्फ़िगरेशन प्रारूप का उपयोग करता है जो व्यापक रूप से OWL/RDFS अवधारणाओं का प्रतिनिधित्व करता है, जबकि ट्रस्टग्राफ की आवश्यकताओं के लिए अनुकूलित है। + +**नामकरण सम्मेलन**: यह परियोजना सभी पहचानकर्ताओं (कॉन्फ़िगरेशन कुंजियों, API एंडपॉइंट, मॉड्यूल नामों, आदि) के लिए "केबब-केस" का उपयोग करती है, न कि "स्नेक_केस" का। + +## लक्ष्य + +- **क्लास और प्रॉपर्टी प्रबंधन**: OWL-जैसी क्लास को प्रॉपर्टी, डोमेन, रेंज और टाइप बाधाओं के साथ परिभाषित करें। +- **समृद्ध शब्दार्थ समर्थन**: व्यापक RDFS/OWL प्रॉपर्टी सहित लेबल, बहु-भाषा समर्थन और औपचारिक बाधाओं को सक्षम करें। +- **बहु-ऑन्टोलॉजी समर्थन**: कई ऑन्टोलॉजी को एक साथ मौजूद रहने और इंटरऑपरेट करने की अनुमति दें। +- **सत्यापन और तर्क**: सुनिश्चित करें कि ऑन्टोलॉजी OWL-जैसी मानकों के अनुरूप हैं, जिसमें स्थिरता जांच और अनुमान समर्थन शामिल है। +- **मानक अनुकूलता**: मानक प्रारूपों (टर्टल, RDF/XML, OWL/XML) में आयात/निर्यात का समर्थन करें, जबकि आंतरिक अनुकूलन बनाए रखें। + +## पृष्ठभूमि + +ट्रस्टग्राफ ऑन्टोलॉजी को एक लचीली कुंजी-मान्य सिस्टम में कॉन्फ़िगरेशन आइटम के रूप में संग्रहीत करता है। जबकि प्रारूप OWL (वेब ऑन्टोलॉजी लैंग्वेज) से प्रेरित है, यह ट्रस्टग्राफ के विशिष्ट उपयोग के मामलों के लिए अनुकूलित है और सभी OWL विनिर्देशों का सख्ती से पालन नहीं करता है। + +ट्रस्टग्राफ में ऑन्टोलॉजी निम्नलिखित को सक्षम करते हैं: +- औपचारिक ऑब्जेक्ट प्रकारों और उनके गुणों की परिभाषा +- प्रॉपर्टी डोमेन, रेंज और टाइप बाधाओं का विनिर्देश +- तार्किक तर्क और अनुमान +- जटिल संबंध और कार्डिनैलिटी बाधाएं +- अंतर्राष्ट्रीयकरण के लिए बहु-भाषा समर्थन + +## ऑन्टोलॉजी संरचना + +### कॉन्फ़िगरेशन भंडारण + +ऑन्टोलॉजी को निम्नलिखित पैटर्न के साथ कॉन्फ़िगरेशन आइटम के रूप में संग्रहीत किया जाता है: +- **टाइप**: `ऑन्टोलॉजी` +- **कुंजी**: अद्वितीय ऑन्टोलॉजी पहचानकर्ता (जैसे, `प्राकृतिक-दुनिया`, `डोमेन-मॉडल`) +- **मान**: JSON प्रारूप में पूरी ऑन्टोलॉजी + +### JSON संरचना + +ऑन्टोलॉजी JSON प्रारूप में चार मुख्य अनुभाग होते हैं: + +#### 1. मेटाडेटा + +ऑन्टोलॉजी के बारे में प्रशासनिक और वर्णनात्मक जानकारी शामिल है: + +```json +{ + "metadata": { + "नाम": "प्राकृतिक दुनिया", + "विवरण": "प्राकृतिक क्रम को कवर करने वाली ऑन्टोलॉजी", + "संस्करण": "1.0.0", + "बनाया गया": "2025-09-20T12:07:37.068Z", + "संशोधित": "2025-09-20T12:12:20.725Z", + "निर्माता": "वर्तमान-उपयोगकर्ता", + "नेमस्पेस": "http://trustgraph.ai/ontologies/natural-world", + "आयात": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**फ़ील्ड:** +- `नाम`: ऑन्टोलॉजी का मानव-पठनीय नाम +- `विवरण`: ऑन्टोलॉजी के उद्देश्य का संक्षिप्त विवरण +- `संस्करण`: सिमेंटिक संस्करण संख्या +- `बनाया गया`: निर्माण का ISO 8601 टाइमस्टैम्प +- `संशोधित`: अंतिम संशोधन का ISO 8601 टाइमस्टैम्प +- `निर्माता`: निर्माता उपयोगकर्ता/सिस्टम की पहचान +- `नेमस्पेस`: ऑन्टोलॉजी तत्वों के लिए आधार URI +- `आयात`: आयातित ऑन्टोलॉजी URI का सरणी + +#### 2. क्लास + +ऑब्जेक्ट प्रकार और उनके पदानुक्रमित संबंधों को परिभाषित करता है: + +```json +{ + "क्लास": { + "जानवर": { + "URI": "http://trustgraph.ai/ontologies/natural-world#animal", + "टाइप": "owl:Class", + "rdfs:लेबल": [{"मान": "जानवर", "भाषा": "en"}], + "rdfs:टिप्पणी": "एक जानवर", + "rdfs:उपवर्ग": "जीवनरूप", + "owl:समतुल्यक्लास": ["प्राणी"], + "owl:भिन्न": ["पौधा"], + "dcterms:पहचानकर्ता": "ANI-001" + } + } +} +``` + +**समर्थित प्रॉपर्टी:** +- `URI`: क्लास का पूरा URI +- `टाइप`: `owl:Class` +- `rdfs:लेबल`: क्लास का लेबल +- `rdfs:टिप्पणी`: क्लास का विवरण +- `rdfs:उपवर्ग`: पैरेंट क्लास +- `owl:समतुल्यक्लास`: समान क्लास +- `owl:भिन्न`: अलग क्लास +- `dcterms:पहचानकर्ता`: क्लास का पहचानकर्ता + +#### 3. ऑब्जेक्ट प्रॉपर्टी + +ऑब्जेक्ट और उनके गुणों के बीच संबंधों को परिभाषित करता है: + +```json +{ + "ऑब्जेक्टप्रॉपर्टी": { + "hasPart": { + "URI": "http://trustgraph.ai/ontologies/natural-world#hasPart", + "टाइप": "owl:ObjectProperty", + "rdfs:लेबल": [{"मान": "hasPart", "भाषा": "en"}], + "rdfs:टिप्पणी": "यह दर्शाता है कि एक ऑब्जेक्ट का एक भाग है" + } + } +} +``` + +**समर्थित प्रॉपर्टी:** +- `URI`: प्रॉपर्टी का पूरा URI +- `टाइप`: `owl:ObjectProperty` या `owl:DatatypeProperty` +- `rdfs:लेबल`: प्रॉपर्टी का लेबल +- `rdfs:टिप्पणी`: प्रॉपर्टी का विवरण + +#### 4. डेटाटाइप प्रॉपर्टी + +ऑब्जेक्ट के डेटा मानों को परिभाषित करता है: + +```json +{ + "डेटाटाइप्रॉपर्टी": { + "नंबरऑफलेग्स": { + "URI": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "टाइप": "owl:DatatypeProperty", + "rdfs:लेबल": [{"मान": "नंबर-ऑफ-लेग्स", "भाषा": "en"}], + "rdfs:टिप्पणी": "जानवर की पैर की संख्या", + "rdfs:डोमेन": "जानवर" + } + } +} +``` + +**समर्थित प्रॉपर्टी:** +- `URI`: प्रॉपर्टी का पूरा URI +- `टाइप`: `owl:DatatypeProperty` +- `rdfs:लेबल`: प्रॉपर्टी का लेबल +- `rdfs:टिप्पणी`: प्रॉपर्टी का विवरण +- `rdfs:डोमेन`: प्रॉपर्टी का डोमेन + +## सत्यापन नियम + +### संरचनात्मक सत्यापन + +1. **URI संगति**: सभी URI `{नेमस्पेस}#{पहचानकर्ता}` पैटर्न का पालन करना चाहिए। +2. **क्लास पदानुक्रम**: `rdfs:उपवर्ग` में कोई गोलाकार वंश नहीं होना चाहिए। +3. **प्रॉपर्टी डोमेन/रेंज**: मौजूदा क्लास या मान्य XSD प्रकारों को संदर्भित करना चाहिए। +4. **भिन्न वर्ग**: एक दूसरे के उपवर्ग नहीं हो सकते। +5. **उलटा प्रॉपर्टी**: यदि निर्दिष्ट है, तो द्विदिश होना चाहिए। + +### शब्दार्थ सत्यापन + +1. **अद्वितीय पहचानकर्ता**: क्लास और प्रॉपर्टी पहचानकर्ता ऑन्टोलॉजी के भीतर अद्वितीय होने चाहिए। +2. **भाषा टैग**: BCP 47 भाषा टैग प्रारूप का पालन करना चाहिए। +3. **कार्डिनैलिटी बाधाएं**: जब दोनों निर्दिष्ट हों, तो `minCardinality` ≤ `maxCardinality` होना चाहिए। +4. **कार्यात्मक प्रॉपर्टी**: `maxCardinality` > 1 नहीं हो सकता। + +## आयात/निर्यात प्रारूप समर्थन + +जबकि आंतरिक प्रारूप JSON है, सिस्टम मानक ऑन्टोलॉजी प्रारूपों में रूपांतरण का समर्थन करता है: + +- **टर्टल (.ttl)** - कॉम्पैक्ट RDF क्रमबद्धता +- **RDF/XML (.rdf, .owl)** - W3C मानक प्रारूप +- **OWL/XML (.owx)** - OWL-विशिष्ट XML प्रारूप +- **JSON-LD (.jsonld)** - लिंक्ड डेटा के लिए JSON + +## संदर्भ + +- [OWL 2 वेब ऑन्टोलॉजी भाषा](https://www.w3.org/TR/owl2-overview/) +- [RDF स्कीमा 1.1](https://www.w3.org/TR/rdf-schema/) +- [XML स्कीमा डेटाटाइप](https://www.w3.org/TR/xmlschema-2/) +- [BCP 47 भाषा टैग](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.md b/docs/tech-specs/ontology.md index 61cc09e4..3dfa62b6 100644 --- a/docs/tech-specs/ontology.md +++ b/docs/tech-specs/ontology.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Ontology Structure Technical Specification" +parent: "Tech Specs" +--- + # Ontology Structure Technical Specification ## Overview @@ -283,4 +289,4 @@ While the internal format is JSON, the system supports conversion to/from standa - [OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) - [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) - [XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) -- [BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) \ No newline at end of file +- [BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.pt.md b/docs/tech-specs/ontology.pt.md new file mode 100644 index 00000000..cc377b33 --- /dev/null +++ b/docs/tech-specs/ontology.pt.md @@ -0,0 +1,294 @@ +--- +layout: default +title: "Especificação Técnica da Estrutura da Ontologia" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica da Estrutura da Ontologia + +> **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 a estrutura e o formato das ontologias dentro do sistema TrustGraph. As ontologias fornecem modelos de conhecimento formais que definem classes, propriedades e relacionamentos, suportando capacidades de raciocínio e inferência. O sistema usa um formato de configuração inspirado em OWL que representa amplamente os conceitos OWL/RDFS, ao mesmo tempo que é otimizado para os requisitos do TrustGraph. + +**Convenção de Nomenclatura**: Este projeto usa kebab-case para todos os identificadores (chaves de configuração, pontos finais de API, nomes de módulos, etc.) em vez de snake_case. + +## Objetivos + +**Gerenciamento de Classes e Propriedades**: Definir classes semelhantes a OWL com propriedades, domínios, intervalos e restrições de tipo. +**Suporte Semântico Rico**: Habilitar propriedades abrangentes RDFS/OWL, incluindo rótulos, suporte multilíngue e restrições formais. +**Suporte a Múltiplas Ontologias**: Permitir que várias ontologias coexistam e interoperem. +**Validação e Raciocínio**: Garantir que as ontologias estejam em conformidade com padrões semelhantes a OWL, com verificação de consistência e suporte de inferência. +**Compatibilidade com Padrões**: Suportar importação/exportação em formatos padrão (Turtle, RDF/XML, OWL/XML) mantendo a otimização interna. + +## Contexto + +O TrustGraph armazena ontologias como itens de configuração em um sistema flexível de chave-valor. Embora o formato seja inspirado em OWL (Web Ontology Language), ele é otimizado para casos de uso específicos do TrustGraph e não adere estritamente a todas as especificações do OWL. + +As ontologias no TrustGraph permitem: +Definição de tipos de objetos formais e suas propriedades. +Especificação de domínios, intervalos e restrições de tipo de propriedade. +Raciocínio e inferência lógica. +Relacionamentos complexos e restrições de cardinalidade. +Suporte multilíngue para internacionalização. + +## Estrutura da Ontologia + +### Armazenamento de Configuração + +As ontologias são armazenadas como itens de configuração com o seguinte padrão: +**Tipo**: `ontology` +**Chave**: Identificador de ontologia exclusivo (por exemplo, `natural-world`, `domain-model`) +**Valor**: Ontologia completa em formato JSON. + +### Estrutura JSON + +O formato JSON da ontologia consiste em quatro seções principais: + +#### 1. Metadados + +Contém informações administrativas e descritivas sobre a ontologia: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**Campos:** +`name`: Nome legível para humanos da ontologia +`description`: Breve descrição do propósito da ontologia +`version`: Número de versão semântico +`created`: Carimbo de data/hora ISO 8601 de criação +`modified`: Carimbo de data/hora ISO 8601 da última modificação +`creator`: Identificador do usuário/sistema que criou +`namespace`: URI base para elementos da ontologia +`imports`: Array de URIs de ontologias importadas + +#### 2. Classes + +Define os tipos de objeto e seus relacionamentos hierárquicos: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform", + "owl:equivalentClass": ["creature"], + "owl:disjointWith": ["plant"], + "dcterms:identifier": "ANI-001" + } + } +} +``` + +**Propriedades Suportadas:** +`uri`: URI completo da classe +`type`: Sempre `"owl:Class"` +`rdfs:label`: Array de rótulos com informações de idioma +`rdfs:comment`: Descrição da classe +`rdfs:subClassOf`: Identificador da classe pai (herança simples) +`owl:equivalentClass`: Array de identificadores de classes equivalentes +`owl:disjointWith`: Array de identificadores de classes disjuntas +`dcterms:identifier`: Identificador de referência externa opcional + +#### 3. Propriedades de Objeto + +Propriedades que conectam instâncias a outras instâncias: + +```json +{ + "objectProperties": { + "has-parent": { + "uri": "http://trustgraph.ai/ontologies/natural-world#has-parent", + "type": "owl:ObjectProperty", + "rdfs:label": [{"value": "has parent", "lang": "en"}], + "rdfs:comment": "Links an animal to its parent", + "rdfs:domain": "animal", + "rdfs:range": "animal", + "owl:inverseOf": "parent-of", + "owl:functionalProperty": false + } + } +} +``` + +**Propriedades Suportadas:** +`uri`: URI completo da propriedade +`type`: Sempre `"owl:ObjectProperty"` +`rdfs:label`: Array de rótulos com informações de idioma +`rdfs:comment`: Descrição da propriedade +`rdfs:domain`: Identificador da classe que possui esta propriedade +`rdfs:range`: Identificador da classe para valores de propriedade +`owl:inverseOf`: Identificador da propriedade inversa +`owl:functionalProperty`: Booleano indicando no máximo um valor +`owl:inverseFunctionalProperty`: Booleano para propriedades de identificação única + +#### 4. Propriedades de Tipo de Dado + +Propriedades que conectam instâncias a valores literais: + +```json +{ + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number of legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:domain": "animal", + "rdfs:range": "xsd:nonNegativeInteger", + "owl:functionalProperty": true, + "owl:minCardinality": 0, + "owl:maxCardinality": 1 + } + } +} +``` + +**Propriedades Suportadas:** +`uri`: URI completo da propriedade +`type`: Sempre `"owl:DatatypeProperty"` +`rdfs:label`: Array de rótulos com marcação de idioma +`rdfs:comment`: Descrição da propriedade +`rdfs:domain`: Identificador da classe que possui esta propriedade +`rdfs:range`: Tipo de dados XSD para os valores da propriedade +`owl:functionalProperty`: Booleano indicando no máximo um valor +`owl:minCardinality`: Número mínimo de valores (opcional) +`owl:maxCardinality`: Número máximo de valores (opcional) +`owl:cardinality`: Número exato de valores (opcional) + +### Tipos de Dados XSD Suportados + +Os seguintes tipos de dados XML Schema são suportados para intervalos de propriedades: + +`xsd:string` - Valores de texto +`xsd:integer` - Números inteiros +`xsd:nonNegativeInteger` - Inteiros não negativos +`xsd:float` - Números de ponto flutuante +`xsd:double` - Números de precisão dupla +`xsd:boolean` - Valores verdadeiro/falso +`xsd:dateTime` - Valores de data e hora +`xsd:date` - Valores de data +`xsd:anyURI` - Referências de URI + +### Suporte a Idiomas + +Rótulos e comentários suportam vários idiomas usando o formato de etiqueta de idioma W3C: + +```json +{ + "rdfs:label": [ + {"value": "Animal", "lang": "en"}, + {"value": "Tier", "lang": "de"}, + {"value": "Animal", "lang": "es"} + ] +} +``` + +## Exemplo de Ontologia + +Aqui está um exemplo completo de uma ontologia simples: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + }, + "classes": { + "lifeform": { + "uri": "http://trustgraph.ai/ontologies/natural-world#lifeform", + "type": "owl:Class", + "rdfs:label": [{"value": "Lifeform", "lang": "en"}], + "rdfs:comment": "A living thing" + }, + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "Cat", "lang": "en"}], + "rdfs:comment": "A cat", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "Dog", "lang": "en"}], + "rdfs:comment": "A dog", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + }, + "objectProperties": {}, + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +## Regras de Validação + +### Validação Estrutural + +1. **Consistência de URIs**: Todos os URIs devem seguir o padrão `{namespace}#{identifier}` +2. **Hierarquia de Classes**: Não pode haver herança circular em `rdfs:subClassOf` +3. **Domínios/Intervalos de Propriedades**: Deve referenciar classes existentes ou tipos XSD válidos +4. **Classes Disjuntas**: Não podem ser subclasses umas das outras +5. **Propriedades Inversas**: Devem ser bidirecionais se especificadas + +### Validação Semântica + +1. **Identificadores Únicos**: Os identificadores de classe e propriedade devem ser únicos dentro de uma ontologia +2. **Etiquetas de Idioma**: Devem seguir o formato de etiqueta de idioma BCP 47 +3. **Restrições de Cardinalidade**: `minCardinality` ≤ `maxCardinality` quando ambos são especificados +4. **Propriedades Funcionais**: Não podem ter `maxCardinality` > 1 + +## Suporte a Formatos de Importação/Exportação + +Embora o formato interno seja JSON, o sistema suporta a conversão para/de formatos de ontologia padrão: + +**Turtle (.ttl)** - Serialização RDF compacta +**RDF/XML (.rdf, .owl)** - Formato padrão W3C +**OWL/XML (.owx)** - Formato XML específico para OWL +**JSON-LD (.jsonld)** - JSON para Dados Vinculados + +## Referências + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) +[XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) +[BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.ru.md b/docs/tech-specs/ontology.ru.md new file mode 100644 index 00000000..75c64e93 --- /dev/null +++ b/docs/tech-specs/ontology.ru.md @@ -0,0 +1,160 @@ +--- +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. Онтологии предоставляют формальные модели знаний, определяя классы, свойства и отношения, обеспечивая возможности для рассуждения и вывода. Система использует формат конфигурации, вдохновленный OWL, который широко представляет концепции OWL/RDFS, оптимизированный для требований TrustGraph. + +**Конвенция именования**: Для всех идентификаторов (ключей конфигурации, конечных точек API, названий модулей и т.д.) используется формат kebab-case, а не snake_case. + +## Цели + +- **Управление классами и свойствами**: Определение классов, похожих на OWL, с свойствами, доменами, диапазонами и ограничениями типов. +- **Поддержка богатых семантических возможностей**: Обеспечение полных возможностей RDFS/OWL, включая метки, поддержку нескольких языков и формальные ограничения. +- **Поддержка нескольких онтологий**: Разрешение одновременного существования и взаимодействия нескольких онтологий. +- **Валидация и рассуждение**: Обеспечение соответствия онтологий стандартам, похожим на OWL, с проверкой согласованности и поддержкой вывода. +- **Совместимость со стандартами**: Поддержка импорта/экспорта в стандартных форматах (Turtle, RDF/XML, OWL/XML), сохраняя оптимизацию. + +## Предыстория + +TrustGraph хранит онтологии как элементы конфигурации в гибкой системе ключ-значение. Хотя формат вдохновлен OWL (Web Ontology Language), он оптимизирован для конкретных случаев использования TrustGraph и не строго соответствует всем спецификациям OWL. + +Онтологии в TrustGraph обеспечивают: +- Определение формальных типов объектов и их свойств. +- Спецификацию доменов, диапазонов и ограничений типов свойств. +- Логическое рассуждение и вывод. +- Сложные отношения и ограничения кардинальности. +- Поддержку нескольких языков для международного использования. + +## Структура Онтологии + +### Хранение конфигурации + +Онтологии хранятся как элементы конфигурации с следующим шаблоном: +- **Тип**: `ontology` +- **Ключ**: Уникальный идентификатор онтологии (например, `natural-world`, `domain-model`) +- **Значение**: Полная онтология в формате JSON + +### JSON структура + +Формат JSON для онтологии состоит из четырех основных разделов: + +#### 1. Метаданные + +Содержит административную и описательную информацию об онтологии: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**Поля:** +- `name`: Человекочитаемое имя онтологии +- `description`: Краткое описание цели онтологии +- `version`: Семантическая версия +- `created`: Дата создания в формате ISO 8601 +- `modified`: Дата последнего изменения в формате ISO 8601 +- `creator`: Идентификатор пользователя/системы, создавшей онтологию +- `namespace`: Базовый URI для элементов онтологии +- `imports`: Массив URI импортируемых онтологий + +#### 2. Классы + +Определяет типы объектов и их иерархические отношения: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform", + "owl:equivalentClass": ["creature"], + "owl:disjointWith": ["plant"], + "dcterms:identifier": "ANI-001" + } + } +} +``` + +**Поддерживаемые свойства:** +- `uri`: Полный URI класса +- `type`: Всегда `"owl:Class"` +- `rdfs:label`: Массив меток с указанием языка +- `rdfs:comment`: Описание класса +- `rdfs:subClassOf`: Идентификатор родительского класса (наследование) +- `owl:equivalentClass`: Массив идентификаторов эквивалентных классов +- `owl:disjointWith`: Массив идентификаторов классов, отличных друг от друга +- `dcterms:identifier`: Опциональный внешний идентификатор + +#### 3. Объектные свойства + +Свойства, связывающие экземпляры между собой: + +```json +{ + "objectProperties": {} +} +``` + +#### 4. Свойства данных + +```json +{ + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +## Правила валидации + +### Структурная валидация + +1. **Уникальность URI**: Все URI должны соответствовать формату `{namespace}#{identifier}` +2. **Иерархия классов**: Не должно быть циклической иерархии в `rdfs:subClassOf` +3. **Области/Диапазоны свойств**: Должны ссылаться на существующие классы или допустимые типы XSD +4. **Отличные классы**: Не могут быть подклассами друг друга +5. **Обратные свойства**: Должны быть двусторонними, если указаны + +### Семантическая валидация + +1. **Уникальные идентификаторы**: Идентификаторы классов и свойств должны быть уникальными в онтологии +2. **Языковые теги**: Должны соответствовать формату BCP 47 +3. **Ограничения кардинальности**: `minCardinality` ≤ `maxCardinality` при указании обоих +4. **Функциональные свойства**: Не должны иметь `maxCardinality` > 1 + +## Поддержка импорта/экспорта + +Хотя внутренний формат - JSON, система поддерживает преобразование в/из стандартных форматов онтологий: + +- **Turtle (.ttl)** - компактная RDF-сериализация +- **RDF/XML (.rdf, .owl)** - стандартный формат W3C +- **OWL/XML (.owx)** - XML-формат OWL +- **JSON-LD (.jsonld)** - JSON для Linked Data diff --git a/docs/tech-specs/ontology.sw.md b/docs/tech-specs/ontology.sw.md new file mode 100644 index 00000000..5f08bb23 --- /dev/null +++ b/docs/tech-specs/ontology.sw.md @@ -0,0 +1,155 @@ +--- +layout: default +title: "Mbinu ya Muundo wa Ontolojia" +parent: "Swahili (Beta)" +--- + +# Mbinu ya Muundo wa Ontolojia + +> **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. + +## Maelezo + +Mazingira haya yanatoa maelezo kuhusu muundo na umbizo wa ontolojia ndani ya mfumo wa TrustGraph. Ontolojia hutoa modeli rasmi za maarifa ambayo inafafanua madarasa, sifa, na uhusiano, na inasaidia uwezo wa utafsiri na utabiri. Mfumo hutumia umbizo unaolingana na OWL (Web Ontology Language) ambao unafafanua dhana za OWL/RDFS, lakini umeboreshwa kwa mahitaji maalum ya TrustGraph. + +**Mikataba ya Majina**: Mradi huu hutumia "kebab-case" kwa kitambulisho chote (funguo za usanidi, sehemu za API, majina ya moduli, n.k.) badala ya "snake_case". + +## Lengo + +- **Usimamizi wa Darasa na Sifa**: Tafsiri madarasa kama vile ya OWL na sifa, vikoa, masafa, na vikwazo vya aina. +- **Usaidizi Kamili wa Semantikia**: Uwezo wa kutumia sifa za RDFS/OWL ikiwa ni pamoja na lebo, usaidizi wa lugha nyingi, na vikwazo rasmi. +- **Usaidizi wa Ontolojia nyingi**: Kuruhusu ontolojia nyingi kuwepo na kufanya kazi pamoja. +- **Uthibitisho na Utabiri**: Hakikisha kuwa ontolojia zinafuata viwango vya aina ya OWL, na hutoa ufuatiliaji wa uthabiti na usaidizi wa utabiri. +- **Ulinganisho na Viwango**: Kusaidia uingizaji na urekebishaji katika umbizo wa kawaida (Turtle, RDF/XML, OWL/XML) wakati unahifadhi uboreshaji wa ndani. + +## Misingi + +TrustGraph huhifadhi ontolojia kama vitu vya usanidi katika mfumo wa thamani-funguo ambao una uwezo wa kubadilika. Ingawa umbizo huu unatokana na OWL (Web Ontology Language), umeboreshwa kwa matumio maalum ya TrustGraph na haufuate vipengele vyote vya OWL. + +Ontolojia katika TrustGraph zinaruhusu: +- Ufafanuzi wa aina rasmi za vitu na sifa zake. +- Ufafanuzi wa vikoa na masafa ya sifa, pamoja na vikwazo vya aina. +- Utabiri na utafsiri wa mantiki. +- Uhusiano tata na vikwazo vya wingi. +- Usaidizi wa lugha nyingi kwa utoaji wa lugha. + +## Muundo wa Ontolojia + +### Uhifadhi wa Usanidi + +Ontolojia huhifadhiwa kama vitu vya usanidi na muundo ufuatao: +- **Aina**: `ontology` +- **Funguo**: Kitambulisho cha kipekee cha ontolojia (k.m., `natural-world`, `domain-model`) +- **Thamani**: Ontolojia kamili katika umbizo la JSON. + +### Muundo wa JSON + +Muundo wa JSON wa ontolojia una sehemu nne kuu: + +#### 1. MetaData + +Inayo habari ya utawala na maelezo kuhusu ontolojia: + +```json +{ + "metadata": { + "name": "Ulimwengu wa asili", + "description": "Ontolojia inayofafanua mazingira ya asili", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "mtumiaji-sasa", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**Vifaa:** +- `name`: Jina linaloweza kusomwa na binadamu la ontolojia. +- `description`: Maelezo mafupi ya lengo la ontolojia. +- `version`: Nambari ya toleo. +- `created`: Alama ya muda wa ISO 8601 ya uundaji. +- `modified`: Alama ya muda wa ISO 8601 ya mabadiliko ya mwisho. +- `creator`: Kitambulisho cha mtumiaji/mfumo aliyeuunda. +- `namespace`: URI ya msingi kwa vipengele vya ontolojia. +- `imports`: Orodha ya URI za ontolojia zilizounganishwa. + +#### 2. Madarasa + +Inafafanua aina za vitu na uhusiano wao wa kimfumo: + +```json +{ + "classes": { + "lifeform": { + "uri": "http://trustgraph.ai/ontologies/natural-world#lifeform", + "type": "owl:Class", + "rdfs:label": [{"value": "Lifeform", "lang": "en"}], + "rdfs:comment": "Kiumbe hai" + }, + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "Kiumbe cha wanyama", + "rdfs:subClassOf": "lifeform" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "Cat", "lang": "en"}], + "rdfs:comment": "Paka", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "Dog", "lang": "en"}], + "rdfs:comment": "Mbwa", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + }, +``` + +#### 3. Sifa + +(Tangu hakuna sifa katika mfano, sehemu hii imetolewa) + +#### 4. Ufafanuzi wa Sifa za Data + +(Tangu hakunafafanushwi, sehemu hii imetolewa) + +## Kanuni za Uthibitisho + +### Uthibitisho wa Muundo + +1. **Ulinganifu wa URI**: URI zote zinapaswa kufuata muundo `{namespace}#{identifier}`. +2. **Hieroni ya Darasa**: Hakuna urithi wa mzunguko katika `rdfs:subClassOf`. +3. **Vikoa/Masafa ya Sifa**: Lazima irejee madarasa yaliyopo au aina halali za XSD. +4. **Darasa zisizolingana**: Haiwezi kuwa ndogo za kila mmoja. +5. **Sifa za Kinyume**: Lazima iwe bidirectional ikiwa imeelezwa. + +### Uthibitisho wa Semantikia + +1. **Kitambulisho cha kipekee**: Kitambulisho cha darasa na sifa lazima kiwe kipekee ndani ya ontolojia. +2. **Lebo za Lugha**: Lazima ifuate muundo wa lebo wa BCP 47. +3. **Vikwazo vya Kiasi**: `minCardinality` ≤ `maxCardinality` wakati zote zimetajwa. +4. **Sifa za Kifaa**: Haiwezi kuwa na `maxCardinality` > 1. + +## Usaidizi wa Umbizo wa Uingizaji/Urekebishaji + +Ingawa umbizo la ndani ni JSON, mfumo unaweza kubadilisha hadi/kutoka kwa umbizo wa kawaida wa ontolojia: + +- **Turtle (.ttl)** - Urekebishaji kompakt wa RDF. +- **RDF/XML (.rdf, .owl)** - Umbizo la kawaida la W3C. +- **OWL/XML (.owx)** - Umbizo la XML maalum kwa OWL. +- **JSON-LD (.jsonld)** - JSON kwa Data iliyounganishwa. + +## Marejeleo + +- [OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +- [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) +- [XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) +- [BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.tr.md b/docs/tech-specs/ontology.tr.md new file mode 100644 index 00000000..72672fe6 --- /dev/null +++ b/docs/tech-specs/ontology.tr.md @@ -0,0 +1,294 @@ +--- +layout: default +title: "Ontoloji Yapısı Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Ontoloji Yapısı 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 sistemindeki ontolojilerin yapısını ve biçimini tanımlar. Ontolojiler, sınıfları, özellikleri ve ilişkileri tanımlayan resmi bilgi modelleri sağlar ve akıl yürütme ve çıkarım yeteneklerini destekler. Sistem, OWL'den ilham alan bir yapılandırma biçimi kullanır ve bu, OWL/RDFS kavramlarını geniş ölçüde temsil ederken aynı zamanda TrustGraph'ın gereksinimleri için optimize edilmiştir. + +**İsimlendirme Kuralları**: Bu proje, yılan_biçimi yerine tüm tanımlayıcılar (yapılandırma anahtarları, API uç noktaları, modül adları vb.) için kebab-case kullanır. + +## Hedefler + +**Sınıf ve Özellik Yönetimi**: OWL benzeri sınıfları, özellikleri, etki alanlarını, aralıkları ve tür kısıtlamalarını tanımlayın. +**Zengin Anlamsal Destek**: Etiketler, çoklu dil desteği ve resmi kısıtlamalar dahil olmak üzere kapsamlı RDFS/OWL özellikleri sağlayın. +**Çoklu Ontoloji Desteği**: Birden fazla ontolojinin birlikte var olmasına ve etkileşimde olmasına izin verin. +**Doğrulama ve Akıl Yürütme**: Ontolojilerin, tutarlılık kontrolü ve çıkarım desteği ile OWL benzeri standartlara uygun olduğundan emin olun. +**Standart Uyumluluğu**: İç optimizasyonu korurken standart formatlarda (Turtle, RDF/XML, OWL/XML) içe/dışa aktarma desteğini sağlayın. + +## Arka Plan + +TrustGraph, ontolojileri esnek bir anahtar-değer sisteminde yapılandırma öğeleri olarak saklar. Biçim OWL (Web Ontology Language) tarafından ilham alınmış olsa da, TrustGraph'ın belirli kullanım durumları için optimize edilmiştir ve tüm OWL özelliklerine kesin olarak uymamaktadır. + +TrustGraph'taki ontolojiler şunları sağlar: +Resmi nesne türlerinin ve özelliklerinin tanımlanması +Özellik etki alanlarının, aralıklarının ve tür kısıtlamalarının belirtilmesi +Mantıksal akıl yürütme ve çıkarım +Karmaşık ilişkiler ve kardinalite kısıtlamaları +Uluslararasılaştırma için çoklu dil desteği + +## Ontoloji Yapısı + +### Yapılandırma Depolama + +Ontolojiler, aşağıdaki kalıba sahip yapılandırma öğeleri olarak saklanır: +**Tür**: `ontology` +**Anahtar**: Benzersiz ontoloji tanımlayıcısı (örneğin, `natural-world`, `domain-model`) +**Değer**: JSON formatında eksiksiz ontoloji + +### JSON Yapısı + +Ontoloji JSON biçimi, dört ana bölümden oluşur: + +#### 1. Meta Veriler + +Ontoloji hakkında idari ve tanımlayıcı bilgiler içerir: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**Alanlar:** +`name`: Ontolojinin insan tarafından okunabilir adı +`description`: Ontolojinin amacının kısa açıklaması +`version`: Semantik sürüm numarası +`created`: Oluşturulma zamanının ISO 8601 zaman damgası +`modified`: Son değişiklik zamanının ISO 8601 zaman damgası +`creator`: Ontolojiyi oluşturan kullanıcı/sistemin kimliği +`namespace`: Ontoloji öğeleri için temel URI +`imports`: İçe aktarılan ontoloji URI'lerinin dizisi + +#### 2. Sınıflar + +Nesne türlerini ve hiyerarşik ilişkilerini tanımlar: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform", + "owl:equivalentClass": ["creature"], + "owl:disjointWith": ["plant"], + "dcterms:identifier": "ANI-001" + } + } +} +``` + +**Desteklenen Özellikler:** +`uri`: Sınıfın tam URI'si +`type`: Her zaman `"owl:Class"` +`rdfs:label`: Dil etiketli etiketlerin dizisi +`rdfs:comment`: Sınıfın açıklaması +`rdfs:subClassOf`: Üst sınıf tanımlayıcısı (tekli miras) +`owl:equivalentClass`: Eşdeğer sınıf tanımlayıcılarının dizisi +`owl:disjointWith`: Ayrık sınıf tanımlayıcılarının dizisi +`dcterms:identifier`: İsteğe bağlı harici referans tanımlayıcısı + +#### 3. Nesne Özellikleri + +Örnekleri diğer örneklere bağlayan özellikler: + +```json +{ + "objectProperties": { + "has-parent": { + "uri": "http://trustgraph.ai/ontologies/natural-world#has-parent", + "type": "owl:ObjectProperty", + "rdfs:label": [{"value": "has parent", "lang": "en"}], + "rdfs:comment": "Links an animal to its parent", + "rdfs:domain": "animal", + "rdfs:range": "animal", + "owl:inverseOf": "parent-of", + "owl:functionalProperty": false + } + } +} +``` + +**Desteklenen Özellikler:** +`uri`: Özelliğin tam URI'si +`type`: Her zaman `"owl:ObjectProperty"` +`rdfs:label`: Dil etiketli etiketlerin dizisi +`rdfs:comment`: Özelliğin açıklaması +`rdfs:domain`: Bu özelliğe sahip sınıf tanımlayıcısı +`rdfs:range`: Özellik değerleri için sınıf tanımlayıcısı +`owl:inverseOf`: Ters özelliğin tanımlayıcısı +`owl:functionalProperty`: En fazla bir değer olduğunu gösteren boolean değeri +`owl:inverseFunctionalProperty`: Benzersiz tanımlayıcı özellikleri için boolean değeri + +#### 4. Veri Tipi Özellikleri + +Örnekleri, literal değerlere bağlayan özellikler: + +```json +{ + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number of legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:domain": "animal", + "rdfs:range": "xsd:nonNegativeInteger", + "owl:functionalProperty": true, + "owl:minCardinality": 0, + "owl:maxCardinality": 1 + } + } +} +``` + +**Desteklenen Özellikler:** +`uri`: Özelliğin tam URI'si +`type`: Her zaman `"owl:DatatypeProperty"` +`rdfs:label`: Dil etiketli etiketlerin dizisi +`rdfs:comment`: Özelliğin açıklaması +`rdfs:domain`: Bu özelliğe sahip sınıf tanımlayıcısı +`rdfs:range`: Özellik değerleri için XSD veri türü +`owl:functionalProperty`: En fazla bir değer olduğunu gösteren boolean değeri +`owl:minCardinality`: Minimum değer sayısı (isteğe bağlı) +`owl:maxCardinality`: Maksimum değer sayısı (isteğe bağlı) +`owl:cardinality`: Tam değer sayısı (isteğe bağlı) + +### Desteklenen XSD Veri Türleri + +Aşağıdaki XML Şema veri türleri, veri türü özellik aralıkları için desteklenmektedir: + +`xsd:string` - Metin değerleri +`xsd:integer` - Tamsayılar +`xsd:nonNegativeInteger` - Negatif olmayan tamsayılar +`xsd:float` - Ondalık sayılar +`xsd:double` - Çift hassasiyetli sayılar +`xsd:boolean` - Doğru/yanlış değerleri +`xsd:dateTime` - Tarih ve saat değerleri +`xsd:date` - Tarih değerleri +`xsd:anyURI` - URI referansları + +### Dil Desteği + +Etiketler ve yorumlar, W3C dil etiketi biçimini kullanarak çoklu dilleri destekler: + +```json +{ + "rdfs:label": [ + {"value": "Animal", "lang": "en"}, + {"value": "Tier", "lang": "de"}, + {"value": "Animal", "lang": "es"} + ] +} +``` + +## Örnek Ontoloji + +İşte basit bir ontolojinin eksiksiz bir örneği: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + }, + "classes": { + "lifeform": { + "uri": "http://trustgraph.ai/ontologies/natural-world#lifeform", + "type": "owl:Class", + "rdfs:label": [{"value": "Lifeform", "lang": "en"}], + "rdfs:comment": "A living thing" + }, + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "Cat", "lang": "en"}], + "rdfs:comment": "A cat", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "Dog", "lang": "en"}], + "rdfs:comment": "A dog", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + }, + "objectProperties": {}, + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +## Doğrulama Kuralları + +### Yapısal Doğrulama + +1. **URI Tutarlılığı**: Tüm URI'ler `{namespace}#{identifier}` kalıbını takip etmelidir. +2. **Sınıf Hiyerarşisi**: `rdfs:subClassOf` içinde döngüsel miras ilişkisi olmamalıdır. +3. **Özellik Alanları/Aralıkları**: Mevcut sınıflara veya geçerli XSD türlerine başvurmalıdır. +4. **Ayrık Sınıflar**: Birbirinin alt sınıfı olamazlar. +5. **Ters Özellikler**: Belirtilmişse, çift yönlü olmalıdır. + +### Anlamsal Doğrulama + +1. **Benzersiz Tanımlayıcılar**: Sınıf ve özellik tanımlayıcıları, bir ontoloji içinde benzersiz olmalıdır. +2. **Dil Etiketleri**: BCP 47 dil etiketi formatını takip etmelidir. +3. **Kardinalite Kısıtlamaları**: Hem belirtilmişse, `minCardinality` ≤ `maxCardinality` olmalıdır. +4. **Fonksiyonel Özellikler**: `maxCardinality` > 1 olamaz. + +## İçe/Dışa Aktarma Formatı Desteği + +İç format JSON olmasına rağmen, sistem standart ontoloji formatlarına dönüştürmeyi destekler: + +**Turtle (.ttl)** - RDF'nin kompakt seri hale getirilmesi +**RDF/XML (.rdf, .owl)** - W3C standardı formatı +**OWL/XML (.owx)** - OWL'e özel XML formatı +**JSON-LD (.jsonld)** - Bağlı Veri için JSON + +## Referanslar + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) +[XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) +[BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontology.zh-cn.md b/docs/tech-specs/ontology.zh-cn.md new file mode 100644 index 00000000..5fde5e56 --- /dev/null +++ b/docs/tech-specs/ontology.zh-cn.md @@ -0,0 +1,241 @@ +--- +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 系统中本体的结构和格式。 本体提供正式的知识模型,定义类、属性、以及它们之间的关系,从而支持推理和推断功能。 该系统采用基于 OWL 的配置格式,广泛地表示 OWL/RDFS 概念,同时针对 TrustGraph 的特定需求进行了优化。 + +**命名约定**: 该项目使用 kebab-case 格式(例如,`natural-world`、`domain-model`、`configuration keys`、`API endpoints`、`module names` 等)来表示所有标识符,而不是 snake_case。 + +## 目标 + +- **类和属性管理**: 定义类似 OWL 的类,并包含属性、域、范围以及类型约束 +- **强大的语义支持**: 启用全面的 RDFS/OWL 属性,包括标签、多语言支持以及正式约束 +- **多本体支持**: 允许多个本体共存并相互协作 +- **验证和推理**: 确保本体符合 OWL 类似的标准,包括一致性检查和推理支持 +- **标准兼容性**: 支持以标准格式(Turtle、RDF/XML、OWL/XML)进行导入/导出,同时保持内部优化 + +## 背景 + +TrustGraph 将本体存储为配置项,采用灵活的键值系统。 尽管该格式受到 OWL (Web Ontology Language) 的启发,但它针对 TrustGraph 的特定用例进行了优化,并且并非完全符合所有 OWL 规范。 + +在 TrustGraph 中,本体能够实现以下功能: + +- 定义对象类型及其属性 +- 规范属性的域、范围和类型约束 +- 进行逻辑推理 +- 定义复杂的关系和数量约束 +- 支持多种语言,用于国际化 + +## 本体结构 + +### 配置存储 + +本体以配置项的形式存储,具有以下模式: + +- **类型**: `ontology` +- **键**: 唯一本体标识符(例如,`natural-world`、`domain-model`) +- **值**: 完整的本体,采用 JSON 格式 + +### JSON 结构 + +本体的 JSON 格式主要包含四个部分: + +#### 1. 元数据 + +包含本体的行政和描述性信息: + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + } +} +``` + +**字段**: +- `name`: 本体的人类可读名称 +- `description`: 本体目的的简要描述 +- `version`: 语义版本号 +- `created`: 创建时间 (ISO 8601 格式) +- `modified`: 最后修改时间 (ISO 8601 格式) +- `creator`: 创建用户的/系统的标识符 +- `namespace`: 本体元素的基 URI +- `imports`: 导入本体 URI 数组 + +#### 2. 类 + +定义对象类型及其层次关系: + +```json +{ + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal", + "rdfs:subClassOf": "lifeform", + "owl:equivalentClass": ["creature"], + "owl:disjointWith": ["plant"], + "dcterms:identifier": "ANI-001" + } + } +} +``` + +**支持的属性**: +- `uri`: 类的完整 URI +- `type`: 始终为 `"owl:Class"` +- `rdfs:label`: 语言标记的标签数组 +- `rdfs:comment`: 类的描述 +- `rdfs:subClassOf`: 上级类的标识符 (单继承) +- `owl:equivalentClass`: 等效类的标识符数组 +- `owl:disjointWith`: 互斥类的标识符数组 +- `dcterms:identifier`: 外部参考标识符 (可选) + +#### 3. 对象属性 + +用于链接实例的对象属性: + +```json +{ + "objectProperties": { + "has-parent": { + "uri": "http://trustgraph.ai/ontologies/natural-world#has-parent", + "type": "owl:ObjectProperty", + "rdfs:label": [{"value": "has parent", "lang": "en"}], + "rdfs:comment": "Links an animal to its parent", + "rdfs:domain": "animal", + "rdfs:range": "animal", + "owl:inverseOf": "parent-of", + "owl:functionalProperty": false + } + } +} +``` + +**支持的属性**: +- `uri`: 属性的完整 URI +- `type`: 始终为 `"owl:ObjectProperty"` +- `rdfs:label`: 语言标记的标签数组 +- `rdfs:comment`: 属性的描述 +- `rdfs:domain`: 域的标识符 +- `rdfs:range`: 范围的标识符 +- `owl:inverseOf`: 互反属性的标识符 +- `owl:functionalProperty`: 功能属性的标识符 (可选) + +#### 4. 数据类型属性 + +```json +{ + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +#### 5. 示例本体 + +```json +{ + "metadata": { + "name": "The natural world", + "description": "Ontology covering the natural order", + "version": "1.0.0", + "created": "2025-09-20T12:07:37.068Z", + "modified": "2025-09-20T12:12:20.725Z", + "creator": "current-user", + "namespace": "http://trustgraph.ai/ontologies/natural-world", + "imports": ["http://www.w3.org/2002/07/owl#"] + }, + "classes": { + "animal": { + "uri": "http://trustgraph.ai/ontologies/natural-world#animal", + "type": "owl:Class", + "rdfs:label": [{"value": "Animal", "lang": "en"}], + "rdfs:comment": "An animal" + }, + "cat": { + "uri": "http://trustgraph.ai/ontologies/natural-world#cat", + "type": "owl:Class", + "rdfs:label": [{"value": "Cat", "lang": "en"}], + "rdfs:comment": "A cat", + "rdfs:subClassOf": "animal" + }, + "dog": { + "uri": "http://trustgraph.ai/ontologies/natural-world#dog", + "type": "owl:Class", + "rdfs:label": [{"value": "Dog", "lang": "en"}], + "rdfs:comment": "A dog", + "rdfs:subClassOf": "animal", + "owl:disjointWith": ["cat"] + } + }, + "objectProperties": {}, + "datatypeProperties": { + "number-of-legs": { + "uri": "http://trustgraph.ai/ontologies/natural-world#number-of-legs", + "type": "owl:DatatypeProperty", + "rdfs:label": [{"value": "number-of-legs", "lang": "en"}], + "rdfs:comment": "Count of number of legs of the animal", + "rdfs:range": "xsd:nonNegativeInteger", + "rdfs:domain": "animal" + } + } +} +``` + +## 验证规则 + +### 结构验证 + +1. **URI 约束**: 所有 URI 必须遵循模式 `{namespace}#{identifier}` +2. **类层次**: 避免在 `rdfs:subClassOf` 中出现循环继承 +3. **属性域/范围**: 必须引用现有类或有效的 XSD 类型 +4. **互斥类**: 互斥类不能是互斥类的子类 +5. **互反属性**: 如果指定,必须是双向的 + +### 语义验证 + +1. **唯一标识符**: 类的标识符和属性标识符必须是唯一的 +2. **语言标签**: 必须符合 BCP 47 语言标签格式 +3. **数量约束**: `minCardinality` ≤ `maxCardinality`,当两者都指定时 +4. **功能属性**: 不能有 `maxCardinality` > 1 + +## 导入/导出格式支持 + +虽然内部格式为 JSON,但该系统支持与标准本体格式的转换: + +- **Turtle (.ttl)** - 紧凑的 RDF 序列化 +- **RDF/XML (.rdf, .owl)** - W3C 标准格式 +- **OWL/XML (.owx)** - OWL 特定 XML 格式 +- **JSON-LD (.jsonld)** - 用于链接数据的 JSON + +## 参考文献 + +- [OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +- [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) +- [XML Schema Datatypes](https://www.w3.org/TR/xmlschema-2/) +- [BCP 47 Language Tags](https://tools.ietf.org/html/bcp47) diff --git a/docs/tech-specs/ontorag.ar.md b/docs/tech-specs/ontorag.ar.md new file mode 100644 index 00000000..20165a81 --- /dev/null +++ b/docs/tech-specs/ontorag.ar.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "المواصفات الفنية لنظام OntoRAG: استخراج المعرفة القائم على علم الأنطولوجيا والاستعلام." +parent: "Arabic (Beta)" +--- + +# المواصفات الفنية لنظام OntoRAG: استخراج المعرفة القائم على علم الأنطولوجيا والاستعلام. + +> **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. + +## نظرة عامة + +OntoRAG هو نظام لاستخراج المعرفة والاستعلام القائم على علم الأنطولوجيا يفرض اتساقًا دلاليًا صارمًا أثناء كل من استخراج ثلاثيات المعرفة من النصوص غير المنظمة والاستعلام عن الرسم البياني المعرفي الناتج. على غرار GraphRAG ولكن مع قيود الأنطولوجيا الرسمية، يضمن OntoRAG أن جميع الثلاثيات المستخرجة تتوافق مع الهياكل الأنطولوجية المحددة مسبقًا ويوفر قدرات استعلام واعية دلاليًا. + +يستخدم النظام مطابقة التشابه المتجهي لتحديد مجموعات فرعية ذات صلة من الأنطولوجيا ديناميكيًا لكل من عمليات الاستخراج والاستعلام، مما يتيح معالجة مركزة ومناسبة للسياق مع الحفاظ على الصحة الدلالية. + +**اسم الخدمة**: `kg-extract-ontology` + +## الأهداف + +**استخراج متوافق مع الأنطولوجيا**: التأكد من أن جميع الثلاثيات المستخرجة تتوافق بشكل صارم مع الأنطولوجيات المحملة. +**تحديد السياق الديناميكي**: استخدام التضمينات لتحديد مجموعات فرعية ذات صلة من الأنطولوجيا لكل جزء. +**الاتساق الدلالي**: الحفاظ على التسلسلات الهرمية للفئات، ونطاقات/مدى الخصائص، والقيود. +**معالجة فعالة**: استخدام مخازن متجهات في الذاكرة لمطابقة سريعة لعناصر الأنطولوجيا. +**هيكلة قابلة للتوسع**: دعم أنطولوجيات متعددة متزامنة ذات مجالات مختلفة. + +## الخلفية + +تعمل خدمات استخراج المعرفة الحالية (`kg-extract-definitions`، `kg-extract-relationships`) بدون قيود رسمية، مما قد يؤدي إلى إنتاج ثلاثيات غير متسقة أو غير متوافقة. يعالج OntoRAG ذلك عن طريق: + +1. تحميل أنطولوجيات رسمية تحدد الفئات والخصائص الصالحة. +2. استخدام التضمينات لمطابقة محتوى النص مع عناصر الأنطولوجيا ذات الصلة. +3. تقييد الاستخراج لإنتاج ثلاثيات متوافقة مع الأنطولوجيا فقط. +4. توفير التحقق الدلالي للمعرفة المستخرجة. + +يجمع هذا النهج بين مرونة الاستخراج العصبي ودقة تمثيل المعرفة الرسمي. + +## التصميم الفني + +### البنية + +يتكون نظام OntoRAG من المكونات التالية: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### تفاصيل المكون + +#### 1. مُحمِّل الأونتولوجيا + +**الغرض**: يسترجع ويحلل تكوينات الأونتولوجيا من خدمة التكوين باستخدام تحديثات تعتمد على الأحداث. + +**التنفيذ**: +يستخدم مُحمِّل الأونتولوجيا قائمة انتظار ConfigPush الخاصة بـ TrustGraph لتلقي تحديثات تكوين الأونتولوجيا التي تعتمد على الأحداث. عندما تتم إضافة عنصر تكوين من نوع "أونتولوجيا" أو تعديله، يتلقى المُحمِّل التحديث عبر قائمة انتظار config-update ويحلل هيكل JSON الذي يحتوي على البيانات الوصفية والفئات وخصائص الكائنات وخصائص أنواع البيانات. يتم تخزين هذه الأونتولوجيات التي تم تحليلها في الذاكرة ككائنات منظمة يمكن الوصول إليها بكفاءة أثناء عملية الاستخراج. + +**العمليات الرئيسية**: +الاشتراك في قائمة انتظار config-update لتكوينات من نوع الأونتولوجيا +تحليل هياكل الأونتولوجيا بتنسيق JSON إلى كائنات OntologyClass و OntologyProperty +التحقق من صحة هيكل الأونتولوجيا واتساقه +تخزين الأونتولوجيات التي تم تحليلها مؤقتًا في الذاكرة للوصول السريع +التعامل مع المعالجة الخاصة بكل تدفق باستخدام مخازن متجهة خاصة بالتدفق + +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. مُضمِّن الأونتولوجيا + +**الغرض**: ينشئ تضمينات متجهة لجميع عناصر الأونتولوجيا لتمكين مطابقة التشابه الدلالي. + +**التنفيذ**: +يعالج مُضمِّن الأونتولوجيا كل عنصر في الأونتولوجيات التي تم تحميلها (الفئات وخصائص الكائنات وخصائص أنواع البيانات) وينشئ تضمينات متجهة باستخدام خدمة EmbeddingsClientSpec. لكل عنصر، يجمع بين معرف العنصر والتسميات والوصف (التعليق) لإنشاء تمثيل نصي. ثم يتم تحويل هذا النص إلى تضمين متجهي عالي الأبعاد يلتقط معناه الدلالي. يتم تخزين هذه التضمينات في مخزن متجهات FAISS في الذاكرة الخاص بكل تدفق مع بيانات وصفية حول نوع العنصر والأونتولوجيا المصدر والتعريف الكامل. يكتشف المُضمِّن تلقائيًا بُعد التضمين من الاستجابة الأولى للتضمين. + +**العمليات الرئيسية**: +إنشاء تمثيلات نصية من معرفات العناصر والتسميات والتعليقات +إنشاء تضمينات عبر EmbeddingsClientSpec (باستخدام asyncio.gather للمعالجة الدفعية) +تخزين التضمينات مع بيانات وصفية شاملة في مخزن متجهات FAISS +الفهرسة حسب الأونتولوجيا ونوع العنصر ومعرف العنصر للاسترجاع الفعال +الكشف التلقائي عن أبعاد التضمين لتهيئة مخزن المتجهات +التعامل مع نماذج التضمين الخاصة بكل تدفق مع مخازن متجهة مستقلة + +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. معالج النصوص (مقسم الجمل) + +**الغرض**: يقوم بتقسيم أجزاء النص إلى أجزاء دقيقة لتمكين مطابقة دقيقة للأونتولوجيا. + +**التنفيذ**: +يستخدم معالج النصوص NLTK لترميز الجملة ووسم أجزاء الكلام لتقسيم أجزاء النص الواردة إلى جمل. يتعامل مع توافق إصدارات NLTK عن طريق محاولة تنزيل `punkt_tab` و `averaged_perceptron_tagger_eng` مع الرجوع إلى الإصدارات الأقدم إذا لزم الأمر. يتم تقسيم كل جزء نصي إلى جمل فردية يمكن مطابقتها بشكل مستقل مع عناصر الأونتولوجيا. + +**العمليات الرئيسية**: +تقسيم النص إلى جمل باستخدام ترميز الجملة الخاص بـ NLTK +التعامل مع توافق إصدارات NLTK (punkt_tab مقابل punkt) +إنشاء كائنات TextSegment مع النص ومعلومات الموضع +دعم كل من الجمل الكاملة والأجزاء الفردية + +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. مُحدد الأونتولوجيا + +**الغرض**: يحدد المجموعة الفرعية الأكثر صلة من عناصر الأونتولوجيا للقطعة النصية الحالية. + +**التنفيذ**: +يقوم مُحدد الأونتولوجيا بإجراء مطابقة دلالية بين أجزاء النص وعناصر الأونتولوجيا باستخدام بحث تشابه متجهات FAISS. لكل جملة من قطعة النص، يقوم بإنشاء تضمين والبحث في مخزن المتجهات عن عناصر الأونتولوجيا الأكثر تشابهًا باستخدام تشابه جيب التمام مع حد عتبة قابل للتكوين (افتراضي 0.3). بعد جمع جميع العناصر ذات الصلة، يقوم بإجراء تحليل شامل للتبعيات: إذا تم تحديد فئة، يتم تضمين الفئات الأصلية؛ إذا تم تحديد خاصية، تتم إضافة الفئات النطاق والنطاق. بالإضافة إلى ذلك، لكل فئة محددة، فإنه يتضمن تلقائيًا **جميع الخصائص التي تشير إلى تلك الفئة** في نطاقها أو نطاقها. يضمن ذلك أن عملية الاستخراج لديها إمكانية الوصول إلى جميع خصائص العلاقة ذات الصلة. + +**العمليات الرئيسية**: +إنشاء تضمينات لكل جزء نصي (جمل) +إجراء بحث أقرب جار في مخزن المتجهات FAISS (top_k=10، threshold=0.3) +تطبيق حد التشابه لتصفية التطابقات الضعيفة +حل التبعيات (الفئات الأصلية، النطاقات، المجالات) +**إضافة تلقائيًا جميع الخصائص المتعلقة بالفئات المحددة** (مطابقة المجال/النطاق) +إنشاء مجموعة فرعية متماسكة من علم الأنطولوجيا مع جميع العلاقات المطلوبة +إزالة العناصر المكررة التي تظهر عدة مرات + +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. بناء المطالبات (Prompt Construction) + +**الغرض**: إنشاء مطالبات منظمة توجه نموذج اللغة الكبير (LLM) لاستخراج فقط الثلاثيات المتوافقة مع علم الأنطولوجيا. + +**التنفيذ**: +تستخدم خدمة الاستخراج قالب Jinja2 يتم تحميله من `ontology-prompt.md` والذي يقوم بتنسيق مجموعة فرعية من علم الأنطولوجيا والنص لاستخراج LLM. يتكرر القالب ديناميكيًا عبر الفئات وخصائص الكائنات وخصائص البيانات باستخدام بناء جملة Jinja2، حيث يتم تقديم كل منها مع أوصافها، ومجالاتها، ونطاقاتها، وعلاقاتها الهرمية. تتضمن المطالبة قواعد صارمة لاستخدام عناصر علم الأنطولوجيا المقدمة فقط وتطلب تنسيق JSON للإخراج لسهولة التحليل. + +**العمليات الرئيسية**: +استخدام قالب Jinja2 مع حلقات عبر عناصر علم الأنطولوجيا +تنسيق الفئات مع علاقات الأبوة (subclass_of) والتعليقات +تنسيق الخصائص مع قيود المجال/النطاق والتعليقات +تضمين قواعد استخراج صريحة ومتطلبات تنسيق الإخراج +استدعاء خدمة المطالبة باستخدام معرف القالب "extract-with-ontologies" + +**موقع القالب**: `ontology-prompt.md` +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (طريقة build_extraction_variables) + +#### 6. خدمة الاستخراج الرئيسية + +**الغرض**: تنسيق جميع المكونات لأداء استخراج شامل قائم على علم الأنطولوجيا. + +**التنفيذ**: +خدمة الاستخراج الرئيسية (KgExtractOntology) هي الطبقة التي تدير سير عمل الاستخراج بأكمله. إنها تستخدم نمط TrustGraph's FlowProcessor مع تهيئة المكونات الخاصة بكل تدفق. عندما يصل تحديث لتكوين علم الأنطولوجيا، فإنها تقوم بتهيئة أو تحديث المكونات الخاصة بالتدفق (محمل علم الأنطولوجيا، والمُضمّن، ومعالج النصوص، والمحدد). عندما يصل جزء نص للمعالجة، فإنها تنسق المسار: تقسيم النص إلى أجزاء، والعثور على عناصر علم الأنطولوجيا ذات الصلة من خلال البحث عن المتجهات، وإنشاء مطالبة مقيدة، واستدعاء خدمة المطالبة، وتحليل الاستجابة والتحقق من صحتها، وإنشاء ثلاثيات تعريف علم الأنطولوجيا، وإخراج كل من ثلاثيات المحتوى وسياقات الكيانات. + +**مسار الاستخراج**: +1. استقبال جزء نص عبر قائمة الانتظار chunks-input +2. تهيئة مكونات التدفق إذا لزم الأمر (في أول جزء أو عند تحديث التكوين) +3. تقسيم النص إلى جمل باستخدام NLTK +4. البحث في مخزن المتجهات FAISS للعثور على مفاهيم علم الأنطولوجيا ذات الصلة +5. بناء مجموعة فرعية من علم الأنطولوجيا مع إضافة تلقائي للخصائص +6. إنشاء متغيرات مطالبة من قالب Jinja2 +7. استدعاء خدمة المطالبة باستخدام قالب extract-with-ontologies +8. تحليل استجابة JSON إلى ثلاثيات منظمة +9. التحقق من صحة الثلاثيات وتوسيع معرفات الموارد الموحدة (URIs) إلى معرفات موارد موحدة كاملة لعلم الأنطولوجيا +10. إنشاء ثلاثيات تعريف علم الأنطولوجيا (الفئات والخصائص مع التسميات والتعليقات والمجالات والنطاقات) +11. بناء سياقات الكيانات من جميع الثلاثيات +12. الإخراج إلى قوائم الانتظار triples و entity-contexts + +**الميزات الرئيسية**: +مخازن متجهات خاصة بكل تدفق تدعم نماذج تضمين مختلفة +تحديثات علم الأنطولوجيا المستندة إلى الأحداث عبر قائمة الانتظار config-update +توسيع تلقائي لمعرفات الموارد الموحدة باستخدام معرفات موارد موحدة لعلم الأنطولوجيا +إضافة عناصر علم الأنطولوجيا إلى الرسم البياني للمعرفة مع بيانات التعريف الكاملة +تتضمن سياقات الكيانات عناصر المحتوى وعناصر علم الأنطولوجيا + +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### التكوين + +تستخدم الخدمة نهج التكوين القياسي لـ TrustGraph مع وسيطات سطر الأوامر: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**المعلمات الأساسية للتكوين**: +`similarity_threshold`: 0.3 (افتراضي، يمكن تكوينه في الكود) +`top_k`: 10 (عدد عناصر الأونطولوجيا التي يتم استرجاعها لكل جزء) +`vector_store`: فهرس FAISS FlatIP لكل تدفق مع أبعاد يتم اكتشافها تلقائيًا +`text_processor`: NLTK مع تجزئة الجمل punkt_tab +`prompt_template`: "extract-with-ontologies" (قالب Jinja2) + +**تكوين الأونطولوجيا**: +يتم تحميل الأونطولوجيات ديناميكيًا عبر قائمة انتظار التحديثات (config-update) من النوع "ontology". + +### تدفق البيانات + +1. **مرحلة التهيئة** (لكل تدفق): + استقبال تكوين الأونطولوجيا عبر قائمة انتظار التحديثات. + تحليل كائن JSON للأونطولوجيا إلى كائنات OntologyClass و OntologyProperty. + إنشاء تضمينات لجميع عناصر الأونطولوجيا باستخدام EmbeddingsClientSpec. + تخزين التضمينات في مخزن متجه FAISS الخاص بكل تدفق. + اكتشاف أبعاد التضمين تلقائيًا من الاستجابة الأولى. + +2. **مرحلة الاستخراج** (لكل جزء): + استقبال جزء من قائمة انتظار chunks-input. + تقسيم الجزء إلى جمل باستخدام NLTK. + حساب تضمينات لكل جملة. + البحث في مخزن المتجهات FAISS عن عناصر الأونطولوجيا ذات الصلة. + إنشاء مجموعة فرعية من الأونطولوجيا مع تضمين تلقائي للخصائص. + إنشاء متغيرات قالب Jinja2 مع النص والأونطولوجيا. + استدعاء خدمة المطالبة باستخدام قالب extract-with-ontologies. + تحليل استجابة JSON والتحقق من صحة الثلاثيات. + توسيع الروابط باستخدام روابط الأونطولوجيا. + إنشاء ثلاثيات تعريف الأونطولوجيا. + إنشاء سياقات الكيانات من جميع الثلاثيات. + الإخراج إلى قوائم انتظار triples و entity-contexts. + +### مخزن المتجهات في الذاكرة + +**الغرض**: يوفر بحث سريع قائم على الذاكرة عن طريق تشابه للعثور على تطابقات لعناصر الأونطولوجيا. + +**التنفيذ: FAISS** + +يستخدم النظام **FAISS (Facebook AI Similarity Search)** مع IndexFlatIP للبحث الدقيق عن التشابه بناءً على الجيب التمامي. الميزات الرئيسية: + +**IndexFlatIP**: بحث دقيق عن التشابه بناءً على الجيب التمامي باستخدام الضرب الداخلي. +**الاكتشاف التلقائي**: يتم تحديد البعد من استجابة التضمين الأولى. +**مخازن خاصة بكل تدفق**: يحتوي كل تدفق على مخزن متجه مستقل لنماذج تضمين مختلفة. +**التطبيع**: يتم تطبيع جميع المتجهات قبل الفهرسة. +**عمليات الدفعات**: إضافة دفعات فعالة للتحميل الأولي للأونطولوجيا. + +**موقع التنفيذ**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### خوارزمية اختيار المجموعة الفرعية من الأونطولوجيا + +**الغرض**: يختار ديناميكيًا الجزء ذي الصلة الأدنى لكل جزء نصي. + +**خطوات الخوارزمية التفصيلية**: + +1. **تقسيم النص**: + تقسيم الجزء المدخل إلى جمل باستخدام اكتشاف الجملة الخاص بمعالجة اللغة الطبيعية. + استخراج العبارات الاسمية وعبارات الأفعال والكيانات المسماة من كل جملة. + إنشاء هيكل هرمي من الأجزاء مع الحفاظ على السياق. + +2. **إنشاء التضمينات**: + إنشاء تضمينات متجهة لكل جزء نصي (جمل وعبارات). + استخدم نفس نموذج التضمين المستخدم لعناصر الأونطولوجيا. + تخزين التضمينات للأجزاء المتكررة لتحسين الأداء. + +3. **بحث عن التشابه**: + لكل تضمين جزء نصي، ابحث في مخزن المتجهات. + استرجع أفضل k (مثل 10) من عناصر الأونطولوجيا الأكثر تشابهًا. + تطبيق عتبة التشابه (مثل 0.7) لتصفية التطابقات الضعيفة. + تجميع النتائج عبر جميع الأجزاء، مع تتبع ترددات التطابقات. + +4. **حل التبعيات**: + لكل فئة محددة، قم بتضمين جميع الفئات الأصلية بشكل متكرر حتى الجذر. + لكل خاصية محددة، قم بتضمين الفئات الخاصة بالنطاق والنطاق. + بالنسبة للخصائص العكسية، تأكد من تضمين كلا الاتجاهين. + أضف الفئات المكافئة إذا كانت موجودة في الأونطولوجيا. + +5. **إنشاء المجموعة الفرعية**: + إزالة العناصر المكررة مع الحفاظ على العلاقات. + تنظيمها في فئات وخصائص كائن وخصائص بيانات. + تأكد من الحفاظ على جميع القيود والعلاقات. + إنشاء أونطولوجيا مصغرة مكتفية بذاتها وصالحة وكاملة. + +**شرح تفصيلي**: +بالنظر إلى النص: "The brown dog chased the white cat up the tree." +الأجزاء: ["brown dog", "white cat", "tree", "chased"] +العناصر المتطابقة: [dog (class), cat (class), animal (parent), chases (property)] +التبعيات: [animal (parent of dog and cat), lifeform (parent of animal)] +المجموعة الفرعية النهائية: أونطولوجيا مصغرة كاملة مع تسلسل هرمي للحيوانات وعلاقة المطاردة. + +### التحقق من صحة الثلاثيات + +**الغرض**: يضمن أن جميع الثلاثيات المستخرجة تتوافق بشكل صارم مع قيود الأونطولوجيا. + +**خوارزمية التحقق**: + +1. **التحقق من الفئة (Class Validation)**: + التحقق من أن الكيانات هي مثيلات للفئات المحددة في مجموعة الأنطولوجيا. + بالنسبة لخصائص الكائنات، التحقق من أن الكائنات هي أيضًا مثيلات صالحة للفئات. + التحقق من أسماء الفئات مقابل قاموس الفئات في الأنطولوجيا. + التعامل مع التسلسلات الهرمية للفئات - تعتبر مثيلات الفئات الفرعية صالحة لقيود الفئة الأصل. + +2. **التحقق من الخاصية (Property Validation)**: + التأكد من أن الرأس (predicate) يتوافق مع الخصائص في مجموعة الأنطولوجيا. + التمييز بين خصائص الكائنات (من كيان إلى كيان) وخصائص البيانات (من كيان إلى حرفي). + التحقق من أن أسماء الخصائص تتطابق تمامًا (مع الأخذ في الاعتبار مساحة الاسم إذا كانت موجودة). + +3. **التحقق من النطاق/المدى (Domain/Range Checking)**: + لكل خاصية مستخدمة كرأس، استرجاع النطاق والمدى الخاص بها. + التحقق من أن نوع الكيان يطابق أو يرث من نطاق الخاصية. + التحقق من أن نوع الكائن يطابق أو يرث من مدى الخاصية. + بالنسبة لخصائص البيانات، التحقق من أن الكائن هو حرفي من النوع XSD الصحيح. + +4. **التحقق من التعددية (Cardinality Validation)**: + تتبع عدد مرات استخدام الخاصية لكل كيان. + التحقق من الحد الأدنى للتعددية - التأكد من وجود الخصائص المطلوبة. + التحقق من الحد الأقصى للتعددية - التأكد من عدم استخدام الخاصية مرات عديدة جدًا. + بالنسبة للخصائص الوظيفية، التأكد من وجود قيمة واحدة على الأكثر لكل كيان. + +5. **التحقق من نوع البيانات (Datatype Validation)**: + تحليل القيم الحرفية وفقًا لأنواع XSD المعلنة الخاصة بها. + التحقق من أن الأعداد الصحيحة هي أرقام صالحة، وأن التواريخ منسقة بشكل صحيح، وما إلى ذلك. + التحقق من أنماط السلاسل النصية إذا تم تعريف قيود regex. + التأكد من أن عناوين URI ذات تنسيق صحيح لأنواع xsd:anyURI. + +**مثال على التحقق (Validation Example)**: +ثلاثية: ("Buddy", "has-owner", "John") +التحقق من أن "Buddy" مصنف على أنه فئة يمكن أن تحتوي على خاصية "has-owner". +التحقق من وجود "has-owner" في الأنطولوجيا. +التحقق من قيد النطاق: يجب أن يكون نوع الكيان هو "Pet" أو فئة فرعية. +التحقق من قيد المدى: يجب أن يكون نوع الكائن هو "Person" أو فئة فرعية. +إذا كان الأمر صالحًا، قم بإضافته إلى الإخراج؛ إذا كان غير صالح، قم بتسجيل الانتهاك وتجاهله. + +## اعتبارات الأداء (Performance Considerations) + +### استراتيجيات التحسين (Optimisation Strategies) + +1. **التخزين المؤقت للتضمين (Embedding Caching)**: تخزين التضمينات لأجزاء النص المستخدمة بشكل متكرر. +2. **المعالجة الدفعية (Batch Processing)**: معالجة أجزاء متعددة بالتوازي. +3. **فهرسة مخزن المتجهات (Vector Store Indexing)**: استخدم خوارزميات أقرب جار تقريبي للأنطولوجيات الكبيرة. +4. **تحسين المطالبة (Prompt Optimisation)**: قلل من حجم المطالبة عن طريق تضمين عناصر الأنطولوجيا الأساسية فقط. +5. **تخزين نتائج مؤقت (Result Caching)**: تخزين نتائج الاستخراج لقطع متطابقة. + +### قابلية التوسع (Scalability) + +**التوسع الأفقي (Horizontal Scaling)**: مثيلات مستخرجة متعددة مع ذاكرة تخزين مؤقت للأنطولوجيا مشتركة. +**تقسيم الأنطولوجيا (Ontology Partitioning)**: تقسيم الأنطولوجيات الكبيرة حسب المجال. +**المعالجة المتدفقة (Streaming Processing)**: معالجة الأجزاء أثناء وصولها دون تجميعها. +**إدارة الذاكرة (Memory Management)**: تنظيف دوري للتضمينات غير المستخدمة. + +## معالجة الأخطاء (Error Handling) + +### سيناريوهات الفشل (Failure Scenarios) + +1. **الأنطولوجيات المفقودة (Missing Ontologies)**: العودة إلى الاستخراج غير المقيد. +2. **فشل خدمة التضمين (Embedding Service Failure)**: استخدم التضمينات المخزنة مؤقتًا أو تخطى المطابقة الدلالية. +3. **انتهاء مهلة خدمة المطالبة (Prompt Service Timeout)**: أعد المحاولة باستخدام تأخير متزايد. +4. **تنسيق ثلاثي غير صالح (Invalid Triple Format)**: سجل وتجاهل الثلاثيات المشوهة. +5. **عدم اتساق الأنطولوجيا (Ontology Inconsistencies)**: الإبلاغ عن التعارضات واستخدام العناصر الصالحة الأكثر تحديدًا. + +### المراقبة (Monitoring) + +المقاييس الرئيسية التي يجب تتبعها: + +وقت تحميل الأنطولوجيا واستهلاك الذاكرة. +زمن انتقال إنشاء التضمين. +أداء البحث عن المتجهات. +وقت استجابة خدمة المطالبة. +دقة استخراج الثلاثيات. +معدل توافق الأنطولوجيا. + +## مسار الترحيل (Migration Path) + +### من المستخرجات الحالية (From Existing Extractors) + +1. **التشغيل بالتوازي (Parallel Operation)**: قم بتشغيله جنبًا إلى جنب مع المستخرجات الحالية في البداية. +2. **النشر التدريجي (Gradual Rollout)**: ابدأ بأنواع مستندات محددة. +3. **مقارنة الجودة (Quality Comparison)**: قارن جودة الإخراج مع المستخرجات الحالية. +4. **الترحيل الكامل (Full Migration)**: استبدل المستخرجات الحالية بمجرد التحقق من الجودة. + +### تطوير الأنطولوجيا (Ontology Development) + +1. **البدء من الموجود (Bootstrap from Existing)**: قم بإنشاء أنطولوجيات أولية من المعرفة الحالية. +2. **التحسين التكراري (Iterative Refinement)**: قم بتحسينها بناءً على أنماط الاستخراج. +3. **مراجعة الخبراء (Domain Expert Review)**: التحقق من صحتها مع خبراء الموضوع. +4. **التحسين المستمر (Continuous Improvement)**: قم بتحديثها بناءً على ملاحظات الاستخراج. + +## خدمة الاستعلام الحساسة للأنطولوجيا (Ontology-Sensitive Query Service) + +### نظرة عامة (Overview) + +توفر خدمة الاستعلام الحساسة للأنطولوجيا مسارات استعلام متعددة لدعم أنواع مختلفة من قواعد البيانات. + +**مكونات الخدمة**: +`onto-query-sparql`: يحول اللغة الطبيعية إلى SPARQL لقاعدة بيانات Cassandra. +`sparql-cassandra`: طبقة استعلام SPARQL لقاعدة بيانات Cassandra باستخدام rdflib. +`onto-query-cypher`: يحول اللغة الطبيعية إلى Cypher لقواعد بيانات الرسوم البيانية. +`cypher-executor`: تنفيذ استعلامات Cypher لـ Neo4j/Memgraph/FalkorDB. + +### العمارة + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### معالجة الاستعلامات (Query Processing Pipeline) + +#### 1. محلل الأسئلة (Question Analyser) + +**الغرض**: يقوم بتفكيك أسئلة المستخدم إلى مكونات دلالية لمطابقة الأنطولوجيا. + +**وصف الخوارزمية**: +يقوم محلل الأسئلة بتحليل السؤال باللغة الطبيعية وتقسيمه إلى أجزاء ذات معنى باستخدام نفس طريقة تقسيم الجمل المستخدمة في مسار الاستخراج. يحدد الكيانات والعلاقات والقيود الرئيسية المذكورة في السؤال. يتم تحليل كل جزء لتحديد نوع السؤال (حقيقي، تجميعي، مقارنة، إلخ) والتنسيق المتوقع للإجابة. يساعد هذا التقسيم في تحديد الأجزاء الأكثر صلة من الأنطولوجيا للإجابة على السؤال. + +**العمليات الرئيسية**: +تقسيم السؤال إلى جمل وعبارات +تحديد نوع السؤال والنية +استخراج الكيانات والعلاقات المذكورة +اكتشاف القيود والمرشحات في السؤال +تحديد التنسيق المتوقع للإجابة + +#### 2. مُطابق الأنطولوجيا للاستعلامات (Ontology Matcher for Queries) + +**الغرض**: يحدد مجموعة الأنطولوجيا ذات الصلة اللازمة للإجابة على السؤال. + +**وصف الخوارزمية**: +مشابه لمُحدد الأنطولوجيا في مسار الاستخراج، ولكنه مُحسَّن للإجابة على الأسئلة. يقوم المُطابق بإنشاء تضمينات لأجزاء السؤال ويبحث في مستودع المتجهات عن عناصر الأنطولوجيا ذات الصلة. ومع ذلك، فإنه يركز على إيجاد المفاهيم التي ستكون مفيدة لبناء الاستعلامات بدلاً من الاستخراج. يقوم بتوسيع التحديد ليشمل الخصائص ذات الصلة التي قد يتم استكشافها أثناء استكشاف الرسم البياني، حتى لو لم يتم ذكرها صراحةً في السؤال. على سبيل المثال، إذا تم طرح سؤال حول "الموظفين"، فقد يتضمن خصائص مثل "يعمل لدى" و "يدير" و "يقدم تقارير إلى" والتي يمكن أن تكون ذات صلة للعثور على معلومات الموظفين. + +**استراتيجية المطابقة**: +إنشاء تضمينات لأجزاء السؤال +العثور على مفاهيم الأنطولوجيا المذكورة بشكل مباشر +تضمين الخصائص التي تربط الفئات المذكورة +إضافة خصائص عكسية ومرتبطة للاستكشاف +تضمين الفئات الأبوية/الفرعية للاستعلامات الهرمية +بناء قسم الأنطولوجيا الموجه نحو الاستعلام + +#### 3. موجه الواجهة الخلفية (Backend Router) + +**الغرض**: يوجه الاستعلامات إلى مسار الاستعلام الخاص بالواجهة الخلفية المناسب بناءً على التكوين. + +**وصف الخوارزمية**: +يقوم موجه الواجهة الخلفية بفحص تكوين النظام لتحديد الواجهة الخلفية للرسم البياني النشطة (Cassandra أو Cypher-based). يوجه السؤال وقسم الأنطولوجيا إلى خدمة إنشاء الاستعلامات المناسبة. يمكن للموجه أيضًا دعم موازنة التحميل عبر واجهات خلفية متعددة أو آليات احتياطية إذا كانت الواجهة الخلفية الأساسية غير متاحة. + +**منطق التوجيه**: +التحقق من نوع الواجهة الخلفية المُكوَّن من إعدادات النظام +التوجيه إلى `onto-query-sparql` لواجهات خلفية Cassandra +التوجيه إلى `onto-query-cypher` لواجهات خلفية Neo4j/Memgraph/FalkorDB +دعم تكوينات متعددة الواجهات الخلفية مع توزيع الاستعلامات +التعامل مع سيناريوهات التعافي من الأعطال وموازنة التحميل + +#### 4. إنشاء استعلام SPARQL (`onto-query-sparql`) + +**الغرض**: يحول أسئلة اللغة الطبيعية إلى استعلامات SPARQL لتنفيذها على Cassandra. + +**وصف الخوارزمية**: +يأخذ مُنشئ استعلام SPARQL السؤال وقسم الأنطولوجيا وينشئ استعلام SPARQL مُحسَّنًا للتنفيذ على الواجهة الخلفية Cassandra. يستخدم خدمة المطالبة بقالب مُخصص لـ SPARQL والذي يتضمن دلالات RDF/OWL. يفهم المُنشئ أنماط SPARQL مثل مسارات الخصائص والعبارات الاختيارية والمرشحات التي يمكن أن تترجم بكفاءة إلى عمليات Cassandra. + +**قالب مطالبة إنشاء SPARQL**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. توليد استعلامات Cypher (`onto-query-cypher`) + +**الغرض**: تحويل الأسئلة بلغة طبيعية إلى استعلامات Cypher لقواعد البيانات الرسومية. + +**وصف الخوارزمية**: +يقوم مُولِّد استعلامات Cypher بإنشاء استعلامات Cypher أصلية مُحسَّنة لـ Neo4j و Memgraph و FalkorDB. فهو يربط فئات علم الوجود بتسميات العقد والخصائص بعلاقات، باستخدام بناء جملة مطابقة الأنماط الخاص بـ Cypher. يتضمن المولد تحسينات خاصة بـ Cypher مثل تلميحات اتجاه العلاقة واستخدام الفهارس وتلميحات تخطيط الاستعلام. + +**قالب المطالبة لتوليد Cypher**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. محرك الاستعلامات SPARQL-Cassandra (`sparql-cassandra`) + +**الغرض**: ينفذ استعلامات SPARQL على Cassandra باستخدام مكتبة Python rdflib. + +**وصف الخوارزمية**: +يقوم محرك SPARQL-Cassandra بتنفيذ معالج SPARQL باستخدام مكتبة rdflib الخاصة بـ Python مع مخزن خلفي مخصص لـ Cassandra. يقوم بترجمة أنماط الرسم البياني SPARQL إلى استعلامات CQL المناسبة لـ Cassandra، مع معالجة عمليات الربط والتصفية والتجميع. يحتفظ المحرك بخريطة من RDF إلى Cassandra تحافظ على البنية الدلالية مع تحسينها لتخزين Cassandra القائم على نماذج الأعمدة. + +**ميزات التنفيذ**: +تطبيق واجهة rdflib Store لـ Cassandra. +دعم استعلامات SPARQL 1.1 مع الأنماط الشائعة. +ترجمة فعالة لأنماط الثلاثيات إلى CQL. +دعم مسارات الخصائص والاستعلامات الهرمية. +بث النتائج لمجموعات البيانات الكبيرة. +تجميع الاتصالات وتخزين الاستعلامات مؤقتًا. + +**مثال للترجمة**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +يترجم إلى استعلامات Cassandra مُحسّنة تستفيد من الفهارس ومفاتيح التقسيم. + +#### 7. مُنفّذ استعلامات Cypher (`cypher-executor`) + +**الغرض**: ينفذ استعلامات Cypher ضد Neo4j و Memgraph و FalkorDB. + +**وصف الخوارزمية**: +يوفر مُنفّذ Cypher واجهة موحدة لتنفيذ استعلامات Cypher عبر قواعد بيانات الرسوم البيانية المختلفة. يتعامل مع بروتوكولات الاتصال الخاصة بقاعدة البيانات، وتلميحات تحسين الاستعلام، وتوحيد تنسيق النتائج. يتضمن المُنفّذ منطق إعادة المحاولة، وتجميع الاتصالات، وإدارة المعاملات المناسبة لكل نوع قاعدة بيانات. + +**دعم قواعد بيانات متعددة**: +**Neo4j**: بروتوكول Bolt، ووظائف المعاملات، وتلميحات الفهرسة. +**Memgraph**: بروتوكول مخصص، ونتائج متدفقة، واستعلامات تحليلية. +**FalkorDB**: تكييف بروتوكول Redis، وتحسينات الذاكرة. + +**ميزات التنفيذ**: +إدارة اتصالات مستقلة عن قاعدة البيانات. +التحقق من صحة الاستعلام وفحص بناء الجملة. +فرض حدود المهلة والموارد. +تقسيم النتائج وتدفقها. +مراقبة الأداء لكل نوع قاعدة بيانات. +التبديل التلقائي بين مثيلات قاعدة البيانات. + +#### 8. مُولّد الإجابات + +**الغرض**: يجمع إجابة بلغة طبيعية من نتائج الاستعلام. + +**وصف الخوارزمية**: +يأخذ مُولّد الإجابات النتائج المنظمة للاستعلام والسؤال الأصلي، ثم يستخدم خدمة المطالبة لإنشاء إجابة شاملة. على عكس الاستجابات القائمة على القوالب البسيطة، فإنه يستخدم نموذج لغة كبير (LLM) لتفسير بيانات الرسم البياني في سياق السؤال، والتعامل مع العلاقات المعقدة، والتجميعات، والاستدلالات. يمكن للمولد شرح منطقه من خلال الرجوع إلى هيكل علم الوجود والعبارات الثلاثية المحددة المستخرجة من الرسم البياني. + +**عملية توليد الإجابات**: +تنسيق نتائج الاستعلام في سياق منظم. +تضمين تعريفات علم الوجود ذات الصلة من أجل الوضوح. +إنشاء مطالبة مع السؤال والنتائج. +إنشاء إجابة بلغة طبيعية عبر نموذج لغة كبير. +التحقق من صحة الإجابة مقابل نية الاستعلام. +إضافة اقتباسات إلى كيانات الرسم البياني المحددة إذا لزم الأمر. + +### التكامل مع الخدمات الحالية + +#### العلاقة مع GraphRAG + +**تكميلية**: توفر onto-query دقة دلالية بينما توفر GraphRAG تغطية واسعة. +**بنية تحتية مشتركة**: يستخدم كلاهما نفس الرسم البياني للمعرفة وخدمات المطالبة. +**توجيه الاستعلامات**: يمكن للنظام توجيه الاستعلامات إلى الخدمة الأكثر ملاءمة بناءً على نوع السؤال. +**الوضع الهجين**: يمكن الجمع بين كلا النهجين للحصول على إجابات شاملة. + +#### العلاقة مع استخراج OntoRAG + +**علم الوجود المشترك**: يستخدم نفس تكوينات علم الوجود التي يتم تحميلها بواسطة kg-extract-ontology. +**مخزن المتجهات المشترك**: يعيد استخدام التضمينات الموجودة في الذاكرة من خدمة الاستخراج. +**دلالات متسقة**: تعمل الاستعلامات على الرسوم البيانية التي تم إنشاؤها بنفس القيود الدلالية. + +### أمثلة الاستعلامات + +#### المثال 1: استعلام بسيط عن الكيان +**السؤال**: "ما هي الحيوانات التي تعتبر ثدييات؟" +**تطابق علم الوجود**: [حيوان، ثديي، subClassOf] +**الاستعلام الذي تم إنشاؤه**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### مثال 2: استعلام عن العلاقة +**السؤال**: "ما هي المستندات التي كتبها جون سميث؟" +**مطابقة علم الوجود**: [مستند، شخص، له-مؤلف] +**الاستعلام الناتج**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### مثال 3: استعلام التجميع +**السؤال**: "كم عدد أرجل القطط؟" +**مطابقة علم المفاهيم**: [قطة، عدد الأرجل (خاصية بيانات)] +**الاستعلام الناتج**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### التكوين + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### التحسينات في الأداء + +#### تحسين الاستعلام + +**تقليم علم الأنطولوجيا**: قم بتضمين عناصر علم الأنطولوجيا الضرورية فقط في المطالبات. +**تخزين مؤقت للاستعلامات**: قم بتخزين الأسئلة المتكررة والاستعلامات الخاصة بها مؤقتًا. +**تخزين مؤقت للنتائج**: قم بتخزين النتائج للاستعلامات المتطابقة ضمن إطار زمني. +**المعالجة الدفعية**: تعامل مع أسئلة متعددة ذات صلة في عبور رسم بياني واحد. + +#### اعتبارات قابلية التوسع + +**التنفيذ الموزع**: قم بتوازي الاستعلامات الفرعية عبر أقسام الرسم البياني. +**النتائج التدريجية**: قم بتدفق النتائج لمجموعات البيانات الكبيرة. +**موازنة التحميل**: وزّع حمل الاستعلام عبر مثيلات خدمة متعددة. +**مجموعات الموارد**: قم بإدارة مجموعات الاتصال بقواعد بيانات الرسم البياني. + +### معالجة الأخطاء + +#### سيناريوهات الفشل + +1. **توليد استعلام غير صالح**: التراجع إلى GraphRAG أو البحث عن الكلمات الرئيسية البسيطة. +2. **عدم تطابق علم الأنطولوجيا**: قم بتوسيع البحث ليشمل مجموعة فرعية أوسع من علم الأنطولوجيا. +3. **انتهاء مهلة الاستعلام**: قم بتبسيط الاستعلام أو زيادة المهلة. +4. **نتائج فارغة**: اقترح إعادة صياغة الاستعلام أو أسئلة ذات صلة. +5. **فشل خدمة LLM**: استخدم الاستعلامات المخزنة مؤقتًا أو الاستجابات المستندة إلى القوالب. + +### مقاييس المراقبة + +توزيع تعقيد الأسئلة. +أحجام أقسام علم الأنطولوجيا. +معدل نجاح توليد الاستعلام. +وقت تنفيذ استعلام الرسم البياني. +درجات جودة الإجابة. +معدلات الإصابة في ذاكرة التخزين المؤقت. +ترددات الأخطاء حسب النوع. + +## التحسينات المستقبلية + +1. **تعلم علم الأنطولوجيا**: قم بتوسيع علم الأنطولوجيا تلقائيًا بناءً على أنماط الاستخراج. +2. **تسجيل الثقة**: قم بتعيين درجات ثقة للثلاثيات المستخرجة. +3. **توليد الشرح**: قم بتوفير التفسير لعملية استخراج الثلاثيات. +4. **التعلم النشط**: اطلب التحقق البشري للاستخراج غير المؤكد. + +## اعتبارات الأمان + +1. **منع حقن المطالبات**: قم بتنظيف نص الكتلة قبل إنشاء المطالبة. +2. **حدود الموارد**: حد من استخدام الذاكرة لمخزن المتجهات. +3. **تحديد المعدل**: حد من طلبات الاستخراج لكل عميل. +4. **تسجيل التدقيق**: تتبع جميع طلبات الاستخراج والنتائج. + +## استراتيجية الاختبار + +### اختبار الوحدة + +مُحمِّل علم الأنطولوجيا بتنسيقات مختلفة. +توليد المتجهات وتخزينها. +خوارزميات تقسيم الجمل. +حسابات التشابه المتجهي. +تحليل الثلاثيات والتحقق من صحتها. + +### اختبار التكامل + +مسار استخراج شامل. +تكامل خدمة التكوين. +تفاعل خدمة المطالبة. +معالجة الاستخراج المتزامن. + +### اختبار الأداء + +التعامل مع علم الأنطولوجيا الكبيرة (1000+ فئة). +معالجة دفعية عالية الحجم. +استخدام الذاكرة تحت الحمل. +معايير زمن الوصول. + +## خطة التسليم + +### نظرة عامة + +سيتم تسليم نظام OntoRAG في أربع مراحل رئيسية، حيث توفر كل مرحلة قيمة متزايدة مع بناء النظام بأكمله. تركز الخطة على إنشاء إمكانات الاستخراج الأساسية أولاً، ثم إضافة وظائف الاستعلام، متبوعة بالتحسينات والميزات المتقدمة. + +### المرحلة 1: الأساس والاستخراج الأساسي + +**الهدف**: إنشاء مسار استخراج أساسي مدفوع بعلم الأنطولوجيا مع مطابقة بسيطة للمتجهات. + +#### الخطوة 1.1: أساس إدارة علم الأنطولوجيا +تنفيذ مُحمِّل تكوين علم الأنطولوجيا (`OntologyLoader`). +تحليل بنى JSON الخاصة بعلم الأنطولوجيا والتحقق من صحتها. +إنشاء تخزين علم الأنطولوجيا في الذاكرة وأنماط الوصول. +تنفيذ آلية تحديث علم الأنطولوجيا. + +**معايير النجاح**: +تحميل وتحليل تكوينات علم الأنطولوجيا بنجاح. +التحقق من صحة بنية علم الأنطولوجيا واتساقها. +التعامل مع العديد من علم الأنطولوجيا المتزامنة. + +#### الخطوة 1.2: تنفيذ مستودع المتجهات +تنفيذ مستودع متجهات بسيط يعتمد على NumPy كنموذج أولي أولي. +إضافة تطبيق مستودع متجهات FAISS. +إنشاء تجريد واجهة مستودع المتجهات. +تنفيذ البحث عن التشابه مع تحديد العتبات القابلة للتكوين. + +**معايير النجاح**: +تخزين واسترجاع التضمينات بكفاءة. +إجراء بحث عن التشابه مع زمن انتقال أقل من 100 مللي ثانية. +دعم كل من الواجهات الخلفية NumPy و FAISS. + +#### الخطوة 1.3: مسار تضمين علم المفاهيم. +التكامل مع خدمة التضمين. +تنفيذ المكون `OntologyEmbedder`. +إنشاء تضمينات لجميع عناصر علم المفاهيم. +تخزين التضمينات مع البيانات الوصفية في مخزن المتجهات. + +**معايير النجاح**: +إنشاء تضمينات للفئات والخصائص. +تخزين التضمينات مع البيانات الوصفية المناسبة. +إعادة بناء التضمينات عند تحديث علم المفاهيم. + +#### الخطوة 1.4: مكونات معالجة النصوص. +تنفيذ أداة تقسيم الجمل باستخدام NLTK/spaCy. +استخراج العبارات والكيانات المسماة. +إنشاء تسلسل هرمي لشرائح النصوص. +إنشاء تضمينات لشرائح النصوص. + +**معايير النجاح**: +تقسيم النصوص بدقة إلى جمل. +استخراج عبارات ذات معنى. +الحفاظ على علاقات السياق. + +#### الخطوة 1.5: خوارزمية اختيار علم المفاهيم. +تنفيذ مطابقة التشابه بين النصوص وعلم المفاهيم. +بناء حل لتبعيات عناصر علم المفاهيم. +إنشاء مجموعات فرعية متماسكة من علم المفاهيم. +تحسين أداء إنشاء المجموعة الفرعية. + +**معايير النجاح**: +تحديد عناصر علم المفاهيم ذات الصلة بدقة >80%. +تضمين جميع التبعيات اللازمة. +إنشاء مجموعات فرعية في <500 مللي ثانية. + +#### الخطوة 1.6: خدمة الاستخراج الأساسية. +تنفيذ بناء المطالبات للاستخراج. +التكامل مع خدمة المطالبات. +تحليل والتحقق من صحة استجابات الثلاثيات. +إنشاء نقطة نهاية الخدمة `kg-extract-ontology`. + +**معايير النجاح**: +استخراج ثلاثيات متوافقة مع علم المفاهيم. +التحقق من صحة جميع الثلاثيات مقابل علم المفاهيم. +التعامل مع أخطاء الاستخراج بأمان. + +### المرحلة 2: تنفيذ نظام الاستعلام. + +**الهدف**: إضافة إمكانات استعلام واعية بعلم المفاهيم مع دعم واجهات خلفية متعددة. + +#### الخطوة 2.1: مكونات أساسية للاستعلام. +تنفيذ محلل الأسئلة. +إنشاء مُطابق لعلم المفاهيم للاستعلامات. +تكييف بحث المتجهات لسياق الاستعلام. +بناء مكون توجيه الواجهة الخلفية. + +**معايير النجاح**: +تحليل الأسئلة إلى مكونات دلالية. +مطابقة الأسئلة مع عناصر علم المفاهيم ذات الصلة. +توجيه الاستعلامات إلى الواجهة الخلفية المناسبة. + +#### الخطوة 2.2: تنفيذ مسار SPARQL. +تنفيذ الخدمة `onto-query-sparql`. +إنشاء مُولد استعلامات SPARQL باستخدام LLM. +تطوير قوالب المطالبات لإنشاء SPARQL. +التحقق من صحة بناء جملة SPARQL الذي تم إنشاؤه. + +**معايير النجاح**: +إنشاء استعلامات SPARQL صالحة. +استخدام أنماط SPARQL المناسبة. +التعامل مع أنواع الاستعلامات المعقدة. + +#### الخطوة 2.3: محرك SPARQL-Cassandra. +تنفيذ واجهة تخزين rdflib لـ Cassandra. +إنشاء مترجم استعلامات CQL. +تحسين مطابقة أنماط الثلاثيات. +التعامل مع تنسيق نتائج SPARQL. + +**معايير النجاح**: +تنفيذ استعلامات SPARQL على Cassandra. +دعم أنماط SPARQL الشائعة. +إرجاع النتائج بالتنسيق القياسي. + +#### الخطوة 2.4: تنفيذ مسار Cypher. +تنفيذ الخدمة `onto-query-cypher`. +إنشاء مُولد استعلامات Cypher باستخدام LLM. +تطوير قوالب المطالبات لإنشاء Cypher. +التحقق من صحة بناء جملة Cypher الذي تم إنشاؤه. + +**معايير النجاح**: +إنشاء استعلامات Cypher صالحة. +استخدام أنماط الرسم البياني المناسبة. +دعم Neo4j و Memgraph و FalkorDB. + +#### الخطوة 2.5: منفذ Cypher. +تنفيذ مُنفِّذ Cypher متعدد قواعد البيانات. +دعم بروتوكول Bolt (Neo4j/Memgraph). +دعم بروتوكول Redis (FalkorDB). +التعامل مع التطبيع (Normalization) للنتائج. + +**معايير النجاح**: +تنفيذ Cypher على جميع قواعد البيانات المستهدفة. +التعامل مع الاختلافات الخاصة بقواعد البيانات. +الحفاظ على كفاءة مجموعات الاتصال (Connection Pools). + +#### الخطوة 2.6: توليد الإجابات. +تنفيذ مكون توليد الإجابات. +إنشاء مطالبات (Prompts) لتوليف الإجابات. +تنسيق نتائج الاستعلامات للاستهلاك بواسطة نماذج اللغة الكبيرة (LLM). +توليد إجابات بلغة طبيعية. + +**معايير النجاح**: +توليد إجابات دقيقة من نتائج الاستعلامات. +الحفاظ على السياق من السؤال الأصلي. +تقديم استجابات واضحة وموجزة. + +### المرحلة 3: التحسين والمرونة. + +**الهدف**: تحسين الأداء، وإضافة التخزين المؤقت (Caching)، وتحسين معالجة الأخطاء، وتعزيز الموثوقية. + +#### الخطوة 3.1: تحسين الأداء. +تنفيذ تخزين مؤقت للتضمينات (Embeddings). +إضافة تخزين مؤقت لنتائج الاستعلامات. +تحسين البحث عن المتجهات باستخدام فهارس FAISS IVF. +تنفيذ معالجة الدُفعات (Batch Processing) للتضمينات. + +**معايير النجاح**: +تقليل متوسط زمن الاستجابة للاستعلام بنسبة 50٪. +دعم 10 أضعاف عدد الطلبات المتزامنة. +الحفاظ على أوقات استجابة أقل من ثانية واحدة. + +#### الخطوة 3.2: معالجة متقدمة للأخطاء. +تنفيذ استعادة شاملة للأخطاء. +إضافة آليات احتياطية بين مسارات الاستعلام. +إنشاء منطق إعادة المحاولة مع تأخير أسي (Exponential Backoff). +تحسين تسجيل الأخطاء والتشخيص. + +**معايير النجاح**: +التعامل بأمان مع جميع سيناريوهات الفشل. +التبديل التلقائي بين الواجهات الخلفية (Backends). +تقديم تقارير تفصيلية عن الأخطاء لتصحيح الأخطاء. + +#### الخطوة 3.3: المراقبة وقابلية الملاحظة (Observability). +إضافة جمع مقاييس الأداء. +تنفيذ تتبع الاستعلامات. +إنشاء نقاط فحص صحة (Health Check Endpoints). +إضافة مراقبة استخدام الموارد. + +**معايير النجاح**: +تتبع جميع مؤشرات الأداء الرئيسية. +تحديد الاختناقات بسرعة. +مراقبة صحة النظام في الوقت الفعلي. + +#### الخطوة 3.4: إدارة التكوين (Configuration). +تنفيذ تحديثات ديناميكية للتكوين. +إضافة التحقق من صحة التكوين. +إنشاء قوالب تكوين. +دعم الإعدادات الخاصة بالبيئة. + +**معايير النجاح**: +تحديث التكوين دون إعادة التشغيل. +التحقق من صحة جميع تغييرات التكوين. +دعم بيئات نشر متعددة. + +### المرحلة 4: الميزات المتقدمة. + +**الهدف**: إضافة قدرات متطورة للنشر في بيئة الإنتاج وتعزيز الوظائف. + +#### الخطوة 4.1: دعم متعدد الأبعاد (Multi-Ontology). +تنفيذ منطق اختيار الأبعاد. +دعم الاستعلامات عبر الأبعاد. +التعامل مع إصدارات الأبعاد. +إنشاء قدرات دمج الأبعاد. + +**معايير النجاح**: +الاستعلام عبر أبعاد متعددة. +التعامل مع تعارضات الأبعاد. +دعم تطور الأبعاد. + +#### الخطوة 4.2: توجيه استعلامات ذكي. +تنفيذ التوجيه بناءً على الأداء +إضافة تحليل لتعقيد الاستعلام +إنشاء خوارزميات توجيه تكيفية +دعم اختبار A/B لمسارات التوجيه + +**معايير النجاح**: +توجيه الاستعلامات بشكل مثالي +التعلم من أداء الاستعلام +تحسين التوجيه بمرور الوقت + +#### الخطوة 4.3: ميزات الاستخراج المتقدمة +إضافة تقييم مستوى الثقة للمجموعات الثلاثية +تنفيذ توليد الشروحات +إنشاء حلقات ردود فعل للتحسين +دعم التعلم التدريجي + +**معايير النجاح**: +توفير درجات الثقة +شرح قرارات الاستخراج +تحسين الدقة باستمرار + +#### الخطوة 4.4: تعزيز الإنتاج +إضافة تحديد المعدل +تنفيذ المصادقة/التفويض +إنشاء أتمتة النشر +إضافة النسخ الاحتياطي والاستعادة + +**معايير النجاح**: +أمان جاهز للإنتاج +مسار نشر آلي +قدرة على التعافي من الكوارث + +### مراحل التسليم + +1. **المرحلة الأولى** (نهاية المرحلة 1): استخراج قائم على علم الوجود ويعمل بشكل أساسي +2. **المرحلة الثانية** (نهاية المرحلة 2): نظام استعلام كامل مع مسارات SPARQL و Cypher +3. **المرحلة الثالثة** (نهاية المرحلة 3): نظام مُحسَّن وموثوق به وجاهز للمرحلة التجريبية +4. **المرحلة الرابعة** (نهاية المرحلة 4): نظام جاهز للإنتاج مع ميزات متقدمة + +### تخفيف المخاطر + +#### المخاطر الفنية +**قابلية توسع مخزن المتجهات**: ابدأ بـ NumPy، وانتقل تدريجيًا إلى FAISS +**دقة توليد الاستعلامات**: تنفيذ آليات التحقق والحلول البديلة +**توافق الواجهة الخلفية**: الاختبار بشكل مكثف مع كل نوع قاعدة بيانات +**عقبات الأداء**: التحليل المبكر والمتكرر، والتحسين بشكل تكراري + +#### المخاطر التشغيلية +**جودة علم الوجود**: تنفيذ التحقق من الصحة والاتساق +**تبعيات الخدمة**: إضافة قواطع الدائرة والحلول البديلة +**قيود الموارد**: المراقبة وتعيين الحدود المناسبة +**اتساق البيانات**: تنفيذ معالجة المعاملات المناسبة + +### مقاييس النجاح + +#### مقاييس نجاح المرحلة الأولى +دقة الاستخراج: >90% من التوافق مع علم الوجود +سرعة المعالجة: <1 ثانية لكل جزء +وقت تحميل علم الوجود: <10 ثوانٍ +زمن استجابة البحث عن المتجهات: <100 مللي ثانية + +#### مقاييس نجاح المرحلة الثانية +معدل نجاح الاستعلام: >95% +زمن استجابة الاستعلام: <2 ثانية من البداية إلى النهاية +توافق الواجهة الخلفية: 100% لقواعد البيانات المستهدفة +دقة الإجابة: >85% بناءً على البيانات المتاحة + +#### مقاييس نجاح المرحلة الثالثة +وقت تشغيل النظام: >99.9% +معدل التعافي من الأخطاء: >95% +معدل الوصول إلى ذاكرة التخزين المؤقت: >60% +عدد المستخدمين المتزامنين: >100 + +#### مقاييس نجاح المرحلة الرابعة +الاستعلامات متعددة علم الوجود: مدعومة بالكامل +تحسين التوجيه: تقليل زمن الوصول بنسبة 30% +دقة تقييم مستوى الثقة: >90% +نشر الإنتاج: تحديثات بدون توقف + +## المراجع + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.es.md b/docs/tech-specs/ontorag.es.md new file mode 100644 index 00000000..16dfe72b --- /dev/null +++ b/docs/tech-specs/ontorag.es.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: Especificación Técnica de Extracción y Consulta de Conocimiento Basada en Ontologías" +parent: "Spanish (Beta)" +--- + +# OntoRAG: Especificación Técnica de Extracción y Consulta de Conocimiento Basada en Ontologías + +> **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 + +OntoRAG es un sistema de extracción y consulta de conocimiento impulsado por ontologías que impone una coherencia semántica estricta tanto durante la extracción de triples de conocimiento de texto no estructurado como durante la consulta del grafo de conocimiento resultante. Similar a GraphRAG, pero con restricciones de ontología formales, OntoRAG garantiza que todos los triples extraídos cumplan con estructuras ontológicas predefinidas y proporciona capacidades de consulta con conciencia semántica. + +El sistema utiliza la coincidencia de similitud vectorial para seleccionar dinámicamente subconjuntos de ontología relevantes tanto para las operaciones de extracción como de consulta, lo que permite un procesamiento enfocado y contextualmente apropiado al tiempo que se mantiene la validez semántica. + +**Nombre del Servicio**: `kg-extract-ontology` + +## Objetivos + +**Extracción Conforme a la Ontología**: Asegurar que todos los triples extraídos cumplan estrictamente con las ontologías cargadas. +**Selección de Contexto Dinámico**: Utilizar incrustaciones para seleccionar subconjuntos de ontología relevantes para cada fragmento. +**Coherencia Semántica**: Mantener jerarquías de clases, dominios/rangos de propiedades y restricciones. +**Procesamiento Eficiente**: Utilizar almacenes vectoriales en memoria para una coincidencia rápida de elementos de la ontología. +**Arquitectura Escalable**: Soporte para múltiples ontologías concurrentes con diferentes dominios. + +## Antecedentes + +Los servicios actuales de extracción de conocimiento (`kg-extract-definitions`, `kg-extract-relationships`) operan sin restricciones formales, lo que podría generar triples inconsistentes o incompatibles. OntoRAG aborda esto mediante: + +1. Carga de ontologías formales que definen clases y propiedades válidas. +2. Utilización de incrustaciones para hacer coincidir el contenido de texto con elementos de ontología relevantes. +3. Restricción de la extracción para producir solo triples conformes a la ontología. +4. Provisión de validación semántica del conocimiento extraído. + +Este enfoque combina la flexibilidad de la extracción neuronal con la rigurosidad de la representación formal del conocimiento. + +## Diseño Técnico + +### Arquitectura + +El sistema OntoRAG consta de los siguientes componentes: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### Detalles del Componente + +#### 1. Carga de Ontologías + +**Propósito**: Recupera y analiza las configuraciones de ontologías desde el servicio de configuración utilizando actualizaciones basadas en eventos. + +**Implementación**: +El cargador de ontologías utiliza la cola ConfigPush de TrustGraph para recibir actualizaciones de configuración de ontologías basadas en eventos. Cuando se agrega o modifica un elemento de configuración de tipo "ontología", el cargador recibe la actualización a través de la cola config-update y analiza la estructura JSON que contiene metadatos, clases, propiedades de objeto y propiedades de tipo de datos. Estas ontologías analizadas se almacenan en la memoria como objetos estructurados que se pueden acceder de forma eficiente durante el proceso de extracción. + +**Operaciones Clave**: +Suscribirse a la cola config-update para configuraciones de tipo ontología +Analizar estructuras JSON de ontologías en objetos OntologyClass y OntologyProperty +Validar la estructura y la coherencia de la ontología +Almacenar en caché las ontologías analizadas en la memoria para un acceso rápido +Manejar el procesamiento por flujo con almacenes de vectores específicos del flujo + +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. Incrustador de Ontologías + +**Propósito**: Crea incrustaciones vectoriales para todos los elementos de la ontología para habilitar la coincidencia de similitud semántica. + +**Implementación**: +El incrustador de ontologías procesa cada elemento en las ontologías cargadas (clases, propiedades de objeto y propiedades de tipo de datos) y genera incrustaciones vectoriales utilizando el servicio EmbeddingsClientSpec. Para cada elemento, combina el identificador del elemento, las etiquetas y la descripción (comentario) para crear una representación de texto. Este texto se convierte luego en una incrustación vectorial de alta dimensión que captura su significado semántico. Estas incrustaciones se almacenan en un almacén de vectores FAISS en la memoria, específico de cada flujo, junto con metadatos sobre el tipo de elemento, la ontología de origen y la definición completa. El incrustador detecta automáticamente la dimensión de la incrustación a partir de la primera respuesta de la incrustación. + +**Operaciones Clave**: +Crear representaciones de texto a partir de ID de elementos, etiquetas y comentarios +Generar incrustaciones a través de EmbeddingsClientSpec (utilizando asyncio.gather para el procesamiento por lotes) +Almacenar incrustaciones con metadatos completos en el almacén de vectores FAISS +Indexar por ontología, tipo de elemento y ID de elemento para una recuperación eficiente +Detectar automáticamente las dimensiones de la incrustación para la inicialización del almacén de vectores +Manejar modelos de incrustación específicos del flujo con almacenes de vectores independientes + +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. Procesador de Texto (Divisor de Oraciones) + +**Propósito**: Descompone los fragmentos de texto en segmentos granulares para una coincidencia precisa de ontologías. + +**Implementación**: +El procesador de texto utiliza NLTK para la tokenización de oraciones y el etiquetado POS para dividir los fragmentos de texto entrantes en oraciones. Maneja la compatibilidad de la versión de NLTK intentando descargar `punkt_tab` y `averaged_perceptron_tagger_eng`, con retrocesos a versiones anteriores si es necesario. Cada fragmento de texto se divide en oraciones individuales que se pueden hacer coincidir de forma independiente con los elementos de la ontología. + +**Operaciones Clave**: +Dividir el texto en oraciones utilizando la tokenización de oraciones de NLTK +Manejar la compatibilidad de la versión de NLTK (punkt_tab vs punkt) +Crear objetos TextSegment con texto e información de posición +Soporte tanto para oraciones completas como para fragmentos individuales + +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. Selector de Ontologías + +**Propósito**: Identifica el subconjunto más relevante de elementos de la ontología para el fragmento de texto actual. + +**Implementación**: +El selector de ontologías realiza una coincidencia semántica entre los segmentos de texto y los elementos de la ontología utilizando la búsqueda de similitud vectorial FAISS. Para cada oración del fragmento de texto, genera una incrustación y busca en el almacén de vectores los elementos de la ontología más similares utilizando la similitud coseno con un umbral configurable (por defecto 0.3). Después de recopilar todos los elementos relevantes, realiza una resolución de dependencias integral: si se selecciona una clase, se incluyen sus clases padre; si se selecciona una propiedad, se agregan sus clases de dominio y rango. Además, para cada clase seleccionada, incluye automáticamente **todas las propiedades que hacen referencia a esa clase** en su dominio o rango. Esto asegura que la extracción tenga acceso a todas las propiedades relevantes de la relación. + +**Operaciones Clave**: +Generar incrustaciones para cada segmento de texto (oraciones) +Realizar una búsqueda de vecinos más cercanos en el almacén vectorial FAISS (top_k=10, threshold=0.3) +Aplicar un umbral de similitud para filtrar coincidencias débiles +Resolver dependencias (clases padre, dominios, rangos) +**Incluir automáticamente todas las propiedades relacionadas con las clases seleccionadas** (coincidencia de dominio/rango) +Construir un subconjunto de ontología coherente con todas las relaciones requeridas +Eliminar elementos duplicados que aparecen varias veces + +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. Construcción de la Consulta (Prompt) + +**Propósito**: Crea consultas estructuradas que guían al LLM para extraer solo triples conformes a la ontología. + +**Implementación**: +El servicio de extracción utiliza una plantilla Jinja2 cargada desde `ontology-prompt.md` que formatea el subconjunto de la ontología y el texto para la extracción del LLM. La plantilla itera dinámicamente sobre clases, propiedades de objeto y propiedades de tipo de datos utilizando la sintaxis de Jinja2, presentando cada una con sus descripciones, dominios, rangos y relaciones jerárquicas. La consulta incluye reglas estrictas sobre el uso únicamente de los elementos de la ontología proporcionados y solicita un formato de salida JSON para un análisis coherente. + +**Operaciones Clave**: +Utilizar una plantilla Jinja2 con bucles sobre los elementos de la ontología +Formatear clases con relaciones padre (subclass_of) y comentarios +Formatear propiedades con restricciones de dominio/rango y comentarios +Incluir reglas de extracción explícitas y requisitos de formato de salida +Llamar al servicio de consulta con el ID de la plantilla "extract-with-ontologies" + +**Ubicación de la Plantilla**: `ontology-prompt.md` +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (método build_extraction_variables) + +#### 6. Servicio de Extracción Principal + +**Propósito**: Coordina todos los componentes para realizar la extracción de triples basada en la ontología de extremo a extremo. + +**Implementación**: +El Servicio de Extracción Principal (KgExtractOntology) es la capa de orquestación que gestiona el flujo de trabajo completo de extracción. Utiliza el patrón FlowProcessor de TrustGraph con inicialización de componentes específicos del flujo. Cuando llega una actualización de la configuración de la ontología, inicializa o actualiza los componentes específicos del flujo (cargador de ontología, incrustador, procesador de texto, selector). Cuando llega un fragmento de texto para su procesamiento, coordina la canalización: divide el texto en segmentos, encuentra elementos de ontología relevantes mediante búsqueda vectorial, construye una consulta restringida, llama al servicio de consulta, analiza y valida la respuesta, genera triples de definición de ontología y emite tanto triples de contenido como contextos de entidades. + +**Canalización de Extracción**: +1. Recibir un fragmento de texto a través de la cola chunks-input +2. Inicializar los componentes del flujo si es necesario (en el primer fragmento o en la actualización de la configuración) +3. Dividir el texto en oraciones utilizando NLTK +4. Buscar en el almacén vectorial FAISS para encontrar conceptos de ontología relevantes +5. Construir un subconjunto de ontología con inclusión automática de propiedades +6. Construir variables de consulta Jinja2 +7. Llamar al servicio de consulta con la plantilla extract-with-ontologies +8. Analizar la respuesta JSON en triples estructurados +9. Validar los triples y expandir los URIs a URIs completos de la ontología +10. Generar triples de definición de ontología (clases y propiedades con etiquetas/comentarios/dominios/rangos) +11. Construir contextos de entidades a partir de todos los triples +12. Emitir a las colas de triples y contextos de entidades + +**Características Clave**: +Almacenes vectoriales específicos del flujo que admiten diferentes modelos de incrustación +Actualizaciones de ontología basadas en eventos a través de la cola config-update +Expansión automática de URIs utilizando URIs de ontología +Elementos de ontología añadidos al grafo de conocimiento con metadatos completos +Los contextos de entidades incluyen tanto elementos de contenido como de ontología + +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### Configuración + +El servicio utiliza el enfoque de configuración estándar de TrustGraph con argumentos de línea de comandos: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**Parámetros de Configuración Clave**: +`similarity_threshold`: 0.3 (predeterminado, configurable en el código) +`top_k`: 10 (número de elementos de la ontología a recuperar por segmento) +`vector_store`: Índice FAISS FlatIP por flujo con detección automática de dimensiones +`text_processor`: NLTK con tokenización de oraciones punkt_tab +`prompt_template`: "extract-with-ontologies" (plantilla Jinja2) + +**Configuración de la Ontología**: +Las ontologías se cargan dinámicamente a través de la cola de actualización de configuración con el tipo "ontology". + +### Flujo de Datos + +1. **Fase de Inicialización** (por flujo): + Recibir la configuración de la ontología a través de la cola de actualización de configuración + Analizar el JSON de la ontología en objetos OntologyClass y OntologyProperty + Generar incrustaciones para todos los elementos de la ontología utilizando EmbeddingsClientSpec + Almacenar las incrustaciones en el almacén de vectores FAISS específico de cada flujo + Detectar automáticamente las dimensiones de la incrustación a partir de la primera respuesta + +2. **Fase de Extracción** (por fragmento): + Recibir un fragmento de la cola chunks-input + Dividir el fragmento en oraciones utilizando NLTK + Calcular las incrustaciones para cada oración + Buscar en el almacén de vectores FAISS los elementos de la ontología relevantes + Construir un subconjunto de la ontología con inclusión automática de propiedades + Construir variables de plantilla Jinja2 con texto y ontología + Llamar al servicio de solicitud con la plantilla extract-with-ontologías + Analizar la respuesta JSON y validar las triples + Expandir los URIs utilizando los URIs de la ontología + Generar triples de definición de ontología + Construir contextos de entidades a partir de todas las triples + Emitir a las colas de triples y entity-contexts + +### Almacén de Vectores en Memoria + +**Propósito**: Proporciona una búsqueda de similitud rápida y basada en memoria para la coincidencia de elementos de la ontología. + +**Implementación: FAISS** + +El sistema utiliza **FAISS (Facebook AI Similarity Search)** con IndexFlatIP para la búsqueda de similitud coseno exacta. Características clave: + +**IndexFlatIP**: Búsqueda de similitud coseno exacta utilizando el producto interno +**Detección automática**: La dimensión se determina a partir de la primera respuesta de incrustación +**Almacenes por flujo**: Cada flujo tiene un almacén de vectores independiente para diferentes modelos de incrustación +**Normalización**: Todos los vectores se normalizan antes de la indexación +**Operaciones por lotes**: Adición por lotes eficiente para la carga inicial de la ontología + +**Ubicación de la Implementación**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### Algoritmo de Selección de Subconjunto de Ontología + +**Propósito**: Selecciona dinámicamente la porción relevante mínima de la ontología para cada fragmento de texto. + +**Pasos Detallados del Algoritmo**: + +1. **Segmentación de Texto**: + Dividir el fragmento de entrada en oraciones utilizando la detección de oraciones de NLP + Extraer frases nominales, frases verbales y entidades nombradas de cada oración + Crear una estructura jerárquica de segmentos que preserve el contexto + +2. **Generación de Incrustaciones**: + Generar incrustaciones vectoriales para cada segmento de texto (oraciones y frases) + Utilizar el mismo modelo de incrustación que se utiliza para los elementos de la ontología + Almacenar en caché las incrustaciones para los segmentos repetidos para mejorar el rendimiento + +3. **Búsqueda de Similitud**: + Para cada incrustación de segmento de texto, buscar en el almacén de vectores + Recuperar los k elementos de la ontología más similares (por ejemplo, 10) + Aplicar un umbral de similitud (por ejemplo, 0.7) para filtrar las coincidencias débiles + Agregar los resultados en todos los segmentos, rastreando las frecuencias de coincidencia + +4. **Resolución de Dependencias**: + Para cada clase seleccionada, incluir recursivamente todas las clases padre hasta la raíz + Para cada propiedad seleccionada, incluir las clases de dominio y rango + Para las propiedades inversas, asegurarse de incluir ambas direcciones + Agregar clases equivalentes si existen en la ontología + +5. **Construcción del Subconjunto**: + Desduplicar los elementos recopilados mientras se preservan las relaciones + Organizar en clases, propiedades de objeto y propiedades de tipo de datos + Asegurarse de que todas las restricciones y relaciones se preserven + Crear una mini-ontología autocontenida que sea válida y completa + +**Ejemplo de Demostración**: +Dado el texto: "The brown dog chased the white cat up the tree." +Segmentos: ["brown dog", "white cat", "tree", "chased"] +Elementos coincidentes: [dog (class), cat (class), animal (parent), chases (property)] +Dependencias: [animal (parent of dog and cat), lifeform (parent of animal)] +Subconjunto final: Mini-ontología completa con la jerarquía de animales y la relación de persecución + +### Validación de Triples + +**Propósito**: Asegura que todas las triples extraídas cumplan estrictamente con las restricciones de la ontología. + +**Algoritmo de Validación**: + +1. **Validación de Clases**: + Verificar que los sujetos sean instancias de clases definidas en el subconjunto de la ontología. + Para las propiedades de objeto, verificar que los objetos también sean instancias de clases válidas. + Comprobar los nombres de las clases contra el diccionario de clases de la ontología. + Manejar las jerarquías de clases: las instancias de subclases son válidas para las restricciones de la clase principal. + +2. **Validación de Propiedades**: + Confirmar que los predicados corresponden a las propiedades del subconjunto de la ontología. + Distinguir entre propiedades de objeto (entidad a entidad) y propiedades de tipo de datos (entidad a literal). + Verificar que los nombres de las propiedades coincidan exactamente (considerando el espacio de nombres si está presente). + +3. **Comprobación de Dominio/Rango**: + Para cada propiedad utilizada como predicado, recuperar su dominio y rango. + Verificar que el tipo del sujeto coincida o herede del dominio de la propiedad. + Verificar que el tipo del objeto coincida o herede del rango de la propiedad. + Para las propiedades de tipo de datos, verificar que el objeto sea un literal del tipo XSD correcto. + +4. **Validación de Cardinalidad**: + Registrar los recuentos de uso de la propiedad por sujeto. + Comprobar la cardinalidad mínima: asegurarse de que las propiedades requeridas estén presentes. + Comprobar la cardinalidad máxima: asegurarse de que la propiedad no se utilice demasiadas veces. + Para las propiedades funcionales, asegurarse de que haya como máximo un valor por sujeto. + +5. **Validación de Tipos de Datos**: + Analizar los valores literales según sus tipos XSD declarados. + Validar que los enteros sean números válidos, que las fechas tengan un formato correcto, etc. + Comprobar los patrones de cadena si se definen restricciones de expresión regular. + Asegurarse de que las URIs estén bien formadas para los tipos xsd:anyURI. + +**Ejemplo de Validación**: +Triple: ("Buddy", "tiene-dueño", "John") +Comprobar que "Buddy" esté tipado como una clase que puede tener la propiedad "tiene-dueño". +Comprobar que "tiene-dueño" exista en la ontología. +Verificar la restricción de dominio: el sujeto debe ser de tipo "Mascota" o subclase. +Verificar la restricción de rango: el objeto debe ser de tipo "Persona" o subclase. +Si es válido, agregar a la salida; si no es válido, registrar la violación y omitir. + +## Consideraciones de Rendimiento + +### Estrategias de Optimización + +1. **Caché de Incrustaciones**: Almacenar en caché las incrustaciones para segmentos de texto utilizados con frecuencia. +2. **Procesamiento por Lotes**: Procesar múltiples segmentos en paralelo. +3. **Indexación de Almacenes Vectoriales**: Utilizar algoritmos de vecinos más cercanos aproximados para ontologías grandes. +4. **Optimización de Indicaciones**: Minimizar el tamaño de la indicación incluyendo solo los elementos esenciales de la ontología. +5. **Caché de Resultados**: Almacenar en caché los resultados de la extracción para fragmentos idénticos. + +### Escalabilidad + +**Escalabilidad Horizontal**: Múltiples instancias del extractor con un caché de ontología compartido. +**Partición de Ontologías**: Dividir ontologías grandes por dominio. +**Procesamiento por Transmisión**: Procesar fragmentos a medida que llegan sin agruparlos. +**Gestión de Memoria**: Limpieza periódica de incrustaciones no utilizadas. + +## Manejo de Errores + +### Escenarios de Fallo + +1. **Ontologías Faltantes**: Recurrir a la extracción sin restricciones. +2. **Fallo del Servicio de Incrustaciones**: Utilizar incrustaciones almacenadas en caché o omitir la coincidencia semántica. +3. **Tiempo de Espera del Servicio de Indicaciones**: Reintentar con retroceso exponencial. +4. **Formato de Triple Inválido**: Registrar y omitir triples mal formados. +5. **Inconsistencias de la Ontología**: Informar de conflictos y utilizar los elementos válidos más específicos. + +### Monitorización + +Métricas clave a seguir: + +Tiempo de carga de la ontología y uso de memoria. +Latencia de generación de incrustaciones. +Rendimiento de la búsqueda vectorial. +Tiempo de respuesta del servicio de indicaciones. +Precisión de la extracción de triples. +Tasa de conformidad de la ontología. + +## Ruta de Migración + +### Desde Extractores Existentes + +1. **Operación Paralela**: Ejecutar junto con los extractores existentes inicialmente. +2. **Implementación Gradual**: Comenzar con tipos de documentos específicos. +3. **Comparación de Calidad**: Comparar la calidad de la salida con los extractores existentes. +4. **Migración Completa**: Reemplazar los extractores existentes una vez que se haya verificado la calidad. + +### Desarrollo de Ontologías + +1. **Generación Inicial desde Conocimiento Existente**: Generar ontologías iniciales a partir de conocimiento existente. +2. **Refinamiento Iterativo**: Refinar basándose en patrones de extracción. +3. **Revisión por Expertos en la Materia**: Validar con expertos en la materia. +4. **Mejora Continua**: Actualizar basándose en la retroalimentación de la extracción. + +## Servicio de Consulta Sensible a la Ontología + +### Descripción General + +El servicio de consulta sensible a la ontología proporciona múltiples rutas de consulta para admitir diferentes almacenes de grafos de backend. Aprovecha el conocimiento de la ontología para una respuesta a preguntas precisa y semánticamente consciente en diferentes almacenes de grafos, tanto Cassandra (a través de SPARQL) como almacenes de grafos basados en Cypher (Neo4j, Memgraph, FalkorDB). + +**Componentes del Servicio**: +`onto-query-sparql`: Convierte el lenguaje natural a SPARQL para Cassandra. +`sparql-cassandra`: Capa de consulta SPARQL para Cassandra que utiliza rdflib. +`onto-query-cypher`: Convierte el lenguaje natural a Cypher para bases de datos de grafos. +`cypher-executor`: Ejecución de consultas Cypher para Neo4j/Memgraph/FalkorDB. + +### Arquitectura + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### Query Processing Pipeline + +#### 1. Question Analyser + +**Purpose**: Decomposes user questions into semantic components for ontology matching. + +**Algorithm Description**: +The Question Analyser takes the incoming natural language question and breaks it down into meaningful segments using the same sentence splitting approach as the extraction pipeline. It identifies key entities, relationships, and constraints mentioned in the question. Each segment is analysed for question type (factual, aggregation, comparison, etc.) and the expected answer format. This decomposition helps identify which parts of the ontology are most relevant for answering the question. + +**Key Operations**: +Split question into sentences and phrases +Identify question type and intent +Extract mentioned entities and relationships +Detect constraints and filters in the question +Determine expected answer format + +#### 2. Ontology Matcher for Queries + +**Purpose**: Identifies the relevant ontology subset needed to answer the question. + +**Algorithm Description**: +Similar to the extraction pipeline's Ontology Selector, but optimised for question answering. The matcher generates embeddings for question segments and searches the vector store for relevant ontology elements. However, it focuses on finding concepts that would be useful for query construction rather than extraction. It expands the selection to include related properties that might be traversed during graph exploration, even if not explicitly mentioned in the question. For example, if asked about "employees," it might include properties like "works-for," "manages," and "reports-to" that could be relevant for finding employee information. + +**Matching Strategy**: +Embed question segments +Find directly mentioned ontology concepts +Include properties that connect mentioned classes +Add inverse and related properties for traversal +Include parent/child classes for hierarchical queries +Build query-focused ontology partition + +#### 3. Backend Router + +**Purpose**: Routes queries to the appropriate backend-specific query path based on configuration. + +**Algorithm Description**: +The Backend Router examines the system configuration to determine which graph backend is active (Cassandra or Cypher-based). It routes the question and ontology partition to the appropriate query generation service. The router can also support load balancing across multiple backends or fallback mechanisms if the primary backend is unavailable. + +**Routing Logic**: +Check configured backend type from system settings +Route to `onto-query-sparql` for Cassandra backends +Route to `onto-query-cypher` for Neo4j/Memgraph/FalkorDB +Support multi-backend configurations with query distribution +Handle failover and load balancing scenarios + +#### 4. SPARQL Query Generation (`onto-query-sparql`) + +**Purpose**: Converts natural language questions to SPARQL queries for Cassandra execution. + +**Algorithm Description**: +The SPARQL query generator takes the question and ontology partition and constructs a SPARQL query optimised for execution against the Cassandra backend. It uses the prompt service with a SPARQL-specific template that includes RDF/OWL semantics. The generator understands SPARQL patterns like property paths, optional clauses, and filters that can efficiently translate to Cassandra operations. + +**SPARQL Generation Prompt Template**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. Generación de Consultas Cypher (`onto-query-cypher`) + +**Propósito**: Convierte preguntas en lenguaje natural en consultas Cypher para bases de datos de grafos. + +**Descripción del Algoritmo**: +El generador de consultas Cypher crea consultas Cypher nativas optimizadas para Neo4j, Memgraph y FalkorDB. Mapea clases de ontología a etiquetas de nodos y propiedades a relaciones, utilizando la sintaxis de coincidencia de patrones de Cypher. El generador incluye optimizaciones específicas de Cypher, como sugerencias de dirección de relación, uso de índices y sugerencias de planificación de consultas. + +**Plantilla de Indicación para la Generación de Cypher**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. Motor de Consulta SPARQL-Cassandra (`sparql-cassandra`) + +**Propósito**: Ejecuta consultas SPARQL contra Cassandra utilizando Python rdflib. + +**Descripción del Algoritmo**: +El motor SPARQL-Cassandra implementa un procesador SPARQL utilizando la biblioteca rdflib de Python con un almacenamiento backend personalizado para Cassandra. Traduce los patrones de grafo SPARQL en consultas CQL de Cassandra apropiadas, manejando uniones, filtros y agregaciones. El motor mantiene un mapeo de RDF a Cassandra que preserva la estructura semántica al tiempo que optimiza para el modelo de almacenamiento de familias de columnas de Cassandra. + +**Características de la Implementación**: +Implementación de la interfaz de almacenamiento rdflib para Cassandra +Soporte para consultas SPARQL 1.1 con patrones comunes +Traducción eficiente de patrones de triple a CQL +Soporte para rutas de propiedades y consultas jerárquicas +Transmisión de resultados para conjuntos de datos grandes +Agrupación de conexiones y almacenamiento en caché de consultas + +**Ejemplo de Traducción**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +Traduce a consultas optimizadas de Cassandra que aprovechan los índices y las claves de partición. + +#### 7. Ejecutor de Consultas Cypher (`cypher-executor`) + +**Propósito**: Ejecuta consultas Cypher contra Neo4j, Memgraph y FalkorDB. + +**Descripción del Algoritmo**: +El ejecutor de Cypher proporciona una interfaz unificada para ejecutar consultas Cypher en diferentes bases de datos de grafos. Maneja protocolos de conexión específicos de la base de datos, sugerencias de optimización de consultas y normalización del formato de resultados. El ejecutor incluye lógica de reintento, agrupación de conexiones y gestión de transacciones adecuadas para cada tipo de base de datos. + +**Soporte para Múltiples Bases de Datos**: +**Neo4j**: Protocolo Bolt, funciones de transacción, sugerencias de índice +**Memgraph**: Protocolo personalizado, resultados de transmisión, consultas analíticas +**FalkorDB**: Adaptación del protocolo Redis, optimizaciones en memoria + +**Características de Ejecución**: +Gestión de conexiones independiente de la base de datos +Validación de consultas y verificación de sintaxis +Aplicación de límites de tiempo y recursos +Paginación y transmisión de resultados +Monitoreo de rendimiento por tipo de base de datos +Conmutación por error automática entre instancias de base de datos + +#### 8. Generador de Respuestas + +**Propósito**: Sintetiza una respuesta en lenguaje natural a partir de los resultados de la consulta. + +**Descripción del Algoritmo**: +El Generador de Respuestas toma los resultados de la consulta estructurados y la pregunta original, y luego utiliza el servicio de prompts para generar una respuesta completa. A diferencia de las respuestas simples basadas en plantillas, utiliza un LLM para interpretar los datos del grafo en el contexto de la pregunta, manejando relaciones complejas, agregaciones y inferencias. El generador puede explicar su razonamiento haciendo referencia a la estructura de la ontología y a los triples específicos recuperados del grafo. + +**Proceso de Generación de Respuestas**: +Formatea los resultados de la consulta en un contexto estructurado +Incluye definiciones de ontología relevantes para mayor claridad +Construye un prompt con la pregunta y los resultados +Genera una respuesta en lenguaje natural mediante un LLM +Valida la respuesta con respecto a la intención de la consulta +Agrega citas a entidades específicas del grafo si es necesario + +### Integración con Servicios Existentes + +#### Relación con GraphRAG + +**Complementario**: onto-query proporciona precisión semántica mientras que GraphRAG proporciona una cobertura amplia +**Infraestructura Compartida**: Ambos utilizan el mismo grafo de conocimiento y servicios de prompts +**Enrutamiento de Consultas**: El sistema puede enrutar las consultas al servicio más apropiado según el tipo de pregunta +**Modo Híbrido**: Puede combinar ambos enfoques para obtener respuestas completas + +#### Relación con OntoRAG Extraction + +**Ontologías Compartidas**: Utiliza las mismas configuraciones de ontología cargadas por kg-extract-ontology +**Almacén de Vectores Compartido**: Reutiliza los embeddings en memoria del servicio de extracción +**Semántica Consistente**: Las consultas operan en grafos construidos con las mismas restricciones ontológicas + +### Ejemplos de Consultas + +#### Ejemplo 1: Consulta Simple de Entidad +**Pregunta**: "¿Qué animales son mamíferos?" +**Coincidencia de Ontología**: [animal, mammal, subClassOf] +**Consulta Generada**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### Ejemplo 2: Consulta de Relación +**Pregunta**: "¿Qué documentos fueron escritos por John Smith?" +**Correspondencia con la Ontología**: [documento, persona, tiene-autor] +**Consulta Generada**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### Ejemplo 3: Consulta de agregación +**Pregunta**: "¿Cuántas patas tienen los gatos?" +**Coincidencia con la ontología**: [gato, número-de-patas (propiedad de tipo de dato)] +**Consulta generada**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### Configuración + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### Optimizaciones de rendimiento + +#### Optimización de consultas + +**Poda de la ontología**: Incluir solo los elementos de la ontología necesarios en las indicaciones. +**Caché de consultas**: Almacenar en caché las preguntas frecuentes y sus consultas. +**Caché de resultados**: Almacenar los resultados para consultas idénticas dentro de un intervalo de tiempo. +**Procesamiento por lotes**: Manejar múltiples preguntas relacionadas en una sola exploración del grafo. + +#### Consideraciones de escalabilidad + +**Ejecución distribuida**: Paralelizar subconsultas en particiones del grafo. +**Resultados incrementales**: Transmitir los resultados para conjuntos de datos grandes. +**Equilibrio de carga**: Distribuir la carga de las consultas entre múltiples instancias de servicio. +**Grupos de recursos**: Administrar grupos de conexiones a bases de datos de grafos. + +### Manejo de errores + +#### Escenarios de fallo + +1. **Generación de consultas inválidas**: Revertir a GraphRAG o a una búsqueda simple por palabras clave. +2. **Desajuste de la ontología**: Ampliar la búsqueda a un subconjunto más amplio de la ontología. +3. **Tiempo de espera de la consulta**: Simplificar la consulta o aumentar el tiempo de espera. +4. **Resultados vacíos**: Sugerir la reformulación de la consulta o preguntas relacionadas. +5. **Fallo del servicio LLM**: Utilizar consultas almacenadas en caché o respuestas basadas en plantillas. + +### Métricas de monitoreo + +Distribución de la complejidad de las preguntas. +Tamaños de las particiones de la ontología. +Tasa de éxito de la generación de consultas. +Tiempo de ejecución de las consultas al grafo. +Puntuaciones de calidad de las respuestas. +Tasas de aciertos de la caché. +Frecuencias de error por tipo. + +## Mejoras futuras + +1. **Aprendizaje de la ontología**: Extender automáticamente las ontologías basándose en patrones de extracción. +2. **Puntuación de confianza**: Asignar puntuaciones de confianza a las triples extraídas. +3. **Generación de explicaciones**: Proporcionar la justificación para la extracción de triples. +4. **Aprendizaje activo**: Solicitar la validación humana para las extracciones inciertas. + +## Consideraciones de seguridad + +1. **Prevención de la inyección de indicaciones**: Sanitizar el texto de los fragmentos antes de construir la indicación. +2. **Límites de recursos**: Limitar el uso de memoria para el almacén de vectores. +3. **Limitación de velocidad**: Limitar las solicitudes de extracción por cliente. +4. **Registro de auditoría**: Registrar todas las solicitudes y resultados de extracción. + +## Estrategia de pruebas + +### Pruebas unitarias + +Carga de ontología con varios formatos. +Generación y almacenamiento de incrustaciones. +Algoritmos de división de oraciones. +Cálculos de similitud vectorial. +Análisis y validación de triples. + +### Pruebas de integración + +Canalización de extracción de extremo a extremo. +Integración del servicio de configuración. +Interacción con el servicio de indicaciones. +Manejo de extracción concurrente. + +### Pruebas de rendimiento + +Manejo de ontologías grandes (1000+ clases). +Procesamiento de gran volumen de fragmentos. +Uso de memoria bajo carga. +Referencias de latencia. + +## Plan de entrega + +### Resumen + +El sistema OntoRAG se entregará en cuatro fases principales, con cada fase proporcionando valor incremental mientras se construye hacia el sistema completo. El plan se centra en establecer primero las capacidades básicas de extracción, luego agregar la funcionalidad de consulta, seguida de optimizaciones y funciones avanzadas. + +### Fase 1: Fundación y extracción central + +**Objetivo**: Establecer la canalización básica de extracción impulsada por la ontología con el simple emparejamiento de vectores. + +#### Paso 1.1: Fundación de la gestión de la ontología +Implementar el cargador de configuración de la ontología (`OntologyLoader`). +Analizar y validar las estructuras JSON de la ontología. +Crear un almacenamiento de ontología en memoria y patrones de acceso. +Implementar un mecanismo de actualización de la ontología. + +**Criterios de éxito**: +Cargar y analizar correctamente las configuraciones de la ontología. +Validar la estructura y la coherencia de la ontología. +Manejar múltiples ontologías concurrentes. + +#### Paso 1.2: Implementación del almacén de vectores +Implementar un almacén de vectores simple basado en NumPy como prototipo inicial. +Agregar la implementación del almacén de vectores FAISS. +Crear una abstracción de interfaz para el almacén de vectores. +Implementar la búsqueda de similitud con umbrales configurables. + +**Criterios de Éxito**: +Almacenar y recuperar incrustaciones de manera eficiente +Realizar búsquedas de similitud con una latencia menor a 100 ms +Soporte para backends NumPy y FAISS + +#### Paso 1.3: Canal de Incrustación de Ontologías +Integración con el servicio de incrustación +Implementar componente `OntologyEmbedder` +Generar incrustaciones para todos los elementos de la ontología +Almacenar las incrustaciones con metadatos en el almacén de vectores + +**Criterios de Éxito**: +Generar incrustaciones para clases y propiedades +Almacenar las incrustaciones con los metadatos correctos +Reconstruir las incrustaciones al actualizar la ontología + +#### Paso 1.4: Componentes de Procesamiento de Texto +Implementar un divisor de oraciones utilizando NLTK/spaCy +Extraer frases y entidades nombradas +Crear una jerarquía de segmentos de texto +Generar incrustaciones para los segmentos de texto + +**Criterios de Éxito**: +Dividir el texto en oraciones de forma precisa +Extraer frases significativas +Mantener las relaciones de contexto + +#### Paso 1.5: Algoritmo de Selección de Ontología +Implementar la coincidencia de similitud entre el texto y la ontología +Construir la resolución de dependencias para los elementos de la ontología +Crear subconjuntos coherentes mínimos de la ontología +Optimizar el rendimiento de la generación de subconjuntos + +**Criterios de Éxito**: +Seleccionar elementos de la ontología relevantes con una precisión >80% +Incluir todas las dependencias necesarias +Generar subconjuntos en <500 ms + +#### Paso 1.6: Servicio de Extracción Básico +Implementar la construcción de indicaciones para la extracción +Integración con el servicio de indicaciones +Analizar y validar las respuestas de triple +Crear un punto final de servicio `kg-extract-ontology` + +**Criterios de Éxito**: +Extraer triples conformes a la ontología +Validar todos los triples contra la ontología +Manejar los errores de extracción de forma elegante + +### Fase 2: Implementación del Sistema de Consulta + +**Objetivo**: Agregar capacidades de consulta con conocimiento de la ontología con soporte para múltiples backends. + +#### Paso 2.1: Componentes Fundamentales de la Consulta +Implementar el analizador de preguntas +Crear un comparador de ontologías para las consultas +Adaptar la búsqueda vectorial al contexto de la consulta +Construir el componente de enrutamiento de backends + +**Criterios de Éxito**: +Analizar las preguntas en componentes semánticos +Hacer coincidir las preguntas con los elementos de ontología relevantes +Enrutar las consultas al backend apropiado + +#### Paso 2.2: Implementación de la Ruta SPARQL +Implementar el servicio `onto-query-sparql` +Crear un generador de consultas SPARQL utilizando LLM +Desarrollar plantillas de indicaciones para la generación de SPARQL +Validar la sintaxis SPARQL generada + +**Criterios de Éxito**: +Generar consultas SPARQL válidas +Utilizar patrones SPARQL apropiados +Manejar tipos de consultas complejos + +#### Paso 2.3: Motor SPARQL-Cassandra +Implementar la interfaz de almacenamiento rdflib para Cassandra +Crear un traductor de consultas CQL +Optimizar la coincidencia de patrones de triple +Manejar el formato de resultados de SPARQL + +**Criterios de Éxito**: +Ejecutar consultas SPARQL en Cassandra +Soporte para patrones SPARQL comunes +Devolver resultados en formato estándar + +#### Paso 2.4: Implementación de la Ruta Cypher +Implementar el servicio `onto-query-cypher` +Crear un generador de consultas Cypher utilizando LLM +Desarrollar plantillas de indicaciones para la generación de Cypher +Validar la sintaxis Cypher generada + +**Criterios de Éxito**: +Generar consultas Cypher válidas +Utilizar patrones de grafos apropiados +Soporte para Neo4j, Memgraph, FalkorDB + +#### Paso 2.5: Ejecutor de Cypher +Implement multi-database Cypher executor +Support Bolt protocol (Neo4j/Memgraph) +Support Redis protocol (FalkorDB) +Handle result normalization + +**Success Criteria**: +Execute Cypher on all target databases +Handle database-specific differences +Maintain connection pools efficiently + +#### Step 2.6: Answer Generation +Implement answer generator component +Create prompts for answer synthesis +Format query results for LLM consumption +Generate natural language answers + +**Success Criteria**: +Generate accurate answers from query results +Maintain context from original question +Provide clear, concise responses + +### Phase 3: Optimization and Robustness + +**Goal**: Optimize performance, add caching, improve error handling, and enhance reliability. + +#### Step 3.1: Performance Optimization +Implement embedding caching +Add query result caching +Optimize vector search with FAISS IVF indexes +Implement batch processing for embeddings + +**Success Criteria**: +Reduce average query latency by 50% +Support 10x more concurrent requests +Maintain sub-second response times + +#### Step 3.2: Advanced Error Handling +Implement comprehensive error recovery +Add fallback mechanisms between query paths +Create retry logic with exponential backoff +Improve error logging and diagnostics + +**Success Criteria**: +Gracefully handle all failure scenarios +Automatic failover between backends +Detailed error reporting for debugging + +#### Step 3.3: Monitoring and Observability +Add performance metrics collection +Implement query tracing +Create health check endpoints +Add resource usage monitoring + +**Success Criteria**: +Track all key performance indicators +Identify bottlenecks quickly +Monitor system health in real-time + +#### Step 3.4: Configuration Management +Implement dynamic configuration updates +Add configuration validation +Create configuration templates +Support environment-specific settings + +**Success Criteria**: +Update configuration without restart +Validate all configuration changes +Support multiple deployment environments + +### Phase 4: Advanced Features + +**Goal**: Add sophisticated capabilities for production deployment and enhanced functionality. + +#### Step 4.1: Multi-Ontology Support +Implement ontology selection logic +Support cross-ontology queries +Handle ontology versioning +Create ontology merge capabilities + +**Success Criteria**: +Query across multiple ontologies +Handle ontology conflicts +Support ontology evolution + +#### Step 4.2: Intelligent Query Routing +Implementar enrutamiento basado en el rendimiento +Agregar análisis de complejidad de la consulta +Crear algoritmos de enrutamiento adaptativos +Compatibilizar pruebas A/B para rutas + +**Criterios de éxito**: +Enrutar las consultas de forma óptima +Aprender del rendimiento de las consultas +Mejorar el enrutamiento con el tiempo + +#### Paso 4.3: Características Avanzadas de Extracción +Agregar puntuación de confianza para las triples +Implementar generación de explicaciones +Crear bucles de retroalimentación para la mejora +Compatibilizar aprendizaje incremental + +**Criterios de éxito**: +Proporcionar puntuaciones de confianza +Explicar las decisiones de extracción +Mejorar continuamente la precisión + +#### Paso 4.4: Endurecimiento para Producción +Agregar limitación de velocidad +Implementar autenticación/autorización +Crear automatización de implementación +Agregar copia de seguridad y recuperación + +**Criterios de éxito**: +Seguridad lista para producción +Canal de implementación automatizado +Capacidad de recuperación ante desastres + +### Hitos de Entrega + +1. **Hito 1** (Fin de la Fase 1): Extracción básica basada en la ontología en funcionamiento +2. **Hito 2** (Fin de la Fase 2): Sistema de consulta completo con rutas SPARQL y Cypher +3. **Hito 3** (Fin de la Fase 3): Sistema optimizado y robusto listo para la etapa de pruebas +4. **Hito 4** (Fin de la Fase 4): Sistema listo para producción con características avanzadas + +### Mitigación de Riesgos + +#### Riesgos Técnicos +**Escalabilidad del Almacén de Vectores**: Comenzar con NumPy, migrar gradualmente a FAISS +**Precisión de la Generación de Consultas**: Implementar mecanismos de validación y respaldo +**Compatibilidad con el Backend**: Probar exhaustivamente con cada tipo de base de datos +**Cuellos de Botella de Rendimiento**: Perfil temprano y con frecuencia, optimizar de forma iterativa + +#### Riesgos Operacionales +**Calidad de la Ontología**: Implementar validación y verificación de la consistencia +**Dependencias del Servicio**: Agregar interruptores de circuito y mecanismos de respaldo +**Restricciones de Recursos**: Monitorear y establecer límites apropiados +**Consistencia de Datos**: Implementar un manejo adecuado de transacciones + +### Métricas de Éxito + +#### Métricas de Éxito de la Fase 1 +Precisión de la extracción: >90% de conformidad con la ontología +Velocidad de procesamiento: <1 segundo por fragmento +Tiempo de carga de la ontología: <10 segundos +Latencia de búsqueda de vectores: <100 ms + +#### Métricas de Éxito de la Fase 2 +Tasa de éxito de las consultas: >95% +Latencia de la consulta: <2 segundos de extremo a extremo +Compatibilidad con el backend: 100% para las bases de datos objetivo +Precisión de la respuesta: >85% según los datos disponibles + +#### Métricas de Éxito de la Fase 3 +Tiempo de actividad del sistema: >99.9% +Tasa de recuperación de errores: >95% +Tasa de aciertos en caché: >60% +Usuarios concurrentes: >100 + +#### Métricas de Éxito de la Fase 4 +Consultas multi-ontología: Totalmente compatibles +Optimización del enrutamiento: Reducción de la latencia del 30% +Precisión de la puntuación de confianza: >90% +Implementación en producción: Actualizaciones sin tiempo de inactividad + +## Referencias + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.he.md b/docs/tech-specs/ontorag.he.md new file mode 100644 index 00000000..a534d110 --- /dev/null +++ b/docs/tech-specs/ontorag.he.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: מפרט טכני לחילוץ ידע מבוסס אונטולוגיה ושליפת שאילתות" +parent: "Hebrew (Beta)" +--- + +# OntoRAG: מפרט טכני לחילוץ ידע מבוסס אונטולוגיה ושליפת שאילתות + +> **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. + +## סקירה כללית + +OntoRAG היא מערכת לחילוץ ידע ושליפת שאילתות המונעת על ידי אונטולוגיה, המאכפת עקביות סמנטית קפדנית במהלך חילוץ משולשים של ידע מטקסט לא מובנה וכן במהלך שליפת שאילתות מגרף הידע המתקבל. בדומה ל-GraphRAG, אך עם אילוצי אונטולוגיה פורמליים, OntoRAG מבטיחה שכל המשולשים החילוצים תואמים למבנים אונטולוגיים מוגדרים מראש ומספקת יכולות שליפת שאילתות מודעות לסמנטיקה. + +המערכת משתמשת בהתאמת דמיון וקטורי כדי לבחור דינמית תת-קבוצות רלוונטיות של אונטולוגיות הן עבור פעולות חילוץ והן עבור פעולות שליפה, ומאפשרת עיבוד ממוקד ומתאים להקשר תוך שמירה על תוקף סמנטי. + +**שם השירות**: `kg-extract-ontology` + +## מטרות + +**חילוץ התואם לאונטולוגיה**: להבטיח שכל המשולשים החילוצים תואמים באופן קפדני לאונטולוגיות הטעונות. +**בחירת הקשר דינמית**: להשתמש בהטבעות כדי לבחור תת-קבוצות רלוונטיות של אונטולוגיות עבור כל מקטע. +**עקביות סמנטית**: לשמור על היררכיות מחלקות, תחומים/טווחים של תכונות ואילוצים. +**עיבוד יעיל**: להשתמש במאגרי וקטורים בזיכרון עבור התאמת אלמנטים של אונטולוגיה מהירה. +**ארכיטקטורה ניתנת להרחבה**: לתמוך במספר אונטולוגיות מקבילות עם תחומים שונים. + +## רקע + +שירותי חילוץ ידע נוכחיים (`kg-extract-definitions`, `kg-extract-relationships`) פועלים ללא אילוצים פורמליים, מה שעלול לגרום ליצירת משולשים לא עקביים או לא תואמים. OntoRAG פותרת בעיה זו על ידי: + +1. טעינת אונטולוגיות פורמליות המגדירות מחלקות ותכונות חוקיות. +2. שימוש בהטבעות כדי להתאים תוכן טקסטואלי לאלמנטים רלוונטיים של אונטולוגיה. +3. הגבלת החילוץ ליצירת משולשים התואמים לאונטולוגיה בלבד. +4. מתן אימות סמנטי של ידע חילוץ. + +גישה זו משלבת את הגמישות של חילוץ עצבי עם הדיוק של ייצוג ידע פורמלי. + +## עיצוב טכני + +### ארכיטקטורה + +מערכת OntoRAG מורכבת מהרכיבים הבאים: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### פרטי רכיב + +#### 1. טוען אונטולוגיות + +**מטרה**: שולף ומנתח תצורות אונטולוגיות משירות התצורה באמצעות עדכונים מבוססי אירועים. + +**יישום**: +טוען האונטולוגיות משתמש בתור ConfigPush של TrustGraph כדי לקבל עדכוני תצורת אונטולוגיות מבוססי אירועים. כאשר רכיב תצורה מסוג "אונטולוגיה" נוסף או משתנה, הטוען מקבל את העדכון דרך תור config-update ומנתח את מבנה ה-JSON המכיל מטא-נתונים, מחלקות, מאפייני אובייקטים ומאפייני טיפוס נתונים. האונטולוגיות המנותחות מאוחסנות בזיכרון כאובייקטים מובנים שניתן לגשת אליהם ביעילות במהלך תהליך החילוץ. + +**פעולות מרכזיות**: +להירשם לתור config-update עבור תצורות מסוג אונטולוגיה +לנתח מבני אונטולוגיה מסוג JSON לאובייקטים של OntologyClass ו-OntologyProperty +לאמת את מבנה האונטולוגיה ועקביותה +לשמור אונטולוגיות מנותחות בזיכרון לגישה מהירה +לטפל בעיבוד פר-פלואו עם מאגרי וקטורים ספציפיים ל-פלואו + +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. משובץ אונטולוגיות + +**מטרה**: יוצר הטמעות וקטוריות עבור כל רכיבי האונטולוגיה כדי לאפשר התאמת דמיון סמנטי. + +**יישום**: +משובץ האונטולוגיות מעבד כל רכיב באונטולוגיות הטעונות ויוצר הטמעות וקטוריות באמצעות שירות EmbeddingsClientSpec. עבור כל רכיב, הוא משלב את מזהה הרכיב, התוויות והתיאור (הערה) כדי ליצור ייצוג טקסטואלי. טקסט זה מומר לאחר מכן להטמעת וקטור ממדית גבוהה הלוכדת את המשמעות הסמנטית שלו. הטמעות אלה מאוחסנות במאגר וקטורים FAISS בזיכרון, פר-פלואו, יחד עם מטא-נתונים על סוג הרכיב, האונטולוגיה המקורית וההגדרה המלאה. המשובץ מזהה באופן אוטומטי את ממד ההטמעה מהתגובה הראשונה להטמעה. + +**פעולות מרכזיות**: +ליצור ייצוגים טקסטואליים ממזהי רכיבים, תוויות והערות +ליצור הטמעות באמצעות EmbeddingsClientSpec (תוך שימוש ב-asyncio.gather לעיבוד באצווה) +לאחסן הטמעות עם מטא-נתונים מקיפים במאגר וקטורים FAISS +לאנדקס לפי אונטולוגיה, סוג רכיב ומזהה רכיב לשליפה יעילה +לזהות באופן אוטומטי את ממדי ההטמעה לאתחול מאגר הווקטורים +לטפל במודלי הטמעה פר-פלואו עם מאגרי וקטורים עצמאיים + +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. מעבד טקסט (מפצל משפטים) + +**מטרה**: מפרק מקטעי טקסט לפלחי משנה מפורטים לצורך התאמת אונטולוגיות מדויקת. + +**יישום**: +מעבד הטקסט משתמש ב-NLTK לטוקניזציה של משפטים וסימון חלקי דיבור כדי לחלק מקטעי טקסט נכנסים למשפטים. הוא מטפל בתאימות גרסאות של NLTK על ידי ניסיון להוריד את `punkt_tab` ו-`averaged_perceptron_tagger_eng`, עם מעבר לגרסאות ישנות יותר במידת הצורך. כל מקטע טקסט מחולק למשפטים בודדים שניתן להתאים אליהם באופן עצמאי לרכיבי אונטולוגיה. + +**פעולות מרכזיות**: +לחלק טקסט למשפטים באמצעות טוקניזציה של משפטים של NLTK +לטפל בתאימות גרסאות של NLTK (punkt_tab לעומת punkt) +ליצור אובייקטים של TextSegment עם טקסט ומידע על מיקום +לתמוך הן במשפטים שלמים והן במקטעים בודדים + +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. בורר אונטולוגיות + +**מטרה**: מזהה את תת-הקבוצה הרלוונטית ביותר של רכיבי אונטולוגיה עבור מקטע הטקסט הנוכחי. + +**יישום**: +בורר האונטולוגיות מבצע התאמה סמנטית בין פלחי טקסט ורכיבי אונטולוגיה באמצעות חיפוש דמיון וקטורי של FAISS. עבור כל משפט ממקטע הטקסט, הוא יוצר הטמעה ומחפש במאגר הווקטורים את רכיבי האונטולוגיה הדומים ביותר באמצעות דמיון קוסינוס עם סף הניתן להגדרה (ברירת מחדל 0.3). לאחר איסוף כל הרכיבים הרלוונטיים, הוא מבצע פתרון תלות מקיף: אם נבחרה מחלקה, מחלקות האב שלה כלולות; אם נבחר מאפיין, מחלקות הדומיין והטווח שלו מתווספות. בנוסף, עבור כל מחלקה שנבחרה, הוא כולל באופן אוטומטי **את כל המאפיינים המתייחסים למחלקה זו** בתחום או בטווח שלה. זה מבטיח שלחילוץ יש גישה לכל מאפייני היחס הרלוונטיים. + +**פעולות מפתח**: +יצירת הטמעות עבור כל מקטע טקסט (משפטים) +ביצוע חיפוש של שכנים הקרובים ביותר בבנק וקטורים FAISS (top_k=10, threshold=0.3) +החלת סף דמיון כדי לסנן התאמות חלשות +פתרון תלויות (מחלקות הורים, תחומים, טווחים) +**הכללת כל המאפיינים הקשורים למחלקות שנבחרו באופן אוטומטי** (התאמת תחום/טווח) +יצירת תת-אונטולוגיה קוהרנטית עם כל היחסים הנדרשים +הסרת אלמנטים כפולים המופיעים מספר פעמים + +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. בניית הנחיה (Prompt) + +**מטרה**: יוצר הנחיות מובנות המכוונות את מודל השפה הגדול (LLM) לחלץ רק משולשות התואמים לאונטולוגיה. + +**יישום**: +שירות החילוץ משתמש בתבנית Jinja2 שנטענת מ-`ontology-prompt.md` אשר מעצבת את תת-האונטולוגיה ואת הטקסט לחילוץ על ידי מודל השפה הגדול. התבנית חוזרת באופן דינמי על מחלקות, מאפייני אובייקט ומאפייני נתוני טיפוס תוך שימוש בתחביר Jinja2, ומציגה כל אחד עם התיאורים, התחומים, הטווחים והיחסים ההיררכיים שלהם. ההנחיה כוללת כללים קפדניים לגבי שימוש רק באלמנטים של האונטולוגיה המסופקת ומבקשת פורמט פלט JSON לצורך ניתוח עקבי. + +**פעולות מפתח**: +שימוש בתבנית Jinja2 עם לולאות על אלמנטים של אונטולוגיה +עיצוב מחלקות עם יחסי הורה (subclass_of) והערות +עיצוב מאפיינים עם אילוצי תחום/טווח והערות +הכללת כללי חילוץ מפורשים ודרישות פורמט פלט +קריאה לשירות ההנחיה עם מזהה התבנית "extract-with-ontologies" + +**מיקום התבנית**: `ontology-prompt.md` +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (שיטת build_extraction_variables) + +#### 6. שירות החילוץ הראשי + +**מטרה**: מתאם את כל הרכיבים לביצוע חילוץ משולשות מבוסס אונטולוגיה מקצה לקצה. + +**יישום**: +שירות החילוץ הראשי (KgExtractOntology) הוא שכבת הארגון המנהלת את זרימת העבודה שלמה. הוא משתמש בדפוס FlowProcessor של TrustGraph עם אתחול רכיבים ספציפיים לכל זרימה. כאשר מגיעה עדכון תצורה של אונטולוגיה, הוא מאתחל או מעדכן את הרכיבים הספציפיים לזרימה (טוען אונטולוגיה, ממיר, מעבד טקסט, בוחר). כאשר מגיע מקטע טקסט לעיבוד, הוא מתאם את הצינור: חלוקת הטקסט למקטעים, מציאת אלמנטי אונטולוגיה רלוונטיים באמצעות חיפוש וקטורי, בניית הנחיה מוגבלת, קריאה לשירות ההנחיה, ניתוח ותיקוף של התגובה, יצירת משולשות הגדרת אונטולוגיה, ופליטה הן של משולשות תוכן והן של הקשרים של ישויות. + +**צינור חילוץ**: +1. קבלת מקטע טקסט דרך תור chunks-input +2. אתחול רכיבי זרימה אם יש צורך (במקטע הראשון או בעדכון תצורה) +3. חלוקת הטקסט למשפטים באמצעות NLTK +4. חיפוש בבנק וקטורים FAISS כדי למצוא מושגי אונטולוגיה רלוונטיים +5. בניית תת-אונטולוגיה עם הכללה אוטומטית של מאפיינים +6. בניית משתני תבנית Jinja2 +7. קריאה לשירות ההנחיה עם תבנית extract-with-ontologies +8. ניתוח תגובת JSON למשולשות מובנים +9. תיקוף משולשות והרחבת URIs ל-URIs מלאים של אונטולוגיה +10. יצירת משולשות הגדרת אונטולוגיה (מחלקות ומאפיינים עם תויות/הערות/תחומים/טווחים) +11. בניית הקשרים של ישויות מכל המשולשות +12. פליטה לתורים של משולשות והקשרים של ישויות + +**תכונות מפתח**: +בנקי וקטורים ספציפיים לכל זרימה התומכים במודלי הטמעה שונים +עדכוני אונטולוגיה מונעי אירועים דרך תור config-update +הרחבת URI אוטומטית באמצעות URIs של אונטולוגיה +אלמנטים של אונטולוגיה מוספים לגרף ידע עם מטא-נתונים מלאים +הקשרים של ישויות כוללים הן אלמנטים של תוכן והן אלמנטים של אונטולוגיה + +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### תצורה + +השירות משתמש בגישה הסטנדרטית של TrustGraph לתצורה עם ארגומנטים של שורת הפקודה: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**פרמטרי תצורה מרכזיים**: +`similarity_threshold`: 0.3 (ברירת מחדל, ניתן להגדרה בקוד) +`top_k`: 10 (מספר רכיבי אונטולוגיה לשליפה לכל מקטע) +`vector_store`: FAISS IndexFlatIP עם זיהוי אוטומטי של ממדים לכל זרימה +`text_processor`: NLTK עם טוקניזציה של משפטים punkt_tab +`prompt_template`: "extract-with-ontologies" (תבנית Jinja2) + +**תצורת אונטולוגיה**: +אונטולוגיות נטענות באופן דינמי באמצעות תור ההודעות config-update עם סוג "ontology". + +### זרימת נתונים + +1. **שלב אתחול** (לכל זרימה): + קבלת תצורת אונטולוגיה באמצעות תור ההודעות config-update + ניתוח JSON של האונטולוגיה לאובייקטים של OntologyClass ו-OntologyProperty + יצירת הטמעות עבור כל רכיבי אונטולוגיה באמצעות EmbeddingsClientSpec + אחסון הטמעות בתוך מאגר וקטורים FAISS ספציפי לכל זרימה + זיהוי אוטומטי של ממדי ההטמעה מהתגובה הראשונה + +2. **שלב חילוץ** (לכל מקטע): + קבלת מקטע מתור הקלט chunks-input + חלוקת המקטע למשפטים באמצעות NLTK + חישוב הטמעות עבור כל משפט + חיפוש במאגר הווקטורים FAISS עבור רכיבי אונטולוגיה רלוונטיים + בניית תת-אונטולוגיה עם הכללת מאפיינים אוטומטית + יצירת משתנים לתבנית Jinja2 עם טקסט ואונטולוגיה + הפעלת שירות שאילתות עם תבנית extract-with-ontologies + ניתוח תגובת JSON ואימות של שלשות + הרחבת URIs באמצעות URIs של אונטולוגיה + יצירת שלשות הגדרת אונטולוגיה + בניית הקשרים של ישויות מכל השלשות + פליטה לתורים triples ו-entity-contexts + +### מאגר וקטורים בזיכרון + +**מטרה**: מספק חיפוש מהיר של דמיון המבוסס על זיכרון, לציפוף של התאמת רכיבי אונטולוגיה. + +**יישום: FAISS** + +המערכת משתמשת ב-**FAISS (Facebook AI Similarity Search)** עם IndexFlatIP לחיפוש מדויק של דמיון קוסינוס. תכונות עיקריות: + +**IndexFlatIP**: חיפוש מדויק של דמיון קוסינוס באמצעות מכפלה פנימית +**זיהוי אוטומטי**: ממד נקבע מהתגובת ההטמעה הראשונה +**מאגרים ספציפיים לזרימה**: לכל זרימה יש מאגר וקטורים עצמאי עבור מודלים שונים של הטמעה +**נרמול**: כל הווקטורים מנורמלים לפני אינדוקס +**פעולות באצווה**: הוספה יעילה באצווה לטעינת אונטולוגיה ראשונית + +**מיקום יישום**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### אלגוריתם בחירת תת-אונטולוגיה + +**מטרה**: בוחר באופן דינמי את החלק הרלוונטי המינימלי של האונטולוגיה עבור כל מקטע טקסט. + +**שלבי אלגוריתם מפורטים**: + +1. **פילוח טקסט**: + חלוקת המקטע הקלט למשפטים באמצעות זיהוי משפטים של NLP + חילוץ צירופי שמות עצם, צירופי פעלים וישויות בעלות שם מכל משפט + יצירת מבנה היררכי של מקטעים תוך שמירה על הקשר + +2. **יצירת הטמעות**: + יצירת הטמעות וקטוריות עבור כל מקטע טקסט (משפטים וצירופים) + שימוש באותו מודל הטמעה כמו זה המשמש עבור רכיבי אונטולוגיה + שמירת הטמעות עבור מקטעים חוזרים כדי לשפר את הביצועים + +3. **חיפוש דמיון**: + עבור כל הטמעת מקטע טקסט, חיפוש במאגר הווקטורים + אחזור rכיבי אונטולוגיה הדומים ביותר (לדוגמה, 10) + החלת סף דמיון (לדוגמה, 0.7) כדי לסנן התאמות חלשות + צבירת תוצאות על פני כל המקטעים, תוך מעקב אחר תדירות התאמות + +4. **פתרון תלות**: + עבור כל מחלקה שנבחרה, הכללה רקורסיבית של כל מחלקות האב עד לשורש + עבור כל מאפיין שנבחר, הכללת מחלקות הדומיין והטווח שלו + עבור מאפיינים הפוכים, ודאו ששני הכיוונים כלולים + הוספת מחלקות שוות ערך אם הן קיימות באונטולוגיה + +5. **בניית תת-קבוצה**: + הסרת כפילויות של רכיבים שנאספו תוך שמירה על יחסים + ארגון למחלקות, מאפיינים אובייקטיים ומאפיינים של טיפוסי נתונים + ודאו שכל האילוצים והיחסים נשמרים + יצירת מיני-אונטולוגיה עצמאית שתקפה ושלמה + +**דוגמה להמחשה**: +בהינתן טקסט: "The brown dog chased the white cat up the tree." +מקטעים: ["brown dog", "white cat", "tree", "chased"] +רכיבים תואמים: [dog (class), cat (class), animal (parent), chases (property)] +תלויות: [animal (parent of dog and cat), lifeform (parent of animal)] +תת-קבוצה סופית: מיני-אונטולוגיה שלמה עם היררכיית animal ויחס chase + +### אימות שלשות + +**מטרה**: מבטיח שכל שלשות החילוץ תואמות באופן קפדני לאילוצי האונטולוגיה. + +**אלגוריתם אימות**: +פלט חוזה (יש לעקוב אחר הפורמט בדיוק). +1. **בדיקת תקינות מחלקה**: + ודאו שהנושאים הם מופעים של מחלקות המוגדרות בתת-אונטולוגיה. + עבור מאפיינים אובייקטים, ודאו שהאובייקטים הם גם מופעים חוקיים של מחלקות. + בדקו שמות מחלקות מול מילון המחלקות של האונטולוגיה. + התייחסו להירוארכיות מחלקות - מופעים של תת-מחלקות תקפים עבור אילוצי מחלקת האב. + +2. **בדיקת תקינות מאפיינים**: + ודאו שהפרדיקטים תואמים למאפיינים בתת-אונטולוגיה. + הבדילו בין מאפייני אובייקטים (מקישורים בין ישויות) ומאפייני טיפוס נתונים (מקישורים בין ישות לליטרל). + ודאו ששמות המאפיינים תואמים בדיוק (תוך התחשבות בשם המרחב אם קיים). + +3. **בדיקת תחום/טווח**: + עבור כל מאפיין המשמש כפרדיקט, אחזרו את התחום והטווח שלו. + ודאו שסוג הנושא תואם או יורש מסוג התחום של המאפיין. + ודאו שסוג האובייקט תואם או יורש מסוג הטווח של המאפיין. + עבור מאפייני טיפוס נתונים, ודאו שהאובייקט הוא ליטרל מסוג XSD הנכון. + +4. **בדיקת קרדינליות**: + עקבו אחר ספירת השימוש במאפיינים לכל נושא. + בדקו קרדינליות מינימלית - ודאו שמאפיינים נדרשים קיימים. + בדקו קרדינליות מקסימלית - ודאו שמאפיין לא משמש יותר מדי פעמים. + עבור מאפיינים פונקציונליים, ודאו שיש לכל היותר ערך אחד לכל נושא. + +5. **בדיקת טיפוס נתונים**: + נתחו ערכי ליטרל בהתאם לטיפוסי XSD המוצהרים שלהם. + ודאו שמספרים שלמים הם מספרים חוקיים, תאריכים מעוצבים כראוי וכו'. + בדקו תבניות מחרוזות אם מוגדרים אילוצי regex. + ודאו שכתובות URI מעוצבות כראוי עבור טיפוסי xsd:anyURI. + +**דוגמה לבדיקה**: +טריפל: ("Buddy", "has-owner", "John") +בדקו ש-"Buddy" מסווג כמחלקה שיכולה להיות בעלת מאפיין "has-owner". +בדקו ש-"has-owner" קיים באונטולוגיה. +ודאו אילוץ תחום: הנושא חייב להיות מסוג "Pet" או תת-מחלקה. +ודאו אילוץ טווח: האובייקט חייב להיות מסוג "Person" או תת-מחלקה. +אם תקף, הוסיפו לפלט; אם לא תקף, רשמו הפרה ודלגו. + +## שיקולי ביצועים + +### אסטרטגיות אופטימיזציה + +1. **מטמון הטבעות**: שמרו הטבעות עבור פלחים טקסטואליים בשימוש תכוף. +2. **עיבוד באצווה**: עבדו על מספר פלחים במקביל. +3. **אינדקס אחסון וקטורים**: השתמשו באלגוריתמים של שכנים קרובים ביותר משוערים עבור אונטולוגיות גדולות. +4. **אופטימיזציית שאילתות**: צמצמו את גודל השאילתה על ידי הכללת רק אלמנטים חיוניים של האונטולוגיה. +5. **מטמון תוצאות**: שמרו תוצאות חילוץ עבור מקטעים זהים. + +### יכולת הרחבה + +**הרחבה אופקית**: מספר מופעים של תוכנת חילוץ עם מטמון אונטולוגיה משותף. +**חלוקת אונטולוגיה**: חלקו אונטולוגיות גדולות לפי תחום. +**עיבוד סטרימינג**: עבדו על מקטעים כשהם מגיעים מבלי לבצע אצווה. +**ניהול זיכרון**: ניקוי תקופתי של הטבעות לא בשימוש. + +## טיפול בשגיאות + +### תרחישי כשל + +1. **אונטולוגיות חסרות**: חזרו לחילוץ לא מוגבל. +2. **כשל בשירות הטבעות**: השתמשו בהטבעות שמורות או דלגו על התאמה סמנטית. +3. **חריגה של זמן תגובה של שירות השאילתות**: נסו שוב עם השהייה אקספוננציאלית. +4. **פורמט טריפל לא חוקי**: רשמו ודלגו על טריפלים מעוותים. +5. **אי-עקביות באונטולוגיה**: דווחו על סתירות והשתמשו באלמנטים חוקיים הספציפיים ביותר. + +### ניטור + +מדדים מרכזיים למעקב: + +זמן טעינה ושימוש בזיכרון של האונטולוגיה. +השהייה ביצירת הטבעות. +ביצועי חיפוש וקטורי. +זמן תגובה של שירות השאילתות. +דיוק חילוץ טריפלים. +שיעור התאמה לאונטולוגיה. + +## נתיב מעבר + +### מתוכנות חילוץ קיימות + +1. **פעולה מקבילה**: הפעילו במקביל לתוכנות החילוץ הקיימות בתחילה. +2. **פריסה הדרגתית**: התחילו עם סוגי מסמכים ספציפיים. +3. **השוואת איכות**: השוו את איכות הפלט לתוכנות החילוץ הקיימות. +4. **מעבר מלא**: החליפו את תוכנות החילוץ הקיימות לאחר אימות האיכות. + +### פיתוח אונטולוגיה + +1. **התחילו מקיים**: צרו אונטולוגיות ראשוניות מידע קיים. +2. **שיפור איטרטיבי**: שפרו בהתבסס על תבניות חילוץ. +3. **סקירה של מומחי תחום**: ודאו עם מומחי תחום. +4. **השתמשו ב-LLM**: השתמשו במודלים גדולים של שפה כדי ליצור אונטולוגיות. +**השתמשו ב-RAG**: השתמשו בשליפה מבוססת אחזור כדי לשפר את התוצאות. +**השתמשו ב-Agent**: השתמשו בסוכנים כדי לבצע משימות. +**השתמשו ב-Tool**: השתמשו בכלים כדי לשפר את הפרודוקטיביות. +**השתמשו ב-Memory**: השתמשו בזיכרון כדי לשפר את ההקשר. +**השתמשו ב-Output**: השתמשו בפלט כדי לשפר את התוצאות. + + +**רכיבי השירות**: +`onto-query-sparql`: ממיר שפה טבעית לשאילתות SPARQL עבור Cassandra. +`sparql-cassandra`: שכבת שאילתות SPARQL עבור Cassandra באמצעות rdflib. +`onto-query-cypher`: ממיר שפה טבעית לשאילתות Cypher עבור מסדי נתונים גרפיים. +`cypher-executor`: ביצוע שאילתות Cypher עבור Neo4j/Memgraph/FalkorDB. + +### ארכיטקטורה + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### צינור עיבוד שאילתות + +#### 1. מנתח שאלות + +**מטרה**: מפרק שאלות משתמש לרכיבים סמנטיים לצורך התאמה לאונטולוגיה. + +**תיאור אלגוריתם**: +מנתח השאלות לוקח את השאלה בשפה טבעית ומפרק אותה לפלחי משמעות באמצעות אותה גישת חלוקת משפטים כמו צינור החילוץ. הוא מזהה ישויות, קשרים ואילוצים מרכזיים המוזכרים בשאלה. כל פלח נתח עבור סוג השאלה (עובדתית, אגרגציה, השוואה וכו') ופורמט התשובה הצפוי. פירוק זה עוזר לזהות אילו חלקים של האונטולוגיה רלוונטיים ביותר למענה על השאלה. + +**פעולות מרכזיות**: +חלוקת השאלה למשפטים ולביטויים +זיהוי סוג השאלה והכוונתה +חילוץ ישויות ויחסים המוזכרים +זיהוי אילוצים וסינונים בשאלה +קביעת פורמט התשובה הצפוי + +#### 2. מותאם אונטולוגיות לשאילתות + +**מטרה**: מזהה את תת-האונטולוגיה הרלוונטית הדרושה כדי לענות על השאלה. + +**תיאור אלגוריתם**: +דומה לבחירת האונטולוגיה בצינור החילוץ, אך מותאם לשאלות ותשובות. המתאם מייצר הטבעות עבור פלחי שאלה ומחפש במאגר הווקטורים אלמנטים רלוונטיים באונטולוגיה. עם זאת, הוא מתמקד במציאת מושגים שיכולים להיות שימושיים ליצירת שאילתות, ולא לחילוץ. הוא מרחיב את הבחירה כדי לכלול מאפיינים קשורים שניתן לעבור דרכם במהלך חקר הגרף, גם אם הם אינם מוזכרים במפורש בשאלה. לדוגמה, אם נשאל על "עובדים", הוא עשוי לכלול מאפיינים כמו "עובד עבור", "מנהל" ו"מדווח ל" שיכולים להיות רלוונטיים למציאת מידע על עובדים. + +**אסטרטגיית התאמה**: +הטבעת פלחי שאלה +מציאת מושגי אונטולוגיה המוזכרים ישירות +הכללת מאפיינים המחברים בין מחלקות המוזכרות +הוספת מאפיינים הפוכים וקשורים לניווט +הכללת מחלקות הורה/ילד לשאילתות היררכיות +יצירת מחיצת אונטולוגיה ממוקדת שאילתות + +#### 3. מנתב רקע + +**מטרה**: מנתב שאילתות לנתיב השאילתות הספציפי המתאים לרקע בהתבסס על תצורה. + +**תיאור אלגוריתם**: +מנתב הרקע בודק את תצורת המערכת כדי לקבוע איזה רקע גרף פעיל (Cassandra או מבוסס Cypher). הוא מנתב את השאלה ומחיצת האונטולוגיה לשירות יצירת השאילתות המתאים. המנתב יכול גם לתמוך באיזון עומסים בין רקעים מרובים או במנגנוני גיבוי אם הרקע הראשי אינו זמין. + +**לוגיקת ניתוב**: +בדיקת סוג הרקע המוגדר בהגדרות המערכת +ניתוב ל-`onto-query-sparql` עבור רקעי Cassandra +ניתוב ל-`onto-query-cypher` עבור Neo4j/Memgraph/FalkorDB +תמיכה בתצורות מרובות רקעים עם הפצת שאילתות +טיפול בתרחישי גיבוי ואיזון עומסים + +#### 4. יצירת שאילתות SPARQL (`onto-query-sparql`) + +**מטרה**: ממיר שאלות בשפה טבעית לשאילתות SPARQL לביצוע ב-Cassandra. + +**תיאור אלגוריתם**: +מחולל שאילתות ה-SPARQL לוקח את השאלה ואת מחיצת האונטולוגיה ויוצר שאילתת SPARQL המותאמת לביצוע על הרקע של Cassandra. הוא משתמש בשירות ה-prompt עם תבנית ספציפית ל-SPARQL הכוללת סמנטיקה של RDF/OWL. המחולל מבין תבניות SPARQL כמו נתיבי מאפיינים, סעיפים אופציונליים וסינונים שיכולים לתרגם ביעילות לפעולות Cassandra. + +**תבנית prompt ליצירת SPARQL**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. יצירת שאילתות Cypher (`onto-query-cypher`) + +**מטרה**: ממירה שאלות בשפה טבעית לשאילתות Cypher עבור מסדי נתונים גרפיים. + +**תיאור האלגוריתם**: +יוצר השאילתות Cypher מייצר שאילתות Cypher מקומיות המותאמות ל-Neo4j, Memgraph ו-FalkorDB. הוא ממפה מחלקות אונטולוגיה לתגיות צמתים ומאפיינים ליחסים, תוך שימוש בתחביר התאמת תבניות של Cypher. היוצר כולל אופטימיזציות ספציפיות ל-Cypher כגון רמזים לכיוון יחסים, שימוש באינדקסים ורמזים לתכנון שאילתות. + +**תבנית הנחיה ליצירת Cypher**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. מנוע שאילתות SPARQL-Cassandra (`sparql-cassandra`) + +**מטרה**: מבצע שאילתות SPARQL נגד Cassandra באמצעות ספריית rdflib של Python. + +**תיאור האלגוריתם**: +מנוע ה-SPARQL-Cassandra מיישם מעבד SPARQL באמצעות ספריית rdflib של Python עם אחסון מותאם אישית ב-Cassandra. הוא מתרגם תבניות גרף SPARQL לשאילתות CQL מתאימות של Cassandra, תוך טיפול בחיבורים, פילטרים ואגרגציות. המנוע שומר על מיפוי מ-RDF ל-Cassandra המשמר את המבנה הסמנטי תוך אופטימיזציה עבור מודל האחסון של משפחות עמודות של Cassandra. + +**מאפייני יישום**: +יישום ממשק rdflib Store עבור Cassandra +תמיכה בשאילתות SPARQL 1.1 עם תבניות נפוצות +תרגום יעיל של תבניות משולשות ל-CQL +תמיכה בנתיבי מאפיינים ובשאילתות היררכיות +הזרמת תוצאות עבור מערכי נתונים גדולים +בריכת חיבורים ומטמון שאילתות + +**דוגמה לתרגום**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +מתרגם לשאילתות Cassandra מותאמות אופטימלית תוך שימוש באינדקסים ומפתחות מחיצה. + +#### 7. מפעיל שאילתות Cypher (`cypher-executor`) + +**מטרה**: מריץ שאילתות Cypher נגד Neo4j, Memgraph ו-FalkorDB. + +**תיאור האלגוריתם**: +מפעיל ה-Cypher מספק ממשק אחיד להרצת שאילתות Cypher על פני מסדי נתונים גרפיים שונים. הוא מטפל בפרוטוקולי חיבור ספציפיים למסד הנתונים, רמזי אופטימיזציה לשאילתות ושינוי פורמט תוצאות. המפעיל כולל מנגנון ניסיון חוזר, ניהול חיבורים וניהול טרנזקציות המתאימים לכל סוג מסד נתונים. + +**תמיכה במספר מסדי נתונים**: +**Neo4j**: פרוטוקול Bolt, פונקציות טרנזקציה, רמזי אינדקס +**Memgraph**: פרוטוקול מותאם אישית, זרימת תוצאות, שאילתות אנליטיות +**FalkorDB**: התאמת פרוטוקול Redis, אופטימיזציות בזיכרון + +**תכונות ביצוע**: +ניהול חיבורים שאינו תלוי במסד הנתונים +אימות שאילתות ובדיקת תחביר +אכיפת מגבלות זמן ומשאבים +דף תוצאות וזרימת תוצאות +ניטור ביצועים לפי סוג מסד נתונים +מעבר אוטומטי בין מופעי מסד נתונים + +#### 8. מחולל תשובות + +**מטרה**: יוצר תשובה בשפה טבעית מתוצאות שאילתות. + +**תיאור האלגוריתם**: +מחולל התשובות לוקח את תוצאות השאילתות המובנות ואת השאלה המקורית, ולאחר מכן משתמש בשירות ה-prompt כדי ליצור תשובה מקיפה. בניגוד לתגובות פשוטות המבוססות על תבניות, הוא משתמש ב-LLM כדי לפרש את נתוני הגרף בהקשר של השאלה, תוך טיפול ביחסים מורכבים, אגרגציות והסקת מסקנות. המחולל יכול להסביר את הנימוקים שלו על ידי התייחסות למבנה האונטולוגיה ולטרפלים הספציפיים שנשלפו מהגרף. + +**תהליך יצירת תשובות**: +עיצוב תוצאות שאילתות להקשר מובנה +הכללת הגדרות אונטולוגיה רלוונטיות לצורך בהירות +יצירת prompt עם שאלה ותוצאות +יצירת תשובה בשפה טבעית באמצעות LLM +אימות התשובה מול כוונת השאלה +הוספת ציטוטים לישויות גרף ספציפיות במידת הצורך + +### אינטגרציה עם שירותים קיימים + +#### יחס עם GraphRAG + +**משלימים**: onto-query מספק דיוק סמנטי בעוד ש-GraphRAG מספק כיסוי רחב +**תשתית משותפת**: שניהם משתמשים באותו גרף ידע ובשירותי prompt +**ניתוב שאילתות**: המערכת יכולה לנתב שאילתות לשירות המתאים ביותר בהתאם לסוג השאלה +**מצב היברידי**: ניתן לשלב את שתי הגישות ליצירת תשובות מקיפות + +#### יחס עם OntoRAG Extraction + +**אונטולוגיות משותפות**: משתמש באותות תצורת האונטולוגיה שנטענו על ידי kg-extract-ontology +**מאגר וקטורים משותף**: משתמש בהטמעות בזיכרון משירות החילוץ +**סמנטיקה עקבית**: השאילתות פועלות על גרפים שנבנו עם אותן מגבלות אונטולוגיות + +### דוגמאות לשאילתות + +#### דוגמה 1: שאילתת ישות פשוטה +**שאלה**: "אילו בעלי חיים הם יונקים?" +**התאמת אונטולוגיה**: [animal, mammal, subClassOf] +**שאילתה שנוצרה**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### דוגמה 2: שאילתת קשר +**שאלה**: "אילו מסמכים נכתבו על ידי ג'ון סמית'?" +**התאמה לאונטולוגיה**: [document, person, has-author] +**שאילתה שנוצרה**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### דוגמה 3: שאילתת אגרגציה +**שאלה**: "כמה רגליים יש לחתולים?" +**התאמה לאונטולוגיה**: [חתול, מספר-רגליים (מאפיין נתונים)] +**שאילתה שנוצרה**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### הגדרות + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### אופטימיזציות ביצועים + +#### אופטימיזציית שאילתות + +**גיזום אונטולוגיה**: כלול רק רכיבי אונטולוגיה נחוצים בפרומפטים +**מטמון שאילתות**: שמור שאילתות נפוצות ותשובותיהן +**מטמון תוצאות**: שמור תוצאות עבור שאילתות זהות בתוך חלון זמן +**עיבוד באצווה**: טפל במספר שאלות קשורות בביצוע מעבר גרף יחיד + +#### שיקולי סקיילביליות + +**ביצוע מבוזר**: חלק תת-שאילתות בין מחיצות גרף +**תוצאות מצטברות**: הזרם תוצאות עבור מערכי נתונים גדולים +**איזון עומסים**: חלק את עומס השאילתות בין מופעים רבים של שירות +**בריכות משאבים**: נהל בריכות חיבורים למסדי נתונים גרפיים + +### טיפול בשגיאות + +#### תרחישי כשל + +1. **יצירת שאילתה לא חוקית**: חזור ל-GraphRAG או לחיפוש מילות מפתח פשוט +2. **אי התאמת אונטולוגיה**: הרחב את החיפוש לתת-אונטולוגיה רחבה יותר +3. **זמן קצוב של שאילתה**: פשט את השאילתה או הגדל את זמן הקצוב +4. **תוצאות ריקות**: הצע ניסוח מחדש של השאילתה או שאלות קשורות +5. **כשל בשירות LLM**: השתמש בשאילתות שמורות או בתגובות מבוססות תבניות + +### מדדי ניטור + +התפלגות מורכבות של שאלות +גדלי מחיצות אונטולוגיה +שיעור הצלחה של יצירת שאילתות +זמן ביצוע שאילתות גרפיות +ציוני איכות תשובות +שיעורי פגיעה במטמון +תדירויות שגיאות לפי סוג + +## שיפורים עתידיים + +1. **למידת אונטולוגיה**: הרחב באופן אוטומטי אונטולוגיות בהתבסס על דפוסי חילוץ +4. **הקצאת ציוני אמון**: הקצה ציוני אמון לטרפלים שחולצו +3. **יצירת הסברים**: ספק הסבר לניתוח טריפלים +4. **למידה פעילה**: בקש אימות אנושי לחילוצים לא ודאיים + +## שיקולי אבטחה + +1. **מניעת הזרקת פרומפטים**: נקה טקסט של חלקים לפני בניית פרומפט +2. **מגבלות משאבים**: הגבל את השימוש בזיכרון עבור מאגר וקטורים +3. **הגבלת קצב**: הגבל בקשות חילוץ לכל לקוח +4. **רישום ביקורת**: עקוב אחר כל בקשות חילוץ ותוצאות + +## אסטרטגיית בדיקה + +### בדיקות יחידה + +טוען אונטולוגיה עם פורמטים שונים +יצירת ואחסון וקטורים +אלגוריתמים לחלוקת משפטים +חישובים של דמיון וקטורי +ניתוח ותיקוף טריפלים + +### בדיקות אינטגרציה + +צינור חילוץ מקצה לקצה +אינטגרציה עם שירות תצורה +אינטראקציה עם שירות פרומפטים +טיפול בו-זמני בחילוץ + +### בדיקות ביצועים + +טיפול באונטולוגיות גדולות (1000+ מחלקות) +עיבוד נפח גבוה של חלקים +שימוש בזיכרון תחת עומס +מדדי השהייה + +## תוכנית הפצה + +### סקירה כללית + +מערכת OntoRAG תופץ בארבע פאזות עיקריות, כאשר כל פאזה מספקת ערך מצטבר תוך בניית המערכת השלמה. התוכנית מתמקדת בהקמת יכולות חילוץ בסיסיות תחילה, ולאחר מכן הוספת פונקציונליות שאילתות, ולאחר מכן אופטימיזציות ותכונות מתקדמות. + +### פאזה 1: יסודות וחילוץ ליבה + +**מטרה**: הקמת צינור חילוץ מונחה אונטולוגיה בסיסי עם התאמת וקטורים פשוטה. + +#### שלב 1.1: יסודות ניהול אונטולוגיה +יישום טוען תצורה של אונטולוגיה (`OntologyLoader`) +ניתוח ותיקוף מבני JSON של אונטולוגיה +יצירת אחסון אונטולוגיה בזיכרון ודפוסי גישה +יישום מנגנון רענון אונטולוגיה + +**קריטריוני הצלחה**: +טעינה וניתוח מוצלחים של תצורות אונטולוגיה +אימות מבנה אונטולוגיה ועקביות +טיפול במספר אונטולוגיות בו-זמנית + +#### שלב 1.2: יישום מאגר וקטורים +יישום מאגר וקטורים פשוט מבוסס NumPy כפרוטוטייפ ראשוני +הוספת יישום מאגר וקטורים FAISS +יצירת הפשטת ממשק למאגר וקטורים +יישום חיפוש דמיון עם ספים הניתנים לתצורה + +**קריטריוני הצלחה**: +אחסון ושליפה של הטמעות בצורה יעילה +ביצוע חיפוש דמיון עם השהייה של פחות מ-100ms +תמיכה גם ב-NumPy וגם ב-FAISS + +#### שלב 1.3: צינור הטמעת אונטולוגיה +שילוב עם שירות הטמעות +יישום רכיב `OntologyEmbedder` +יצירת הטמעות עבור כל רכיבי האונטולוגיה +אחסון הטמעות עם מטא-דאטה ב-vector store + +**קריטריוני הצלחה**: +יצירת הטמעות עבור מחלקות ומאפיינים +אחסון הטמעות עם מטא-דאטה מתאים +בנייה מחדש של הטמעות בעת עדכוני אונטולוגיה + +#### שלב 1.4: רכיבי עיבוד טקסט +יישום מפצל משפטים באמצעות NLTK/spaCy +חילוץ ביטויים וישויות שמניות +יצירת היררכיה של פלחי טקסט +יצירת הטמעות עבור פלחי טקסט + +**קריטריוני הצלחה**: +חלוקה מדויקת של טקסט למשפטים +חילוץ ביטויים בעלי משמעות +שמירה על יחסי הקשר + +#### שלב 1.5: אלגוריתם בחירת אונטולוגיה +יישום התאמת דמיון בין טקסט לאונטולוגיה +בניית פתרון תלות עבור רכיבי אונטולוגיה +יצירת תת-קבוצות אונטולוגיה קוהרנטיות מינימליות +אופטימיזציה של ביצועי יצירת תת-קבוצות + +**קריטריוני הצלחה**: +בחירת רכיבי אונטולוגיה רלוונטיים בדיוק של >80% +הכללת כל התלויות הנדרשות +יצירת תת-קבוצות בפחות מ-500ms + +#### שלב 1.6: שירות חילוץ בסיסי +יישום בניית הנחיה לחילוץ +שילוב עם שירות הנחיות +ניתוח ואימות תגובות משולשות +יצירת נקודת שירות `kg-extract-ontology` + +**קריטריוני הצלחה**: +חילוץ משולשות התואמות לאונטולוגיה +אימות כל המשולשות מול האונטולוגיה +טיפול בשגיאות חילוץ בצורה חלקה + +### שלב 2: יישום מערכת שאילתות + +**מטרה**: הוספת יכולות שאילתות מודעות לאונטולוגיה עם תמיכה במספר ממשקים. + +#### שלב 2.1: רכיבי יסוד של שאילתות +יישום מנתח שאלות +יצירת מתאם אונטולוגיה לשאילתות +התאמת חיפוש וקטורי להקשר השאילתה +בניית רכיב ניתוב ממשקים + +**קריטריוני הצלחה**: +ניתוח שאלות לרכיבים סמנטיים +התאמת שאלות לרכיבי אונטולוגיה רלוונטיים +ניתוב שאילתות לממשק מתאים + +#### שלב 2.2: יישום נתיב SPARQL +יישום שירות `onto-query-sparql` +יצירת מחולל שאילתות SPARQL באמצעות LLM +פיתוח תבניות הנחיה ליצירת SPARQL +אימות תחביר SPARQL שנוצר + +**קריטריוני הצלחה**: +יצירת שאילתות SPARQL חוקיות +שימוש בתבניות SPARQL מתאימות +טיפול בסוגי שאילתות מורכבים + +#### שלב 2.3: מנוע SPARQL-Cassandra +יישום ממשק rdflib Store עבור Cassandra +יצירת מתרגם שאילתות CQL +אופטימיזציה של התאמת תבניות משולשות +טיפול בעיצוב תוצאות SPARQL + +**קריטריוני הצלחה**: +ביצוע שאילתות SPARQL על Cassandra +תמיכה בתבניות SPARQL נפוצות +החזרת תוצאות בפורמט סטנדרטי + +#### שלב 2.4: יישום נתיב Cypher +יישום שירות `onto-query-cypher` +יצירת מחולל שאילתות Cypher באמצעות LLM +פיתוח תבניות הנחיה ליצירת Cypher +אימות תחביר Cypher שנוצר + +**קריטריוני הצלחה**: +יצירת שאילתות Cypher חוקיות +שימוש בתבניות גרף מתאימות +תמיכה ב-Neo4j, Memgraph, FalkorDB + +#### שלב 2.5: מפעיל Cypher +הטמעת מנגנון ביצוע שאילתות Cypher עבור מספר מסדי נתונים. +תמיכה בפרוטוקול Bolt (Neo4j/Memgraph). +תמיכה בפרוטוקול Redis (FalkorDB). +טיפול בנרמול תוצאות. + +**קריטריוני הצלחה**: +ביצוע שאילתות Cypher על כל מסדי הנתונים המיועדים. +טיפול בהבדלים ספציפיים למסד נתונים. +שמירה על בריכות חיבורים בצורה יעילה. + +#### שלב 2.6: יצירת תשובות +הטמעת רכיב ליצירת תשובות. +יצירת הנחיות ליצירת תשובות. +עיצוב תוצאות שאילתות לצריכה על ידי מודל שפה גדול (LLM). +יצירת תשובות בשפה טבעית. + +**קריטריוני הצלחה**: +יצירת תשובות מדויקות מתוצאות שאילתות. +שמירה על הקשר משאלת השאלה המקורית. +מתן תשובות ברורות ותמציתיות. + +### שלב 3: אופטימיזציה ואמינות + +**מטרה**: אופטימיזציה של ביצועים, הוספת מנגנון אחסון מטמון, שיפור טיפול בשגיאות ושיפור אמינות. + +#### שלב 3.1: אופטימיזציה של ביצועים +הטמעת מנגנון אחסון מטמון עבור הטמעות (embeddings). +הוספת מנגנון אחסון מטמון עבור תוצאות שאילתות. +אופטימיזציה של חיפוש וקטורי באמצעות אינדקסים IVF של FAISS. +הטמעת עיבוד באצווה עבור הטמעות. + +**קריטריוני הצלחה**: +הפחתת זמן השהייה ממוצע של שאילתות ב-50%. +תמיכה במספר גדול פי 10 של בקשות מקבילות. +שמירה על זמני תגובה מתחת לשנייה. + +#### שלב 3.2: טיפול מתקדם בשגיאות +הטמעת מנגנון התאוששות מקיף משגיאות. +הוספת מנגנוני גיבוי בין נתיבי שאילתות. +יצירת לוגיקה של ניסיונות חוזרים עם השהייה אקספוננציאלית. +שיפור רישום שגיאות ואבחון. + +**קריטריוני הצלחה**: +טיפול תקין בכל תרחישי כשל. +מעבר אוטומטי בין מערכות גיבוי. +דיווח מפורט על שגיאות לצורך איתור באגים. + +#### שלב 3.3: ניטור ונגישות +הוספת איסוף מדדי ביצועים. +הטמעת מעקב אחר שאילתות. +יצירת נקודות קצה לבדיקת תקינות. +הוספת ניטור שימוש במשאבים. + +**קריטריוני הצלחה**: +מעקב אחר כל מדדי הביצועים העיקריים. +זיהוי צווארי בקבוק במהירות. +ניטור בריאות המערכת בזמן אמת. + +#### שלב 3.4: ניהול תצורה +הטמעת עדכונים דינמיים של תצורה. +הוספת אימות תצורה. +יצירת תבניות תצורה. +תמיכה בהגדרות ספציפיות לסביבה. + +**קריטריוני הצלחה**: +עדכון תצורה ללא אתחול מחדש. +אימות כל שינויי התצורה. +תמיכה בסביבות פריסה מרובות. + +### שלב 4: תכונות מתקדמות + +**מטרה**: הוספת יכולות מתקדמות לפריסה בסביבת ייצור ושיפור פונקציונליות. + +#### שלב 4.1: תמיכה במספר אונטולוגיות +הטמעת לוגיקה לבחירת אונטולוגיה. +תמיכה בשאילתות חוצות אונטולוגיות. +טיפול בגרסאות של אונטולוגיות. +יצירת יכולות מיזוג אונטולוגיות. + +**קריטריוני הצלחה**: +שאילתות על פני מספר אונטולוגיות. +טיפול בקונפליקטים בין אונטולוגיות. +תמיכה באבולוציה של אונטולוגיות. + +#### שלב 4.2: ניתוב שאילתות חכם +הטמעת ניתוב מבוסס ביצועים +הוספת ניתוח מורכבות שאילתות +יצירת אלגוריתמי ניתוב אדפטיביים +תמיכה בבדיקות A/B עבור נתיבים + +**קריטריוני הצלחה**: +ניתוב שאילתות בצורה אופטימלית +למידה מביצועי שאילתות +שיפור הניתוב לאורך זמן + +#### שלב 4.3: תכונות חילוץ מתקדמות +הוספת ניקוד אמון עבור משולשות +הטמעת יצירת הסברים +יצירת לולאות משוב לשיפור +תמיכה בלמידה מצטברת + +**קריטריוני הצלחה**: +מתן ציוני אמון +הסבר החלטות חילוץ +שיפור מתמיד של הדיוק + +#### שלב 4.4: חיזוק עבור סביבת ייצור +הוספת הגבלת קצב +הטמעת אימות/הרשאה +יצירת אוטומציה של פריסה +הוספת גיבוי ושחזור + +**קריטריוני הצלחה**: +אבטחה מוכנה לסביבת ייצור +תהליך פריסה אוטומטי +יכולת שחזור מאסון + +### אבני דרך של אספקה + +1. **אבן דרך 1** (סוף שלב 1): חילוץ מבוסס אונטולוגיה בסיסי פועל +2. **אבן דרך 2** (סוף שלב 2): מערכת שאילתות מלאה עם נתיבי SPARQL ו-Cypher +3. **אבן דרך 3** (סוף שלב 3): מערכת מותאמת ויציבה, מוכנה לשלב בדיקות +4. **אבן דרך 4** (סוף שלב 4): מערכת מוכנה לסביבת ייצור עם תכונות מתקדמות + +### הפחתת סיכונים + +#### סיכונים טכניים +**מדרגיות של מאגר וקטורים**: להתחיל עם NumPy, לעבור בהדרגה ל-FAISS +**דיוק יצירת שאילתות**: הטמעת מנגנוני אימות וגיבוי +**תאימות לבסיס נתונים**: לבדוק באופן נרחב עם כל סוג בסיס נתונים +**צווארי בקבוק בביצועים**: לנתח ולבצע אופטימיזציה באופן איטרטיבי + +#### סיכונים תפעוליים +**איכות אונטולוגיה**: הטמעת מנגנוני אימות ובדיקת עקביות +**תלויות שירות**: הוספת מנגנוני ניתוב וגיבוי +**מגבלות משאבים**: ניטור והגדרת מגבלות מתאימות +**עקביות נתונים**: הטמעת טיפול מתאים בעסקאות + +### מדדי הצלחה + +#### מדדי הצלחה לשלב 1 +דיוק חילוץ: >90% התאמה לאונטולוגיה +מהירות עיבוד: <שנייה אחת לחלק +זמן טעינת אונטולוגיה: <10 שניות +השהיה של חיפוש וקטורים: <100ms + +#### מדדי הצלחה לשלב 2 +שיעור הצלחה של שאילתות: >95% +השהיה של שאילתות: <2 שניות מקצה לקצה +תאימות לבסיס נתונים: 100% עבור בסיסי נתונים מיועדים +דיוק תשובות: >85% בהתבסס על נתונים זמינים + +#### מדדי הצלחה לשלב 3 +זמן פעולה של המערכת: >99.9% +שיעור התאוששות משגיאות: >95% +שיעור פגיעות במטמון: >60% +משתמשים מקבילים: >100 + +#### מדדי הצלחה לשלב 4 +שאילתות מרובות אונטולוגיות: נתמכות במלואן +אופטימיזציה של ניתוב: הפחתת השהיה של 30% +דיוק ניקוד אמון: >90% +פריסה לסביבת ייצור: עדכונים ללא השבתה + +## הפניות + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.hi.md b/docs/tech-specs/ontorag.hi.md new file mode 100644 index 00000000..399f3407 --- /dev/null +++ b/docs/tech-specs/ontorag.hi.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: ज्ञान निष्कर्षण और क्वेरी के लिए ऑन्टोलॉजी-आधारित तकनीकी विनिर्देश" +parent: "Hindi (Beta)" +--- + +# OntoRAG: ज्ञान निष्कर्षण और क्वेरी के लिए ऑन्टोलॉजी-आधारित तकनीकी विनिर्देश + +> **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. + +## अवलोकन + +OntoRAG एक ऑन्टोलॉजी-संचालित ज्ञान निष्कर्षण और क्वेरी प्रणाली है जो असंरचित पाठ से ज्ञान त्रिक के निष्कर्षण और परिणामी ज्ञान ग्राफ की क्वेरी दोनों के दौरान सख्त सिमेंटिक स्थिरता लागू करती है। GraphRAG के समान, लेकिन औपचारिक ऑन्टोलॉजी बाधाओं के साथ, OntoRAG यह सुनिश्चित करता है कि सभी निकाले गए त्रिक पूर्वनिर्धारित ऑन्टोलॉजिकल संरचनाओं का पालन करते हैं और सिमेंटिक रूप से जागरूक क्वेरी क्षमताओं को प्रदान करता है। + +सिस्टम निष्कर्षण और क्वेरी दोनों कार्यों के लिए प्रासंगिक ऑन्टोलॉजी उपसमुच्चय को गतिशील रूप से चुनने के लिए वेक्टर समानता मिलान का उपयोग करता है, जो केंद्रित और प्रासंगिक प्रसंस्करण को सक्षम करता है जबकि सिमेंटिक वैधता बनाए रखता है। + +**सेवा का नाम**: `kg-extract-ontology` + +## लक्ष्य + +**ऑन्टोलॉजी-अनुरूप निष्कर्षण**: सुनिश्चित करें कि सभी निकाले गए त्रिक लोड की गई ऑन्टोलॉजी का सख्ती से पालन करते हैं। +**गतिशील संदर्भ चयन**: प्रत्येक खंड के लिए प्रासंगिक ऑन्टोलॉजी उपसमुच्चय का चयन करने के लिए एम्बेडिंग का उपयोग करें। +**सिमेंटिक स्थिरता**: वर्ग पदानुक्रम, संपत्ति डोमेन/रेंज और बाधाओं को बनाए रखें। +**कुशल प्रसंस्करण**: तेज़ ऑन्टोलॉजी तत्व मिलान के लिए इन-मेमोरी वेक्टर स्टोर का उपयोग करें। +**स्केलेबल आर्किटेक्चर**: विभिन्न डोमेन वाली कई समवर्ती ऑन्टोलॉजी का समर्थन करें। + +## पृष्ठभूमि + +वर्तमान ज्ञान निष्कर्षण सेवाएं (`kg-extract-definitions`, `kg-extract-relationships`) औपचारिक बाधाओं के बिना काम करती हैं, जिससे असंगत या असंगत त्रिक उत्पन्न हो सकते हैं। OntoRAG इस समस्या को हल करता है: + +1. औपचारिक ऑन्टोलॉजी लोड करना जो मान्य वर्ग और गुण परिभाषित करते हैं। +2. पाठ सामग्री को प्रासंगिक ऑन्टोलॉजी तत्वों से मिलाने के लिए एम्बेडिंग का उपयोग करना। +3. निष्कर्षण को केवल ऑन्टोलॉजी-अनुरूप त्रिक उत्पन्न करने तक सीमित करना। +4. निकाले गए ज्ञान का सिमेंटिक सत्यापन प्रदान करना। + +यह दृष्टिकोण औपचारिक ज्ञान प्रतिनिधित्व की कठोरता के साथ तंत्रिका निष्कर्षण की लचीलापन को जोड़ता है। + +## तकनीकी डिजाइन + +### आर्किटेक्चर + +OntoRAG सिस्टम में निम्नलिखित घटक शामिल हैं: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### घटक विवरण + +#### 1. ऑन्टोलॉजी लोडर + +**उद्देश्य**: इवेंट-ड्रिवेन अपडेट का उपयोग करके, कॉन्फ़िगरेशन सेवा से ऑन्टोलॉजी कॉन्फ़िगरेशन प्राप्त करता है और पार्स करता है। + +**कार्यान्वयन**: +ऑन्टोलॉजी लोडर, इवेंट-ड्रिवेन ऑन्टोलॉजी कॉन्फ़िगरेशन अपडेट प्राप्त करने के लिए ट्रस्टग्राफ के कॉन्फ़िगपुश क्यू का उपयोग करता है। जब "ऑन्टोलॉजी" प्रकार का कोई कॉन्फ़िगरेशन तत्व जोड़ा या संशोधित किया जाता है, तो लोडर कॉन्फ़िग-अपडेट क्यू के माध्यम से अपडेट प्राप्त करता है और मेटाडेटा, क्लास, ऑब्जेक्ट प्रॉपर्टी और डेटाटाइप प्रॉपर्टी युक्त JSON संरचना को पार्स करता है। इन पार्स किए गए ऑन्टोलॉजी को संरचित ऑब्जेक्ट के रूप में मेमोरी में संग्रहीत किया जाता है, जिन्हें निष्कर्षण प्रक्रिया के दौरान कुशलतापूर्वक एक्सेस किया जा सकता है। + +**मुख्य कार्य**: +ऑन्टोलॉजी-प्रकार कॉन्फ़िगरेशन के लिए कॉन्फ़िग-अपडेट क्यू की सदस्यता लें +JSON ऑन्टोलॉजी संरचनाओं को ऑन्टोलॉजीक्लास और ऑन्टोलॉजीप्रॉपर्टी ऑब्जेक्ट में पार्स करें +ऑन्टोलॉजी संरचना और स्थिरता को मान्य करें +तेज़ एक्सेस के लिए पार्स किए गए ऑन्टोलॉजी को मेमोरी में कैश करें +फ्लो-विशिष्ट वेक्टर स्टोर के साथ प्रति-फ्लो प्रोसेसिंग को संभालें + +**कार्यान्वयन स्थान**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. ऑन्टोलॉजी एम्बेडर + +**उद्देश्य**: सभी ऑन्टोलॉजी तत्वों के लिए वेक्टर एम्बेडिंग बनाता है ताकि सिमेंटिक समानता मिलान को सक्षम किया जा सके। + +**कार्यान्वयन**: +ऑन्टोलॉजी एम्बेडर, लोड किए गए ऑन्टोलॉजी (क्लास, ऑब्जेक्ट प्रॉपर्टी और डेटाटाइप प्रॉपर्टी) में प्रत्येक तत्व को संसाधित करता है और एम्बेडिंगक्लाइंटस्पेसिफिकेशन सेवा का उपयोग करके वेक्टर एम्बेडिंग उत्पन्न करता है। प्रत्येक तत्व के लिए, यह तत्व की पहचानकर्ता, लेबल और विवरण (टिप्पणी) को मिलाकर एक टेक्स्ट प्रतिनिधित्व बनाता है। इस टेक्स्ट को तब एक उच्च-आयामी वेक्टर एम्बेडिंग में परिवर्तित किया जाता है जो इसके सिमेंटिक अर्थ को कैप्चर करता है। ये एम्बेडिंग, तत्व प्रकार, स्रोत ऑन्टोलॉजी और पूर्ण परिभाषा के बारे में मेटाडेटा के साथ, प्रति-फ्लो इन-मेमोरी FAISS वेक्टर स्टोर में संग्रहीत किए जाते हैं। एम्बेडर स्वचालित रूप से पहले एम्बेडिंग प्रतिक्रिया से एम्बेडिंग आयाम का पता लगाता है। + +**मुख्य कार्य**: +तत्व आईडी, लेबल और टिप्पणियों से टेक्स्ट प्रतिनिधित्व बनाएं +बैच प्रोसेसिंग के लिए asyncio.gather का उपयोग करके एम्बेडिंगक्लाइंटस्पेसिफिकेशन के माध्यम से एम्बेडिंग उत्पन्न करें +व्यापक मेटाडेटा के साथ FAISS वेक्टर स्टोर में एम्बेडिंग संग्रहीत करें +कुशल पुनर्प्राप्ति के लिए ऑन्टोलॉजी, तत्व प्रकार और तत्व आईडी द्वारा अनुक्रमित करें +वेक्टर स्टोर इनिशियलाइज़ेशन के लिए एम्बेडिंग आयामों का स्वचालित रूप से पता लगाएं +स्वतंत्र वेक्टर स्टोर के साथ प्रति-फ्लो एम्बेडिंग मॉडल को संभालें + +**कार्यान्वयन स्थान**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. टेक्स्ट प्रोसेसर (वाक्य विभाजक) + +**उद्देश्य**: सटीक ऑन्टोलॉजी मिलान के लिए टेक्स्ट चंक्स को बारीक खंडों में विघटित करता है। + +**कार्यान्वयन**: +टेक्स्ट प्रोसेसर, वाक्य टोकनाइजेशन और POS टैगिंग के लिए NLTK का उपयोग करता है ताकि आने वाले टेक्स्ट चंक्स को वाक्यों में तोड़ा जा सके। यह NLTK संस्करण अनुकूलता को संभालने के लिए `punkt_tab` और `averaged_perceptron_tagger_eng` डाउनलोड करने का प्रयास करता है, और यदि आवश्यक हो तो पुराने संस्करणों पर वापस आ जाता है। प्रत्येक टेक्स्ट चंक को व्यक्तिगत वाक्यों में विभाजित किया जाता है जिन्हें स्वतंत्र रूप से ऑन्टोलॉजी तत्वों के खिलाफ मिलान किया जा सकता है। + +**मुख्य कार्य**: +NLTK वाक्य टोकनाइजेशन का उपयोग करके टेक्स्ट को वाक्यों में विभाजित करें +NLTK संस्करण अनुकूलता को संभालें (punkt_tab बनाम punkt) +टेक्स्ट और स्थिति जानकारी के साथ TextSegment ऑब्जेक्ट बनाएं +पूर्ण वाक्यों और व्यक्तिगत चंक्स दोनों का समर्थन करें + +**कार्यान्वयन स्थान**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. ऑन्टोलॉजी चयनकर्ता + +**उद्देश्य**: वर्तमान टेक्स्ट चंक के लिए सबसे प्रासंगिक ऑन्टोलॉजी तत्वों का सबसे उपयुक्त उपसमुच्चय की पहचान करता है। + +**कार्यान्वयन**: +ऑन्टोलॉजी चयनकर्ता, FAISS वेक्टर समानता खोज का उपयोग करके टेक्स्ट सेगमेंट और ऑन्टोलॉजी तत्वों के बीच सिमेंटिक मिलान करता है। प्रत्येक टेक्स्ट चंक से प्रत्येक वाक्य के लिए, यह एक एम्बेडिंग उत्पन्न करता है और कॉन्फ़िगर करने योग्य थ्रेसहोल्ड (डिफ़ॉल्ट 0.3) के साथ कोसाइन समानता का उपयोग करके वेक्टर स्टोर में सबसे समान ऑन्टोलॉजी तत्वों की खोज करता है। सभी प्रासंगिक तत्वों को एकत्र करने के बाद, यह व्यापक निर्भरता संकल्प करता है: यदि कोई क्लास का चयन किया जाता है, तो उसके पैरेंट क्लास शामिल होते हैं; यदि कोई प्रॉपर्टी का चयन किया जाता है, तो उसके डोमेन और रेंज क्लास जोड़े जाते हैं। इसके अतिरिक्त, प्रत्येक चयनित क्लास के लिए, यह स्वचालित रूप से **सभी प्रॉपर्टी को शामिल करता है जो उस क्लास को उनके डोमेन या रेंज में संदर्भित करती हैं**। यह सुनिश्चित करता है कि निष्कर्षण के पास सभी प्रासंगिक संबंध प्रॉपर्टी तक पहुंच है। + +**मुख्य कार्य:** +प्रत्येक पाठ खंड के लिए एम्बेडिंग उत्पन्न करें (वाक्य) +FAISS वेक्टर स्टोर में k-निकटतम पड़ोसी खोज करें (top_k=10, threshold=0.3) +कमजोर मिलानों को फ़िल्टर करने के लिए समानता सीमा लागू करें +निर्भरताएँ हल करें (पैरेंट क्लास, डोमेन, रेंज) +**चयनित कक्षाओं से संबंधित सभी गुणों को स्वचालित रूप से शामिल करें** (डोमेन/रेंज मिलान) +सभी आवश्यक संबंधों के साथ सुसंगत ऑन्टोलॉजी उपसमुच्चय बनाएं +ऐसे तत्व डुप्लिकेट करें जो कई बार दिखाई देते हैं + +**कार्यान्वयन स्थान:** `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. प्रॉम्प्ट निर्माण + +**उद्देश्य:** संरचित प्रॉम्प्ट बनाता है जो LLM को केवल ऑन्टोलॉजी-अनुरूप ट्रिपल निकालने के लिए मार्गदर्शन करता है। + +**कार्यान्वयन:** +निष्कर्षण सेवा एक Jinja2 टेम्पलेट का उपयोग करती है जिसे `ontology-prompt.md` से लोड किया जाता है जो LLM निष्कर्षण के लिए ऑन्टोलॉजी उपसमुच्चय और पाठ को प्रारूपित करता है। टेम्पलेट गतिशील रूप से Jinja2 सिंटैक्स का उपयोग करके कक्षाओं, ऑब्जेक्ट गुणों और डेटाटाइप गुणों पर पुनरावृति करता है, प्रत्येक को उनके विवरण, डोमेन, रेंज और पदानुक्रमित संबंधों के साथ प्रस्तुत करता है। प्रॉम्प्ट में केवल प्रदान किए गए ऑन्टोलॉजी तत्वों का उपयोग करने के बारे में सख्त नियम शामिल हैं और सुसंगत पार्सिंग के लिए JSON आउटपुट प्रारूप का अनुरोध करता है। + +**मुख्य कार्य:** +ऑन्टोलॉजी तत्वों पर लूप के साथ Jinja2 टेम्पलेट का उपयोग करें +पैरेंट रिलेशनशिप (subclass_of) और टिप्पणियों के साथ कक्षाओं को प्रारूपित करें +डोमेन/रेंज बाधाओं और टिप्पणियों के साथ गुणों को प्रारूपित करें +स्पष्ट निष्कर्षण नियमों और आउटपुट प्रारूप आवश्यकताओं को शामिल करें +"extract-with-ontologies" टेम्पलेट आईडी के साथ प्रॉम्प्ट सेवा को कॉल करें + +**टेम्पलेट स्थान:** `ontology-prompt.md` +**कार्यान्वयन स्थान:** `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (build_extraction_variables विधि) + +#### 6. मुख्य निष्कर्षण सेवा + +**उद्देश्य:** एंड-टू-एंड ऑन्टोलॉजी-आधारित ट्रिपल निष्कर्षण करने के लिए सभी घटकों का समन्वय करें। + +**कार्यान्वयन:** +मुख्य निष्कर्षण सेवा (KgExtractOntology) ऑर्केस्ट्रेशन परत है जो संपूर्ण निष्कर्षण वर्कफ़्लो का प्रबंधन करती है। यह प्रति-प्रवाह घटक प्रारंभिकरण के साथ TrustGraph के FlowProcessor पैटर्न का उपयोग करता है। जब कोई ऑन्टोलॉजी कॉन्फ़िगरेशन अपडेट प्राप्त होता है, तो यह प्रवाह-विशिष्ट घटकों (ऑन्टोलॉजी लोडर, एम्बेडर, टेक्स्ट प्रोसेसर, सेलेक्टर) को आरंभ या अपडेट करता है। जब प्रसंस्करण के लिए एक पाठ खंड प्राप्त होता है, तो यह पाइपलाइन का समन्वय करता है: पाठ को खंडों में विभाजित करना, वेक्टर खोज के माध्यम से प्रासंगिक ऑन्टोलॉजी तत्वों को खोजना, एक प्रतिबंधित प्रॉम्प्ट का निर्माण करना, प्रॉम्प्ट सेवा को कॉल करना, प्रतिक्रिया को पार्स और मान्य करना, ऑन्टोलॉजी परिभाषा ट्रिपल उत्पन्न करना और सामग्री ट्रिपल और इकाई संदर्भ दोनों का उत्सर्जन करना। + +**निष्कर्षण पाइपलाइन:** +1. chunks-input क्यू के माध्यम से पाठ खंड प्राप्त करें +2. यदि आवश्यक हो तो प्रवाह घटकों को आरंभ करें (पहले खंड या कॉन्फ़िगरेशन अपडेट पर) +3. NLTK का उपयोग करके पाठ को वाक्यों में विभाजित करें +4. प्रासंगिक ऑन्टोलॉजी अवधारणाओं को खोजने के लिए FAISS वेक्टर स्टोर खोजें +5. स्वचालित संपत्ति समावेश के साथ ऑन्टोलॉजी उपसमुच्चय बनाएं +6. Jinja2-टेम्प्लेटेड प्रॉम्प्ट चर बनाएं +7. extract-with-ontologies टेम्पलेट के साथ प्रॉम्प्ट सेवा को कॉल करें +8. संरचित ट्रिपल में JSON प्रतिक्रिया को पार्स करें +9. ट्रिपल को मान्य करें और पूर्ण ऑन्टोलॉजी URIs का उपयोग करके URIs का विस्तार करें +10. ऑन्टोलॉजी परिभाषा ट्रिपल (लेबल/टिप्पणी/डोमेन/रेंज के साथ कक्षाएं और गुण) उत्पन्न करें +11. सभी ट्रिपल से इकाई संदर्भ बनाएं +12. ट्रिपल और इकाई-संदर्भ क्यू पर उत्सर्जित करें + +**मुख्य विशेषताएं:** +विभिन्न एम्बेडिंग मॉडल का समर्थन करने वाले प्रति-प्रवाह वेक्टर स्टोर +config-update क्यू के माध्यम से घटना-संचालित ऑन्टोलॉजी अपडेट +ऑन्टोलॉजी URIs का उपयोग करके स्वचालित URI विस्तार +पूर्ण मेटाडेटा के साथ ज्ञान ग्राफ में जोड़े गए ऑन्टोलॉजी तत्व +इकाई संदर्भों में सामग्री और ऑन्टोलॉजी तत्व दोनों शामिल हैं + +**कार्यान्वयन स्थान:** `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### कॉन्फ़िगरेशन + +सेवा कमांड-लाइन तर्कों के साथ TrustGraph के मानक कॉन्फ़िगरेशन दृष्टिकोण का उपयोग करती है: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**मुख्य कॉन्फ़िगरेशन पैरामीटर**: +`similarity_threshold`: 0.3 (डिफ़ॉल्ट, कोड में कॉन्फ़िगर करने योग्य) +`top_k`: 10 (प्रत्येक खंड के लिए पुनः प्राप्त होने वाले ऑन्टोलॉजी तत्वों की संख्या) +`vector_store`: ऑटो-डिटेक्टेड आयामों के साथ प्रति-फ़्लो FAISS IndexFlatIP +`text_processor`: NLTK के साथ punt_tab वाक्य टोकनाइजेशन +`prompt_template`: "extract-with-ontologies" (Jinja2 टेम्पलेट) + +**ऑन्टोलॉजी कॉन्फ़िगरेशन**: +ऑन्टोलॉजी को "ontology" प्रकार के साथ कॉन्फ़िग-अपडेट कतार के माध्यम से गतिशील रूप से लोड किया जाता है। + +### डेटा प्रवाह + +1. **आरंभीकरण चरण** (प्रति-फ़्लो): + कॉन्फ़िग-अपडेट कतार के माध्यम से ऑन्टोलॉजी कॉन्फ़िगरेशन प्राप्त करें + ऑन्टोलॉजी JSON को OntologyClass और OntologyProperty ऑब्जेक्ट में पार्स करें + EmbeddingsClientSpec का उपयोग करके सभी ऑन्टोलॉजी तत्वों के लिए एम्बेडिंग उत्पन्न करें + प्रति-फ़्लो FAISS वेक्टर स्टोर में एम्बेडिंग संग्रहीत करें + पहले प्रतिक्रिया से एम्बेडिंग आयामों का ऑटो-डिटेक्शन + +2. **निष्कर्षण चरण** (प्रति-खंड): + chunks-input कतार से खंड प्राप्त करें + NLTK का उपयोग करके खंड को वाक्यों में विभाजित करें + प्रत्येक वाक्य के लिए एम्बेडिंग की गणना करें + प्रासंगिक ऑन्टोलॉजी तत्वों के लिए FAISS वेक्टर स्टोर खोजें + स्वचालित संपत्ति समावेश के साथ ऑन्टोलॉजी उपसमुच्चय बनाएं + पाठ और ऑन्टोलॉजी के साथ Jinja2 टेम्पलेट चर बनाएं + extract-with-ontologies टेम्पलेट के साथ प्रॉम्प्ट सेवा को कॉल करें + JSON प्रतिक्रिया को पार्स करें और ट्रिपल को मान्य करें + ऑन्टोलॉजी URIs का उपयोग करके URIs का विस्तार करें + ऑन्टोलॉजी परिभाषा ट्रिपल उत्पन्न करें + सभी ट्रिपल से इकाई संदर्भ बनाएं + ट्रिपल और इकाई-संदर्भ कतारों पर उत्सर्जित करें + +### इन-मेमोरी वेक्टर स्टोर + +**उद्देश्य**: ऑन्टोलॉजी तत्व मिलान के लिए तेज़, मेमोरी-आधारित समानता खोज प्रदान करता है। + +**कार्यान्वयन: FAISS** + +सिस्टम **FAISS (फेसबुक एआई समानता खोज)** का उपयोग सटीक कोसाइन समानता खोज के लिए IndexFlatIP के साथ करता है। मुख्य विशेषताएं: + +**IndexFlatIP**: आंतरिक उत्पाद का उपयोग करके सटीक कोसाइन समानता खोज +**ऑटो-डिटेक्शन**: पहले एम्बेडिंग प्रतिक्रिया से आयाम निर्धारित होता है +**प्रति-फ़्लो स्टोर**: प्रत्येक फ़्लो में विभिन्न एम्बेडिंग मॉडल के लिए एक स्वतंत्र वेक्टर स्टोर होता है +**सामान्यीकरण**: अनुक्रमण से पहले सभी वेक्टर सामान्य होते हैं +**बैच ऑपरेशन**: प्रारंभिक ऑन्टोलॉजी लोडिंग के लिए कुशल बैच जोड़ + +**कार्यान्वयन स्थान**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### ऑन्टोलॉजी उपसमुच्चय चयन एल्गोरिदम + +**उद्देश्य**: प्रत्येक पाठ खंड के लिए ऑन्टोलॉजी के न्यूनतम प्रासंगिक भाग का गतिशील रूप से चयन करता है। + +**विस्तृत एल्गोरिदम चरण**: + +1. **पाठ विभाजन**: + NLP वाक्य पहचान का उपयोग करके इनपुट खंड को वाक्यों में विभाजित करें + प्रत्येक वाक्य से संज्ञा वाक्यांश, क्रिया वाक्यांश और नामित संस्थाएं निकालें + संदर्भ को संरक्षित करते हुए खंडों की एक पदानुक्रमित संरचना बनाएं + +2. **एम्बेडिंग पीढ़ी**: + प्रत्येक पाठ खंड (वाक्यों और वाक्यांशों) के लिए वेक्टर एम्बेडिंग उत्पन्न करें + ऑन्टोलॉजी तत्वों के लिए उपयोग किए गए समान एम्बेडिंग मॉडल का उपयोग करें + प्रदर्शन में सुधार के लिए बार-बार खंडों के लिए एम्बेडिंग कैश करें + +3. **समानता खोज**: + प्रत्येक पाठ खंड एम्बेडिंग के लिए, वेक्टर स्टोर खोजें + शीर्ष-k (जैसे, 10) सबसे समान ऑन्टोलॉजी तत्वों को पुनः प्राप्त करें + कमजोर मिलानों को फ़िल्टर करने के लिए समानता थ्रेसहोल्ड (जैसे, 0.7) लागू करें + सभी खंडों में परिणामों को एकत्रित करें, मिलान आवृत्तियों को ट्रैक करें + +4. **निर्भरता संकल्प**: + प्रत्येक चयनित वर्ग के लिए, रूट तक सभी मूल वर्गों को पुनरावर्ती रूप से शामिल करें + प्रत्येक चयनित संपत्ति के लिए, इसके डोमेन और रेंज कक्षाओं को शामिल करें + उलटे गुणों के लिए, सुनिश्चित करें कि दोनों दिशाएं शामिल हैं + यदि ऑन्टोलॉजी में मौजूद हैं तो समकक्ष कक्षाओं को जोड़ें + +5. **उपसमुच्चय निर्माण**: + संबंधों को संरक्षित करते हुए एकत्र किए गए तत्वों को डुप्लिकेट करें + कक्षाओं, ऑब्जेक्ट गुणों और डेटा प्रकार गुणों में व्यवस्थित करें + सुनिश्चित करें कि सभी बाधाएं और संबंध संरक्षित हैं + एक स्व-निहित मिनी-ऑन्टोलॉजी बनाएं जो मान्य और पूर्ण हो + +**उदाहरण वॉकथ्रू**: +पाठ: "भूरे रंग का कुत्ता सफेद बिल्ली को पेड़ पर दौड़ाता है।" +खंड: ["भूरा कुत्ता", "सफेद बिल्ली", "पेड़", "दौड़ाता है"] +मिलान किए गए तत्व: [कुत्ता (वर्ग), बिल्ली (वर्ग), जानवर (मूल), पीछा करता है (संपत्ति)] +निर्भरता: [जानवर (कुत्ते और बिल्ली का मूल), जीवनरूप (जानवर का मूल)] +अंतिम उपसमुच्चय: जानवर पदानुक्रम और पीछा संबंध के साथ पूर्ण मिनी-ऑन्टोलॉजी + +### ट्रिपल सत्यापन + +**उद्देश्य**: सुनिश्चित करता है कि सभी निकाले गए ट्रिपल सख्ती से ऑन्टोलॉजी बाधाओं का पालन करते हैं। + +**सत्यापन एल्गोरिदम**: + +1. **वर्ग सत्यापन**: + सत्यापित करें कि विषय, शब्दावली उपसमुच्चय में परिभाषित वर्गों के उदाहरण हैं। + ऑब्जेक्ट गुणों के लिए, सत्यापित करें कि ऑब्जेक्ट भी मान्य वर्ग उदाहरण हैं। + वर्ग नामों की तुलना शब्दावली के वर्ग शब्दकोश से करें। + वर्ग पदानुक्रमों को संभालें - उपवर्गों के उदाहरण मूल वर्ग बाधाओं के लिए मान्य हैं। + +2. **गुण सत्यापन**: + पुष्टि करें कि विधेय शब्दावली उपसमुच्चय में गुणों से मेल खाते हैं। + ऑब्जेक्ट गुणों (इकाई-से-इकाई) और डेटा प्रकार गुणों (इकाई-से-लिटरल) के बीच अंतर करें। + सत्यापित करें कि संपत्ति नाम बिल्कुल मेल खाते हैं (यदि मौजूद है तो नामस्थान पर विचार करते हुए)। + +3. **डोमेन/रेंज जाँच**: + प्रत्येक संपत्ति के लिए जिसका उपयोग विधेय के रूप में किया जाता है, उसका डोमेन और रेंज प्राप्त करें। + सत्यापित करें कि विषय का प्रकार संपत्ति के डोमेन से मेल खाता है या उससे विरासत में मिला है। + सत्यापित करें कि ऑब्जेक्ट का प्रकार संपत्ति के रेंज से मेल खाता है या उससे विरासत में मिला है। + डेटा प्रकार गुणों के लिए, सत्यापित करें कि ऑब्जेक्ट सही XSD प्रकार का एक लिटरल है। + +4. **कार्डिनैलिटी सत्यापन**: + प्रति विषय संपत्ति उपयोग गणनाओं को ट्रैक करें। + न्यूनतम कार्डिनैलिटी की जाँच करें - सुनिश्चित करें कि आवश्यक गुण मौजूद हैं। + अधिकतम कार्डिनैलिटी की जाँच करें - सुनिश्चित करें कि संपत्ति का उपयोग बहुत अधिक बार नहीं किया गया है। + कार्यात्मक गुणों के लिए, सुनिश्चित करें कि प्रति विषय अधिकतम एक मान है। + +5. **डेटा प्रकार सत्यापन**: + उनके घोषित XSD प्रकारों के अनुसार लिटरल मानों को पार्स करें। + सत्यापित करें कि पूर्णांक मान्य संख्याएँ हैं, तिथियाँ ठीक से स्वरूपित हैं, आदि। + यदि regex बाधाएँ परिभाषित हैं तो स्ट्रिंग पैटर्न की जाँच करें। + सुनिश्चित करें कि URIs xsd:anyURI प्रकारों के लिए अच्छी तरह से स्वरूपित हैं। + +**सत्यापन उदाहरण**: +ट्रिपल: ("बडी", "has-owner", "जॉन") +जाँचें कि "बडी" को एक ऐसे वर्ग के रूप में टाइप किया गया है जिसके पास "has-owner" संपत्ति हो सकती है। +जाँचें कि "has-owner" शब्दावली में मौजूद है। +डोमेन बाधा का सत्यापन: विषय को "पालतू" प्रकार या उपवर्ग का होना चाहिए। +रेंज बाधा का सत्यापन: ऑब्जेक्ट को "व्यक्ति" प्रकार या उपवर्ग का होना चाहिए। +यदि मान्य है, तो आउटपुट में जोड़ें; यदि अमान्य है, तो उल्लंघन को लॉग करें और छोड़ दें। + +## प्रदर्शन संबंधी विचार + +### अनुकूलन रणनीतियाँ + +1. **एम्बेडिंग कैशिंग**: बार-बार उपयोग किए जाने वाले पाठ खंडों के लिए एम्बेडिंग कैश करें। +2. **बैच प्रोसेसिंग**: कई खंडों को समानांतर में संसाधित करें। +3. **वेक्टर स्टोर इंडेक्सिंग**: बड़े शब्दावली के लिए अनुमानित निकटतम पड़ोसी एल्गोरिदम का उपयोग करें। +4. **प्रॉम्प्ट अनुकूलन**: केवल आवश्यक शब्दावली तत्वों को शामिल करके प्रॉम्प्ट आकार को कम करें। +5. **परिणाम कैशिंग**: समान टुकड़ों के लिए निष्कर्षण परिणामों को कैश करें। + +### मापनीयता + +**क्षैतिज स्केलिंग**: साझा शब्दावली कैश के साथ कई एक्सट्रैक्टर उदाहरण। +**शब्दावली विभाजन**: बड़े शब्दावली को डोमेन द्वारा विभाजित करें। +**स्ट्रीमिंग प्रोसेसिंग**: बैचिंग के बिना आने वाले टुकड़ों को संसाधित करें। +**मेमोरी प्रबंधन**: अप्रयुक्त एम्बेडिंग की आवधिक सफाई। + +## त्रुटि प्रबंधन + +### विफलता परिदृश्य + +1. **गायब शब्दावली**: बिना बाधा वाले निष्कर्षण पर वापस जाएँ। +2. **एम्बेडिंग सेवा विफलता**: कैश किए गए एम्बेडिंग का उपयोग करें या सिमेंटिक मिलान छोड़ दें। +3. **प्रॉम्प्ट सेवा टाइमआउट**: घातीय बैकऑफ़ के साथ पुनः प्रयास करें। +4. **अमान्य ट्रिपल प्रारूप**: लॉग करें और खराब ट्रिपल छोड़ दें। +5. **शब्दावली असंगतताएँ**: संघर्षों की रिपोर्ट करें और सबसे विशिष्ट मान्य तत्वों का उपयोग करें। + +### निगरानी + +ट्रैक करने के लिए प्रमुख मेट्रिक्स: + +शब्दावली लोड समय और मेमोरी उपयोग +एम्बेडिंग पीढ़ी विलंबता +वेक्टर खोज प्रदर्शन +प्रॉम्प्ट सेवा प्रतिक्रिया समय +ट्रिपल निष्कर्षण सटीकता +शब्दावली अनुरूपता दर + +## माइग्रेशन पथ + +### मौजूदा निष्कर्षक से + +1. **समानांतर संचालन**: शुरू में मौजूदा निष्कर्षक के साथ समानांतर में चलाएँ। +2. **धीरे-धीरे रोलआउट**: विशिष्ट दस्तावेज़ प्रकारों के साथ प्रारंभ करें। +3. **गुणवत्ता तुलना**: मौजूदा निष्कर्षक के साथ आउटपुट गुणवत्ता की तुलना करें। +4. **पूर्ण माइग्रेशन**: गुणवत्ता सत्यापित होने के बाद मौजूदा निष्कर्षक को बदलें। + +### शब्दावली विकास + +1. **मौजूदा से बूटस्ट्रैप करें**: मौजूदा ज्ञान से प्रारंभिक शब्दावली उत्पन्न करें। +2. **पुनरावृत्त परिशोधन**: निष्कर्षण पैटर्न के आधार पर परिष्कृत करें। +3. **डोमेन विशेषज्ञ समीक्षा**: विषय वस्तु विशेषज्ञों के साथ मान्य करें। +4. **लगातार सुधार**: निष्कर्षण प्रतिक्रिया के आधार पर अपडेट करें। + +## शब्दावली-संवेदनशील क्वेरी सेवा + +### अवलोकन + +शब्दावली-संवेदनशील क्वेरी सेवा विभिन्न बैकएंड ग्राफ स्टोर का समर्थन करने के लिए कई क्वेरी पथ प्रदान करती है। यह सटीक, सिमेंटिक रूप से-जागरूक प्रश्न उत्तर के लिए कैसेंड्रा (SPARQL के माध्यम से) और साइफर-आधारित ग्राफ स्टोर (Neo4j, Memgraph, FalkorDB) दोनों में शब्दावली ज्ञान का लाभ उठाता है। + +**सेवा घटक**: +`onto-query-sparql`: कैसेंड्रा के लिए प्राकृतिक भाषा को SPARQL में परिवर्तित करता है। +`sparql-cassandra`: कैसेंड्रा के लिए SPARQL क्वेरी परत rdflib का उपयोग करके। +`onto-query-cypher`: ग्राफ डेटाबेस के लिए प्राकृतिक भाषा को साइफर में परिवर्तित करता है। +`cypher-executor`: Neo4j/Memgraph/FalkorDB के लिए साइफर क्वेरी निष्पादन। + +### आर्किटेक्चर + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### क्वेरी प्रोसेसिंग पाइपलाइन + +#### 1. प्रश्न विश्लेषक + +**उद्देश्य**: उपयोगकर्ता के प्रश्नों को अर्थ संबंधी घटकों में विघटित करता है ताकि ऑन्टोलॉजी मिलान किया जा सके। + +**एल्गोरिदम विवरण**: +प्रश्न विश्लेषक, आने वाले प्राकृतिक भाषा प्रश्न को लेता है और इसे सार्थक खंडों में तोड़ता है, निष्कर्षण पाइपलाइन के समान वाक्य विभाजन दृष्टिकोण का उपयोग करके। यह प्रश्न में उल्लिखित प्रमुख संस्थाओं, संबंधों और बाधाओं की पहचान करता है। प्रत्येक खंड का विश्लेषण प्रश्न के प्रकार (तथ्यात्मक, एकत्रीकरण, तुलना, आदि) और अपेक्षित उत्तर प्रारूप के लिए किया जाता है। यह विघटन यह पहचानने में मदद करता है कि ऑन्टोलॉजी का कौन सा भाग प्रश्न का उत्तर देने के लिए सबसे अधिक प्रासंगिक है। + +**मुख्य कार्य**: +प्रश्न को वाक्यों और वाक्यांशों में विभाजित करें +प्रश्न के प्रकार और इरादे की पहचान करें +उल्लिखित संस्थाओं और संबंधों को निकालें +प्रश्न में बाधाओं और फ़िल्टरों का पता लगाएं +अपेक्षित उत्तर प्रारूप निर्धारित करें + +#### 2. प्रश्नों के लिए ऑन्टोलॉजी मिलानकर्ता + +**उद्देश्य**: प्रश्न का उत्तर देने के लिए आवश्यक प्रासंगिक ऑन्टोलॉजी उपसमुच्चय की पहचान करता है। + +**एल्गोरिदम विवरण**: +निष्कर्षण पाइपलाइन के ऑन्टोलॉजी चयनकर्ता के समान, लेकिन प्रश्न उत्तर देने के लिए अनुकूलित। मिलानकर्ता प्रश्न खंडों के लिए एम्बेडिंग उत्पन्न करता है और प्रासंगिक ऑन्टोलॉजी तत्वों को खोजने के लिए वेक्टर स्टोर में खोज करता है। हालांकि, यह निष्कर्षण के बजाय प्रश्न निर्माण के लिए उपयोगी होने वाले अवधारणाओं को खोजने पर ध्यान केंद्रित करता है। यह चयन को संबंधित गुणों को शामिल करने के लिए विस्तारित करता है जो ग्राफ अन्वेषण के दौरान पारगमन योग्य हो सकते हैं, भले ही उन्हें प्रश्न में स्पष्ट रूप से उल्लेख न किया गया हो। उदाहरण के लिए, यदि "कर्मचारियों" के बारे में पूछा जाता है, तो यह "काम करता है," "प्रबंधित करता है," और "रिपोर्ट करता है" जैसे गुणों को शामिल कर सकता है जो कर्मचारी जानकारी खोजने के लिए प्रासंगिक हो सकते हैं। + +**मिलान रणनीति**: +प्रश्न खंडों को एम्बेड करें +सीधे उल्लिखित ऑन्टोलॉजी अवधारणाओं को खोजें +उल्लिखित वर्गों को जोड़ने वाले गुणों को शामिल करें +पारगमन के लिए व्युत्क्रम और संबंधित गुणों को जोड़ें +पदानुक्रमित प्रश्नों के लिए मूल/चाइल्ड कक्षाओं को शामिल करें +प्रश्न-केंद्रित ऑन्टोलॉजी विभाजन बनाएं + +#### 3. बैकएंड राउटर + +**उद्देश्य**: कॉन्फ़िगरेशन के आधार पर प्रश्नों को उपयुक्त बैकएंड-विशिष्ट क्वेरी पथ पर रूट करता है। + +**एल्गोरिदम विवरण**: +बैकएंड राउटर यह निर्धारित करने के लिए सिस्टम कॉन्फ़िगरेशन की जांच करता है कि कौन सा ग्राफ बैकएंड सक्रिय है (कैसेंड्रा या साइफर-आधारित)। यह प्रश्न और ऑन्टोलॉजी विभाजन को उपयुक्त क्वेरी पीढ़ी सेवा पर रूट करता है। राउटर कई बैकएंड में लोड संतुलन का भी समर्थन कर सकता है या यदि प्राथमिक बैकएंड अनुपलब्ध है तो बैकअप तंत्र प्रदान कर सकता है। + +**राउटिंग तर्क**: +सिस्टम सेटिंग्स से कॉन्फ़िगर किए गए बैकएंड प्रकार की जांच करें +कैसेंड्रा बैकएंड के लिए `onto-query-sparql` पर रूट करें +Neo4j/Memgraph/FalkorDB के लिए `onto-query-cypher` पर रूट करें +क्वेरी वितरण के साथ मल्टी-बैकएंड कॉन्फ़िगरेशन का समर्थन करें +विफल-ओवर और लोड संतुलन परिदृश्यों को संभालें + +#### 4. SPARQL क्वेरी पीढ़ी (`onto-query-sparql`) + +**उद्देश्य**: कैसेंड्रा निष्पादन के लिए प्राकृतिक भाषा प्रश्नों को SPARQL प्रश्नों में परिवर्तित करता है। + +**एल्गोरिदम विवरण**: +SPARQL क्वेरी जनरेटर प्रश्न और ऑन्टोलॉजी विभाजन लेता है और कैसेंड्रा बैकएंड के खिलाफ निष्पादन के लिए अनुकूलित एक SPARQL क्वेरी बनाता है। यह RDF/OWL सिमेंटिक्स को शामिल करने वाले एक SPARQL-विशिष्ट टेम्पलेट के साथ प्रॉम्प्ट सेवा का उपयोग करता है। जनरेटर SPARQL पैटर्न को समझता है जैसे कि प्रॉपर्टी पथ, वैकल्पिक खंड और फ़िल्टर जो कैसेंड्रा ऑपरेशनों में कुशलता से अनुवाद कर सकते हैं। + +**SPARQL पीढ़ी प्रॉम्प्ट टेम्पलेट**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. सिफर क्वेरी जनरेशन (`onto-query-cypher`) + +**उद्देश्य**: प्राकृतिक भाषा के प्रश्नों को ग्राफ डेटाबेस के लिए सिफर क्वेरी में परिवर्तित करता है। + +**एल्गोरिदम विवरण**: +सिफर क्वेरी जनरेटर, Neo4j, Memgraph और FalkorDB के लिए अनुकूलित मूल सिफर क्वेरी बनाता है। यह ऑन्टोलॉजी कक्षाओं को नोड लेबल और गुणों को संबंधों में मैप करता है, और सिफर के पैटर्न मिलान सिंटैक्स का उपयोग करता है। जनरेटर में सिफर-विशिष्ट अनुकूलन शामिल हैं, जैसे कि संबंध दिशा संकेत, इंडेक्स का उपयोग और क्वेरी प्लानिंग संकेत। + +**सिफर जनरेशन प्रॉम्प्ट टेम्पलेट**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. SPARQL-कैसेंड्रा क्वेरी इंजन (`sparql-cassandra`) + +**उद्देश्य**: यह पाइथन rdflib का उपयोग करके कैसेंड्रा के विरुद्ध SPARQL क्वेरी निष्पादित करता है। + +**एल्गोरिदम विवरण**: +SPARQL-कैसेंड्रा इंजन, पाइथन की rdflib लाइब्रेरी का उपयोग करके एक SPARQL प्रोसेसर को लागू करता है, जिसमें एक कस्टम कैसेंड्रा बैकएंड स्टोर होता है। यह SPARQL ग्राफ पैटर्न को उपयुक्त कैसेंड्रा CQL क्वेरी में अनुवाद करता है, जिसमें जॉइन, फ़िल्टर और एग्रीगेशन शामिल हैं। इंजन एक RDF-से-कैसेंड्रा मैपिंग बनाए रखता है जो सिमेंटिक संरचना को संरक्षित करता है, साथ ही कैसेंड्रा के कॉलम-फैमिली स्टोरेज मॉडल के लिए अनुकूलन करता है। + +**कार्यान्वयन विशेषताएं**: +कैसेंड्रा के लिए rdflib स्टोर इंटरफ़ेस कार्यान्वयन +सामान्य पैटर्न के साथ SPARQL 1.1 क्वेरी समर्थन +ट्रिपल पैटर्न का CQL में कुशल अनुवाद +प्रॉपर्टी पाथ और पदानुक्रमित क्वेरी के लिए समर्थन +बड़े डेटासेट के लिए परिणाम स्ट्रीमिंग +कनेक्शन पूलिंग और क्वेरी कैशिंग + +**उदाहरण अनुवाद**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +अनुकूलित कैसेंड्रा प्रश्नों का अनुवाद, जो इंडेक्स और विभाजन कुंजियों का उपयोग करते हैं। + +#### 7. साइफर क्वेरी एग्जीक्यूटर (`cypher-executor`) + +**उद्देश्य**: नियो4जे, मेमग्राफ और फाल्कोर्डबी के खिलाफ साइफर प्रश्नों को निष्पादित करता है। + +**एल्गोरिदम विवरण**: +साइफर एग्जीक्यूटर विभिन्न ग्राफ डेटाबेस में साइफर प्रश्नों को निष्पादित करने के लिए एक एकीकृत इंटरफ़ेस प्रदान करता है। यह डेटाबेस-विशिष्ट कनेक्शन प्रोटोकॉल, क्वेरी अनुकूलन संकेतों और परिणाम प्रारूप सामान्यीकरण को संभालता है। एग्जीक्यूटर में प्रत्येक डेटाबेस प्रकार के लिए उपयुक्त पुन: प्रयास तर्क, कनेक्शन पूलिंग और लेनदेन प्रबंधन शामिल हैं। + +**मल्टी-डेटाबेस समर्थन**: +**नियो4जे**: बोल्ट प्रोटोकॉल, लेनदेन फ़ंक्शन, इंडेक्स संकेत +**मेमग्राफ**: कस्टम प्रोटोकॉल, स्ट्रीमिंग परिणाम, विश्लेषणात्मक प्रश्न +**फाल्कोर्डबी**: रेडिस प्रोटोकॉल अनुकूलन, इन-मेमोरी अनुकूलन + +**निष्पादन विशेषताएं**: +डेटाबेस-अज्ञेय कनेक्शन प्रबंधन +क्वेरी सत्यापन और सिंटैक्स जांच +टाइमआउट और संसाधन सीमा प्रवर्तन +परिणाम पेजिंग और स्ट्रीमिंग +प्रत्येक डेटाबेस प्रकार के लिए प्रदर्शन निगरानी +डेटाबेस उदाहरणों के बीच स्वचालित फेलओवर + +#### 8. उत्तर जनरेटर + +**उद्देश्य**: क्वेरी परिणामों से एक प्राकृतिक भाषा उत्तर का संश्लेषण करता है। + +**एल्गोरिदम विवरण**: +उत्तर जनरेटर संरचित क्वेरी परिणामों और मूल प्रश्न को लेता है, और फिर एक व्यापक उत्तर उत्पन्न करने के लिए प्रॉम्प्ट सेवा का उपयोग करता है। साधारण टेम्पलेट-आधारित प्रतिक्रियाओं के विपरीत, यह ग्राफ डेटा को प्रश्न के संदर्भ में व्याख्या करने के लिए एक एलएलएम का उपयोग करता है, जटिल संबंधों, एग्रीगेशन और अनुमानों को संभालता है। जनरेटर ज्ञानकोश संरचना और ग्राफ से प्राप्त विशिष्ट ट्रिपल को संदर्भित करके अपनी तर्कसंगतता को समझा सकता है। + +**उत्तर पीढ़ी प्रक्रिया**: +क्वेरी परिणामों को संरचित संदर्भ में प्रारूपित करें +स्पष्टता के लिए प्रासंगिक ज्ञानकोश परिभाषाएँ शामिल करें +प्रश्न और परिणामों के साथ प्रॉम्प्ट बनाएं +एलएलएम के माध्यम से प्राकृतिक भाषा उत्तर उत्पन्न करें +क्वेरी इरादे के खिलाफ उत्तर को मान्य करें +यदि आवश्यक हो तो विशिष्ट ग्राफ संस्थाओं के लिए उद्धरण जोड़ें + +### मौजूदा सेवाओं के साथ एकीकरण + +#### ग्राफआरएजी के साथ संबंध + +**पूरक**: onto-query सिमेंटिक परिशुद्धता प्रदान करता है जबकि GraphRAG व्यापक कवरेज प्रदान करता है +**साझा बुनियादी ढांचा**: दोनों समान ज्ञानकोश और प्रॉम्प्ट सेवाओं का उपयोग करते हैं +**क्वेरी रूटिंग**: सिस्टम प्रश्न के प्रकार के आधार पर सबसे उपयुक्त सेवा में प्रश्नों को रूट कर सकता है +**हाइब्रिड मोड**: व्यापक उत्तरों के लिए दोनों दृष्टिकोणों को जोड़ सकता है + +#### ऑन्टोरैग निष्कर्षण के साथ संबंध + +**साझा ज्ञानकोश**: kg-extract-ontology द्वारा लोड किए गए समान ज्ञानकोश कॉन्फ़िगरेशन का उपयोग करता है +**साझा वेक्टर स्टोर**: निष्कर्षण सेवा से इन-मेमोरी एम्बेडिंग का पुन: उपयोग करता है +**संगत सिमेंटिक्स**: क्वेरी समान ऑन्टोलॉजिकल बाधाओं के साथ बनाए गए ग्राफ पर संचालित होती हैं + +### क्वेरी उदाहरण + +#### उदाहरण 1: साधारण इकाई क्वेरी +**प्रश्न**: "कौन से जानवर स्तनधारी हैं?" +**ज्ञानकोश मिलान**: [जानवर, स्तनधारी, उपवर्ग] +**उत्पन्न क्वेरी**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### उदाहरण 2: संबंध क्वेरी +**प्रश्न**: "जॉन स्मिथ द्वारा लिखित कौन से दस्तावेज़ हैं?" +**ऑन्टोलॉजी मिलान**: [दस्तावेज़, व्यक्ति, लेखक-है] +**उत्पन्न क्वेरी**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### उदाहरण 3: एकत्रीकरण क्वेरी +**प्रश्न**: "बिल्लियों के कितने पैर होते हैं?" +**ऑन्टोलॉजी मिलान**: [बिल्ली, पैरों की संख्या (डेटा प्रकार गुण)] +**उत्पन्न क्वेरी**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### कॉन्फ़िगरेशन + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### प्रदर्शन अनुकूलन + +#### क्वेरी अनुकूलन + +**ऑन्टोलॉजी छंटाई (Ontology Pruning)**: केवल आवश्यक ऑन्टोलॉजी तत्वों को प्रॉम्प्ट में शामिल करें। +**क्वेरी कैशिंग (Query Caching)**: बार-बार पूछे जाने वाले प्रश्नों और उनकी क्वेरी को कैश करें। +**परिणाम कैशिंग (Result Caching)**: समान प्रश्नों के लिए परिणामों को एक निश्चित समय अवधि के लिए संग्रहीत करें। +**बैच प्रोसेसिंग (Batch Processing)**: एक ही ग्राफ ट्रैवर्सल में कई संबंधित प्रश्नों को संभालें। + +#### स्केलेबिलिटी विचार + +**वितरित निष्पादन (Distributed Execution)**: उप-क्वेरी को ग्राफ विभाजनों में समानांतर करें। +**क्रमिक परिणाम (Incremental Results)**: बड़े डेटासेट के लिए परिणामों को स्ट्रीम करें। +**लोड बैलेंसिंग (Load Balancing)**: क्वेरी लोड को कई सेवा उदाहरणों में वितरित करें। +**संसाधन पूल (Resource Pools)**: ग्राफ डेटाबेस के लिए कनेक्शन पूल का प्रबंधन करें। + +### त्रुटि प्रबंधन + +#### विफलता परिदृश्य + +1. **अमान्य क्वेरी पीढ़ी (Invalid Query Generation)**: GraphRAG या सरल कीवर्ड खोज पर वापस जाएँ। +2. **ऑन्टोलॉजी बेमेल (Ontology Mismatch)**: व्यापक ऑन्टोलॉजी उपसमुच्चय में खोज का विस्तार करें। +3. **क्वेरी टाइमआउट (Query Timeout)**: क्वेरी को सरल बनाएं या टाइमआउट बढ़ाएं। +4. **खाली परिणाम (Empty Results)**: क्वेरी को फिर से तैयार करने या संबंधित प्रश्नों का सुझाव दें। +5. **एलएलएम सेवा विफलता (LLM Service Failure)**: कैश किए गए प्रश्नों या टेम्पलेट-आधारित प्रतिक्रियाओं का उपयोग करें। + +### निगरानी मेट्रिक्स + +प्रश्न जटिलता वितरण +ऑन्टोलॉजी विभाजन आकार +क्वेरी पीढ़ी सफलता दर +ग्राफ क्वेरी निष्पादन समय +उत्तर गुणवत्ता स्कोर +कैश हिट दर +त्रुटि आवृत्तियाँ (प्रकार द्वारा) + +## भविष्य के सुधार + +1. **ऑन्टोलॉजी सीखना (Ontology Learning)**: निष्कर्षण पैटर्न के आधार पर स्वचालित रूप से ऑन्टोलॉजी का विस्तार करें। +2. **आत्मविश्वास स्कोरिंग (Confidence Scoring)**: निकाले गए त्रिगुटों को आत्मविश्वास स्कोर असाइन करें। +3. **स्पष्टीकरण पीढ़ी (Explanation Generation)**: ट्रिपल निष्कर्षण के लिए तर्क प्रदान करें। +4. **सक्रिय शिक्षण (Active Learning)**: अनिश्चित निष्कर्षण के लिए मानव सत्यापन का अनुरोध करें। + +## सुरक्षा विचार + +1. **प्रॉम्प्ट इंजेक्शन रोकथाम (Prompt Injection Prevention)**: प्रॉम्प्ट निर्माण से पहले चंक टेक्स्ट को सैनिटाइज करें। +2. **संसाधन सीमाएँ (Resource Limits)**: वेक्टर स्टोर के लिए मेमोरी उपयोग को सीमित करें। +3. **दर सीमित करना (Rate Limiting)**: प्रति क्लाइंट निष्कर्षण अनुरोधों को सीमित करें। +4. **ऑडिट लॉगिंग (Audit Logging)**: सभी निष्कर्षण अनुरोधों और परिणामों को ट्रैक करें। + +## परीक्षण रणनीति + +### यूनिट परीक्षण + +विभिन्न प्रारूपों के साथ ऑन्टोलॉजी लोडर +एम्बेडिंग पीढ़ी और भंडारण +वाक्य विभाजन एल्गोरिदम +वेक्टर समानता गणना +ट्रिपल पार्सिंग और सत्यापन + +### एकीकरण परीक्षण + +एंड-टू-एंड निष्कर्षण पाइपलाइन +कॉन्फ़िगरेशन सेवा एकीकरण +प्रॉम्प्ट सेवा इंटरैक्शन +समवर्ती निष्कर्षण हैंडलिंग + +### प्रदर्शन परीक्षण + +बड़े ऑन्टोलॉजी हैंडलिंग (1000+ कक्षाएं) +उच्च-मात्रा चंक प्रसंस्करण +लोड के तहत मेमोरी उपयोग +विलंबता बेंचमार्क + +## वितरण योजना + +### अवलोकन + +OntoRAG सिस्टम को चार प्रमुख चरणों में वितरित किया जाएगा, जिसमें प्रत्येक चरण क्रमिक मूल्य प्रदान करेगा, जबकि पूर्ण सिस्टम की ओर निर्माण करेगा। योजना का ध्यान पहले मुख्य निष्कर्षण क्षमताओं को स्थापित करने पर है, फिर क्वेरी कार्यक्षमता जोड़ने, इसके बाद अनुकूलन और उन्नत सुविधाओं पर। + +### चरण 1: नींव और मुख्य निष्कर्षण + +**लक्ष्य**: सरल वेक्टर मिलान के साथ बुनियादी ऑन्टोलॉजी-संचालित निष्कर्षण पाइपलाइन स्थापित करें। + +#### चरण 1.1: ऑन्टोलॉजी प्रबंधन नींव +ऑन्टोलॉजी कॉन्फ़िगरेशन लोडर (`OntologyLoader`) लागू करें +ऑन्टोलॉजी JSON संरचनाओं को पार्स और मान्य करें +इन-मेमोरी ऑन्टोलॉजी भंडारण और एक्सेस पैटर्न बनाएं +ऑन्टोलॉजी रिफ्रेश तंत्र लागू करें + +**सफलता मानदंड**: +ऑन्टोलॉजी कॉन्फ़िगरेशन को सफलतापूर्वक लोड और पार्स करें +ऑन्टोलॉजी संरचना और स्थिरता को मान्य करें +कई समवर्ती ऑन्टोलॉजी को संभालें + +#### चरण 1.2: वेक्टर स्टोर कार्यान्वयन +प्रारंभिक प्रोटोटाइप के रूप में सरल NumPy-आधारित वेक्टर स्टोर लागू करें +FAISS वेक्टर स्टोर कार्यान्वयन जोड़ें +वेक्टर स्टोर इंटरफ़ेस एब्स्ट्रैक्शन बनाएं +कॉन्फ़िगर करने योग्य थ्रेसहोल्ड के साथ समानता खोज लागू करें + +**सफलता मानदंड**: +एम्बेडिंग को कुशलतापूर्वक स्टोर और पुनर्प्राप्त करें +<100ms विलंबता के साथ समानता खोज करें +NumPy और FAISS दोनों बैकएंड का समर्थन करें + +#### चरण 1.3: ऑन्टोलॉजी एम्बेडिंग पाइपलाइन +एम्बेडिंग सेवा के साथ एकीकृत करें +`OntologyEmbedder` घटक को लागू करें +सभी ऑन्टोलॉजी तत्वों के लिए एम्बेडिंग उत्पन्न करें +वेक्टर स्टोर में मेटाडेटा के साथ एम्बेडिंग स्टोर करें + +**सफलता मानदंड**: +कक्षाओं और गुणों के लिए एम्बेडिंग उत्पन्न करें +उचित मेटाडेटा के साथ एम्बेडिंग स्टोर करें +ऑन्टोलॉजी अपडेट पर एम्बेडिंग को फिर से बनाएं + +#### चरण 1.4: टेक्स्ट प्रोसेसिंग घटक +NLTK/spaCy का उपयोग करके वाक्य विभाजक को लागू करें +वाक्यांश और नामित संस्थाएं निकालें +टेक्स्ट सेगमेंट पदानुक्रम बनाएं +टेक्स्ट सेगमेंट के लिए एम्बेडिंग उत्पन्न करें + +**सफलता मानदंड**: +पाठ को सटीक रूप से वाक्यों में विभाजित करें +सार्थक वाक्यांश निकालें +संदर्भ संबंधों को बनाए रखें + +#### चरण 1.5: ऑन्टोलॉजी चयन एल्गोरिदम +पाठ और ऑन्टोलॉजी के बीच समानता मिलान को लागू करें +ऑन्टोलॉजी तत्वों के लिए निर्भरता रिज़ॉल्यूशन बनाएं +न्यूनतम सुसंगत ऑन्टोलॉजी उपसमुच्चय बनाएं +उपसमुच्चय पीढ़ी प्रदर्शन को अनुकूलित करें + +**सफलता मानदंड**: +>80% परिशुद्धता के साथ प्रासंगिक ऑन्टोलॉजी तत्वों का चयन करें +सभी आवश्यक निर्भरताओं को शामिल करें +<500ms में उपसमुच्चय उत्पन्न करें + +#### चरण 1.6: बुनियादी निष्कर्षण सेवा +निष्कर्षण के लिए प्रॉम्प्ट निर्माण को लागू करें +प्रॉम्प्ट सेवा के साथ एकीकृत करें +ट्रिपल प्रतिक्रियाओं को पार्स और मान्य करें +`kg-extract-ontology` सेवा एंडपॉइंट बनाएं + +**सफलता मानदंड**: +ऑन्टोलॉजी-अनुरूप ट्रिपल निकालें +सभी ट्रिपल को ऑन्टोलॉजी के विरुद्ध मान्य करें +निष्कर्षण त्रुटियों को सुचारू रूप से संभालें + +### चरण 2: क्वेरी सिस्टम कार्यान्वयन + +**लक्ष्य**: कई बैकएंड के लिए समर्थन के साथ ऑन्टोलॉजी-जागरूक क्वेरी क्षमताओं को जोड़ें। + +#### चरण 2.1: क्वेरी फाउंडेशन घटक +प्रश्न विश्लेषक को लागू करें +प्रश्नों के लिए ऑन्टोलॉजी मिलान बनाएं +क्वेरी संदर्भ के लिए वेक्टर खोज को अनुकूलित करें +बैकएंड राउटर घटक बनाएं + +**सफलता मानदंड**: +प्रश्नों का विश्लेषण करके सिमेंटिक घटकों में बदलें +प्रश्नों का मिलान प्रासंगिक ऑन्टोलॉजी तत्वों से करें +प्रश्नों को उपयुक्त बैकएंड पर रूट करें + +#### चरण 2.2: SPARQL पथ कार्यान्वयन +`onto-query-sparql` सेवा लागू करें +LLM का उपयोग करके SPARQL क्वेरी जनरेटर बनाएं +SPARQL पीढ़ी के लिए प्रॉम्प्ट टेम्पलेट विकसित करें +उत्पन्न SPARQL सिंटैक्स को मान्य करें + +**सफलता मानदंड**: +मान्य SPARQL क्वेरी उत्पन्न करें +उपयुक्त SPARQL पैटर्न का उपयोग करें +जटिल क्वेरी प्रकारों को संभालें + +#### चरण 2.3: SPARQL-Cassandra इंजन +Cassandra के लिए rdflib Store इंटरफ़ेस लागू करें +CQL क्वेरी ट्रांसलेटर बनाएं +ट्रिपल पैटर्न मिलान को अनुकूलित करें +SPARQL परिणाम स्वरूपण को संभालें + +**सफलता मानदंड**: +Cassandra पर SPARQL क्वेरी निष्पादित करें +सामान्य SPARQL पैटर्न का समर्थन करें +परिणामों को मानक प्रारूप में लौटाएं + +#### चरण 2.4: Cypher पथ कार्यान्वयन +`onto-query-cypher` सेवा लागू करें +LLM का उपयोग करके Cypher क्वेरी जनरेटर बनाएं +Cypher पीढ़ी के लिए प्रॉम्प्ट टेम्पलेट विकसित करें +उत्पन्न Cypher सिंटैक्स को मान्य करें + +**सफलता मानदंड**: +मान्य Cypher क्वेरी उत्पन्न करें +उपयुक्त ग्राफ पैटर्न का उपयोग करें +Neo4j, Memgraph, FalkorDB का समर्थन करें + +#### चरण 2.5: Cypher निष्पादक +मल्टी-डेटाबेस साइफर एग्जीक्यूटर को लागू करें +बॉल्ट प्रोटोकॉल (Neo4j/Memgraph) का समर्थन करें +रेडिस प्रोटोकॉल (FalkorDB) का समर्थन करें +परिणाम सामान्यीकरण को संभालें + +**सफलता मानदंड**: +सभी लक्षित डेटाबेस पर साइफर को निष्पादित करें +डेटाबेस-विशिष्ट अंतरों को संभालें +कनेक्शन पूल को कुशलतापूर्वक बनाए रखें + +#### चरण 2.6: उत्तर पीढ़ी +उत्तर जनरेटर घटक को लागू करें +उत्तर संश्लेषण के लिए संकेत बनाएं +एलएलएम (LLM) के उपयोग के लिए क्वेरी परिणामों को प्रारूपित करें +प्राकृतिक भाषा में उत्तर उत्पन्न करें + +**सफलता मानदंड**: +क्वेरी परिणामों से सटीक उत्तर उत्पन्न करें +मूल प्रश्न से संदर्भ बनाए रखें +स्पष्ट, संक्षिप्त प्रतिक्रियाएं प्रदान करें + +### चरण 3: अनुकूलन और मजबूती + +**लक्ष्य**: प्रदर्शन को अनुकूलित करें, कैशिंग जोड़ें, त्रुटि प्रबंधन में सुधार करें और विश्वसनीयता बढ़ाएं। + +#### चरण 3.1: प्रदर्शन अनुकूलन +एम्बेडिंग कैशिंग को लागू करें +क्वेरी परिणाम कैशिंग जोड़ें +FAISS IVF इंडेक्स के साथ वेक्टर खोज को अनुकूलित करें +एम्बेडिंग के लिए बैच प्रोसेसिंग को लागू करें + +**सफलता मानदंड**: +औसत क्वेरी विलंबता को 50% तक कम करें +10 गुना अधिक समवर्ती अनुरोधों का समर्थन करें +उप-सेकंड प्रतिक्रिया समय बनाए रखें + +#### चरण 3.2: उन्नत त्रुटि प्रबंधन +व्यापक त्रुटि रिकवरी को लागू करें +क्वेरी पथों के बीच फॉलबैक तंत्र जोड़ें +घातीय बैकऑफ़ के साथ रीट्राय लॉजिक बनाएं +त्रुटि लॉगिंग और निदान में सुधार करें + +**सफलता मानदंड**: +सभी विफलता परिदृश्यों को सुचारू रूप से संभालें +बैकएंड के बीच स्वचालित फेलओवर +डिबगिंग के लिए विस्तृत त्रुटि रिपोर्टिंग + +#### चरण 3.3: निगरानी और अवलोकनशीलता +प्रदर्शन मेट्रिक्स संग्रह जोड़ें +क्वेरी ट्रेसिंग को लागू करें +स्वास्थ्य जांच एंडपॉइंट बनाएं +संसाधन उपयोग निगरानी जोड़ें + +**सफलता मानदंड**: +सभी प्रमुख प्रदर्शन संकेतकों को ट्रैक करें +बाधाओं की पहचान जल्दी करें +सिस्टम स्वास्थ्य की वास्तविक समय में निगरानी करें + +#### चरण 3.4: कॉन्फ़िगरेशन प्रबंधन +गतिशील कॉन्फ़िगरेशन अपडेट को लागू करें +कॉन्फ़िगरेशन सत्यापन जोड़ें +कॉन्फ़िगरेशन टेम्प्लेट बनाएं +पर्यावरण-विशिष्ट सेटिंग्स का समर्थन करें + +**सफलता मानदंड**: +पुनरारंभ किए बिना कॉन्फ़िगरेशन अपडेट करें +सभी कॉन्फ़िगरेशन परिवर्तनों को मान्य करें +कई परिनियोजन वातावरण का समर्थन करें + +### चरण 4: उन्नत सुविधाएँ + +**लक्ष्य**: उत्पादन परिनियोजन और बेहतर कार्यक्षमता के लिए परिष्कृत क्षमताएं जोड़ें। + +#### चरण 4.1: मल्टी-ऑन्टोलॉजी समर्थन +ऑन्टोलॉजी चयन तर्क को लागू करें +क्रॉस-ऑन्टोलॉजी क्वेरी का समर्थन करें +ऑन्टोलॉजी संस्करण नियंत्रण को संभालें +ऑन्टोलॉजी मर्ज क्षमताएं बनाएं + +**सफलता मानदंड**: +कई ऑन्टोलॉजी पर क्वेरी करें +ऑन्टोलॉजी संघर्षों को संभालें +ऑन्टोलॉजी विकास का समर्थन करें + +#### चरण 4.2: इंटेलिजेंट क्वेरी रूटिंग +प्रदर्शन-आधारित रूटिंग को लागू करें +क्वेरी जटिलता विश्लेषण जोड़ें +अनुकूली रूटिंग एल्गोरिदम बनाएं +रास्तों के लिए A/B परीक्षण का समर्थन करें + +**सफलता मानदंड**: +क्वेरी को इष्टतम रूप से रूट करें +क्वेरी प्रदर्शन से सीखें +समय के साथ रूटिंग में सुधार करें + +#### चरण 4.3: उन्नत निष्कर्षण विशेषताएं +त्रिपुंजों के लिए आत्मविश्वास स्कोरिंग जोड़ें +स्पष्टीकरण पीढ़ी को लागू करें +सुधार के लिए प्रतिक्रिया लूप बनाएं +वृद्धिशील सीखने का समर्थन करें + +**सफलता मानदंड**: +आत्मविश्वास स्कोर प्रदान करें +निष्कर्षण निर्णयों की व्याख्या करें +सटीकता में लगातार सुधार करें + +#### चरण 4.4: उत्पादन कठोरता +दर सीमित करना जोड़ें +प्रमाणीकरण/प्राधिकरण लागू करें +परिनियोजन स्वचालन बनाएं +बैकअप और रिकवरी जोड़ें + +**सफलता मानदंड**: +उत्पादन-तैयार सुरक्षा +स्वचालित परिनियोजन पाइपलाइन +आपदा रिकवरी क्षमता + +### वितरण मील के पत्थर + +1. **मील का पत्थर 1** (चरण 1 का अंत): बुनियादी ऑन्टोलॉजी-संचालित निष्कर्षण परिचालन +2. **मील का पत्थर 2** (चरण 2 का अंत): SPARQL और Cypher दोनों पथों के साथ पूर्ण क्वेरी सिस्टम +3. **मील का पत्थर 3** (चरण 3 का अंत): अनुकूलित, मजबूत सिस्टम जो स्टेजिंग के लिए तैयार है +4. **मील का पत्थर 4** (चरण 4 का अंत): उन्नत सुविधाओं के साथ उत्पादन-तैयार सिस्टम + +### जोखिम शमन + +#### तकनीकी जोखिम +**वेक्टर स्टोर स्केलेबिलिटी**: NumPy के साथ शुरू करें, धीरे-धीरे FAISS में माइग्रेट करें +**क्वेरी पीढ़ी सटीकता**: सत्यापन और बैकअप तंत्र लागू करें +**बैकएंड संगतता**: प्रत्येक डेटाबेस प्रकार के साथ व्यापक रूप से परीक्षण करें +**प्रदर्शन बाधाएं**: जल्दी और अक्सर प्रोफाइल करें, पुनरावृत्त रूप से अनुकूलित करें + +#### परिचालन जोखिम +**ऑन्टोलॉजी गुणवत्ता**: सत्यापन और स्थिरता जांच लागू करें +**सेवा निर्भरताएँ**: सर्किट ब्रेकर और बैकअप जोड़ें +**संसाधन बाधाएँ**: मॉनिटर करें और उचित सीमाएँ निर्धारित करें +**डेटा स्थिरता**: उचित लेनदेन हैंडलिंग लागू करें + +### सफलता मेट्रिक्स + +#### चरण 1 सफलता मेट्रिक्स +निष्कर्षण सटीकता: >90% ऑन्टोलॉजी अनुरूपता +प्रसंस्करण गति: <1 सेकंड प्रति टुकड़ा +ऑन्टोलॉजी लोड समय: <10 सेकंड +वेक्टर खोज विलंबता: <100ms + +#### चरण 2 सफलता मेट्रिक्स +क्वेरी सफलता दर: >95% +क्वेरी विलंबता: <2 सेकंड एंड-टू-एंड +बैकएंड संगतता: लक्षित डेटाबेस के लिए 100% +उत्तर सटीकता: उपलब्ध डेटा के आधार पर >85% + +#### चरण 3 सफलता मेट्रिक्स +सिस्टम अपटाइम: >99.9% +त्रुटि रिकवरी दर: >95% +कैश हिट दर: >60% +समवर्ती उपयोगकर्ता: >100 + +#### चरण 4 सफलता मेट्रिक्स +मल्टी-ऑन्टोलॉजी क्वेरी: पूरी तरह से समर्थित +रूटिंग अनुकूलन: 30% विलंबता में कमी +आत्मविश्वास स्कोरिंग सटीकता: >90% +उत्पादन परिनियोजन: शून्य-डाउनटाइम अपडेट + +## संदर्भ + +[OWL 2 वेब ऑन्टोलॉजी भाषा](https://www.w3.org/TR/owl2-overview/) +[GraphRAG आर्किटेक्चर](https://github.com/microsoft/graphrag) +[वाक्य ट्रांसफॉर्मर](https://www.sbert.net/) +[FAISS वेक्टर खोज](https://github.com/facebookresearch/faiss) +[spaCy एनएलपी लाइब्रेरी](https://spacy.io/) +[rdflib प्रलेखन](https://rdflib.readthedocs.io/) +[Neo4j बोल्ट प्रोटोकॉल](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.md b/docs/tech-specs/ontorag.md index 47426dbe..86a3cd19 100644 --- a/docs/tech-specs/ontorag.md +++ b/docs/tech-specs/ontorag.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "OntoRAG: Ontology-Based Knowledge Extraction and Query Technical Specification" +parent: "Tech Specs" +--- + # OntoRAG: Ontology-Based Knowledge Extraction and Query Technical Specification ## Overview diff --git a/docs/tech-specs/ontorag.pt.md b/docs/tech-specs/ontorag.pt.md new file mode 100644 index 00000000..abe0b86e --- /dev/null +++ b/docs/tech-specs/ontorag.pt.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: Especificação Técnica de Extração e Consulta de Conhecimento Baseada em Ontologia" +parent: "Portuguese (Beta)" +--- + +# OntoRAG: Especificação Técnica de Extração e Consulta de Conhecimento Baseada em Ontologia + +> **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 + +OntoRAG é um sistema de extração e consulta de conhecimento orientado por ontologia que impõe uma consistência semântica rigorosa durante a extração de triplas de conhecimento de texto não estruturado e durante a consulta do grafo de conhecimento resultante. Semelhante ao GraphRAG, mas com restrições de ontologia formais, o OntoRAG garante que todas as triplas extraídas estejam em conformidade com estruturas ontológicas predefinidas e fornece recursos de consulta com consciência semântica. + +O sistema usa correspondência de similaridade vetorial para selecionar dinamicamente subconjuntos de ontologia relevantes para operações de extração e consulta, permitindo um processamento focado e contextualmente apropriado, mantendo a validade semântica. + +**Nome do Serviço**: `kg-extract-ontology` + +## Objetivos + +**Extração Conforme à Ontologia**: Garantir que todas as triplas extraídas estejam estritamente em conformidade com as ontologias carregadas. +**Seleção de Contexto Dinâmico**: Usar incorporações para selecionar subconjuntos de ontologia relevantes para cada trecho. +**Consistência Semântica**: Manter hierarquias de classes, domínios/intervalos de propriedades e restrições. +**Processamento Eficiente**: Usar armazenamentos vetoriais em memória para correspondência rápida de elementos de ontologia. +**Arquitetura Escalável**: Suportar múltiplas ontologias concorrentes com diferentes domínios. + +## Contexto + +Os serviços atuais de extração de conhecimento (`kg-extract-definitions`, `kg-extract-relationships`) operam sem restrições formais, potencialmente produzindo triplas inconsistentes ou incompatíveis. O OntoRAG aborda isso através de: + +1. Carregamento de ontologias formais que definem classes e propriedades válidas. +2. Uso de incorporações para corresponder o conteúdo do texto com elementos de ontologia relevantes. +3. Restringir a extração para produzir apenas triplas conformes à ontologia. +4. Fornecer validação semântica do conhecimento extraído. + +Essa abordagem combina a flexibilidade da extração neural com a precisão da representação formal do conhecimento. + +## Design Técnico + +### Arquitetura + +O sistema OntoRAG consiste nos seguintes componentes: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### Detalhes do Componente + +#### 1. Carregador de Ontologia + +**Propósito**: Recupera e analisa configurações de ontologia do serviço de configuração usando atualizações orientadas a eventos. + +**Implementação**: +O Carregador de Ontologia usa a fila ConfigPush da TrustGraph para receber atualizações orientadas a eventos de configuração de ontologia. Quando um elemento de configuração do tipo "ontologia" é adicionado ou modificado, o carregador recebe a atualização através da fila config-update e analisa a estrutura JSON contendo metadados, classes, propriedades de objeto e propriedades de tipo de dados. Essas ontologias analisadas são armazenadas na memória como objetos estruturados que podem ser acessados de forma eficiente durante o processo de extração. + +**Operações Chave**: +Assinar a fila config-update para configurações do tipo ontologia +Analisar estruturas JSON de ontologia em objetos OntologyClass e OntologyProperty +Validar a estrutura e a consistência da ontologia +Armazenar em cache as ontologias analisadas na memória para acesso rápido +Lidar com o processamento por fluxo com armazenamentos de vetores específicos do fluxo + +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. Incorporador de Ontologia + +**Propósito**: Cria incorporações vetoriais para todos os elementos da ontologia para permitir a correspondência de similaridade semântica. + +**Implementação**: +O Incorporador de Ontologia processa cada elemento nas ontologias carregadas (classes, propriedades de objeto e propriedades de tipo de dados) e gera incorporações vetoriais usando o serviço EmbeddingsClientSpec. Para cada elemento, ele combina o identificador do elemento, os rótulos e a descrição (comentário) para criar uma representação de texto. Este texto é então convertido em uma incorporação vetorial de alta dimensão que captura seu significado semântico. Essas incorporações são armazenadas em um armazenamento de vetores FAISS na memória, específico para cada fluxo, juntamente com metadados sobre o tipo de elemento, a ontologia de origem e a definição completa. O incorporador detecta automaticamente a dimensão da incorporação a partir da primeira resposta de incorporação. + +**Operações Chave**: +Criar representações de texto a partir de IDs de elementos, rótulos e comentários +Gerar incorporações via EmbeddingsClientSpec (usando asyncio.gather para processamento em lote) +Armazenar incorporações com metadados abrangentes no armazenamento de vetores FAISS +Indexar por ontologia, tipo de elemento e ID de elemento para recuperação eficiente +Detectar automaticamente as dimensões da incorporação para a inicialização do armazenamento de vetores +Lidar com modelos de incorporação específicos do fluxo com armazenamentos de vetores independentes + +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. Processador de Texto (Divisor de Sentenças) + +**Propósito**: Decompõe blocos de texto em segmentos granulares para correspondência precisa de ontologia. + +**Implementação**: +O Processador de Texto usa NLTK para tokenização de sentenças e marcação POS para dividir os blocos de texto recebidos em sentenças. Ele lida com a compatibilidade de versão do NLTK tentando baixar `punkt_tab` e `averaged_perceptron_tagger_eng`, com fallback para versões mais antigas, se necessário. Cada bloco de texto é dividido em sentenças individuais que podem ser correspondidas independentemente com elementos de ontologia. + +**Operações Chave**: +Dividir o texto em sentenças usando a tokenização de sentenças do NLTK +Lidar com a compatibilidade de versão do NLTK (punkt_tab vs punkt) +Criar objetos TextSegment com texto e informações de posição +Suportar tanto sentenças completas quanto blocos individuais + +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. Selecionador de Ontologia + +**Propósito**: Identifica o subconjunto mais relevante de elementos de ontologia para o bloco de texto atual. + +**Implementação**: +O Selecionador de Ontologia realiza a correspondência semântica entre segmentos de texto e elementos de ontologia usando a pesquisa de similaridade vetorial FAISS. Para cada sentença do bloco de texto, ele gera uma incorporação e pesquisa o armazenamento de vetores pelos elementos de ontologia mais semelhantes usando a similaridade de cossenos com um limite configurável (padrão 0,3). Após coletar todos os elementos relevantes, ele realiza a resolução de dependências abrangente: se uma classe é selecionada, suas classes pai são incluídas; se uma propriedade é selecionada, suas classes de domínio e intervalo são adicionadas. Além disso, para cada classe selecionada, ele inclui automaticamente **todas as propriedades que referenciam essa classe** em seu domínio ou intervalo. Isso garante que a extração tenha acesso a todas as propriedades relevantes. + +**Operações Chave**: +Gerar incorporações para cada segmento de texto (frases) +Realizar busca de vizinhos mais próximos em k no armazenamento vetorial FAISS (top_k=10, threshold=0.3) +Aplicar um limite de similaridade para filtrar correspondências fracas +Resolver dependências (classes pai, domínios, intervalos) +**Incluir automaticamente todas as propriedades relacionadas às classes selecionadas** (correspondência de domínio/intervalo) +Construir um subconjunto de ontologia coerente com todos os relacionamentos necessários +Eliminar elementos duplicados que aparecem várias vezes + +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. Construção do Prompt + +**Propósito**: Cria prompts estruturados que orientam o LLM a extrair apenas triplas conformes à ontologia. + +**Implementação**: +O serviço de extração usa um modelo Jinja2 carregado de `ontology-prompt.md` que formata o subconjunto da ontologia e o texto para a extração do LLM. O modelo itera dinamicamente sobre classes, propriedades de objeto e propriedades de tipo de dados usando a sintaxe Jinja2, apresentando cada uma com suas descrições, domínios, intervalos e relacionamentos hierárquicos. O prompt inclui regras estritas sobre o uso apenas dos elementos da ontologia fornecidos e solicita um formato de saída JSON para análise consistente. + +**Operações Chave**: +Usar modelo Jinja2 com loops sobre elementos da ontologia +Formatar classes com relacionamentos pai (subclass_of) e comentários +Formatar propriedades com restrições de domínio/intervalo e comentários +Incluir regras de extração explícitas e requisitos de formato de saída +Chamar o serviço de prompt com o ID do modelo "extract-with-ontologies" + +**Localização do Modelo**: `ontology-prompt.md` +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (método build_extraction_variables) + +#### 6. Serviço Principal de Extração + +**Propósito**: Coordena todos os componentes para realizar a extração de triplas baseada em ontologia de ponta a ponta. + +**Implementação**: +O Serviço Principal de Extração (KgExtractOntology) é a camada de orquestração que gerencia todo o fluxo de trabalho de extração. Ele usa o padrão FlowProcessor da TrustGraph com inicialização de componentes específica para cada fluxo. Quando uma atualização de configuração da ontologia é recebida, ele inicializa ou atualiza os componentes específicos do fluxo (carregador de ontologia, incorporador, processador de texto, selecionador). Quando um trecho de texto chega para processamento, ele coordena o pipeline: dividindo o texto em segmentos, encontrando elementos de ontologia relevantes por meio de busca vetorial, construindo um prompt restrito, chamando o serviço de prompt, analisando e validando a resposta, gerando triplas de definição de ontologia e emitindo tanto triplas de conteúdo quanto contextos de entidade. + +**Pipeline de Extração**: +1. Receber trecho de texto via fila chunks-input +2. Inicializar componentes do fluxo, se necessário (na primeira execução ou atualização de configuração) +3. Dividir o texto em frases usando NLTK +4. Pesquisar no armazenamento vetorial FAISS para encontrar conceitos de ontologia relevantes +5. Construir subconjunto de ontologia com inclusão automática de propriedades +6. Construir variáveis de prompt com modelo Jinja2 +7. Chamar o serviço de prompt com o modelo extract-with-ontologies +8. Analisar a resposta JSON em triplas estruturadas +9. Validar as triplas e expandir os URIs para URIs completos da ontologia +10. Gerar triplas de definição de ontologia (classes e propriedades com rótulos/comentários/domínios/intervalos) +11. Construir contextos de entidade a partir de todas as triplas +12. Emitir para as filas de triplas e contextos de entidade + +**Características Principais**: +Armazenamentos vetoriais específicos para cada fluxo, suportando diferentes modelos de incorporação +Atualizações de ontologia orientadas por eventos via fila config-update +Expansão automática de URIs usando URIs de ontologia +Elementos de ontologia adicionados ao grafo de conhecimento com metadados completos +Contextos de entidade incluem elementos de conteúdo e de ontologia + +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### Configuração + +O serviço usa a abordagem de configuração padrão da TrustGraph com argumentos de linha de comando: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**Parâmetros de Configuração Chave**: +`similarity_threshold`: 0.3 (padrão, configurável no código) +`top_k`: 10 (número de elementos de ontologia a serem recuperados por segmento) +`vector_store`: Per-flow FAISS IndexFlatIP com dimensões detectadas automaticamente +`text_processor`: NLTK com tokenização de frases punkt_tab +`prompt_template`: "extract-with-ontologies" (template Jinja2) + +**Configuração da Ontologia**: +As ontologias são carregadas dinamicamente através da fila de atualização de configuração com o tipo "ontology". + +### Fluxo de Dados + +1. **Fase de Inicialização** (por fluxo): + Receber configuração da ontologia através da fila de atualização de configuração + Analisar o JSON da ontologia em objetos OntologyClass e OntologyProperty + Gerar embeddings para todos os elementos da ontologia usando EmbeddingsClientSpec + Armazenar embeddings no armazenamento vetorial FAISS específico do fluxo + Detectar automaticamente as dimensões do embedding a partir da primeira resposta + +2. **Fase de Extração** (por chunk): + Receber um chunk da fila chunks-input + Dividir o chunk em frases usando NLTK + Calcular embeddings para cada frase + Pesquisar no armazenamento vetorial FAISS por elementos de ontologia relevantes + Construir um subconjunto de ontologia com inclusão automática de propriedades + Construir variáveis de template Jinja2 com texto e ontologia + Chamar o serviço de prompt com o template extract-with-ontologies + Analisar a resposta JSON e validar as triplas + Expandir URIs usando URIs da ontologia + Gerar triplas de definição de ontologia + Construir contextos de entidade a partir de todas as triplas + Emitir para as filas de triplas e entity-contexts + +### Armazenamento Vetorial em Memória + +**Propósito**: Fornece uma pesquisa de similaridade rápida e baseada em memória para correspondência de elementos de ontologia. + +**Implementação: FAISS** + +O sistema usa **FAISS (Facebook AI Similarity Search)** com IndexFlatIP para pesquisa de similaridade de cosseno exata. Características principais: + +**IndexFlatIP**: Pesquisa de similaridade de cosseno exata usando produto interno +**Detecção automática**: Dimensão determinada a partir da primeira resposta de embedding +**Armazenamentos per-flow**: Cada fluxo tem um armazenamento vetorial independente para diferentes modelos de embedding +**Normalização**: Todos os vetores normalizados antes da indexação +**Operações em lote**: Adição em lote eficiente para o carregamento inicial da ontologia + +**Localização da Implementação**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### Algoritmo de Seleção de Subconjunto de Ontologia + +**Propósito**: Seleciona dinamicamente a porção relevante mínima da ontologia para cada chunk de texto. + +**Etapas Detalhadas do Algoritmo**: + +1. **Segmentação de Texto**: + Dividir o chunk de entrada em frases usando detecção de frases NLP + Extrair frases nominais, frases verbais e entidades nomeadas de cada frase + Criar uma estrutura hierárquica de segmentos preservando o contexto + +2. **Geração de Embedding**: + Gerar embeddings vetoriais para cada segmento de texto (frases e frases) + Usar o mesmo modelo de embedding usado para elementos de ontologia + Armazenar em cache os embeddings para segmentos repetidos para melhorar o desempenho + +3. **Pesquisa de Similaridade**: + Para cada embedding de segmento de texto, pesquisar no armazenamento vetorial + Recuperar os k (por exemplo, 10) elementos de ontologia mais similares + Aplicar um limite de similaridade (por exemplo, 0,7) para filtrar correspondências fracas + Agregar os resultados em todos os segmentos, rastreando as frequências de correspondência + +4. **Resolução de Dependências**: + Para cada classe selecionada, incluir recursivamente todas as classes pai até a raiz + Para cada propriedade selecionada, incluir suas classes de domínio e intervalo + Para propriedades inversas, garantir que ambas as direções sejam incluídas + Adicionar classes equivalentes se existirem na ontologia + +5. **Construção de Subconjunto**: + Desduplicar os elementos coletados, preservando os relacionamentos + Organizar em classes, propriedades de objeto e propriedades de tipo de dados + Garantir que todas as restrições e relacionamentos sejam preservados + Criar uma mini-ontologia autocontida que seja válida e completa + +**Exemplo de Demonstração**: +Dado o texto: "The brown dog chased the white cat up the tree." +Segmentos: ["brown dog", "white cat", "tree", "chased"] +Elementos correspondidos: [dog (class), cat (class), animal (parent), chases (property)] +Dependências: [animal (parent of dog and cat), lifeform (parent of animal)] +Subconjunto final: Mini-ontologia completa com hierarquia animal e relação de perseguição + +### Validação de Triplas + +**Propósito**: Garante que todas as triplas extraídas estejam estritamente em conformidade com as restrições da ontologia. + +**Algoritmo de Validação**: +Após a última linha traduzida, insira uma linha final contendo exatamente: [[__END_OF_TRANSLATION__]] +1. **Validação de Classe**: + Verificar se os sujeitos são instâncias de classes definidas no subconjunto da ontologia + Para propriedades de objeto, verificar se os objetos também são instâncias de classes válidas + Verificar os nomes das classes em relação ao dicionário de classes da ontologia + Lidar com hierarquias de classes - instâncias de subclasses são válidas para restrições da classe pai + +2. **Validação de Propriedade**: + Confirmar se os predicados correspondem a propriedades no subconjunto da ontologia + Distinguir entre propriedades de objeto (entidade-para-entidade) e propriedades de tipo de dado (entidade-para-literal) + Verificar se os nomes das propriedades correspondem exatamente (considerando o namespace, se presente) + +3. **Verificação de Domínio/Intervalo**: + Para cada propriedade usada como predicado, recuperar seu domínio e intervalo + Verificar se o tipo do sujeito corresponde ou herda do domínio da propriedade + Verificar se o tipo do objeto corresponde ou herda do intervalo da propriedade + Para propriedades de tipo de dado, verificar se o objeto é um literal do tipo XSD correto + +4. **Validação de Cardinalidade**: + Monitorar a contagem de uso da propriedade por sujeito + Verificar a cardinalidade mínima - garantir que as propriedades obrigatórias estejam presentes + Verificar a cardinalidade máxima - garantir que a propriedade não seja usada muitas vezes + Para propriedades funcionais, garantir que haja no máximo um valor por sujeito + +5. **Validação de Tipo de Dado**: + Analisar os valores literais de acordo com seus tipos XSD declarados + Validar se os inteiros são números válidos, se as datas estão formatadas corretamente, etc. + Verificar padrões de string se restrições de regex forem definidas + Garantir que os URIs sejam bem formados para tipos xsd:anyURI + +**Exemplo de Validação**: +Tripla: ("Buddy", "has-owner", "John") +Verificar se "Buddy" é tipado como uma classe que pode ter a propriedade "has-owner" +Verificar se "has-owner" existe na ontologia +Verificar a restrição de domínio: o sujeito deve ser do tipo "Pet" ou subclasse +Verificar a restrição de intervalo: o objeto deve ser do tipo "Person" ou subclasse +Se válido, adicionar à saída; se inválido, registrar a violação e pular + +## Considerações de Desempenho + +### Estratégias de Otimização + +1. **Cache de Incorporações**: Armazenar em cache as incorporações para segmentos de texto frequentemente usados +2. **Processamento em Lote**: Processar vários segmentos em paralelo +3. **Indexação de Armazenamento Vetorial**: Usar algoritmos de vizinhos mais próximos aproximados para ontologias grandes +4. **Otimização de Prompt**: Minimizar o tamanho do prompt incluindo apenas os elementos essenciais da ontologia +5. **Cache de Resultados**: Armazenar em cache os resultados da extração para trechos idênticos + +### Escalabilidade + +**Escalabilidade Horizontal**: Múltiplas instâncias do extrator com cache de ontologia compartilhado +**Particionamento da Ontologia**: Dividir ontologias grandes por domínio +**Processamento em Streaming**: Processar trechos à medida que chegam, sem agrupamento +**Gerenciamento de Memória**: Limpeza periódica de incorporações não utilizadas + +## Tratamento de Erros + +### Cenários de Falha + +1. **Ontologias Ausentes**: Recuar para a extração sem restrições +2. **Falha do Serviço de Incorporação**: Usar incorporações armazenadas em cache ou pular a correspondência semântica +3. **Tempo Limite do Serviço de Prompt**: Tentar novamente com retrocesso exponencial +4. **Formato de Tripla Inválido**: Registrar e pular triplas mal formadas +5. **Inconsistências na Ontologia**: Relatar conflitos e usar os elementos válidos mais específicos + +### Monitoramento + +Métricas-chave a serem monitoradas: + +Tempo de carregamento da ontologia e uso de memória +Latência de geração de incorporação +Desempenho da pesquisa vetorial +Tempo de resposta do serviço de prompt +Precisão da extração de triplas +Taxa de conformidade da ontologia + +## Caminho de Migração + +### De Extratores Existentes + +1. **Operação Paralela**: Executar em paralelo com os extratores existentes inicialmente +2. **Implantação Gradual**: Começar com tipos específicos de documentos +3. **Comparação de Qualidade**: Comparar a qualidade da saída com os extratores existentes +4. **Migração Completa**: Substituir os extratores existentes assim que a qualidade for verificada + +### Desenvolvimento de Ontologia + +1. **Inicialização a partir do Existente**: Gerar ontologias iniciais a partir do conhecimento existente +2. **Refinamento Iterativo**: Refinar com base em padrões de extração +3. **Revisão por Especialistas no Domínio**: Validar com especialistas no assunto +4. **Melhoria Contínua**: Atualizar com base no feedback da extração + +## Serviço de Consulta Sensível à Ontologia + +### Visão Geral + +O serviço de consulta sensível à ontologia fornece múltiplos caminhos de consulta para suportar diferentes armazenamentos de grafos de back-end. Ele aproveita o conhecimento da ontologia para um questionamento preciso e semanticamente consciente em diferentes armazenamentos de grafos, tanto Cassandra (via SPARQL) quanto armazenamentos de grafos baseados em Cypher (Neo4j, Memgraph, FalkorDB). + +**Componentes do Serviço**: +`onto-query-sparql`: Converte linguagem natural para SPARQL para Cassandra +`sparql-cassandra`: Camada de consulta SPARQL para Cassandra usando rdflib +`onto-query-cypher`: Converte linguagem natural para Cypher para bancos de dados de grafos +`cypher-executor`: Execução de consulta Cypher para Neo4j/Memgraph/FalkorDB + +### Arquitetura + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### Processamento de Consultas + +#### 1. Analisador de Perguntas + +**Propósito**: Decompõe as perguntas do usuário em componentes semânticos para correspondência com a ontologia. + +**Descrição do Algoritmo**: +O Analisador de Perguntas recebe a pergunta em linguagem natural e a divide em segmentos significativos, utilizando a mesma abordagem de divisão de frases utilizada no pipeline de extração. Ele identifica entidades, relacionamentos e restrições importantes mencionadas na pergunta. Cada segmento é analisado para determinar o tipo de pergunta (factual, agregação, comparação, etc.) e o formato de resposta esperado. Essa decomposição ajuda a identificar quais partes da ontologia são mais relevantes para responder à pergunta. + +**Operações Principais**: +Dividir a pergunta em frases e expressões +Identificar o tipo e a intenção da pergunta +Extrair entidades e relacionamentos mencionados +Detectar restrições e filtros na pergunta +Determinar o formato de resposta esperado + +#### 2. Correspondência de Ontologia para Consultas + +**Propósito**: Identifica o subconjunto relevante da ontologia necessário para responder à pergunta. + +**Descrição do Algoritmo**: +Similar ao Seletor de Ontologia do pipeline de extração, mas otimizado para responder a perguntas. O correspondente gera incorporações para segmentos de perguntas e pesquisa no armazenamento vetorial por elementos relevantes da ontologia. No entanto, ele se concentra em encontrar conceitos que seriam úteis para a construção de consultas, em vez de extração. Ele expande a seleção para incluir propriedades relacionadas que podem ser percorridas durante a exploração do grafo, mesmo que não sejam explicitamente mencionadas na pergunta. Por exemplo, se for feita uma pergunta sobre "funcionários", ele pode incluir propriedades como "trabalha-para", "gerencia" e "reporta-a", que podem ser relevantes para encontrar informações sobre funcionários. + +**Estratégia de Correspondência**: +Gerar incorporações para segmentos de perguntas +Encontrar conceitos da ontologia diretamente mencionados +Incluir propriedades que conectam classes mencionadas +Adicionar propriedades inversas e relacionadas para travessia +Incluir classes pai/filho para consultas hierárquicas +Construir uma partição da ontologia focada na consulta + +#### 3. Roteador de Backend + +**Propósito**: Roteia as consultas para o caminho de consulta específico do backend apropriado, com base na configuração. + +**Descrição do Algoritmo**: +O Roteador de Backend examina a configuração do sistema para determinar qual backend de grafo está ativo (Cassandra ou baseado em Cypher). Ele roteia a pergunta e a partição da ontologia para o serviço de geração de consulta apropriado. O roteador também pode suportar balanceamento de carga entre vários backends ou mecanismos de fallback se o backend primário estiver indisponível. + +**Lógica de Roteamento**: +Verificar o tipo de backend configurado nas configurações do sistema +Rotear para `onto-query-sparql` para backends Cassandra +Rotear para `onto-query-cypher` para Neo4j/Memgraph/FalkorDB +Suportar configurações multi-backend com distribuição de consultas +Lidar com cenários de failover e balanceamento de carga + +#### 4. Geração de Consulta SPARQL (`onto-query-sparql`) + +**Propósito**: Converte perguntas em linguagem natural em consultas SPARQL para execução no Cassandra. + +**Descrição do Algoritmo**: +O gerador de consulta SPARQL recebe a pergunta e a partição da ontologia e constrói uma consulta SPARQL otimizada para execução no backend Cassandra. Ele usa o serviço de prompt com um modelo específico para SPARQL que inclui semântica RDF/OWL. O gerador entende padrões SPARQL como caminhos de propriedade, cláusulas opcionais e filtros que podem ser traduzidos de forma eficiente em operações do Cassandra. + +**Modelo de Prompt de Geração SPARQL**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. Geração de Consultas Cypher (`onto-query-cypher`) + +**Propósito**: Converte perguntas em linguagem natural em consultas Cypher para bancos de dados de grafos. + +**Descrição do Algoritmo**: +O gerador de consultas Cypher cria consultas Cypher nativas otimizadas para Neo4j, Memgraph e FalkorDB. Ele mapeia classes de ontologia para rótulos de nós e propriedades para relacionamentos, usando a sintaxe de correspondência de padrões do Cypher. O gerador inclui otimizações específicas do Cypher, como dicas de direção de relacionamento, uso de índices e dicas de planejamento de consulta. + +**Modelo de Prompt de Geração Cypher**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. Motor de Consulta SPARQL-Cassandra (`sparql-cassandra`) + +**Propósito**: Executa consultas SPARQL contra o Cassandra usando Python rdflib. + +**Descrição do Algoritmo**: +O motor SPARQL-Cassandra implementa um processador SPARQL usando a biblioteca rdflib do Python com um armazenamento backend personalizado para o Cassandra. Ele traduz padrões de grafos SPARQL em consultas CQL apropriadas para o Cassandra, tratando junções, filtros e agregações. O motor mantém um mapeamento RDF para Cassandra que preserva a estrutura semântica, otimizando para o modelo de armazenamento de famílias de colunas do Cassandra. + +**Características da Implementação**: +Implementação da interface de armazenamento rdflib para o Cassandra +Suporte para consultas SPARQL 1.1 com padrões comuns +Tradução eficiente de padrões de triplas para CQL +Suporte para caminhos de propriedades e consultas hierárquicas +Streaming de resultados para grandes conjuntos de dados +Pool de conexões e cache de consultas + +**Exemplo de Tradução**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +Traduz para consultas otimizadas do Cassandra, utilizando índices e chaves de partição. + +#### 7. Executor de Consultas Cypher (`cypher-executor`) + +**Propósito**: Executa consultas Cypher contra Neo4j, Memgraph e FalkorDB. + +**Descrição do Algoritmo**: +O executor de consultas Cypher fornece uma interface unificada para executar consultas Cypher em diferentes bancos de dados de grafos. Ele gerencia protocolos de conexão específicos do banco de dados, dicas de otimização de consultas e normalização do formato de resultados. O executor inclui lógica de repetição, pool de conexões e gerenciamento de transações adequados para cada tipo de banco de dados. + +**Suporte a Múltiplos Bancos de Dados**: +**Neo4j**: Protocolo Bolt, funções de transação, dicas de índice +**Memgraph**: Protocolo personalizado, resultados de streaming, consultas analíticas +**FalkorDB**: Adaptação do protocolo Redis, otimizações em memória + +**Recursos de Execução**: +Gerenciamento de conexão independente do banco de dados +Validação de consulta e verificação de sintaxe +Imposição de tempo limite e limites de recursos +Paginação e streaming de resultados +Monitoramento de desempenho por tipo de banco de dados +Failover automático entre instâncias de banco de dados + +#### 8. Gerador de Respostas + +**Propósito**: Sintetiza uma resposta em linguagem natural a partir dos resultados da consulta. + +**Descrição do Algoritmo**: +O Gerador de Respostas recebe os resultados estruturados da consulta e a pergunta original, e então usa o serviço de prompt para gerar uma resposta abrangente. Ao contrário de respostas simples baseadas em modelos, ele usa um LLM para interpretar os dados do grafo no contexto da pergunta, lidando com relacionamentos complexos, agregações e inferências. O gerador pode explicar seu raciocínio referenciando a estrutura da ontologia e os triplos específicos recuperados do grafo. + +**Processo de Geração de Respostas**: +Formata os resultados da consulta em um contexto estruturado +Inclui definições de ontologia relevantes para maior clareza +Constrói um prompt com a pergunta e os resultados +Gera uma resposta em linguagem natural por meio de um LLM +Valida a resposta em relação à intenção da consulta +Adiciona citações a entidades específicas do grafo, se necessário + +### Integração com Serviços Existentes + +#### Relação com GraphRAG + +**Complementar**: onto-query fornece precisão semântica, enquanto GraphRAG fornece ampla cobertura +**Infraestrutura Compartilhada**: Ambos usam o mesmo grafo de conhecimento e serviços de prompt +**Roteamento de Consultas**: O sistema pode rotear consultas para o serviço mais apropriado com base no tipo de pergunta +**Modo Híbrido**: Pode combinar ambas as abordagens para respostas abrangentes + +#### Relação com OntoRAG Extraction + +**Ontologias Compartilhadas**: Usa as mesmas configurações de ontologia carregadas por kg-extract-ontology +**Vector Store Compartilhado**: Reutiliza os embeddings na memória do serviço de extração +**Semântica Consistente**: As consultas operam em grafos construídos com as mesmas restrições ontológicas + +### Exemplos de Consultas + +#### Exemplo 1: Consulta Simples de Entidade +**Pergunta**: "Quais animais são mamíferos?" +**Correspondência de Ontologia**: [animal, mammal, subClassOf] +**Consulta Gerada**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### Exemplo 2: Consulta de Relacionamento +**Pergunta**: "Quais documentos foram escritos por John Smith?" +**Correspondência com a Ontologia**: [documento, pessoa, tem-autor] +**Consulta Gerada**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### Exemplo 3: Consulta de Agregação +**Pergunta**: "Quantas patas têm os gatos?" +**Correspondência com a Ontologia**: [gato, número-de-patas (propriedade de tipo de dado)] +**Consulta Gerada**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### Configuração + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### Otimizações de Desempenho + +#### Otimização de Consultas + +**Poda da Ontologia**: Inclua apenas os elementos da ontologia necessários nos prompts. +**Cache de Consultas**: Armazene em cache as perguntas e consultas frequentemente feitas. +**Cache de Resultados**: Armazene os resultados para consultas idênticas dentro de um período de tempo. +**Processamento em Lote**: Processe várias perguntas relacionadas em uma única travessia de grafo. + +#### Considerações de Escalabilidade + +**Execução Distribuída**: Paralelize subconsultas em partições do grafo. +**Resultados Incrementais**: Transmita os resultados para conjuntos de dados grandes. +**Balanceamento de Carga**: Distribua a carga de consulta entre várias instâncias de serviço. +**Piscina de Recursos**: Gerencie as piscinas de conexão para bancos de dados de grafo. + +### Tratamento de Erros + +#### Cenários de Falha + +1. **Geração de Consulta Inválida**: Utilize o GraphRAG ou a pesquisa por palavras-chave. +2. **Incompatibilidade da Ontologia**: Expanda a pesquisa para um subconjunto mais amplo da ontologia. +3. **Tempo Limite da Consulta**: Simplifique a consulta ou aumente o tempo limite. +4. **Resultados Vazios**: Sugira a reformulação da consulta ou perguntas relacionadas. +5. **Falha do Serviço LLM**: Utilize consultas armazenadas em cache ou respostas baseadas em modelos. + +### Métricas de Monitoramento + +Distribuição da complexidade das perguntas. +Tamanhos das partições da ontologia. +Taxa de sucesso na geração de consultas. +Tempo de execução da consulta do grafo. +Pontuações de qualidade da resposta. +Taxas de acerto do cache. +Frequências de erro por tipo. + +## Melhorias Futuras + +1. **Aprendizado da Ontologia**: Estenda automaticamente as ontologias com base em padrões de extração. +2. **Pontuação de Confiança**: Atribua pontuações de confiança às triplas extraídas. +3. **Geração de Explicação**: Forneça o raciocínio para a extração de triplas. +4. **Aprendizado Ativo**: Solicite validação humana para extrações incertas. + +## Considerações de Segurança + +1. **Prevenção de Injeção de Prompt**: Limpe o texto do chunk antes da construção do prompt. +2. **Limites de Recursos**: Defina um limite para o uso de memória para o armazenamento vetorial. +3. **Limitação de Taxa**: Limite as solicitações de extração por cliente. +4. **Registro de Auditoria**: Rastreie todas as solicitações e resultados de extração. + +## Estratégia de Teste + +### Teste Unitário + +Carregador de ontologia com vários formatos. +Geração e armazenamento de incorporações. +Algoritmos de divisão de frases. +Cálculos de similaridade vetorial. +Análise e validação de triplas. + +### Teste de Integração + +Pipeline de extração de ponta a ponta. +Integração do serviço de configuração. +Interação com o serviço de prompt. +Tratamento de extração concorrente. + +### Teste de Desempenho + +Tratamento de ontologias grandes (1000+ classes). +Processamento de alto volume de chunks. +Uso de memória sob carga. +Benchmarks de latência. + +## Plano de Entrega + +### Visão Geral + +O sistema OntoRAG será entregue em quatro fases principais, com cada fase fornecendo valor incremental, construindo em direção ao sistema completo. O plano se concentra em estabelecer as capacidades básicas de extração primeiro, depois adicionando funcionalidade de consulta, seguido por otimizações e recursos avançados. + +### Fase 1: Fundação e Extração Central + +**Objetivo**: Estabelecer o pipeline básico de extração orientado à ontologia com correspondência vetorial simples. + +#### Etapa 1.1: Fundação do Gerenciamento de Ontologia +Implementar o carregador de configuração da ontologia (`OntologyLoader`). +Analisar e validar estruturas JSON da ontologia. +Criar armazenamento de ontologia na memória e padrões de acesso. +Implementar o mecanismo de atualização da ontologia. + +**Critérios de Sucesso**: +Carregar e analisar com sucesso as configurações da ontologia. +Validar a estrutura e a consistência da ontologia. +Lidar com várias ontologias simultâneas. + +#### Etapa 1.2: Implementação do Armazenamento Vetorial +Implementar um armazenamento vetorial simples baseado em NumPy como um protótipo inicial. +Adicionar a implementação do armazenamento vetorial FAISS. +Criar uma abstração de interface de armazenamento vetorial. +Implementar a pesquisa de similaridade com limites configuráveis. + +**Critérios de Sucesso**: +Armazenar e recuperar embeddings de forma eficiente +Realizar busca de similaridade com latência inferior a 100ms +Suportar backends NumPy e FAISS + +#### Etapa 1.3: Pipeline de Embedding de Ontologia +Integrar com o serviço de embedding +Implementar componente `OntologyEmbedder` +Gerar embeddings para todos os elementos da ontologia +Armazenar embeddings com metadados no armazenamento vetorial + +**Critérios de Sucesso**: +Gerar embeddings para classes e propriedades +Armazenar embeddings com metadados adequados +Reconstruir embeddings em caso de atualizações da ontologia + +#### Etapa 1.4: Componentes de Processamento de Texto +Implementar separador de frases usando NLTK/spaCy +Extrair frases e entidades nomeadas +Criar hierarquia de segmentos de texto +Gerar embeddings para segmentos de texto + +**Critérios de Sucesso**: +Dividir o texto em frases com precisão +Extrair frases significativas +Manter as relações de contexto + +#### Etapa 1.5: Algoritmo de Seleção de Ontologia +Implementar correspondência de similaridade entre texto e ontologia +Criar resolução de dependências para elementos da ontologia +Criar subconjuntos coerentes mínimos da ontologia +Otimizar o desempenho da geração de subconjuntos + +**Critérios de Sucesso**: +Selecionar elementos relevantes da ontologia com precisão >80% +Incluir todas as dependências necessárias +Gerar subconjuntos em <500ms + +#### Etapa 1.6: Serviço Básico de Extração +Implementar construção de prompts para extração +Integrar com o serviço de prompts +Analisar e validar respostas de triplas +Criar endpoint de serviço `kg-extract-ontology` + +**Critérios de Sucesso**: +Extrair triplas conformes à ontologia +Validar todas as triplas em relação à ontologia +Lidar com erros de extração de forma elegante + +### Fase 2: Implementação do Sistema de Consulta + +**Objetivo**: Adicionar capacidades de consulta com conhecimento da ontologia, com suporte para vários backends. + +#### Etapa 2.1: Componentes Fundamentais da Consulta +Implementar analisador de perguntas +Criar correspondência de ontologia para consultas +Adaptar a busca vetorial para o contexto da consulta +Construir componente de roteamento de backend + +**Critérios de Sucesso**: +Analisar perguntas em componentes semânticos +Corresponder perguntas a elementos relevantes da ontologia +Rotear consultas para o backend apropriado + +#### Etapa 2.2: Implementação do Caminho SPARQL +Implementar serviço `onto-query-sparql` +Criar gerador de consultas SPARQL usando LLM +Desenvolver modelos de prompt para geração de SPARQL +Validar a sintaxe SPARQL gerada + +**Critérios de Sucesso**: +Gerar consultas SPARQL válidas +Usar padrões SPARQL apropriados +Lidar com tipos de consulta complexos + +#### Etapa 2.3: Motor SPARQL-Cassandra +Implementar interface de armazenamento rdflib para Cassandra +Criar tradutor de consultas CQL +Otimizar a correspondência de padrões de triplas +Lidar com a formatação de resultados SPARQL + +**Critérios de Sucesso**: +Executar consultas SPARQL no Cassandra +Suportar padrões SPARQL comuns +Retornar resultados em formato padrão + +#### Etapa 2.4: Implementação do Caminho Cypher +Implementar serviço `onto-query-cypher` +Criar gerador de consultas Cypher usando LLM +Desenvolver modelos de prompt para geração de Cypher +Validar a sintaxe Cypher gerada + +**Critérios de Sucesso**: +Gerar consultas Cypher válidas +Usar padrões de grafo apropriados +Suportar Neo4j, Memgraph, FalkorDB + +#### Etapa 2.5: Executor Cypher +Implementar executor Cypher multi-banco de dados +Suportar protocolo Bolt (Neo4j/Memgraph) +Suportar protocolo Redis (FalkorDB) +Lidar com a normalização de resultados + +**Critérios de Sucesso**: +Executar Cypher em todos os bancos de dados alvo +Lidar com diferenças específicas de cada banco de dados +Manter pools de conexão de forma eficiente + +#### Etapa 2.6: Geração de Respostas +Implementar componente de gerador de respostas +Criar prompts para síntese de respostas +Formatar resultados de consulta para consumo por LLM +Gerar respostas em linguagem natural + +**Critérios de Sucesso**: +Gerar respostas precisas a partir de resultados de consulta +Manter o contexto da pergunta original +Fornecer respostas claras e concisas + +### Fase 3: Otimização e Robustez + +**Objetivo**: Otimizar o desempenho, adicionar cache, melhorar o tratamento de erros e aumentar a confiabilidade. + +#### Etapa 3.1: Otimização de Desempenho +Implementar cache de embeddings +Adicionar cache de resultados de consulta +Otimizar a busca vetorial com índices FAISS IVF +Implementar processamento em lote para embeddings + +**Critérios de Sucesso**: +Reduzir a latência média da consulta em 50% +Suportar 10 vezes mais requisições simultâneas +Manter tempos de resposta abaixo de um segundo + +#### Etapa 3.2: Tratamento Avançado de Erros +Implementar recuperação abrangente de erros +Adicionar mecanismos de fallback entre caminhos de consulta +Criar lógica de repetição com retrocesso exponencial +Melhorar o registro e o diagnóstico de erros + +**Critérios de Sucesso**: +Lidar graciosamente com todos os cenários de falha +Failover automático entre backends +Relatório de erros detalhado para depuração + +#### Etapa 3.3: Monitoramento e Observabilidade +Adicionar coleta de métricas de desempenho +Implementar rastreamento de consultas +Criar endpoints de verificação de saúde +Adicionar monitoramento de uso de recursos + +**Critérios de Sucesso**: +Rastrear todos os indicadores de desempenho chave +Identificar gargalos rapidamente +Monitorar a saúde do sistema em tempo real + +#### Etapa 3.4: Gerenciamento de Configuração +Implementar atualizações dinâmicas de configuração +Adicionar validação de configuração +Criar modelos de configuração +Suportar configurações específicas do ambiente + +**Critérios de Sucesso**: +Atualizar a configuração sem reinicialização +Validar todas as alterações de configuração +Suportar múltiplos ambientes de implantação + +### Fase 4: Recursos Avançados + +**Objetivo**: Adicionar capacidades sofisticadas para implantação em produção e funcionalidade aprimorada. + +#### Etapa 4.1: Suporte a Múltiplas Ontologias +Implementar lógica de seleção de ontologia +Suportar consultas entre ontologias +Lidar com versionamento de ontologias +Criar capacidades de mesclagem de ontologias + +**Critérios de Sucesso**: +Consultar em múltiplas ontologias +Lidar com conflitos de ontologia +Suportar a evolução da ontologia + +#### Etapa 4.2: Roteamento Inteligente de Consultas +Implementar roteamento baseado em desempenho +Adicionar análise de complexidade de consulta +Criar algoritmos de roteamento adaptativos +Suportar testes A/B para caminhos + +**Critérios de Sucesso**: +Roteamento de consultas de forma otimizada +Aprendizado com o desempenho das consultas +Melhoria do roteamento ao longo do tempo + +#### Etapa 4.3: Recursos Avançados de Extração +Adicionar pontuação de confiança para triplas +Implementar geração de explicações +Criar loops de feedback para melhoria +Suportar aprendizado incremental + +**Critérios de Sucesso**: +Fornecer pontuações de confiança +Explicar decisões de extração +Melhorar continuamente a precisão + +#### Etapa 4.4: Endurecimento para Produção +Adicionar limitação de taxa +Implementar autenticação/autorização +Criar automação de implantação +Adicionar backup e recuperação + +**Critérios de Sucesso**: +Segurança pronta para produção +Pipeline de implantação automatizado +Capacidade de recuperação de desastres + +### Marcos de Entrega + +1. **Marco 1** (Fim da Fase 1): Extração básica orientada por ontologia operacional +2. **Marco 2** (Fim da Fase 2): Sistema de consulta completo com caminhos SPARQL e Cypher +3. **Marco 3** (Fim da Fase 3): Sistema otimizado e robusto pronto para o ambiente de testes +4. **Marco 4** (Fim da Fase 4): Sistema pronto para produção com recursos avançados + +### Mitigação de Riscos + +#### Riscos Técnicos +**Escalabilidade do Vector Store**: Começar com NumPy, migrar gradualmente para FAISS +**Precisão da Geração de Consultas**: Implementar mecanismos de validação e fallback +**Compatibilidade com o Backend**: Testar extensivamente com cada tipo de banco de dados +**Gargalos de Desempenho**: Analisar o desempenho frequentemente e otimizar iterativamente + +#### Riscos Operacionais +**Qualidade da Ontologia**: Implementar validação e verificação de consistência +**Dependências de Serviço**: Adicionar circuit breakers e fallbacks +**Restrições de Recursos**: Monitorar e definir limites apropriados +**Consistência de Dados**: Implementar tratamento de transações adequado + +### Métricas de Sucesso + +#### Métricas de Sucesso da Fase 1 +Precisão da extração: >90% de conformidade com a ontologia +Velocidade de processamento: <1 segundo por chunk +Tempo de carregamento da ontologia: <10 segundos +Latência da busca vetorial: <100ms + +#### Métricas de Sucesso da Fase 2 +Taxa de sucesso da consulta: >95% +Latência da consulta: <2 segundos de ponta a ponta +Compatibilidade com o backend: 100% para bancos de dados de destino +Precisão da resposta: >85% com base nos dados disponíveis + +#### Métricas de Sucesso da Fase 3 +Tempo de atividade do sistema: >99,9% +Taxa de recuperação de erros: >95% +Taxa de acerto em cache: >60% +Usuários simultâneos: >100 + +#### Métricas de Sucesso da Fase 4 +Consultas multi-ontologia: Totalmente suportadas +Otimização de roteamento: Redução de latência de 30% +Precisão da pontuação de confiança: >90% +Implantação em produção: Atualizações sem interrupção + +## Referências + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.ru.md b/docs/tech-specs/ontorag.ru.md new file mode 100644 index 00000000..e06db939 --- /dev/null +++ b/docs/tech-specs/ontorag.ru.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: Техническая спецификация системы извлечения знаний на основе онтологий." +parent: "Russian (Beta)" +--- + +# OntoRAG: Техническая спецификация системы извлечения знаний на основе онтологий. + +> **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. + +## Обзор + +OntoRAG – это система извлечения знаний и запросов, основанная на онтологиях, которая обеспечивает строгую семантическую согласованность как при извлечении триплетов знаний из неструктурированного текста, так и при запросах к полученному графу знаний. Подобно GraphRAG, но с формальными ограничениями онтологий, OntoRAG гарантирует, что все извлеченные триплеты соответствуют предопределенным онтологическим структурам, и предоставляет возможности семантически-осведомленных запросов. + +Система использует сопоставление векторного сходства для динамического выбора соответствующих подмножеств онтологий как для извлечения, так и для операций запросов, что позволяет осуществлять целенаправленную и контекстуально-подходящую обработку при сохранении семантической достоверности. + +**Название сервиса**: `kg-extract-ontology` + +## Цели + +**Извлечение, соответствующее онтологии**: Обеспечить строгое соответствие всех извлеченных триплетов загруженным онтологиям. +**Динамический выбор контекста**: Использовать эмбеддинги для выбора соответствующих подмножеств онтологий для каждого фрагмента. +**Семантическая согласованность**: Поддерживать иерархии классов, области/диапазоны свойств и ограничения. +**Эффективная обработка**: Использовать векторные хранилища в памяти для быстрого сопоставления элементов онтологии. +**Масштабируемая архитектура**: Поддержка нескольких одновременных онтологий с разными доменами. + +## Предыстория + +Текущие сервисы извлечения знаний (`kg-extract-definitions`, `kg-extract-relationships`) работают без формальных ограничений, что может приводить к несовместимым или противоречивым триплетам. OntoRAG решает эту проблему следующим образом: + +1. Загрузка формальных онтологий, определяющих допустимые классы и свойства. +2. Использование эмбеддингов для сопоставления текстового содержимого с соответствующими элементами онтологии. +3. Ограничение извлечения только производством триплетов, соответствующих онтологии. +4. Обеспечение семантической проверки извлеченных знаний. + +Этот подход сочетает гибкость нейронного извлечения с строгостью формального представления знаний. + +## Технический дизайн + +### Архитектура + +Система OntoRAG состоит из следующих компонентов: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### Детали компонента + +#### 1. Загрузчик онтологий + +**Назначение**: Извлекает и анализирует конфигурации онтологий из сервиса конфигураций, используя обновления, основанные на событиях. + +**Реализация**: +Загрузчик онтологий использует очередь ConfigPush от TrustGraph для получения обновлений конфигураций онтологий, основанных на событиях. Когда элемент конфигурации типа "онтология" добавляется или изменяется, загрузчик получает обновление через очередь config-update и анализирует структуру JSON, содержащую метаданные, классы, объектные свойства и свойства типов данных. Эти проанализированные онтологии хранятся в памяти в виде структурированных объектов, которые могут быть эффективно доступны во время процесса извлечения. + +**Основные операции**: +Подписаться на очередь config-update для конфигураций типа онтология +Анализировать структуры JSON онтологий в объекты OntologyClass и OntologyProperty +Проверять структуру и согласованность онтологии +Кэшировать проанализированные онтологии в памяти для быстрого доступа +Обрабатывать потоки данных с использованием векторных хранилищ, специфичных для каждого потока + +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. Встраиватель онтологий + +**Назначение**: Создает векторные представления для всех элементов онтологии, чтобы обеспечить сопоставление семантической схожести. + +**Реализация**: +Встраиватель онтологий обрабатывает каждый элемент в загруженных онтологиях (классы, объектные свойства и свойства типов данных) и генерирует векторные представления с использованием сервиса EmbeddingsClientSpec. Для каждого элемента он объединяет идентификатор элемента, метки и описание (комментарий), чтобы создать текстовое представление. Этот текст затем преобразуется в векторное представление высокой размерности, которое отражает его семантическое значение. Эти представления хранятся в векторном хранилище FAISS, специфичном для каждого потока, вместе с метаданными об элементе, источнике онтологии и полном определении. Встраиватель автоматически определяет размерность представления из первого ответа на запрос. + +**Основные операции**: +Создавать текстовые представления из идентификаторов элементов, меток и комментариев +Генерировать представления с помощью EmbeddingsClientSpec (используя asyncio.gather для пакетной обработки) +Хранить представления с исчерпывающими метаданными в векторном хранилище FAISS +Индексировать по онтологии, типу элемента и идентификатору элемента для эффективного поиска +Автоматически определять размерность представления для инициализации векторного хранилища +Использовать модели встраивания, специфичные для каждого потока, с независимыми векторными хранилищами + +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. Обработчик текста (Разделитель предложений) + +**Назначение**: Разбивает текстовые фрагменты на более мелкие сегменты для точного сопоставления с онтологиями. + +**Реализация**: +Обработчик текста использует NLTK для токенизации предложений и разметки частей речи, чтобы разделить входящие текстовые фрагменты на предложения. Он обрабатывает совместимость версий NLTK, пытаясь загрузить `punkt_tab` и `averaged_perceptron_tagger_eng`, с возможностью использования более старых версий, если это необходимо. Каждый текстовый фрагмент разбивается на отдельные предложения, которые могут быть независимо сопоставлены с элементами онтологии. + +**Основные операции**: +Разделять текст на предложения с помощью токенизации предложений NLTK +Обрабатывать совместимость версий NLTK (punkt_tab vs punkt) +Создавать объекты TextSegment с текстом и информацией о позиции +Поддерживать как полные предложения, так и отдельные фрагменты + +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. Выборщик онтологий + +**Назначение**: Определяет наиболее релевантный поднабор элементов онтологии для текущего текстового фрагмента. + +**Реализация**: +Выборщик онтологий выполняет семантическое сопоставление между текстовыми сегментами и элементами онтологии с использованием векторного поиска по схожести FAISS. Для каждого предложения из текстового фрагмента генерируется представление, и выполняется поиск в векторном хранилище наиболее похожих элементов онтологии с использованием косинусной схожести с настраиваемым порогом (по умолчанию 0,3). После сбора всех релевантных элементов выполняется комплексное разрешение зависимостей: если выбран класс, включаются его родительские классы; если выбрано свойство, добавляются классы, являющиеся доменом и диапазоном этого свойства. Кроме того, для каждого выбранного класса автоматически включаются **все свойства, которые ссылаются на этот класс** в качестве домена или диапазона. Это обеспечивает доступ к всем релевантным свойствам отношений. + +**Основные операции**: +Генерация векторных представлений для каждого текстового сегмента (предложений) +Выполнение поиска ближайших соседей в векторном хранилище FAISS (top_k=10, threshold=0.3) +Применение порогового значения для фильтрации слабых соответствий +Разрешение зависимостей (родительские классы, домены, диапазоны) +**Автоматическое включение всех свойств, связанных с выбранными классами** (сопоставление домена/диапазона) +Построение согласованного подмножества онтологии со всеми необходимыми связями +Удаление дублирующихся элементов, появляющихся несколько раз + +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. Создание запросов + +**Назначение**: Создает структурированные запросы, которые направляют LLM (большую языковую модель) на извлечение только троек, соответствующих онтологии. + +**Реализация**: +Сервис извлечения использует шаблон Jinja2, загруженный из `ontology-prompt.md`, который форматирует подмножество онтологии и текст для извлечения LLM. Шаблон динамически перебирает классы, объектные свойства и свойства типов данных, используя синтаксис Jinja2, представляя каждый из них с их описаниями, доменами, диапазонами и иерархическими связями. Запрос включает строгие правила использования только предоставленных элементов онтологии и запрашивает вывод в формате JSON для последовательного разбора. + +**Основные операции**: +Использование шаблона Jinja2 с циклами по элементам онтологии +Форматирование классов с отношениями родительских классов (subclass_of) и комментариями +Форматирование свойств с ограничениями домена/диапазона и комментариями +Включение явных правил извлечения и требований к формату вывода +Вызов сервиса запросов с идентификатором шаблона "extract-with-ontologies" + +**Местоположение шаблона**: `ontology-prompt.md` +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (метод build_extraction_variables) + +#### 6. Основной сервис извлечения + +**Назначение**: Координирует все компоненты для выполнения сквозного извлечения троек на основе онтологии. + +**Реализация**: +Основной сервис извлечения (KgExtractOntology) является уровнем оркестровки, который управляет полным рабочим процессом извлечения. Он использует шаблон TrustGraph's FlowProcessor с инициализацией компонентов для каждого потока. Когда поступает обновление конфигурации онтологии, он инициализирует или обновляет компоненты, специфичные для потока (загрузчик онтологии, эмбеддер, обработчик текста, селектор). Когда для обработки поступает текстовый фрагмент, он координирует конвейер: разделение текста на сегменты, поиск соответствующих элементов онтологии с помощью векторного поиска, построение ограниченного запроса, вызов сервиса запросов, разбор и проверка ответа, генерация троек определения онтологии и вывод как контентных троек, так и контекстов сущностей. + +**Конвейер извлечения**: +1. Получение текстового фрагмента через очередь chunks-input +2. Инициализация компонентов потока, если это необходимо (при первом фрагменте или обновлении конфигурации) +3. Разделение текста на предложения с использованием NLTK +4. Поиск в векторном хранилище FAISS для поиска соответствующих концепций онтологии +5. Построение подмножества онтологии с автоматическим включением свойств +6. Создание переменных шаблона Jinja2 +7. Вызов сервиса запросов с шаблоном extract-with-ontologies +8. Разбор ответа JSON в структурированные тройки +9. Проверка троек и расширение URI до полных URI онтологии +10. Генерация троек определения онтологии (классы и свойства с метками/комментариями/доменами/диапазонами) +11. Построение контекстов сущностей из всех троек +12. Вывод в очереди троек и entity-contexts + +**Основные характеристики**: +Векторные хранилища на поток, поддерживающие различные модели эмбеддинга +Обновления онтологии, управляемые событиями, через очередь config-update +Автоматическое расширение URI с использованием URI онтологии +Элементы онтологии добавляются в графовое представление знаний со всеми метаданными +Контексты сущностей включают как контентные, так и элементы онтологии + +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### Конфигурация + +Сервис использует стандартный подход к конфигурации TrustGraph с аргументами командной строки: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**Основные параметры конфигурации**: +`similarity_threshold`: 0.3 (по умолчанию, настраивается в коде) +`top_k`: 10 (количество элементов онтологии для извлечения на сегмент) +`vector_store`: Per-flow FAISS IndexFlatIP с автоматически определенными измерениями +`text_processor`: NLTK с токенизацией предложений punkt_tab +`prompt_template`: "extract-with-ontologies" (шаблон Jinja2) + +**Конфигурация онтологии**: +Онтологии загружаются динамически через очередь config-update с типом "ontology". + +### Поток данных + +1. **Фаза инициализации** (для каждого потока): + Получение конфигурации онтологии через очередь config-update + Разбор JSON онтологии в объекты OntologyClass и OntologyProperty + Генерация векторных представлений для всех элементов онтологии с использованием EmbeddingsClientSpec + Сохранение векторных представлений во временном хранилище FAISS для каждого потока + Автоматическое определение размерности векторных представлений из первого ответа + +2. **Фаза извлечения** (для каждого фрагмента): + Получение фрагмента из очереди chunks-input + Разбиение фрагмента на предложения с использованием NLTK + Вычисление векторных представлений для каждого предложения + Поиск в векторном хранилище FAISS наиболее релевантных элементов онтологии + Создание подмножества онтологии с автоматическим включением свойств + Формирование переменных шаблона Jinja2 с текстом и онтологией + Вызов сервиса запросов с шаблоном extract-with-ontologies + Разбор ответа в формате JSON и проверка корректности троек + Расширение URI с использованием URI онтологии + Генерация троек определения онтологии + Создание контекстов сущностей из всех троек + Отправка в очереди triples и entity-contexts + +### Временное векторное хранилище + +**Назначение**: Обеспечивает быстрый поиск по сходству в памяти для сопоставления элементов онтологии. + +**Реализация: FAISS** + +Система использует **FAISS (Facebook AI Similarity Search)** с IndexFlatIP для поиска по точному косинусному сходству. Основные характеристики: + +**IndexFlatIP**: Точный поиск по косинусному сходству с использованием внутреннего произведения +**Автоматическое определение**: Размерность определяется из первого ответа на векторное представление +**Хранилища для каждого потока**: Каждый поток имеет независимое векторное хранилище для разных моделей векторных представлений +**Нормализация**: Все векторы нормализуются перед индексацией +**Пакетные операции**: Эффективное добавление пакетами для начальной загрузки онтологии + +**Местоположение реализации**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### Алгоритм выбора подмножества онтологии + +**Назначение**: Динамически выбирает минимальную релевантную часть онтологии для каждого текстового фрагмента. + +**Подробные шаги алгоритма**: + +1. **Сегментация текста**: + Разбиение входного фрагмента на предложения с использованием NLP для определения границ предложений + Извлечение именных групп, глагольных групп и именованных сущностей из каждого предложения + Создание иерархической структуры сегментов с сохранением контекста + +2. **Генерация векторных представлений**: + Генерация векторных представлений для каждого текстового сегмента (предложений и фраз) + Использование той же модели векторных представлений, что и для элементов онтологии + Кэширование векторных представлений для повторяющихся сегментов для повышения производительности + +3. **Поиск по сходству**: + Для каждого векторного представления текстового сегмента выполняется поиск в векторном хранилище + Извлекаются k (например, 10) наиболее похожих элементов онтологии + Применяется порог сходства (например, 0.7) для фильтрации слабых совпадений + Результаты агрегируются по всем сегментам, отслеживается частота совпадений + +4. **Разрешение зависимостей**: + Для каждого выбранного класса рекурсивно включаются все родительские классы до корневого + Для каждого выбранного свойства включаются классы, являющиеся доменом и диапазоном + Для обратных свойств обеспечивается включение обоих направлений + Добавляются эквивалентные классы, если они существуют в онтологии + +5. **Создание подмножества**: + Удаление дубликатов элементов при сохранении взаимосвязей + Организация в классы, объектные свойства и свойства типов данных + Обеспечение сохранения всех ограничений и взаимосвязей + Создание мини-онтологии, которая является самодостаточной и полной + +**Пример**: +Данный текст: "The brown dog chased the white cat up the tree." +Сегменты: ["brown dog", "white cat", "tree", "chased"] +Соответствующие элементы: [dog (class), cat (class), animal (parent), chases (property)] +Зависимости: [animal (parent of dog and cat), lifeform (parent of animal)] +Окончательное подмножество: Полная мини-онтология с иерархией животных и отношением "chases" + +### Проверка троек + +**Назначение**: Обеспечивает строгое соответствие всех извлеченных троек ограничениям онтологии. + +**Алгоритм проверки**: + +1. **Валидация классов**: + Проверьте, являются ли субъекты экземплярами классов, определенных в подмножестве онтологии. + Для свойств объектов убедитесь, что объекты также являются допустимыми экземплярами классов. + Проверьте имена классов по отношению к словарю классов онтологии. + Обрабатывайте иерархии классов: экземпляры подклассов считаются допустимыми для ограничений родительского класса. + +2. **Валидация свойств**: + Убедитесь, что предикаты соответствуют свойствам в подмножестве онтологии. + Различайте свойства объектов (от сущности к сущности) и свойства данных (от сущности к литералу). + Проверьте, соответствуют ли имена свойств точно (с учетом пространства имен, если оно присутствует). + +3. **Проверка домена/диапазона**: + Для каждого свойства, используемого в качестве предиката, извлеките его домен и диапазон. + Убедитесь, что тип субъекта соответствует или наследуется от домена свойства. + Убедитесь, что тип объекта соответствует или наследуется от диапазона свойства. + Для свойств данных убедитесь, что объект является литералом правильного типа XSD. + +4. **Валидация кардинальности**: + Отслеживайте количество использования свойств для каждого субъекта. + Проверьте минимальную кардинальность: убедитесь, что обязательные свойства присутствуют. + Проверьте максимальную кардинальность: убедитесь, что свойство не используется слишком много раз. + Для функциональных свойств убедитесь, что присутствует не более одного значения для каждого субъекта. + +5. **Валидация данных**: + Разбирайте литеральные значения в соответствии с их объявленными типами XSD. + Проверяйте, являются ли целые числа допустимыми числами, правильно ли отформатированы даты и т.д. + Проверяйте шаблоны строк, если определены ограничения regex. + Убедитесь, что URI имеют правильную структуру для типов xsd:anyURI. + +**Пример валидации**: +Тройка: ("Buddy", "has-owner", "John") +Проверьте, что "Buddy" имеет тип класса, который может иметь свойство "has-owner". +Проверьте, существует ли "has-owner" в онтологии. +Убедитесь, что ограничение домена: субъект должен быть типа "Pet" или подкласса. +Убедитесь, что ограничение диапазона: объект должен быть типа "Person" или подкласса. +Если допустимо, добавьте в вывод; если недопустимо, зарегистрируйте нарушение и пропустите. + +## Вопросы производительности + +### Стратегии оптимизации + +1. **Кэширование вложений**: Кэшируйте вложения для часто используемых текстовых фрагментов. +2. **Пакетная обработка**: Обрабатывайте несколько фрагментов параллельно. +3. **Индексирование векторного хранилища**: Используйте алгоритмы приблизительного поиска ближайших соседей для больших онтологий. +4. **Оптимизация запросов**: Минимизируйте размер запроса, включая только необходимые элементы онтологии. +5. **Кэширование результатов**: Кэшируйте результаты извлечения для идентичных фрагментов. + +### Масштабируемость + +**Горизонтальное масштабирование**: Несколько экземпляров экстрактора с общим кэшем онтологии. +**Разделение онтологии**: Разделите большие онтологии по доменам. +**Потоковая обработка**: Обрабатывайте фрагменты по мере их поступления, без пакетной обработки. +**Управление памятью**: Периодическая очистка неиспользуемых вложений. + +## Обработка ошибок + +### Сценарии сбоев + +1. **Отсутствующие онтологии**: Переход к извлечению без ограничений. +2. **Сбой службы вложений**: Используйте кэшированные вложения или пропустите семантическое сопоставление. +3. **Тайм-аут службы запросов**: Повторите попытку с экспоненциальной задержкой. +4. **Недопустимый формат тройки**: Зарегистрируйте и пропустите неформатированные тройки. +5. **Несоответствия в онтологии**: Сообщите о конфликтах и используйте наиболее конкретные допустимые элементы. + +### Мониторинг + +Ключевые метрики для отслеживания: + +Время загрузки онтологии и использование памяти. +Задержка генерации вложений. +Производительность векторного поиска. +Время отклика службы запросов. +Точность извлечения тройки. +Уровень соответствия онтологии. + +## Путь миграции + +### Из существующих экстракторов + +1. **Параллельная работа**: Работайте параллельно с существующими экстракторами изначально. +2. **Постепенное развертывание**: Начните с определенных типов документов. +3. **Сравнение качества**: Сравните качество вывода с существующими экстракторами. +4. **Полная миграция**: Замените существующие экстракторы после проверки качества. + +### Разработка онтологии + +1. **Начальная версия из существующих**: Сгенерируйте начальные онтологии из существующих знаний. +2. **Итеративная доработка**: Дорабатывайте на основе шаблонов извлечения. +3. **Экспертная оценка**: Проверьте с экспертами в предметной области. +4. **Непрерывное улучшение**: Обновляйте на основе обратной связи об извлечении. + +## Сервис запросов, чувствительный к онтологии + +### Обзор + +Сервис запросов, чувствительный к онтологии, предоставляет несколько путей запросов для поддержки различных бэкенд-хранилищ графов. Он использует знания онтологии для точного, семантически-осведомленного ответа на вопросы как в Cassandra (через SPARQL), так и в графовых хранилищах (Neo4j, Memgraph, FalkorDB) (через Cypher). + +**Компоненты сервиса**: +`onto-query-sparql`: Преобразует естественный язык в SPARQL для Cassandra. +`sparql-cassandra`: Слой запросов SPARQL для Cassandra с использованием rdflib. +`onto-query-cypher`: Преобразует естественный язык в Cypher для графовых баз данных. +`cypher-executor`: Выполнение запросов Cypher для Neo4j/Memgraph/FalkorDB. + +### Архитектура + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### Конвейер обработки запросов + +#### 1. Анализатор вопросов + +**Назначение**: Разделяет вопросы пользователей на семантические компоненты для сопоставления с онтологией. + +**Описание алгоритма**: +Анализатор вопросов принимает входящий вопрос на естественном языке и разбивает его на значимые сегменты, используя тот же подход к разделению предложений, что и конвейер извлечения. Он определяет ключевые сущности, отношения и ограничения, упомянутые в вопросе. Каждый сегмент анализируется для определения типа вопроса (фактический, агрегирующий, сравнительный и т. д.) и ожидаемого формата ответа. Это разделение помогает определить, какие части онтологии наиболее релевантны для ответа на вопрос. + +**Основные операции**: +Разделение вопроса на предложения и фразы +Определение типа и намерения вопроса +Извлечение упомянутых сущностей и отношений +Обнаружение ограничений и фильтров в вопросе +Определение ожидаемого формата ответа + +#### 2. Сопоставитель онтологий для запросов + +**Назначение**: Определяет соответствующий подмножество онтологии, необходимое для ответа на вопрос. + +**Описание алгоритма**: +Подобно компоненту Ontology Selector конвейера извлечения, но оптимизирован для ответов на вопросы. Сопоставитель генерирует представления для сегментов вопроса и ищет в векторном хранилище соответствующие элементы онтологии. Однако он фокусируется на поиске концепций, которые будут полезны для построения запросов, а не для извлечения. Он расширяет выбор, включая связанные свойства, которые могут быть пройдены во время исследования графа, даже если они не упоминаются явно в вопросе. Например, если задан вопрос о "сотрудниках", он может включить такие свойства, как "работает в", "управляет" и "отчитывается", которые могут быть релевантны для поиска информации о сотрудниках. + +**Стратегия сопоставления**: +Генерация представлений для сегментов вопроса +Поиск непосредственно упомянутых концепций онтологии +Включение свойств, соединяющих упомянутые классы +Добавление обратных и связанных свойств для обхода +Включение родительских/дочерних классов для иерархических запросов +Создание подмножества онтологии, ориентированного на запросы + +#### 3. Маршрутизатор бэкэнда + +**Назначение**: Маршрутизирует запросы к соответствующему бэкэнду в зависимости от конфигурации. + +**Описание алгоритма**: +Маршрутизатор бэкэнда анализирует системную конфигурацию, чтобы определить, какой бэкэнд графа активен (на базе Cassandra или Cypher). Он направляет вопрос и подмножество онтологии к соответствующему сервису генерации запросов. Маршрутизатор также может поддерживать балансировку нагрузки между несколькими бэкэндами или механизмы отката, если основной бэкэнд недоступен. + +**Логика маршрутизации**: +Проверка настроенного типа бэкэнда из системных настроек +Маршрутизация к `onto-query-sparql` для бэкэндов Cassandra +Маршрутизация к `onto-query-cypher` для Neo4j/Memgraph/FalkorDB +Поддержка конфигураций с несколькими бэкэндами с распределением запросов +Обработка сценариев отката и балансировки нагрузки + +#### 4. Генерация SPARQL-запросов (`onto-query-sparql`) + +**Назначение**: Преобразует вопросы на естественном языке в SPARQL-запросы для выполнения в Cassandra. + +**Описание алгоритма**: +Генератор SPARQL-запросов принимает вопрос и подмножество онтологии и создает SPARQL-запрос, оптимизированный для выполнения в бэкэнде Cassandra. Он использует сервис подсказок со специальной для SPARQL-шаблоном, который включает семантику RDF/OWL. Генератор понимает шаблоны SPARQL, такие как пути свойств, необязательные предложения и фильтры, которые могут эффективно преобразовываться в операции Cassandra. + +**Шаблон подсказки для генерации SPARQL**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. Генерация запросов Cypher (`onto-query-cypher`) + +**Назначение**: Преобразует вопросы, сформулированные на естественном языке, в запросы Cypher для графовых баз данных. + +**Описание алгоритма**: +Генератор запросов Cypher создает нативные запросы Cypher, оптимизированные для Neo4j, Memgraph и FalkorDB. Он сопоставляет классы онтологии с метками узлов, а свойства - с отношениями, используя синтаксис сопоставления шаблонов Cypher. Генератор включает в себя оптимизации, специфичные для Cypher, такие как указания направления отношений, использование индексов и указания для планирования запросов. + +**Шаблон запроса Cypher**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. Движок запросов SPARQL-Cassandra (`sparql-cassandra`) + +**Назначение**: Выполняет запросы SPARQL к базе данных Cassandra с использованием библиотеки Python rdflib. + +**Описание алгоритма**: +Движок SPARQL-Cassandra реализует обработчик SPARQL с использованием библиотеки rdflib на Python и пользовательского хранилища для Cassandra. Он преобразует графы запросов SPARQL в соответствующие запросы CQL для Cassandra, обрабатывая соединения, фильтры и агрегации. Движок поддерживает отображение RDF в Cassandra, которое сохраняет семантическую структуру, оптимизируя при этом для модели хранения колоночных семей Cassandra. + +**Особенности реализации**: +Реализация интерфейса хранилища rdflib для Cassandra +Поддержка запросов SPARQL 1.1 с распространенными шаблонами +Эффективный перевод шаблонов триплетов в CQL +Поддержка путей свойств и иерархических запросов +Потоковая передача результатов для больших наборов данных +Объединение подключений и кэширование запросов + +**Пример перевода**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +Переводит в оптимизированные запросы Cassandra, использующие индексы и ключи разделения. + +#### 7. Исполнитель запросов Cypher (`cypher-executor`) + +**Назначение**: Выполняет запросы Cypher к базам данных Neo4j, Memgraph и FalkorDB. + +**Описание алгоритма**: +Исполнитель запросов Cypher предоставляет унифицированный интерфейс для выполнения запросов Cypher в различных графовых базах данных. Он обрабатывает специфичные для базы данных протоколы подключения, подсказки для оптимизации запросов и нормализацию формата результатов. Исполнитель включает логику повторных попыток, пулинг соединений и управление транзакциями, соответствующие для каждого типа базы данных. + +**Поддержка нескольких баз данных**: +**Neo4j**: Протокол Bolt, функции транзакций, подсказки для индексов +**Memgraph**: Собственный протокол, потоковая передача результатов, аналитические запросы +**FalkorDB**: Адаптация протокола Redis, оптимизации в памяти + +**Функции выполнения**: +Управление подключениями, независимое от базы данных +Проверка запросов и синтаксический анализ +Применение ограничений по времени ожидания и ресурсам +Пагинация и потоковая передача результатов +Мониторинг производительности для каждого типа базы данных +Автоматическое переключение при отказе между экземплярами базы данных + +#### 8. Генератор ответов + +**Назначение**: Синтезирует ответ на естественном языке на основе результатов запроса. + +**Описание алгоритма**: +Генератор ответов принимает структурированные результаты запроса и исходный вопрос, а затем использует сервис подсказок для генерации всестороннего ответа. В отличие от простых ответов, основанных на шаблонах, он использует LLM для интерпретации данных графа в контексте вопроса, обрабатывая сложные взаимосвязи, агрегации и выводы. Генератор может объяснить свою логику, ссылаясь на структуру онтологии и конкретные тройки, извлеченные из графа. + +**Процесс генерации ответов**: +Форматирование результатов запроса в структурированный контекст +Включение соответствующих определений онтологии для ясности +Создание подсказки с вопросом и результатами +Генерация ответа на естественном языке с помощью LLM +Проверка ответа на соответствие намерению запроса +Добавление ссылок на конкретные сущности графа, если это необходимо + +### Интеграция с существующими сервисами + +#### Взаимодействие с GraphRAG + +**Дополняющие**: onto-query обеспечивает семантическую точность, а GraphRAG обеспечивает широкое покрытие +**Общая инфраструктура**: Оба используют одну и ту же базу знаний и сервисы подсказок +**Маршрутизация запросов**: Система может маршрутизировать запросы к наиболее подходящему сервису в зависимости от типа вопроса +**Гибридный режим**: Можно комбинировать оба подхода для получения всесторонних ответов + +#### Взаимодействие с OntoRAG Extraction + +**Общие онтологии**: Использует одни и те же конфигурации онтологии, загруженные kg-extract-ontology +**Общий векторный магазин**: Повторно использует встроенные представления из сервиса извлечения +**Согласованная семантика**: Запросы выполняются над графами, созданными с использованием одних и тех же онтологических ограничений + +### Примеры запросов + +#### Пример 1: Простой запрос сущности +**Вопрос**: "Какие животные являются млекопитающими?" +**Соответствие онтологии**: [животное, млекопитающее, subClassOf] +**Сгенерированный запрос**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### Пример 2: Запрос взаимосвязей +**Вопрос**: "Какие документы были написаны Джоном Смитом?" +**Соответствие онтологии**: [документ, человек, автор] +**Сгенерированный запрос**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### Пример 3: Запрос агрегации +**Вопрос**: "Сколько ног у кошек?" +**Соответствие онтологии**: [кошка, количество_ног (свойство типа данных)] +**Сгенерированный запрос**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### Конфигурация + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### Оптимизация производительности + +#### Оптимизация запросов + +**Обрезка онтологии**: Включайте только необходимые элементы онтологии в запросы. +**Кэширование запросов**: Кэшируйте часто задаваемые вопросы и соответствующие запросы. +**Кэширование результатов**: Сохраняйте результаты для идентичных запросов в течение определенного периода времени. +**Пакетная обработка**: Обрабатывайте несколько связанных вопросов в рамках одного обхода графа. + +#### Соображения масштабируемости + +**Распределенное выполнение**: Параллелизуйте подзапросы по разделам графа. +**Инкрементные результаты**: Потоково передавайте результаты для больших наборов данных. +**Балансировка нагрузки**: Распределяйте нагрузку запросов между несколькими экземплярами сервиса. +**Пул ресурсов**: Управляйте пулами соединений к базам данных графов. + +### Обработка ошибок + +#### Сценарии сбоев + +1. **Неправильная генерация запроса**: Переключайтесь на GraphRAG или простой поиск по ключевым словам. +2. **Несоответствие онтологии**: Расширьте поиск до более широкого подмножества онтологии. +3. **Тайм-аут запроса**: Упростите запрос или увеличьте время ожидания. +4. **Отсутствие результатов**: Предложите переформулировать запрос или связанные вопросы. +5. **Сбой сервиса LLM**: Используйте кэшированные запросы или ответы на основе шаблонов. + +### Метрики мониторинга + +Распределение сложности вопросов. +Размеры разделов онтологии. +Успешность генерации запросов. +Время выполнения запросов к графу. +Оценки качества ответов. +Коэффициенты попадания в кэш. +Частота ошибок по типам. + +## Будущие улучшения + +1. **Обучение онтологии**: Автоматически расширяйте онтологии на основе шаблонов извлечения. +2. **Оценка достоверности**: Присваивайте оценки достоверности извлеченным тройкам. +3. **Генерация объяснений**: Предоставляйте обоснование для извлечения троек. +4. **Активное обучение**: Запрашивайте подтверждение человеком для неопределенных извлечений. + +## Соображения безопасности + +1. **Предотвращение внедрения вредоносного кода**: Очищайте текст фрагментов перед построением запроса. +2. **Ограничения ресурсов**: Ограничивайте использование памяти для векторного хранилища. +3. **Ограничение скорости**: Ограничивайте количество запросов на извлечение от каждого клиента. +4. **Журналирование аудита**: Отслеживайте все запросы и результаты извлечения. + +## Стратегия тестирования + +### Модульное тестирование + +Загрузчик онтологии с различными форматами. +Генерация и хранение векторов. +Алгоритмы разбиения предложений. +Расчеты векторного сходства. +Разбор и проверка троек. + +### Интеграционное тестирование + +Комплексная цепочка извлечения. +Интеграция с сервисом конфигурации. +Взаимодействие с сервисом запросов. +Обработка одновременных извлечений. + +### Тестирование производительности + +Обработка больших онтологий (1000+ классов). +Обработка больших объемов фрагментов. +Использование памяти под нагрузкой. +Тесты на задержку. + +## План поставки + +### Обзор + +Система OntoRAG будет поставляться в четыре основные фазы, каждая из которых будет предоставлять постепенную ценность, одновременно создавая полную систему. План сосредоточен на создании основных возможностей извлечения, а затем добавлении функциональности запросов, а также оптимизации и расширенных функций. + +### Фаза 1: Основа и основное извлечение + +**Цель**: Создать базовый конвейер извлечения на основе онтологии с простым векторным сопоставлением. + +#### Шаг 1.1: Основа управления онтологией +Реализовать загрузчик конфигурации онтологии (`OntologyLoader`). +Разбирать и проверять структуры JSON онтологии. +Создать хранилище онтологии в памяти и шаблоны доступа. +Реализовать механизм обновления онтологии. + +**Критерии успеха**: +Успешная загрузка и разбор конфигураций онтологии. +Проверка структуры и согласованности онтологии. +Обработка нескольких одновременных онтологий. + +#### Шаг 1.2: Реализация векторного хранилища +Реализовать простое векторное хранилище на основе NumPy в качестве первоначального прототипа. +Добавить реализацию векторного хранилища FAISS. +Создать абстракцию интерфейса векторного хранилища. +Реализовать поиск по сходству с настраиваемыми порогами. + +**Критерии успеха**: +Эффективное хранение и извлечение эмбеддингов. +Выполнение поиска по схожести с задержкой менее 100 мс. +Поддержка бэкендов NumPy и FAISS. + +#### Шаг 1.3: Конвейер эмбеддингов онтологии +Интеграция с сервисом эмбеддингов. +Реализация компонента `OntologyEmbedder`. +Генерация эмбеддингов для всех элементов онтологии. +Хранение эмбеддингов с метаданными в векторном хранилище. + +**Критерии успеха**: +Генерация эмбеддингов для классов и свойств. +Хранение эмбеддингов с правильными метаданными. +Перегенерация эмбеддингов при обновлениях онтологии. + +#### Шаг 1.4: Компоненты обработки текста +Реализация разбиения на предложения с использованием NLTK/spaCy. +Извлечение фраз и именованных сущностей. +Создание иерархии текстовых сегментов. +Генерация эмбеддингов для текстовых сегментов. + +**Критерии успеха**: +Точное разбиение текста на предложения. +Извлечение значимых фраз. +Сохранение контекстных связей. + +#### Шаг 1.5: Алгоритм выбора онтологии +Реализация сопоставления по схожести между текстом и онтологией. +Создание механизма разрешения зависимостей для элементов онтологии. +Создание минимальных когерентных подмножеств онтологии. +Оптимизация производительности генерации подмножеств. + +**Критерии успеха**: +Выбор релевантных элементов онтологии с точностью >80%. +Включение всех необходимых зависимостей. +Генерация подмножеств менее чем за 500 мс. + +#### Шаг 1.6: Базовый сервис извлечения +Реализация построения запросов для извлечения. +Интеграция с сервисом запросов. +Разбор и проверка ответов в формате триплетов. +Создание конечной точки сервиса `kg-extract-ontology`. + +**Критерии успеха**: +Извлечение триплетов, соответствующих онтологии. +Проверка всех триплетов на соответствие онтологии. +Обработка ошибок извлечения. + +### Фаза 2: Реализация системы запросов + +**Цель**: Добавление возможностей запросов, учитывающих онтологию, с поддержкой нескольких бэкендов. + +#### Шаг 2.1: Базовые компоненты системы запросов +Реализация анализатора вопросов. +Создание сопоставителя онтологии для запросов. +Адаптация векторного поиска для контекста запроса. +Создание компонента маршрутизации бэкендов. + +**Критерии успеха**: +Анализ вопросов на семантические компоненты. +Сопоставление вопросов с релевантными элементами онтологии. +Маршрутизация запросов к соответствующему бэкенду. + +#### Шаг 2.2: Реализация пути SPARQL +Реализация сервиса `onto-query-sparql`. +Создание генератора SPARQL-запросов с использованием LLM. +Разработка шаблонов запросов для генерации SPARQL. +Проверка синтаксиса сгенерированных SPARQL-запросов. + +**Критерии успеха**: +Генерация корректных SPARQL-запросов. +Использование соответствующих шаблонов SPARQL. +Поддержка сложных типов запросов. + +#### Шаг 2.3: Движок SPARQL-Cassandra +Реализация интерфейса хранилища rdflib для Cassandra. +Создание переводчика CQL-запросов. +Оптимизация сопоставления триплетов. +Обработка форматирования результатов SPARQL. + +**Критерии успеха**: +Выполнение SPARQL-запросов на Cassandra. +Поддержка распространенных шаблонов SPARQL. +Возврат результатов в стандартном формате. + +#### Шаг 2.4: Реализация пути Cypher +Реализация сервиса `onto-query-cypher`. +Создание генератора Cypher-запросов с использованием LLM. +Разработка шаблонов запросов для генерации Cypher. +Проверка синтаксиса сгенерированных Cypher-запросов. + +**Критерии успеха**: +Генерация корректных Cypher-запросов. +Использование соответствующих шаблонов графов. +Поддержка Neo4j, Memgraph, FalkorDB. + +#### Шаг 2.5: Исполнитель Cypher +Реализовать многобазовый исполнитель запросов Cypher. +Поддержка протокола Bolt (Neo4j/Memgraph). +Поддержка протокола Redis (FalkorDB). +Обработка нормализации результатов. + +**Критерии успеха**: +Выполнение запросов Cypher на всех целевых базах данных. +Обработка специфических для базы данных различий. +Эффективное управление пулами соединений. + +#### Шаг 2.6: Генерация ответов +Реализовать компонент генерации ответов. +Создать подсказки для синтеза ответов. +Форматировать результаты запросов для использования LLM. +Генерировать ответы на естественном языке. + +**Критерии успеха**: +Генерировать точные ответы на основе результатов запросов. +Сохранять контекст из исходного вопроса. +Предоставлять четкие и лаконичные ответы. + +### Фаза 3: Оптимизация и надежность + +**Цель**: Оптимизировать производительность, добавить кэширование, улучшить обработку ошибок и повысить надежность. + +#### Шаг 3.1: Оптимизация производительности +Реализовать кэширование эмбеддингов. +Добавить кэширование результатов запросов. +Оптимизировать векторный поиск с использованием индексов FAISS IVF. +Реализовать пакетную обработку для эмбеддингов. + +**Критерии успеха**: +Уменьшить среднюю задержку запроса на 50%. +Поддерживать в 10 раз больше одновременных запросов. +Поддерживать время отклика менее 1 секунды. + +#### Шаг 3.2: Продвинутая обработка ошибок +Реализовать комплексное восстановление после ошибок. +Добавить механизмы отката между путями запросов. +Создать логику повторных попыток с экспоненциальной задержкой. +Улучшить ведение журналов ошибок и диагностику. + +**Критерии успеха**: +Грациозно обрабатывать все сценарии сбоев. +Автоматическое переключение на резервные системы. +Подробное сообщение об ошибках для отладки. + +#### Шаг 3.3: Мониторинг и наблюдаемость +Добавить сбор показателей производительности. +Реализовать трассировку запросов. +Создать конечные точки проверки состояния. +Добавить мониторинг использования ресурсов. + +**Критерии успеха**: +Отслеживать все ключевые показатели производительности. +Быстро выявлять узкие места. +Мониторить состояние системы в режиме реального времени. + +#### Шаг 3.4: Управление конфигурацией +Реализовать динамические обновления конфигурации. +Добавить проверку конфигурации. +Создать шаблоны конфигурации. +Поддержка настроек, специфичных для среды. + +**Критерии успеха**: +Обновлять конфигурацию без перезапуска. +Проверять все изменения конфигурации. +Поддерживать несколько сред развертывания. + +### Фаза 4: Продвинутые функции + +**Цель**: Добавить сложные возможности для производственного развертывания и расширенной функциональности. + +#### Шаг 4.1: Поддержка нескольких онтологий +Реализовать логику выбора онтологии. +Поддержка межонтологических запросов. +Обработка версий онтологий. +Создать возможности объединения онтологий. + +**Критерии успеха**: +Выполнять запросы между несколькими онтологиями. +Обрабатывать конфликты онтологий. +Поддерживать эволюцию онтологий. + +#### Шаг 4.2: Интеллектуальная маршрутизация запросов +Реализовать маршрутизацию на основе производительности +Добавить анализ сложности запросов +Создать адаптивные алгоритмы маршрутизации +Поддержка A/B-тестирования для путей + +**Критерии успеха**: +Оптимизировать маршрутизацию запросов +Учиться на основе производительности запросов +Улучшать маршрутизацию со временем + +#### Шаг 4.3: Расширенные функции извлечения +Добавить оценку достоверности для троек +Реализовать генерацию объяснений +Создать механизмы обратной связи для улучшения +Поддержка инкрементного обучения + +**Критерии успеха**: +Предоставлять оценки достоверности +Объяснять решения по извлечению +Постоянно повышать точность + +#### Шаг 4.4: Подготовка к производству +Добавить ограничение скорости +Реализовать аутентификацию/авторизацию +Создать автоматизацию развертывания +Добавить резервное копирование и восстановление + +**Критерии успеха**: +Безопасность, готовая к производству +Автоматизированная цепочка развертывания +Возможность восстановления после сбоев + +### Этапы выполнения + +1. **Этап 1** (Конец Фазы 1): Базовая работа системы извлечения, основанной на онтологии. +2. **Этап 2** (Конец Фазы 2): Полная система запросов с путями SPARQL и Cypher. +3. **Этап 3** (Конец Фазы 3): Оптимизированная, надежная система, готовая к тестированию. +4. **Этап 4** (Конец Фазы 4): Система, готовая к производству, с расширенными функциями. + +### Смягчение рисков + +#### Технические риски +**Масштабируемость векторного хранилища**: Начать с NumPy, постепенно перейти на FAISS. +**Точность генерации запросов**: Реализовать механизмы проверки и резервирования. +**Совместимость с бэкендом**: Тщательно тестировать с каждым типом базы данных. +**Узкие места производительности**: Профилировать и оптимизировать итеративно. + +#### Операционные риски +**Качество онтологии**: Реализовать проверку и контроль согласованности. +**Зависимости от сервисов**: Добавить предохранители и механизмы резервирования. +**Ограничения ресурсов**: Отслеживать и устанавливать соответствующие лимиты. +**Согласованность данных**: Реализовать правильную обработку транзакций. + +### Показатели успеха + +#### Показатели успеха Фазы 1 +Точность извлечения: >90% соответствия онтологии +Скорость обработки: <1 секунды на фрагмент +Время загрузки онтологии: <10 секунд +Задержка векторного поиска: <100 мс + +#### Показатели успеха Фазы 2 +Успешность выполнения запросов: >95% +Задержка запросов: <2 секунды (от начала до конца) +Совместимость с бэкендом: 100% для целевых баз данных +Точность ответов: >85% на основе доступных данных + +#### Показатели успеха Фазы 3 +Время безотказной работы системы: >99.9% +Скорость восстановления после ошибок: >95% +Процент попаданий в кэш: >60% +Количество одновременных пользователей: >100 + +#### Показатели успеха Фазы 4 +Поддержка запросов к нескольким онтологиям: Полная поддержка +Оптимизация маршрутизации: Снижение задержки на 30% +Точность оценки достоверности: >90% +Развертывание в производственной среде: Обновления без простоев + +## Ссылки + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.sw.md b/docs/tech-specs/ontorag.sw.md new file mode 100644 index 00000000..baea5794 --- /dev/null +++ b/docs/tech-specs/ontorag.sw.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: Vigezo vya Kiufundi vya Utaratibu wa Kuchimbua Maarifa na Ufuatiliaji Kulingana na Ontolojia." +parent: "Swahili (Beta)" +--- + +# OntoRAG: Vigezo vya Kiufundi vya Utaratibu wa Kuchimbua Maarifa na Ufuatiliaji Kulingana na Ontolojia. + +> **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 + +OntoRAG ni mfumo wa kuchimbua maarifa na kufuatilia maswali unaoendeshwa na ontolojia, ambao unaweka vikwazo vikali vya utaratibu wakati wa kuchimbua vipengele vya maarifa kutoka kwa maandishi yasiyo na muundo na wakati wa kufuatilia maswali kwenye grafu ya maarifa iliyoundwa. Kufanana na GraphRAG lakini na vikwazo vya ontolojia rasmi, OntoRAG huhakikisha kwamba vipengele vyote vilivyochimbwa vinafuata miundo iliyobainishwa ya ontolojia na hutoa uwezo wa kufuatilia maswali kwa kuzingatia maana. + +Mfumo hutumia utangamano wa vector ili kuchagua kwa kasi sehemu muhimu za ontolojia kwa ajili ya uchimbaji na operesheni za kufuatilia maswali, na hivyo kuruhusu usindikaji ulioelezwa na unaofaa kwa muktadha huku ukiendelea kudumisha utaratibu wa maana. + +**Jina la Huduma**: `kg-extract-ontology` + +## Malengo + +**Uchimbaji Unaofuata Ontolojia**: Hakikisha kwamba vipengele vyote vilivyochimbwa vinafuata kikamilifu ontolojia zilizopakuliwa. +**Uchaguzi wa Muktadha Unaobadilika**: Tumia embeddings kuchagua sehemu muhimu za ontolojia kwa kila sehemu. +**Utaratibu wa Maana**: Dumu kwa safu za darasa, nyanja/mahusiano ya mali, na vikwazo. +**Usindikaji Wenye Ufanisi**: Tumia maduka ya vector ya ndani kwa utangamano wa haraka wa vipengele vya ontolojia. +**Muundo Unaoweza Kukua**: Unga ontolojia nyingi za wakati mmoja zenye nyanja tofauti. + +## Asili + +Huduma za sasa za kuchimbua maarifa (`kg-extract-definitions`, `kg-extract-relationships`) zinafanya kazi bila vikwazo rasmi, na hivyo zinaweza kuzalisha vipengele ambavyo havifanani au ambavyo havikubaliki. OntoRAG inashughulikia hili kwa: + +1. Kupakua ontolojia rasmi ambazo zinafafanua madarasa na mali halali. +2. Kutumia embeddings kulinganisha yaliyomo katika maandishi na vipengele muhimu vya ontolojia. +3. Kuweka kikwazo kwa uchimbaji ili kuzalisha tu vipengele vinavyofuata ontolojia. +4. Kutoa uthibitisho wa maana wa maarifa yaliyochimbwa. + +Mbinu hii inachanganya unyumbufu wa uchimbaji wa neva na ukakamavu wa uwakilishi rasmi wa maarifa. + +## Muundo wa Kiufundi + +### Muundo + +Mfumo wa OntoRAG una vipengele vifuatavyo: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### Maelezo ya Vipengele + +#### 1. Mpakuzi wa Ontolojia + +**Madhumuni**: Hupata na huchanganua usanidi wa ontolojia kutoka kwa huduma ya usanidi kwa kutumia sasisho zinazotokana na matukio. + +**Utekelezaji**: +Mpakuzi wa Ontolojia hutumia folyo ya ConfigPush ya TrustGraph ili kupokea sasisho za usanidi wa ontolojia zinazotokana na matukio. Wakati kipengele cha usanidi cha aina ya "ontolojia" kinaongezwa au kihaririwa, mpakuzi hupokea sasisho kupitia folyo ya config-update na huchanganua muundo wa JSON unao na metadata, madarasa, sifa za kitu, na sifa za aina ya data. Ontolojia zilizochanganuliwa hizi huhifadhiwa katika kumbukumbu kama vitu vilivyopangwa ambavyo vinaweza kupatikana kwa urahisi wakati wa mchakato wa uondoaji. + +**Miamala Muhimu**: +Jisajili kwa folyo ya config-update kwa usanidi wa aina ya ontolojia +Changanua muundo wa ontolojia wa JSON katika vitu vya OntologyClass na OntologyProperty +Thibitisha muundo na utangamano wa ontolojia +Hifadhi ontolojia zilizochanganuliwa katika kumbukumbu kwa upatikanaji wa haraka +Shirikisha usindikaji wa kila mtiririko na maduka ya vekta maalum ya mtiririko + +**Mahali pa Utekelezaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. Mpakuzi wa Ontolojia + +**Madhumuni**: Huunda ufumbuzi wa vekta kwa vipengele vyote vya ontolojia ili kuwezesha utangamano wa kulinganisha wa kiufundi. + +**Utekelezaji**: +Mpakuzi wa Ontolojia huchakata kila kipengele katika ontolojia zilizopakuliwa (madarasa, sifa za kitu, na sifa za aina ya data) na huunda ufumbuzi wa vekta kwa kutumia huduma ya EmbeddingsClientSpec. Kwa kila kipengele, huunganisha kitambulisho cha kipengele, lebo, na maelezo (maoni) ili kuunda uwakilishi wa maandishi. Maandishi haya yabadilishwa kisha kuwa ufumbuzi wa vekta wa mchemuko mkuu ambao unaonyesha maana yake ya kiufundi. Ufumbuzi huu huhifadhiwa katika duka la vekta la FAISS la kila mtiririko pamoja na metadata kuhusu aina ya kipengele, ontolojia ya chanzo, na ufafanuzi kamili. Mpakuzi hugundua kiotomatiki mchemuko wa ufumbuzi kutoka kwa majibu ya kwanza ya ufumbuzi. + +**Miamala Muhimu**: +Unda uwakilishi wa maandishi kutoka kwa kitambulisho cha kipengele, lebo, na maoni +Zunda ufumbuzi kupitia EmbeddingsClientSpec (ukitumia asyncio.gather kwa usindikaji wa kikundi) +Hifadhi ufumbuzi na metadata kamili katika duka la vekta la FAISS +Indexi kwa ontolojia, aina ya kipengele, na kitambulisho cha kipengele kwa upatikanaji wa ufanisi +Gundua kiotomatiki mchemuko wa ufumbuzi kwa upangaji wa duka la vekta +Shirikisha modeli za ufumbuzi za kila mtiririko na maduka ya vekta yanayojitegemea + +**Mahali pa Utekelezaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. Mchakato wa Nakala (Kigawanyishi Sentensi) + +**Madhumuni**: Huondoa vipande vya nakala katika sehemu ndogo kwa utangamano wa ontolojia. + +**Utekelezaji**: +Mchakato wa Nakala hutumia NLTK kwa utambaji wa sentensi na utambulisho wa POS ili kugawanya vipande vya nakala vinavyoingia katika sentensi. Inashughulikia utangamano wa toleo la NLTK kwa kujaribu kupakua `punkt_tab` na `averaged_perceptron_tagger_eng`, na kutoa nafasi kwa matoleo ya zamani ikiwa ni lazima. Kila kipande cha nakala kigawanywa katika sentensi binafsi ambazo zinaweza kulinganishwa kwa kujitegemea na vipengele vya ontolojia. + +**Miamala Muhimu**: +Gawa nakala katika sentensi kwa kutumia utambaji wa sentensi wa NLTK +Shirikisha utangamano wa toleo la NLTK (punkt_tab vs punkt) +Unda vitu vya TextSegment na nakala na maelezo ya nafasi +Saidia sentensi kamili na vipande vya mtu binafsi + +**Mahali pa Utekelezaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. Mchagua wa Ontolojia + +**Madhumuni**: Hutambua sehemu muhimu zaidi ya vipengele vya ontolojia kwa kipande cha sasa cha nakala. + +**Utekelezaji**: +Mchagua wa Ontolojia hufanya utangamano wa kiufundi kati ya sehemu za nakala na vipengele vya ontolojia kwa kutumia utafutaji wa ufanisi wa vekta wa FAISS. Kwa kila sentensi kutoka kwa kipande cha nakala, huunda ufumbuzi na hufuatilia duka la vekta kwa vipengele vya ontolojia vinavyolingana kwa ufanisi kwa kutumia ufanisi wa cosine na kizingiti kinachoweza kusanidiwa (kiasi 0.3). Baada ya kukusanya vipengele vyote muhimu, hufanya utatuzi kamili wa utegemezi: ikiwa darasa lilitajwa, madarasa yake ya wazazi hujumuishwa; ikiwa sifa ilitajwa, madarasa yake ya uwanja na safu huongezwa. Zaidi ya hayo, kwa kila darasa lililochaguliwa, hujumuisha kiotomatiki **sifa zote ambazo zinarejelea darasa hilo** katika uwanja au safu yake. Hii inahakikisha kuwa uondoaji una upatikanaji wa sifa zote muhimu za uhusiano. + +**Operesheni Muhimu**: +Tengeneza embeddings kwa kila sehemu ya maandishi (sentensi) +Fanya utafutaji wa jirani wa karibu (k-nearest neighbor) katika hifadhi ya vector ya FAISS (top_k=10, threshold=0.3) +Tumia kikomo cha ufanano ili kuchuja mechi dhaifu +Tatua utegemezi (madarasa ya wazazi, nyanja, mipaka) +**Jumuisha moja kwa moja sifa zote zinazohusiana na madarasa yaliyochaguliwa** (mechi ya nyanja/mipaka) +Jenga sehemu ndogo ya ontology inayofaa na uhusiano wote unaohitajika +Ondoa vipengele ambavyo huonekana mara nyingi + +**Mahali pa Utendaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. Uundaji wa Maagizo + +**Madhumuni**: Huunda maagizo yaliyo na muundo ambayo huongoza LLM ili kuchimbua tu triples zinazolingana na ontology. + +**Utendaji**: +Huduma ya uchimbaji hutumia kiolezo cha Jinja2 kilicho pakuliwa kutoka `ontology-prompt.md` ambayo inaandika sehemu ndogo ya ontology na maandishi kwa uchimbaji wa LLM. Kiolezo hicho huendelea mara kwa mara juu ya madarasa, sifa za vitu, na sifa za aina ya data kwa kutumia sintaksia ya Jinja2, na kuwasilisha kila moja pamoja na maelezo yake, nyanja, mipaka, na uhusiano wa kishati. Maagizo hayo yana sheria kali kuhusu kutumia vipengele vya ontology vilivyotolewa pekee na huomba muundo wa pato la JSON kwa upangaji thabiti. + +**Operesheni Muhimu**: +Tumia kiolezo cha Jinja2 na marudio juu ya vipengele vya ontology +Andika madarasa na uhusiano wa wazazi (subclass_of) na maoni +Andika sifa na vikwazo vya nyanja/mipaka na maoni +Jumuisha sheria wazi za uchimbaji na mahitaji ya muundo wa pato +Piga simu huduma ya maagizo na kitambulisho cha kiolezo "extract-with-ontologies" + +**Mahali pa Kiolezo**: `ontology-prompt.md` +**Mahali pa Utendaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (mbinu ya build_extraction_variables) + +#### 6. Huduma Kuu ya Uchimbaji + +**Madhumuni**: Inadhihirisha vipengele vyote ili kufanya uchimbaji kamili wa triples kulingana na ontology. + +**Utendaji**: +Huduma Kuu ya Uchimbaji (KgExtractOntology) ni safu ya upangaji ambayo inasimamia mtiririko kamili wa uchimbaji. Inatumia mtindo wa TrustGraph's FlowProcessor na usanidi wa kila mtiririko. Wakati sasisho la usanidi wa ontology linapofika, inaanzisha au inasasisha vipengele vya mtiririko (mji wa ontology, mchimbaji, mchakato wa maandishi, mchagua). Wakati kipande cha maandishi kinapofika kwa uchunguzi, inadhihirisha mstari wa kazi: kugawanya maandishi katika sehemu, kutafuta vipengele muhimu vya ontology kupitia utafutaji wa vector, kuunda maagizo ya kikomo, kupiga simu huduma ya maagizo, kuchanganua na kuthibitisha jibu, kuunda triples za ufafanuzi wa ontology, na kutoa triples za yaliyomo na mandhari ya vitu. + +**Mstari wa Kazi wa Uchimbaji**: +1. Pokea kipande cha maandishi kupitia folyo ya chunks-input +2. Anzisha vipengele vya mtiririko ikiwa ni lazima (kwa kipande cha kwanza au sasisho la usanidi) +3. Gawa maandishi katika sentensi kwa kutumia NLTK +4. Tafuta hifadhi ya vector ya FAISS ili kupata dhana muhimu za ontology +5. Jenga sehemu ndogo ya ontology na ujumuishaji wa moja kwa moja wa sifa +6. Jenga mbadala wa Jinja2-templated +7. Piga simu huduma ya maagizo na kiolezo cha extract-with-ontologies +8. Changanisha jibu la JSON katika triples zilizopangwa +9. Thibitisha triples na upanue URI hadi URI kamili ya ontology +10. Jenga triples za ufafanuzi wa ontology (madarasa na sifa na lebo/maoni/nyanja/mipaka) +11. Jenga mandhari ya vitu kutoka kwa triples zote +12. Toa kwa folyo za triples na entity-contexts + +**Vipengele Muhimu**: +Hifadhi za vector za kila mtiririko inayounga mkono modeli tofauti za uchimbaji +Sasisho ya ontology iliyoendeshwa na tukio kupitia folyo ya config-update +Upanuzi wa moja kwa moja wa URI kwa kutumia URI za ontology +Vipengele vya ontology vilivyoongezwa kwenye grafu ya maarifa na metadata kamili +Mandhari ya vitu inajumuisha vipengele vya yaliyomo na ontology + +**Mahali pa Utendaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### Usanidi + +Huduma hutumia mbinu ya kawaida ya usanidi ya TrustGraph na hoja za mstari wa amri: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**Vigezo Muhimu vya Usanidi**: +`similarity_threshold`: 0.3 (kiwango chachilia, kinaweza kusanidiwa katika programu) +`top_k`: 10 (idadi ya vipengele vya ontolojia ambavyo vitapatikana kwa kila sehemu) +`vector_store`: FAIISS IndexFlatIP kwa kila mtiririko na vipimo ambavyo vitapatikana kiotomatiki +`text_processor`: NLTK na utambuzi wa sentensi ya punkt_tab +`prompt_template`: "extract-with-ontologies" (template ya Jinja2) + +**Usanidi wa Ontolojia**: +Ontolojia huzamilishwa moja kwa moja kupitia folyo ya config-update yenye aina="ontology". + +### Mtiririko wa Data + +1. **Awamu ya Uanzishaji** (kwa kila mtiririko): + Pokea usanidi wa ontolojia kupitia folyo ya config-update + Changanua JSON ya ontolojia katika vitu vya OntologyClass na OntologyProperty + Zizalisha embeddings kwa vipengele vyote vya ontolojia kwa kutumia EmbeddingsClientSpec + Hifadhi embeddings katika duka la vector la FAISS kwa kila mtiririko + Gundua vipimo vya embedding kutoka kwa majibu ya kwanza + +2. **Awamu ya Utoaji** (kwa kila sehemu): + Pokea sehemu kutoka kwa folyo ya chunks-input + Gawanya sehemu katika sentensi kwa kutumia NLTK + Hesabu embeddings kwa kila sentensi + Tafuta duka la vector la FAISS kwa vipengele muhimu vya ontolojia + Unda subset ya ontolojia na ujumuishaji wa kiotomatiki wa sifa + Unda vigezo vya template ya Jinja2 na maandishi na ontolojia + Piga huduma ya prompt na template ya extract-with-ontologies + Changanisha majibu ya JSON na uthibitishe triples + Panua URIs kwa kutumia URIs za ontolojia + Zizalisha triples za ufafanuzi wa ontolojia + Unda muktadha wa vitu kutoka kwa triples zote + Tuma kwa folyo za triples na entity-contexts + +### Duka la Vector la Kumbukumbu + +**Madhumuni**: Hutoa utafutaji wa haraka wa ufanano, unaotegemea kumbukumbu kwa utangamano wa vipengele vya ontolojia. + +**Utekelezaji: FAISS** + +Mfumo hutumia **FAISS (Facebook AI Similarity Search)** na IndexFlatIP kwa utafutaji wa usawa wa cosine. Vipengele muhimu: + +**IndexFlatIP**: Utafutaji wa usawa wa cosine kwa kutumia bidhaa ya ndani +**Uugunduzi wa kiotomatiki**: Vipimo vinatambuliwa kutoka kwa majibu ya kwanza ya embedding +**Maduka ya kila mtiririko**: Kila mtiririko una duka la vector linalojitegemea kwa modeli tofauti za embedding +**Urekebishaji**: Vector zote zimefanywa kuwa sawa kabla ya kuingizwa +**Operesheni za kundi**: Kuongeza kikundi kwa upakiaji wa awali wa ontolojia + +**Mahali pa Utekelezaji**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### Algoritimu ya Uchaguzi wa Subset ya Ontolojia + +**Madhumuni**: Inachagua kwa moja kwa moja sehemu muhimu zaidi ya ontolojia kwa kila sehemu ya maandishi. + +**Hatua za Algoritimu**: + +1. **Umgawaji wa Maandishi**: + Gawa sehemu ya pembeni katika sentensi kwa kutumia utambuzi wa sentensi ya NLP + Toa maneno muhimu, maneno muhimu, na vitu vilivyotajwa kutoka kwa kila sentensi + Unda muundo wa kishati wa sehemu ukiendeleza muktadha + +2. **Uzalishaji wa Embedding**: + Zizalisha embeddings ya vector kwa kila sehemu ya maandishi (sentensi na maneno) + Tumia modeli sawa ya embedding kama ilivyotumika kwa vipengele vya ontolojia + Hifadhi embeddings kwa sehemu zinazorudiwa ili kuboresha utendaji + +3. **Utafiti wa Ufanano**: + Kwa kila embedding ya sehemu ya maandishi, tafuta duka la vector + Rudisha vipengele 10 bora (e.g., 10) vinavyofanana na ontolojia + Tumia kizuia cha ufanano (e.g., 0.7) kuchuja mechi dhaifu + Jumuisha matokeo kote katika sehemu zote, ukihesabu masafa ya mechi + +4. **Suluhisho la Utendaji**: + Kwa kila darasa lililochaguliwa, jumuisha madarasa yote ya wazazi hadi mizizi + Kwa kila sifa iliyochaguliwa, jumuisha madarasa yake ya uwanja na upeo + Kwa sifa za kinyume, hakikisha kuwa mwelekeo wote wamejumuishwa + Ongeza madarasa sawa ikiwa zipo katika ontolojia + +5. **Uundaji wa Subset**: + Ondoa vipengele vilivyo na marudio huku ukiendeleza uhusiano + Panga katika madarasa, sifa za kitu, na sifa za aina ya data + Hakikisha kuwa vikwazo vyote na uhusiano vimehifadhiwa + Unda mini-ontolojia inayojitegemea ambayo ni halali na kamili + +**Mfano wa Uelekezaji**: +Ikiwa kuna maandishi: "Mbwa mweusi alimfuatilia paka mweupe kwenye mti." +Sehemu: ["mbwa mweusi", "paka mweupe", "mti", "alifuatilia"] +Vipengele vilivyolingana: [mbwa (darasa), paka (darasa), wanyama (mzazi), hufuatia (sifa)] +Utendaji: [wanyama (mzazi wa mbwa na paka), viumbehai (mzazi wa wanyama)] +Subset ya mwisho: Mini-ontolojia kamili na hierarkia ya wanyama na uhusiano wa kufuatilia + +### Uthibitisho wa Triples + +**Madhumuni**: Inahakikisha kwamba triples zote zilizotolewa zinaendana kikamilifu na vikwazo vya ontolojia. + +**Algoritimu ya Uthibitisho**: + +1. **Uthibiti wa Darasa**: + Hakikisha kwamba vitu ni mifano ya madarasa yaliyoundwa katika sehemu ya ontolojia. + Kwa sifa za vitu, hakikisha kwamba vitu pia ni mifano halali ya madarasa. + Angalia majina ya madarasa dhidi ya kamusi ya madarasa ya ontolojia. + Shirudia safu za madarasa - mifano ya madarasa ya chini yanafaa kwa sheria za darasa kuu. + +2. **Uthibiti wa Sifa**: + Thibitisha kwamba manukuu yanalingana na sifa katika sehemu ya ontolojia. + Tofautisha kati ya sifa za vitu (kitu hadi kitu) na sifa za aina ya data (kitu hadi literal). + Hakikisha kwamba majina ya sifa yanalingana kabisa (kikumbukie nafasi ikiwa ipo). + +3. **Uchunguzi wa Doman/Safu**: + Kwa kila sifa inayotumika kama manukuu, pata domania na safu yake. + Hakikisha kwamba aina ya kitu inalingana au inameridia aina ya domania ya sifa. + Hakikisha kwamba aina ya kitu inalingana au inameridia aina ya safu ya sifa. + Kwa sifa za aina ya data, hakikisha kwamba kitu ni literal ya aina ya XSD inayofaa. + +4. **Uthibiti wa Idadi**: + Fuatilia idadi ya matumizi ya sifa kwa kila kitu. + Angalia idadi ya chini - hakikisha kwamba sifa zinazohitajika zipo. + Angalia idadi ya juu - hakikisha kwamba sifa haitumiki mara nyingi sana. + Kwa sifa za kazi, hakikisha kwamba kuna thamani moja tu kwa kila kitu. + +5. **Uthibiti wa Aina ya Data**: + Tafsiri maadili ya literal kulingana na aina zao zilizotangazwa za XSD. + Thibitisha kwamba nambari za integer ni nambari halali, tarehe zinaumbwa vizuri, n.k. + Angalia muundo wa maandishi ikiwa sheria za regex zimefafuliwa. + Hakikisha kwamba URI zimeumbwa vizuri kwa aina za xsd:anyURI. + +**Mfano wa Uthibiti**: +Kifurushi: ("Buddy", "ana-miliki", "John") +Angalia kwamba "Buddy" imewekwa kama darasa ambalo linaweza kuwa na sifa ya "ana-miliki". +Angalia kwamba "ana-miliki" ipo katika ontolojia. +Thibitisha sheria ya domania: kitu lazima kiwe cha aina ya "Mbwa" au darasa la chini. +Thibitisha sheria ya safu: kitu lazima kiwe cha aina ya "Mtu" au darasa la chini. +Ikiwa halali, iongeze kwenye pato; ikiwa halali, rekodi ukiukaji na epuka. + +## Mlinganisho wa Utendaji + +### Mikakati ya Ubora + +1. **Uficha wa Kuweka**: Hifadhi maadili yaliyowekwa kwa sehemu za maandishi ambazo hutumiwa mara kwa mara. +2. **Uchakataji wa Kundi**: Chakata sehemu nyingi kwa wakati mmoja. +3. **Ufichuaji wa Faharasa**: Tumia algorimu za jirani za karibu za takriban kwa ontolojia kubwa. +4. **Uboreshaji wa Ombi**: Punguza saizi ya ombi kwa kujumuisha tu vipengele muhimu vya ontolojia. +5. **Uficha wa Matokeo**: Hifadhi matokeo ya uondoaji kwa vipande sawa. + +### Urahisi + +**Upanuzi wa Afakasi**: Mifumo mingi ya utoaji inayoshiriki kumbukumbu ya ontolojia. +**Umgawanyaji wa Ontolojia**: Gawanya ontolojia kubwa kwa kulingana na eneo. +**Uchakataji wa Msururu**: Chakata vipande kadri vinavyofika bila kuunganisha. +**Usimamizi wa Kumbukumbu**: Usafishaji wa mara kwa mara wa vipimo visivyotumika. + +## Usimamizi wa Madosa + +### Hali za Kushindwa + +1. **Ontolojia Zinazokosekana**: Tumia utoaji usio na kikomo. +2. **Ushindwa wa Huduma ya Vipimo**: Tumia vipimo vilivyohifadhiwa au epuka utoaji wa maana. +3. **Kutofa kwa Huduma ya Maagizo**: Jaribu tena kwa kuongeza muda polepole. +4. **Muundo Usio sahihi wa Triples**: Rekodi na epuka triples zilizoharibika. +5. **Utangamano wa Ontolojia**: Ripoti migogoro na tumia vipengele sahihi zaidi. + +### Ufuatiliaji + +Vipimo muhimu vya kufuatilia: + +Muda wa kupakia ontolojia na matumizi ya kumbukumbu. +Muda wa kuunda vipimo. +Utendaji wa utafutaji wa vector. +Muda wa majibu ya huduma ya maagizo. +Usahihi wa utoaji wa triples. +Kiwango cha utangamano wa ontolojia. + +## Njia ya Uhamishaji + +### Kutoka kwa Vifaa vya Utoaji Vilivyopo + +1. **Uendeshaji Sambamba**: Endesha pamoja na vifaa vya utoaji vilivyopo awali. +2. **Upanuzi Polepole**: Anzisha na aina mahususi za hati. +3. **Ulinganisho wa Ubora**: Linganisha ubora wa matokeo na vifaa vya utoaji vilivyopo. +4. **Uhamisho Kamili**: Badilisha vifaa vya utoaji vilivyopo baada ya ubora kuthibitishwa. + +### Maendeleo ya Ontolojia + +1. **Anzisha kutoka kwa Vipengele Vilivyopo**: Unda ontolojia za awali kutoka kwa maarifa iliyopo. +2. **Uboreshaji wa Mara kwa Mara**: Boresha kulingana na mifumo ya utoaji. +3. **Uhakiki wa Mtaalamu wa Lugha**: Thibitisha na wataalamu wa somo. +4. **Uboreshaji Unaoendelea**: Sasisha kulingana na maoni ya utoaji. + +## Huduma ya Uulizaje inayohusiana na Ontolojia + +### Maelezo + +Huduma ya uulizaje inayohusiana na ontolojia hutoa njia nyingi za uulizaje ili kusaidia hifadhi tofauti za grafu. Inatumia maarifa ya ontolojia kwa majibu sahihi na ya maana ya maswali katika hifadhi za Cassandra (kupitia SPARQL) na hifadhi za grafu zinazotumia Cypher (Neo4j, Memgraph, FalkorDB). + +**Vipengele vya Huduma**: +`onto-query-sparql`: Hubadilisha lugha ya asili kuwa SPARQL kwa Cassandra. +`sparql-cassandra`: Safu ya uulizaje ya SPARQL kwa Cassandra inayotumia rdflib. +`onto-query-cypher`: Hubadilisha lugha ya asili kuwa Cypher kwa hifadhi za grafu. +`cypher-executor`: Utendeshaji wa uulizaje wa Cypher kwa Neo4j/Memgraph/FalkorDB. + +### Usanifu + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### Mchakato wa Uchunguzi wa Maswali + +#### 1. Mchambuzi wa Maswali + +**Madhumuni**: Huainisha maswali ya mtumiaji katika vipengele vya maana kwa ajili ya utangamano wa ontolojia. + +**Maelezo ya Algoritimu**: +Mchambuzi wa Maswali huchukua swali la lugha ya asili ambalo limeingia na hulifanya iwe sehemu za maana kwa kutumia mbinu sawa ya ugawaji wa sentensi kama ilivyo kwenye mchakato wa uondoaji. Hutambua vitu, uhusiano, na vikwazo muhimu ambavyo yameelezwa katika swali. Kila sehemu inachambuliwa kwa aina ya swali (ukweli, jumlisho, kulinganisha, n.k.) na muundo unaotarajiwa wa jibu. Uainishaji huu husaidia kutambua sehemu zipi za ontolojia ambazo ni muhimu zaidi kwa kujibu swali. + +**Utendaji Muhimu**: +Gawa swali katika sentensi na maneno +Tambua aina na nia ya swali +Toa vitu na uhusiano uliotajwa +Gundua vikwazo na vichujio katika swali +Tambua muundo unaotarajiwa wa jibu + +#### 2. Kichunguzi cha Ontolojia kwa Maswali + +**Madhumuni**: Hutambua sehemu muhimu ya ontolojia inayohitajika kujibu swali. + +**Maelezo ya Algoritimu**: +Kichunguzi hiki ni kama Kichunguzi cha Ontolojia katika mchakato wa uondoaji, lakini kimeboreshwa kwa ajili ya kujibu maswali. Kichunguzi hicho hutengeneza maandishi (embeddings) kwa sehemu za swali na kutafuta katika hifadhi ya maandishi vipengele muhimu vya ontolojia. Hata hivyo, linazingatia kutafuta dhana ambazo zitakuwa muhimu kwa uundaji wa swali badala ya uondoaji. Huongeza uteuzi ili kujumuisha sifa zinazohusiana ambazo zinaweza kuvinjwa wakati wa uchunguzi wa grafu, hata kama hazijaelezwa wazi katika swali. Kwa mfano, ikiwa swali ni kuhusu "wafanyakazi," linaweza kujumuisha sifa kama vile "hufanya kazi kwa," "husaidia," na "huripoti kwa" ambazo zinaweza kuwa muhimu kwa kupata habari kuhusu wafanyakazi. + +**Mbinu ya Ulinganisho**: +Tengeneza maandishi ya sehemu za swali +Tafuta dhana za ontolojia zilizotajwa moja kwa moja +Jumuisha sifa zinazounganisha madarasa yaliyotajwa +Ongeza sifa za kinyume na zinazohusiana kwa ajili ya uvinjaji +Jumuisha madarasa ya wazazi/watoto kwa maswali ya kishirikina +Unda sehemu ya ontolojia iliyo na umakini wa swali + +#### 3. Kijaribu cha Nyuma (Backend Router) + +**Madhumuni**: Hupeleka maswali kwenye njia inayofaa ya utekelezaji wa swali kulingana na usanidi. + +**Maelezo ya Algoritimu**: +Kijaribu cha Nyuma huchunguza usanidi wa mfumo ili kubaini ambayo ya mifumo ya nyuma (backends) inafanya kazi (Cassandra au Cypher-based). Hupeleka swali na sehemu ya ontolojia kwenye huduma inayofaa ya uundaji wa swali. Kijaribu hicho pia kinaweza kusaidia usambazaji wa maswali kwenye mifumo ya nyuma mingi au mitaratibu ya dharura ikiwa mfumo wa nyuma mkuu haupatikani. + +**Mantiki ya Upelekeshaji**: +Angalia aina ya mfumo wa nyuma iliyosanidiwa kutoka kwa mipangilio ya mfumo +Peleka kwenye `onto-query-sparql` kwa mifumo ya nyuma ya Cassandra +Peleka kwenye `onto-query-cypher` kwa Neo4j/Memgraph/FalkorDB +Saidia usanidi wa mifumo ya nyuma mingi na usambazaji wa maswali +Shirikisha matukio ya dharura na usambazaji wa maswali + +#### 4. Uundaji wa Swali la SPARQL (`onto-query-sparql`) + +**Madhumuni**: Hubadilisha maswali ya lugha ya asili kuwa maswali ya SPARQL kwa utekelezaji katika Cassandra. + +**Maelezo ya Algoritimu**: +Mgenuzi wa swali la SPARQL huchukua swali na sehemu ya ontolojia na huunda swali la SPARQL lililoboreshwa kwa utekelezaji katika mfumo wa nyuma wa Cassandra. Hutumia huduma ya maagizo (prompt) na kiolezo maalum cha SPARQL ambacho kinajumuisha maana ya RDF/OWL. Mgenuzi hufahamu muundo wa SPARQL kama vile njia za sifa, vifungu vya hiari, na vichujio ambavyo vinaweza kubadilishwa kwa ufanisi katika operesheni za Cassandra. + +**Kiolezo cha Maagizo ya Uundaji wa SPARQL**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. Uzalishaji wa Uliza wa Cypher (`onto-query-cypher`) + +**Madhumuni**: Hubadilisha maswali ya lugha ya asili kuwa uliza za Cypher kwa hifadhidata za grafu. + +**Maelezo ya Algoritimu**: +Mzalishaji wa uliza wa Cypher huunda uliza za Cypher ambazo zimeboreshwa kwa Neo4j, Memgraph, na FalkorDB. Huunganisha madarasa ya ontolojia na lebo za node na sifa na uhusiano, kwa kutumia sintaksia ya utambuzi wa Cypher. Mzalishaji unajumuisha maboresho maalum ya Cypher kama vile vidokezo vya mwelekeo wa uhusiano, matumizi ya fahirisi, na vidokezo vya upangaji wa uliza. + +**Sampuli ya Kiolezo ya Kuomba Uliza wa Cypher**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. Injini ya Ufuatiliaji wa SPARQL-Cassandra (`sparql-cassandra`) + +**Madhumuni**: Inafanya kazi ya utekelezaji wa maswali ya SPARQL dhidi ya Cassandra kwa kutumia Python rdflib. + +**Maelezo ya Algoritimu**: +Injini ya SPARQL-Cassandra inatekeleza kichakataji cha SPARQL kwa kutumia maktaba ya Python's rdflib pamoja na hifadhi maalum ya Cassandra. Inatengeneza mifumo ya grafu ya SPARQL kuwa maswali ya CQL ya Cassandra, huku ikiwezesha uunganisho, vichujio, na jumlishaji. Injini hii inahifadhi uhusiano kati ya RDF na Cassandra ambao unahifadhi muundo wa maana huku ukiwezesha utendakazi bora kwa mfumo wa uhifadhi wa safu za Cassandra. + +**Vipengele vya Utendakazi**: +Utendakazi wa interface ya rdflib kwa Cassandra +Usaidizi wa maswali ya SPARQL 1.1 pamoja na mifumo ya kawaida +Tafsiri bora ya mifumo ya tatu kuwa CQL +Usaidizi wa njia za mali na maswali ya kimtindo +Uhamisho wa matokeo kwa data kubwa +Uunganishaji wa kikao na kuhifadhi maswali + +**Mfano wa Tafsiri**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +Huuandika maswali bora ya Cassandra kwa kutumia fahirisi na funguo za partition. + +#### 7. Mfumo wa Utendaji wa Maswali ya Cypher (`cypher-executor`) + +**Madhumuni**: Hufanya maswali ya Cypher dhidi ya Neo4j, Memgraph, na FalkorDB. + +**Maelezo ya Algoritimu**: +Mfumo wa utendaji wa Cypher hutoa kiolesura cha pamoja kwa kutekeleza maswali ya Cypher katika hifadhi tofauti za data za grafu. Inashughulikia itifaki maalum za muunganisho wa hifadhidata, vidokezo vya uboreshaji wa maswali, na utaratibu wa kawaida wa umbizo wa matokeo. Mfumo huu unajumuisha utaratibu wa kujaribu tena, udhibiti wa muunganisho, na usimamizi wa miamala unaofaa kwa kila aina ya hifadhidata. + +**Usaidizi wa Hifadhidata Mbalimbali**: +**Neo4j**: Itifaki ya Bolt, kazi za miamala, vidokezo vya fahirisi +**Memgraph**: Itifaki maalum, matokeo ya utiririshaji, maswali ya uchambuzi +**FalkorDB**: Marekebisho ya itifaki ya Redis, uboreshaji wa kumbukumbu + +**Vipengele vya Utendaji**: +Usimamizi wa muunganisho usio tegemea hifadhidata +Uthibitisho wa maswali na ukaguzi wa sintaksia +Utumiaji wa muda na vikwazo vya rasilimali +Urekebishaji na utiririshaji wa matokeo +Ufuatiliaji wa utendaji kwa kila aina ya hifadhidata +Uhamisho wa kiotomatiki kati ya mifano ya hifadhidata + +#### 8. Mjenzi wa Majibu + +**Madhumuni**: Huunda jibu la lugha ya asili kutoka kwa matokeo ya maswali. + +**Maelezo ya Algoritimu**: +Mjenzi wa Majibu huchukua matokeo ya maswali yaliyopangwa na swali la awali, kisha hutumia huduma ya matangazo ili kuunda jibu kamili. Tofauti na majibu rahisi yanayotegemea vipengele, hutumia LLM (Large Language Model) ili kuchambua data ya grafu katika muktadha wa swali, na kushughulikia uhusiano tata, jumlisho, na utabiri. Mjenzi anaweza kueleza hoja zake kwa kurejelea muundo wa ontolojia na triples maalum zilizopatikana kutoka kwa grafu. + +**Mchakato wa Uundaji wa Majibu**: +Huunda matokeo ya maswali katika muktadha uliopangwa +Jumuisha maelezo muhimu ya ontolojia kwa uwazi +Unda matangazo na swali na matokeo +Huunda jibu la lugha ya asili kupitia LLM +Thibitisha jibu dhidi ya nia ya swali +Ongeza marejeleo kwa vitu maalum vya grafu ikiwa inahitajika + +### Uunganisho na Huduma Zilizopo + +#### Uhusiano na GraphRAG + +**Inakamilisha**: onto-query hutoa usahihi wa semantic huku GraphRAG hutoa matoleo mapana +**Infrastraki Iliyoshiriki**: Zote mbili hutumia grafu ya maarifa na huduma sawa za matangazo +**Uelekezaji wa Maswali**: Mfumo unaweza kuelekeza maswali kwa huduma inayofaa zaidi kulingana na aina ya swali +**Njia ya Mchanganyiko**: Inaweza kuchanganya mbinu zote mbili kwa majibu kamili + +#### Uhusiano na Utoaji wa OntoRAG + +**Ontolojia Zilizoshiriki**: Hutumia mipangilio sawa ya ontolojia iliyopakuliwa na kg-extract-ontology +**Hifadhi ya Vector Iliyoshiriki**: Inatumia embeddings za kumbukumbu kutoka kwa huduma ya uundaji +**Semantics Sawa**: Maswali hufanya kazi kwenye grafu zilizojengwa na vikwazo sawa vya ontolojia + +### Mifano ya Maswali + +#### Mfano 1: Swali la Kieleleku +**Swali**: "Wanyama gani ni wanyamapori?" +**Ulinganisho wa Ontolojia**: [wanyama, wanyamapori, subClassOf] +**Swali Lililoundwa**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### Mfano wa 2: Ulinganisho wa Maswali +**Swali**: "Ni nyaraka zipi ambazo ziliandikwa na John Smith?" +**Ulinganisho wa Dhana**: [hati, mtu, aliyeandika] +**Swali Lililoundwa**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### Mfano wa 3: Uchunguzi wa Uunganishaji +**Swali**: "Paka wana miguu mingapi?" +**Ulinganisho wa Dhana**: [paka, idadi-ya-miguu (sifa ya aina ya data)] +**Uchunguzi Ulioundwa**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### Usanidi + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### Uboreshaji wa Utendaji + +#### Uboreshaji wa Maswali + +**Uondoo wa Ontolojia**: Jumuisha tu vipengele muhimu vya ontolojia katika maagizo. +**Kuhifadhi Maswali Yanayoulizwa Mara kwa Mara**: Hifadhi maswali yanayoulizwa mara kwa mara na maswali yao. +**Kuhifadhi Matokeo**: Hifadhi matokeo kwa maswali sawa ndani ya muda maalum. +**Uchakataji wa Kundi**: Shughulikia maswali mengi yanayohusiana katika utafutaji mmoja wa chati. + +#### Masuala ya Ukuaji + +**Utendakazi Uliohusishwa**: Panga maswali madogo katika sehemu tofauti za chati. +**Matokeo ya Kuongezeka**: Tuma matokeo kwa data kubwa. +**Usawa wa Mizigo**: Sogeza mzigo wa maswali katika huduma tofauti. +**Makundi ya Rasilimali**: Dhibiti makundi ya muunganisho kwa hifadhia za chati. + +### Usimamizi wa Madhira + +#### Hali za Kushindwa + +1. **Uundaji Usiofaa wa Swali**: Rudi kwenye GraphRAG au utafutaji rahisi wa neno. +2. **Utangamano Usiofaa wa Ontolojia**: Panua utafutaji hadi sehemu pana ya ontolojia. +3. **Kukata Tamaa kwa Swali**: Rahisisha swali au ongeza muda wa kutuma. +4. **Matokeo Nyembamba**: Pendekeza marekebisho ya swali au maswali yanayohusiana. +5. **Kushindwa kwa Huduma ya LLM**: Tumia maswali yaliyohifadhiwa au majibu ya msingi ya kigeuzi. + +### Viashiria vya Ufuatiliaji + +Usambazaji wa ugumu wa swali. +Ukubwa wa sehemu za ontolojia. +Kiwango cha mafanikio ya uundaji wa swali. +Muda wa utekelezaji wa swali la chati. +Alama za ubora wa jibu. +Viwango vya kufanikiwa kwa uhifadhi. +Masafa ya madhira kwa aina. + +## Uboresho wa Baadaye + +1. **Ujifunzaji wa Ontolojia**: Panua ontolojia moja kwa moja kulingana na mifumo ya uundaji. +2. **Upeo wa Umoja**: Toa alama za umoja kwa vipengele vilivyoundwa. +3. **Uundaji wa Maelezo**: Toa sababu kwa uundaji wa vipengele. +4. **Ujifunzaji Kamili**: Omba uthibitisho wa binadamu kwa uundaji usio wa uhakika. + +## Masuala ya Usalama + +1. **Kuzuia Uingizwaji wa Maagizo**: Safisha maandishi ya sehemu kabla ya uundaji wa agizo. +2. **Mipaka ya Rasilimali**: Punguza matumizi ya kumbukumbu kwa hifadhi ya vekta. +3. **Kikomo cha Kasi**: Punguza ombi la uundaji kwa kila mteja. +4. **Uandikaji wa Ufuatiliaji**: Fuatilia ombi na matokeo ya uundaji. + +## Mkakati wa Majaribio + +### Majaribio ya Kitengo + +Mpakuzi wa ontolojia na muundo tofauti. +Uundaji na uhifadhi wa vekta. +Algorithmu za kutenganisha sentensi. +Hesabu za ufanano wa vekta. +Uchakataji na uthibitisho wa vipengele. + +### Majaribio ya Uunganisho + +Msururu kamili wa uundaji. +Uunganisho wa huduma ya usanidi. +Mwingiliano wa huduma ya agizo. +Usimamizi wa uundaji wa wakati mmoja. + +### Majaribio ya Utendaji + +Usimamizi wa ontolojia kubwa (madarasa 1000+). +Uchakataji wa kundi la juu. +Matumizi ya kumbukumbu chini ya mzigo. +Viwango vya kuchelewesha. + +## Mpango wa Utoaji + +### Muhtasari + +Mfumo wa OntoRAG utatolewa katika awamu nne kuu, na kila awamu itatoa thamani ya hatua kwa hatua huku ikijenga mfumo kamili. Mpango huo unalenga kuanzisha uwezo wa msingi wa uundaji kwanza, kisha kuongeza utendakazi wa swali, kisha uboreshaji na vipengele vya hali ya juu. + +### Awamu ya 1: Msingi na Uundaji wa Msingi + +**Lengo**: Kuanzisha mstari wa msingi wa uundaji unaoongozwa na ontolojia na utangamano wa vekta rahisi. + +#### Hatua ya 1.1: Msingi wa Usimamizi wa Ontolojia +Tengeneza mpakuzi wa usanidi wa ontolojia (`OntologyLoader`). +Pata na thibitisha miundo ya JSON ya ontolojia. +Unda hifadhi ya ontolojia ya ndani na mifumo ya ufikiaji. +Tengeneza utaratibu wa kusasisha ontolojia. + +**Vigezo vya Mafanikio**: +Pakia na pata usanidi wa ontolojia. +Thibitisha muundo na utangamano wa ontolojia. +Shiriki ontolojia nyingi. + +#### Hatua ya 1.2: Utumiaji wa Hifadhi ya Vektas +Tengeneza hifadhi ya vekta rahisi inayotumia NumPy kama mfano wa awali. +Ongeza utumiaji wa hifadhi ya vekta ya FAISS. +Unda utaratibu wa kiwango cha hifadhi ya vekta. +Tengeneza utafutaji wa ufanano na viwango vinavyoweza kusanidi. + +**Vigezo vya Mafanikio**: +Kuhifadhi na kurejesha ujazo (embeddings) kwa ufanisi. +Kufanya utafutaji wa ufanano kwa latensi ya chini ya <100ms. +Kusaidia mifumo ya NumPy na FAISS. + +#### Hatua ya 1.3: Mchakato wa Ujazo wa Ontolojia +Kuunganisha na huduma ya ujazo. +Kutekeleza kipengele cha `OntologyEmbedder`. +Kutoa ujazo kwa vipengele vyote vya ontolojia. +Kuhifadhi ujazo pamoja na metadata katika hifadhi ya vekta. + +**Vigezo vya Mafanikio**: +Kutoa ujazo kwa madarasa na sifa. +Kuhifadhi ujazo pamoja na metadata sahihi. +Kujenga upya ujazo wakati wa sasisho za ontolojia. + +#### Hatua ya 1.4: Vipengele vya Uchunguzi wa Nakala +Kutekeleza mgawaji wa sentensi kwa kutumia NLTK/spaCy. +Kuchukua maneno na vitambulisho. +Kuunda hierarkia ya sehemu za nakala. +Kutoa ujazo kwa sehemu za nakala. + +**Vigezo vya Mafanikio**: +Kugawanya nakala katika sentensi kwa usahihi. +Kuchukua maneno yenye maana. +Kuhifadhi uhusiano wa muktadha. + +#### Hatua ya 1.5: Algoritimu ya Uchaguzi wa Ontolojia +Kutekeleza utangamano kati ya nakala na ontolojia. +Kuunda utatuzi wa utegemezi kwa vipengele vya ontolojia. +Kuunda subseti ndogo na muunganisho. +Kuboresha utendaji wa utengenezaji wa subseti. + +**Vigezo vya Mafanikio**: +Kuchagua vipengele muhimu vya ontolojia kwa usahihi wa >80%. +Kuunganisha utegemezi wote muhimu. +Kutoa subseti katika <500ms. + +#### Hatua ya 1.6: Huduma ya Msingi ya Utoaji +Kutekeleza uundaji wa ombi la utoaji. +Kuunganisha na huduma ya ombi. +Kuchanganua na kuthibitisha majibu ya triplet. +Kuunda mwisho wa huduma ya `kg-extract-ontology`. + +**Vigezo vya Mafanikio**: +Kutoa triplets inayolingana na ontolojia. +Kuthibitisha triplets zote dhidi ya ontolojia. +Kushughulikia makosa ya utoaji kwa utulivu. + +### Awamu ya 2: Utendaji wa Mfumo wa Umasilifu + +**Lengo**: Kuongeza uwezo wa masilifu unaoegemea kwenye ontolojia, kwa usaidizi wa mifumo mingi. + +#### Hatua ya 2.1: Vipengele vya Msingi ya Umasilifu +Kutekeleza mchanganuzi wa swali. +Kuunda mlinganishi wa ontolojia kwa masilifu. +Kurekebisha utafutaji wa vekta kwa muktadha wa masilifu. +Kuunda kipengele cha kutoa masilifu. + +**Vigezo vya Mafanikio**: +Kuchambua maswali katika vipengele vya semantic. +Kulinganisha maswali na vipengele muhimu vya ontolojia. +Kutoa masilifu kwa mfumo unaofaa. + +#### Hatua ya 2.2: Utendaji wa Njia ya SPARQL +Kutekeleza huduma ya `onto-query-sparql`. +Kuunda jenereta ya swali la SPARQL kwa kutumia LLM. +Kuunda vipatterno vya ombi kwa utengenezaji wa SPARQL. +Kuthibitisha sintaksia iliyoundwa ya SPARQL. + +**Vigezo vya Mafanikio**: +Kutoa maswali valid ya SPARQL. +Kutumia mitindo ya SPARQL inayofaa. +Kushughulikia aina ngumu za maswali. + +#### Hatua ya 2.3: Injini ya SPARQL-Cassandra +Kutekeleza interface ya Hifadhi ya rdflib kwa Cassandra. +Kuunda mtafsiri wa swali la CQL. +Kuboresha utangamano wa muundo wa triplet. +Kushughulikia umbizo la matokeo ya SPARQL. + +**Vigezo vya Mafanikio**: +Kutekeleza maswali ya SPARQL kwenye Cassandra. +Kusaidia mitindo ya kawaida ya SPARQL. +Kurudisha matokeo katika umbizo la kawaida. + +#### Hatua ya 2.4: Utendaji wa Njia ya Cypher +Kutekeleza huduma ya `onto-query-cypher`. +Kuunda jenereta ya swali la Cypher kwa kutumia LLM. +Kuunda vipatterno vya ombi kwa utengenezaji wa Cypher. +Kuthibitisha sintaksia iliyoundwa ya Cypher. + +**Vigezo vya Mafanikio**: +Kutoa maswali valid ya Cypher. +Kutumia mitindo ya grafu inayofaa. +Kusaidia Neo4j, Memgraph, FalkorDB. + +#### Hatua ya 2.5: Mfumo wa Utendaji wa Cypher +Implement multi-database Cypher executor +Support Bolt protocol (Neo4j/Memgraph) +Support Redis protocol (FalkorDB) +Handle result normalization + +**Success Criteria**: +Execute Cypher on all target databases +Handle database-specific differences +Maintain connection pools efficiently + +#### Step 2.6: Answer Generation +Implement answer generator component +Create prompts for answer synthesis +Format query results for LLM consumption +Generate natural language answers + +**Success Criteria**: +Generate accurate answers from query results +Maintain context from original question +Provide clear, concise responses + +### Phase 3: Optimization and Robustness + +**Goal**: Optimize performance, add caching, improve error handling, and enhance reliability. + +#### Step 3.1: Performance Optimization +Implement embedding caching +Add query result caching +Optimize vector search with FAISS IVF indexes +Implement batch processing for embeddings + +**Success Criteria**: +Reduce average query latency by 50% +Support 10x more concurrent requests +Maintain sub-second response times + +#### Step 3.2: Advanced Error Handling +Implement comprehensive error recovery +Add fallback mechanisms between query paths +Create retry logic with exponential backoff +Improve error logging and diagnostics + +**Success Criteria**: +Gracefully handle all failure scenarios +Automatic failover between backends +Detailed error reporting for debugging + +#### Step 3.3: Monitoring and Observability +Add performance metrics collection +Implement query tracing +Create health check endpoints +Add resource usage monitoring + +**Success Criteria**: +Track all key performance indicators +Identify bottlenecks quickly +Monitor system health in real-time + +#### Step 3.4: Configuration Management +Implement dynamic configuration updates +Add configuration validation +Create configuration templates +Support environment-specific settings + +**Success Criteria**: +Update configuration without restart +Validate all configuration changes +Support multiple deployment environments + +### Phase 4: Advanced Features + +**Goal**: Add sophisticated capabilities for production deployment and enhanced functionality. + +#### Step 4.1: Multi-Ontology Support +Implement ontology selection logic +Support cross-ontology queries +Handle ontology versioning +Create ontology merge capabilities + +**Success Criteria**: +Query across multiple ontologies +Handle ontology conflicts +Support ontology evolution + +#### Step 4.2: Intelligent Query Routing +Implementa njia za msingi kulingana na utendaji +Ongeza uchambuzi wa utata wa swali +Unda algoriti za njia zinazobadilika +Saidia vipimo vya A/B kwa njia + +**Vigezo vya Mafanikio**: +Pata njia za maswali kwa ufanisi +Jifunze kutoka kwa utendaji wa maswali +Boresha njia kwa muda + +#### Hatua ya 4.3: Vipengele vya Uvunaji Vilivyoendelezwa +Ongeza alama za uaminifu kwa vitu +Leta utengenezaji wa maelezo +Unda mzunguko wa maoni kwa uboreshaji +Saidia ujifunzaji wa hatua kwa hatua + +**Vigezo vya Mafanikio**: +Toa alama za uaminifu +Eleza maamuzi ya uvunaji +Boresha kwa ufanisi + +#### Hatua ya 4.4: Uimarishaji wa Uzalishaji +Ongeza kikomo cha kasi +Leta uthibitishaji/idhinishaji +Unda automatisering ya usakinishaji +Ongeza nakala na urejesho + +**Vigezo vya Mafanikio**: +Usalama unaofaa kwa uzalishaji +Mfumo wa usakinishaji uliyo na automatisering +Uwezo wa urejesho wa majanga + +### Hatua za Utoaji + +1. **Hatua ya 1** (Mwisho wa Awamu ya 1): Uvunaji wa msingi unaoendeshwa na ontolojia unafanya kazi +2. **Hatua ya 2** (Mwisho wa Awamu ya 2): Mfumo kamili wa maswali na njia za SPARQL na Cypher +3. **Hatua ya 3** (Mwisho wa Awamu ya 3): Mfumo uliopunguzwa, thabiti, na unaoendelea kufaa kwa majaribio +4. **Hatua ya 4** (Mwisho wa Awamu ya 4): Mfumo unaofaa kwa uzalishaji na vipengele vilivyoendelezwa + +### Kupunguza Hatari + +#### Hatari za Kiufundi +**Uwezo wa Hifadhi ya Vektor**: Anza na NumPy, uhamishie kwa FAISS hatua kwa hatua +**Ukamavu wa Uundaji wa Maswali**: Leta uthibitisho na njia mbadala +**Ulinganishi wa Backend**: Jaribu kwa uangalifu na kila aina ya hifadhidata +**Vizuizi vya Utendaji**: Fafanua mapema na mara kwa mara, boresha kwa hatua kwa hatua + +#### Hatari za Uendeshaji +**Ubora wa Ontolojia**: Leta uthibitisho na ukaguzi wa utangamano +**Utegemezi wa Huduma**: Ongeza vituo vya mzunguko na njia mbadala +**Hadhara za Rasilimali**: Fuatilia na weka mipaka inayofaa +**Utangamano wa Data**: Leta ushughulikiaji sahihi wa miamala + +### Viashiria vya Mafanikio + +#### Viashiria vya Mafanikio ya Awamu ya 1 +Ukamavu wa uvunaji: >90% utangamano wa ontolojia +Njia ya usindikaji: <1 sekunde kwa sehemu +Muda wa kupakia ontolojia: <10 sekunde +Latensi ya utafutaji wa vektor: <100ms + +#### Viashiria vya Mafanikio ya Awamu ya 2 +Njia ya mafanikio ya swali: >95% +Latensi ya swali: <2 sekunde kwa jumla +Ulinganishi wa backend: 100% kwa hifadhidata zilizolengwa +Ukamavu wa jibu: >85% kulingana na data iliyopo + +#### Viashiria vya Mafanikio ya Awamu ya 3 +Muda wa mfumo: >99.9% +Njia ya urejesho wa makosa: >95% +Njia ya hit ya kumbukumbu: >60% +Watumiaji wengi: >100 + +#### Viashiria vya Mafanikio ya Awamu ya 4 +Maswali ya ontolojia nyingi: Yameunganishwa kikamilifu +Uboreshaji wa njia: Kupunguzwa kwa latensi ya 30% +Ukamavu wa alama: >90% +Usakinishaji wa uzalishaji: Masasisho bila kukatizwa + +## Marejeleo + +[Lugha ya Ontolojia ya Wavuti ya OWL 2](https://www.w3.org/TR/owl2-overview/) +[Usanifu wa GraphRAG](https://github.com/microsoft/graphrag) +[Transformers za Sentensi](https://www.sbert.net/) +[Utafiti wa Vektor wa FAISS](https://github.com/facebookresearch/faiss) +[Maktaba ya NLP ya spaCy](https://spacy.io/) +[Dokumenti ya rdflib](https://rdflib.readthedocs.io/) +[Itifaki ya Neo4j Bolt](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.tr.md b/docs/tech-specs/ontorag.tr.md new file mode 100644 index 00000000..3eb16e9a --- /dev/null +++ b/docs/tech-specs/ontorag.tr.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: Ontolojiye Dayalı Bilgi Çıkarma ve Sorgulama Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# OntoRAG: Ontolojiye Dayalı Bilgi Çıkarma ve Sorgulama 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ış + +OntoRAG, yapılandırılmamış metinden bilgi üçlülerinin çıkarılması ve elde edilen bilgi grafiğinin sorgulanması sırasında sıkı semantik tutarlılığı sağlayan, ontoloji odaklı bir bilgi çıkarma ve sorgulama sistemidir. GraphRAG'e benzer, ancak resmi ontoloji kısıtlamalarıyla, OntoRAG, çıkarılan tüm üçlülerin önceden tanımlanmış ontolojik yapılara uygun olmasını sağlar ve semantik olarak bilinçli sorgulama yetenekleri sunar. + +Sistem, hem çıkarma hem de sorgulama işlemlerinde ilgili ontoloji alt kümelerini dinamik olarak seçmek için vektör benzerliği eşleştirmesi kullanır, bu da odaklı ve bağlamsal olarak uygun işleme sağlarken semantik geçerliliği korur. + +**Servis Adı**: `kg-extract-ontology` + +## Hedefler + +**Ontolojiye Uygun Çıkarma**: Çıkarılan tüm üçlülerin yüklenen ontolojilere kesinlikle uygun olmasını sağlamak +**Dinamik Bağlam Seçimi**: Her parça için ilgili ontoloji alt kümelerini seçmek için gömülmeleri kullanmak +**Semantik Tutarlılık**: Sınıf hiyerarşilerini, özellik alanlarını/aralıklarını ve kısıtlamaları korumak +**Verimli İşleme**: Hızlı ontoloji öğesi eşleştirmesi için bellek içi vektör depoları kullanmak +**Ölçeklenebilir Mimari**: Farklı alanlara sahip çoklu eşzamanlı ontolojileri desteklemek + +## Arka Plan + +Mevcut bilgi çıkarma hizmetleri (`kg-extract-definitions`, `kg-extract-relationships`), resmi kısıtlamalar olmadan çalışır ve potansiyel olarak tutarsız veya uyumsuz üçlüler üretebilir. OntoRAG, bunu şunları yaparak ele alır: + +1. Geçerli sınıfları ve özellikleri tanımlayan resmi ontolojileri yüklemek +2. Metin içeriğini ilgili ontoloji öğeleriyle eşleştirmek için gömülmeleri kullanmak +3. Çıkarma işleminin yalnızca ontolojiye uygun üçlüler üretmesini sağlamak +4. Çıkarılan bilginin semantik olarak doğrulanmasını sağlamak + +Bu yaklaşım, sinirsel çıkarmanın esnekliğini, resmi bilgi gösteriminin titizliğiyle birleştirir. + +## Teknik Tasarım + +### Mimari + +OntoRAG sistemi aşağıdaki bileşenlerden oluşur: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### Bileşen Detayları + +#### 1. Ontoloji Yükleyici + +**Amaç**: Ontoloji yapılandırmalarını olay odaklı güncellemeler kullanarak yapılandırma hizmetinden alır ve ayrıştırır. + +**Uygulama**: +Ontoloji Yükleyici, olay odaklı ontoloji yapılandırma güncellemelerini almak için TrustGraph'in ConfigPush kuyruğunu kullanır. "ontoloji" türünde bir yapılandırma öğesi eklendiğinde veya değiştirildiğinde, yükleyici yapılandırma-güncelleme kuyrusu aracılığıyla güncellemeyi alır ve meta veriler, sınıflar, nesne özellikleri ve veri türü özellikleri içeren JSON yapısını ayrıştırır. Bu ayrıştırılmış ontolojiler, çıkarma işlemi sırasında verimli bir şekilde erişilebilen yapılandırılmış nesneler olarak bellekte saklanır. + +**Temel İşlemler**: +Ontoloji türündeki yapılandırmalar için config-update kuyruğuna abone olun +JSON ontoloji yapılarını OntologyClass ve OntologyProperty nesnelerine ayrıştırın +Ontoloji yapısını ve tutarlılığını doğrulayın +Ayrıştırılmış ontolojileri hızlı erişim için bellekte önbelleğe alın +Akışa özgü vektör depolarıyla akışa özel işleme yapın + +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. Ontoloji Gömücüsü + +**Amaç**: Tüm ontoloji öğeleri için vektör gömüleri oluşturarak semantik benzerlik eşleştirmesini etkinleştirir. + +**Uygulama**: +Ontoloji Gömücüsü, yüklenen ontolojilerdeki her öğeyi (sınıflar, nesne özellikleri ve veri türü özellikleri) işler ve EmbeddingsClientSpec hizmetini kullanarak vektör gömüleri oluşturur. Her öğe için, öğenin tanımlayıcısını, etiketlerini ve açıklamasını (yorum) birleştirerek bir metin gösterimi oluşturur. Bu metin daha sonra, semantik anlamını yakalayan yüksek boyutlu bir vektör gömüsüne dönüştürülür. Bu gömüler, öğe türü, kaynak ontoloji ve tam tanım hakkında meta verilerle birlikte, akışa özel bir bellek içi FAISS vektör deposunda saklanır. Gömücü, ilk gömü yanıtından gömü boyutunu otomatik olarak algılar. + +**Temel İşlemler**: +Öğenin kimliklerinden, etiketlerinden ve yorumlarından metin gösterimleri oluşturun +Toplu işleme için asyncio.gather kullanarak EmbeddingsClientSpec aracılığıyla gömüler oluşturun +Gömüleri kapsamlı meta verilerle FAISS vektör deposunda saklayın +Verimli erişim için ontolojiye, öğe türüne ve öğe kimliğine göre indeksleyin +Vektör deposu başlatması için gömü boyutlarını otomatik olarak algılayın +Bağımsız vektör depolarıyla akışa özel gömü modelleriyle çalışın + +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. Metin İşleyici (Cümle Ayırıcı) + +**Amaç**: Ontoloji eşleştirmesi için hassas bir şekilde metin parçalarını ince taneli segmentlere ayırır. + +**Uygulama**: +Metin İşleyici, gelen metin parçalarını cümlelere ayırmak ve POS etiketlemesi yapmak için NLTK'yi kullanır. NLTK sürüm uyumluluğunu, `punkt_tab` ve `averaged_perceptron_tagger_eng`'i indirmeye çalışarak ve gerekirse eski sürümlere geri dönerek yönetir. Her metin parçası, ontoloji öğeleriyle bağımsız olarak eşleştirilebilen ayrı cümlelere bölünür. + +**Temel İşlemler**: +NLTK cümle ayrıştırması kullanarak metni cümlelere ayırın +NLTK sürüm uyumluluğunu yönetin (punkt_tab vs punkt) +Metin ve konum bilgileriyle TextSegment nesneleri oluşturun +Hem tam cümleleri hem de ayrı parçaları destekleyin + +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. Ontoloji Seçici + +**Amaç**: Mevcut metin parçası için en alakalı ontoloji öğesi alt kümesini belirler. + +**Uygulama**: +Ontoloji Seçici, metin segmentleri ile ontoloji öğeleri arasında semantik eşleştirme yapmak için FAISS vektör benzerlik araması kullanır. Metin parçasındaki her cümle için, bir gömü oluşturur ve vektör deposunda en benzer ontoloji öğelerini yapılandırılabilir bir eşik değeri (varsayılan 0,3) ile kosinüs benzerliği kullanarak arar. Tüm ilgili öğeler toplandıktan sonra, kapsamlı bir bağımlılık çözümlemesi yapılır: bir sınıf seçilirse, üst sınıfları dahil edilir; bir özellik seçilirse, etki alanı ve aralık sınıfları eklenir. Ek olarak, seçilen her sınıf için, **o sınıfa referans veren tüm özellikleri** (etki alanı veya aralık olarak) otomatik olarak dahil eder. Bu, çıkarmanın ilgili tüm ilişki özelliklerine erişmesini sağlar. + +**Temel İşlemler**: +Her metin parçasının (cümlelerin) gömülme değerlerini oluşturun. +FAISS vektör deposunda k-en yakın komşu araması yapın (top_k=10, eşik=0.3). +Zayıf eşleşmeleri filtrelemek için benzerlik eşiği uygulayın. +Bağımlılıkları çözün (üst sınıflar, etki alanları, aralıklar). +**Seçilen sınıflarla ilgili tüm özellikleri otomatik olarak dahil edin** (etki alanı/aralık eşleşmesi). +Tüm gerekli ilişkilerle tutarlı bir ontoloji alt kümesi oluşturun. +Birden çok kez görünen öğeleri yinelenenleri kaldırın. + +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. İstek Oluşturma + +**Amaç**: LLM'yi yalnızca ontolojiye uygun üçlüleri çıkarması için yönlendiren yapılandırılmış istekler oluşturur. + +**Uygulama**: +Çıkarma hizmeti, `ontology-prompt.md`'dan yüklenen bir Jinja2 şablonu kullanır ve bu şablon, ontoloji alt kümesini ve LLM tarafından çıkarım için kullanılan metni biçimlendirir. Şablon, Jinja2 sözdizimini kullanarak sınıflar, nesne özellikleri ve veri türü özellikleri üzerinde dinamik olarak yineleme yapar ve her birini açıklamaları, etki alanları, aralıkları ve hiyerarşik ilişkileriyle birlikte sunar. İstek, yalnızca sağlanan ontoloji öğelerinin kullanılması konusunda kesin kurallar içerir ve tutarlı ayrıştırma için JSON çıktı biçimi talep eder. + +**Temel İşlemler**: +Ontoloji öğeleri üzerinde döngüler içeren Jinja2 şablonunu kullanın. +Üst sınıf ilişkileri (subclass_of) ve yorumlarla sınıfları biçimlendirin. +Etki alanı/aralık kısıtlamaları ve yorumlarla özellikleri biçimlendirin. +Açık çıkarma kuralları ve çıktı biçimi gereksinimleri ekleyin. +"extract-with-ontologies" şablonuyla istek hizmetini çağırın. + +**Şablon Konumu**: `ontology-prompt.md` +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (build_extraction_variables metodu) + +#### 6. Ana Çıkarma Hizmeti + +**Amaç**: Uçtan uca, ontolojiye dayalı üçlü çıkarma işlemini gerçekleştirmek için tüm bileşenleri koordine eder. + +**Uygulama**: +Ana Çıkarma Hizmeti (KgExtractOntology), eksiksiz çıkarma iş akışını yöneten orkestrasyon katmanıdır. Her akış için bileşen başlatmayı kullanan TrustGraph'ın FlowProcessor kalıbını kullanır. Bir ontoloji yapılandırma güncellemesi geldiğinde, akışa özgü bileşenleri (ontoloji yükleyici, gömücü, metin işlemcisi, seçici) başlatır veya günceller. Bir metin parçası işlenmek üzere geldiğinde, aşağıdaki adımları koordine eder: metni segmentlere ayırmak, vektör araması yoluyla ilgili ontoloji öğelerini bulmak, kısıtlı bir istek oluşturmak, istek hizmetini çağırmak, yanıtı ayrıştırmak ve doğrulamak, ontoloji tanım üçlüleri oluşturmak ve hem içerik üçlülerini hem de varlık bağlamlarını yayınlamak. + +**Çıkarma İş Akışı**: +1. Metin parçasını chunks-input kuyruğu aracılığıyla alın. +2. Gerekirse akış bileşenlerini başlatın (ilk parça veya yapılandırma güncellemesinde). +3. Metni NLTK kullanarak cümlelere ayırın. +4. İlgili ontoloji kavramlarını bulmak için FAISS vektör deposunda arama yapın. +5. Otomatik özellik dahil etme ile ontoloji alt kümesini oluşturun. +6. Jinja2 şablonlu istek değişkenlerini oluşturun. +7. extract-with-ontologies şablonuyla istek hizmetini çağırın. +8. JSON yanıtını yapılandırılmış üçlülere ayrıştırın. +9. Üçlüleri doğrulayın ve URI'ları tam ontoloji URI'lerine genişletin. +10. Sınıflar ve özellikler (etiketler/yorumlar/etki alanları/aralıklar) ile ontoloji tanım üçlülerini oluşturun. +11. Tüm üçlülerden varlık bağlamlarını oluşturun. +12. Üçlüleri ve varlık-bağlamlarını kuyruklara yayınlayın. + +**Temel Özellikler**: +Farklı gömme modellerini destekleyen akış içi vektör depoları. +config-update kuyruğu aracılığıyla olay odaklı ontoloji güncellemeleri. +Ontoloji URI'lerini kullanarak otomatik URI genişletme. +Ontoloji öğeleri, tüm meta verilerle birlikte bilgi grafiğine eklenir. +Varlık bağlamları hem içerik hem de ontoloji öğelerini içerir. + +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### Yapılandırma + +Bu hizmet, komut satırı argümanlarıyla TrustGraph'ın standart yapılandırma yaklaşımını kullanır: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**Temel Yapılandırma Parametreleri**: +`similarity_threshold`: 0.3 (varsayılan, kod içinde yapılandırılabilir) +`top_k`: 10 (her segment için alınacak ontoloji öğelerinin sayısı) +`vector_store`: Otomatik olarak algılanan boyutlara sahip Per-flow FAISS IndexFlatIP +`text_processor`: NLTK ile punkt_tab cümle tokenizasyonu +`prompt_template`: "extract-with-ontologies" (Jinja2 şablonu) + +**Ontoloji Yapılandırması**: +Ontolojiler, "ontology" türü ile yapılandırma güncelleme kuyruğu aracılığıyla dinamik olarak yüklenir. + +### Veri Akışı + +1. **Başlangıç Aşaması** (her akış için): + Yapılandırma güncelleme kuyruğu aracılığıyla ontoloji yapılandırmasını alın + Ontoloji JSON'unu OntologyClass ve OntologyProperty nesnelerine ayrıştırın + Tüm ontoloji öğeleri için EmbeddingsClientSpec kullanarak gömülme oluşturun + Gömülmeleri her akış için FAISS vektör deposunda saklayın + İlk yanıttan gömülme boyutlarını otomatik olarak algılayın + +2. **Çıkarma Aşaması** (her parça için): + chunks-input kuyruğundan bir parça alın + Parçayı NLTK kullanarak cümlelere bölün + Her cümle için gömülmeler hesaplayın + İlgili ontoloji öğelerini bulmak için FAISS vektör deposunda arama yapın + Otomatik özellik eklemeli ontoloji alt kümesi oluşturun + Metin ve ontoloji ile Jinja2 şablon değişkenlerini oluşturun + extract-with-ontologies şablonu ile istem hizmetini çağırın + JSON yanıtını ayrıştırın ve üçlüleri doğrulayın + URI'ları ontoloji URI'lerini kullanarak genişletin + Ontoloji tanım üçlülerini oluşturun + Tüm üçlülerden varlık bağlamlarını oluşturun + üçlüler ve varlık-bağlamları kuyruklarına yayınlayın + +### Bellek İçi Vektör Deposu + +**Amaç**: Ontoloji öğesi eşleştirmesi için hızlı, bellek tabanlı benzerlik araması sağlar. + +**Uygulama: FAISS** + +Sistem, tam kosinüs benzerliği araması için **FAISS (Facebook AI Similarity Search)** ve IndexFlatIP kullanır. Temel özellikler: + +**IndexFlatIP**: İç çarpım kullanarak tam kosinüs benzerliği araması +**Otomatik algılama**: Boyut, ilk gömülme yanıtından belirlenir +**Per-flow depoları**: Her akış, farklı gömülme modelleri için bağımsız bir vektör deposuna sahiptir +**Normalleştirme**: Tüm vektörler dizine eklenmeden önce normalleştirilir +**Toplu işlemler**: Başlangıç ontoloji yüklemesi için verimli toplu ekleme + +**Uygulama Konumu**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### Ontoloji Alt Kümesi Seçim Algoritması + +**Amaç**: Her metin parçası için ontolojinin ilgili en küçük bölümünü dinamik olarak seçer. + +**Detaylı Algoritma Adımları**: + +1. **Metin Segmentasyonu**: + Giriş parçasını NLP cümle algılama kullanarak cümlelere bölün + Her cümleden isim öbeklerini, fiil öbeklerini ve adlandırılmış varlıkları çıkarın + Bağlamı koruyan hiyerarşik bir segmentler yapısı oluşturun + +2. **Gömülme Oluşturma**: + Her metin segmenti (cümleler ve öbekler) için vektör gömülmeleri oluşturun + Ontoloji öğeleri için kullanılan aynı gömülme modelini kullanın + Tekrarlayan segmentler için performansı artırmak için gömülmeleri önbelleğe alın + +3. **Benzerlik Araması**: + Her metin segmenti gömülmesi için vektör deposunda arama yapın + En benzer ontoloji öğelerinin en üst N tanesini (örneğin, 10) alın + Zayıf eşleşmeleri filtrelemek için bir benzerlik eşiği (örneğin, 0.7) uygulayın + Tüm segmentler genelinde sonuçları toplayın ve eşleşme sıklıklarını izleyin + +4. **Bağımlılık Çözümü**: + Seçilen her sınıf için, köke kadar tüm üst sınıfları yinelemeli olarak dahil edin + Seçilen her özellik için, alan ve aralık sınıflarını dahil edin + Ters özellikler için, her iki yönü de dahil edin + Ontolojide mevcutsa, eşdeğer sınıfları ekleyin + +5. **Alt Küme Oluşturma**: + Toplanan öğeleri ilişkileri korurken yinelenenleri kaldırın + Sınıflara, nesne özelliklerine ve veri türü özelliklerine göre düzenleyin + Tüm kısıtlamaların ve ilişkilerin korunmasını sağlayın + Geçerli ve eksiksiz olan kendi kendine yeterli bir mini-ontoloji oluşturun + +**Örnek İnceleme**: +Verilen metin: "Kahverengi köpek, beyaz kedinin ağacın tepesine doğru koştuğunu gördü." +Segmentler: ["kahverengi köpek", "beyaz kedi", "ağaç", "koştu"] +Eşleşen öğeler: [köpek (sınıf), kedi (sınıf), hayvan (üst sınıf), koşar (özellik)] +Bağımlılıklar: [hayvan (köpek ve kedinin üst sınıfı), canlı (hayvanın üst sınıfı)] +Sonuç alt kümesi: Hayvan hiyerarşisi ve koşma ilişkisi ile eksiksiz mini-ontoloji + +### Üçlü Doğrulama + +**Amaç**: Çıkarılan tüm üçlülerin ontoloji kısıtlamalarına kesinlikle uygun olduğundan emin olun. + +**Doğrulama Algoritması**: + +1. **Sınıf Doğrulama**: + Konuların, ontoloji alt kümesinde tanımlanan sınıfların örnekleri olduğundan emin olun. + Nesne özellikleri için, nesnelerin de geçerli sınıf örnekleri olduğundan emin olun. + Sınıf adlarını, ontolojinin sınıf sözlüğü ile karşılaştırın. + Sınıf hiyerarşilerini işleyin - alt sınıfların örnekleri, üst sınıf kısıtlamaları için geçerlidir. + +2. **Özellik Doğrulama**: + Öncüllerin, ontoloji alt kümesindeki özelliklerle eşleştiğinden emin olun. + Varlıklar arası nesne özellikleri ile varlıklardan literal değerlere olan veri tipi özellikleri arasındaki farkı belirtin. + Özellik adlarının tam olarak eşleştiğinden emin olun (varsa ad alanını dikkate alın). + +3. **Alan/Aralık Kontrolü**: + Kullanılan her özellik için, alanını ve aralığını alın. + Konunun türünün, özelliğin alanıyla eşleştiğinden veya ondan türediğinden emin olun. + Nesnenin türünün, özelliğin aralığıyla eşleştiğinden veya ondan türediğinden emin olun. + Veri tipi özellikleri için, nesnenin doğru XSD türünde bir literal olduğundan emin olun. +Veri tipi özellikleri için, nesnenin doğru XSD türünde bir literal olduğundan emin olun +4. **Kardinalite Doğrulama**: + Her konu için özellik kullanım sayılarını takip edin. + Minimum kardinaliteyi kontrol edin - gerekli özelliklerin mevcut olduğundan emin olun. + Maksimum kardinaliteyi kontrol edin - özelliğin çok fazla kullanılmadığından emin olun. + Fonksiyonel özellikler için, her konu için en fazla bir değer olduğundan emin olun. + +5. **Veri Tipi Doğrulama**: + Literal değerleri, bildirilen XSD türlerine göre ayrıştırın. + Tamsayıların geçerli sayılar olduğundan, tarihlerinin doğru biçimlendirildiğinden emin olun, vb. + Regex kısıtlamaları tanımlanmışsa, dize kalıplarını kontrol edin. + URI'lerin xsd:anyURI türleri için doğru biçimlendirildiğinden emin olun. + +**Doğrulama Örneği**: +Üçlü: ("Buddy", "has-owner", "John") +"Buddy"nin, "has-owner" özelliğine sahip olabilen bir sınıf olarak tanımlandığından emin olun. +"has-owner" özelliğinin ontolojide olduğundan emin olun. +Alan kısıtlamasını doğrulayın: konu, "Pet" türünde veya bir alt türünde olmalıdır. +Aralık kısıtlamasını doğrulayın: nesne, "Person" türünde veya bir alt türünde olmalıdır. +Geçerliyse, çıktıya ekleyin; geçersizse, ihlali günlüğe kaydedin ve atlayın. + +## Performans Hususları + +### Optimizasyon Stratejileri + +1. **Gömülü Önbellekleme**: Sık kullanılan metin segmentleri için gömülmeleri önbelleğe alın. +2. **Toplu İşleme**: Birden fazla segmenti paralel olarak işleyin. +3. **Vektör Deposu İndeksleme**: Büyük ontolojiler için yaklaşık en yakın komşu algoritmalarını kullanın. +4. **İstem Optimizasyonu**: Yalnızca gerekli ontoloji öğelerini dahil ederek istem boyutunu en aza indirin. +5. **Sonuç Önbellekleme**: Aynı parçalar için çıkarma sonuçlarını önbelleğe alın. + +### Ölçeklenebilirlik + +**Yatay Ölçekleme**: Paylaşılan ontoloji önbelleğine sahip çoklu çıkarıcı örneği. +**Ontoloji Bölümleme**: Büyük ontolojileri alanlara göre bölün. +**Akışlı İşleme**: Parçalara toplu olarak işlem yapmadan geldikçe işleyin. +**Bellek Yönetimi**: Kullanılmayan gömülmelerin periyodik olarak temizlenmesi. + +## Hata Yönetimi + +### Başarısızlık Senaryoları + +1. **Eksik Ontolojiler**: Kısıtlanmamış çıkarma işlemine geri dönün. +2. **Gömme Hizmeti Hatası**: Önbelleğe alınmış gömülmeleri kullanın veya semantik eşleşmeyi atlayın. +3. **İstem Hizmeti Zaman Aşımı**: Üstel geri alma ile yeniden deneyin. +4. **Geçersiz Üçlü Biçimi**: Hatalı üçlüleri günlüğe kaydedin ve atlayın. +5. **Ontoloji Tutarsızlıkları**: Çakışmaları bildirin ve en spesifik geçerli öğeleri kullanın. + +### İzleme + +İzlenecek temel ölçütler: + +Ontoloji yükleme süresi ve bellek kullanımı +Gömme oluşturma gecikmesi +Vektör arama performansı +İstem hizmeti yanıt süresi +Üçlü çıkarma doğruluğu +Ontoloji uyumluluk oranı + +## Geçiş Yolu + +### Mevcut Çıkarıcılardan + +1. **Paralel Çalışma**: Başlangıçta mevcut çıkarıcılarla birlikte çalıştırın. +2. **Aşamalı Dağıtım**: Belirli belge türleriyle başlayın. +3. **Kalite Karşılaştırması**: Çıktı kalitesini mevcut çıkarıcılarla karşılaştırın. +4. **Tam Geçiş**: Kalite doğrulandığında mevcut çıkarıcıları değiştirin. + +### Ontoloji Geliştirme + +1. **Mevcut Bilgilerden Başlatma**: Başlangıç ontolojilerini mevcut bilgilerden oluşturun. +2. **Yinelemeli İyileştirme**: Çıkarma kalıplarına göre iyileştirin. +3. **Alan Uzmanı İncelemesi**: Konu uzmanlarıyla doğrulayın. +4. **Sürekli İyileştirme**: Çıkarma geri bildirimine göre güncelleyin. + +## Ontolojiye Duyarlı Sorgu Hizmeti + +### Genel Bakış + +Ontolojiye duyarlı sorgu hizmeti, farklı arka uç grafik depolarını desteklemek için çoklu sorgu yolu sağlar. Cassandra (SPARQL aracılığıyla) ve Cypher tabanlı grafik depoları (Neo4j, Memgraph, FalkorDB) için hem hassas hem de semantik olarak bilinçli soru yanıtlama için ontoloji bilgisini kullanır. + +**Hizmet Bileşenleri**: +`onto-query-sparql`: Doğal dili, Cassandra için SPARQL'e dönüştürür. +`sparql-cassandra`: Cassandra için rdflib kullanarak SPARQL sorgu katmanı. +`onto-query-cypher`: Doğal dili, grafik veritabanları için Cypher'a dönüştürür. +`cypher-executor`: Neo4j, Memgraph, FalkorDB için Cypher sorgu katmanı. + +### Mimari + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### Sorgu İşleme Hattı + +#### 1. Soru Analizörü + +**Amaç**: Kullanıcı sorularını, ontoloji eşleştirmesi için anlamsal bileşenlere ayırır. + +**Algoritma Açıklaması**: +Soru Analizörü, gelen doğal dil sorgusunu alır ve çıkarma hattında kullanılan aynı cümle bölme yaklaşımıyla anlamlı segmentlere böler. Soruda bahsedilen temel varlıkları, ilişkileri ve kısıtlamaları belirler. Her segment, soru türü (olaysal, toplama, karşılaştırma vb.) ve beklenen cevap formatı açısından analiz edilir. Bu ayrıştırma, soruyu yanıtlamak için ontolojinin hangi bölümlerinin en alakalı olduğunu belirlemeye yardımcı olur. + +**Temel İşlemler**: +Soruyu cümlelere ve ifadelere ayırın +Soru türünü ve amacını belirleyin +Bahsedilen varlıkları ve ilişkileri çıkarın +Sorudaki kısıtlamaları ve filtreleri tespit edin +Beklenen cevap formatını belirleyin + +#### 2. Sorgular İçin Ontoloji Eşleştirici + +**Amaç**: Soruyu yanıtlamak için gereken ilgili ontoloji alt kümesini belirler. + +**Algoritma Açıklaması**: +Çıkarma hattının Ontoloji Seçici'sine benzer, ancak soru yanıtlama için optimize edilmiştir. Eşleştirici, soru segmentleri için gömülme değerleri oluşturur ve ilgili ontoloji öğelerini vektör deposunda arar. Ancak, sorgu oluşturma için yararlı olacak kavramları bulmaya odaklanır, çıkarma işlemine değil. Grafiği keşfederken bahsedilmeyen ancak ilgili olabilecek ilgili özellikleri de seçime dahil eder. Örneğin, "çalışanlar" hakkında bir soru sorulursa, çalışan bilgileri bulmak için ilgili olabilecek "çalışır", "yönetir" ve "rapor verir" gibi özellikleri de içerebilir. + +**Eşleştirme Stratejisi**: +Soru segmentlerini gömülme değerlerine dönüştürün +Doğrudan bahsedilen ontoloji kavramlarını bulun +Bahsedilen sınıfları birbirine bağlayan özellikleri dahil edin +Gezinme için ters ve ilgili özellikleri ekleyin +Hiyerarşik sorgular için üst/alt sınıfları dahil edin +Sorgu odaklı bir ontoloji bölümü oluşturun + +#### 3. Arka Uç Yönlendirici + +**Amaç**: Sorguları, yapılandırmaya göre uygun arka uç özel sorgu yoluna yönlendirir. + +**Algoritma Açıklaması**: +Arka Uç Yönlendirici, sistem yapılandırmasını inceleyerek hangi grafik arka ucunun (Cassandra veya Cypher tabanlı) etkin olduğunu belirler. Soruyu ve ontoloji bölümünü uygun sorgu oluşturma hizmetine yönlendirir. Yönlendirici, birincil arka uç kullanılamıyorsa, aynı zamanda birden fazla arka uç arasında yük dengeleme veya yedekleme mekanizmalarını da destekleyebilir. + +**Yönlendirme Mantığı**: +Sistem ayarlarından yapılandırılmış arka uç türünü kontrol edin +Cassandra arka uçları için `onto-query-sparql`'a yönlendirin +Neo4j/Memgraph/FalkorDB için `onto-query-cypher`'a yönlendirin +Sorgu dağıtımı ile çoklu arka uç yapılandırmalarını destekleyin +Arıza ve yük dengeleme senaryolarını işleyin + +#### 4. SPARQL Sorgu Oluşturma (`onto-query-sparql`) + +**Amaç**: Doğal dil sorularını, Cassandra üzerinde yürütme için SPARQL sorgularına dönüştürür. + +**Algoritma Açıklaması**: +SPARQL sorgu oluşturucu, soruyu ve ontoloji bölümünü alır ve Cassandra arka ucu üzerinde yürütülmek üzere optimize edilmiş bir SPARQL sorgusu oluşturur. RDF/OWL semantiğini içeren, SPARQL'e özel bir şablon kullanan bir istem hizmeti kullanır. Oluşturucu, Cassandra işlemleriyle verimli bir şekilde çevrilebilen özellik yolları, isteğe bağlı ifadeler ve filtreler gibi SPARQL kalıplarını anlar. + +**SPARQL Oluşturma İstem Şablonu**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. Şifre Sorgu Üretimi (`onto-query-cypher`) + +**Amaç**: Doğal dil sorularını, grafik veritabanları için Şifre sorgularına dönüştürür. + +**Algoritma Açıklaması**: +Şifre sorgu üreticisi, Neo4j, Memgraph ve FalkorDB için optimize edilmiş yerel Şifre sorguları oluşturur. Ontoloji sınıflarını düğüm etiketlerine ve özellikleri ilişkilerle eşler, Şifre'nin desen eşleştirme sözdizimini kullanır. Üretici, ilişki yönü ipuçları, indeks kullanımı ve sorgu planlama ipuçları gibi Şifre'ye özgü optimizasyonları içerir. + +**Şifre Üretim İstem Şablonu**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. SPARQL-Cassandra Sorgu Motoru (`sparql-cassandra`) + +**Amaç**: Python rdflib kullanarak Cassandra'ya karşı SPARQL sorgularını yürütür. + +**Algoritma Açıklaması**: +SPARQL-Cassandra motoru, Python'ın rdflib kütüphanesini ve özel bir Cassandra arka uç depolama alanını kullanan bir SPARQL işlemcisi uygular. SPARQL grafik desenlerini, birleştirmeleri, filtreleri ve toplama işlemlerini işleyerek uygun Cassandra CQL sorgularına dönüştürür. Motor, semantik yapıyı korurken Cassandra'nın sütun ailesi depolama modeline göre optimizasyon sağlayan bir RDF-Cassandra eşleme sürdürür. + +**Uygulama Özellikleri**: +Cassandra için rdflib Store arayüzü uygulaması +Yaygın desenlerle SPARQL 1.1 sorgu desteği +Üçlü desenlerin CQL'ye verimli çevirisi +Özellik yolları ve hiyerarşik sorgular için destek +Büyük veri kümeleri için sonuç akışı +Bağlantı havuzu ve sorgu önbelleği + +**Örnek Çeviri**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +İndeksleri ve bölüm anahtarlarını kullanan, optimize edilmiş Cassandra sorgularına çevrilir. + +#### 7. Cypher Sorgu Yürütücüsü (`cypher-executor`) + +**Amaç**: Neo4j, Memgraph ve FalkorDB'ye karşı Cypher sorgularını yürütür. + +**Algoritma Açıklaması**: +Cypher yürütücüsü, farklı grafik veritabanları arasında Cypher sorgularını yürütmek için birleşik bir arayüz sağlar. Veritabanına özgü bağlantı protokollerini, sorgu optimizasyonu ipuçlarını ve sonuç biçimi normalizasyonunu işler. Yürütücü, her veritabanı türü için uygun olan yeniden deneme mantığını, bağlantı havuzunu ve işlem yönetimini içerir. + +**Çoklu Veritabanı Desteği**: +**Neo4j**: Bolt protokolü, işlem fonksiyonları, indeks ipuçları +**Memgraph**: Özel protokol, akışlı sonuçlar, analitik sorgular +**FalkorDB**: Redis protokolü adaptasyonu, bellek içi optimizasyonlar + +**Yürütme Özellikleri**: +Veritabanından bağımsız bağlantı yönetimi +Sorgu doğrulaması ve sözdizimi kontrolü +Zaman aşımı ve kaynak limiti uygulama +Sonuç sayfalama ve akış +Veritabanı türüne göre performans izleme +Veritabanı örnekleri arasında otomatik geçiş + +#### 8. Cevap Oluşturucu + +**Amaç**: Sorgu sonuçlarından doğal bir dil cevabı oluşturur. + +**Algoritma Açıklaması**: +Cevap Oluşturucu, yapılandırılmış sorgu sonuçlarını ve orijinal soruyu alır, ardından kapsamlı bir cevap oluşturmak için istem hizmetini kullanır. Basit şablon tabanlı yanıtlardan farklı olarak, grafik verilerini sorunun bağlamında yorumlamak için bir LLM kullanır, karmaşık ilişkileri, toplamaları ve çıkarımları işler. Oluşturucu, ontoloji yapısına ve grafikten alınan belirli üçlülere başvurarak akıl yürütmesini açıklayabilir. + +**Cevap Oluşturma Süreci**: +Sorgu sonuçlarını yapılandırılmış bir bağlama dönüştürür +Açıklık için ilgili ontoloji tanımlarını ekler +Soru ve sonuçlarla bir istem oluşturur +LLM aracılığıyla doğal dil cevabı oluşturur +Cevabı sorgu amacına göre doğrular +Gerekirse belirli grafik varlıklarına alıntılar ekler + +### Mevcut Hizmetlerle Entegrasyon + +#### GraphRAG ile İlişki + +**Tamamlayıcı**: onto-query semantik hassasiyet sağlarken, GraphRAG geniş kapsamlı bir kapsama sahiptir. +**Paylaşılan Altyapı**: Her ikisi de aynı bilgi grafiğini ve istem hizmetlerini kullanır. +**Sorgu Yönlendirmesi**: Sistem, sorunun türüne göre sorguları en uygun hizmete yönlendirebilir. +**Hibrit Mod**: Kapsamlı cevaplar için her iki yaklaşımı da birleştirebilir. + +#### OntoRAG Çıkarma ile İlişki + +**Paylaşılan Ontolojiler**: kg-extract-ontology tarafından yüklenen aynı ontoloji yapılandırmalarını kullanır. +**Paylaşılan Vektör Deposu**: Çıkarma hizmetinden alınan bellek içi gömülmeleri yeniden kullanır. +**Tutarlı Semantikler**: Sorgular, aynı ontolojik kısıtlamalarla oluşturulmuş grafikler üzerinde çalışır. + +### Sorgu Örnekleri + +#### Örnek 1: Basit Varlık Sorgusu +**Soru**: "Hangi hayvanlar memelidir?" +**Ontoloji Eşleşmesi**: [hayvan, memeli, subClassOf] +**Oluşturulan Sorgu**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### Örnek 2: İlişki Sorgusu +**Soru**: "Hangi belgeler John Smith tarafından yazılmıştır?" +**Ontoloji Eşleşmesi**: [belge, kişi, yazarıdır] +**Oluşturulan Sorgu**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### Örnek 3: Toplama Sorgusu +**Soru**: "Kedilerin kaç tane bacağı vardır?" +**Ontoloji Eşleşmesi**: [kedi, bacak sayısı (veri tipi özelliği)] +**Oluşturulan Sorgu**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### Yapılandırma + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### Performans Optimizasyonları + +#### Sorgu Optimizasyonu + +**Ontoloji Budama**: Sadece gerekli ontoloji öğelerini istemlerde kullanın. +**Sorgu Önbelleği**: Sıkça sorulan soruları ve sorgularını önbelleğe alın. +**Sonuç Önbelleği**: Aynı sorgular için sonuçları belirli bir zaman aralığında saklayın. +**Toplu İşleme**: Birden fazla ilgili soruyu tek bir grafik geçişiyle işleyin. + +#### Ölçeklenebilirlik Hususları + +**Dağıtık Çalıştırma**: Alt sorguları grafik bölümlerine göre paralel hale getirin. +**Artan Sonuçlar**: Büyük veri kümeleri için sonuçları akış şeklinde gönderin. +**Yük Dengeleme**: Sorgu yükünü birden fazla hizmet örneğine dağıtın. +**Kaynak Havuzları**: Grafik veritabanlarına bağlantı havuzlarını yönetin. + +### Hata Yönetimi + +#### Hata Senaryoları + +1. **Geçersiz Sorgu Oluşturma**: GraphRAG'e veya basit anahtar kelime aramasına geri dönün. +2. **Ontoloji Uyuşmazlığı**: Aramayı daha geniş bir ontoloji alt kümesine genişletin. +3. **Sorgu Zaman Aşımı**: Sorguyu basitleştirin veya zaman aşımı süresini artırın. +4. **Boş Sonuçlar**: Sorguyu yeniden formüle etmeyi veya ilgili soruları önerin. +5. **LLM Hizmeti Hatası**: Önbelleğe alınmış sorguları veya şablon tabanlı yanıtları kullanın. + +### İzleme Metrikleri + +Soru karmaşıklığı dağılımı +Ontoloji bölüm boyutları +Sorgu oluşturma başarı oranı +Grafik sorgu yürütme süresi +Cevap kalitesi puanları +Önbellek isabet oranları +Hata frekansları (türlere göre) + +## Gelecek Geliştirmeler + +1. **Ontoloji Öğrenimi**: Çıkarma kalıplarına göre ontolojileri otomatik olarak genişletin. +2. **Güvenilirlik Puanlama**: Çıkarılan üçlülere güvenilirlik puanları atayın. +3. **Açıklama Oluşturma**: Üçlü çıkarma için gerekçeler sağlayın. +4. **Aktif Öğrenme**: Belirsiz çıkarmalar için insan doğrulaması isteyin. + +## Güvenlik Hususları + +1. **İstem Enjeksiyonu Önleme**: İstem oluşturulmadan önce parça metnini temizleyin. +2. **Kaynak Limitleri**: Vektör deposu için bellek kullanımını sınırlayın. +3. **Hız Sınırlama**: İstem başına çıkarma isteklerini sınırlayın. +4. **Denetim Kaydı**: Tüm çıkarma isteklerini ve sonuçlarını izleyin. + +## Test Stratejisi + +### Birim Testleri + +Çeşitli formatlarda ontoloji yükleyici +Gömme oluşturma ve depolama +Cümle bölme algoritmaları +Vektör benzerliği hesaplamaları +Üçlü ayrıştırma ve doğrulama + +### Entegrasyon Testleri + +Uçtan uca çıkarma hattı +Yapılandırma hizmeti entegrasyonu +İstem hizmeti etkileşimi +Eşzamanlı çıkarma işleme + +### Performans Testleri + +Büyük ontoloji işleme (1000+ sınıf) +Yüksek hacimli parça işleme +Yük altında bellek kullanımı +Gecikme ölçümleri + +## Teslimat Planı + +### Genel Bakış + +OntoRAG sistemi, her fazda kademeli değer sağlayan ve tamamlanmış sisteme doğru ilerleyen dört ana fazda teslim edilecektir. Plan, öncelikle temel çıkarma yeteneklerini, ardından sorgu işlevselliğini ve ardından optimizasyonları ve gelişmiş özellikleri eklemeyi hedeflemektedir. + +### 1. Faz: Temel ve Temel Çıkarma + +**Hedef**: Basit vektör eşleştirmesiyle temel, ontoloji odaklı çıkarma hattını kurun. + +#### 1. Adım: Ontoloji Yönetimi Temeli +Ontoloji yapılandırma yükleyici uygulayın (`OntologyLoader`). +Ontoloji JSON yapılarını ayrıştırın ve doğrulayın. +Bellekte ontoloji depolama ve erişim kalıplarını oluşturun. +Ontoloji yenileme mekanizmasını uygulayın. + +**Başarı Kriterleri**: +Ontoloji yapılandırmalarını başarıyla yükleyin ve ayrıştırın. +Ontoloji yapısını ve tutarlılığını doğrulayın. +Birden fazla eşzamanlı ontolojiyi işleyin. + +#### 2. Adım: Vektör Deposu Uygulaması +Başlangıç prototipi olarak basit NumPy tabanlı bir vektör deposu uygulayın. +FAISS vektör deposu uygulamasını ekleyin. +Vektör deposu arayüzü soyutlamasını oluşturun. +Yapılandırılabilir eşiklerle benzerlik araması uygulayın. + +**Başarı Kriterleri**: +Gömme vektörlerini verimli bir şekilde depola ve geri yükle +<100ms gecikmeyle benzerlik araması yap +NumPy ve FAISS arka uçlarını destekle + +#### 1.3 Adımı: Ontoloji Gömme İşlem Hattı +Gömme hizmetiyle entegre ol +`OntologyEmbedder` bileşenini uygula +Tüm ontoloji öğeleri için gömmeler oluştur +Vektör deposunda meta verilerle birlikte gömmeleri depola + +**Başarı Kriterleri**: +Sınıflar ve özellikler için gömmeler oluştur +Uygun meta verilerle birlikte gömmeleri depola +Ontoloji güncellemelerinde gömmeleri yeniden oluştur + +#### 1.4 Adımı: Metin İşleme Bileşenleri +NLTK/spaCy kullanarak cümle bölücü uygula +Cümleleri ve adlandırılmış varlıkları çıkar +Metin segmenti hiyerarşisi oluştur +Metin segmentleri için gömmeler oluştur + +**Başarı Kriterleri**: +Metni doğru bir şekilde cümlelere böl +Anlamlı cümleleri çıkar +Bağlam ilişkilerini koru + +#### 1.5 Adımı: Ontoloji Seçim Algoritması +Metin ve ontoloji arasındaki benzerlik eşleştirmesini uygula +Ontoloji öğeleri için bağımlılık çözümlemesi oluştur +Minimal, tutarlı ontoloji alt kümeleri oluştur +Alt küme oluşturma performansını optimize et + +**Başarı Kriterleri**: +İlgili ontoloji öğelerini >%80 doğrulukla seç +Tüm gerekli bağımlılıkları dahil et +Alt kümeleri <500ms içinde oluştur + +#### 1.6 Adımı: Temel Çıkarma Hizmeti +Çıkarma için istem oluşturma uygula +İstem hizmetiyle entegre ol +Üçlü yanıtları ayrıştır ve doğrula +`kg-extract-ontology` hizmet uç noktası oluştur + +**Başarı Kriterleri**: +Ontolojiye uygun üçlüler çıkar +Tüm üçlüleri ontolojiye göre doğrula +Çıkarma hatalarını düzgün bir şekilde işle + +### 2. Aşama: Sorgu Sistemi Uygulaması + +**Amaç**: Çoklu arka uç desteğiyle ontolojiye duyarlı sorgu yetenekleri ekle. + +#### 2.1 Adımı: Sorgu Temel Bileşenleri +Soru analizörünü uygula +Sorgular için ontoloji eşleştirici oluştur +Vektör aramayı sorgu bağlamı için uyarlayın +Arka uç yönlendirici bileşeni oluştur + +**Başarı Kriterleri**: +Soruları anlamsal bileşenlere ayır +Soruları ilgili ontoloji öğelerine eşleştir +Sorguları uygun arka uca yönlendir + +#### 2.2 Adımı: SPARQL Yolu Uygulaması +`onto-query-sparql` hizmetini uygula +LLM kullanarak SPARQL sorgu oluşturucu oluştur +SPARQL oluşturma için istem şablonları geliştir +Oluşturulan SPARQL sözdizimini doğrula + +**Başarı Kriterleri**: +Geçerli SPARQL sorguları oluştur +Uygun SPARQL kalıplarını kullan +Karmaşık sorgu türlerini işle + +#### 2.3 Adımı: SPARQL-Cassandra Motoru +Cassandra için rdflib Store arayüzünü uygula +CQL sorgu çevirmeni oluştur +Üçlü kalıp eşleştirmesini optimize et +SPARQL sonuç biçimlendirmesini işle + +**Başarı Kriterleri**: +SPARQL sorgularını Cassandra üzerinde çalıştır +Yaygın SPARQL kalıplarını destekle +Sonuçları standart biçimde döndür + +#### 2.4 Adımı: Cypher Yolu Uygulaması +`onto-query-cypher` hizmetini uygula +LLM kullanarak Cypher sorgu oluşturucu oluştur +Cypher oluşturma için istem şablonları geliştir +Oluşturulan Cypher sözdizimini doğrula + +**Başarı Kriterleri**: +Geçerli Cypher sorguları oluştur +Uygun grafik kalıplarını kullan +Neo4j, Memgraph, FalkorDB'yi destekle + +#### 2.5 Adımı: Cypher Yürütücü +Çoklu veritabanı Cypher yürütücüsünü uygulayın +Bolt protokolünü destekleyin (Neo4j/Memgraph) +Redis protokolünü destekleyin (FalkorDB) +Sonuç normalleştirmesini yönetin + +**Başarı Kriterleri**: +Cypher'ı tüm hedef veritabanlarında çalıştırın +Veritabanına özgü farklılıkları ele alın +Bağlantı havuzlarını verimli bir şekilde koruyun + +#### 2. Adım: Cevap Üretimi +Cevap üretici bileşenini uygulayın +Cevap sentezi için istemler oluşturun +Sorgu sonuçlarını LLM'nin kullanabileceği bir formata dönüştürün +Doğal dil cevapları oluşturun + +**Başarı Kriterleri**: +Sorgu sonuçlarından doğru cevaplar üretin +Orijinal sorudan bağlamı koruyun +Açık, öz cevaplar sağlayın + +### 3. Aşama: Optimizasyon ve Güvenilirlik + +**Amaç**: Performansı optimize edin, önbellekleme ekleyin, hata yönetimini iyileştirin ve güvenilirliği artırın. + +#### 3.1 Adım: Performans Optimizasyonu +Gömme önbelleklemesini uygulayın +Sorgu sonucu önbelleklemesini ekleyin +FAISS IVF indeksleriyle vektör aramayı optimize edin +Gömme işlemleri için toplu işleme uygulayın + +**Başarı Kriterleri**: +Ortalama sorgu gecikmesini %50 azaltın +10 kat daha fazla eşzamanlı istek destekleyin +Saniyeden daha kısa yanıt sürelerini koruyun + +#### 3.2 Adım: Gelişmiş Hata Yönetimi +Kapsamlı bir hata kurtarma mekanizması uygulayın +Sorgu yolları arasında yedekleme mekanizmaları ekleyin +Üstel geri çekilme ile yeniden deneme mantığı oluşturun +Hata günlüğünü ve tanılama bilgilerini iyileştirin + +**Başarı Kriterleri**: +Tüm hata senaryolarını sorunsuz bir şekilde ele alın +Arka uçlar arasında otomatik geçiş +Hata ayıklama için ayrıntılı hata raporlama + +#### 3.3 Adım: İzleme ve Gözlemlenebilirlik +Performans metrikleri toplama ekleyin +Sorgu izlemeyi uygulayın +Sağlık kontrol uç noktaları oluşturun +Kaynak kullanımı izlemeyi ekleyin + +**Başarı Kriterleri**: +Tüm önemli performans göstergelerini izleyin +Engelleri hızlı bir şekilde belirleyin +Sistem sağlığını gerçek zamanlı olarak izleyin + +#### 3.4 Adım: Yapılandırma Yönetimi +Dinamik yapılandırma güncellemelerini uygulayın +Yapılandırma doğrulama ekleyin +Yapılandırma şablonları oluşturun +Ortam özelinde ayarlara destek sağlayın + +**Başarı Kriterleri**: +Yapılandırmayı yeniden başlatmadan güncelleyin +Tüm yapılandırma değişikliklerini doğrulayın +Birden çok dağıtım ortamını destekleyin + +### 4. Aşama: Gelişmiş Özellikler + +**Amaç**: Üretim dağıtımı ve gelişmiş işlevsellik için sofistike yetenekler ekleyin. + +#### 4.1 Adım: Çoklu Ontoloji Desteği +Ontoloji seçimi mantığını uygulayın +Çapraz ontoloji sorgularını destekleyin +Ontoloji sürümlemesini yönetin +Ontoloji birleştirme yetenekleri oluşturun + +**Başarı Kriterleri**: +Birden çok ontoloji üzerinde sorgu yapın +Ontoloji çakışmalarını ele alın +Ontoloji evrimini destekleyin + +#### 4.2 Adım: Akıllı Sorgu Yönlendirme +Performans odaklı yönlendirme uygulayın +Sorgu karmaşıklığı analizini ekleyin +Adaptif yönlendirme algoritmaları oluşturun +Yollar için A/B testlerini destekleyin + +**Başarı Kriterleri**: +Sorguları en uygun şekilde yönlendirin +Sorgu performansından öğrenin +Yönlendirmeyi zamanla iyileştirin + +#### 4.3. Adım: Gelişmiş Çıkarma Özellikleri +Üçlüler için güvenilirlik puanı ekleyin +Açıklama oluşturma uygulayın +İyileştirme için geri bildirim döngüleri oluşturun +Artımlı öğrenmeyi destekleyin + +**Başarı Kriterleri**: +Güvenilirlik puanları sağlayın +Çıkarma kararlarını açıklayın +Doğruluğu sürekli olarak iyileştirin + +#### 4.4. Adım: Üretim Hazırlığı +Hız sınırlaması ekleyin +Kimlik doğrulama/yetkilendirme uygulayın +Dağıtım otomasyonu oluşturun +Yedekleme ve kurtarma ekleyin + +**Başarı Kriterleri**: +Üretim için uygun güvenlik +Otomatikleştirilmiş dağıtım hattı +Afet kurtarma yeteneği + +### Teslimat Aşamaları + +1. **Aşama 1** (1. Aşamanın Sonu): Temel, ontoloji odaklı çıkarma işleminin çalışır durumda olması +2. **Aşama 2** (2. Aşamanın Sonu): Hem SPARQL hem de Cypher yollarına sahip tam sorgu sistemi +3. **Aşama 3** (3. Aşamanın Sonu): Optimize edilmiş, sağlam sistem, üretim ortamına hazır +4. **Aşama 4** (4. Aşamanın Sonu): Gelişmiş özelliklere sahip, üretim için hazır sistem + +### Risk Azaltma + +#### Teknik Riskler +**Vektör Depolama Ölçeklenebilirliği**: NumPy ile başlayın, FAISS'e kademeli olarak geçin +**Sorgu Oluşturma Doğruluğu**: Doğrulama ve yedekleme mekanizmaları uygulayın +**Arka Uç Uyumluluğu**: Her veritabanı türüyle kapsamlı bir şekilde test edin +**Performans Engelleri**: Erken ve sık sık profil oluşturun, yinelemeli olarak optimize edin + +#### İşletim Riskleri +**Ontoloji Kalitesi**: Doğrulama ve tutarlılık kontrolü uygulayın +**Hizmet Bağımlılıkları**: Devre kesiciler ve yedeklemeler ekleyin +**Kaynak Kısıtlamaları**: İzleyin ve uygun limitler ayarlayın +**Veri Tutarlılığı**: Uygun işlem yönetimi uygulayın + +### Başarı Metrikleri + +#### 1. Aşama Başarı Metrikleri +Çıkarma doğruluğu: %90'ın üzerinde ontoloji uyumluluğu +İşleme hızı: Parça başına <1 saniye +Ontoloji yükleme süresi: <10 saniye +Vektör arama gecikmesi: <100 ms + +#### 2. Aşama Başarı Metrikleri +Sorgu başarı oranı: %95'in üzerinde +Sorgu gecikmesi: Uçtan uca <2 saniye +Arka uç uyumluluğu: Hedef veritabanları için %100 +Cevap doğruluğu: Mevcut verilere göre %85'in üzerinde + +#### 3. Aşama Başarı Metrikleri +Sistem çalışma süresi: >%99.9 +Hata kurtarma oranı: >%95 +Önbellek isabet oranı: >%60 +Eşzamanlı kullanıcılar: >100 + +#### 4. Aşama Başarı Metrikleri +Çoklu ontoloji sorguları: Tamamen destekleniyor +Yönlendirme optimizasyonu: Gecikmede %30 azalma +Güvenilirlik puanı doğruluğu: >%90 +Üretim dağıtımı: Sıfır kesintiyle güncellemeler + +## Referanslar + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/ontorag.zh-cn.md b/docs/tech-specs/ontorag.zh-cn.md new file mode 100644 index 00000000..7254bf12 --- /dev/null +++ b/docs/tech-specs/ontorag.zh-cn.md @@ -0,0 +1,1075 @@ +--- +layout: default +title: "OntoRAG: 基于本体的知识提取和查询技术规范" +parent: "Chinese (Beta)" +--- + +# OntoRAG: 基于本体的知识提取和查询技术规范 + +> **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. + +## 概述 + +OntoRAG 是一个基于本体的知识提取和查询系统,它在从非结构化文本中提取知识三元组以及查询结果知识图谱的过程中,强制执行严格的语义一致性。类似于 GraphRAG,但具有正式的本体约束,OntoRAG 确保所有提取的三元组都符合预定义的本体结构,并提供具有语义意识的查询功能。 + +该系统使用向量相似性匹配,动态选择相关的本体子集,用于提取和查询操作,从而实现专注于上下文相关的处理,同时保持语义有效性。 + +**服务名称**: `kg-extract-ontology` + +## 目标 + +**符合本体的提取**: 确保所有提取的三元组严格符合加载的本体。 +**动态上下文选择**: 使用嵌入向量来选择每个文本块相关的本体子集。 +**语义一致性**: 维护类层次结构、属性域/范围以及约束。 +**高效处理**: 使用内存中的向量存储,以实现快速的本体元素匹配。 +**可扩展架构**: 支持多个并发的本体,具有不同的领域。 + +## 背景 + +当前的知识提取服务 (`kg-extract-definitions`, `kg-extract-relationships`) 在没有正式约束的情况下运行,这可能会产生不一致或不兼容的三元组。OntoRAG 通过以下方式解决此问题: + +1. 加载正式的本体,定义有效的类和属性。 +2. 使用嵌入向量将文本内容与相关的本体元素进行匹配。 +3. 限制提取,仅产生符合本体的三元组。 +4. 提供对提取知识的语义验证。 + +这种方法结合了神经网络提取的灵活性和正式知识表示的严谨性。 + +## 技术设计 + +### 架构 + +OntoRAG 系统由以下组件组成: + +``` +┌─────────────────┐ +│ Configuration │ +│ Service │ +└────────┬────────┘ + │ Ontologies + ▼ +┌─────────────────┐ ┌──────────────┐ +│ kg-extract- │────▶│ Embedding │ +│ ontology │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ │ + ▼ ▼ +┌─────────────────┐ ┌──────────────┐ +│ In-Memory │◀────│ Ontology │ +│ Vector Store │ │ Embedder │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Sentence │────▶│ Chunker │ +│ Splitter │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Ontology │────▶│ Vector │ +│ Selector │ │ Search │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Prompt │────▶│ Prompt │ +│ Constructor │ │ Service │ +└────────┬────────┘ └──────────────┘ + │ + ▼ +┌─────────────────┐ +│ Triple Output │ +└─────────────────┘ +``` + +### 组件详情 + +#### 1. 本体加载器 + +**目的**: 使用事件驱动的更新,从配置服务检索和解析本体配置。 + +**实现**: +本体加载器使用 TrustGraph 的 ConfigPush 队列接收事件驱动的本体配置更新。当类型为“本体”的配置元素被添加或修改时,加载器通过 config-update 队列接收更新,并解析包含元数据、类、对象属性和数据类型属性的 JSON 结构。这些解析的本体存储在内存中,作为结构化的对象,以便在提取过程中高效访问。 + +**主要操作**: +订阅 config-update 队列,用于本体类型配置 +将 JSON 本体结构解析为 OntologyClass 和 OntologyProperty 对象 +验证本体结构和一致性 +将解析的本体缓存到内存中,以便快速访问 +使用 flow-specific 向量存储,处理每个流程的数据 + +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_loader.py` + +#### 2. 本体嵌入器 + +**目的**: 为所有本体元素创建向量嵌入,以实现语义相似性匹配。 + +**实现**: +本体嵌入器处理加载的本体中的每个元素(类、对象属性和数据类型属性),并使用 EmbeddingsClientSpec 服务生成向量嵌入。对于每个元素,它将元素的标识符、标签和描述(注释)组合成文本表示。然后,将此文本转换为高维向量嵌入,以捕获其语义含义。这些嵌入存储在每个流程的内存 FAISS 向量存储中,以及有关元素类型、源本体和完整定义的元数据。嵌入器会自动从第一个嵌入响应中检测嵌入维度。 + +**主要操作**: +从元素 ID、标签和注释创建文本表示 +通过 EmbeddingsClientSpec 生成嵌入(使用 asyncio.gather 进行批量处理) +将嵌入以及全面的元数据存储在 FAISS 向量存储中 +按本体、元素类型和元素 ID 进行索引,以便高效检索 +自动检测嵌入维度,用于向量存储初始化 +使用独立的向量存储,处理每个流程的嵌入模型 + +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_embedder.py` + +#### 3. 文本处理器(句子分割器) + +**目的**: 将文本块分解为细粒度的片段,以便进行精确的本体匹配。 + +**实现**: +文本处理器使用 NLTK 进行句子分词和词性标注,将传入的文本块分解为句子。它通过尝试下载 `punkt_tab` 和 `averaged_perceptron_tagger_eng` 来处理 NLTK 版本兼容性,如果需要,可以回退到较旧的版本。每个文本块被拆分为独立的句子,这些句子可以独立地与本体元素进行匹配。 + +**主要操作**: +使用 NLTK 句子分词,将文本拆分为句子 +处理 NLTK 版本兼容性(punkt_tab vs punkt) +创建包含文本和位置信息的 TextSegment 对象 +支持完整的句子和单独的块 + +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/text_processor.py` + +#### 4. 本体选择器 + +**目的**: 识别当前文本块中最相关的本体元素子集。 + +**实现**: +本体选择器使用 FAISS 向量相似性搜索,在文本片段和本体元素之间执行语义匹配。对于文本块中的每个句子,它生成一个嵌入,并在向量存储中搜索最相似的本体元素,使用具有可配置阈值(默认值为 0.3)的余弦相似度。在收集所有相关元素后,它执行全面的依赖关系解析:如果选择了类,则包含其父类;如果选择了属性,则添加其域和范围类。此外,对于每个选定的类,它会自动包含**引用该类的所有属性**(无论是其域还是范围)。这确保了提取过程可以访问所有相关的关系属性。 + +**关键操作**: +为每个文本段(句子)生成嵌入向量 +在 FAISS 向量存储中执行 k 近邻搜索(top_k=10,threshold=0.3) +应用相似度阈值以过滤弱匹配项 +解决依赖关系(父类、领域、范围) +**自动包含与所选类相关的所有属性**(领域/范围匹配) +构建包含所有必需关系的连贯本体子集 +消除多次出现的元素 + +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/ontology_selector.py` + +#### 5. 提示构建 + +**目的**: 创建结构化的提示,引导 LLM 仅提取符合本体的元组。 + +**实现**: +提取服务使用从 `ontology-prompt.md` 加载的 Jinja2 模板,该模板格式化本体子集和文本以供 LLM 提取。该模板使用 Jinja2 语法动态地循环遍历类、对象属性和数据类型属性,并显示它们的描述、领域、范围和层次关系。该提示包含关于仅使用提供的本体元素的严格规则,并请求 JSON 格式的输出以进行一致的解析。 + +**关键操作**: +使用 Jinja2 模板,对本体元素进行循环 +格式化具有父关系(subclass_of)和注释的类 +格式化具有领域/范围约束和注释的属性 +包含明确的提取规则和输出格式要求 +使用模板 ID "extract-with-ontologies" 调用提示服务 + +**模板位置**: `ontology-prompt.md` +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` (build_extraction_variables 方法) + +#### 6. 主提取服务 + +**目的**: 协调所有组件以执行端到端的基于本体的三元组提取。 + +**实现**: +主提取服务 (KgExtractOntology) 是管理完整提取工作流程的编排层。它使用 TrustGraph 的 FlowProcessor 模式,并对每个流程进行组件初始化。当收到本体配置更新时,它会初始化或更新流程特定的组件(本体加载器、嵌入器、文本处理器、选择器)。当接收到用于处理的文本块时,它会协调管道:将文本拆分为段,通过向量搜索找到相关的本体元素,构建受约束的提示,调用提示服务,解析和验证响应,生成本体定义三元组,并发出内容三元组和实体上下文。 + +**提取管道**: +1. 通过 chunks-input 队列接收文本块 +2. 如果需要,初始化流程组件(在第一个块或配置更新时) +3. 使用 NLTK 将文本拆分为句子 +4. 搜索 FAISS 向量存储以查找相关的本体概念 +5. 构建包含自动属性包含的本体子集 +6. 构建 Jinja2 模板的提示变量 +7. 使用 extract-with-ontologies 模板调用提示服务 +8. 将 JSON 响应解析为结构化的三元组 +9. 验证三元组并扩展 URI 为完整的本体 URI +10. 生成本体定义三元组(具有标签/注释/领域/范围的类和属性) +11. 从所有三元组构建实体上下文 +12. 发送到三元组和实体上下文队列 + +**关键特性**: +每个流程的向量存储支持不同的嵌入模型 +通过 config-update 队列驱动的本体更新 +使用本体 URI 自动扩展 URI +将本体元素添加到知识图谱中,包含完整的元数据 +实体上下文包含内容和本体元素 + +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/extract.py` + +### 配置 + +该服务使用 TrustGraph 的标准配置方法,通过命令行参数: + +```bash +kg-extract-ontology \ + --id kg-extract-ontology \ + --pulsar-host localhost:6650 \ + --input-queue chunks \ + --config-input-queue config-update \ + --output-queue triples \ + --entity-contexts-output-queue entity-contexts +``` + +**关键配置参数**: +`similarity_threshold`: 0.3 (默认值,可在代码中配置) +`top_k`: 10 (每个段检索的本体元素数量) +`vector_store`: Per-flow FAISS IndexFlatIP with auto-detected dimensions +`text_processor`: NLTK with punkt_tab sentence tokenization +`prompt_template`: "extract-with-ontologies" (Jinja2 模板) + +**本体配置**: +本体通过 config-update 队列以 type="ontology" 的方式动态加载。 + +### 数据流 + +1. **初始化阶段** (每个流程): + 通过 config-update 队列接收本体配置 + 将本体 JSON 解析为 OntologyClass 和 OntologyProperty 对象 + 使用 EmbeddingsClientSpec 为所有本体元素生成嵌入向量 + 将嵌入向量存储在每个流程的 FAISS 向量存储中 + 从第一个响应中自动检测嵌入维度 + +2. **提取阶段** (每个块): + 从 chunks-input 队列接收块 + 使用 NLTK 将块拆分为句子 + 计算每个句子的嵌入向量 + 在 FAISS 向量存储中搜索相关的本体元素 + 构建包含自动属性的本体子集 + 使用文本和本体构建 Jinja2 模板变量 + 使用 extract-with-ontologies 模板调用提示服务 + 解析 JSON 响应并验证三元组 + 使用本体 URI 扩展 URI + 生成本体定义三元组 + 从所有三元组构建实体上下文 + 发送到 triples 和 entity-contexts 队列 + +### 内存向量存储 + +**目的**: 为本体元素匹配提供快速、基于内存的相似性搜索。 + +**实现: FAISS** + +该系统使用 **FAISS (Facebook AI Similarity Search)**,并使用 IndexFlatIP 进行精确的余弦相似性搜索。 关键特性: + +**IndexFlatIP**: 使用内积进行精确的余弦相似性搜索 +**自动检测**: 从第一个嵌入响应确定维度 +**每个流程的存储**: 每个流程都有独立的向量存储,用于不同的嵌入模型 +**归一化**: 在索引之前,所有向量都进行归一化 +**批量操作**: 适用于初始本体加载的高效批量添加 + +**实现位置**: `trustgraph-flow/trustgraph/extract/kg/ontology/vector_store.py` + +### 本体子集选择算法 + +**目的**: 动态地为每个文本块选择本体中最小的相关部分。 + +**详细算法步骤**: + +1. **文本分割**: + 使用 NLP 句子检测将输入块拆分为句子 + 从每个句子中提取名词短语、动词短语和命名实体 + 创建一个层次结构,保留上下文的段落 + +2. **嵌入生成**: + 为每个文本段(句子和短语)生成向量嵌入 + 使用与本体元素相同的嵌入模型 + 缓存重复段的嵌入,以提高性能 + +3. **相似性搜索**: + 对于每个文本段嵌入,搜索向量存储 + 检索最相似的 k 个(例如,10)本体元素 + 应用相似性阈值(例如,0.7)以过滤弱匹配 + 汇总所有段的结果,跟踪匹配频率 + +4. **依赖关系解析**: + 对于每个选定的类,递归地包含所有父类,直到根类 + 对于每个选定的属性,包含其域和范围类 + 对于反向属性,确保包含两个方向 + 如果本体中存在等效类,则添加它们 + +5. **子集构建**: + 在保留关系的同时,对收集的元素进行去重 + 组织为类、对象属性和数据类型属性 + 确保所有约束和关系都得到保留 + 创建一个自包含的迷你本体,该本体是有效且完整的 + +**示例演示**: +给定的文本: "The brown dog chased the white cat up the tree." +段落: ["brown dog", "white cat", "tree", "chased"] +匹配的元素: [dog (class), cat (class), animal (parent), chases (property)] +依赖关系: [animal (dog 和 cat 的父类), lifeform (animal 的父类)] +最终子集: 包含 animal 层次结构和 chase 关系的完整迷你本体 + +### 三元组验证 + +**目的**: 确保所有提取的三元组严格符合本体约束。 + +**验证算法**: + +1. **类验证 (Class Validation)**: + 验证主体是否是本体子集中定义的类的实例。 + 对于对象属性,验证对象是否也是有效的类实例。 + 检查类名是否与本体的类字典匹配。 + 处理类层次结构 - 子类的实例对于父类的约束有效。 + +2. **属性验证 (Property Validation)**: + 确认谓词是否对应于本体子集中的属性。 + 区分对象属性(实体到实体)和数据类型属性(实体到字面量)。 + 验证属性名称是否完全匹配(如果存在,则考虑命名空间)。 + +3. **域/范围检查 (Domain/Range Checking)**: + 对于每个用作谓语的属性,检索其域和范围。 + 验证主体的类型是否匹配或继承自属性的域。 + 验证对象的类型是否匹配或继承自属性的范围。 + 对于数据类型属性,验证对象是否是具有正确 XSD 类型的字面量。 + +4. **基数验证 (Cardinality Validation)**: + 跟踪每个主体属性的使用计数。 + 检查最小基数 - 确保必需的属性存在。 + 检查最大基数 - 确保属性未被使用太多次。 + 对于函数属性,确保每个主体最多有一个值。 + +5. **数据类型验证 (Datatype Validation)**: + 根据其声明的 XSD 类型解析字面值。 + 验证整数是否为有效数字,日期是否格式正确等。 + 检查字符串模式,如果定义了正则表达式约束。 + 确保 URI 对于 xsd:anyURI 类型是格式正确的。 + +**验证示例 (Validation Example)**: +三元组: ("Buddy", "has-owner", "John") +检查 "Buddy" 是否被标记为可以具有 "has-owner" 属性的类。 +检查 "has-owner" 是否存在于本体中。 +验证域约束:主体必须是 "Pet" 类型或子类型。 +验证范围约束:对象必须是 "Person" 类型或子类型。 +如果有效,则添加到输出;如果无效,则记录违规并跳过。 + +## 性能考虑 (Performance Considerations) + +### 优化策略 (Optimisation Strategies) + +1. **嵌入缓存 (Embedding Caching)**: 缓存常用文本片段的嵌入。 +2. **批量处理 (Batch Processing)**: 并行处理多个片段。 +3. **向量存储索引 (Vector Store Indexing)**: 使用近似最近邻算法进行大型本体。 +4. **提示优化 (Prompt Optimisation)**: 通过仅包含必要的本体元素来最小化提示大小。 +5. **结果缓存 (Result Caching)**: 缓存相同块的提取结果。 + +### 可扩展性 (Scalability) + +**水平扩展 (Horizontal Scaling)**: 具有共享本体缓存的多个提取器实例。 +**本体分区 (Ontology Partitioning)**: 通过域分割大型本体。 +**流式处理 (Streaming Processing)**: 在不进行批处理的情况下处理到达的块。 +**内存管理 (Memory Management)**: 定期清理未使用的嵌入。 + +## 错误处理 (Error Handling) + +### 故障场景 (Failure Scenarios) + +1. **缺少本体 (Missing Ontologies)**: 回退到不受约束的提取。 +2. **嵌入服务故障 (Embedding Service Failure)**: 使用缓存的嵌入或跳过语义匹配。 +3. **提示服务超时 (Prompt Service Timeout)**: 使用指数退避重试。 +4. **无效三元组格式 (Invalid Triple Format)**: 记录并跳过格式错误的元组。 +5. **本体不一致 (Ontology Inconsistencies)**: 报告冲突并使用最具体的有效元素。 + +### 监控 (Monitoring) + +需要跟踪的关键指标: + +本体加载时间和内存使用情况。 +嵌入生成延迟。 +向量搜索性能。 +提示服务响应时间。 +三元组提取准确性。 +本体符合性率。 + +## 迁移路径 (Migration Path) + +### 从现有提取器 (From Existing Extractors) + +1. **并行运行 (Parallel Operation)**: 初始阶段与现有提取器并行运行。 +2. **逐步推广 (Gradual Rollout)**: 从特定文档类型开始。 +3. **质量比较 (Quality Comparison)**: 将输出质量与现有提取器进行比较。 +4. **完全迁移 (Full Migration)**: 在验证质量后,替换现有提取器。 + +### 本体开发 (Ontology Development) + +1. **从现有知识生成初始本体 (Bootstrap from Existing)**: 从现有知识生成初始本体。 +2. **基于提取模式进行迭代改进 (Iterative Refinement)**: 基于提取模式进行迭代改进。 +3. **领域专家审查 (Domain Expert Review)**: 由领域专家进行验证。 +4. **基于提取反馈进行持续改进 (Continuous Improvement)**: 基于提取反馈进行持续改进。 + +## 基于本体的查询服务 (Ontology-Sensitive Query Service) + +### 概述 (Overview) + +基于本体的查询服务提供多种查询路径,以支持不同的后端图存储。它利用本体知识,为 Cassandra(通过 SPARQL)和基于 Cypher 的图存储(Neo4j、Memgraph、FalkorDB)提供精确、语义化的问答功能。 + +**服务组件 (Service Components)**: +`onto-query-sparql`: 将自然语言转换为 Cassandra 的 SPARQL。 +`sparql-cassandra`: 用于 Cassandra 的 rdflib 的 SPARQL 查询层。 +`onto-query-cypher`: 将自然语言转换为图数据库的 Cypher。 +`cypher-executor`: 用于 Neo4j/Memgraph/FalkorDB 的 Cypher 查询执行。 + +### 架构 + +``` + ┌─────────────────┐ + │ User Query │ + └────────┬────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Question │────▶│ Sentence │ + │ Analyser │ │ Splitter │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Ontology │────▶│ Vector │ + │ Matcher │ │ Store │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Backend Router │ + └────────┬────────┘ + │ + ┌───────────┴───────────┐ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ onto-query- │ │ onto-query- │ + │ sparql │ │ cypher │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ SPARQL │ │ Cypher │ + │ Generator │ │ Generator │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ sparql- │ │ cypher- │ + │ cassandra │ │ executor │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Cassandra │ │ Neo4j/Memgraph/ │ + │ │ │ FalkorDB │ + └────────┬────────┘ └────────┬────────┘ + │ │ + └────────────┬───────────────┘ + │ + ▼ + ┌─────────────────┐ ┌──────────────┐ + │ Answer │────▶│ Prompt │ + │ Generator │ │ Service │ + └────────┬────────┘ └──────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Final Answer │ + └─────────────────┘ +``` + +### 查询处理流程 + +#### 1. 问题分析器 + +**目的**: 将用户问题分解为语义组件,用于本体匹配。 + +**算法描述**: +问题分析器接收输入的自然语言问题,并使用与提取流程相同的句子分割方法将其分解为有意义的片段。它识别问题中提到的关键实体、关系和约束。每个片段都用于分析问题类型(事实、聚合、比较等)以及预期的答案格式。这种分解有助于确定本体的哪些部分最相关,以回答问题。 + +**主要操作**: +将问题拆分为句子和短语 +识别问题类型和意图 +提取提到的实体和关系 +检测问题中的约束和过滤器 +确定预期的答案格式 + +#### 2. 用于查询的本体匹配器 + +**目的**: 识别回答问题所需的相关的本体子集。 + +**算法描述**: +与提取流程中的本体选择器类似,但针对问题解答进行了优化。匹配器为问题片段生成嵌入向量,并在向量存储中搜索相关的本体元素。但是,它侧重于找到用于查询构造的概念,而不是提取。它扩展选择范围,包括可能在图探索过程中被遍历的关联属性,即使这些属性没有明确地在问题中提到。例如,如果询问“员工”,它可能包括“工作单位”、“管理”、“汇报”等属性,这些属性可能与查找员工信息相关。 + +**匹配策略**: +嵌入问题片段 +查找直接提到的本体概念 +包含连接到提到的类的属性 +添加反向和相关属性以进行遍历 +包含父/子类以进行层次查询 +构建面向查询的本体分区 + +#### 3. 后端路由器 + +**目的**: 根据配置,将查询路由到适当的后端特定的查询路径。 + +**算法描述**: +后端路由器检查系统配置以确定哪个图后端处于活动状态(Cassandra 或 Cypher 驱动)。它将问题和本体分区路由到适当的查询生成服务。路由器还可以支持跨多个后端进行负载平衡,或者在主后端不可用时提供回退机制。 + +**路由逻辑**: +检查系统设置中配置的后端类型 +路由到 `onto-query-sparql` 用于 Cassandra 后端 +路由到 `onto-query-cypher` 用于 Neo4j/Memgraph/FalkorDB +支持具有查询分发的多个后端配置 +处理故障转移和负载平衡场景 + +#### 4. SPARQL 查询生成 (`onto-query-sparql`) + +**目的**: 将自然语言问题转换为 SPARQL 查询,以便在 Cassandra 上执行。 + +**算法描述**: +SPARQL 查询生成器接收问题和本体分区,并构造一个针对 Cassandra 后端优化的 SPARQL 查询。它使用带有 SPARQL 特定模板的提示服务,该模板包含 RDF/OWL 语义。该生成器理解 SPARQL 模式,例如属性路径、可选子句和过滤器,这些模式可以有效地转换为 Cassandra 操作。 + +**SPARQL 生成提示模板**: +``` +Generate a SPARQL query for the following question using the provided ontology. + +ONTOLOGY CLASSES: +{classes} + +ONTOLOGY PROPERTIES: +{properties} + +RULES: +- Use proper RDF/OWL semantics +- Include relevant prefixes +- Use property paths for hierarchical queries +- Add FILTER clauses for constraints +- Optimise for Cassandra backend + +QUESTION: {question} + +SPARQL QUERY: +``` + +#### 5. Cypher 查询生成 (`onto-query-cypher`) + +**目的**: 将自然语言问题转换为用于图数据库的 Cypher 查询。 + +**算法描述**: +Cypher 查询生成器创建针对 Neo4j、Memgraph 和 FalkorDB 优化的原生 Cypher 查询。它将本体类映射到节点标签,并将属性映射到关系,使用 Cypher 的模式匹配语法。该生成器包含 Cypher 专有的优化,例如关系方向提示、索引使用和查询计划提示。 + +**Cypher 生成提示模板**: +``` +Generate a Cypher query for the following question using the provided ontology. + +NODE LABELS (from classes): +{classes} + +RELATIONSHIP TYPES (from properties): +{properties} + +RULES: +- Use MATCH patterns for graph traversal +- Include WHERE clauses for filters +- Use aggregation functions when needed +- Optimise for graph database performance +- Consider index hints for large datasets + +QUESTION: {question} + +CYPHER QUERY: +``` + +#### 6. SPARQL-Cassandra 查询引擎 (`sparql-cassandra`) + +**目的**: 使用 Python rdflib 对 Cassandra 执行 SPARQL 查询。 + +**算法描述**: +SPARQL-Cassandra 引擎使用 Python 的 rdflib 库实现了一个 SPARQL 处理器,并具有自定义的 Cassandra 后端存储。它将 SPARQL 图模式转换为适当的 Cassandra CQL 查询,处理连接、过滤器和聚合。该引擎维护一个 RDF 到 Cassandra 的映射,该映射保留了语义结构,同时针对 Cassandra 的列族存储模型进行了优化。 + +**实现特性**: +用于 Cassandra 的 rdflib Store 接口实现 +支持常见的 SPARQL 1.1 查询模式 +将三元组模式高效地转换为 CQL +支持属性路径和分层查询 +用于大型数据集的结果流式传输 +连接池和查询缓存 + +**示例翻译**: +```sparql +SELECT ?animal WHERE { + ?animal rdf:type :Animal . + ?animal :hasOwner "John" . +} +``` +将其翻译为针对 Cassandra 的优化查询,利用索引和分区键。 + +#### 7. Cypher 查询执行器 (`cypher-executor`) + +**目的**: 对 Neo4j、Memgraph 和 FalkorDB 执行 Cypher 查询。 + +**算法描述**: +Cypher 执行器提供了一个统一的接口,用于在不同的图数据库上执行 Cypher 查询。它处理特定于数据库的连接协议、查询优化提示以及结果格式标准化。执行器包括针对每种数据库类型的重试逻辑、连接池和事务管理。 + +**多数据库支持**: +**Neo4j**: Bolt 协议、事务函数、索引提示 +**Memgraph**: 自定义协议、流式结果、分析查询 +**FalkorDB**: Redis 协议适配、内存优化 + +**执行特性**: +数据库无关的连接管理 +查询验证和语法检查 +超时和资源限制强制 +结果分页和流式传输 +按数据库类型进行性能监控 +数据库实例之间的自动故障转移 + +#### 8. 答案生成器 + +**目的**: 从查询结果中合成自然语言答案。 + +**算法描述**: +答案生成器接收结构化的查询结果和原始问题,然后使用提示服务生成一个全面的答案。与简单的基于模板的响应不同,它使用 LLM 来在问题的上下文中解释图数据,处理复杂的关联、聚合和推断。生成器可以通过引用本体结构和从图中检索的特定三元组来解释其推理过程。 + +**答案生成过程**: +将查询结果格式化为结构化上下文 +包含相关的本体定义以提高清晰度 +构建包含问题和结果的提示 +通过 LLM 生成自然语言答案 +验证答案是否符合查询意图 +如果需要,添加指向特定图实体的引用 + +### 与现有服务的集成 + +#### 与 GraphRAG 的关系 + +**互补**: onto-query 提供语义精度,而 GraphRAG 提供广泛的覆盖范围 +**共享基础设施**: 两者都使用相同的知识图谱和提示服务 +**查询路由**: 系统可以根据问题类型将查询路由到最合适的服务 +**混合模式**: 可以结合两种方法来获得全面的答案 + +#### 与 OntoRAG 提取的关系 + +**共享本体**: 使用与 kg-extract-ontology 加载的相同的本体配置 +**共享向量存储**: 重用提取服务中的内存嵌入 +**一致的语义**: 查询在具有相同本体约束的图上运行 + +### 查询示例 + +#### 示例 1: 简单实体查询 +**问题**: "哪些动物是哺乳动物?" +**本体匹配**: [animal, mammal, subClassOf] +**生成的查询**: +```cypher +MATCH (a:animal)-[:subClassOf*]->(m:mammal) +RETURN a.name +``` + +#### 示例 2:关系查询 +**问题**: "哪些文档是由 John Smith 撰写的?" +**本体匹配**: [document, person, has-author] +**生成的查询**: +```cypher +MATCH (d:document)-[:has-author]->(p:person {name: "John Smith"}) +RETURN d.title, d.date +``` + +#### 示例 3:聚合查询 +**问题**: "猫有多少条腿?" +**本体匹配**: [猫, 腿的数量 (数据类型属性)] +**生成的查询**: +```cypher +MATCH (c:cat) +RETURN c.name, c.number_of_legs +``` + +### 配置 + +```yaml +onto-query: + embedding_model: "text-embedding-3-small" + vector_store: + shared_with_extractor: true # Reuse kg-extract-ontology's store + query_builder: + model: "gpt-4" + temperature: 0.1 + max_query_length: 1000 + graph_executor: + timeout: 30000 # ms + max_results: 1000 + answer_generator: + model: "gpt-4" + temperature: 0.3 + max_tokens: 500 +``` + +### 性能优化 + +#### 查询优化 + +**本体图剪枝**: 仅在提示中包含必要的本体图元素 +**查询缓存**: 缓存常见问题及其查询 +**结果缓存**: 存储相同查询的结果,并在指定时间窗口内 +**批量处理**: 使用单次图遍历处理多个相关问题 + +#### 可扩展性考虑 + +**分布式执行**: 在图分区上并行化子查询 +**增量结果**: 为大型数据集流式传输结果 +**负载均衡**: 在多个服务实例之间分配查询负载 +**资源池**: 管理到图数据库的连接池 + +### 错误处理 + +#### 故障场景 + +1. **无效查询生成**: 回退到 GraphRAG 或简单的关键词搜索 +2. **本体图不匹配**: 扩展搜索范围到更广泛的本体图子集 +3. **查询超时**: 简化查询或增加超时时间 +4. **无结果**: 建议重新构建查询或提供相关问题 +5. **LLM 服务故障**: 使用缓存的查询或基于模板的响应 + +### 监控指标 + +问题复杂性分布 +本体图分区大小 +查询生成成功率 +图查询执行时间 +答案质量分数 +缓存命中率 +按类型划分的错误频率 + +## 未来增强功能 + +1. **本体图学习**: 根据提取模式自动扩展本体图 +2. **置信度评分**: 为提取的三元组分配置信度分数 +3. **解释生成**: 提供三元组提取的推理 +4. **主动学习**: 请求人工验证不确定的提取结果 + +## 安全性考虑 + +1. **防止提示注入**: 在构建提示之前,清理文本块 +2. **资源限制**: 限制向量存储的内存使用量 +3. **速率限制**: 限制每个客户端的提取请求 +4. **审计日志**: 跟踪所有提取请求和结果 + +## 测试策略 + +### 单元测试 + +带各种格式的本体图加载器 +嵌入式生成和存储 +句子分割算法 +向量相似度计算 +三元组解析和验证 + +### 集成测试 + +端到端提取管道 +配置服务集成 +提示服务交互 +并发提取处理 + +### 性能测试 + +处理大型本体图(1000+ 个类) +处理大量文本块 +负载下的内存使用情况 +延迟基准测试 + +## 发布计划 + +### 概述 + +OntoRAG 系统将分四个主要阶段交付,每个阶段都提供增量价值,并逐步构建到完整的系统。 该计划侧重于首先建立核心提取功能,然后添加查询功能,然后是优化和高级功能。 + +### 第一阶段:基础和核心提取 + +**目标**: 建立基于本体图驱动的基本提取管道,并使用简单的向量匹配。 + +#### 第一步:本体图管理基础 +实现本体图配置加载器 (`OntologyLoader`) +解析和验证本体图 JSON 结构 +创建内存中的本体图存储和访问模式 +实现本体图刷新机制 + +**成功标准**: +成功加载和解析本体图配置 +验证本体图结构和一致性 +处理多个并发本体图 + +#### 第二步:向量存储实现 +实现简单的基于 NumPy 的向量存储作为初始原型 +添加 FAISS 向量存储实现 +创建向量存储接口抽象 +实现具有可配置阈值的相似度搜索 + +**成功标准**: +高效地存储和检索嵌入向量 +以<100毫秒的延迟执行相似性搜索 +支持NumPy和FAISS后端 + +#### 步骤 1.3:本体嵌入管道 +与嵌入服务集成 +实现 `OntologyEmbedder` 组件 +为所有本体元素生成嵌入向量 +将嵌入向量及其元数据存储在向量存储中 + +**成功标准**: +为类和属性生成嵌入向量 +存储带有适当元数据的嵌入向量 +在本体更新时重建嵌入向量 + +#### 步骤 1.4:文本处理组件 +使用NLTK/spaCy实现句子分割器 +提取短语和命名实体 +创建文本段层级结构 +为文本段生成嵌入向量 + +**成功标准**: +准确地将文本分割成句子 +提取有意义的短语 +维护上下文关系 + +#### 步骤 1.5:本体选择算法 +实现文本与本体之间的相似性匹配 +构建本体元素的依赖关系解析 +创建最小的、连贯的本体子集 +优化子集生成性能 + +**成功标准**: +使用>80%的精度选择相关的本体元素 +包含所有必要的依赖项 +在<500毫秒内生成子集 + +#### 步骤 1.6:基本提取服务 +实现用于提取的提示构建 +与提示服务集成 +解析和验证三元组响应 +创建 `kg-extract-ontology` 服务端点 + +**成功标准**: +提取符合本体的三元组 +验证所有三元组与本体 +优雅地处理提取错误 + +### 第二阶段:查询系统实现 + +**目标**: 添加具有对多个后端支持的本体感知查询功能。 + +#### 步骤 2.1:查询基础组件 +实现问题分析器 +创建用于查询的本体匹配器 +调整向量搜索以适应查询上下文 +构建后端路由器组件 + +**成功标准**: +将问题分析成语义组件 +将问题与相关的本体元素匹配 +将查询路由到适当的后端 + +#### 步骤 2.2:SPARQL路径实现 +实现 `onto-query-sparql` 服务 +使用LLM创建SPARQL查询生成器 +开发用于SPARQL生成的提示模板 +验证生成的SPARQL语法 + +**成功标准**: +生成有效的SPARQL查询 +使用适当的SPARQL模式 +处理复杂的查询类型 + +#### 步骤 2.3:SPARQL-Cassandra引擎 +为Cassandra实现rdflib Store接口 +创建CQL查询翻译器 +优化三元组模式匹配 +处理SPARQL结果格式 + +**成功标准**: +在Cassandra上执行SPARQL查询 +支持常见的SPARQL模式 +以标准格式返回结果 + +#### 步骤 2.4:Cypher路径实现 +实现 `onto-query-cypher` 服务 +使用LLM创建Cypher查询生成器 +开发用于Cypher生成的提示模板 +验证生成的Cypher语法 + +**成功标准**: +生成有效的Cypher查询 +使用适当的图模式 +支持Neo4j、Memgraph、FalkorDB + +#### 步骤 2.5:Cypher执行器 +Implement multi-database Cypher executor +Support Bolt protocol (Neo4j/Memgraph) +Support Redis protocol (FalkorDB) +Handle result normalization + +**Success Criteria**: +Execute Cypher on all target databases +Handle database-specific differences +Maintain connection pools efficiently + +#### Step 2.6: Answer Generation +Implement answer generator component +Create prompts for answer synthesis +Format query results for LLM consumption +Generate natural language answers + +**Success Criteria**: +Generate accurate answers from query results +Maintain context from original question +Provide clear, concise responses + +### Phase 3: Optimization and Robustness + +**Goal**: Optimize performance, add caching, improve error handling, and enhance reliability. + +#### Step 3.1: Performance Optimization +Implement embedding caching +Add query result caching +Optimize vector search with FAISS IVF indexes +Implement batch processing for embeddings + +**Success Criteria**: +Reduce average query latency by 50% +Support 10x more concurrent requests +Maintain sub-second response times + +#### Step 3.2: Advanced Error Handling +Implement comprehensive error recovery +Add fallback mechanisms between query paths +Create retry logic with exponential backoff +Improve error logging and diagnostics + +**Success Criteria**: +Gracefully handle all failure scenarios +Automatic failover between backends +Detailed error reporting for debugging + +#### Step 3.3: Monitoring and Observability +Add performance metrics collection +Implement query tracing +Create health check endpoints +Add resource usage monitoring + +**Success Criteria**: +Track all key performance indicators +Identify bottlenecks quickly +Monitor system health in real-time + +#### Step 3.4: Configuration Management +Implement dynamic configuration updates +Add configuration validation +Create configuration templates +Support environment-specific settings + +**Success Criteria**: +Update configuration without restart +Validate all configuration changes +Support multiple deployment environments + +### Phase 4: Advanced Features + +**Goal**: Add sophisticated capabilities for production deployment and enhanced functionality. + +#### Step 4.1: Multi-Ontology Support +Implement ontology selection logic +Support cross-ontology queries +Handle ontology versioning +Create ontology merge capabilities + +**Success Criteria**: +Query across multiple ontologies +Handle ontology conflicts +Support ontology evolution + +#### Step 4.2: Intelligent Query Routing +Implement performance-based routing +Add query complexity analysis +Create adaptive routing algorithms +Support A/B testing for paths + +**Success Criteria**: +Route queries optimally +Learn from query performance +Improve routing over time + +#### Step 4.3: Advanced Extraction Features +Add confidence scoring for triples +Implement explanation generation +Create feedback loops for improvement +Support incremental learning + +**Success Criteria**: +Provide confidence scores +Explain extraction decisions +Continuously improve accuracy + +#### Step 4.4: Production Hardening +Add rate limiting +Implement authentication/authorization +Create deployment automation +Add backup and recovery + +**Success Criteria**: +Production-ready security +Automated deployment pipeline +Disaster recovery capability + +### Delivery Milestones + +1. **Milestone 1** (End of Phase 1): Basic ontology-driven extraction operational +2. **Milestone 2** (End of Phase 2): Full query system with both SPARQL and Cypher paths +3. **Milestone 3** (End of Phase 3): Optimized, robust system ready for staging +4. **Milestone 4** (End of Phase 4): Production-ready system with advanced features + +### Risk Mitigation + +#### Technical Risks +**Vector Store Scalability**: Start with NumPy, migrate to FAISS gradually +**Query Generation Accuracy**: Implement validation and fallback mechanisms +**Backend Compatibility**: Test extensively with each database type +**Performance Bottlenecks**: Profile early and often, optimize iteratively + +#### Operational Risks +**Ontology Quality**: Implement validation and consistency checking +**Service Dependencies**: Add circuit breakers and fallbacks +**Resource Constraints**: Monitor and set appropriate limits +**Data Consistency**: Implement proper transaction handling + +### Success Metrics + +#### Phase 1 Success Metrics +Extraction accuracy: >90% ontology conformance +Processing speed: <1 second per chunk +Ontology load time: <10 seconds +Vector search latency: <100ms + +#### Phase 2 Success Metrics +Query success rate: >95% +Query latency: <2 seconds end-to-end +Backend compatibility: 100% for target databases +Answer accuracy: >85% based on available data + +#### Phase 3 Success Metrics +System uptime: >99.9% +Error recovery rate: >95% +Cache hit rate: >60% +Concurrent users: >100 + +#### Phase 4 Success Metrics +Multi-ontology queries: Fully supported +Routing optimization: 30% latency reduction +Confidence scoring accuracy: >90% +Production deployment: Zero-downtime updates + +## References + +[OWL 2 Web Ontology Language](https://www.w3.org/TR/owl2-overview/) +[GraphRAG Architecture](https://github.com/microsoft/graphrag) +[Sentence Transformers](https://www.sbert.net/) +[FAISS Vector Search](https://github.com/facebookresearch/faiss) +[spaCy NLP Library](https://spacy.io/) +[rdflib Documentation](https://rdflib.readthedocs.io/) +[Neo4j Bolt Protocol](https://neo4j.com/docs/bolt/current/) diff --git a/docs/tech-specs/openapi-spec.ar.md b/docs/tech-specs/openapi-spec.ar.md new file mode 100644 index 00000000..71a88412 --- /dev/null +++ b/docs/tech-specs/openapi-spec.ar.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "مواصفات OpenAPI - المواصفات الفنية" +parent: "Arabic (Beta)" +--- + +# مواصفات OpenAPI - المواصفات الفنية + +> **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. + +## الهدف + +إنشاء مواصفات OpenAPI 3.1 شاملة وقابلة للتطوير لواجهة TrustGraph REST API التي: +توثق جميع نقاط النهاية REST. +تستخدم `$ref` خارجية من أجل modularity وقابلية الصيانة. +تتوافق مباشرة مع كود مترجم الرسائل. +توفر مخططات دقيقة للطلبات والاستجابات. + +## المصدر الموثوق + +يتم تعريف واجهة برمجة التطبيقات بواسطة: +**مترجمو الرسائل**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**مدير الموزع**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**مدير نقطة النهاية**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## هيكل الدليل + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## ربط الخدمات + +### الخدمات العامة (`/api/v1/{kind}`) +`config` - إدارة التكوين +`flow` - دورة حياة التدفق +`librarian` - مكتبة المستندات +`knowledge` - نوى المعرفة +`collection-management` - بيانات وصفية للمجموعة + +### الخدمات المستضافة على التدفق (`/api/v1/flow/{flow}/service/{kind}`) + +**الطلب/الاستجابة:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**إرسال واستقبال:** +`text-load`, `document-load` + +### الاستيراد/التصدير +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### أخرى +`/api/v1/socket` (WebSocket متعدد) +`/api/metrics` (Prometheus) + +## النهج + +### المرحلة الأولى: الإعداد +1. إنشاء هيكل الدليل +2. إنشاء ملف رئيسي `openapi.yaml` مع البيانات الوصفية والخوادم والأمان +3. إنشاء مكونات قابلة لإعادة الاستخدام (أخطاء، معلمات شائعة، مخططات أمان) + +### المرحلة الثانية: المخططات الشائعة +إنشاء مخططات مشتركة تستخدم عبر الخدمات: +`RdfValue`, `Triple` - هياكل RDF/ثلاثية +`ErrorObject` - استجابة الخطأ +`DocumentMetadata`, `ProcessingMetadata` - هياكل البيانات الوصفية +المعلمات الشائعة: `FlowId`, `User`, `Collection` + +### المرحلة الثالثة: الخدمات العامة +لكل خدمة عامة (تكوين، تدفق، أمين مكتبة، معرفة، إدارة المجموعة): +1. إنشاء ملف مسار في `paths/` +2. إنشاء مخطط الطلب في `components/schemas/{service}/` +3. إنشاء مخطط الاستجابة +4. إضافة أمثلة +5. الإشارة من الملف الرئيسي `openapi.yaml` + +### المرحلة الرابعة: الخدمات المستضافة على التدفق +لكل خدمة مستضافة على التدفق: +1. إنشاء ملف مسار في `paths/flow-services/` +2. إنشاء مخططات الطلب/الاستجابة في `components/schemas/ai-services/` +3. إضافة وثائق علامة التدفق حيثما ينطبق +4. الإشارة من الملف الرئيسي `openapi.yaml` + +### المرحلة الخامسة: الاستيراد/التصدير و WebSocket +1. توثيق نقاط النهاية الأساسية للاستيراد/التصدير +2. توثيق أنماط بروتوكول WebSocket +3. توثيق نقاط نهاية استيراد/تصدير WebSocket على مستوى التدفق + +### المرحلة السادسة: التحقق من الصحة +1. التحقق من الصحة باستخدام أدوات التحقق من صحة OpenAPI +2. الاختبار باستخدام واجهة Swagger UI +3. التحقق من تغطية جميع المترجمين + +## اصطلاح تسمية الحقول + +جميع الحقول في JSON تستخدم **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`، إلخ. + +## إنشاء ملفات المخططات + +لكل مترجم في `trustgraph-base/trustgraph/messaging/translators/`: + +1. **قراءة طريقة مترجم `to_pulsar()`** - يحدد مخطط الطلب +2. **قراءة طريقة مترجم `from_pulsar()`** - يحدد مخطط الاستجابة +3. **استخراج أسماء وأنواع الحقول** +4. **إنشاء مخطط OpenAPI** مع: + أسماء الحقول (kebab-case) + الأنواع (سلسلة، عدد صحيح، منطقي، كائن، مصفوفة) + الحقول المطلوبة + القيم الافتراضية + الأوصاف + +### مثال لعملية التعيين + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +الترجمة: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## الاستجابات المتدفقة + +الخدمات التي تدعم التدفق تُرجع استجابات متعددة مع العلامة `end_of_stream`: +`agent`، `text-completion`، `prompt` +`document-rag`، `graph-rag` + +قم بتوثيق هذا النمط في مخطط استجابة كل خدمة. + +## استجابات الأخطاء + +يمكن لجميع الخدمات إرجاع: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +حيث أن `ErrorObject` هو: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## المراجع + +المترجمون: `trustgraph-base/trustgraph/messaging/translators/` +تعيين الموزع: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +توجيه نقطة النهاية: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +ملخص الخدمة: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.es.md b/docs/tech-specs/openapi-spec.es.md new file mode 100644 index 00000000..e9354fc4 --- /dev/null +++ b/docs/tech-specs/openapi-spec.es.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "Especificación OpenAPI - Especificación Técnica" +parent: "Spanish (Beta)" +--- + +# Especificación OpenAPI - Especificación Técnica + +> **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. + +## Objetivo + +Crear una especificación OpenAPI 3.1 completa y modular para la puerta de enlace de la API REST de TrustGraph que: +Documente todos los puntos finales REST. +Utilice `$ref` externo para la modularidad y el mantenimiento. +Se mapee directamente con el código del traductor de mensajes. +Proporcione esquemas precisos de solicitud/respuesta. + +## Fuente de la Verdad + +La API está definida por: +**Traductores de Mensajes**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**Administrador del Despachador**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**Administrador de Puntos Finales**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## Estructura de Directorios + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## Mapeo de Servicios + +### Servicios Globales (`/api/v1/{kind}`) +`config` - Gestión de configuración +`flow` - Ciclo de vida del flujo +`librarian` - Biblioteca de documentos +`knowledge` - Núcleos de conocimiento +`collection-management` - Metadatos de colección + +### Servicios Alojados en el Flujo (`/api/v1/flow/{flow}/service/{kind}`) + +**Solicitud/Respuesta:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**Enviar y Olvidar:** +`text-load`, `document-load` + +### Importación/Exportación +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### Otros +`/api/v1/socket` (WebSocket multiplexado) +`/api/metrics` (Prometheus) + +## Enfoque + +### Fase 1: Configuración +1. Crear estructura de directorios +2. Crear el archivo principal `openapi.yaml` con metadatos, servidores, seguridad +3. Crear componentes reutilizables (errores, parámetros comunes, esquemas de seguridad) + +### Fase 2: Esquemas Comunes +Crear esquemas compartidos utilizados en todos los servicios: +`RdfValue`, `Triple` - Estructuras RDF/triple +`ErrorObject` - Respuesta de error +`DocumentMetadata`, `ProcessingMetadata` - Estructuras de metadatos +Parámetros comunes: `FlowId`, `User`, `Collection` + +### Fase 3: Servicios Globales +Para cada servicio global (configuración, flujo, biblioteca, conocimiento, gestión de colecciones): +1. Crear el archivo de ruta en `paths/` +2. Crear el esquema de solicitud en `components/schemas/{service}/` +3. Crear el esquema de respuesta +4. Agregar ejemplos +5. Referenciar desde el archivo principal `openapi.yaml` + +### Fase 4: Servicios Alojados en el Flujo +Para cada servicio alojado en el flujo: +1. Crear el archivo de ruta en `paths/flow-services/` +2. Crear los esquemas de solicitud/respuesta en `components/schemas/ai-services/` +3. Agregar la documentación de la bandera de transmisión cuando corresponda +4. Referenciar desde el archivo principal `openapi.yaml` + +### Fase 5: Importación/Exportación y WebSocket +1. Documentar los puntos finales principales de importación/exportación +2. Documentar los patrones de protocolo WebSocket +3. Documentar los puntos finales de importación/exportación WebSocket a nivel de flujo + +### Fase 6: Validación +1. Validar con herramientas de validación de OpenAPI +2. Probar con Swagger UI +3. Verificar que todos los traductores estén cubiertos + +## Convención de Nombres de Campos + +Todos los campos JSON utilizan **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, etc. + +## Creación de Archivos de Esquema + +Para cada traductor en `trustgraph-base/trustgraph/messaging/translators/`: + +1. **Leer el método del traductor `to_pulsar()`** - Define el esquema de solicitud +2. **Leer el método del traductor `from_pulsar()`** - Define el esquema de respuesta +3. **Extraer nombres y tipos de campos** +4. **Crear el esquema OpenAPI** con: + Nombres de campos (kebab-case) + Tipos (string, integer, boolean, object, array) + Campos obligatorios + Valores predeterminados + Descripciones + +### Ejemplo de Proceso de Mapeo + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +Traducción: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## Respuestas de transmisión + +Los servicios que admiten la transmisión devuelven múltiples respuestas con la bandera `end_of_stream`: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +Documente este patrón en el esquema de respuesta de cada servicio. + +## Respuestas de error + +Todos los servicios pueden devolver: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +Donde `ErrorObject` es: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## Referencias + +Traductores: `trustgraph-base/trustgraph/messaging/translators/` +Mapeo del despachador: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +Enrutamiento de puntos finales: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +Resumen del servicio: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.he.md b/docs/tech-specs/openapi-spec.he.md new file mode 100644 index 00000000..6e94d44b --- /dev/null +++ b/docs/tech-specs/openapi-spec.he.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "מפרט OpenAPI - מפרט טכני" +parent: "Hebrew (Beta)" +--- + +# מפרט OpenAPI - מפרט טכני + +> **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. + +## מטרה + +ליצור מפרט OpenAPI 3.1 מקיף ומודולרי עבור שער ה-API של TrustGraph REST, אשר: +מתעד את כל נקודות הקצה של REST +משתמש בקוד חיצוני `$ref` לצורך מודולריות ותחזוקה +מתאים ישירות לקוד מתרגם ההודעות +מספק סכימות מדויקות של בקשות/תגובות + +## מקור האמת + +ה-API מוגדר על ידי: +**מתרגמי הודעות**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**מנהל ה-Dispatcher**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**מנהל נקודות הקצה**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## מבנה תיקיות + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## מיפוי שירותים + +### שירותים גלובליים (`/api/v1/{kind}`) +`config` - ניהול תצורה +`flow` - מחזור חיים של זרימה +`librarian` - ספריית מסמכים +`knowledge` - ליבות ידע +`collection-management` - מטא-דאטה של אוסף + +### שירותים המאוחסנים בתוך זרימה (Flow-Hosted Services) (`/api/v1/flow/{flow}/service/{kind}`) + +**בקשה/תגובה:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**שליחה והתעלמות (Fire-and-Forget):** +`text-load`, `document-load` + +### ייבוא/ייצוא +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### אחר +`/api/v1/socket` (WebSocket מרובה) +`/api/metrics` (Prometheus) + +## גישה + +### שלב 1: הגדרה +1. צור מבנה תיקיות +2. צור את הקובץ הראשי `openapi.yaml` עם מטא-דאטה, שרתים, אבטחה +3. צור רכיבים שניתנים לשימוש חוזר (שגיאות, פרמטרים נפוצים, סכימות אבטחה) + +### שלב 2: סכימות נפוצות +צור סכימות משותפות המשמשות בכל השירותים: +`RdfValue`, `Triple` - מבני RDF/טריפל +`ErrorObject` - תגובת שגיאה +`DocumentMetadata`, `ProcessingMetadata` - מבני מטא-דאטה +פרמטרים נפוצים: `FlowId`, `User`, `Collection` + +### שלב 3: שירותים גלובליים +עבור כל שירות גלובלי (תצורה, זרימה, ספרן, ידע, ניהול אוסף): +1. צור קובץ נתיב ב-`paths/` +2. צור סכימת בקשה ב-`components/schemas/{service}/` +3. צור סכימת תגובה +4. הוסף דוגמאות +5. הפנה מהקובץ הראשי `openapi.yaml` + +### שלב 4: שירותים המאוחסנים בתוך זרימה +עבור כל שירות המאוחסן בתוך זרימה: +1. צור קובץ נתיב ב-`paths/flow-services/` +2. צור סכימות בקשה/תגובה ב-`components/schemas/ai-services/` +3. הוסף תיעוד לדגל סטרימינג במידת הצורך +4. הפנה מהקובץ הראשי `openapi.yaml` + +### שלב 5: ייבוא/ייצוא ו-WebSocket +1. תעד נקודות קצה מרכזיות לייבוא/ייצוא +2. תעד תבניות פרוטוקול WebSocket +3. תעד נקודות קצה של ייבוא/ייצוא ברמת הזרימה של WebSocket + +### שלב 6: אימות +1. אמת באמצעות כלי אימות OpenAPI +2. בדוק באמצעות Swagger UI +3. ודא שכל המתרגמים מכוסים + +## מוסכמות מתן שמות לשדות + +כל השדות ב-JSON משתמשים בפורמט **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, וכו'. + +## יצירת קבצי סכימה + +עבור כל מתרגם ב-`trustgraph-base/trustgraph/messaging/translators/`: + +1. **קרא את שיטת המתרגם `to_pulsar()`** - מגדיר סכימת בקשה +2. **קרא את שיטת המתרגם `from_pulsar()`** - מגדיר סכימת תגובה +3. **חלץ שמות שדות וסוגים** +4. **צור סכימה של OpenAPI** עם: + שמות שדות (kebab-case) + סוגים (string, integer, boolean, object, array) + שדות חובה + ערכי ברירת מחדל + תיאורים + +### תהליך מיפוי לדוגמה + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +מתורגם ל: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## תגובות סטרימינג + +שירותים התומכים בסטרימינג מחזירים מספר תגובות עם הדגל `end_of_stream`: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +יש לתעד דפוס זה בסכימת התגובות של כל שירות. + +## תגובות שגיאה + +כל השירותים יכולים להחזיר: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +היכן ש-`ErrorObject` נמצא: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## הפניות + +מתרגמים: `trustgraph-base/trustgraph/messaging/translators/` +מיפוי מפיץ: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +ניתוב נקודת קצה: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +תקציר שירות: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.hi.md b/docs/tech-specs/openapi-spec.hi.md new file mode 100644 index 00000000..254358d5 --- /dev/null +++ b/docs/tech-specs/openapi-spec.hi.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "OpenAPI विनिर्देश - तकनीकी विनिर्देश" +parent: "Hindi (Beta)" +--- + +# OpenAPI विनिर्देश - तकनीकी विनिर्देश + +> **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. + +## लक्ष्य + +ट्रस्टग्राफ REST API गेटवे के लिए एक व्यापक, मॉड्यूलर OpenAPI 3.1 विनिर्देश बनाना जो: +सभी REST एंडपॉइंट्स का दस्तावेजीकरण करता है +मॉड्यूलरिटी और रखरखाव के लिए बाहरी `$ref` का उपयोग करता है +सीधे संदेश अनुवाद कोड से मेल खाता है +सटीक अनुरोध/प्रतिक्रिया स्कीमा प्रदान करता है + +## सत्य का स्रोत + +API को निम्नलिखित द्वारा परिभाषित किया गया है: +**संदेश अनुवादक**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**डिस्पैचर मैनेजर**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**एंडपॉइंट मैनेजर**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## निर्देशिका संरचना + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## सर्विस मैपिंग + +### ग्लोबल सर्विसेज (`/api/v1/{kind}`) +`config` - कॉन्फ़िगरेशन प्रबंधन +`flow` - फ्लो लाइफसाइकिल +`librarian` - दस्तावेज़ लाइब्रेरी +`knowledge` - नॉलेज कोर +`collection-management` - कलेक्शन मेटाडेटा + +### फ्लो-होस्टेड सर्विसेज (`/api/v1/flow/{flow}/service/{kind}`) + +**अनुरोध/प्रतिक्रिया:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**फायर-एंड-फॉरगेट:** +`text-load`, `document-load` + +### इम्पोर्ट/एक्सपोर्ट +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### अन्य +`/api/v1/socket` (WebSocket मल्टीप्लेक्स) +`/api/metrics` (Prometheus) + +## दृष्टिकोण + +### चरण 1: सेटअप +1. डायरेक्टरी संरचना बनाएं +2. मुख्य `openapi.yaml` बनाएं जिसमें मेटाडेटा, सर्वर, सुरक्षा शामिल हो +3. पुन: प्रयोज्य घटक बनाएं (त्रुटियां, सामान्य पैरामीटर, सुरक्षा योजनाएं) + +### चरण 2: सामान्य स्कीमा +साझा स्कीमा बनाएं जिनका उपयोग सेवाओं में किया जाता है: +`RdfValue`, `Triple` - RDF/ट्रिपल संरचनाएं +`ErrorObject` - त्रुटि प्रतिक्रिया +`DocumentMetadata`, `ProcessingMetadata` - मेटाडेटा संरचनाएं +सामान्य पैरामीटर: `FlowId`, `User`, `Collection` + +### चरण 3: ग्लोबल सर्विसेज +प्रत्येक ग्लोबल सर्विस (कॉन्फ़िग, फ्लो, लाइब्रेरियन, नॉलेज, कलेक्शन-मैनेजमेंट) के लिए: +1. `paths/` में पाथ फ़ाइल बनाएं +2. `components/schemas/{service}/` में अनुरोध स्कीमा बनाएं +3. प्रतिक्रिया स्कीमा बनाएं +4. उदाहरण जोड़ें +5. मुख्य `openapi.yaml` से संदर्भ लें + +### चरण 4: फ्लो-होस्टेड सर्विसेज +प्रत्येक फ्लो-होस्टेड सर्विस के लिए: +1. `paths/flow-services/` में पाथ फ़ाइल बनाएं +2. `components/schemas/ai-services/` में अनुरोध/प्रतिक्रिया स्कीमा बनाएं +3. जहां लागू हो, स्ट्रीमिंग फ़्लैग दस्तावेज़ जोड़ें +4. मुख्य `openapi.yaml` से संदर्भ लें + +### चरण 5: इम्पोर्ट/एक्सपोर्ट और WebSocket +1. मुख्य इम्पोर्ट/एक्सपोर्ट एंडपॉइंट्स का दस्तावेज़ बनाएं +2. WebSocket प्रोटोकॉल पैटर्न का दस्तावेज़ बनाएं +3. फ्लो-लेवल इम्पोर्ट/एक्सपोर्ट WebSocket एंडपॉइंट्स का दस्तावेज़ बनाएं + +### चरण 6: सत्यापन +1. OpenAPI सत्यापन उपकरणों के साथ सत्यापित करें +2. Swagger UI के साथ परीक्षण करें +3. सत्यापित करें कि सभी अनुवादक कवर किए गए हैं + +## फ़ील्ड नामकरण सम्मेलन + +सभी JSON फ़ील्ड **केबाब-केस** का उपयोग करते हैं: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, आदि। + +## स्कीमा फ़ाइलें बनाना + +प्रत्येक अनुवादक के लिए `trustgraph-base/trustgraph/messaging/translators/`: + +1. **अनुवादक `to_pulsar()` विधि पढ़ें** - अनुरोध स्कीमा को परिभाषित करता है +2. **अनुवादक `from_pulsar()` विधि पढ़ें** - प्रतिक्रिया स्कीमा को परिभाषित करता है +3. **फ़ील्ड नाम और प्रकार निकालें** +4. **OpenAPI स्कीमा बनाएं** जिसमें: + फ़ील्ड नाम (केबाब-केस) + प्रकार (स्ट्रिंग, पूर्णांक, बूलियन, ऑब्जेक्ट, सरणी) + आवश्यक फ़ील्ड + डिफ़ॉल्ट + विवरण + +### उदाहरण मैपिंग प्रक्रिया + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +अनुवाद: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## स्ट्रीमिंग प्रतिक्रियाएं + +वे सेवाएं जो स्ट्रीमिंग का समर्थन करती हैं, वे `end_of_stream` ध्वज के साथ कई प्रतिक्रियाएं लौटाती हैं: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +इस पैटर्न को प्रत्येक सेवा की प्रतिक्रिया स्कीमा में प्रलेखित करें। + +## त्रुटि प्रतिक्रियाएं + +सभी सेवाएं निम्नलिखित लौटा सकती हैं: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +जहाँ `ErrorObject` है: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## संदर्भ + +अनुवादक: `trustgraph-base/trustgraph/messaging/translators/` +डिस्पैचर मैपिंग: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +एंडपॉइंट रूटिंग: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +सेवा सारांश: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.md b/docs/tech-specs/openapi-spec.md index ec82681d..b6e8f876 100644 --- a/docs/tech-specs/openapi-spec.md +++ b/docs/tech-specs/openapi-spec.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "OpenAPI Specification - Technical Spec" +parent: "Tech Specs" +--- + # OpenAPI Specification - Technical Spec ## Goal diff --git a/docs/tech-specs/openapi-spec.pt.md b/docs/tech-specs/openapi-spec.pt.md new file mode 100644 index 00000000..aa807ff4 --- /dev/null +++ b/docs/tech-specs/openapi-spec.pt.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "Especificação OpenAPI - Especificação Técnica" +parent: "Portuguese (Beta)" +--- + +# Especificação OpenAPI - Especificação Técnica + +> **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. + +## Objetivo + +Criar uma especificação OpenAPI 3.1 abrangente e modular para o Gateway de API REST TrustGraph que: +Documenta todos os endpoints REST +Utiliza `$ref` externo para modularidade e manutenção +Mapeia diretamente para o código do tradutor de mensagens +Fornece esquemas precisos de requisição/resposta + +## Fonte da Verdade + +A API é definida por: +**Tradutores de Mensagens**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**Gerenciador de Dispatcher**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**Gerenciador de Endpoint**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## Estrutura de Diretórios + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## Mapeamento de Serviços + +### Serviços Globais (`/api/v1/{kind}`) +`config` - Gerenciamento de configuração +`flow` - Ciclo de vida do fluxo +`librarian` - Biblioteca de documentos +`knowledge` - Núcleos de conhecimento +`collection-management` - Metadados de coleção + +### Serviços Hospedados em Fluxo (`/api/v1/flow/{flow}/service/{kind}`) + +**Requisição/Resposta:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**Enviar e Esquecer:** +`text-load`, `document-load` + +### Importação/Exportação +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### Outros +`/api/v1/socket` (WebSocket multiplexado) +`/api/metrics` (Prometheus) + +## Abordagem + +### Fase 1: Configuração +1. Criar estrutura de diretórios +2. Criar o arquivo principal `openapi.yaml` com metadados, servidores, segurança +3. Criar componentes reutilizáveis (erros, parâmetros comuns, esquemas de segurança) + +### Fase 2: Esquemas Comuns +Criar esquemas compartilhados usados em todos os serviços: +`RdfValue`, `Triple` - Estruturas RDF/triplas +`ErrorObject` - Resposta de erro +`DocumentMetadata`, `ProcessingMetadata` - Estruturas de metadados +Parâmetros comuns: `FlowId`, `User`, `Collection` + +### Fase 3: Serviços Globais +Para cada serviço global (configuração, fluxo, bibliotecário, conhecimento, gerenciamento de coleção): +1. Criar arquivo de caminho em `paths/` +2. Criar esquema de solicitação em `components/schemas/{service}/` +3. Criar esquema de resposta +4. Adicionar exemplos +5. Referenciar do arquivo principal `openapi.yaml` + +### Fase 4: Serviços Hospedados em Fluxo +Para cada serviço hospedado em fluxo: +1. Criar arquivo de caminho em `paths/flow-services/` +2. Criar esquemas de solicitação/resposta em `components/schemas/ai-services/` +3. Adicionar documentação da flag de streaming, quando aplicável +4. Referenciar do arquivo principal `openapi.yaml` + +### Fase 5: Importação/Exportação e WebSocket +1. Documentar os principais endpoints de importação/exportação +2. Documentar os padrões de protocolo WebSocket +3. Documentar os endpoints de importação/exportação WebSocket no nível do fluxo + +### Fase 6: Validação +1. Validar com ferramentas de validação OpenAPI +2. Testar com Swagger UI +3. Verificar se todos os tradutores estão cobertos + +## Convenção de Nomenclatura de Campos + +Todos os campos JSON usam **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, etc. + +## Criação de Arquivos de Esquema + +Para cada tradutor em `trustgraph-base/trustgraph/messaging/translators/`: + +1. **Ler o método do tradutor `to_pulsar()`** - Define o esquema de solicitação +2. **Ler o método do tradutor `from_pulsar()`** - Define o esquema de resposta +3. **Extrair nomes e tipos de campos** +4. **Criar o esquema OpenAPI** com: + Nomes de campos (kebab-case) + Tipos (string, integer, boolean, object, array) + Campos obrigatórios + Valores padrão + Descrições + +### Exemplo de Processo de Mapeamento + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +Tradução para: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## Respostas de Streaming + +Serviços que suportam streaming retornam múltiplas respostas com a flag `end_of_stream`: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +Documente este padrão no esquema de resposta de cada serviço. + +## Respostas de Erro + +Todos os serviços podem retornar: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +Onde `ErrorObject` está: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## Referências + +Tradutores: `trustgraph-base/trustgraph/messaging/translators/` +Mapeamento do despachante: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +Roteamento de endpoint: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +Resumo do serviço: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.ru.md b/docs/tech-specs/openapi-spec.ru.md new file mode 100644 index 00000000..5a3e9858 --- /dev/null +++ b/docs/tech-specs/openapi-spec.ru.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "Спецификация OpenAPI - Техническая спецификация" +parent: "Russian (Beta)" +--- + +# Спецификация OpenAPI - Техническая спецификация + +> **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. + +## Цель + +Создать всеобъемлющую, модульную спецификацию OpenAPI 3.1 для шлюза REST API TrustGraph, которая: +Документирует все конечные точки REST +Использует внешние `$ref` для модульности и удобства обслуживания +Непосредственно соответствует коду переводчика сообщений +Предоставляет точные схемы запросов/ответов + +## Источник истины + +API определяется следующим: +**Переводчики сообщений**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**Менеджер диспетчера**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**Менеджер конечных точек**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## Структура каталогов + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## Отображение сервисов + +### Глобальные сервисы (`/api/v1/{kind}`) +`config` - Управление конфигурацией +`flow` - Жизненный цикл потока +`librarian` - Библиотека документов +`knowledge` - Базы знаний +`collection-management` - Метаданные коллекции + +### Сервисы, размещенные в потоке (`/api/v1/flow/{flow}/service/{kind}`) + +**Запрос/Ответ:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**Отправка и получение (Fire-and-Forget):** +`text-load`, `document-load` + +### Импорт/Экспорт +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### Другое +`/api/v1/socket` (Множественный WebSocket) +`/api/metrics` (Prometheus) + +## Подход + +### Фаза 1: Настройка +1. Создание структуры каталогов +2. Создание основного файла `openapi.yaml` с метаданными, серверами, безопасностью +3. Создание многократно используемых компонентов (ошибок, общих параметров, схем безопасности) + +### Фаза 2: Общие схемы +Создание общих схем, используемых во всех сервисах: +`RdfValue`, `Triple` - RDF/структуры троек +`ErrorObject` - Ответ об ошибке +`DocumentMetadata`, `ProcessingMetadata` - Структуры метаданных +Общие параметры: `FlowId`, `User`, `Collection` + +### Фаза 3: Глобальные сервисы +Для каждого глобального сервиса (конфигурация, поток, библиотека, знания, управление коллекцией): +1. Создание файла пути в `paths/` +2. Создание схемы запроса в `components/schemas/{service}/` +3. Создание схемы ответа +4. Добавление примеров +5. Ссылка из основного файла `openapi.yaml` + +### Фаза 4: Сервисы, размещенные в потоке +Для каждого сервиса, размещенного в потоке: +1. Создание файла пути в `paths/flow-services/` +2. Создание схем запроса/ответа в `components/schemas/ai-services/` +3. Добавление документации о флаге потоковой передачи, где это применимо +4. Ссылка из основного файла `openapi.yaml` + +### Фаза 5: Импорт/Экспорт и WebSocket +1. Документирование основных конечных точек импорта/экспорта +2. Документирование шаблонов протокола WebSocket +3. Документирование конечных точек импорта/экспорта WebSocket на уровне потока + +### Фаза 6: Валидация +1. Проверка с помощью инструментов валидации OpenAPI +2. Тестирование с помощью Swagger UI +3. Убедитесь, что все переводчики охвачены + +## Соглашение об именовании полей + +Все поля JSON используют **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit` и т. д. + +## Создание файлов схем + +Для каждого переводчика в `trustgraph-base/trustgraph/messaging/translators/`: + +1. **Прочитать метод переводчика `to_pulsar()`** - Определяет схему запроса +2. **Прочитать метод переводчика `from_pulsar()`** - Определяет схему ответа +3. **Извлечь имена и типы полей** +4. **Создать схему OpenAPI** с: + Имена полей (kebab-case) + Типы (string, integer, boolean, object, array) + Обязательные поля + Значения по умолчанию + Описания + +### Пример процесса сопоставления + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +Соответствует: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## Потоковые ответы + +Сервисы, поддерживающие потоковую передачу, возвращают несколько ответов с флагом `end_of_stream`: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +Опишите эту схему в схеме ответа каждого сервиса. + +## Ответы об ошибках + +Все сервисы могут возвращать: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +Где `ErrorObject` находится: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## Ссылки + +Переводчики: `trustgraph-base/trustgraph/messaging/translators/` +Отображение диспетчера: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +Маршрутизация конечных точек: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +Обзор сервисов: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.sw.md b/docs/tech-specs/openapi-spec.sw.md new file mode 100644 index 00000000..217335d3 --- /dev/null +++ b/docs/tech-specs/openapi-spec.sw.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "Maelezo ya Kiufundi ya OpenAPI" +parent: "Swahili (Beta)" +--- + +# Maelezo ya Kiufundi ya OpenAPI + +> **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. + +## Lengo + +Kuunda maelezo kamili na yanayoweza kutenganishwa ya OpenAPI 3.1 kwa lango la API la TrustGraph ambalo: +Yanadhihirisha viungo vyote vya REST +Yanatumia `$ref` ya nje kwa utendaji na uendelevu +Yanalingana moja kwa moja na msimuaji wa ujumbe +Yanatoa muundo sahihi wa ombi/jibu + +## Chanzo cha Uhakika + +API inafafanuliwa na: +**Wasimamizi wa Tafsiri ya Ujumbe**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**Meneja wa Msambazaji**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**Meneja wa Kikoa**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## Muundo wa Saraka + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## Huduma za Ulinganishaji + +### Huduma za Kimataifa (`/api/v1/{kind}`) +`config` - Usimamizi wa usanidi +`flow` - Mzungano wa mchakato +`librarian` - Maktaba ya nyaraka +`knowledge` - Vituo vya maarifa +`collection-management` - Meta data ya mkusanyiko + +### Huduma Zilizowekwa kwenye Mchakato (`/api/v1/flow/{flow}/service/{kind}`) + +**Ombi/Jibu:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**Tuma na Usisubiri:** +`text-load`, `document-load` + +### Uingizaji/Utoaji +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### Mengine +`/api/v1/socket` (WebSocket iliyounganishwa) +`/api/metrics` (Prometheus) + +## Mbinu + +### Awamu ya 1: Uwekaji +1. Unda muundo wa saraka +2. Unda `openapi.yaml` kuu pamoja na metadata, seva, usalama +3. Unda vipengele vinavyoweza kutumika tena (makosa, vigezo vya kawaida, mpango wa usalama) + +### Awamu ya 2: Mfumo wa Kawaida +Unda mfumo wa kawaida unaotumika katika huduma: +`RdfValue`, `Triple` - Miundo ya RDF/triple +`ErrorObject` - Jibu la kosa +`DocumentMetadata`, `ProcessingMetadata` - Miundo ya metadata +Vigezo vya kawaida: `FlowId`, `User`, `Collection` + +### Awamu ya 3: Huduma za Kimataifa +Kwa kila huduma ya kimataifa (usanidi, mchakato, maktaba, maarifa, usimamizi wa mkusanyiko): +1. Unda faili ya njia katika `paths/` +2. Unda mfumo wa ombi katika `components/schemas/{service}/` +3. Unda mfumo wa jibu +4. Ongeza mifano +5. Rejelea kutoka kwa `openapi.yaml` kuu + +### Awamu ya 4: Huduma Zilizowekwa kwenye Mchakato +Kwa kila huduma iliyowekwa kwenye mchakato: +1. Unda faili ya njia katika `paths/flow-services/` +2. Unda mifumo ya ombi/jibu katika `components/schemas/ai-services/` +3. Ongeza maandishi ya bendera ya utiririshaji ambapo inafaa +4. Rejelea kutoka kwa `openapi.yaml` kuu + +### Awamu ya 5: Uingizaji/Utoaji & WebSocket +1. Andika kuhusu mwisho wa msingi wa uingizaji/utoaji +2. Andika kuhusu mifumo ya itifaki ya WebSocket +3. Andika kuhusu mwisho wa uingizaji/utoaji wa WebSocket wa kiwango cha mchakato + +### Awamu ya 6: Uthibitisho +1. Thibitisha kwa kutumia zana za uthibitisho wa OpenAPI +2. Jaribu kwa kutumia Swagger UI +3. Hakikisha kuwa watumizi wote wamefunikwa + +## Mfumo wa Majina ya Nyanja + +Nyanja zote za JSON hutumia **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, n.k. + +## Kuunda Faili za Mfumo + +Kwa kila mtumizi katika `trustgraph-base/trustgraph/messaging/translators/`: + +1. **Soma njia ya mtumizi `to_pulsar()`** - Inaweka mfumo wa ombi +2. **Soma njia ya mtumizi `from_pulsar()`** - Inaweka mfumo wa jibu +3. **Toa majina na aina za nyanja** +4. **Unda mfumo wa OpenAPI** pamoja na: + Majina ya nyanja (kebab-case) + Aina (string, integer, boolean, object, array) + Nyanja zinazohitajika + Maagizo + Maelezo + +### Mchakato wa Ulinganishaji wa Kifaa + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +Inafanana na: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## Majibu ya Utiririshaji + +Huduma zinazounga mkono utiririshaji hurudisha majibu mengi na bendera `end_of_stream`: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +Elezea mfumo huu katika schema ya majibu ya kila huduma. + +## Majibu ya Kosa + +Huduma zote zinaweza kurudisha: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +Ambako `ErrorObject` iko: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## Marejeleo + +Watengenezaji: `trustgraph-base/trustgraph/messaging/translators/` +Ramani ya utumaji: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +Uelekezaji wa mwisho: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +Muhtasari wa huduma: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.tr.md b/docs/tech-specs/openapi-spec.tr.md new file mode 100644 index 00000000..100af626 --- /dev/null +++ b/docs/tech-specs/openapi-spec.tr.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "OpenAPI Özellikleri - Teknik Belge" +parent: "Turkish (Beta)" +--- + +# OpenAPI Özellikleri - Teknik Belge + +> **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. + +## Amaç + +TrustGraph REST API Gateway için kapsamlı, modüler bir OpenAPI 3.1 spesifikasyonu oluşturmak, bu spesifikasyon şunları sağlamalıdır: +Tüm REST uç noktalarını belgelemelidir +Modülerlik ve bakım kolaylığı için harici `$ref` kullanmalıdır +Doğrudan mesaj çevirici koduna eşlenmelidir +Doğru istek/yanıt şemaları sağlamalıdır + +## Doğru Kaynak + +API aşağıdaki öğeler tarafından tanımlanır: +**Mesaj Çeviriciler**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**Dağıtıcı Yöneticisi**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**Uç Nokta Yöneticisi**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## Dizin Yapısı + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## Hizmet Eşlemesi + +### Küresel Hizmetler (`/api/v1/{kind}`) +`config` - Yapılandırma yönetimi +`flow` - Akış yaşam döngüsü +`librarian` - Belge kütüphanesi +`knowledge` - Bilgi çekirdekleri +`collection-management` - Koleksiyon meta verileri + +### Akışa Dayalı Hizmetler (`/api/v1/flow/{flow}/service/{kind}`) + +**İstek/Yanıt:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**Gönder ve Unut:** +`text-load`, `document-load` + +### İçe/Dışa Aktarma +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### Diğer +`/api/v1/socket` (WebSocket çoklama) +`/api/metrics` (Prometheus) + +## Yaklaşım + +### Aşama 1: Kurulum +1. Dizin yapısını oluşturun +2. Ana `openapi.yaml` dosyasını meta veriler, sunucular, güvenlik ile birlikte oluşturun +3. Yeniden kullanılabilir bileşenleri (hatalar, ortak parametreler, güvenlik şemaları) oluşturun + +### Aşama 2: Ortak Şemalar +Hizmetler arasında kullanılan ortak şemaları oluşturun: +`RdfValue`, `Triple` - RDF/üçlü yapılar +`ErrorObject` - Hata yanıtı +`DocumentMetadata`, `ProcessingMetadata` - Meta veri yapıları +Ortak parametreler: `FlowId`, `User`, `Collection` + +### Aşama 3: Küresel Hizmetler +Her küresel hizmet için (yapılandırma, akış, kütüphaneci, bilgi, koleksiyon yönetimi): +1. `paths/` içinde bir yol dosyası oluşturun +2. `components/schemas/{service}/` içinde bir istek şeması oluşturun +3. Bir yanıt şeması oluşturun +4. Örnekler ekleyin +5. Ana `openapi.yaml` dosyasından referans alın + +### Aşama 4: Akışa Dayalı Hizmetler +Her akışa dayalı hizmet için: +1. `paths/flow-services/` içinde bir yol dosyası oluşturun +2. `components/schemas/ai-services/` içinde istek/yanıt şemalarını oluşturun +3. Gerekli durumlarda akış düzeyi akış bayrak dokümantasyonunu ekleyin +4. Ana `openapi.yaml` dosyasından referans alın + +### Aşama 5: İçe/Dışa Aktarma & WebSocket +1. Temel içe/dışa aktarma uç noktalarını belgeleyin +2. WebSocket protokol kalıplarını belgeleyin +3. Akış düzeyindeki içe/dışa aktarma WebSocket uç noktalarını belgeleyin + +### Aşama 6: Doğrulama +1. OpenAPI doğrulama araçlarıyla doğrulayın +2. Swagger UI ile test edin +3. Tüm çeviricilerin kapsandığından emin olun + +## Alan Adlandırma Kuralları + +Tüm JSON alanları **kebab-case** kullanır: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, vb. + +## Şema Dosyaları Oluşturma + +Her çevirici için `trustgraph-base/trustgraph/messaging/translators/` içinde: + +1. **Çevirici `to_pulsar()` yöntemini okuyun** - İstek şemasını tanımlar +2. **Çevirici `from_pulsar()` yöntemini okuyun** - Yanıt şemasını tanımlar +3. **Alan adlarını ve türlerini çıkarın** +4. Aşağıdakilerle bir OpenAPI şeması oluşturun: + Alan adları (kebab-case) + Türler (string, integer, boolean, object, array) + Gerekli alanlar + Varsayılanlar + Açıklamalar + +### Örnek Eşleme Süreci + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +Çevrilir: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## Akışlı Yanıtlar + +Akışlı yanıtları destekleyen hizmetler, `end_of_stream` bayrağı ile birden fazla yanıt döndürür: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +Bu kalıbı, her hizmetin yanıt şemasında belgeleyin. + +## Hata Yanıtları + +Tüm hizmetler aşağıdaki yanıtları döndürebilir: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +`ErrorObject` ifadesi nerede bulunuyor: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## Referanslar + +Çevirenler: `trustgraph-base/trustgraph/messaging/translators/` +Dağıtım eşlemesi: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +Uç nokta yönlendirmesi: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +Hizmet özeti: `API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/openapi-spec.zh-cn.md b/docs/tech-specs/openapi-spec.zh-cn.md new file mode 100644 index 00000000..15c6eb66 --- /dev/null +++ b/docs/tech-specs/openapi-spec.zh-cn.md @@ -0,0 +1,239 @@ +--- +layout: default +title: "OpenAPI 规范 - 技术规范" +parent: "Chinese (Beta)" +--- + +# OpenAPI 规范 - 技术规范 + +> **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. + +## 目标 + +创建一个全面的、模块化的 OpenAPI 3.1 规范,用于 TrustGraph REST API 网关,该规范应: +记录所有 REST 接口 +使用外部 `$ref` 以实现模块化和可维护性 +直接映射到消息转换器代码 +提供准确的请求/响应模式 + +## 权威来源 + +API 由以下内容定义: +**消息转换器**: `trustgraph-base/trustgraph/messaging/translators/*.py` +**分派器管理器**: `trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +**端点管理器**: `trustgraph-flow/trustgraph/gateway/endpoint/manager.py` + +## 目录结构 + +``` +openapi/ +├── openapi.yaml # Main entry point +├── paths/ +│ ├── config.yaml # Global services +│ ├── flow.yaml +│ ├── librarian.yaml +│ ├── knowledge.yaml +│ ├── collection-management.yaml +│ ├── flow-services/ # Flow-hosted services +│ │ ├── agent.yaml +│ │ ├── document-rag.yaml +│ │ ├── graph-rag.yaml +│ │ ├── text-completion.yaml +│ │ ├── prompt.yaml +│ │ ├── embeddings.yaml +│ │ ├── mcp-tool.yaml +│ │ ├── triples.yaml +│ │ ├── objects.yaml +│ │ ├── nlp-query.yaml +│ │ ├── structured-query.yaml +│ │ ├── structured-diag.yaml +│ │ ├── graph-embeddings.yaml +│ │ ├── document-embeddings.yaml +│ │ ├── text-load.yaml +│ │ └── document-load.yaml +│ ├── import-export/ +│ │ ├── core-import.yaml +│ │ ├── core-export.yaml +│ │ └── flow-import-export.yaml # WebSocket import/export +│ ├── websocket.yaml +│ └── metrics.yaml +├── components/ +│ ├── schemas/ +│ │ ├── config/ +│ │ ├── flow/ +│ │ ├── librarian/ +│ │ ├── knowledge/ +│ │ ├── collection/ +│ │ ├── ai-services/ +│ │ ├── common/ +│ │ └── errors/ +│ ├── parameters/ +│ ├── responses/ +│ └── examples/ +└── security/ + └── bearerAuth.yaml +``` + +## 服务映射 + +### 全局服务 (`/api/v1/{kind}`) +`config` - 配置管理 +`flow` - 流生存周期 +`librarian` - 文档库 +`knowledge` - 知识核心 +`collection-management` - 集合元数据 + +### 托管于流的服务 (`/api/v1/flow/{flow}/service/{kind}`) + +**请求/响应:** +`agent`, `text-completion`, `prompt`, `mcp-tool` +`graph-rag`, `document-rag` +`embeddings`, `graph-embeddings`, `document-embeddings` +`triples`, `objects`, `nlp-query`, `structured-query`, `structured-diag` + +**发布/订阅:** +`text-load`, `document-load` + +### 导入/导出 +`/api/v1/import-core` (POST) +`/api/v1/export-core` (GET) +`/api/v1/flow/{flow}/import/{kind}` (WebSocket) +`/api/v1/flow/{flow}/export/{kind}` (WebSocket) + +### 其他 +`/api/v1/socket` (WebSocket 多路复用) +`/api/metrics` (Prometheus) + +## 方案 + +### 第一阶段:设置 +1. 创建目录结构 +2. 创建主 `openapi.yaml` 文件,包含元数据、服务器、安全配置 +3. 创建可重用组件(错误、通用参数、安全方案) + +### 第二阶段:通用模式 +创建在服务间共享的模式: +`RdfValue`, `Triple` - RDF/三元组结构 +`ErrorObject` - 错误响应 +`DocumentMetadata`, `ProcessingMetadata` - 元数据结构 +通用参数:`FlowId`, `User`, `Collection` + +### 第三阶段:全球服务 +对于每个全球服务(配置、流程、库管理员、知识、集合管理): +1. 在 `paths/` 中创建路径文件。 +2. 在 `components/schemas/{service}/` 中创建请求模式。 +3. 创建响应模式。 +4. 添加示例。 +5. 从主文件 `openapi.yaml` 中引用。 + +### 第四阶段:流程托管服务 +对于每个流程托管服务: +1. 在 `paths/flow-services/` 中创建路径文件。 +2. 在 `components/schemas/ai-services/` 中创建请求/响应模式。 +3. 在适用情况下,添加流媒体标志文档。 +4. 从主文件 `openapi.yaml` 中引用。 + +### 第五阶段:导入/导出 & WebSocket +1. 文档核心导入/导出端点。 +2. 文档 WebSocket 协议模式。 +3. 文档流程级别的导入/导出 WebSocket 端点。 + +### 第六阶段:验证 +1. 使用 OpenAPI 验证工具进行验证。 +2. 使用 Swagger UI 进行测试。 +3. 验证所有翻译器是否已覆盖。 + +## 字段命名约定 + +所有 JSON 字段使用 **kebab-case**: +`flow-id`, `blueprint-name`, `doc-limit`, `entity-limit`, 等。 + +## 创建模式文件 + +对于 `trustgraph-base/trustgraph/messaging/translators/` 中的每个翻译器: + +1. **读取翻译器 `to_pulsar()` 方法** - 定义请求模式。 +2. **读取翻译器 `from_pulsar()` 方法** - 定义响应模式。 +3. **提取字段名称和类型**。 +4. **创建 OpenAPI 模式**,包含: + 字段名称(kebab-case)。 + 类型(字符串、整数、布尔值、对象、数组)。 + 必需字段。 + 默认值。 + 描述。 + +### 示例映射过程 + +```python +# From retrieval.py DocumentRagRequestTranslator +def to_pulsar(self, data: Dict[str, Any]) -> DocumentRagQuery: + return DocumentRagQuery( + query=data["query"], # required string + user=data.get("user", "trustgraph"), # optional string, default "trustgraph" + collection=data.get("collection", "default"), # optional string, default "default" + doc_limit=int(data.get("doc-limit", 20)), # optional integer, default 20 + streaming=data.get("streaming", False) # optional boolean, default false + ) +``` + +对应于: + +```yaml +# components/schemas/ai-services/DocumentRagRequest.yaml +type: object +required: + - query +properties: + query: + type: string + description: Search query + user: + type: string + default: trustgraph + collection: + type: string + default: default + doc-limit: + type: integer + default: 20 + description: Maximum number of documents to retrieve + streaming: + type: boolean + default: false + description: Enable streaming responses +``` + +## 流式响应 + +支持流式传输的服务会返回带有 `end_of_stream` 标志的多个响应: +`agent`, `text-completion`, `prompt` +`document-rag`, `graph-rag` + +在每个服务的响应模式中记录此模式。 + +## 错误响应 + +所有服务都可以返回: +```yaml +error: + oneOf: + - type: string + - $ref: '#/components/schemas/ErrorObject' +``` + +其中,`ErrorObject` 指的是: +```yaml +type: object +properties: + type: + type: string + message: + type: string +``` + +## 参考文献 + +翻译人员:`trustgraph-base/trustgraph/messaging/translators/` +调度映射:`trustgraph-flow/trustgraph/gateway/dispatch/manager.py` +终端路由:`trustgraph-flow/trustgraph/gateway/endpoint/manager.py` +服务摘要:`API_SERVICES_SUMMARY.md` diff --git a/docs/tech-specs/pubsub-abstraction.md b/docs/tech-specs/pubsub-abstraction.md index 722b3b47..b1ff0818 100644 --- a/docs/tech-specs/pubsub-abstraction.md +++ b/docs/tech-specs/pubsub-abstraction.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Pub/Sub Abstraction: Broker-Independent Messaging" +parent: "Tech Specs" +--- + # Pub/Sub Abstraction: Broker-Independent Messaging ## Problem @@ -548,4 +554,3 @@ The `state` queue class needs "start from earliest" semantics — a newly starte RabbitMQ Streams (available since 3.9) solve this directly. Streams are persistent, append-only logs that support consumer offset positioning. The RabbitMQ backend maps the `state` class to a stream, and consumers attach with offset `first` to read from the beginning, or `last` to read the most recent entry plus future updates. Since config pushes are full state snapshots (not deltas), a consumer only needs the most recent entry. The RabbitMQ backend can use `last` offset positioning for `state` class consumers, which delivers the last message in the stream followed by any new messages. This matches the current behaviour where processors read config on startup and then react to updates. - diff --git a/docs/tech-specs/pubsub.ar.md b/docs/tech-specs/pubsub.ar.md new file mode 100644 index 00000000..223e4e1f --- /dev/null +++ b/docs/tech-specs/pubsub.ar.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "البنية التحتية للنشر والاشتراك (Pub/Sub)" +parent: "Arabic (Beta)" +--- + +# البنية التحتية للنشر والاشتراك (Pub/Sub) + +> **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 والبنية التحتية للنشر والاشتراك. حاليًا، يتم ترميز النظام لاستخدام Apache Pulsar. تحدد هذه التحليلات جميع نقاط التكامل لإعلام عمليات إعادة الهيكلة المستقبلية نحو تجريد نشر واشتراك قابل للتكوين. + +## الحالة الحالية: نقاط تكامل Pulsar + +### 1. استخدام عميل Pulsar المباشر + +**الموقع:** `trustgraph-flow/trustgraph/gateway/service.py` + +يقوم بوابة واجهة برمجة التطبيقات باستيراد وتثبيت عميل Pulsar مباشرةً: + +**السطر 20:** `import pulsar` +**الأسطر 54-61:** تثبيت مباشر لـ `pulsar.Client()` مع `pulsar.AuthenticationToken()` الاختياري +**الأسطر 33-35:** تكوين مضيف Pulsar الافتراضي من متغيرات البيئة +**الأسطر 178-192:** وسيطات سطر الأوامر لـ `--pulsar-host`، `--pulsar-api-key`، و `--pulsar-listener` +**الأسطر 78، 124:** تمرير `pulsar_client` إلى `ConfigReceiver` و `DispatcherManager` + +هذا هو الموقع الوحيد الذي يقوم بتثبيت عميل Pulsar مباشرةً خارج طبقة التجريد. + +### 2. إطار عمل المعالج الأساسي + +**الموقع:** `trustgraph-base/trustgraph/base/async_processor.py` + +يوفر الفئة الأساسية لجميع المعالجات اتصال Pulsar: + +**السطر 9:** `import _pulsar` (للتعامل مع الاستثناءات) +**السطر 18:** `from . pubsub import PulsarClient` +**السطر 38:** إنشاء `pulsar_client_object = PulsarClient(**params)` +**الأسطر 104-108:** خصائص تعرض `pulsar_host` و `pulsar_client` +**السطر 250:** تستدعي الطريقة الثابتة `add_args()` `PulsarClient.add_args(parser)` لوسيطات سطر الأوامر +**الأسطر 223-225:** معالجة الاستثناءات لـ `_pulsar.Interrupted` + +ترث جميع المعالجات من `AsyncProcessor`، مما يجعل هذا نقطة التكامل المركزية. + +### 3. تجريد المستهلك + +**الموقع:** `trustgraph-base/trustgraph/base/consumer.py` + +يستهلك الرسائل من قوائم الانتظار ويستدعي وظائف المعالج: + +**استيرادات Pulsar:** +**السطر 12:** `from pulsar.schema import JsonSchema` +**السطر 13:** `import pulsar` +**السطر 14:** `import _pulsar` + +**الاستخدام المحدد لـ Pulsar:** +**الأسطر 100، 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**السطر 108:** غلاف `JsonSchema(self.schema)` +**السطر 110:** `pulsar.ConsumerType.Shared` +**الأسطر 104-111:** `self.client.subscribe()` مع معلمات خاصة بـ Pulsar +**الأسطر 143، 150، 65:** طرق `consumer.unsubscribe()` و `consumer.close()` +**السطر 162:** استثناء `_pulsar.Timeout` +**الأسطر 182، 205، 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**ملف المواصفات:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**السطر 22:** يشير إلى `processor.pulsar_client` + +### 4. تجريد الناشر + +**الموقع:** `trustgraph-base/trustgraph/base/producer.py` + +يرسل الرسائل إلى قوائم الانتظار: + +**استيرادات Pulsar:** +**السطر 2:** `from pulsar.schema import JsonSchema` + +**الاستخدام المحدد لـ Pulsar:** +**السطر 49:** غلاف `JsonSchema(self.schema)` +**الأسطر 47-51:** `self.client.create_producer()` مع معلمات خاصة بـ Pulsar (الموضوع، المخطط، تمكين التجزئة) +**الأسطر 31، 76:** طريقة `producer.close()` +**الأسطر 64-65:** `producer.send()` مع الرسالة والخصائص + +**ملف المواصفات:** `trustgraph-base/trustgraph/base/producer_spec.py` +**السطر 18:** يشير إلى `processor.pulsar_client` + +### 5. تجريد الناشر + +**الموقع:** `trustgraph-base/trustgraph/base/publisher.py` + +نشر الرسائل بشكل غير متزامن مع تخزين الرسائل مؤقتًا في قائمة الانتظار: + +**استيرادات Pulsar:** +**السطر 2:** `from pulsar.schema import JsonSchema` +**السطر 6:** `import pulsar` + +**الاستخدام المحدد لـ Pulsar:** +**السطر 52:** غلاف `JsonSchema(self.schema)` +**الأسطر 50-54:** `self.client.create_producer()` مع معلمات خاصة بـ Pulsar +**الأسطر 101، 103:** `producer.send()` مع الرسالة والخصائص الاختيارية +**الأسطر 106-107:** طرق `producer.flush()` و `producer.close()` + +### 6. تجريد المشترك + +**الموقع:** `trustgraph-base/trustgraph/base/subscriber.py` + +يوفر توزيع رسائل متعددة المستلمين من خلال قوائم الانتظار: + +**استيرادات Pulsar:** +**السطر 6:** `from pulsar.schema import JsonSchema` +**السطر 8:** `import _pulsar` + +**الاستخدام الخاص بـ Pulsar:** +**السطر 55:** `JsonSchema(self.schema)` wrapper +**السطر 57:** `self.client.subscribe(**subscribe_args)` +**الأسطر 101، 136، 160، 167-172:** استثناءات Pulsar: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**الأسطر 159، 166، 170:** طرق المستهلك: `negative_acknowledge()`, `unsubscribe()`, `close()` +**الأسطر 247، 251:** إقرار الرسالة: `acknowledge()`, `negative_acknowledge()` + +**ملف المواصفات:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**السطر 19:** يشير إلى `processor.pulsar_client` + +### 7. نظام المخططات (قلب الظلام) + +**الموقع:** `trustgraph-base/trustgraph/schema/` + +يتم تعريف كل مخطط رسالة في النظام باستخدام إطار عمل المخططات الخاص بـ Pulsar. + +**المكونات الأساسية:** `schema/core/primitives.py` +**السطر 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +ترث جميع المخططات من الفئة الأساسية `Record` الخاصة بـ Pulsar +جميع أنواع الحقول هي أنواع Pulsar: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**أمثلة على المخططات:** +`schema/services/llm.py` (السطر 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (السطر 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**تسمية الموضوع:** `schema/core/topic.py` +**الأسطر 2-3:** تنسيق الموضوع: `{kind}://{tenant}/{namespace}/{topic}` +هذه البنية URI خاصة بـ Pulsar (على سبيل المثال، `persistent://tg/flow/config`) + +**التأثير:** +تستخدم جميع تعريفات الرسائل/الردود في قاعدة التعليمات البرمجية مخططات Pulsar +يتضمن ذلك الخدمات الخاصة بـ: config, flow, llm, prompt, query, storage, agent, collection, diagnosis, library, lookup, nlp_query, objects_query, retrieval, structured_query +يتم استيراد تعريفات المخططات واستخدامها على نطاق واسع في جميع المعالجات والخدمات + +## ملخص + +### تبعيات Pulsar حسب الفئة + +1. **إنشاء العميل:** + مباشر: `gateway/service.py` + مجرد: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **نقل الرسائل:** + المستهلك: `consumer.py`, `consumer_spec.py` + المنتج: `producer.py`, `producer_spec.py` + الناشر: `publisher.py` + المشترك: `subscriber.py`, `subscriber_spec.py` + +3. **نظام المخططات:** + الأنواع الأساسية: `schema/core/primitives.py` + جميع مخططات الخدمة: `schema/services/*.py` + تسمية الموضوع: `schema/core/topic.py` + +4. **مفاهيم Pulsar الخاصة المطلوبة:** + رسائل قائمة على الموضوع + نظام المخططات (السجل، أنواع الحقول) + اشتراكات مشتركة + إقرار الرسالة (إيجابي/سلبي) + موضع المستهلك (الأول/الأخير) + خصائص الرسالة + المواضع الأولية وأنواع المستهلك + دعم التجزئة + مواضيع مستمرة مقابل مواضيع غير مستمرة + +### تحديات إعادة الهيكلة + +الخبر السار: توفر طبقة التجريد (المستهلك، المنتج، الناشر، المشترك) تغليفًا نظيفًا لمعظم تفاعلات Pulsar. + +التحديات: +1. **انتشار نظام المخططات:** يستخدم كل تعريف للرسالة `pulsar.schema.Record` وأنواع Pulsar للحقول +2. **قوائم Pulsar الخاصة:** `InitialPosition`, `ConsumerType` +3. **استثناءات Pulsar:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **توقيعات الطريقة:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`، إلخ. +5. **تنسيق URI للموضوع:** هيكل Pulsar `kind://tenant/namespace/topic` + +### الخطوات التالية + +لجعل البنية التحتية للنشر/الاشتراك قابلة للتكوين، نحتاج إلى: + +1. إنشاء واجهة تجريد لنظام العميل/المخططات +2. تجريد قوائم Pulsar الخاصة والاستثناءات +3. إنشاء أغلفة المخططات أو تعريفات مخططات بديلة +4. تنفيذ الواجهة لكل من Pulsar وأنظمة بديلة (Kafka, RabbitMQ, Redis Streams, إلخ.) +5. تحديث `pubsub.py` ليكون قابلاً للتكوين ودعم الخلفيات المتعددة +6. توفير مسار ترحيل للنشر الحالي + +## مسودة النهج 1: نمط المحول مع طبقة ترجمة المخططات + +### الفكرة الرئيسية +**نظام المخططات** هو نقطة التكامل الأعمق - كل شيء آخر ينبع منه. نحتاج إلى حل هذه المشكلة أولاً، وإلا سنعيد كتابة قاعدة التعليمات البرمجية بأكملها. + +### الاستراتيجية: الحد الأدنى من الاضطرابات مع المحولات + +**1. الحفاظ على مخططات Pulsar كتمثيل داخلي** +لا تقم بإعادة كتابة جميع تعريفات المخططات. +تبقى المخططات `pulsar.schema.Record` داخليًا. +استخدم المحولات لترجمة البيانات عند الحد بين التعليمات البرمجية الخاصة بنا والخلفية الخاصة بالنشر والاشتراك. + +**2. إنشاء طبقة تجريدية للنشر والاشتراك:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. تحديد الواجهات المجردة:** +`PubSubClient` - اتصال العميل +`PubSubProducer` - إرسال الرسائل +`PubSubConsumer` - استقبال الرسائل +`SchemaAdapter` - ترجمة مخططات Pulsar إلى/من JSON أو التنسيقات الخاصة بالخلفية + +**4. تفاصيل التنفيذ:** + +بالنسبة إلى **محول Pulsar**: تمرير تقريبي، ترجمة محدودة + +بالنسبة إلى **الخلفيات الأخرى** (Kafka، RabbitMQ، إلخ): +تسلسل كائنات سجل Pulsar إلى JSON/بايت +مطابقة المفاهيم مثل: + `InitialPosition.Earliest/Latest` → auto.offset.reset في Kafka + `acknowledge()` → commit في Kafka + `negative_acknowledge()` → نمط إعادة الترتيب أو قائمة الانتظار الميتة (DLQ) + عناوين الموضوع → أسماء الموضوعات الخاصة بالخلفية + +### التحليل + +**المزايا:** +✅ تغييرات قليلة في التعليمات البرمجية للخدمات الحالية +✅ تبقى المخططات كما هي (بدون إعادة كتابة شاملة) +✅ مسار ترحيل تدريجي +✅ لا يلاحظ مستخدمو Pulsar أي فرق +✅ إضافة خلفيات جديدة عبر المحولات + +**العيوب:** +⚠️ لا يزال يعتمد على Pulsar (لتحديد المخططات) +⚠️ بعض عدم التطابق في ترجمة المفاهيم + +### بديل يجب أخذه في الاعتبار + +إنشاء **نظام مخططات TrustGraph** مستقل عن النشر والاشتراك (باستخدام فئات البيانات أو Pydantic)، ثم إنشاء مخططات Pulsar/Kafka/إلخ من ذلك. يتطلب هذا إعادة كتابة كل ملف مخطط وقد يؤدي إلى تغييرات غير متوقعة. + +### التوصية للإصدار الأول + +ابدأ بـ **نهج المحول** لأنه: +1. عملي - يعمل مع التعليمات البرمجية الحالية +2. يثبت المفهوم بأقل قدر من المخاطر +3. يمكن أن يتطور إلى نظام مخططات أصلي لاحقًا إذا لزم الأمر +4. مدفوع بالتكوين: متغير بيئة واحد يقوم بتبديل الخلفيات + +## النهج المقترح للإصدار الثاني: نظام مخططات مستقل عن الخلفية باستخدام فئات البيانات + +### المفهوم الأساسي + +استخدم **فئات البيانات** في Python كتنسيق تعريف مخطط محايد. توفر كل خلفية نشر واشتراك الخاصة بها تسلسلًا/إلغاء تسلسل لـ فئات البيانات، مما يلغي الحاجة إلى بقاء مخططات Pulsar في قاعدة التعليمات البرمجية. + +### تعدد الأشكال للمخططات على مستوى المصنع + +بدلاً من ترجمة مخططات Pulsar، **توفر كل خلفية معالجتها الخاصة للمخططات** والتي تعمل مع فئات البيانات القياسية في Python. + +### تدفق الناشر + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### تدفق المستهلك + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### ما الذي يحدث وراء الكواليس + +**للخلفية التقنية لـ Pulsar:** +`create_producer()` → ينشئ مُنتج Pulsar باستخدام مخطط JSON أو سجل تم إنشاؤه ديناميكيًا. +`send(request)` → يقوم بتسلسل كائن البيانات (dataclass) إلى تنسيق JSON/Pulsar، ويرسله إلى Pulsar. +`receive()` → يستقبل رسالة Pulsar، ويقوم بإلغاء تسلسلها مرة أخرى إلى كائن البيانات. + +**للخلفية التقنية لـ MQTT:** +`create_producer()` → يتصل بخادم MQTT، ولا يلزم تسجيل أي مخطط. +`send(request)` → يحول كائن البيانات إلى JSON، وينشره في موضوع MQTT. +`receive()` → يشترك في موضوع MQTT، ويقوم بإلغاء تسلسل JSON إلى كائن بيانات. + +**للخلفية التقنية لـ Kafka:** +`create_producer()` → ينشئ مُنتج Kafka، ويسجل مخطط Avro إذا لزم الأمر. +`send(request)` → يقوم بتسلسل كائن البيانات إلى تنسيق Avro، ويرسله إلى Kafka. +`receive()` → يستقبل رسالة Kafka، ويقوم بإلغاء تسلسل Avro مرة أخرى إلى كائن بيانات. + +### النقاط الرئيسية في التصميم + +1. **إنشاء كائن المخطط**: نسخة كائن البيانات (`TextCompletionRequest(...)`) متطابقة بغض النظر عن الخلفية التقنية. +2. **الخلفية التقنية تتعامل مع الترميز**: كل خلفية تقنية تعرف كيفية تسلسل كائن البيانات الخاص بها إلى التنسيق المستخدم. +3. **تعريف المخطط عند الإنشاء**: عند إنشاء المنتج/المستهلك، تحدد نوع المخطط. +4. **الحفاظ على سلامة النوع**: تحصل على كائن `TextCompletionRequest` صحيح، وليس قاموسًا. +5. **لا يوجد تسرب للخلفية التقنية**: لا يقوم كود التطبيق باستيراد مكتبات خاصة بالخلفية التقنية. + +### مثال للتحويل + +**الحالي (خاص بـ Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**جديد (لا يعتمد على الواجهة الخلفية):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### التكامل مع الواجهة الخلفية (Backend Integration) + +كل واجهة خلفية تتعامل مع التسلسل/إلغاء التسلسل لفئات البيانات (dataclasses): + +**واجهة خلفية Pulsar:** +إنشاء فئات `pulsar.schema.Record` ديناميكيًا من فئات البيانات. +أو تسلسل فئات البيانات إلى JSON واستخدام مخطط JSON الخاص بـ Pulsar. +تحافظ على التوافق مع عمليات نشر Pulsar الحالية. + +**واجهة خلفية MQTT/Redis:** +تسلسل JSON مباشر لمثيل فئة البيانات. +استخدم `dataclasses.asdict()` / `from_dict()`. +خفيفة الوزن، لا تحتاج إلى سجل مخططات. + +**واجهة خلفية Kafka:** +إنشاء مخططات Avro من تعريفات فئات البيانات. +استخدم سجل مخططات Confluent. +تسلسل آمن من حيث النوع مع دعم تطور المخطط. + +### البنية (Architecture) + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### تفاصيل التنفيذ + +**1. تعريفات المخططات:** فئات بيانات بسيطة مع تلميحات الأنواع + `str`، `int`، `bool`، `float` للقيم الأولية + `list[T]` للمصفوفات + `dict[str, T]` للخرائط + فئات بيانات متداخلة للأنواع المعقدة + +**2. يوفر كل خلفية:** + المُسلسل: `dataclass → bytes/wire format` + المُفكك: `bytes/wire format → dataclass` + تسجيل المخطط (إذا لزم الأمر، مثل Pulsar/Kafka) + +**3. تجريد المستهلك/المنتج:** + موجود بالفعل (consumer.py, producer.py) + تحديث لاستخدام التسلسل الخاص بالخلفية + إزالة استيرادات Pulsar المباشرة + +**4. تعيينات الأنواع:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### مسار الترحيل + +1. **إنشاء إصدارات من فئات البيانات** لجميع المخططات في `trustgraph/schema/` +2. **تحديث الفئات الخلفية** (المستهلك، المنتج، الناشر، المشترك) لاستخدام التسلسل المقدم من الخلفية +3. **تنفيذ PulsarBackend** باستخدام مخطط JSON أو إنشاء سجل ديناميكي +4. **الاختبار مع Pulsar** للتأكد من التوافق مع الإصدارات السابقة للنشر +5. **إضافة خلفيات جديدة** (MQTT، Kafka، Redis، إلخ) حسب الحاجة +6. **إزالة استيرادات Pulsar** من ملفات المخططات + +### الفوائد + +✅ **لا يوجد اعتماد على النشر/الاشتراك** في تعريفات المخططات +✅ **Python قياسي** - سهل الفهم، التحقق من النوع، التوثيق +✅ **أدوات حديثة** - تعمل مع mypy، إكمال التعليمات البرمجية لبيئات التطوير المتكاملة، المدققين +✅ **محسّنة للخلفية** - تستخدم كل خلفية التسلسل الأصلي +✅ **لا توجد تكلفة ترجمة** - تسلسل مباشر، بدون محولات +✅ **أمان النوع** - كائنات حقيقية مع أنواع مناسبة +✅ **التحقق السهل** - يمكن استخدام Pydantic إذا لزم الأمر + +### التحديات والحلول + +**التحدي:** يحتوي Pulsar's `Record` على تحقق من صحة الحقول في وقت التشغيل +**الحل:** استخدم فئات بيانات Pydantic للتحقق من الصحة إذا لزم الأمر، أو ميزات فئة البيانات Python 3.10+ مع `__post_init__` + +**التحدي:** بعض ميزات Pulsar الخاصة (مثل نوع `Bytes`) +**الحل:** قم بتعيين إلى نوع `bytes` في فئة البيانات، تتعامل الخلفية مع الترميز بشكل مناسب + +**التحدي:** تسمية الموضوع (`persistent://tenant/namespace/topic`) +**الحل:** قم بتجريد أسماء الموضوع في تعريفات المخططات، تقوم الخلفية بتحويلها إلى التنسيق المناسب + +**التحدي:** تطور المخططات والتحكم في الإصدار +**الحل:** تتعامل كل خلفية مع هذا وفقًا لقدراتها (إصدارات مخطط Pulsar، سجل مخطط Kafka، إلخ) + +**التحدي:** الأنواع المعقدة المتداخلة +**الحل:** استخدم فئات بيانات متداخلة، تقوم الخلفيات بالتسلسل/فك التسلسل بشكل متكرر + +### قرارات التصميم + +1. **فئات بيانات عادية أو Pydantic؟** + ✅ **القرار: استخدم فئات بيانات Python عادية** + أبسط، بدون تبعيات إضافية + التحقق من الصحة ليس مطلوبًا عمليًا + أسهل في الفهم والصيانة + +2. **تطور المخطط:** + ✅ **القرار: لا يلزم آلية للتحكم في الإصدار** + المخططات مستقرة وطويلة الأمد + عادةً ما تضيف التحديثات حقولًا جديدة (متوافقة مع الإصدارات السابقة) + تتعامل الخلفيات مع تطور المخطط وفقًا لقدراتها + +3. **التوافق مع الإصدارات السابقة:** + ✅ **القرار: تغيير رئيسي للإصدار، لا يلزم التوافق مع الإصدارات السابقة** + سيكون هذا تغييرًا جذريًا مع تعليمات ترحيل + يسمح الفصل النظيف بتصميم أفضل + سيتم توفير دليل ترحيل للنشر الحالي + +4. **الأنواع المتداخلة والهياكل المعقدة:** + ✅ **القرار: استخدم فئات بيانات متداخلة بشكل طبيعي** + تتعامل فئات بيانات Python مع التداخل بشكل مثالي + `list[T]` للمصفوفات، `dict[K, V]` للخرائط + تقوم الخلفيات بالتسلسل/فك التسلسل بشكل متكرر + مثال: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **القيم الافتراضية والحقول الاختيارية:** + ✅ **القرار: مزيج من الحقول المطلوبة، والقيم الافتراضية، والحقول الاختيارية** + الحقول المطلوبة: لا توجد قيمة افتراضية. + الحقول التي تحتوي على قيم افتراضية: موجودة دائمًا، ولها قيمة افتراضية منطقية. + الحقول الاختيارية حقًا: `T | None = None`، يتم حذفها من التسلسل عند `None`. + مثال: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **المعاني الأساسية للتسلسل الهام:** + + عندما يكون `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + عندما `metadata = {}` (فارغة بشكل صريح): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **الفرق الرئيسي:** + `None` → حقل غير موجود في JSON (غير مُسلسل) + قيمة فارغة (`{}`، `[]`، `""`) → حقل موجود بقيمة فارغة + هذا مهم من الناحية الدلالية: "غير مقدم" مقابل "فارغ بشكل صريح" + يجب على أنظمة التسلسل الخلفية تخطي حقول `None`، وليس ترميزها كـ `null` + +## مسودة الحل الثالث: تفاصيل التنفيذ + +### تنسيق اسم قائمة انتظار عام + +استبدل أسماء قوائم الانتظار الخاصة بكل نظام خلفي بتنسيق عام يمكن للأنظمة الخلفية تعيينه بشكل مناسب. + +**التنسيق:** `{qos}/{tenant}/{namespace}/{queue-name}` + +حيث: +`qos`: مستوى جودة الخدمة + `q0` = بذل جهد (إرسال وإهمال، بدون إقرار) + `q1` = مرة واحدة على الأقل (يتطلب إقرارًا) + `q2` = مرة واحدة بالضبط (إقرار من مرحلتين) +`tenant`: تجميع منطقي للتعددية +`namespace`: تجميع فرعي داخل المستأجر +`queue-name`: اسم قائمة الانتظار/الموضوع الفعلي + +**أمثلة:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### ربط الموضوعات في الواجهة الخلفية + +تقوم كل واجهة خلفية بتحويل التنسيق العام إلى تنسيقها الأصلي: + +**الواجهة الخلفية Pulsar:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**الخلفية التقنية لـ MQTT:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### الدالة المساعدة للموضوع المحدّثة + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### التكوين والتهيئة + +**وسائط سطر الأوامر + متغيرات البيئة:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**دالة المصنع:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**الاستخدام في AsyncProcessor:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### الواجهة الخلفية + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### إعادة هيكلة الفئات الحالية + +تظل الفئات الحالية `Consumer`، `Producer`، `Publisher`، `Subscriber` في الغالب دون تغيير: + +**المسؤوليات الحالية (يجب الحفاظ عليها):** +نموذج الخيوط غير المتزامنة ومجموعات المهام. +منطق إعادة الاتصال ومعالجة إعادة المحاولة. +جمع المقاييس. +تحديد المعدل. +إدارة التزامن. + +**التغييرات المطلوبة:** +إزالة استيرادات Pulsar المباشرة (`pulsar.schema`، `pulsar.InitialPosition`، إلخ). +قبول `BackendProducer`/`BackendConsumer` بدلاً من عميل Pulsar. +تفويض عمليات النشر/الاشتراك الفعلية إلى مثيلات الواجهة الخلفية. +مطابقة المفاهيم العامة إلى استدعاءات الواجهة الخلفية. + +**مثال على إعادة الهيكلة:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### السلوكيات الخاصة بالخادم الخلفي + +**الخادم الخلفي Pulsar:** +يربط `q0` → `non-persistent://`، و `q1`/`q2` → `persistent://` +يدعم جميع أنواع المستهلكين (مشترك، حصري، احتياطي) +يدعم الموضع الأولي (الأول/الأخير) +إقرار الرسائل الأصلي +دعم سجل المخططات + +**الخادم الخلفي MQTT:** +يربط `q0`/`q1`/`q2` بمستويات جودة الخدمة MQTT 0/1/2 +يتضمن المستأجر/المساحة الاسمية في مسار الموضوع لعملية التمييز +يقوم بإنشاء معرفات العملاء تلقائيًا من أسماء الاشتراكات +يتجاهل الموضع الأولي (لا يوجد سجل رسائل في MQTT الأساسي) +يتجاهل نوع المستهلك (يستخدم MQTT معرفات العملاء، وليس مجموعات المستهلكين) +نموذج نشر/اشتراك بسيط + +### ملخص قرارات التصميم + +1. ✅ **تسمية قائمة انتظار عامة**: بتنسيق `qos/tenant/namespace/queue-name` +2. ✅ **جودة الخدمة في معرف قائمة الانتظار**: يتم تحديدها بواسطة تعريف قائمة الانتظار، وليس التكوين +3. ✅ **إعادة الاتصال**: تتم معالجتها بواسطة فئات المستهلك/المنتج، وليس الخوادم الخلفية +4. ✅ **مواضيع MQTT**: تتضمن المستأجر/المساحة الاسمية لعملية التمييز المناسبة +5. ✅ **سجل الرسائل**: يتجاهل MQTT معلمة `initial_position` (تحسين مستقبلي) +6. ✅ **معرفات العملاء**: يقوم خادم MQTT بإنشائها تلقائيًا من اسم الاشتراك + +### التحسينات المستقبلية + +**سجل رسائل MQTT:** +يمكن إضافة طبقة تخزين اختيارية (مثل الرسائل المحفوظة، أو مخزن خارجي) +سيسمح بدعم `initial_position='earliest'` +ليس مطلوبًا للتنفيذ الأولي diff --git a/docs/tech-specs/pubsub.es.md b/docs/tech-specs/pubsub.es.md new file mode 100644 index 00000000..be2b6bc5 --- /dev/null +++ b/docs/tech-specs/pubsub.es.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "Infraestructura Pub/Sub" +parent: "Spanish (Beta)" +--- + +# Infraestructura Pub/Sub + +> **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 cataloga todas las conexiones entre el código base de TrustGraph y la infraestructura pub/sub. Actualmente, el sistema está codificado para usar Apache Pulsar. Este análisis identifica todos los puntos de integración para informar futuras refactorizaciones hacia una abstracción pub/sub configurable. + +## Estado actual: Puntos de integración de Pulsar + +### 1. Uso directo del cliente de Pulsar + +**Ubicación:** `trustgraph-flow/trustgraph/gateway/service.py` + +La puerta de enlace de la API importa y crea una instancia directamente del cliente de Pulsar: + +**Línea 20:** `import pulsar` +**Líneas 54-61:** Creación directa de `pulsar.Client()` con `pulsar.AuthenticationToken()` opcional +**Líneas 33-35:** Configuración predeterminada del host de Pulsar desde variables de entorno +**Líneas 178-192:** Argumentos de la línea de comandos para `--pulsar-host`, `--pulsar-api-key` y `--pulsar-listener` +**Líneas 78, 124:** Pasa `pulsar_client` a `ConfigReceiver` y `DispatcherManager` + +Esta es la única ubicación que crea directamente un cliente de Pulsar fuera de la capa de abstracción. + +### 2. Marco base del procesador + +**Ubicación:** `trustgraph-base/trustgraph/base/async_processor.py` + +La clase base para todos los procesadores proporciona conectividad de Pulsar: + +**Línea 9:** `import _pulsar` (para el manejo de excepciones) +**Línea 18:** `from . pubsub import PulsarClient` +**Línea 38:** Crea `pulsar_client_object = PulsarClient(**params)` +**Líneas 104-108:** Propiedades que exponen `pulsar_host` y `pulsar_client` +**Línea 250:** El método estático `add_args()` llama a `PulsarClient.add_args(parser)` para los argumentos de la línea de comandos +**Líneas 223-225:** Manejo de excepciones para `_pulsar.Interrupted` + +Todos los procesadores heredan de `AsyncProcessor`, lo que convierte a este en el punto de integración central. + +### 3. Abstracción del consumidor + +**Ubicación:** `trustgraph-base/trustgraph/base/consumer.py` + +Consume mensajes de colas e invoca funciones de controlador: + +**Importaciones de Pulsar:** +**Línea 12:** `from pulsar.schema import JsonSchema` +**Línea 13:** `import pulsar` +**Línea 14:** `import _pulsar` + +**Uso específico de Pulsar:** +**Líneas 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**Línea 108:** Envoltorio `JsonSchema(self.schema)` +**Línea 110:** `pulsar.ConsumerType.Shared` +**Líneas 104-111:** `self.client.subscribe()` con parámetros específicos de Pulsar +**Líneas 143, 150, 65:** Métodos `consumer.unsubscribe()` y `consumer.close()` +**Línea 162:** Excepción `_pulsar.Timeout` +**Líneas 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**Archivo de especificación:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**Línea 22:** Hace referencia a `processor.pulsar_client` + +### 4. Abstracción del productor + +**Ubicación:** `trustgraph-base/trustgraph/base/producer.py` + +Envía mensajes a colas: + +**Importaciones de Pulsar:** +**Línea 2:** `from pulsar.schema import JsonSchema` + +**Uso específico de Pulsar:** +**Línea 49:** Envoltorio `JsonSchema(self.schema)` +**Líneas 47-51:** `self.client.create_producer()` con parámetros específicos de Pulsar (tema, esquema, habilitación de fragmentación) +**Líneas 31, 76:** Método `producer.close()` +**Líneas 64-65:** `producer.send()` con mensaje y propiedades + +**Archivo de especificación:** `trustgraph-base/trustgraph/base/producer_spec.py` +**Línea 18:** Hace referencia a `processor.pulsar_client` + +### 5. Abstracción del publicador + +**Ubicación:** `trustgraph-base/trustgraph/base/publisher.py` + +Publicación de mensajes asíncrona con almacenamiento en búfer de cola: + +**Importaciones de Pulsar:** +**Línea 2:** `from pulsar.schema import JsonSchema` +**Línea 6:** `import pulsar` + +**Uso específico de Pulsar:** +**Línea 52:** Envoltorio `JsonSchema(self.schema)` +**Líneas 50-54:** `self.client.create_producer()` con parámetros específicos de Pulsar +**Líneas 101, 103:** `producer.send()` con mensaje y propiedades opcionales +**Líneas 106-107:** Métodos `producer.flush()` y `producer.close()` + +### 6. Abstracción del suscriptor + +**Ubicación:** `trustgraph-base/trustgraph/base/subscriber.py` + +Proporciona la distribución de mensajes a múltiples destinatarios desde colas: + +**Importaciones de Pulsar:** +**Línea 6:** `from pulsar.schema import JsonSchema` +**Línea 8:** `import _pulsar` + +**Uso específico de Pulsar:** +**Línea 55:** `JsonSchema(self.schema)` wrapper +**Línea 57:** `self.client.subscribe(**subscribe_args)` +**Líneas 101, 136, 160, 167-172:** Excepciones de Pulsar: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**Líneas 159, 166, 170:** Métodos de consumidor: `negative_acknowledge()`, `unsubscribe()`, `close()` +**Líneas 247, 251:** Reconocimiento de mensajes: `acknowledge()`, `negative_acknowledge()` + +**Archivo de especificaciones:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**Línea 19:** Referencias a `processor.pulsar_client` + +### 7. Sistema de esquemas (Heart of Darkness) + +**Ubicación:** `trustgraph-base/trustgraph/schema/` + +Cada esquema de mensaje en el sistema se define utilizando el marco de esquemas de Pulsar. + +**Primitivos principales:** `schema/core/primitives.py` +**Línea 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +Todos los esquemas heredan de la clase base de Pulsar `Record` +Todos los tipos de campo son tipos de Pulsar: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**Esquemas de ejemplo:** +`schema/services/llm.py` (Línea 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (Línea 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**Nomenclatura de temas:** `schema/core/topic.py` +**Líneas 2-3:** Formato del tema: `{kind}://{tenant}/{namespace}/{topic}` +Esta estructura de URI es específica de Pulsar (por ejemplo, `persistent://tg/flow/config`) + +**Impacto:** +Todas las definiciones de mensajes de solicitud/respuesta en todo el código base utilizan esquemas de Pulsar +Esto incluye servicios para: config, flow, llm, prompt, query, storage, agent, collection, diagnosis, library, lookup, nlp_query, objects_query, retrieval, structured_query +Las definiciones de esquemas se importan y utilizan ampliamente en todos los procesadores y servicios + +## Resumen + +### Dependencias de Pulsar por Categoría + +1. **Instanciación del cliente:** + Directo: `gateway/service.py` + Abstracto: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **Transporte de mensajes:** + Consumidor: `consumer.py`, `consumer_spec.py` + Productor: `producer.py`, `producer_spec.py` + Publicador: `publisher.py` + Suscriptor: `subscriber.py`, `subscriber_spec.py` + +3. **Sistema de esquemas:** + Tipos base: `schema/core/primitives.py` + Todos los esquemas de servicio: `schema/services/*.py` + Nomenclatura de temas: `schema/core/topic.py` + +4. **Conceptos específicos de Pulsar requeridos:** + Mensajería basada en temas + Sistema de esquemas (Registro, tipos de campo) + Suscripciones compartidas + Reconocimiento de mensajes (positivo/negativo) + Posicionamiento del consumidor (más temprano/más reciente) + Propiedades del mensaje + Posiciones iniciales y tipos de consumidor + Soporte de fragmentación + Temas persistentes frente a no persistentes + +### Desafíos de refactorización + +La buena noticia: la capa de abstracción (Consumidor, Productor, Publicador, Suscriptor) proporciona una encapsulación limpia de la mayoría de las interacciones de Pulsar. + +Los desafíos: +1. **Ubicuidad del sistema de esquemas:** Cada definición de mensaje utiliza `pulsar.schema.Record` y los tipos de campo de Pulsar +2. **Enums específicos de Pulsar:** `InitialPosition`, `ConsumerType` +3. **Excepciones de Pulsar:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **Fichas de método:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, etc. +5. **Formato de URI de tema:** Estructura de Pulsar `kind://tenant/namespace/topic` + +### Próximos pasos + +Para hacer que la infraestructura de pub/sub sea configurable, necesitamos: + +1. Crear una interfaz de abstracción para el sistema de cliente/esquemas +2. Abstractar enums y excepciones específicas de Pulsar +3. Crear envoltorios de esquema o definiciones de esquema alternativas +4. Implementar la interfaz tanto para Pulsar como para sistemas alternativos (Kafka, RabbitMQ, Redis Streams, etc.) +5. Actualizar `pubsub.py` para que sea configurable y admita varios backends +6. Proporcionar una ruta de migración para implementaciones existentes + +## Borrador de enfoque 1: Patrón de adaptador con capa de traducción de esquemas + +### Idea clave +El **sistema de esquemas** es el punto de integración más profundo; todo lo demás se deriva de él. Necesitamos resolver esto primero, o tendremos que reescribir todo el código base. + +### Estrategia: Interrupción mínima con adaptadores + +**1. Mantener los esquemas de Pulsar como la representación interna** +No reescribir todas las definiciones de esquemas. +Los esquemas permanecen `pulsar.schema.Record` internamente. +Utilizar adaptadores para traducir en la frontera entre nuestro código y el backend de publicación/suscripción. + +**2. Crear una capa de abstracción de publicación/suscripción:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. Defina interfaces abstractas:** +`PubSubClient` - conexión del cliente +`PubSubProducer` - envío de mensajes +`PubSubConsumer` - recepción de mensajes +`SchemaAdapter` - traducción de esquemas de Pulsar a/desde JSON o formatos específicos del backend + +**4. Detalles de implementación:** + +Para el **adaptador de Pulsar**: Casi una transmisión directa, traducción mínima. + +Para **otros backends** (Kafka, RabbitMQ, etc.): +Serializar objetos de registro de Pulsar a JSON/bytes. +Mapear conceptos como: + `InitialPosition.Earliest/Latest` → auto.offset.reset de Kafka + `acknowledge()` → confirmación de Kafka + `negative_acknowledge()` → patrón de re-cola o cola de mensajes no entregados (DLQ). + URIs de temas → nombres de temas específicos del backend. + +### Análisis + +**Ventajas:** +✅ Cambios mínimos en el código de los servicios existentes. +✅ Los esquemas permanecen sin cambios (sin reescritura masiva). +✅ Ruta de migración gradual. +✅ Los usuarios de Pulsar no notan ninguna diferencia. +✅ Se agregan nuevos backends a través de adaptadores. + +**Desventajas:** +⚠️ Aún mantiene la dependencia de Pulsar (para las definiciones de esquemas). +⚠️ Algunos problemas de compatibilidad al traducir conceptos. + +### Consideración alternativa + +Crear un sistema de esquemas **TrustGraph** que sea independiente de pub/sub (usando dataclasses o Pydantic), y luego generar esquemas de Pulsar/Kafka/etc a partir de él. Esto requiere reescribir cada archivo de esquema y podría provocar cambios importantes. + +### Recomendación para la versión preliminar 1 + +Comience con el **enfoque de adaptador** porque: +1. Es práctico: funciona con el código existente. +2. Demuestra el concepto con un riesgo mínimo. +3. Puede evolucionar hacia un sistema de esquemas nativo más adelante, si es necesario. +4. Impulsado por la configuración: una variable de entorno cambia entre backends. + +## Enfoque de la versión preliminar 2: Sistema de esquemas independiente del backend con dataclasses + +### Concepto central + +Utilice **dataclasses** de Python como el formato de definición de esquema neutral. Cada backend de pub/sub proporciona su propia serialización/deserialización para dataclasses, eliminando la necesidad de que los esquemas de Pulsar permanezcan en el código base. + +### Polimorfismo de esquema a nivel de fábrica + +En lugar de traducir esquemas de Pulsar, **cada backend proporciona su propia gestión de esquemas** que funciona con dataclasses de Python estándar. + +### Flujo del publicador + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### Flujo del consumidor + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### ¿Qué sucede detrás de escena? + +**Para el backend de Pulsar:** +`create_producer()` → crea un productor de Pulsar con un esquema JSON o un registro generado dinámicamente. +`send(request)` → serializa la clase de datos a formato JSON/Pulsar y lo envía a Pulsar. +`receive()` → recibe un mensaje de Pulsar, lo deserializa de nuevo a la clase de datos. + +**Para el backend de MQTT:** +`create_producer()` → se conecta a un broker de MQTT, no es necesario registrar ningún esquema. +`send(request)` → convierte la clase de datos a JSON y lo publica en un tema de MQTT. +`receive()` → se suscribe a un tema de MQTT y deserializa el JSON a la clase de datos. + +**Para el backend de Kafka:** +`create_producer()` → crea un productor de Kafka y registra el esquema Avro si es necesario. +`send(request)` → serializa la clase de datos a formato Avro y lo envía a Kafka. +`receive()` → recibe un mensaje de Kafka y lo deserializa de Avro de nuevo a la clase de datos. + +### Puntos Clave del Diseño + +1. **Creación del objeto de esquema**: La instancia de la clase de datos (`TextCompletionRequest(...)`) es idéntica independientemente del backend. +2. **El backend se encarga de la codificación**: Cada backend sabe cómo serializar su clase de datos al formato de cable. +3. **Definición del esquema en la creación**: Al crear el productor/consumidor, se especifica el tipo de esquema. +4. **Se mantiene la seguridad de tipos**: Se obtiene un objeto `TextCompletionRequest` adecuado, no un diccionario. +5. **Sin filtración del backend**: El código de la aplicación nunca importa bibliotecas específicas del backend. + +### Ejemplo de Transformación + +**Actual (específico de Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**Nuevo (Independiente del backend):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### Integración con el Backend + +Cada backend se encarga de la serialización/deserialización de dataclasses: + +**Backend de Pulsar:** +Genera clases `pulsar.schema.Record` dinámicamente a partir de dataclasses +O serializa dataclasses a JSON y utiliza el esquema JSON de Pulsar +Mantiene la compatibilidad con implementaciones de Pulsar existentes + +**Backend de MQTT/Redis:** +Serialización directa de instancias de dataclass a JSON +Utiliza `dataclasses.asdict()` / `from_dict()` +Ligero, no se necesita un registro de esquemas + +**Backend de Kafka:** +Genera esquemas Avro a partir de definiciones de dataclass +Utiliza el registro de esquemas de Confluent +Serialización con seguridad de tipos y soporte para la evolución del esquema + +### Arquitectura + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### Detalles de implementación + +**1. Definiciones de esquema:** Clases de datos simples con sugerencias de tipo + `str`, `int`, `bool`, `float` para tipos primitivos + `list[T]` para arreglos + `dict[str, T]` para mapas + Clases de datos anidadas para tipos complejos + +**2. Cada backend proporciona:** + Serializador: `dataclass → bytes/wire format` + Deserializador: `bytes/wire format → dataclass` + Registro de esquema (si es necesario, como Pulsar/Kafka) + +**3. Abstracción de consumidor/productor:** + Ya existe (consumer.py, producer.py) + Actualizar para usar la serialización del backend + Eliminar importaciones directas de Pulsar + +**4. Mapeos de tipo:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### Ruta de migración + +1. **Crear versiones de clases de datos** de todos los esquemas en `trustgraph/schema/` +2. **Actualizar clases de backend** (Consumidor, Productor, Publicador, Suscriptor) para usar la serialización proporcionada por el backend +3. **Implementar PulsarBackend** con esquema JSON o generación dinámica de registros +4. **Probar con Pulsar** para garantizar la compatibilidad hacia atrás con las implementaciones existentes +5. **Agregar nuevos backends** (MQTT, Kafka, Redis, etc.) según sea necesario +6. **Eliminar importaciones de Pulsar** de los archivos de esquema + +### Beneficios + +✅ **Sin dependencia de pub/sub** en las definiciones de esquema +✅ **Python estándar** - fácil de entender, tipificar, documentar +✅ **Herramientas modernas** - funciona con mypy, autocompletado de IDE, analizadores +✅ **Optimizada para el backend** - cada backend utiliza la serialización nativa +✅ **Sin sobrecarga de traducción** - serialización directa, sin adaptadores +✅ **Seguridad de tipos** - objetos reales con tipos adecuados +✅ **Validación fácil** - se puede usar Pydantic si es necesario + +### Desafíos y soluciones + +**Desafío:** El `Record` de Pulsar tiene validación de campo en tiempo de ejecución +**Solución:** Usar clases de datos de Pydantic para la validación si es necesario, o características de clase de datos de Python 3.10+ con `__post_init__` + +**Desafío:** Algunas características específicas de Pulsar (como el tipo `Bytes`) +**Solución:** Mapear al tipo `bytes` en la clase de datos, el backend se encarga de la codificación apropiadamente + +**Desafío:** Nombres de temas (`persistent://tenant/namespace/topic`) +**Solución:** Abstracto los nombres de los temas en las definiciones de esquema, el backend convierte al formato adecuado + +**Desafío:** Evolución y versionado del esquema +**Solución:** Cada backend maneja esto de acuerdo con sus capacidades (versiones de esquema de Pulsar, registro de esquema de Kafka, etc.) + +**Desafío:** Tipos complejos anidados +**Solución:** Usar clases de datos anidadas, los backends serializan/deserializan recursivamente + +### Decisiones de diseño + +1. **¿Clases de datos simples o Pydantic?** + ✅ **Decisión: Usar clases de datos de Python simples** + Más simple, sin dependencias adicionales + La validación no es necesaria en la práctica + Más fácil de entender y mantener + +2. **Evolución del esquema:** + ✅ **Decisión: No se necesita un mecanismo de versionado** + Los esquemas son estables y duraderos + Las actualizaciones normalmente agregan nuevos campos (compatible con versiones anteriores) + Los backends manejan la evolución del esquema según sus capacidades + +3. **Compatibilidad hacia atrás:** + ✅ **Decisión: Cambio de versión importante, no se requiere compatibilidad hacia atrás** + Será un cambio importante con instrucciones de migración + La ruptura limpia permite un mejor diseño + Se proporcionará una guía de migración para las implementaciones existentes + +4. **Tipos anidados y estructuras complejas:** + ✅ **Decisión: Usar clases de datos anidadas de forma natural** + Las clases de datos de Python manejan el anidamiento perfectamente + `list[T]` para arreglos, `dict[K, V]` para mapas + Los backends serializan/deserializan recursivamente + Ejemplo: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **Valores predeterminados y campos opcionales:** + ✅ **Decisión: Combinación de campos obligatorios, valores predeterminados y campos opcionales** + Campos obligatorios: Sin valor predeterminado + Campos con valores predeterminados: Siempre presentes, tienen un valor predeterminado razonable + Campos verdaderamente opcionales: `T | None = None`, omitidos de la serialización cuando `None` + Ejemplo: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **Semántica de serialización importante:** + + Cuando `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + Cuando `metadata = {}` (explícitamente vacío): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **Diferencia clave:** + `None` → campo ausente en JSON (no se serializa) + Valor vacío (`{}`, `[]`, `""`) → campo presente con valor vacío + Esto es importante semánticamente: "no proporcionado" vs "explícitamente vacío" + Los sistemas de serialización deben omitir los campos `None`, no codificarlos como `null` + +## Esquema de Implementación Borrador 3: Detalles de Implementación + +### Formato Genérico para Nombres de Colas + +Reemplace los nombres de colas específicos del sistema de respaldo con un formato genérico que los sistemas de respaldo puedan mapear adecuadamente. + +**Formato:** `{qos}/{tenant}/{namespace}/{queue-name}` + +Donde: +`qos`: Nivel de Calidad de Servicio + `q0` = mejor esfuerzo (enviar y olvidar, sin confirmación) + `q1` = al menos una vez (requiere confirmación) + `q2` = exactamente una vez (confirmación de dos fases) +`tenant`: Agrupación lógica para multi-inquilino +`namespace`: Sub-agrupación dentro del inquilino +`queue-name`: Nombre real de la cola/tema + +**Ejemplos:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### Mapeo de temas del backend + +Cada backend mapea el formato genérico a su formato nativo: + +**Backend de Pulsar:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**Backend de MQTT:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### Función de ayuda de tema actualizada + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### Configuración e Inicialización + +**Argumentos de Línea de Comandos + Variables de Entorno:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**Función de Fábrica:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**Uso en AsyncProcessor:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### Interfaz de Backend + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### Refactorización de Clases Existentes + +Las clases existentes `Consumer`, `Producer`, `Publisher`, `Subscriber` permanecen en gran medida intactas: + +**Responsabilidades actuales (mantener):** +Modelo de subprocesos asíncronos y grupos de tareas +Lógica de reconexión y manejo de reintentos +Recopilación de métricas +Limitación de velocidad +Gestión de la concurrencia + +**Cambios necesarios:** +Eliminar importaciones directas de Pulsar (`pulsar.schema`, `pulsar.InitialPosition`, etc.) +Aceptar `BackendProducer`/`BackendConsumer` en lugar del cliente de Pulsar +Delegar las operaciones de publicación/suscripción reales a instancias de backend +Mapear conceptos genéricos a llamadas de backend + +**Ejemplo de refactorización:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### Comportamientos Específicos del Backend + +**Backend de Pulsar:** +Mapea `q0` → `non-persistent://`, `q1`/`q2` → `persistent://` +Soporta todos los tipos de consumidores (compartido, exclusivo, de respaldo) +Soporta la posición inicial (earliest/latest) +Reconocimiento nativo de mensajes +Soporte para el registro de esquemas + +**Backend de MQTT:** +Mapea `q0`/`q1`/`q2` → Niveles de QoS de MQTT 0/1/2 +Incluye el inquilino/espacio de nombres en la ruta del tema para el espaciado de nombres +Genera automáticamente ID de cliente a partir de los nombres de suscripción +Ignora la posición inicial (no hay historial de mensajes en MQTT básico) +Ignora el tipo de consumidor (MQTT utiliza ID de cliente, no grupos de consumidores) +Modelo de publicación/suscripción simple + +### Resumen de Decisiones de Diseño + +1. ✅ **Nombres de cola genéricos**: Formato `qos/tenant/namespace/queue-name` +2. ✅ **QoS en el ID de la cola**: Determinado por la definición de la cola, no por la configuración +3. ✅ **Reconexión**: Manejada por las clases Consumer/Producer, no por los backends +4. ✅ **Temas de MQTT**: Incluir inquilino/espacio de nombres para un espaciado de nombres adecuado +5. ✅ **Historial de mensajes**: MQTT ignora el parámetro `initial_position` (mejora futura) +6. ✅ **ID de cliente**: El backend de MQTT genera automáticamente a partir del nombre de la suscripción + +### Mejoras Futuras + +**Historial de mensajes de MQTT:** +Se podría agregar una capa de persistencia opcional (por ejemplo, mensajes retenidos, almacenamiento externo) +Permitiría soportar `initial_position='earliest'` +No es necesario para la implementación inicial diff --git a/docs/tech-specs/pubsub.he.md b/docs/tech-specs/pubsub.he.md new file mode 100644 index 00000000..90aeadd3 --- /dev/null +++ b/docs/tech-specs/pubsub.he.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "תשתית Pub/Sub" +parent: "Hebrew (Beta)" +--- + +# תשתית Pub/Sub + +> **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 לתשתית ה-pub/sub. כיום, המערכת מקודדת בצורה קבועה לשימוש ב-Apache Pulsar. ניתוח זה מזהה את כל נקודות האינטגרציה כדי ליידע שינויים עתידיים לכיוון הפשטה של pub/sub הניתנת לתצורה. + +## מצב נוכחי: נקודות אינטגרציה של Pulsar + +### 1. שימוש ישיר בלקוח Pulsar + +**מיקום:** `trustgraph-flow/trustgraph/gateway/service.py` + +שער ה-API מייבא ויוצר ישירות את לקוח ה-Pulsar: + +**שורה 20:** `import pulsar` +**שורות 54-61:** יצירה ישירה של `pulsar.Client()` עם `pulsar.AuthenticationToken()` אופציונלי +**שורות 33-35:** תצורת מארח ברירת מחדל של Pulsar ממשתני סביבה +**שורות 178-192:** ארגומנטים של שורת הפקודה עבור `--pulsar-host`, `--pulsar-api-key` ו-`--pulsar-listener` +**שורות 78, 124:** מעביר `pulsar_client` ל-`ConfigReceiver` ו-`DispatcherManager` + +זה המיקום היחיד שבו נוצר ישירות לקוח Pulsar מחוץ לשכבת ההפשטה. + +### 2. מסגרת מעבד בסיסית + +**מיקום:** `trustgraph-base/trustgraph/base/async_processor.py` + +המחלקה הבסיסית לכל המעבדים מספקת קישוריות ל-Pulsar: + +**שורה 9:** `import _pulsar` (לטיפול בחריגים) +**שורה 18:** `from . pubsub import PulsarClient` +**שורה 38:** יוצר `pulsar_client_object = PulsarClient(**params)` +**שורות 104-108:** מאפיינים החושפים `pulsar_host` ו-`pulsar_client` +**שורה 250:** שיטה סטטית `add_args()` קוראת ל-`PulsarClient.add_args(parser)` עבור ארגומנטים של שורת הפקודה +**שורות 223-225:** טיפול בחריגים עבור `_pulsar.Interrupted` + +כל המעבדים יורשים מ-`AsyncProcessor`, מה שהופך זאת לנקודת האינטגרציה המרכזית. + +### 3. הפשטת צרכן + +**מיקום:** `trustgraph-base/trustgraph/base/consumer.py` + +צורך הודעות מתורים ומפעיל פונקציות מטפלות: + +**ייבוא של Pulsar:** +**שורה 12:** `from pulsar.schema import JsonSchema` +**שורה 13:** `import pulsar` +**שורה 14:** `import _pulsar` + +**שימוש ספציפי ל-Pulsar:** +**שורות 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**שורה 108:** עטיפה של `JsonSchema(self.schema)` +**שורה 110:** `pulsar.ConsumerType.Shared` +**שורות 104-111:** `self.client.subscribe()` עם פרמטרים ספציפיים ל-Pulsar +**שורות 143, 150, 65:** שיטות `consumer.unsubscribe()` ו-`consumer.close()` +**שורה 162:** חריגה של `_pulsar.Timeout` +**שורות 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**קובץ מפרט:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**שורה 22:** מפנה ל-`processor.pulsar_client` + +### 4. הפשטת מפרסם + +**מיקום:** `trustgraph-base/trustgraph/base/producer.py` + +שולח הודעות לתורים: + +**ייבוא של Pulsar:** +**שורה 2:** `from pulsar.schema import JsonSchema` + +**שימוש ספציפי ל-Pulsar:** +**שורה 49:** עטיפה של `JsonSchema(self.schema)` +**שורות 47-51:** `self.client.create_producer()` עם פרמטרים ספציפיים ל-Pulsar (נושא, סכימה, הפעלה של חלוקה לחלקים) +**שורות 31, 76:** שיטה `producer.close()` +**שורות 64-65:** `producer.send()` עם הודעה ומאפיינים + +**קובץ מפרט:** `trustgraph-base/trustgraph/base/producer_spec.py` +**שורה 18:** מפנה ל-`processor.pulsar_client` + +### 5. הפשטת מפרסם + +**מיקום:** `trustgraph-base/trustgraph/base/publisher.py` + +פרסום הודעות אסינכרוני עם חיץ תורים: + +**ייבוא של Pulsar:** +**שורה 2:** `from pulsar.schema import JsonSchema` +**שורה 6:** `import pulsar` + +**שימוש ספציפי ל-Pulsar:** +**שורה 52:** עטיפה של `JsonSchema(self.schema)` +**שורות 50-54:** `self.client.create_producer()` עם פרמטרים ספציפיים ל-Pulsar +**שורות 101, 103:** `producer.send()` עם הודעה ומאפיינים אופציונליים +**שורות 106-107:** שיטות `producer.flush()` ו-`producer.close()` + +### 6. הפשטת מנוי + +**מיקום:** `trustgraph-base/trustgraph/base/subscriber.py` + +מספק הפצת הודעות למספר נמענים ממחזורים: + +**ייבוא מ-Pulsar:** +**שורה 6:** `from pulsar.schema import JsonSchema` +**שורה 8:** `import _pulsar` + +**שימוש ספציפי ל-Pulsar:** +**שורה 55:** `JsonSchema(self.schema)` wrapper +**שורה 57:** `self.client.subscribe(**subscribe_args)` +**שורות 101, 136, 160, 167-172:** חריגות של Pulsar: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**שורות 159, 166, 170:** שיטות צרכן: `negative_acknowledge()`, `unsubscribe()`, `close()` +**שורות 247, 251:** אישור הודעות: `acknowledge()`, `negative_acknowledge()` + +**קובץ מפרט:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**שורה 19:** מפנה ל-`processor.pulsar_client` + +### 7. מערכת סכימות (Heart of Darkness) + +**מיקום:** `trustgraph-base/trustgraph/schema/` + +כל סכימת הודעה במערכת מוגדרת באמצעות מסגרת הסכימות של Pulsar. + +**אלמנטים בסיסיים:** `schema/core/primitives.py` +**שורה 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +כל הסכימות יורשות מהמחלקה הבסיסית של Pulsar `Record` +כל סוגי השדות הם סוגי Pulsar: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**דוגמאות לסכימות:** +`schema/services/llm.py` (שורה 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (שורה 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**שמות נושאים:** `schema/core/topic.py` +**שורות 2-3:** פורמט נושא: `{kind}://{tenant}/{namespace}/{topic}` +מבנה ה-URI הזה ספציפי ל-Pulsar (לדוגמה, `persistent://tg/flow/config`) + +**השפעה:** +כל הגדרות הודעות בקשות/תגובות בכל בסיס הקוד משתמשות בסכימות של Pulsar +זה כולל שירותים עבור: config, flow, llm, prompt, query, storage, agent, collection, diagnosis, library, lookup, nlp_query, objects_query, retrieval, structured_query +הגדרות סכימות מיובאות ומשמשות באופן נרחב בכל המעבדים והשירותים + +## סיכום + +### תלויות של Pulsar לפי קטגוריה + +1. **יצירת מופע לקוח:** + ישיר: `gateway/service.py` + מופשט: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **העברת הודעות:** + צרכן: `consumer.py`, `consumer_spec.py` + מפיק: `producer.py`, `producer_spec.py` + מפרסם: `publisher.py` + מנוי: `subscriber.py`, `subscriber_spec.py` + +3. **מערכת סכימות:** + סוגים בסיסיים: `schema/core/primitives.py` + כל סכימות השירות: `schema/services/*.py` + שמות נושאים: `schema/core/topic.py` + +4. **מושגים ספציפיים ל-Pulsar הנדרשים:** + העברת הודעות מבוססת נושאים + מערכת סכימות (Record, סוגי שדות) + מנויים משותפים + אישור הודעות (חיובי/שלילי) + מיקום צרכן (מוקדם/מאוחר) + מאפייני הודעות + מיקומים התחלתיים וסוגי צרכנים + תמיכה בפיצול + נושאים קבועים לעומת לא קבועים + +### אתגרי שינוי מבנה + +החדשות הטובות: שכבת ההפשטה (צרכן, מפיק, מפרסם, מנוי) מספקת אריזה נקייה של רוב האינטראקציות של Pulsar. + +האתגרים: +1. **הנחת סכימות נרחבת:** כל הגדרת הודעה משתמשת ב-`pulsar.schema.Record` ובסוגי Pulsar +2. **אנונימים ספציפיים ל-Pulsar:** `InitialPosition`, `ConsumerType` +3. **חריגות של Pulsar:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **חתימות שיטות:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, וכו'. +5. **פורמט URI של נושא:** מבנה `kind://tenant/namespace/topic` של Pulsar + +### שלבים הבאים + +כדי להפוך את התשתית של pub/sub לכזו שניתן להגדיר, עלינו: + +1. ליצור ממשק הפשטה עבור מערכת הלקוח/סכימות +2. להפשיט אנונימים ספציפיים ל-Pulsar וחריגות +3. ליצור עטיפות סכימות או הגדרות סכימות חלופיות +4. ליישם את הממשק הן עבור Pulsar והן עבור מערכות חלופיות (Kafka, RabbitMQ, Redis Streams, וכו') +5. לעדכן את `pubsub.py` כך שניתן יהיה להגדיר אותו ולתמוך במספר מערכות אחוריות +6. לספק נתיב מעבר לפריסות קיימות + +## טיוטת גישה 1: תבנית מתאם עם שכבת תרגום סכימות + +### הערה + + +### אסטרטגיה: הפרעה מינימלית באמצעות מתאמים + +**1. שמירה על סכימות Pulsar כייצוג הפנימי** +אין לשכתב את כל הגדרות הסכימות. +הסכימות נשארות `pulsar.schema.Record` באופן פנימי. +השתמשו במתאמים כדי לתרגם בגבול בין הקוד שלנו לבין ה-backend של ה-pub/sub. + +**2. יצירת שכבת הפשטה עבור pub/sub:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. הגדרת ממשקים מופשטים:** +`PubSubClient` - חיבור לקוח +`PubSubProducer` - שליחת הודעות +`PubSubConsumer` - קבלת הודעות +`SchemaAdapter` - המרת סכימות Pulsar ל-JSON או פורמטים ספציפיים ל-backend + +**4. פרטי יישום:** + +עבור **מתאם Pulsar**: כמעט העברה ישירה, המרה מינימלית + +עבור **backends אחרים** (Kafka, RabbitMQ, וכו'): +סריאליזציה של אובייקטי Pulsar Record ל-JSON/bytes +מיפוי מושגים כמו: + `InitialPosition.Earliest/Latest` → auto.offset.reset של Kafka + `acknowledge()` → commit של Kafka + `negative_acknowledge()` → תבנית Re-queue או DLQ + URIs של נושאים → שמות נושאים ספציפיים ל-backend + +### ניתוח + +**יתרונות:** +✅ שינויים מינימליים בקוד של שירותים קיימים +✅ הסכימות נשארות כפי שהן (ללא כתיבה מחדש מסיבית) +✅ מסלול מעבר הדרגתי +✅ משתמשי Pulsar לא רואים הבדל +✅ backends חדשים מתווספים באמצעות מתאמים + +**חסרונות:** +⚠️ עדיין כולל תלות ב-Pulsar (לצרכי הגדרות סכימה) +⚠️ חוסר התאמה מסוים בהמרת מושגים + +### שיקול חלופי + +ליצור **מערכת סכימות TrustGraph** שאינה תלויה ב-pub/sub ספציפי (תוך שימוש ב-dataclasses או Pydantic), ולאחר מכן ליצור סכימות Pulsar/Kafka/וכו מתוך זה. זה דורש כתיבה מחדש של כל קובץ סכימה ועלול לגרום לשינויים משמעותיים. + +### המלצה עבור טיוטה 1 + +להתחיל עם **גישת המתאם** מכיוון ש: +1. זה פרגמטי - עובד עם קוד קיים +2. מוכיח את הקונספט עם סיכון מינימלי +3. ניתן להתפתח למערכת סכימה מקומית יותר בעתיד אם יש צורך +4. מונחה תצורה: משתנה סביבה אחד משנה את ה-backends + +## גישה טיוטה 2: מערכת סכימות עצמאית מ-backend באמצעות Dataclasses + +### מושג מרכזי + +להשתמש ב-**dataclasses** של Python כפורמט הגדרת סכימה ניטרלי. כל backend של pub/sub מספק את הסריאליזציה/דה-סריאליזציה שלו עבור dataclasses, מה שמבטל את הצורך לשמור על סכימות Pulsar בקוד הבסיס. + +### פולימורפיזם של סכימה ברמת המפעל + +במקום להמיר סכימות Pulsar, **כל backend מספק את הטיפול שלו בסכימות** שעובד עם dataclasses סטנדרטיים של Python. + +### זרימת פרסום + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### זרימת לקוח + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### מה קורה מאחורי הקלעים + +**עבור ה-backend של Pulsar:** +`create_producer()` → יוצר יצרן Pulsar עם סכימה JSON או רשומה שנוצרה באופן דינמי +`send(request)` → ממיר את מחלקת הנתונים לפורמט JSON/Pulsar, שולח ל-Pulsar +`receive()` → מקבל הודעת Pulsar, ממיר חזרה למחלקת נתונים + +**עבור ה-backend של MQTT:** +`create_producer()` → מתחבר ל-MQTT broker, אין צורך ברישום סכימה +`send(request)` → ממיר מחלקת נתונים ל-JSON, מפרסם לנושא MQTT +`receive()` → נרשם לנושא MQTT, ממיר JSON למחלקת נתונים + +**עבור ה-backend של Kafka:** +`create_producer()` → יוצר יצרן Kafka, רושם סכימת Avro במידת הצורך +`send(request)` → ממיר מחלקת נתונים לפורמט Avro, שולח ל-Kafka +`receive()` → מקבל הודעת Kafka, ממיר Avro חזרה למחלקת נתונים + +### נקודות עיצוב מרכזיות + +1. **יצירת אובייקט סכימה**: מופע מחלקת הנתונים (`TextCompletionRequest(...)`) זהה ללא קשר ל-backend +2. **ה-backend מטפל בקידוד**: כל backend יודע כיצד לתרגם את מחלקת הנתונים לפורמט הנתונים +3. **הגדרת סכימה ביצירה**: בעת יצירת יצרן/צרכן, מציינים את סוג הסכימה +4. **שמירה על בטיחות טיפוסים**: מקבלים בחזרה אובייקט `TextCompletionRequest` תקין, ולא מילון +5. **ללא חשיפה ל-backend**: קוד האפליקציה לעולם לא מייבא ספריות ספציפיות ל-backend + +### דוגמה לטרנספורמציה + +**נוכחי (ספציפי ל-Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**חדש (בלתי תלוי בטכנולוגיית השרת):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### אינטגרציה עם השרת האחורי + +כל שרת אחורי מטפל בסריאליזציה/דה-סריאליזציה של מחלקות נתונים: + +**שרת אחורי של Pulsar:** +יצירת מחלקות `pulsar.schema.Record` באופן דינמי ממחלקות נתונים +או סריאליזציה של מחלקות נתונים ל-JSON ושימוש בסכימה של JSON של Pulsar +שומר על תאימות לפריסות Pulsar קיימות + +**שרת אחורי של MQTT/Redis:** +סריאליזציה ישירה של מופעים של מחלקות נתונים ל-JSON +שימוש ב-`dataclasses.asdict()` / `from_dict()` +קל משקל, לא נדרש רישום סכימות + +**שרת אחורי של Kafka:** +יצירת סכימות Avro מהגדרות של מחלקות נתונים +שימוש ברישום סכימות של Confluent +סריאליזציה בטוחה עם תמיכה באבולוציה של סכימות + +### ארכיטקטורה + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### פרטי יישום + +**1. הגדרות סכימה:** מחלקות נתונים פשוטות עם רמזי סוג + `str`, `int`, `bool`, `float` עבור ערכים בסיסיים + `list[T]` עבור מערכים + `dict[str, T]` עבור מפות + מחלקות נתונים מקוננות עבור סוגים מורכבים + +**2. כל ממשק מספק:** + ממיר: `dataclass → bytes/wire format` + ממיר הפוך: `bytes/wire format → dataclass` + רישום סכימה (אם נדרש, כמו Pulsar/Kafka) + +**3. הפשטה של צרכן/משדר:** + כבר קיים (consumer.py, producer.py) + עדכון לשימוש בשימוש בשידור של הממשק + הסרת יבוא ישיר של Pulsar + +**4. התאמות סוג:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### נתיב מעבר + +1. **צור גרסאות של מחלקות נתונים** עבור כל הסכימות ב-`trustgraph/schema/` +2. **עדכן מחלקות ממשק** (צרכן, משדר, מפרסם, מנוי) לשימוש בשידור שמסופק על ידי הממשק +3. **יישם PulsarBackend** עם סכימה ב-JSON או יצירת רשומות דינמית +4. **בדוק עם Pulsar** כדי להבטיח תאימות לאחור עם פריסות קיימות +5. **הוסף ממשקים חדשים** (MQTT, Kafka, Redis, וכו') לפי הצורך +6. **הסר יבוא של Pulsar** מקבצי סכימה + +### יתרונות + +✅ **ללא תלות ב-pub/sub** בהגדרות סכימה +✅ **Python סטנדרטי** - קל להבנה, בדיקת סוגים, תיעוד +✅ **כלים מודרניים** - עובד עם mypy, השלמה אוטומטית של IDE, כלי ניתוח +✅ **מותאם לממשק** - כל ממשק משתמש בשידור מקומי +✅ **ללא תקורה של תרגום** - שידור ישיר, ללא מתאמים +✅ **בטיחות סוג** - אובייקטים אמיתיים עם סוגים מתאימים +✅ **אימות קל** - ניתן להשתמש ב-Pydantic אם נדרש + +### אתגרים ופתרונות + +**אתגר:** ל-Pulsar יש `Record` עם אימות שדה בזמן ריצה +**פתרון:** השתמש במחלקות נתונים של Pydantic לאימות אם נדרש, או בתכונות של מחלקת נתונים של Python 3.10+ עם `__post_init__` + +**אתגר:** תכונות ספציפיות של Pulsar (כמו סוג `Bytes`) +**פתרון:** התאם לסוג `bytes` במחלקת נתונים, הממשק מטפל בקידוד המתאים + +**אתגר:** שמות נושא (`persistent://tenant/namespace/topic`) +**פתרון:** הפשט שמות נושא בהגדרות סכימה, הממשק ממיר לפורמט המתאים + +**אתגר:** אבולוציה וגרסאות של סכימה +**פתרון:** כל ממשק מטפל בכך בהתאם ליכולות שלו (גרסאות סכימה של Pulsar, רישום סכימה של Kafka, וכו') + +**אתגר:** סוגים מורכבים מקוננים +**פתרון:** השתמש במחלקות נתונים מקוננות, הממשקים מבצעים שידור/פענוח רקורסיבי + +### החלטות עיצוב + +1. **מחלקות נתונים פשוטות או Pydantic?** + ✅ **החלטה: השתמש במחלקות נתונים של Python פשוטות** + פשוט יותר, ללא תלויות נוספות + אימות אינו נדרש בפועל + קל יותר להבנה ולתחזוקה + +2. **אבולוציה של סכימה:** + ✅ **החלטה: לא נדרש מנגנון גרסאות** + הסכימות יציבות וקיימות לאורך זמן + עדכונים בדרך כלל מוסיפים שדות חדשים (תואמים לאחור) + ממשקים מטפלים באבולוציה של סכימה בהתאם ליכולות שלהם + +3. **תאימות לאחור:** + ✅ **החלטה: שינוי גרסה עיקרית, תאימות לאחור אינה נדרשת** + יהיה שינוי משמעותי עם הוראות מעבר + ניתוק נקי מאפשר עיצוב טוב יותר + מדריך מעבר יסופק עבור פריסות קיימות + +4. **סוגים מקוננים ומבנים מורכבים:** + ✅ **החלטה: השתמש במחלקות נתונים מקוננות באופן טבעי** + מחלקות נתונים של Python מטפלות בקינון בצורה מושלמת + `list[T]` עבור מערכים, `dict[K, V]` עבור מפות + ממשקים מבצעים שידור/פענוח רקורסיבי + דוגמה: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **ערכים ברירת מחדל ושדות אופציונליים:** + ✅ **החלטה: שילוב של שדות חובה, ערכי ברירת מחדל ושדות אופציונליים** + שדות חובה: ללא ערך ברירת מחדל + שדות עם ערכי ברירת מחדל: תמיד נוכחים, בעלי ערך ברירת מחדל הגיוני + שדות אופציונליים לחלוטין: `T | None = None`, מושמטים מסריאליזציה כאשר `None` + דוגמה: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **סמנטיקה חשובה של סריאליזציה:** + + כאשר `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + כאשר `metadata = {}` (ריק במפורש): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **ההבחנה העיקרית:** + `None` → שדה שאינו קיים ב-JSON (לא מיוצא) + ערך ריק (`{}`, `[]`, `""`) → שדה קיים עם ערך ריק + זה חשוב מבחינה סמנטית: "לא סופק" לעומת "ריק באופן מפורש" + מערכות הקידוד חייבות לדלג על שדות `None`, ולא לקודד אותם כ-`null` + +## טיוטה 3 של הגישה: פרטי יישום + +### פורמט שם תור גנרי + +החליפו שמות תורים ספציפיים לכל מערכת קידוד בפורמט גנרי שמערכות הקידוד יכולות למפות בהתאם. + +**פורמט:** `{qos}/{tenant}/{namespace}/{queue-name}` + +כאשר: +`qos`: רמת שירות (Quality of Service) + `q0` = מאמץ מינימלי (שליחה ללא אישור) + `q1` = לפחות פעם אחת (דורש אישור) + `q2` = בדיוק פעם אחת (אישור בשני שלבים) +`tenant`: קיבוץ לוגי עבור ריבוי דיירים +`namespace`: תת-קיבוץ בתוך דייר +`queue-name`: שם התור/נושא בפועל + +**דוגמאות:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### מיפוי נושאים בצד השרת + +כל צד שרת ממפה את הפורמט הכללי לפורמט הייחודי שלו: + +**צד שרת Pulsar:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**שרת MQTT:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### פונקציית עזר מעודכנת לנושא + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### הגדרות ואתחול + +**ארגומנטים של שורת הפקודה + משתני סביבה:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**פונקציית יצירה:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**שימוש ב-AsyncProcessor:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### ממשק צד שרת + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### שינוי מבנה מחלקות קיימות + +המחלקות הקיימות `Consumer`, `Producer`, `Publisher`, `Subscriber` נשארות ברובן ללא שינוי: + +**אחריות נוכחית (לשמור):** +מודל תהליכים אסינכרוניים וקבוצות משימות +לוגיקת חיבור מחדש וטיפול בכישלונות +איסוף מדדים +הגבלת קצב +ניהול תחרות + +**שינויים נדרשים:** +הסרת יבוא ישיר של Pulsar (`pulsar.schema`, `pulsar.InitialPosition`, וכו') +קבלת `BackendProducer`/`BackendConsumer` במקום לקוח Pulsar +העברת פעולות פרסום/מנוי בפועל לאינסטנסים אחוריים +התאמת מושגים כלליים לפעולות אחוריות + +**דוגמה לשינוי מבנה:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### התנהגויות ספציפיות לצד האחורי (Backend) + +**צד אחורי Pulsar:** +ממפה `q0` → `non-persistent://`, `q1`/`q2` → `persistent://` +תומך בכל סוגי הצרכנים (משותף, בלעדי, גיבוי) +תומך בעמדה התחלתית (הכי מוקדם/הכי מאוחר) +אישור הודעות מקורי +תמיכה ברישום סכימות + +**צד אחורי MQTT:** +ממפה `q0`/`q1`/`q2` → רמות QoS של MQTT 0/1/2 +כולל שוכר/מרחב שם בנתיב הנושא לצורך הפרדה +מייצר באופן אוטומטי מזהי לקוח משמות מנויים +מתעלם מעמדה התחלתית (אין היסטוריית הודעות ב-MQTT בסיסי) +מתעלם מסוג צרכן (MQTT משתמש במזהי לקוח, לא בקבוצות צרכנים) +מודל פרסום/מנוי פשוט + +### סיכום החלטות עיצוב + +1. ✅ **שמות תורים גנריים**: פורמט `qos/tenant/namespace/queue-name` +2. ✅ **רמת QoS במזהה תור**: נקבעת על ידי הגדרת התור, ולא על ידי תצורה +3. ✅ **חיבור מחדש**: מטופל על ידי מחלקות צרכן/מפיק, ולא על ידי הצד האחורי +4. ✅ **נושאים של MQTT**: כוללים שוכר/מרחב שם לצורך הפרדה תקינה +5. ✅ **היסטוריית הודעות**: MQTT מתעלם מהפרמטר `initial_position` (שיפור עתידי) +6. ✅ **מזהי לקוח**: צד אחורי MQTT מייצר באופן אוטומטי משם מנוי + +### שיפורים עתידיים + +**היסטוריית הודעות של MQTT:** +ניתן להוסיף שכבת שמירה אופציונלית (לדוגמה, הודעות שמורות, אחסון חיצוני) +יאפשר תמיכה ב-`initial_position='earliest'` +לא נדרש ליישום ראשוני diff --git a/docs/tech-specs/pubsub.hi.md b/docs/tech-specs/pubsub.hi.md new file mode 100644 index 00000000..5a365a56 --- /dev/null +++ b/docs/tech-specs/pubsub.hi.md @@ -0,0 +1,965 @@ +--- +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. डायरेक्ट पल्सर क्लाइंट उपयोग + +**स्थान:** `trustgraph-flow/trustgraph/gateway/service.py` + +एपीआई गेटवे सीधे पल्सर क्लाइंट को आयात और इंस्टेंट करता है: + +**पंक्ति 20:** `import pulsar` +**पंक्तियाँ 54-61:** `pulsar.Client()` का प्रत्यक्ष इंस्टेंटेशन, वैकल्पिक `pulsar.AuthenticationToken()` के साथ +**पंक्तियाँ 33-35:** पर्यावरण चर से डिफ़ॉल्ट पल्सर होस्ट कॉन्फ़िगरेशन +**पंक्तियाँ 178-192:** `--pulsar-host`, `--pulsar-api-key` और `--pulsar-listener` के लिए CLI तर्क +**पंक्तियाँ 78, 124:** `pulsar_client` को `ConfigReceiver` और `DispatcherManager` को पास करता है + +यह एकमात्र स्थान है जहां पल्सर क्लाइंट को एब्स्ट्रैक्शन लेयर के बाहर सीधे इंस्टेंट किया गया है। + +### 2. बेस प्रोसेसर फ्रेमवर्क + +**स्थान:** `trustgraph-base/trustgraph/base/async_processor.py` + +सभी प्रोसेसर के लिए बेस क्लास पल्सर कनेक्टिविटी प्रदान करता है: + +**पंक्ति 9:** `import _pulsar` (अपवाद हैंडलिंग के लिए) +**पंक्ति 18:** `from . pubsub import PulsarClient` +**पंक्ति 38:** `pulsar_client_object = PulsarClient(**params)` बनाता है +**पंक्तियाँ 104-108:** गुण जो `pulsar_host` और `pulsar_client` को उजागर करते हैं +**पंक्ति 250:** स्थैतिक विधि `add_args()` CLI तर्कों के लिए `PulsarClient.add_args(parser)` को कॉल करता है +**पंक्तियाँ 223-225:** `_pulsar.Interrupted` के लिए अपवाद हैंडलिंग + +सभी प्रोसेसर `AsyncProcessor` से इनहेरिट करते हैं, जिससे यह केंद्रीय एकीकरण बिंदु बन जाता है। + +### 3. उपभोक्ता एब्स्ट्रैक्शन + +**स्थान:** `trustgraph-base/trustgraph/base/consumer.py` + +यह कतारों से संदेशों का उपभोग करता है और हैंडलर फ़ंक्शन को लागू करता है: + +**पल्सर आयात:** +**पंक्ति 12:** `from pulsar.schema import JsonSchema` +**पंक्ति 13:** `import pulsar` +**पंक्ति 14:** `import _pulsar` + +**पल्सर-विशिष्ट उपयोग:** +**पंक्तियाँ 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**पंक्ति 108:** `JsonSchema(self.schema)` रैपर +**पंक्ति 110:** `pulsar.ConsumerType.Shared` +**पंक्तियाँ 104-111:** पल्सर-विशिष्ट मापदंडों के साथ `self.client.subscribe()` +**पंक्तियाँ 143, 150, 65:** `consumer.unsubscribe()` और `consumer.close()` विधियाँ +**पंक्ति 162:** `_pulsar.Timeout` अपवाद +**पंक्तियाँ 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**स्पेक फ़ाइल:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**पंक्ति 22:** `processor.pulsar_client` को संदर्भित करता है + +### 4. उत्पादक एब्स्ट्रैक्शन + +**स्थान:** `trustgraph-base/trustgraph/base/producer.py` + +यह कतारों में संदेश भेजता है: + +**पल्सर आयात:** +**पंक्ति 2:** `from pulsar.schema import JsonSchema` + +**पल्सर-विशिष्ट उपयोग:** +**पंक्ति 49:** `JsonSchema(self.schema)` रैपर +**पंक्तियाँ 47-51:** पल्सर-विशिष्ट मापदंडों (विषय, स्कीमा, चंकिंग_सक्षम) के साथ `self.client.create_producer()` +**पंक्तियाँ 31, 76:** `producer.close()` विधि +**पंक्तियाँ 64-65:** संदेश और गुणों के साथ `producer.send()` + +**स्पेक फ़ाइल:** `trustgraph-base/trustgraph/base/producer_spec.py` +**पंक्ति 18:** `processor.pulsar_client` को संदर्भित करता है + +### 5. प्रकाशक एब्स्ट्रैक्शन + +**स्थान:** `trustgraph-base/trustgraph/base/publisher.py` + +यह कतार बफरिंग के साथ एसिंक्रोनस संदेश प्रकाशन है: + +**पल्सर आयात:** +**पंक्ति 2:** `from pulsar.schema import JsonSchema` +**पंक्ति 6:** `import pulsar` + +**पल्सर-विशिष्ट उपयोग:** +**पंक्ति 52:** `JsonSchema(self.schema)` रैपर +**पंक्तियाँ 50-54:** पल्सर-विशिष्ट मापदंडों के साथ `self.client.create_producer()` +**पंक्तियाँ 101, 103:** संदेश और वैकल्पिक गुणों के साथ `producer.send()` +**पंक्तियाँ 106-107:** `producer.flush()` और `producer.close()` विधियाँ + +### 6. सब्सक्राइबर एब्स्ट्रैक्शन + +**स्थान:** `trustgraph-base/trustgraph/base/subscriber.py` + +यह क्यूज़ से मल्टी-रिसीवर मैसेज डिस्ट्रीब्यूशन प्रदान करता है: + +**पल्सर इम्पोर्ट्स:** +**लाइन 6:** `from pulsar.schema import JsonSchema` +**लाइन 8:** `import _pulsar` + +**पल्सर-विशिष्ट उपयोग:** +**लाइन 55:** `JsonSchema(self.schema)` रैपर +**लाइन 57:** `self.client.subscribe(**subscribe_args)` +**लाइनें 101, 136, 160, 167-172:** पल्सर अपवाद: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**लाइनें 159, 166, 170:** उपभोक्ता विधियाँ: `negative_acknowledge()`, `unsubscribe()`, `close()` +**लाइनें 247, 251:** मैसेज स्वीकृति: `acknowledge()`, `negative_acknowledge()` + +**स्पेक फाइल:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**लाइन 19:** संदर्भ `processor.pulsar_client` + +### 7. स्कीमा सिस्टम (हार्ट ऑफ डार्कनेस) + +**स्थान:** `trustgraph-base/trustgraph/schema/` + +सिस्टम में हर मैसेज स्कीमा पल्सर के स्कीमा फ्रेमवर्क का उपयोग करके परिभाषित किया गया है। + +**कोर प्रिमिटिव्स:** `schema/core/primitives.py` +**लाइन 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +सभी स्कीमा पल्सर के `Record` बेस क्लास से इनहेरिट होते हैं +सभी फ़ील्ड प्रकार पल्सर प्रकार हैं: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**उदाहरण स्कीमा:** +`schema/services/llm.py` (लाइन 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (लाइन 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**टॉपिक नामकरण:** `schema/core/topic.py` +**लाइनें 2-3:** टॉपिक फॉर्मेट: `{kind}://{tenant}/{namespace}/{topic}` +यह URI संरचना पल्सर-विशिष्ट है (जैसे, `persistent://tg/flow/config`) + +**प्रभाव:** +पूरे कोडबेस में सभी अनुरोध/प्रतिक्रिया मैसेज परिभाषाएँ पल्सर स्कीमा का उपयोग करती हैं +इसमें निम्नलिखित के लिए सेवाएँ शामिल हैं: कॉन्फ़िग, फ्लो, एलएलएम, प्रॉम्प्ट, क्वेरी, स्टोरेज, एजेंट, कलेक्शन, डायग्नोसिस, लाइब्रेरी, लुकअप, एनएलपी_क्वेरी, ऑब्जेक्ट्स_क्वेरी, रिट्रीवल, स्ट्रक्चर्ड_क्वेरी +स्कीमा परिभाषाएँ सभी प्रोसेसर और सेवाओं में आयात की जाती हैं और व्यापक रूप से उपयोग की जाती हैं + +## सारांश + +### श्रेणी के अनुसार पल्सर निर्भरताएँ + +1. **क्लाइंट इंस्टेंशिएशन:** + सीधा: `gateway/service.py` + अमूर्त: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **मैसेज ट्रांसपोर्ट:** + उपभोक्ता: `consumer.py`, `consumer_spec.py` + उत्पादक: `producer.py`, `producer_spec.py` + प्रकाशक: `publisher.py` + सब्सक्राइबर: `subscriber.py`, `subscriber_spec.py` + +3. **स्कीमा सिस्टम:** + बेस प्रकार: `schema/core/primitives.py` + सभी सेवा स्कीमा: `schema/services/*.py` + टॉपिक नामकरण: `schema/core/topic.py` + +4. **पल्सर-विशिष्ट अवधारणाएँ आवश्यक:** + टॉपिक-आधारित मैसेजिंग + स्कीमा सिस्टम (रिकॉर्ड, फ़ील्ड प्रकार) + साझा सदस्यताएँ + मैसेज स्वीकृति (सकारात्मक/नकारात्मक) + उपभोक्ता पोजिशनिंग (सबसे पहले/नवीनतम) + मैसेज प्रॉपर्टीज़ + प्रारंभिक पोजीशन और उपभोक्ता प्रकार + चंकिंग सपोर्ट + लगातार बनाम गैर-लगातार टॉपिक + +### रिफैक्टरिंग चुनौतियाँ + +अच्छी खबर: एब्स्ट्रैक्शन लेयर (उपभोक्ता, उत्पादक, प्रकाशक, सब्सक्राइबर) पल्सर इंटरैक्शन के अधिकांश पहलुओं को साफ-सुथरा रूप से एनकैप्सुलेट करता है। + +चुनौतियाँ: +1. **स्कीमा सिस्टम की सर्वव्यापकता:** हर मैसेज परिभाषा `pulsar.schema.Record` और पल्सर फ़ील्ड प्रकारों का उपयोग करती है +2. **पल्सर-विशिष्ट एनम्स:** `InitialPosition`, `ConsumerType` +3. **पल्सर अपवाद:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **विधि हस्ताक्षर:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, आदि। +5. **टॉपिक URI फॉर्मेट:** पल्सर की `kind://tenant/namespace/topic` संरचना + +### अगले कदम + +पब/सब इंफ्रास्ट्रक्चर को कॉन्फ़िगर करने योग्य बनाने के लिए, हमें: + +1. क्लाइंट/स्कीमा सिस्टम के लिए एक एब्स्ट्रैक्शन इंटरफ़ेस बनाएं +2. पल्सर-विशिष्ट एनम्स और अपवादों को अमूर्त करें +3. स्कीमा रैपर या वैकल्पिक स्कीमा परिभाषाएँ बनाएँ +4. पल्सर और वैकल्पिक सिस्टम (काफ्का, रैबिटएमक्यू, रेडिस स्ट्रीम्स, आदि) दोनों के लिए इंटरफ़ेस को लागू करें +5. `pubsub.py` को कॉन्फ़िगर करने योग्य बनाएं और कई बैकएंड का समर्थन करें +6. मौजूदा डिप्लॉयमेंट के लिए माइग्रेशन पाथ प्रदान करें + +## दृष्टिकोण ड्राफ्ट 1: स्कीमा ट्रांसलेशन लेयर के साथ एडाप्टर पैटर्न + +### मुख्य अंतर्दृष्टि +**स्कीमा सिस्टम** एकीकरण का सबसे गहरा बिंदु है - बाकी सब कुछ इससे उपजा है। हमें पहले इसे हल करना होगा, अन्यथा हमें पूरे कोडबेस को फिर से लिखना होगा। + +### रणनीति: न्यूनतम व्यवधान के साथ एडाप्टर + +**1. पल्सर स्कीमा को आंतरिक प्रतिनिधित्व के रूप में बनाए रखें** +सभी स्कीमा परिभाषाओं को फिर से न लिखें +स्कीमा `pulsar.schema.Record` आंतरिक रूप से बने रहेंगे +हमारे कोड और पब/सब बैकएंड के बीच की सीमा पर अनुवाद करने के लिए एडेप्टर का उपयोग करें + +**2. एक पब/सब एब्स्ट्रैक्शन लेयर बनाएं:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. अमूर्त इंटरफेस को परिभाषित करें:** +`PubSubClient` - क्लाइंट कनेक्शन +`PubSubProducer` - संदेश भेजना +`PubSubConsumer` - संदेश प्राप्त करना +`SchemaAdapter` - पल्सर स्कीमा को JSON या बैकएंड-विशिष्ट प्रारूपों में अनुवाद करना + +**4. कार्यान्वयन विवरण:** + +**पल्सर एडेप्टर के लिए:** लगभग सीधे, न्यूनतम अनुवाद + +**अन्य बैकएंड के लिए** (Kafka, RabbitMQ, आदि): +पल्सर रिकॉर्ड ऑब्जेक्ट को JSON/बाइट में क्रमबद्ध करें +निम्नलिखित अवधारणाओं को मैप करें: + `InitialPosition.Earliest/Latest` → Kafka का auto.offset.reset + `acknowledge()` → Kafka का कमिट + `negative_acknowledge()` → पुनः कतार या DLQ पैटर्न + टॉपिक URI → बैकएंड-विशिष्ट टॉपिक नाम + +### विश्लेषण + +**लाभ:** +✅ मौजूदा सेवाओं में न्यूनतम कोड परिवर्तन +✅ स्कीमा अपरिवर्तित रहते हैं (कोई बड़ा पुनर्लेखन नहीं) +✅ क्रमिक माइग्रेशन पथ +✅ पल्सर उपयोगकर्ताओं को कोई अंतर दिखाई नहीं देता +✅ एडेप्टर के माध्यम से नए बैकएंड जोड़े जा सकते हैं + +**नुकसान:** +⚠️ अभी भी पल्सर पर निर्भरता है (स्कीमा परिभाषाओं के लिए) +⚠️ अवधारणाओं का अनुवाद करते समय कुछ असंगति + +### वैकल्पिक विचार + +एक **ट्रस्टग्राफ स्कीमा सिस्टम** बनाएं जो पब/सब से स्वतंत्र हो (डेटाक्लासेस या पाइडैंटिक का उपयोग करके), और फिर पल्सर/काफ्का/आदि स्कीमा को इससे उत्पन्न करें। इसके लिए प्रत्येक स्कीमा फ़ाइल को फिर से लिखना होगा और संभावित रूप से ब्रेकिंग परिवर्तन हो सकते हैं। + +### ड्राफ्ट 1 के लिए अनुशंसा + +**एडाप्टर दृष्टिकोण** से शुरुआत करें क्योंकि: +1. यह व्यावहारिक है - मौजूदा कोड के साथ काम करता है +2. यह न्यूनतम जोखिम के साथ अवधारणा को सिद्ध करता है +3. यदि आवश्यक हो तो बाद में एक देशी स्कीमा सिस्टम में विकसित किया जा सकता है +4. कॉन्फ़िगरेशन-संचालित: एक पर्यावरण चर बैकएंड को स्विच करता है + +## दृष्टिकोण ड्राफ्ट 2: डेटाक्लासेस के साथ बैकएंड-अज्ञेय स्कीमा सिस्टम + +### मुख्य अवधारणा + +पायथन **डेटाक्लासेस** का उपयोग तटस्थ स्कीमा परिभाषा प्रारूप के रूप में करें। प्रत्येक पब/सब बैकएंड डेटाक्लासेस के लिए अपना सीरियललाइज़ेशन/डीसेरियलाइज़ेशन प्रदान करता है, जिससे पल्सर स्कीमा को कोडबेस में बने रहने की आवश्यकता समाप्त हो जाती है। + +### फैक्ट्री स्तर पर स्कीमा बहुरूपता + +पल्सर स्कीमा का अनुवाद करने के बजाय, **प्रत्येक बैकएंड अपनी स्कीमा हैंडलिंग प्रदान करता है** जो मानक पायथन डेटाक्लासेस के साथ काम करता है। + +### प्रकाशक प्रवाह + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### उपभोक्ता प्रवाह + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### पर्दे के पीछे क्या होता है + +**पल्सर बैकएंड के लिए:** +`create_producer()` → JSON स्कीमा या गतिशील रूप से उत्पन्न रिकॉर्ड के साथ पल्सर प्रोड्यूसर बनाता है +`send(request)` → डेटाक्लास को JSON/पल्सर प्रारूप में क्रमबद्ध करता है, पल्सर को भेजता है +`receive()` → पल्सर संदेश प्राप्त करता है, डेटाक्लास में वापस क्रमबद्ध करता है + +**MQTT बैकएंड के लिए:** +`create_producer()` → MQTT ब्रोकर से कनेक्ट होता है, स्कीमा पंजीकरण की आवश्यकता नहीं है +`send(request)` → डेटाक्लास को JSON में परिवर्तित करता है, MQTT टॉपिक पर प्रकाशित करता है +`receive()` → MQTT टॉपिक की सदस्यता लेता है, JSON को डेटाक्लास में क्रमबद्ध करता है + +**Kafka बैकएंड के लिए:** +`create_producer()` → Kafka प्रोड्यूसर बनाता है, यदि आवश्यक हो तो Avro स्कीमा पंजीकृत करता है +`send(request)` → डेटाक्लास को Avro प्रारूप में क्रमबद्ध करता है, Kafka को भेजता है +`receive()` → Kafka संदेश प्राप्त करता है, Avro को डेटाक्लास में वापस क्रमबद्ध करता है + +### मुख्य डिज़ाइन बिंदु + +1. **स्कीमा ऑब्जेक्ट निर्माण**: डेटाक्लास इंस्टेंस (`TextCompletionRequest(...)`) बैकएंड की परवाह किए बिना समान होता है +2. **बैकएंड एन्कोडिंग को संभालता है**: प्रत्येक बैकएंड जानता है कि अपने डेटाक्लास को वायर प्रारूप में कैसे क्रमबद्ध करना है +3. **निर्माण पर स्कीमा परिभाषा**: जब प्रोड्यूसर/कंज्यूमर बनाते हैं, तो आप स्कीमा प्रकार निर्दिष्ट करते हैं +4. **टाइप सुरक्षा संरक्षित**: आपको एक उचित `TextCompletionRequest` ऑब्जेक्ट वापस मिलता है, कोई डिक्ट नहीं +5. **कोई बैकएंड रिसाव नहीं**: एप्लिकेशन कोड कभी भी बैकएंड-विशिष्ट लाइब्रेरीज़ को आयात नहीं करता है + +### उदाहरण परिवर्तन + +**वर्तमान (पल्सर-विशिष्ट):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**नया (बैकएंड-स्वतंत्र):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### बैकएंड एकीकरण + +प्रत्येक बैकएंड डेटाक्लासों का क्रमबद्धता/अक्रमबद्धता (सीरियलाइज़ेशन/डीसीरियलाइज़ेशन) संभालता है: + +**पल्सर बैकएंड:** +डेटाक्लासों से गतिशील रूप से `pulsar.schema.Record` क्लास उत्पन्न करें +या डेटाक्लासों को JSON में क्रमबद्ध करें और पल्सर के JSON स्कीमा का उपयोग करें +मौजूदा पल्सर डिप्लॉयमेंट के साथ संगतता बनाए रखता है + +**MQTT/रेडिस बैकएंड:** +डेटाक्लास उदाहरणों का सीधा JSON क्रमबद्धता +`dataclasses.asdict()` / `from_dict()` का उपयोग करें +हल्का, किसी स्कीमा रजिस्ट्री की आवश्यकता नहीं है + +**काफ्का बैकएंड:** +डेटाक्लास परिभाषाओं से एवरो स्कीमा उत्पन्न करें +कॉन्फ्लुएंट की स्कीमा रजिस्ट्री का उपयोग करें +स्कीमा विकास समर्थन के साथ टाइप-सुरक्षित क्रमबद्धता + +### वास्तुकला + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### कार्यान्वयन विवरण + +**1. स्कीमा परिभाषाएँ:** साधारण डेटाक्लास, टाइप हिंट के साथ + `str`, `int`, `bool`, `float` मूल डेटा प्रकारों के लिए + `list[T]` सरणियों के लिए + `dict[str, T]` मानचित्रों के लिए + जटिल प्रकारों के लिए नेस्टेड डेटाक्लास + +**2. प्रत्येक बैकएंड निम्नलिखित प्रदान करता है:** + सीरियलइज़र: `dataclass → bytes/wire format` + डीसीरियलइज़र: `bytes/wire format → dataclass` + स्कीमा पंजीकरण (यदि आवश्यक हो, जैसे कि Pulsar/Kafka) + +**3. उपभोक्ता/उत्पादक सार:** + पहले से मौजूद (consumer.py, producer.py) + बैकएंड के सीरियलइज़ेशन का उपयोग करने के लिए अपडेट करें + सीधे Pulsar आयात को हटा दें + +**4. टाइप मैपिंग:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### माइग्रेशन पथ + +1. `trustgraph/schema/` में सभी स्कीमा के डेटाक्लास संस्करण बनाएं +2. बैकएंड-प्रदान सीरियलइज़ेशन का उपयोग करने के लिए (उपभोक्ता, उत्पादक, प्रकाशक, ग्राहक) बैकएंड क्लास को अपडेट करें +3. JSON स्कीमा या गतिशील रिकॉर्ड पीढ़ी के साथ PulsarBackend को लागू करें +4. मौजूदा परिनियोजनों के साथ पिछड़े अनुकूलता सुनिश्चित करने के लिए Pulsar के साथ परीक्षण करें +5. आवश्यकतानुसार नए बैकएंड (MQTT, Kafka, Redis, आदि) जोड़ें +6. स्कीमा फ़ाइलों से Pulsar आयात को हटा दें + +### लाभ + +✅ **स्कीमा परिभाषाओं में कोई पब/सब निर्भरता नहीं** +✅ **मानक Python** - समझने, टाइप-चेक करने और दस्तावेज़ बनाने में आसान +✅ **आधुनिक टूलिंग** - mypy, IDE ऑटो-कंप्लीट, लिंटर के साथ काम करता है +✅ **बैकएंड-अनुकूलित** - प्रत्येक बैकएंड देशी सीरियलइज़ेशन का उपयोग करता है +✅ **कोई अनुवाद ओवरहेड नहीं** - सीधा सीरियलइज़ेशन, कोई एडेप्टर नहीं +✅ **टाइप सुरक्षा** - उचित प्रकारों के साथ वास्तविक ऑब्जेक्ट +✅ **आसान सत्यापन** - यदि आवश्यक हो तो Pydantic का उपयोग कर सकते हैं + +### चुनौतियाँ और समाधान + +**चुनौती:** Pulsar का `Record` में रनटाइम फ़ील्ड सत्यापन होता है +**समाधान:** यदि आवश्यक हो तो सत्यापन के लिए Pydantic डेटाक्लास का उपयोग करें, या `__post_init__` के साथ Python 3.10+ डेटाक्लास सुविधाओं का उपयोग करें + +**चुनौती:** कुछ Pulsar-विशिष्ट विशेषताएं (जैसे `Bytes` प्रकार) +**समाधान:** डेटाक्लास में `bytes` प्रकार पर मैप करें, बैकएंड उचित रूप से एन्कोडिंग को संभालता है + +**चुनौती:** टॉपिक नामकरण (`persistent://tenant/namespace/topic`) +**समाधान:** स्कीमा परिभाषाओं में टॉपिक नामों को सारगर्भित करें, बैकएंड उचित प्रारूप में परिवर्तित करता है + +**चुनौती:** स्कीमा विकास और संस्करण +**समाधान:** प्रत्येक बैकएंड अपनी क्षमताओं के अनुसार इसका प्रबंधन करता है (Pulsar स्कीमा संस्करण, Kafka स्कीमा रजिस्ट्री, आदि) + +**चुनौती:** नेस्टेड जटिल प्रकार +**समाधान:** नेस्टेड डेटाक्लास का उपयोग करें, बैकएंड पुनरावर्ती रूप से सीरियलइज़/डीसीरियलइज़ करते हैं + +### डिज़ाइन निर्णय + +1. **सादे डेटाक्लास या Pydantic?** + ✅ **निर्णय: सादे Python डेटाक्लास का उपयोग करें** + सरल, कोई अतिरिक्त निर्भरता नहीं + सत्यापन व्यावहारिक रूप से आवश्यक नहीं है + समझना और बनाए रखना आसान है + +2. **स्कीमा विकास:** + ✅ **निर्णय: कोई संस्करण तंत्र आवश्यक नहीं है** + स्कीमा स्थिर और लंबे समय तक चलने वाले हैं + अपडेट आमतौर पर नए फ़ील्ड जोड़ते हैं (पिछड़े संगत) + बैकएंड अपनी क्षमताओं के अनुसार स्कीमा विकास को संभालते हैं + +3. **पिछड़ी संगतता:** + ✅ **निर्णय: प्रमुख संस्करण परिवर्तन, पिछड़े संगतता की आवश्यकता नहीं है** + यह एक ब्रेकिंग परिवर्तन होगा जिसमें माइग्रेशन निर्देश होंगे + बेहतर डिज़ाइन के लिए स्वच्छ ब्रेक + मौजूदा परिनियोजनों के लिए एक माइग्रेशन गाइड प्रदान किया जाएगा + +4. **नेस्टेड प्रकार और जटिल संरचनाएं:** + ✅ **निर्णय: स्वाभाविक रूप से नेस्टेड डेटाक्लास का उपयोग करें** + Python डेटाक्लास नेस्टिंग को पूरी तरह से संभालते हैं + सरणियों के लिए `list[T]`, मानचित्रों के लिए `dict[K, V]` + बैकएंड पुनरावर्ती रूप से सीरियलइज़/डीसीरियलइज़ करते हैं + उदाहरण: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **डिफ़ॉल्ट मान और वैकल्पिक फ़ील्ड:** + ✅ **निर्णय: आवश्यक, डिफ़ॉल्ट और वैकल्पिक फ़ील्ड का मिश्रण** + आवश्यक फ़ील्ड: कोई डिफ़ॉल्ट मान नहीं + डिफ़ॉल्ट वाले फ़ील्ड: हमेशा मौजूद, उनका उचित डिफ़ॉल्ट मान होता है + वास्तव में वैकल्पिक फ़ील्ड: `T | None = None`, जब `None` हो तो क्रमबद्धता से छोड़े जा सकते हैं + उदाहरण: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **महत्वपूर्ण क्रमबद्धता अर्थ:** + + जब `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + जब `metadata = {}` (स्पष्ट रूप से खाली): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **मुख्य अंतर:** + `None` → JSON में अनुपस्थित फ़ील्ड (सीरियलाइज़ नहीं किया गया) + खाली मान (`{}`, `[]`, `""`) → फ़ील्ड मौजूद है लेकिन खाली मान के साथ + यह अर्थपूर्ण रूप से महत्वपूर्ण है: "प्रदान नहीं किया गया" बनाम "स्पष्ट रूप से खाली" + सीरियलाइज़ेशन बैकएंड को `None` फ़ील्ड को छोड़ना चाहिए, न कि इसे `null` के रूप में एन्कोड करना चाहिए + +## दृष्टिकोण ड्राफ्ट 3: कार्यान्वयन विवरण + +### सामान्य कतार नामकरण प्रारूप + +बैकएंड-विशिष्ट कतार नामों को एक सामान्य प्रारूप से बदलें जिसे बैकएंड उचित रूप से मैप कर सकें। + +**प्रारूप:** `{qos}/{tenant}/{namespace}/{queue-name}` + +जहाँ: +`qos`: सेवा की गुणवत्ता स्तर + `q0` = बेस्ट-एफर्ट (फायर एंड फॉरगेट, कोई स्वीकृति नहीं) + `q1` = एट-लीस्ट-वन्स (स्वीकृति की आवश्यकता होती है) + `q2` = एग्ज़ैक्टली-वन्स (दो-चरण स्वीकृति) +`tenant`: मल्टी-टेनेंसी के लिए तार्किक समूहीकरण +`namespace`: किरायेदार के भीतर उप-समूहीकरण +`queue-name`: वास्तविक कतार/विषय नाम + +**उदाहरण:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### बैकएंड टॉपिक मैपिंग + +प्रत्येक बैकएंड सामान्य प्रारूप को अपने मूल प्रारूप में परिवर्तित करता है: + +**पल्सर बैकएंड:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**एमक्यूटीटी बैकएंड:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### अद्यतित विषय सहायक फ़ंक्शन + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### कॉन्फ़िगरेशन और इनिशियलाइज़ेशन + +**कमांड-लाइन तर्क + पर्यावरण चर:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**फ़ैक्टरी फ़ंक्शन:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**एसिंक्रोनसप्रोसेसर में उपयोग:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### बैकएंड इंटरफ़ेस + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### मौजूदा कक्षाओं का पुनर्गठन + +मौजूदा `Consumer`, `Producer`, `Publisher`, `Subscriber` कक्षाएं काफी हद तक अपरिवर्तित रहेंगी: + +**वर्तमान जिम्मेदारियां (बनाए रखें):** +एसिंक्रोनस थ्रेडिंग मॉडल और टास्कग्रुप +पुनः कनेक्शन लॉजिक और पुनः प्रयास प्रबंधन +मेट्रिक्स संग्रह +दर सीमित करना +समवर्ती प्रबंधन + +**आवश्यक परिवर्तन:** +सीधे पल्सर आयात को हटा दें (`pulsar.schema`, `pulsar.InitialPosition`, आदि) +पल्सर क्लाइंट के बजाय `BackendProducer`/`BackendConsumer` स्वीकार करें +वास्तविक पब/सब संचालन को बैकएंड इंस्टेंस को सौंपें +सामान्य अवधारणाओं को बैकएंड कॉल में मैप करें + +**उदाहरण पुनर्गठन:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### बैकएंड-विशिष्ट व्यवहार + +**पल्सर बैकएंड:** +`q0` को `non-persistent://` में मैप करता है, `q1`/`q2` को `persistent://` में मैप करता है। +सभी प्रकार के उपभोक्ताओं का समर्थन करता है (साझा, विशेष, फेलओवर)। +प्रारंभिक स्थिति का समर्थन करता है (सबसे पहले/सबसे बाद में)। +मूल संदेश स्वीकृति। +स्कीमा रजिस्ट्री समर्थन। + +**एमक्यूटीटी बैकएंड:** +`q0`/`q1`/`q2` को एमक्यूटीटी क्यूओएस स्तर 0/1/2 में मैप करता है। +नामस्थान के लिए टॉपिक पथ में किरायेदार/नेमस्पेस शामिल करता है। +सदस्यता नामों से स्वचालित रूप से क्लाइंट आईडी उत्पन्न करता है। +प्रारंभिक स्थिति को अनदेखा करता है (मूल एमक्यूटीटी में कोई संदेश इतिहास नहीं)। +उपभोक्ता प्रकार को अनदेखा करता है (एमक्यूटीटी क्लाइंट आईडी, उपभोक्ता समूहों का उपयोग नहीं करता है)। +सरल प्रकाशित/सदस्यता मॉडल। + +### डिज़ाइन निर्णयों का सारांश + +1. ✅ **सामान्य कतार नामकरण**: `qos/tenant/namespace/queue-name` प्रारूप। +2. ✅ **कतार आईडी में क्यूओएस**: कतार परिभाषा द्वारा निर्धारित, कॉन्फ़िगरेशन द्वारा नहीं। +3. ✅ **पुनः कनेक्शन**: उपभोक्ता/उत्पादक कक्षाओं द्वारा संभाला जाता है, बैकएंड द्वारा नहीं। +4. ✅ **एमक्यूटीटी टॉपिक**: उचित नामस्थान के लिए किरायेदार/नेमस्पेस शामिल करें। +5. ✅ **संदेश इतिहास**: एमक्यूटीटी `initial_position` पैरामीटर को अनदेखा करता है (भविष्य में सुधार)। +6. ✅ **क्लाइंट आईडी**: एमक्यूटीटी बैकएंड सदस्यता नाम से स्वचालित रूप से उत्पन्न करता है। + +### भविष्य के सुधार + +**एमक्यूटीटी संदेश इतिहास:** +वैकल्पिक दृढ़ता परत (जैसे, रिटेन्ड संदेश, बाहरी स्टोर) जोड़ा जा सकता है। +यह `initial_position='earliest'` का समर्थन करने की अनुमति देगा। +प्रारंभिक कार्यान्वयन के लिए आवश्यक नहीं है। diff --git a/docs/tech-specs/pubsub.md b/docs/tech-specs/pubsub.md index 38836838..571f2fb5 100644 --- a/docs/tech-specs/pubsub.md +++ b/docs/tech-specs/pubsub.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Pub/Sub Infrastructure" +parent: "Tech Specs" +--- + # Pub/Sub Infrastructure ## Overview @@ -955,4 +961,3 @@ class Consumer: - Could add optional persistence layer (e.g., retained messages, external store) - Would allow supporting `initial_position='earliest'` - Not required for initial implementation - diff --git a/docs/tech-specs/pubsub.pt.md b/docs/tech-specs/pubsub.pt.md new file mode 100644 index 00000000..32b28b35 --- /dev/null +++ b/docs/tech-specs/pubsub.pt.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "Infraestrutura Pub/Sub" +parent: "Portuguese (Beta)" +--- + +# Infraestrutura Pub/Sub + +> **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 cataloga todas as conexões entre o código-fonte do TrustGraph e a infraestrutura pub/sub. Atualmente, o sistema está codificado para usar o Apache Pulsar. Esta análise identifica todos os pontos de integração para informar futuras refatorações em direção a uma abstração pub/sub configurável. + +## Estado Atual: Pontos de Integração do Pulsar + +### 1. Uso Direto do Cliente Pulsar + +**Localização:** `trustgraph-flow/trustgraph/gateway/service.py` + +O gateway da API importa e instancia diretamente o cliente Pulsar: + +**Linha 20:** `import pulsar` +**Linhas 54-61:** Instanciação direta de `pulsar.Client()` com `pulsar.AuthenticationToken()` opcional +**Linhas 33-35:** Configuração padrão do host Pulsar a partir de variáveis de ambiente +**Linhas 178-192:** Argumentos da linha de comando para `--pulsar-host`, `--pulsar-api-key` e `--pulsar-listener` +**Linhas 78, 124:** Passa `pulsar_client` para `ConfigReceiver` e `DispatcherManager` + +Esta é a única localização que instancia diretamente um cliente Pulsar fora da camada de abstração. + +### 2. Framework Base do Processador + +**Localização:** `trustgraph-base/trustgraph/base/async_processor.py` + +A classe base para todos os processadores fornece conectividade Pulsar: + +**Linha 9:** `import _pulsar` (para tratamento de exceções) +**Linha 18:** `from . pubsub import PulsarClient` +**Linha 38:** Cria `pulsar_client_object = PulsarClient(**params)` +**Linhas 104-108:** Propriedades que expõem `pulsar_host` e `pulsar_client` +**Linha 250:** O método estático `add_args()` chama `PulsarClient.add_args(parser)` para argumentos da linha de comando +**Linhas 223-225:** Tratamento de exceções para `_pulsar.Interrupted` + +Todos os processadores herdam de `AsyncProcessor`, tornando este o ponto de integração central. + +### 3. Abstração do Consumidor + +**Localização:** `trustgraph-base/trustgraph/base/consumer.py` + +Consome mensagens de filas e invoca funções de tratamento: + +**Importações do Pulsar:** +**Linha 12:** `from pulsar.schema import JsonSchema` +**Linha 13:** `import pulsar` +**Linha 14:** `import _pulsar` + +**Uso específico do Pulsar:** +**Linhas 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**Linha 108:** Wrapper `JsonSchema(self.schema)` +**Linha 110:** `pulsar.ConsumerType.Shared` +**Linhas 104-111:** `self.client.subscribe()` com parâmetros específicos do Pulsar +**Linhas 143, 150, 65:** Métodos `consumer.unsubscribe()` e `consumer.close()` +**Linha 162:** Exceção `_pulsar.Timeout` +**Linhas 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**Arquivo de especificação:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**Linha 22:** Referencia `processor.pulsar_client` + +### 4. Abstração do Produtor + +**Localização:** `trustgraph-base/trustgraph/base/producer.py` + +Envia mensagens para filas: + +**Importações do Pulsar:** +**Linha 2:** `from pulsar.schema import JsonSchema` + +**Uso específico do Pulsar:** +**Linha 49:** Wrapper `JsonSchema(self.schema)` +**Linhas 47-51:** `self.client.create_producer()` com parâmetros específicos do Pulsar (tópico, esquema, chunking_enabled) +**Linhas 31, 76:** Método `producer.close()` +**Linhas 64-65:** `producer.send()` com mensagem e propriedades + +**Arquivo de especificação:** `trustgraph-base/trustgraph/base/producer_spec.py` +**Linha 18:** Referencia `processor.pulsar_client` + +### 5. Abstração do Publicador + +**Localização:** `trustgraph-base/trustgraph/base/publisher.py` + +Publicação de mensagens assíncrona com buffer de fila: + +**Importações do Pulsar:** +**Linha 2:** `from pulsar.schema import JsonSchema` +**Linha 6:** `import pulsar` + +**Uso específico do Pulsar:** +**Linha 52:** Wrapper `JsonSchema(self.schema)` +**Linhas 50-54:** `self.client.create_producer()` com parâmetros específicos do Pulsar +**Linhas 101, 103:** `producer.send()` com mensagem e propriedades opcionais +**Linhas 106-107:** Métodos `producer.flush()` e `producer.close()` + +### 6. Abstração do Assinante + +**Localização:** `trustgraph-base/trustgraph/base/subscriber.py` + +Fornece distribuição de mensagens para múltiplos destinatários a partir de filas: + +**Importações do Pulsar:** +**Linha 6:** `from pulsar.schema import JsonSchema` +**Linha 8:** `import _pulsar` + +**Uso específico do Pulsar:** +**Linha 55:** `JsonSchema(self.schema)` wrapper +**Linha 57:** `self.client.subscribe(**subscribe_args)` +**Linhas 101, 136, 160, 167-172:** Exceções do Pulsar: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**Linhas 159, 166, 170:** Métodos do consumidor: `negative_acknowledge()`, `unsubscribe()`, `close()` +**Linhas 247, 251:** Reconhecimento de mensagens: `acknowledge()`, `negative_acknowledge()` + +**Arquivo de especificação:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**Linha 19:** Referencia `processor.pulsar_client` + +### 7. Sistema de Schema (Heart of Darkness) + +**Localização:** `trustgraph-base/trustgraph/schema/` + +Cada schema de mensagem no sistema é definido usando o framework de schema do Pulsar. + +**Primitivos principais:** `schema/core/primitives.py` +**Linha 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +Todos os schemas herdam da classe base do Pulsar `Record` +Todos os tipos de campo são tipos do Pulsar: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**Schemas de exemplo:** +`schema/services/llm.py` (Linha 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (Linha 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**Nomeação de tópicos:** `schema/core/topic.py` +**Linhas 2-3:** Formato do tópico: `{kind}://{tenant}/{namespace}/{topic}` +Esta estrutura de URI é específica do Pulsar (por exemplo, `persistent://tg/flow/config`) + +**Impacto:** +Todas as definições de mensagens de solicitação/resposta em todo o código-fonte usam schemas do Pulsar +Isso inclui serviços para: config, flow, llm, prompt, query, storage, agent, collection, diagnosis, library, lookup, nlp_query, objects_query, retrieval, structured_query +As definições de schema são importadas e usadas extensivamente em todos os processadores e serviços + +## Resumo + +### Dependências do Pulsar por Categoria + +1. **Instanciação do cliente:** + Direto: `gateway/service.py` + Abstrato: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **Transporte de mensagens:** + Consumidor: `consumer.py`, `consumer_spec.py` + Produtor: `producer.py`, `producer_spec.py` + Publicador: `publisher.py` + Assinante: `subscriber.py`, `subscriber_spec.py` + +3. **Sistema de schema:** + Tipos base: `schema/core/primitives.py` + Todos os schemas de serviço: `schema/services/*.py` + Nomeação de tópicos: `schema/core/topic.py` + +4. **Conceitos específicos do Pulsar necessários:** + Mensagens baseadas em tópicos + Sistema de schema (Registro, tipos de campo) + Assinaturas compartilhadas + Reconhecimento de mensagens (positivo/negativo) + Posicionamento do consumidor (mais cedo/mais tarde) + Propriedades da mensagem + Posições iniciais e tipos de consumidor + Suporte de fragmentação + Tópicos persistentes vs não persistentes + +### Desafios de Refatoração + +A boa notícia: A camada de abstração (Consumidor, Produtor, Publicador, Assinante) fornece um encapsulamento limpo da maioria das interações do Pulsar. + +Os desafios: +1. **Ubiquidade do sistema de schema:** Cada definição de mensagem usa `pulsar.schema.Record` e tipos de campo do Pulsar +2. **Enums específicos do Pulsar:** `InitialPosition`, `ConsumerType` +3. **Exceções do Pulsar:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **Assinaturas de método:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, etc. +5. **Formato de URI do tópico:** Estrutura do Pulsar `kind://tenant/namespace/topic` + +### Próximos Passos + +Para tornar a infraestrutura de pub/sub configurável, precisamos: + +1. Criar uma interface de abstração para o sistema de cliente/schema +2. Abstrair enums e exceções específicos do Pulsar +3. Criar wrappers de schema ou definições de schema alternativas +4. Implementar a interface para sistemas Pulsar e sistemas alternativos (Kafka, RabbitMQ, Redis Streams, etc.) +5. Atualizar `pubsub.py` para ser configurável e suportar vários backends +6. Fornecer um caminho de migração para implantações existentes + +## Abordagem Preliminar 1: Padrão Adapter com Camada de Tradução de Schema + +### Principio Fundamental +O **sistema de schema** é o ponto de integração mais profundo - tudo o mais deriva dele. Precisamos resolver isso primeiro, ou teremos que reescrever todo o código-fonte. + +### Estratégia: Encapsulamento Mínimo com Adapters + +**1. Manter os esquemas Pulsar como a representação interna** +Não reescrever todas as definições de esquema +Os esquemas permanecem `pulsar.schema.Record` internamente +Usar adaptadores para traduzir na fronteira entre nosso código e o backend de publicação/assinatura + +**2. Criar uma camada de abstração de publicação/assinatura:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. Defina interfaces abstratas:** +`PubSubClient` - conexão do cliente +`PubSubProducer` - envio de mensagens +`PubSubConsumer` - recebimento de mensagens +`SchemaAdapter` - tradução de esquemas Pulsar para/de JSON ou formatos específicos do backend + +**4. Detalhes de implementação:** + +Para o **adaptador Pulsar**: Quase transparente, tradução mínima + +Para **outros backends** (Kafka, RabbitMQ, etc.): +Serializa objetos de registro Pulsar para JSON/bytes +Mapeia conceitos como: + `InitialPosition.Earliest/Latest` → auto.offset.reset do Kafka + `acknowledge()` → commit do Kafka + `negative_acknowledge()` → padrão de re-fila ou DLQ + URIs de tópicos → nomes de tópicos específicos do backend + +### Análise + +**Prós:** +✅ Alterações mínimas no código dos serviços existentes +✅ Os esquemas permanecem como estão (sem reescrita massiva) +✅ Caminho de migração gradual +✅ Os usuários do Pulsar não percebem diferença +✅ Novos backends adicionados via adaptadores + +**Contras:** +⚠️ Ainda possui dependência do Pulsar (para definições de esquema) +⚠️ Alguma incompatibilidade na tradução de conceitos + +### Consideração Alternativa + +Crie um sistema de esquemas **TrustGraph** que seja agnóstico de pub/sub (usando dataclasses ou Pydantic), e então gere esquemas Pulsar/Kafka/etc a partir dele. Isso requer reescrever todos os arquivos de esquema e pode causar alterações disruptivas. + +### Recomendação para a Versão 1 + +Comece com a **abordagem de adaptador** porque: +1. É pragmática - funciona com o código existente +2. Demonstra o conceito com risco mínimo +3. Pode evoluir para um sistema de esquemas nativo posteriormente, se necessário +4. Impulsionado por configuração: uma variável de ambiente alterna entre backends + +## Abordagem da Versão 2: Sistema de Esquemas Agnostic de Backend com Dataclasses + +### Conceito Central + +Use **dataclasses** do Python como o formato de definição de esquema neutro. Cada backend de pub/sub fornece sua própria serialização/desserialização para dataclasses, eliminando a necessidade de que os esquemas Pulsar permaneçam no código-fonte. + +### Polimorfismo de Esquema no Nível da Fábrica + +Em vez de traduzir esquemas Pulsar, **cada backend fornece seu próprio tratamento de esquema** que funciona com dataclasses Python padrão. + +### Fluxo do Publicador + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### Fluxo do Consumidor + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### O que acontece nos bastidores + +**Para o backend Pulsar:** +`create_producer()` → cria um produtor Pulsar com esquema JSON ou um registro gerado dinamicamente. +`send(request)` → serializa a classe de dados para o formato JSON/Pulsar e envia para o Pulsar. +`receive()` → recebe a mensagem do Pulsar, desserializa de volta para a classe de dados. + +**Para o backend MQTT:** +`create_producer()` → conecta a um broker MQTT, não é necessário registro de esquema. +`send(request)` → converte a classe de dados para JSON e publica em um tópico MQTT. +`receive()` → assina um tópico MQTT e desserializa o JSON para a classe de dados. + +**Para o backend Kafka:** +`create_producer()` → cria um produtor Kafka e registra o esquema Avro, se necessário. +`send(request)` → serializa a classe de dados para o formato Avro e envia para o Kafka. +`receive()` → recebe a mensagem do Kafka e desserializa o Avro de volta para a classe de dados. + +### Pontos-chave do design + +1. **Criação do objeto de esquema**: A instância da classe de dados (`TextCompletionRequest(...)`) é idêntica, independentemente do backend. +2. **O backend lida com a codificação**: Cada backend sabe como serializar sua classe de dados para o formato de transmissão. +3. **Definição do esquema na criação**: Ao criar o produtor/consumidor, você especifica o tipo de esquema. +4. **Segurança de tipo preservada**: Você recebe um objeto `TextCompletionRequest` adequado, não um dicionário. +5. **Nenhum vazamento do backend**: O código da aplicação nunca importa bibliotecas específicas do backend. + +### Exemplo de transformação + +**Atual (específico para Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**Novo (Independente do backend):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### Integração com o Backend + +Cada backend lida com a serialização/desserialização de dataclasses: + +**Backend Pulsar:** +Gera classes `pulsar.schema.Record` dinamicamente a partir de dataclasses +Ou serializa dataclasses para JSON e usa o esquema JSON do Pulsar +Mantém a compatibilidade com implantações Pulsar existentes + +**Backend MQTT/Redis:** +Serialização direta de instâncias de dataclass para JSON +Use `dataclasses.asdict()` / `from_dict()` +Leve, não requer registro de esquema + +**Backend Kafka:** +Gera esquemas Avro a partir de definições de dataclass +Use o registro de esquema da Confluent +Serialização com segurança de tipo com suporte à evolução do esquema + +### Arquitetura + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### Detalhes de Implementação + +**1. Definições de esquema:** Dataclasses simples com dicas de tipo + `str`, `int`, `bool`, `float` para tipos primitivos + `list[T]` para arrays + `dict[str, T]` para mapas + Dataclasses aninhados para tipos complexos + +**2. Cada backend fornece:** + Serializador: `dataclass → bytes/wire format` + Deserializador: `bytes/wire format → dataclass` + Registro de esquema (se necessário, como Pulsar/Kafka) + +**3. Abstração de consumidor/produtor:** + Já existe (consumer.py, producer.py) + Atualizar para usar a serialização do backend + Remover importações diretas do Pulsar + +**4. Mapeamentos de tipo:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### Caminho de Migração + +1. **Criar versões de dataclass** de todos os esquemas em `trustgraph/schema/` +2. **Atualizar classes de backend** (Consumer, Producer, Publisher, Subscriber) para usar a serialização fornecida pelo backend +3. **Implementar PulsarBackend** com esquema JSON ou geração dinâmica de Record +4. **Testar com Pulsar** para garantir a compatibilidade com versões anteriores com implantações existentes +5. **Adicionar novos backends** (MQTT, Kafka, Redis, etc.) conforme necessário +6. **Remover importações do Pulsar** de arquivos de esquema + +### Benefícios + +✅ **Nenhuma dependência de pub/sub** nas definições de esquema +✅ **Python padrão** - fácil de entender, tipar, documentar +✅ **Ferramentas modernas** - funciona com mypy, preenchimento automático de IDE, linters +✅ **Otimizado para backend** - cada backend usa a serialização nativa +✅ **Sem sobrecarga de tradução** - serialização direta, sem adaptadores +✅ **Segurança de tipo** - objetos reais com tipos adequados +✅ **Validação fácil** - pode usar Pydantic, se necessário + +### Desafios e Soluções + +**Desafio:** O `Record` do Pulsar tem validação de campo em tempo de execução +**Solução:** Use dataclasses Pydantic para validação, se necessário, ou recursos de dataclass Python 3.10+ com `__post_init__` + +**Desafio:** Alguns recursos específicos do Pulsar (como o tipo `Bytes`) +**Solução:** Mapear para o tipo `bytes` na dataclass, o backend lida com a codificação apropriadamente + +**Desafio:** Nomenclatura de tópicos (`persistent://tenant/namespace/topic`) +**Solução:** Abstrair nomes de tópicos em definições de esquema, o backend converte para o formato adequado + +**Desafio:** Evolução e versionamento de esquema +**Solução:** Cada backend lida com isso de acordo com suas capacidades (versões de esquema do Pulsar, registro de esquema do Kafka, etc.) + +**Desafio:** Tipos complexos aninhados +**Solução:** Use dataclasses aninhadas, os backends serializam/desserializam recursivamente + +### Decisões de Design + +1. **Dataclasses simples ou Pydantic?** + ✅ **Decisão: Usar dataclasses Python simples** + Mais simples, sem dependências adicionais + Validação não é necessária na prática + Mais fácil de entender e manter + +2. **Evolução de esquema:** + ✅ **Decisão: Nenhum mecanismo de versionamento necessário** + Os esquemas são estáveis e duradouros + As atualizações normalmente adicionam novos campos (compatíveis com versões anteriores) + Os backends lidam com a evolução do esquema de acordo com suas capacidades + +3. **Compatibilidade com versões anteriores:** + ✅ **Decisão: Alteração de versão principal, compatibilidade com versões anteriores não é necessária** + Será uma alteração disruptiva com instruções de migração + A separação limpa permite um melhor design + Um guia de migração será fornecido para implantações existentes + +4. **Tipos aninhados e estruturas complexas:** + ✅ **Decisão: Usar dataclasses aninhadas naturalmente** + Dataclasses Python lidam com o aninhamento perfeitamente + `list[T]` para arrays, `dict[K, V]` para mapas + Backends serializam/desserializam recursivamente + Exemplo: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **Valores padrão e campos opcionais:** + ✅ **Decisão: Mistura de campos obrigatórios, valores padrão e campos opcionais** + Campos obrigatórios: Sem valor padrão + Campos com valores padrão: Sempre presentes, possuem um valor padrão razoável + Campos verdadeiramente opcionais: `T | None = None`, omitidos da serialização quando `None` + Exemplo: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **Semântica de serialização importante:** + + Quando `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + Quando `metadata = {}` (explicitamente vazio): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **Diferença chave:** + `None` → campo ausente do JSON (não serializado) + Valor vazio (`{}`, `[]`, `""`) → campo presente com valor vazio + Isso importa semanticamente: "não fornecido" vs "explicitamente vazio" + Os backends de serialização devem ignorar os campos `None`, não codificá-los como `null` + +## Abordagem Rascunho 3: Detalhes de Implementação + +### Formato Genérico de Nomes de Filas + +Substitua os nomes de filas específicos do backend por um formato genérico que os backends possam mapear adequadamente. + +**Formato:** `{qos}/{tenant}/{namespace}/{queue-name}` + +Onde: +`qos`: Nível de Qualidade de Serviço + `q0` = melhor esforço (enviar e esquecer, sem confirmação) + `q1` = pelo menos uma vez (requer confirmação) + `q2` = exatamente uma vez (confirmação de duas fases) +`tenant`: Agrupamento lógico para multi-inquilinato +`namespace`: Sub-agrupamento dentro do inquilino +`queue-name`: Nome real da fila/tópico + +**Exemplos:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### Mapeamento de Tópicos do Backend + +Cada backend mapeia o formato genérico para o seu formato nativo: + +**Backend do Pulsar:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**Backend MQTT:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### Função de Auxílio de Tópico Atualizada + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### Configuração e Inicialização + +**Argumentos de Linha de Comando + Variáveis de Ambiente:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**Função de Fábrica:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**Uso em AsyncProcessor:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### Interface de Backend + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### Refatoração das Classes Existentes + +As classes existentes `Consumer`, `Producer`, `Publisher`, `Subscriber` permanecem em grande parte inalteradas: + +**Responsabilidades atuais (manter):** +Modelo de threading assíncrono e grupos de tarefas +Lógica de reconexão e tratamento de repetições +Coleta de métricas +Limitação de taxa +Gerenciamento de concorrência + +**Alterações necessárias:** +Remover importações diretas do Pulsar (`pulsar.schema`, `pulsar.InitialPosition`, etc.) +Aceitar `BackendProducer`/`BackendConsumer` em vez do cliente Pulsar +Delegar as operações reais de publicação/assinatura para instâncias de backend +Mapear conceitos genéricos para chamadas de backend + +**Exemplo de refatoração:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### Comportamentos Específicos do Backend + +**Backend Pulsar:** +Mapeia `q0` → `non-persistent://`, `q1`/`q2` → `persistent://` +Suporta todos os tipos de consumidores (compartilhado, exclusivo, failover) +Suporta posição inicial (earliest/latest) +Reconhecimento nativo de mensagens +Suporte para registro de esquema + +**Backend MQTT:** +Mapeia `q0`/`q1`/`q2` → Níveis de QoS MQTT 0/1/2 +Inclui tenant/namespace no caminho do tópico para fins de namespace +Gera automaticamente IDs de cliente a partir de nomes de inscrição +Ignora a posição inicial (sem histórico de mensagens no MQTT básico) +Ignora o tipo de consumidor (o MQTT usa IDs de cliente, não grupos de consumidores) +Modelo de publicação/assinatura simples + +### Resumo das Decisões de Design + +1. ✅ **Nomeação genérica de filas**: Formato `qos/tenant/namespace/queue-name` +2. ✅ **QoS no ID da fila**: Determinado pela definição da fila, não pela configuração +3. ✅ **Reconexão**: Tratada pelas classes Consumer/Producer, não pelos backends +4. ✅ **Tópicos MQTT**: Incluem tenant/namespace para namespace adequado +5. ✅ **Histórico de mensagens**: O MQTT ignora o parâmetro `initial_position` (melhoria futura) +6. ✅ **IDs de cliente**: O backend MQTT gera automaticamente a partir do nome da inscrição + +### Melhorias Futuras + +**Histórico de mensagens MQTT:** +Poderia adicionar uma camada de persistência opcional (por exemplo, mensagens retidas, armazenamento externo) +Permitiria suportar `initial_position='earliest'` +Não é necessário para a implementação inicial diff --git a/docs/tech-specs/pubsub.ru.md b/docs/tech-specs/pubsub.ru.md new file mode 100644 index 00000000..0ff4aa18 --- /dev/null +++ b/docs/tech-specs/pubsub.ru.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "Инфраструктура Pub/Sub" +parent: "Russian (Beta)" +--- + +# Инфраструктура Pub/Sub + +> **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 и инфраструктурой pub/sub. В настоящее время система жестко запрограммирована на использование Apache Pulsar. Этот анализ определяет все точки интеграции для будущей рефакторизации в сторону конфигурируемой абстракции pub/sub. + +## Текущее состояние: точки интеграции Pulsar + +### 1. Прямое использование клиента Pulsar + +**Местоположение:** `trustgraph-flow/trustgraph/gateway/service.py` + +API-шлюз напрямую импортирует и создает экземпляр клиента Pulsar: + +**Строка 20:** `import pulsar` +**Строки 54-61:** Прямая инициализация `pulsar.Client()` с необязательными параметрами `pulsar.AuthenticationToken()` +**Строки 33-35:** Конфигурация хоста Pulsar по умолчанию из переменных окружения +**Строки 178-192:** Аргументы командной строки для `--pulsar-host`, `--pulsar-api-key` и `--pulsar-listener` +**Строки 78, 124:** Передача `pulsar_client` в `ConfigReceiver` и `DispatcherManager` + +Это единственное место, где напрямую создается экземпляр клиента Pulsar за пределами слоя абстракции. + +### 2. Базовая платформа процессоров + +**Местоположение:** `trustgraph-base/trustgraph/base/async_processor.py` + +Базовый класс для всех процессоров обеспечивает подключение к Pulsar: + +**Строка 9:** `import _pulsar` (для обработки исключений) +**Строка 18:** `from . pubsub import PulsarClient` +**Строка 38:** Создание `pulsar_client_object = PulsarClient(**params)` +**Строки 104-108:** Свойства, предоставляющие доступ к `pulsar_host` и `pulsar_client` +**Строка 250:** Статический метод `add_args()` вызывает `PulsarClient.add_args(parser)` для аргументов командной строки +**Строки 223-225:** Обработка исключений для `_pulsar.Interrupted` + +Все процессоры наследуются от `AsyncProcessor`, что делает это центральной точкой интеграции. + +### 3. Абстракция потребителя + +**Местоположение:** `trustgraph-base/trustgraph/base/consumer.py` + +Потребляет сообщения из очередей и вызывает функции обработчиков: + +**Импорты Pulsar:** +**Строка 12:** `from pulsar.schema import JsonSchema` +**Строка 13:** `import pulsar` +**Строка 14:** `import _pulsar` + +**Использование, специфичное для Pulsar:** +**Строки 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**Строка 108:** Обертка `JsonSchema(self.schema)` +**Строка 110:** `pulsar.ConsumerType.Shared` +**Строки 104-111:** `self.client.subscribe()` с параметрами, специфичными для Pulsar +**Строки 143, 150, 65:** Методы `consumer.unsubscribe()` и `consumer.close()` +**Строка 162:** Исключение `_pulsar.Timeout` +**Строки 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**Спецификационный файл:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**Строка 22:** Ссылка на `processor.pulsar_client` + +### 4. Абстракция производителя + +**Местоположение:** `trustgraph-base/trustgraph/base/producer.py` + +Отправляет сообщения в очереди: + +**Импорты Pulsar:** +**Строка 2:** `from pulsar.schema import JsonSchema` + +**Использование, специфичное для Pulsar:** +**Строка 49:** Обертка `JsonSchema(self.schema)` +**Строки 47-51:** `self.client.create_producer()` с параметрами, специфичными для Pulsar (тема, схема, включение фрагментации) +**Строки 31, 76:** Метод `producer.close()` +**Строки 64-65:** `producer.send()` с сообщением и свойствами + +**Спецификационный файл:** `trustgraph-base/trustgraph/base/producer_spec.py` +**Строка 18:** Ссылка на `processor.pulsar_client` + +### 5. Абстракция издателя + +**Местоположение:** `trustgraph-base/trustgraph/base/publisher.py` + +Асинхронная публикация сообщений с буферизацией очереди: + +**Импорты Pulsar:** +**Строка 2:** `from pulsar.schema import JsonSchema` +**Строка 6:** `import pulsar` + +**Использование, специфичное для Pulsar:** +**Строка 52:** Обертка `JsonSchema(self.schema)` +**Строки 50-54:** `self.client.create_producer()` с параметрами, специфичными для Pulsar +**Строки 101, 103:** `producer.send()` с сообщением и необязательными свойствами +**Строки 106-107:** Методы `producer.flush()` и `producer.close()` + +### 6. Абстракция подписчика + +**Местоположение:** `trustgraph-base/trustgraph/base/subscriber.py` + +Предоставляет распределение сообщений для нескольких получателей из очередей: + +**Импорт Pulsar:** +**Строка 6:** `from pulsar.schema import JsonSchema` +**Строка 8:** `import _pulsar` + +**Использование, специфичное для Pulsar:** +**Строка 55:** `JsonSchema(self.schema)` wrapper +**Строка 57:** `self.client.subscribe(**subscribe_args)` +**Строки 101, 136, 160, 167-172:** Исключения Pulsar: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**Строки 159, 166, 170:** Методы потребителя: `negative_acknowledge()`, `unsubscribe()`, `close()` +**Строки 247, 251:** Подтверждение сообщений: `acknowledge()`, `negative_acknowledge()` + +**Файл спецификации:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**Строка 19:** Ссылается на `processor.pulsar_client` + +### 7. Система схем (Heart of Darkness) + +**Расположение:** `trustgraph-base/trustgraph/schema/` + +Каждая схема сообщения в системе определяется с использованием фреймворка схем Pulsar. + +**Основные примитивы:** `schema/core/primitives.py` +**Строка 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +Все схемы наследуются от базового класса Pulsar `Record` +Все типы полей являются типами Pulsar: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**Примеры схем:** +`schema/services/llm.py` (Строка 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (Строка 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**Именование тем:** `schema/core/topic.py` +**Строки 2-3:** Формат темы: `{kind}://{tenant}/{namespace}/{topic}` +Эта структура URI специфична для Pulsar (например, `persistent://tg/flow/config`) + +**Влияние:** +Все определения сообщений запроса/ответа во всем коде используют схемы Pulsar +Это включает в себя сервисы для: config, flow, llm, prompt, query, storage, agent, collection, diagnosis, library, lookup, nlp_query, objects_query, retrieval, structured_query +Определения схем импортируются и используются во всех процессорах и сервисах. + +## Краткое описание + +### Зависимости Pulsar по категориям + +1. **Инициализация клиента:** + Прямая: `gateway/service.py` + Абстрактная: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **Транспортировка сообщений:** + Потребитель: `consumer.py`, `consumer_spec.py` + Издатель: `producer.py`, `producer_spec.py` + Публикатор: `publisher.py` + Подписчик: `subscriber.py`, `subscriber_spec.py` + +3. **Система схем:** + Базовые типы: `schema/core/primitives.py` + Все схемы сервисов: `schema/services/*.py` + Именование тем: `schema/core/topic.py` + +4. **Требуются концепции, специфичные для Pulsar:** + Сообщения на основе тем + Система схем (Record, типы полей) + Общие подписки + Подтверждение сообщений (положительное/отрицательное) + Позиционирование потребителя (самое начало/последнее) + Свойства сообщений + Начальные позиции и типы потребителей + Поддержка разбиения на части + Постоянные и непостоянные темы + +### Проблемы рефакторинга + +Хорошая новость: слой абстракции (Consumer, Producer, Publisher, Subscriber) обеспечивает четкую инкапсуляцию большинства взаимодействий с Pulsar. + +Проблемы: +1. **Всепроникающая система схем:** Каждое определение сообщения использует `pulsar.schema.Record` и типы Pulsar. +2. **Перечисления, специфичные для Pulsar:** `InitialPosition`, `ConsumerType` +3. **Исключения Pulsar:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **Сигнатуры методов:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()` и т.д. +5. **Формат URI темы:** Структура Pulsar `kind://tenant/namespace/topic` + +### Следующие шаги + +Чтобы сделать инфраструктуру публикации/подписки настраиваемой, нам нужно: + +1. Создать интерфейс абстракции для системы клиента/схем. +2. Абстрагировать перечисления и исключения, специфичные для Pulsar. +3. Создать обертки для схем или альтернативные определения схем. +4. Реализовать интерфейс как для Pulsar, так и для альтернативных систем (Kafka, RabbitMQ, Redis Streams и т.д.). +5. Обновить `pubsub.py`, чтобы он был настраиваемым и поддерживал несколько бэкендов. +6. Предоставить путь миграции для существующих развертываний. + +## Предварительный черновик подхода 1: Шаблон адаптера со слоем перевода схем + +### Ключевое понимание +**Система схем** является наиболее глубокой точкой интеграции - от нее зависит все остальное. Мы должны решить эту проблему в первую очередь, иначе нам придется переписывать весь код. + +### Стратегия: Минимальное нарушение с помощью адаптеров + +**1. Сохраняйте схемы Pulsar в качестве внутреннего представления** +Не переписывайте все определения схем. +Схемы остаются `pulsar.schema.Record` во внутреннем представлении. +Используйте адаптеры для преобразования данных на границе между нашим кодом и бэкендом pub/sub. + +**2. Создайте абстрактный слой pub/sub:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. Определение абстрактных интерфейсов:** +`PubSubClient` - клиентское подключение +`PubSubProducer` - отправка сообщений +`PubSubConsumer` - получение сообщений +`SchemaAdapter` - преобразование схем Pulsar в/из JSON или форматы, специфичные для бэкенда + +**4. Детали реализации:** + +Для **адаптера Pulsar**: Практически без изменений, минимальное преобразование. + +Для **других бэкендов** (Kafka, RabbitMQ и т.д.): +Сериализация объектов Pulsar Record в JSON/байты. +Отображение понятий, таких как: + `InitialPosition.Earliest/Latest` → auto.offset.reset в Kafka + `acknowledge()` → commit в Kafka + `negative_acknowledge()` → Паттерн повторной отправки или DLQ (Dead Letter Queue) + URI тем → Имена тем, специфичные для бэкенда. + +### Анализ + +**Преимущества:** +✅ Минимальные изменения существующего кода. +✅ Схемы остаются без изменений (без необходимости масштабной переработки). +✅ Постепенный путь миграции. +✅ Пользователи Pulsar не заметят разницы. +✅ Новые бэкенды добавляются через адаптеры. + +**Недостатки:** +⚠️ Все еще присутствует зависимость от Pulsar (для определений схем). +⚠️ Некоторые несовместимости при преобразовании понятий. + +### Альтернативное решение + +Создать **систему схем TrustGraph**, которая является агностической к pub/sub (используя dataclasses или Pydantic), а затем генерировать схемы Pulsar/Kafka/и т.д. из нее. Это требует переписывания каждого файла схемы и может привести к несовместимым изменениям. + +### Рекомендации для версии 1 + +Начните с **подхода с использованием адаптеров**, потому что: +1. Это практичный подход, который работает с существующим кодом. +2. Подтверждает концепцию с минимальным риском. +3. Может быть усовершенствован до нативной системы схем в будущем, если это необходимо. +4. Управление конфигурацией: одна переменная окружения переключает бэкенды. + +## Подход, версия 2: Система схем, независимая от бэкенда, с использованием dataclasses + +### Основная концепция + +Используйте Python **dataclasses** в качестве нейтрального формата определения схемы. Каждый бэкенд pub/sub предоставляет свой собственный механизм сериализации/десериализации для dataclasses, что устраняет необходимость сохранения схем Pulsar в кодовой базе. + +### Полиморфизм схем на уровне фабрики + +Вместо преобразования схем Pulsar, **каждый бэкенд предоставляет собственную обработку схем**, которая работает со стандартными Python dataclasses. + +### Поток публикации + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### Поток пользователей + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### Что происходит за кулисами + +**Для бэкенда Pulsar:** +`create_producer()` → создает производителя Pulsar с JSON-схемой или динамически генерируемой записью +`send(request)` → сериализует dataclass в формат JSON/Pulsar, отправляет в Pulsar +`receive()` → получает сообщение Pulsar, десериализует обратно в dataclass + +**Для бэкенда MQTT:** +`create_producer()` → подключается к MQTT-брокеру, регистрация схемы не требуется +`send(request)` → преобразует dataclass в JSON, публикует в MQTT-топик +`receive()` → подписывается на MQTT-топик, десериализует JSON в dataclass + +**Для бэкенда Kafka:** +`create_producer()` → создает производителя Kafka, регистрирует схему Avro, если необходимо +`send(request)` → сериализует dataclass в формат Avro, отправляет в Kafka +`receive()` → получает сообщение Kafka, десериализует Avro обратно в dataclass + +### Ключевые моменты проектирования + +1. **Создание объекта схемы**: Экземпляр dataclass (`TextCompletionRequest(...)`) идентичен независимо от бэкенда +2. **Бэкенд обрабатывает кодирование**: Каждый бэкенд знает, как сериализовать свой dataclass в формат для передачи данных +3. **Определение схемы при создании**: При создании производителя/потребителя вы указываете тип схемы +4. **Сохранение типобезопасности**: Вы получаете правильный объект `TextCompletionRequest`, а не словарь +5. **Отсутствие утечек бэкенда**: Код приложения никогда не импортирует библиотеки, специфичные для бэкенда + +### Пример преобразования + +**Текущий (специфичный для Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**Новое (независимое от бэкенда):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### Интеграция с бэкендом + +Каждый бэкенд отвечает за сериализацию/десериализацию dataclasses: + +**Бэкенд Pulsar:** +Динамически генерирует классы `pulsar.schema.Record` из dataclasses +Или сериализует dataclasses в JSON и использует JSON-схему Pulsar +Обеспечивает совместимость с существующими развертываниями Pulsar + +**Бэкенд MQTT/Redis:** +Прямая сериализация в JSON экземпляров dataclass +Использует `dataclasses.asdict()` / `from_dict()` +Легковесный, не требуется реестр схем + +**Бэкенд Kafka:** +Генерирует схемы Avro из определений dataclass +Использует реестр схем Confluent +Типобезопасная сериализация с поддержкой эволюции схемы + +### Архитектура + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### Детали реализации + +**1. Определение схем:** Простые классы данных с подсказками типов + `str`, `int`, `bool`, `float` для примитивов + `list[T]` для массивов + `dict[str, T]` для словарей + Вложенные классы данных для сложных типов + +**2. Каждый бэкенд предоставляет:** + Сериализатор: `dataclass → bytes/wire format` + Десериализатор: `bytes/wire format → dataclass` + Регистрация схемы (если необходимо, например, для Pulsar/Kafka) + +**3. Абстракция потребителя/производителя:** + Уже существует (consumer.py, producer.py) + Обновление для использования сериализации бэкенда + Удаление прямых импортов Pulsar + +**4. Отображение типов:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### Путь миграции + +1. **Создайте версии классов данных** для всех схем в `trustgraph/schema/` +2. **Обновите классы бэкенда** (Consumer, Producer, Publisher, Subscriber) для использования сериализации, предоставляемой бэкендом +3. **Реализуйте PulsarBackend** с использованием JSON-схемы или динамической генерации записей +4. **Протестируйте с Pulsar**, чтобы обеспечить обратную совместимость с существующими развертываниями +5. **Добавьте новые бэкенды** (MQTT, Kafka, Redis и т. д.) по мере необходимости +6. **Удалите импорты Pulsar** из файлов схем + +### Преимущества + +✅ **Отсутствие зависимости от pub/sub** в определениях схем +✅ **Стандартный Python** - легко понять, проверить типы, документировать +✅ **Современные инструменты** - работает с mypy, автодополнением IDE, линтерами +✅ **Оптимизировано для бэкенда** - каждый бэкенд использует собственную сериализацию +✅ **Отсутствие накладных расходов на преобразование** - прямая сериализация, без адаптеров +✅ **Безопасность типов** - реальные объекты с правильными типами +✅ **Простая проверка** - можно использовать Pydantic, если необходимо + +### Проблемы и решения + +**Проблема:** У `Record` Pulsar есть проверка полей во время выполнения +**Решение:** Используйте классы данных Pydantic для проверки, если это необходимо, или функции Python 3.10+ для классов данных с `__post_init__` + +**Проблема:** Некоторые специфичные для Pulsar функции (например, тип `Bytes`) +**Решение:** Отобразите на тип `bytes` в классе данных, бэкенд обрабатывает кодирование соответствующим образом + +**Проблема:** Именование тем (`persistent://tenant/namespace/topic`) +**Решение:** Абстрагируйте имена тем в определениях схем, бэкенд преобразует в правильный формат + +**Проблема:** Эволюция и версионирование схем +**Решение:** Каждый бэкенд обрабатывает это в соответствии со своими возможностями (версии схем Pulsar, реестр схем Kafka и т. д.) + +**Проблема:** Вложенные сложные типы +**Решение:** Используйте вложенные классы данных, бэкенды рекурсивно сериализуют/десериализуют + +### Принятые решения + +1. **Обычные классы данных или Pydantic?** + ✅ **Решение: Используйте обычные классы данных Python** + Проще, без дополнительных зависимостей + Проверка не требуется на практике + Легче понять и поддерживать + +2. **Эволюция схемы:** + ✅ **Решение: Механизм версионирования не требуется** + Схемы стабильны и долговечны + Обновления обычно добавляют новые поля (обратная совместимость) + Бэкенды обрабатывают эволюцию схемы в соответствии со своими возможностями + +3. **Обратная совместимость:** + ✅ **Решение: Изменение основной версии, обратная совместимость не требуется** + Это будет изменение, нарушающее обратную совместимость, с инструкциями по миграции + Чистый разрыв позволяет лучше спроектировать систему + Будет предоставлено руководство по миграции для существующих развертываний + +4. **Вложенные типы и сложные структуры:** + ✅ **Решение: Используйте вложенные классы данных естественным образом** + Классы данных Python отлично справляются с вложенностью + `list[T]` для массивов, `dict[K, V]` для словарей + Бэкенды рекурсивно сериализуют/десериализуют + Пример: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **Значения по умолчанию и необязательные поля:** + ✅ **Решение: Комбинация обязательных, полей со значениями по умолчанию и необязательных полей** + Обязательные поля: Не имеют значения по умолчанию. + Поля со значениями по умолчанию: Всегда присутствуют, имеют разумные значения по умолчанию. + Действительно необязательные поля: `T | None = None`, опускаются при сериализации, когда `None` + Пример: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **Важные семантические аспекты сериализации:** + + Когда `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + Когда `metadata = {}` (явно пусто): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **Ключевое отличие:** + `None` → поле отсутствует в JSON (не сериализуется) + Пустое значение (`{}`, `[]`, `""`) → поле присутствует со значением "пусто" + Это имеет семантическое значение: "не предоставлено" против "явно пусто" + Механизмы сериализации должны пропускать поля `None`, а не кодировать их как `null` + +## Предварительный вариант 3: Детали реализации + +### Универсальный формат именования очередей + +Замените специфичные для каждого бэкенда имена очередей на универсальный формат, который бэкенды могут сопоставить соответствующим образом. + +**Формат:** `{qos}/{tenant}/{namespace}/{queue-name}` + +Где: +`qos`: Уровень качества обслуживания (QoS) + `q0` = best-effort (отправка без подтверждения) + `q1` = at-least-once (требуется подтверждение) + `q2` = exactly-once (двухфазное подтверждение) +`tenant`: Логическая группировка для многопользовательской среды +`namespace`: Подгруппа внутри арендатора +`queue-name`: Фактическое имя очереди/топика + +**Примеры:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### Отображение тем для бэкенда + +Каждый бэкенд преобразует общий формат в свой собственный формат: + +**Бэкенд Pulsar:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**Бэкэнд MQTT:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### Обновленная вспомогательная функция для темы + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### Конфигурация и инициализация + +**Аргументы командной строки + переменные окружения:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**Фабричная функция:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**Использование в AsyncProcessor:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### Интерфейс бэкенда + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### Рефакторинг существующих классов + +Существующие классы `Consumer`, `Producer`, `Publisher`, `Subscriber` остаются в основном без изменений: + +**Текущие обязанности (сохранить):** +Асинхронная модель потоков и группы задач +Логика повторного подключения и обработка повторных попыток +Сбор метрик +Ограничение скорости +Управление параллелизмом + +**Необходимые изменения:** +Удалить прямые импорты Pulsar (`pulsar.schema`, `pulsar.InitialPosition` и т.д.) +Принимать `BackendProducer`/`BackendConsumer` вместо клиента Pulsar +Передавать фактические операции публикации/подписки на экземпляры бэкенда +Отображать общие концепции на вызовы бэкенда + +**Пример рефакторинга:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### Специфические для бэкенда особенности + +**Бэкенд Pulsar:** +Отображает `q0` → `non-persistent://`, `q1`/`q2` → `persistent://` +Поддерживает все типы потребителей (shared, exclusive, failover) +Поддерживает начальную позицию (earliest/latest) +Поддержка подтверждения получения сообщений +Поддержка реестра схем + +**Бэкенд MQTT:** +Отображает `q0`/`q1`/`q2` → уровни качества обслуживания (QoS) MQTT 0/1/2 +Включает арендатора/пространство имен в путь темы для обеспечения разделения имен +Автоматически генерирует идентификаторы клиентов из имен подписок +Игнорирует начальную позицию (нет истории сообщений в базовом MQTT) +Игнорирует тип потребителя (MQTT использует идентификаторы клиентов, а не группы потребителей) +Простая модель публикации/подписки + +### Краткое описание принятых решений + +1. ✅ **Универсальное именование очередей**: формат `qos/tenant/namespace/queue-name` +2. ✅ **QoS в идентификаторе очереди**: определяется определением очереди, а не конфигурацией +3. ✅ **Повторное подключение**: обрабатывается классами Consumer/Producer, а не бэкендами +4. ✅ **Темы MQTT**: включают арендатора/пространство имен для правильного разделения имен +5. ✅ **История сообщений**: MQTT игнорирует параметр `initial_position` (будущее улучшение) +6. ✅ **Идентификаторы клиентов**: бэкенд MQTT автоматически генерирует из имени подписки + +### Будущие улучшения + +**История сообщений MQTT:** +Можно добавить необязательный слой постоянного хранения (например, сохраненные сообщения, внешний хранилище) +Это позволит поддерживать `initial_position='earliest'` +Не требуется для первоначальной реализации diff --git a/docs/tech-specs/pubsub.sw.md b/docs/tech-specs/pubsub.sw.md new file mode 100644 index 00000000..abc30332 --- /dev/null +++ b/docs/tech-specs/pubsub.sw.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "Mifumo ya Uwasilishaji na Ufuatiliaji (Pub/Sub)" +parent: "Swahili (Beta)" +--- + +# Mifumo ya Uwasilishaji na Ufuatiliaji (Pub/Sub) + +> **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 inaorodhesha miunganisho yote kati ya mfumo wa TrustGraph na miundomino ya uwasilishaji na ufuatiliaji. Kwa sasa, mfumo huu umewekwa ili kutumia Apache Pulsar. Uchunguzi huu unaeleza maeneo yote ya kuunganisha ili kutoa taarifa kwa urekebishaji wa baadaye kuelekea uainishaji wa uwasilishaji na ufuatiliaji unaoweza kusanidiwa. + +## Hali ya Sasa: Maeneo ya Kuunganisha ya Pulsar + +### 1. Matumizi ya Moja kwa Moja ya Mteja wa Pulsar + +**Mahali:** `trustgraph-flow/trustgraph/gateway/service.py` + +Lango la API huleta na kuunda mteja wa Pulsar moja kwa moja: + +**Laini ya 20:** `import pulsar` +**Laini za 54-61:** Uundaji wa moja kwa moja wa `pulsar.Client()` pamoja na `pulsar.AuthenticationToken()` inayohitajika. +**Laini za 33-35:** Usanidi chaguo-msingi wa hosti wa Pulsar kutoka kwa vigezo vya mazingira. +**Laini za 178-192:** Vigezo vya CLI kwa `--pulsar-host`, `--pulsar-api-key`, na `--pulsar-listener`. +**Laini za 78, 124:** Hupitisha `pulsar_client` kwa `ConfigReceiver` na `DispatcherManager`. + +Hii ndio eneo pekee ambalo huunda mteja wa Pulsar moja kwa moja nje ya safu ya uainishaji. + +### 2. Muundo wa Msingi wa Mchakato + +**Mahali:** `trustgraph-base/trustgraph/base/async_processor.py` + +Darasa la msingi kwa mchakato wote hutoa uwezo wa kuunganisha na Pulsar: + +**Laini ya 9:** `import _pulsar` (kwa usimamizi wa makosa) +**Laini ya 18:** `from . pubsub import PulsarClient` +**Laini ya 38:** Huunda `pulsar_client_object = PulsarClient(**params)` +**Laini za 104-108:** Vipengele ambavyo huonyesha `pulsar_host` na `pulsar_client` +**Laini ya 250:** Njia ya tuli `add_args()` huita `PulsarClient.add_args(parser)` kwa vigezo vya CLI +**Laini za 223-225:** Usimamizi wa makosa kwa `_pulsar.Interrupted` + +Mchakato wote hurithi kutoka kwa `AsyncProcessor`, na hivyo kuwa eneo kuu la kuunganisha. + +### 3. Uainishaji wa Mtumiaji + +**Mahali:** `trustgraph-base/trustgraph/base/consumer.py` + +Huchukua meseji kutoka kwa folyo na kutoa kazi za utendaji: + +**Uingizaji wa Pulsar:** +**Laini ya 12:** `from pulsar.schema import JsonSchema` +**Laini ya 13:** `import pulsar` +**Laini ya 14:** `import _pulsar` + +**Matumizi maalum ya Pulsar:** +**Laini za 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**Laini ya 108:** `JsonSchema(self.schema)` wrapper +**Laini ya 110:** `pulsar.ConsumerType.Shared` +**Laini za 104-111:** `self.client.subscribe()` pamoja na vigezo maalum ya Pulsar +**Laini za 143, 150, 65:** `consumer.unsubscribe()` na `consumer.close()` methods +**Laini ya 162:** `_pulsar.Timeout` exception +**Laini za 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**Faili ya spec:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**Laini ya 22:** Inarejelea `processor.pulsar_client` + +### 4. Uainishaji wa Mtume + +**Mahali:** `trustgraph-base/trustgraph/base/producer.py` + +Hutuma meseji kwa folyo: + +**Uingizaji wa Pulsar:** +**Laini ya 2:** `from pulsar.schema import JsonSchema` + +**Matumizi maalum ya Pulsar:** +**Laini ya 49:** `JsonSchema(self.schema)` wrapper +**Laini za 47-51:** `self.client.create_producer()` pamoja na vigezo maalum ya Pulsar (mada, schema, chunking_enabled) +**Laini za 31, 76:** `producer.close()` method +**Laini za 64-65:** `producer.send()` pamoja na meseji na vipengele + +**Faili ya spec:** `trustgraph-base/trustgraph/base/producer_spec.py` +**Laini ya 18:** Inarejelea `processor.pulsar_client` + +### 5. Uainishaji wa Mchapishaji + +**Mahali:** `trustgraph-base/trustgraph/base/publisher.py` + +Uchapishaji wa meseji usiohusisha na uwekaji wa folyo: + +**Uingizaji wa Pulsar:** +**Laini ya 2:** `from pulsar.schema import JsonSchema` +**Laini ya 6:** `import pulsar` + +**Matumizi maalum ya Pulsar:** +**Laini ya 52:** `JsonSchema(self.schema)` wrapper +**Laini za 50-54:** `self.client.create_producer()` pamoja na vigezo maalum ya Pulsar +**Laini za 101, 103:** `producer.send()` pamoja na meseji na vipengele vya hiari +**Laini za 106-107:** `producer.flush()` na `producer.close()` methods + +### 6. Uainishaji wa Mlisani + +**Mahali:** `trustgraph-base/trustgraph/base/subscriber.py` + +Inatoa usambazaji wa ujumbe kwa wapokeaji wengi kutoka kwa folyo: + +**Uingizaji kutoka Pulsar:** +**Laini ya 6:** `from pulsar.schema import JsonSchema` +**Laini ya 8:** `import _pulsar` + +**Matumizi maalum ya Pulsar:** +**Laini ya 55:** `JsonSchema(self.schema)` wrapper +**Laini ya 57:** `self.client.subscribe(**subscribe_args)` +**Laini 101, 136, 160, 167-172:** Vizuizi vya Pulsar: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**Laini 159, 166, 170:** Mbinu za mtumiaji: `negative_acknowledge()`, `unsubscribe()`, `close()` +**Laini 247, 251:** Utambuzi wa ujumbe: `acknowledge()`, `negative_acknowledge()` + +**Faili ya spec:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**Laini ya 19:** Inarejelea `processor.pulsar_client` + +### 7. Mfumo wa Schemas (Heart of Darkness) + +**Mahali:** `trustgraph-base/trustgraph/schema/` + +Schemas kila ujumbe katika mfumo huu imefafanuliwa kwa kutumia mfumo wa schemas wa Pulsar. + +**Vipengele muhimu:** `schema/core/primitives.py` +**Laini ya 2:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +Schemas zote hurithi kutoka kwa darasa la msingi la Pulsar `Record` +Aina zote za sehemu ni aina za Pulsar: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**Sampuli za schemas:** +`schema/services/llm.py` (Laini ya 2): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (Laini ya 2): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**Jina la mada:** `schema/core/topic.py` +**Laini 2-3:** Muundo wa mada: `{kind}://{tenant}/{namespace}/{topic}` +Muundo huu wa URI ni maalum kwa Pulsar (k.m.e., `persistent://tg/flow/config`) + +**Athari:** +Ufafanuzi wote wa ujumbe wa ombi/jibu katika msimbo wote hutumia schemas za Pulsar +Hii inajumuisha huduma za: config, flow, llm, prompt, query, storage, agent, collection, diagnosis, library, lookup, nlp_query, objects_query, retrieval, structured_query +Ufafanuzi wa schemas huingizwa na kutumika kwa kina katika processors na huduma zote + +## Muhtasari + +### Utegemezi wa Pulsar kwa Kategoria + +1. **Uundaji wa mteja:** + Moja kwa moja: `gateway/service.py` + Imefichwa: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **Usafirishaji wa ujumbe:** + Mtumiaji: `consumer.py`, `consumer_spec.py` + Mtayarishaji: `producer.py`, `producer_spec.py` + Mchapishaji: `publisher.py` + Msubiri: `subscriber.py`, `subscriber_spec.py` + +3. **Mfumo wa schemas:** + Aina za msingi: `schema/core/primitives.py` + Schemas zote za huduma: `schema/services/*.py` + Jina la mada: `schema/core/topic.py` + +4. **Dhima maalum za Pulsar zinazohitajika:** + Ujumbe unaotegemea mada + Mfumo wa schemas (Rekodi, aina za sehemu) + Usajili uliogawanywa + Utambuzi wa ujumbe (chanya/hasi) + Nafasi ya mtumiaji (mapema/ya hivi karibuni) + Sifa za ujumbe + Nafasi ya awali na aina za mtumiaji + Usaidizi wa chunking + Mada za kudumu vs. zisizo za kudumu + +### Changamoto za Urekebishaji + +Habari njema: Safu ya uainishaji (Mtumiaji, Mtayarishaji, Mchapishaji, Msubiri) hutoa uainishaji safi wa mwingiliano mwingi wa Pulsar. + +Changamoto: +1. **Ukuaji wa mfumo wa schemas:** Ufafanuzi kila ujumbe hutumia `pulsar.schema.Record` na aina za Pulsar +2. **Enums maalum za Pulsar:** `InitialPosition`, `ConsumerType` +3. **Vizuizi vya Pulsar:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **Mifumo ya mbinu:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, n.k. +5. **Muundo wa URI ya mada:** Muundo wa `kind://tenant/namespace/topic` wa Pulsar + +### Hatua Zinazofuata + +Ili kufanya miundombinu ya p/s kuwa configurable, tunahitaji: + +1. Kuunda kiolesura cha uainishaji kwa mfumo wa mteja/schema +2. Kuainisha enums na vizuizi maalum za Pulsar +3. Kuunda wrappers za schemas au ufafanuzi mbadala wa schemas +4. Kutekeleza kiolesura kwa wateja na mifumo mingine (Kafka, RabbitMQ, Redis Streams, n.k.) +5. Kusasisha `pubsub.py` ili iwe configurable na iunge mkono mifumo mingi +6. Kutoa njia ya uhamishaji kwa usakinishaji uliopo + +## Mfumo Mkuu wa 1: Mfumo wa Adapta na Safu ya Tafsiri ya Schemas + +### Maarifa Muhimu +Mfumo wa schemas ndio msingi wa mfumo huu. + + + +**1. Endelea kutumia muundo wa Pulsar kama uwakilishi wa ndani** +Usiandike upya maelezo yote ya muundo. +Muundo utabaki `pulsar.schema.Record` ndani. +Tumia adapta ili kutafsiri katika eneo kati ya programu yetu na mfumo wa utumaji/kupokea. + +**2. Unda safu ya utengwa kwa utumaji/kupokea:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. Tafakikata viambishi vya dhahabu:** +`PubSubClient` - muunganisho wa mteja +`PubSubProducer` - kutuma ujumbe +`PubSubConsumer` - kupokea ujumbe +`SchemaAdapter` - kutafsiri muundo wa Pulsar kuwa/kutoka JSON au muundo maalum wa mfumo wa nyuma + +**4. Maelezo ya utekelezaji:** + +Kwa **adapta ya Pulsar**: Karibu kupita moja kwa moja, tafsiri ndogo. + +Kwa **mfumo mwingine wa nyuma** (Kafka, RabbitMQ, n.k.): +Tafsiri vitu vya rekodi ya Pulsar kuwa JSON/bytes +Linganisha dhana kama: + `InitialPosition.Earliest/Latest` → auto.offset.reset ya Kafka + `acknowledge()` → kukubali kwa Kafka + `negative_acknowledge()` → mfumo wa kurudisha au DLQ + URI za mada → majina ya mada maalum ya mfumo wa nyuma + +### Uchambuzi + +**Faida:** +✅ Mabadiliko madogo ya msimbo kwa huduma zilizopo +✅ Muundo unaendelea kuwa kama ilivyo (hakuna marekebisho makubwa) +✅ Njia ya hatua kwa hatua ya uhamishaji +✅ Watumiaji wa Pulsar hawona tofauti +✅ Mifumo mipya ya nyuma inaongezwa kupitia adapta + +**Hasara:** +⚠️ Bado ina utegemezi wa Pulsar (kwa maelezo ya muundo) +⚠️ Mizozo mingine inapotafsiri dhana + +### Toleo Mbadala + +Unda **mfumo wa muundo wa TrustGraph** ambao hautegemei mfumo wowote wa kutuma na kupokea (kwa kutumia madarasa ya data au Pydantic), kisha uzalisha muundo wa Pulsar/Kafka/n.k. kutoka humo. Hii inahitaji kuandikewa tena kila faili ya muundo na inaweza kusababisha mabadiliko. + +### Mapendekezo kwa Rasimu ya 1 + +Anza na **mbinu ya adapta** kwa sababu: +1. Ni ya vitendo - inafanya kazi na msimbo uliopo +2. Inathibitisha dhana kwa hatari ndogo +3. Inaweza kubadilika kuwa mfumo wa asili wa muundo baadaye ikiwa inahitajika +4. Inadumishwa kupitia usanidi: variable moja ya mazingira inabadilisha mifumo ya nyuma + +## Mbinu ya Rasimu ya 2: Mfumo wa Muundo Usio na Utendaji wa Nyuma na Madarasa ya Data + +### Dhana Kuu + +Tumia **madarasa ya data ya Python** kama muundo wa muundo wa kati. Kila mfumo wa nyuma wa kutuma na kupokea hutoa utafsiri wake mwenyewe wa kuandika/kusoma kwa madarasa ya data, na kuondoa hitaji kwamba muundo wa Pulsar uendelee kuwa katika msimbo. + +### Ulinganifu wa Muundo katika Kiwango cha Kiwanda + +Badala ya kutafsiri muundo wa Pulsar, **kila mfumo wa nyuma hutoa utunzaji wake mwenyewe wa muundo** ambao unafanya kazi na madarasa ya data ya Python ya kawaida. + +### Mtiririko wa Mchapishaji + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### Mchakato wa Mtumiaji + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### Kile Kinachotokea Nyuma ya Kulabu + +**Kwa mfumo wa nyuma (backend) wa Pulsar:** +`create_producer()` → huunda mtayarishaji (producer) wa Pulsar ukitumia schema ya JSON au rekodi iliyoundwa moja kwa moja. +`send(request)` → huhifadhi (hufanya serialization) darasa la data (dataclass) kuwa muundo wa JSON/Pulsar, na hutuma kwa Pulsar. +`receive()` → hupokea ujumbe wa Pulsar, na huhifadhi tena (hufanya deserialization) kurudi kuwa darasa la data. + +**Kwa mfumo wa nyuma (backend) wa MQTT:** +`create_producer()` → huunganisha na programu (broker) ya MQTT, hakuna haja ya usajili wa schema. +`send(request)` → hubadilisha darasa la data kuwa JSON, na hutuma kwenye mada (topic) ya MQTT. +`receive()` → huhudhuria mada (topic) ya MQTT, na huhifadhi tena JSON kurudi kuwa darasa la data. + +**Kwa mfumo wa nyuma (backend) wa Kafka:** +`create_producer()` → huunda mtayarishaji (producer) wa Kafka, na husajili schema ya Avro ikiwa inahitajika. +`send(request)` → huhifadhi darasa la data kuwa muundo wa Avro, na hutuma kwa Kafka. +`receive()` → hupokea ujumbe wa Kafka, na huhifadhi tena Avro kurudi kuwa darasa la data. + +### Vipengele Muhimu vya Ubunifu + +1. **Uundaji wa kitu (object) cha schema:** Kitu (object) cha darasa la data (dataclass) (`TextCompletionRequest(...)`) ni sawa bila kujali mfumo wa nyuma (backend). +2. **Mfumo wa nyuma (backend) hutunza uhifadhi:** Kila mfumo wa nyuma (backend) unajua jinsi ya kuhifadhi darasa lake la data kuwa muundo unaotumwa. +3. **Ufafanuzi wa schema wakati wa uundaji:** Unapounda mtayarishaji (producer)/mpokeaji (consumer), unataja aina ya schema. +4. **Usalama wa aina (type) unahifadhiwa:** Unapata kitu (object) sahihi cha `TextCompletionRequest`, sio kamusi (dict). +5. **Hakuna uvujaji wa mfumo wa nyuma (backend):** Msimbo wa programu kamwe hauingize maktaba maalum za mfumo wa nyuma (backend). + +### Mfano wa Ubadilishaji + +**Hali ya sasa (maalum kwa Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**Mpya (Sio tegemezi ya mfumo wa nyuma):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### Uunganisho wa Seva ya Nyuma (Backend) + +Kila seva ya nyuma hushughulikia us serialization/deserialization wa madatakesi: + +**Seva ya nyuma ya Pulsar:** +Huunda madatakesi `pulsar.schema.Record` moja kwa moja kutoka kwa madatakesi. +Au huserialize madatakesi hadi JSON na kutumia mfumo wa JSON wa Pulsar. +Inaendelea kudumisha utangamano na matumizi ya sasa ya Pulsar. + +**Seva ya nyuma ya MQTT/Redis:** +Huserialize madatakesi ya aina ya JSON moja kwa moja. +Tumia `dataclasses.asdict()` / `from_dict()`. +Nyepesi, haihitaji usajili wa mfumo. + +**Seva ya nyuma ya Kafka:** +Huunda mifumo ya Avro kutoka kwa maelezo ya madatakesi. +Tumia usajili wa mfumo wa Confluent. +Us serialization wa salama wa aina na udhamini wa mabadiliko ya mfumo. + +### Muundo + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### Maelezo ya Utendaji + +**1. Ufafanuzi wa muundo:** Darasa za data za kawaida na maelezo ya aina + `str`, `int`, `bool`, `float` kwa vipengele vya msingi + `list[T]` kwa safu + `dict[str, T]` kwa ramani + Darasa za data zilizounganishwa kwa aina ngumu + +**2. Kila mfumo hutoa:** + Mfumo wa ubadilishaji: `dataclass → bytes/wire format` + Mfumo wa kurejesha: `bytes/wire format → dataclass` + Usajili wa muundo (ikiwa inahitajika, kama Pulsar/Kafka) + +**3. Dhana ya mtumiaji/mtayarishaji:** + Tayari ipo (consumer.py, producer.py) + Sasisha ili kutumia ubadilishaji wa mfumo + Ondoa uingizaji wa moja kwa moja wa Pulsar + +**4. Ulinganisho wa aina:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### Njia ya Uhamishaji + +1. **Tengeneza matoleo ya darasa za data** ya muundo wote katika `trustgraph/schema/` +2. **Sasisha madarasa ya mfumo** (Mtumiaji, Mtayarishaji, Mchapishaji, Mwasili) ili kutumia ubadilishaji unaotolewa na mfumo +3. **Teleza PulsarBackend** na muundo wa JSON au uzalishaji wa Rekodi wa moja kwa moja +4. **Jaribu na Pulsar** ili kuhakikisha utangamano wa nyuma na matumizi yaliyopo +5. **Ongeza mifumo mipya** (MQTT, Kafka, Redis, n.k.) kama inahitajika +6. **Ondoa uingizaji wa Pulsar** kutoka kwa faili za muundo + +### Faida + +✅ **Hakuna utegemezi wa pub/sub** katika ufafanuzi wa muundo +✅ **Python ya kawaida** - rahisi kuelewa, kuangalia aina, na kutoa maelezo +✅ **Zana za kisasa** - inafanya kazi na mypy, kukamilisha kiotomatiki kwa IDE, na vichujio +✅ **Imeboreshwa kwa mfumo** - kila mfumo hutumia ubadilishaji wa asili +✅ **Hakuna gharama ya tafsiri** - ubadilishaji wa moja kwa moja, hakuna adapta +✅ **Usalama wa aina** - vitu halisi na aina sahihi +✅ **Uthibitisho rahisi** - inaweza kutumia Pydantic ikiwa inahitajika + +### Changamoto na Suluhisho + +**Changamoto:** `Record` ya Pulsar ina uthibitisho wa uwanja wakati wa utekelezaji +**Suluhisho:** Tumia darasa za data za Pydantic kwa uthibitisho ikiwa inahitajika, au vipengele vya darasa za data ya Python 3.10+ na `__post_init__` + +**Changamoto:** Vipengele vingine maalum vya Pulsar (kama aina ya `Bytes`) +**Suluhisho:** Linganisha na aina ya `bytes` katika darasa ya data, mfumo hutunza uandikaji ipasavyo + +**Changamoto:** Majina ya mada (`persistent://tenant/namespace/topic`) +**Suluhisho:** Dhani majina ya mada katika ufafanuzi wa muundo, mfumo hubadilisha kuwa muundo sahihi + +**Changamoto:** Maendeleo na toleo la muundo +**Suluhisho:** Kila mfumo hushughulikia hii kulingana na uwezo wake (matoleo ya muundo ya Pulsar, rejista ya muundo ya Kafka, n.k.) + +**Changamoto:** Aina ngumu zilizounganishwa +**Suluhisho:** Tumia darasa za data zilizounganishwa, mifumo inabadilisha/kurejesha kwa uangalifu + +### Maamuzi ya Ubunifu + +1. **Darasa za data za kawaida au Pydantic?** + ✅ **Maamuzi: Tumia darasa za data za Python za kawaida** + Rahisi, hakuna utegemezi wa ziada + Uthibitisho hauhitajiki kwa mazoea + Rahisi kuelewa na kudumisha + +2. **Maendeleo ya muundo:** + ✅ **Maamuzi: Hakuna utaratibu wa toleo unaohitajika** + Miondoko ni thabiti na ya muda mrefu + Marekebisho kawaida huongeza sehemu mpya (utangamano wa nyuma) + Mifumo inashughulikia maendeleo ya muundo kulingana na uwezo wake + +3. **Ulingano wa nyuma:** + ✅ **Maamuzi: Mabadiliko makubwa ya toleo, utangamano wa nyuma hauhitajiki** + Itakuwa mabadiliko ya kuvunja na maagizo ya uhamishaji + Kutoa mtego huruhusu muundo bora + Mwongozo wa uhamishaji utatolewa kwa matumizi yaliyopo + +4. **Aina zilizounganishwa na miundo ngumu:** + ✅ **Maamuzi: Tumia darasa za data zilizounganishwa kwa asili** + Darasa za data za Python zinashughulikia uunganishaji kikamilifu + `list[T]` kwa safu, `dict[K, V]` kwa ramani + Mifumo inabadilisha/kurejesha kwa uangalifu + Mfano: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **Maelezo ya msingi na sehemu za hiari:** + ✅ **Uamuzi: Mchanganyiko wa sehemu za lazima, maelezo ya msingi, na sehemu za hiari** + Sehemu za lazima: Hakuna maelezo ya msingi + Sehemu zilizo na maelezo ya msingi: Zipo kila wakati, zina maelezo ya msingi yanayofaa + Sehemu za hiari kabisa: `T | None = None`, huachwa kutoka kwenye serialization wakati `None` + Mfano: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **Maana muhimu ya usanifu:** + + Wakati `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + Wakati `metadata = {}` (tupu wazi): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **Tofauti kuu:** + `None` → sehemu ambayo haina katika JSON (hairekebishwi) + Thamani tupu (`{}`, `[]`, `""`) → sehemu inayoonekana na thamani tupu + Hii ina umuhimu wa maana: "haiyapatikani" dhidi ya "tupu kwa uwazi" + Mifumo ya kurekebisha data lazima zisipite sehemu za `None`, badala ya kuzirekebisha kama `null` + +## Mfumo wa Awali wa 3: Maelezo ya Utendaji + +### Muundo wa Jina la Kawaida la Kundi + +Badilisha majina ya kundi maalum ya kila mfumo na muundo wa kawaida ambao mifumo inaweza kulinganisha ipasavyo. + +**Muundo:** `{qos}/{tenant}/{namespace}/{queue-name}` + +Ambako: +`qos`: Ngazi ya Huduma ya Ubora + `q0` = juhudi za kawaida (tuma na usisahau, hakuna utambuzi) + `q1` = angalau mara moja (inahitaji utambuzi) + `q2` = hasiwa mara moja (utambuzi wa awamu mbili) +`tenant`: Kikundi cha mantiki kwa ushirikaji wa wateja wengi +`namespace`: Kikundi kidogo ndani ya mteja +`queue-name`: Jina halisi la kundi/mada + +**Mfano:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### Ramani ya Mada za Seva ya Nyuma (Backend) + +Kila seva ya nyuma (backend) inaunganisha muundo wa jumla na muundo wake wa asili: + +**Seva ya Nyuma ya Pulsar:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**Umfumo wa Nyuma wa MQTT:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### Kazi ya Msaidizi ya Mada Iliyosasishwa + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### Usanidi na Uanzishaji + +**Vigezo vya Amri na Vigezo vya Mazingira:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**Fungua Kazi:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**Matumizi katika AsyncProcessor:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### Kiolesura cha Nyuma + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### Urekebishaji wa Darasa Zilizopo + +Madarasa yaliyopo ya `Consumer`, `Producer`, `Publisher`, `Subscriber` yanabaki kwa kiasi kikubwa bila kubadilishwa: + +**Jukumu la sasa (hakikisha):** +Mfumo wa uzi usio na usumbufu na vikundi vya kazi +Mantiki ya kuunganisha tena na udhibiti wa kujaribu tena +Ukusanyaji wa metriki +Udhibiti wa kiwango +Usimamizi wa ushindani + +**Mabadiliko yanayohitajika:** +Ondoa uingizaji wa moja kwa moja wa Pulsar (`pulsar.schema`, `pulsar.InitialPosition`, n.k.) +Kubali `BackendProducer`/`BackendConsumer` badala ya mteja wa Pulsar +Agiza shughuli halisi za kutuma/kupokea kwa mifumo ya nyuma +Linganisha dhana za jumla na simu za mfumo wa nyuma + +**Mfano wa urekebishaji:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### Tabia Maalum za Seva (Backend) + +**Seva ya Pulsar:** +Inahusisha `q0` → `non-persistent://`, `q1`/`q2` → `persistent://` +Inasaidia aina zote za watumiaji (walioshirikiana, wa kipekee, wa chechezi) +Inasaidia nafasi ya awali (ya kwanza/ya mwisho) +Utambuzi wa asili wa ujumbe +Inasaidia usajili wa schema + +**Seva ya MQTT:** +Inahusisha `q0`/`q1`/`q2` → Viwango vya QoS vya MQTT 0/1/2 +Inajumuisha mpangilio/nafasi katika njia ya mada kwa ajili ya utenganishaji +Inazalisha kiotomatiki vitambulisho vya wateja kutoka kwa majina ya usajili +Inapuuza nafasi ya awali (hakuna historia ya ujumbe katika MQTT ya msingi) +Inapuuza aina ya mtumiaji (MQTT hutumia vitambulisho vya wateja, sio vikundi vya watumiaji) +Mfumo rahisi wa kuchapisha/kusajili + +### Muhtasari wa Maamuzi ya Ubunifu + +1. ✅ **Jina la kawaida la folyo:** Muundo wa `qos/tenant/namespace/queue-name` +2. ✅ **QoS katika kitambulisho cha folyo:** Huamuliwa na ufafanuzi wa folyo, sio usanidi +3. ✅ **Uunganishaji upya:** Unashughulikiwa na madarasa ya Mtumiaji/Mzalishaji, sio seva +4. ✅ **Mada za MQTT:** Zijumuishie mpangilio/nafasi kwa ajili ya utenganishaji sahihi +5. ✅ **Historia ya ujumbe:** MQTT inapuuza parameter ya `initial_position` (ongezeko la baadaye) +6. ✅ **Vitambulisho vya wateja:** Seva ya MQTT inazalisha kiotomatiki kutoka kwa jina la usajili + +### Ongezeko za Baadaye + +**Historia ya ujumbe wa MQTT:** +Inaweza kuongeza safu ya hiari ya kudumu (k.m., ujumbe uliokaguliwa, duka la nje) +Itaruhusu kuunga mkono `initial_position='earliest'` +Haihitajiki kwa utekelezaji wa awali diff --git a/docs/tech-specs/pubsub.tr.md b/docs/tech-specs/pubsub.tr.md new file mode 100644 index 00000000..149bbf4d --- /dev/null +++ b/docs/tech-specs/pubsub.tr.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "Pub/Sub Altyapısı" +parent: "Turkish (Beta)" +--- + +# Pub/Sub Altyapısı + +> **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, TrustGraph kod tabanı ile pub/sub altyapısı arasındaki tüm bağlantıları listeler. Şu anda sistem, Apache Pulsar'ı kullanmak üzere sabit kodlanmıştır. Bu analiz, yapılandırılabilir bir pub/sub soyutlamasına yönelik gelecekteki yeniden düzenlemeleri bilgilendirmek için tüm entegrasyon noktalarını belirler. + +## Mevcut Durum: Pulsar Entegrasyon Noktaları + +### 1. Doğrudan Pulsar İstemci Kullanımı + +**Konum:** `trustgraph-flow/trustgraph/gateway/service.py` + +API ağ geçidi, doğrudan Pulsar istemcisini içe aktarır ve örnekler: + +**Satır 20:** `import pulsar` +**Satırlar 54-61:** `pulsar.Client()`'ın doğrudan örneklenmesi, isteğe bağlı `pulsar.AuthenticationToken()` ile birlikte +**Satırlar 33-35:** Ortam değişkenlerinden varsayılan Pulsar ana bilgisayarı yapılandırması +**Satırlar 178-192:** `--pulsar-host`, `--pulsar-api-key` ve `--pulsar-listener` için CLI argümanları +**Satırlar 78, 124:** `pulsar_client`'ı `ConfigReceiver` ve `DispatcherManager`'ye geçirir + +Bu, bir soyutlama katmanı dışında bir Pulsar istemcisinin doğrudan örneklenmesini yapan tek konumdur. + +### 2. Temel İşlemci Çerçevesi + +**Konum:** `trustgraph-base/trustgraph/base/async_processor.py` + +Tüm işlemciler için temel sınıf, Pulsar bağlantısı sağlar: + +**Satır 9:** `import _pulsar` (istisna işleme için) +**Satır 18:** `from . pubsub import PulsarClient` +**Satır 38:** `pulsar_client_object = PulsarClient(**params)` oluşturur +**Satırlar 104-108:** `pulsar_host` ve `pulsar_client`'i ortaya koyan özellikler +**Satır 250:** Statik yöntem `add_args()`, CLI argümanları için `PulsarClient.add_args(parser)`'i çağırır +**Satırlar 223-225:** `_pulsar.Interrupted` için istisna işleme + +Tüm işlemciler `AsyncProcessor`'dan türetildiği için, bu merkezi bir entegrasyon noktasıdır. + +### 3. Tüketici Soyutlaması + +**Konum:** `trustgraph-base/trustgraph/base/consumer.py` + +Kuyruklardan mesajlar tüketir ve işleyici fonksiyonlarını çağırır: + +**Pulsar içe aktarmaları:** +**Satır 12:** `from pulsar.schema import JsonSchema` +**Satır 13:** `import pulsar` +**Satır 14:** `import _pulsar` + +**Pulsar'a özgü kullanım:** +**Satırlar 100, 102:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**Satır 108:** `JsonSchema(self.schema)` sarmalayıcısı +**Satır 110:** `pulsar.ConsumerType.Shared` +**Satırlar 104-111:** Pulsar'a özgü parametrelerle `self.client.subscribe()` +**Satırlar 143, 150, 65:** `consumer.unsubscribe()` ve `consumer.close()` yöntemleri +**Satır 162:** `_pulsar.Timeout` istisnası +**Satırlar 182, 205, 232:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**Belge dosyası:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**Satır 22:** `processor.pulsar_client`'a referans + +### 4. Yayıncı Soyutlaması + +**Konum:** `trustgraph-base/trustgraph/base/producer.py` + +Kuyruklara mesaj gönderir: + +**Pulsar içe aktarmaları:** +**Satır 2:** `from pulsar.schema import JsonSchema` + +**Pulsar'a özgü kullanım:** +**Satır 49:** `JsonSchema(self.schema)` sarmalayıcısı +**Satırlar 47-51:** Pulsar'a özgü parametrelerle (konu, şema, chunking_enabled) `self.client.create_producer()` +**Satırlar 31, 76:** `producer.close()` yöntemi +**Satırlar 64-65:** Mesaj ve özelliklerle `producer.send()` + +**Belge dosyası:** `trustgraph-base/trustgraph/base/producer_spec.py` +**Satır 18:** `processor.pulsar_client`'a referans + +### 5. Yayıncı Soyutlaması + +**Konum:** `trustgraph-base/trustgraph/base/publisher.py` + +Kuyruklu tamponlama ile asenkron mesaj yayınlama: + +**Pulsar içe aktarmaları:** +**Satır 2:** `from pulsar.schema import JsonSchema` +**Satır 6:** `import pulsar` + +**Pulsar'a özgü kullanım:** +**Satır 52:** `JsonSchema(self.schema)` sarmalayıcısı +**Satırlar 50-54:** Pulsar'a özgü parametrelerle `self.client.create_producer()` +**Satırlar 101, 103:** Mesaj ve isteğe bağlı özelliklerle `producer.send()` +**Satırlar 106-107:** `producer.flush()` ve `producer.close()` yöntemleri + +### 6. Abonelik Soyutlaması + +**Konum:** `trustgraph-base/trustgraph/base/subscriber.py` + +Kuyruklardan çoklu alıcıya mesaj dağıtımı sağlar: + +**Pulsar importları:** +**6. Satır:** `from pulsar.schema import JsonSchema` +**8. Satır:** `import _pulsar` + +**Pulsar'a özgü kullanım:** +**55. Satır:** `JsonSchema(self.schema)` wrapper +**57. Satır:** `self.client.subscribe(**subscribe_args)` +**101, 136, 160, 167-172. Satırlar:** Pulsar istisnaları: `_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**159, 166, 170. Satırlar:** Tüketici metotları: `negative_acknowledge()`, `unsubscribe()`, `close()` +**247, 251. Satırlar:** Mesaj onayı: `acknowledge()`, `negative_acknowledge()` + +**Spec dosyası:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**19. Satır:** `processor.pulsar_client`'a referans + +### 7. Şema Sistemi (Heart of Darkness) + +**Konum:** `trustgraph-base/trustgraph/schema/` + +Sistemdeki her mesaj şeması, Pulsar'ın şema çerçevesi kullanılarak tanımlanır. + +**Temel öğeler:** `schema/core/primitives.py` +**2. Satır:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +Tüm şemalar, Pulsar'ın `Record` temel sınıfından türetilir. +Tüm alan türleri Pulsar türleridir: `String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**Örnek şemalar:** +`schema/services/llm.py` (2. Satır): `from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (2. Satır): `from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**Konu adlandırması:** `schema/core/topic.py` +**2-3. Satırlar:** Konu formatı: `{kind}://{tenant}/{namespace}/{topic}` +Bu URI yapısı Pulsar'a özgüdür (örneğin, `persistent://tg/flow/config`) + +**Etki:** +Kod tabanındaki tüm istek/yanıt mesaj tanımları, Pulsar şemalarını kullanır. +Bu, aşağıdaki hizmetler için geçerlidir: yapılandırma, akış, LLM, istem, sorgu, depolama, aracı, koleksiyon, tanı, kütüphane, arama, NLP sorgusu, nesne sorgusu, alma, yapılandırılmış sorgu. +Şema tanımları, tüm işlemciler ve hizmetler genelinde kapsamlı bir şekilde içe aktarılır ve kullanılır. + +## Özet + +### Kategoriye Göre Pulsar Bağımlılıkları + +1. **İstem oluşturma:** + Doğrudan: `gateway/service.py` + Soyutlanmış: `async_processor.py` → `pubsub.py` (PulsarClient) + +2. **Mesaj taşıma:** + Tüketici: `consumer.py`, `consumer_spec.py` + Üretici: `producer.py`, `producer_spec.py` + Yayıncı: `publisher.py` + Abonelik: `subscriber.py`, `subscriber_spec.py` + +3. **Şema sistemi:** + Temel türler: `schema/core/primitives.py` + Tüm hizmet şemaları: `schema/services/*.py` + Konu adlandırması: `schema/core/topic.py` + +4. **Gereken Pulsar'a özgü kavramlar:** + Konuya dayalı mesajlaşma + Şema sistemi (Kayıt, alan türleri) + Paylaşımlı abonelikler + Mesaj onayı (olumlu/olumsuz) + Tüketici konumlandırması (en erken/en son) + Mesaj özellikleri + Başlangıç konumları ve tüketici türleri + Parçalama desteği + Kalıcı ve kalıcı olmayan konular + +### Yeniden Düzenleme Zorlukları + +İyi haber: Soyutlama katmanı (Tüketici, Üretici, Yayıncı, Abonelik), çoğu Pulsar etkileşimini temiz bir şekilde kapsar. + +Zorluklar: +1. **Şema sisteminin yaygınlığı:** Her mesaj tanımı `pulsar.schema.Record` ve Pulsar alan türlerini kullanır. +2. **Pulsar'a özgü numaralandırmalar:** `InitialPosition`, `ConsumerType` +3. **Pulsar istisnaları:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **Metot imzaları:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, vb. +5. **Konu URI formatı:** Pulsar'ın `kind://tenant/namespace/topic` yapısı + +### Sonraki Adımlar + +Yayın/abone altyapısını yapılandırılabilir hale getirmek için şunları yapmamız gerekiyor: + +1. İstem/şema sistemi için bir soyutlama arayüzü oluşturun. +2. Pulsar'a özgü numaralandırmaları ve istisnaları soyutlayın. +3. Şema sargıları veya alternatif şema tanımları oluşturun. +4. Arayüzü hem Pulsar hem de alternatif sistemler (Kafka, RabbitMQ, Redis Streams, vb.) için uygulayın. +5. `pubsub.py`'ı yapılandırılabilir hale getirin ve çoklu arka uçları destekleyin. +6. Mevcut dağıtımlar için bir geçiş yolu sağlayın. + +## Yaklaşım Taslağı 1: Şema Çeviri Katmanıyla Adaptör Kalıbı + +### Temel Bilgi +**Şema sistemi**, en derin entegrasyon noktasıdır - her şey ondan kaynaklanır. Önce bunu çözmemiz gerekiyor, aksi takdirde tüm kodu yeniden yazmamız gerekecek. + +### Strateji: Minimum Bozulma ile Adaptörler + +**1. Pulsar şemalarını, dahili gösterim olarak koruyun** +Tüm şema tanımlarını yeniden yazmayın +Şemalar, dahili olarak `pulsar.schema.Record` olarak kalır +Adaptörleri, kendi kodumuz ile yayın/abonelik arka ucu arasındaki sınırdaki çevirileri yapmak için kullanın + +**2. Bir yayın/abonelik soyutlama katmanı oluşturun:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. Soyut arayüzleri tanımlayın:** +`PubSubClient` - istemci bağlantısı +`PubSubProducer` - mesaj gönderme +`PubSubConsumer` - mesaj alma +`SchemaAdapter` - Pulsar şemalarını JSON'a veya arka uç özel formatlarına dönüştürme/dönüştürme + +**4. Uygulama detayları:** + +**Pulsar adaptörü için:** Neredeyse doğrudan geçiş, minimum çeviri + +**Diğer arka uçlar için** (Kafka, RabbitMQ, vb.): +Pulsar Kayıt nesnelerini JSON/byte'a serileştirin +Aşağıdaki kavramları eşleyin: + `InitialPosition.Earliest/Latest` → Kafka'nın auto.offset.reset'i + `acknowledge()` → Kafka'nın commit'i + `negative_acknowledge()` → Yeniden kuyruklama veya DLQ deseni + Konu URI'leri → Arka uç özel konu adları + +### Analiz + +**Artıları:** +✅ Mevcut hizmetlerde minimum kod değişikliği +✅ Şemalar olduğu gibi kalır (büyük bir yeniden yazım olmaz) +✅ Aşamalı geçiş yolu +✅ Pulsar kullanıcıları hiçbir fark görmez +✅ Yeni arka uçlar adaptörler aracılığıyla eklenir + +**Eksileri:** +⚠️ Hala Pulsar bağımlılığı taşır (şema tanımları için) +⚠️ Kavramları çevirirken bazı uyumsuzluklar olabilir + +### Alternatif Düşünce + +Bir **TrustGraph şema sistemi** oluşturun; bu sistem, pub/sub'dan bağımsızdır (dataclass'lar veya Pydantic kullanarak). Ardından, bu sistemden Pulsar/Kafka/vb. şemalarını oluşturun. Bu, her şema dosyasının yeniden yazılmasını gerektirir ve potansiyel olarak uyumsuzluklara neden olabilir. + +### Taslak 1 için Öneri + +**Adaptör yaklaşımıyla** başlayın çünkü: +1. Pratik bir yaklaşımdır - mevcut kodla çalışır +2. Minimum riskle kavramı kanıtlar +3. Gerekirse daha sonra yerel bir şema sistemine dönüştürülebilir +4. Yapılandırma odaklıdır: tek bir ortam değişkeni arka uçları değiştirir + +## Yaklaşım Taslağı 2: Dataclass'larla Arka Uçtan Bağımsız Şema Sistemi + +### Temel Kavram + +Python **dataclass'ları** tarafsız şema tanımı formatı olarak kullanın. Her pub/sub arka ucu, dataclass'lar için kendi serileştirme/deserileştirme işlemlerini sağlar; bu, Pulsar şemalarının kod tabanında kalma ihtiyacını ortadan kaldırır. + +### Fabrika Seviyesinde Şema Çok Biçimliliği + +Pulsar şemalarını çevirmek yerine, **her arka uç, standart Python dataclass'larıyla çalışan kendi şema işleme yöntemini sağlar**. + +### Yayıncı Akışı + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### Tüketici Akışı + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### Sahne Arkasındaki Olaylar + +**Pulsar arka ucu için:** +`create_producer()` → JSON şeması veya dinamik olarak oluşturulmuş bir kayıtla Pulsar üreticisi oluşturur. +`send(request)` → veri sınıfını JSON/Pulsar formatına serileştirir ve Pulsar'a gönderir. +`receive()` → Pulsar mesajını alır, veri sınıfına geri serileştirir. + +**MQTT arka ucu için:** +`create_producer()` → MQTT aracısına bağlanır, şema kaydı gerektirmez. +`send(request)` → veri sınıfını JSON'a dönüştürür ve MQTT konusuna yayınlar. +`receive()` → MQTT konusuna abone olur, JSON'ı veri sınıfına geri serileştirir. + +**Kafka arka ucu için:** +`create_producer()` → Kafka üreticisini oluşturur, gerekirse Avro şemasını kaydeder. +`send(request)` → veri sınıfını Avro formatına serileştirir ve Kafka'ya gönderir. +`receive()` → Kafka mesajını alır, Avro'yu veri sınıfına geri serileştirir. + +### Temel Tasarım Noktaları + +1. **Şema nesnesi oluşturma**: Veri sınıfı örneği (`TextCompletionRequest(...)`), arka uçtan bağımsız olarak aynıdır. +2. **Arka uç, kodlamayı yönetir**: Her arka uç, veri sınıfını kablo formatına nasıl serileştireceğini bilir. +3. **Oluşturma sırasında şema tanımı**: Üretici/tüketici oluştururken, şema türünü belirtirsiniz. +4. **Tür güvenliği korunur**: Doğru bir `TextCompletionRequest` nesnesi alırsınız, bir sözlük değil. +5. **Arka uç sızıntısı yok**: Uygulama kodu, arka uçla ilgili özel kütüphaneleri asla içe aktarmaz. + +### Örnek Dönüşüm + +**Mevcut (Pulsar'a özel):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**Yeni (Arka uçtan bağımsız):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### Arka Uç Entegrasyonu + +Her arka uç, veri sınıflarının serileştirme/deserileştirme işlemlerini gerçekleştirir: + +**Pulsar arka ucu:** +Veri sınıflarından dinamik olarak `pulsar.schema.Record` sınıfları oluşturun +Veya veri sınıflarını JSON'a serileştirin ve Pulsar'ın JSON şemasını kullanın +Mevcut Pulsar kurulumlarıyla uyumluluğu korur + +**MQTT/Redis arka ucu:** +Veri sınıfı örneklerinin doğrudan JSON serileştirilmesi +`dataclasses.asdict()` / `from_dict()` kullanın +Hafif, şema kayıt defterine gerek yok + +**Kafka arka ucu:** +Veri sınıfı tanımlarından Avro şemaları oluşturun +Confluent'ın şema kayıt defterini kullanın +Şema evrimi desteğiyle tür güvenli serileştirme + +### Mimari + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### Uygulama Detayları + +**1. Şema tanımları:** Basit dataclass'lar ve tür ipuçları + `str`, `int`, `bool`, `float` temel veri tipleri için + `list[T]` diziler için + `dict[str, T]` haritalar için + Karmaşık tipler için iç içe dataclass'lar + +**2. Her arka uç şunları sağlar:** + Serileştirici: `dataclass → bytes/wire format` + Seri dışa aktarıcı: `bytes/wire format → dataclass` + Şema kaydı (gerekirse, örneğin Pulsar/Kafka) + +**3. Tüketici/Üretici soyutlaması:** + Zaten mevcut (consumer.py, producer.py) + Arka uç tarafından sağlanan seri dışa aktarmayı kullanmak için güncellenmeli + Doğrudan Pulsar içe aktarmalarını kaldırmalı + +**4. Tür eşlemeleri:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### Geçiş Yolu + +1. `trustgraph/schema/` içindeki tüm şemaların **dataclass versiyonlarını oluşturun** +2. Arka uç tarafından sağlanan seri dışa aktarmayı kullanmak için **arka uç sınıflarını (Tüketici, Üretici, Yayıncı, Abonelik) güncelleyin** +3. JSON şemasını veya dinamik Kayıt oluşturmayı kullanarak **PulsarBackend'i uygulayın** +4. **Mevcut dağıtımlarla geriye dönük uyumluluğu sağlamak için Pulsar ile test edin** +5. Gerekirse **yeni arka uçlar ekleyin (MQTT, Kafka, Redis, vb.)** +6. Şema dosyalarından **Pulsar içe aktarmalarını kaldırın** + +### Avantajlar + +✅ **Şema tanımlarında herhangi bir yayın/abonelik bağımlılığı yok** +✅ **Standart Python** - anlaşılması, tür denetimi yapılması ve belgelenmesi kolay +✅ **Modern araçlar** - mypy, IDE otomatik tamamlama, lint araçlarıyla çalışır +✅ **Arka uç odaklı** - her arka uç yerel seri dışa aktarmayı kullanır +✅ **Çeviri ek yükü yok** - doğrudan seri dışa aktarma, adaptörler yok +✅ **Tür güvenliği** - uygun türlere sahip gerçek nesneler +✅ **Kolay doğrulama** - gerekirse Pydantic kullanılabilir + +### Zorluklar & Çözümler + +**Zorluk:** Pulsar'ın `Record`'ı çalışma zamanı alan doğrulamasına sahiptir +**Çözüm:** Gerekirse doğrulama için Pydantic dataclass'larını kullanın veya `__post_init__` ile Python 3.10+ dataclass özelliklerini kullanın + +**Zorluk:** Bazı Pulsar'a özgü özellikler (örneğin `Bytes` türü) +**Çözüm:** Bu türü dataclass'ta `bytes` türüne eşleyin, arka uç uygun şekilde kodlamayı işler + +**Zorluk:** Konu adlandırması (`persistent://tenant/namespace/topic`) +**Çözüm:** Şema tanımlarında konu adlarını soyutlayın, arka uç uygun formata dönüştürür + +**Zorluk:** Şema evrimi ve sürüm oluşturma +**Çözüm:** Her arka uç, yeteneklerine göre bunu işler (Pulsar şema sürümleri, Kafka şema kaydı, vb.) + +**Zorluk:** İç içe karmaşık türler +**Çözüm:** İç içe dataclass'ları kullanın, arka uçlar yinelemeli olarak seri dışa aktarır/serileştirir + +### Tasarım Kararları + +1. **Basit dataclass'lar mı yoksa Pydantic mi?** + ✅ **Karar: Basit Python dataclass'ları kullanın** + Daha basit, ek bağımlılık yok + Uygulamada doğrulama gerekli değil + Anlaşılması ve bakımı daha kolay + +2. **Şema evrimi:** + ✅ **Karar: Herhangi bir sürüm oluşturma mekanizmasına gerek yok** + Şemalar kararlı ve uzun ömürlü + Güncellemeler genellikle yeni alanlar ekler (geriye dönük uyumlu) + Arka uçlar, yeteneklerine göre şema evrimini işler + +3. **Geriye dönük uyumluluk:** + ✅ **Karar: Ana sürüm değişikliği, geriye dönük uyumluluk gerekli değil** + Bu, bir kopma değişikliği olacak ve geçiş talimatları sağlanacak + Temiz bir kopma, daha iyi bir tasarım sağlar + Mevcut dağıtımlar için bir geçiş kılavuzu sağlanacaktır + +4. **İç içe türler ve karmaşık yapılar:** + ✅ **Karar: İç içe dataclass'ları doğal olarak kullanın** + Python dataclass'ları iç içe geçmeyi mükemmel şekilde işler + Diziler için `list[T]`, haritalar için `dict[K, V]` + Arka uçlar yinelemeli olarak seri dışa aktarır/serileştirir + Örnek: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **Varsayılan değerler ve isteğe bağlı alanlar:** + ✅ **Karar: Gerekli, varsayılan ve isteğe bağlı alanların birleşimi** + Gerekli alanlar: Herhangi bir varsayılan değer yok + Varsayılan değerlere sahip alanlar: Her zaman mevcut, anlamlı varsayılan değerlere sahip + Tamamen isteğe bağlı alanlar: `T | None = None`, `None` olduğunda serileştirmeden çıkarılır + Örnek: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **Önemli serileştirme kuralları:** + + `metadata = None` olduğunda: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + `metadata = {}` (açıkça boş) olduğunda: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **Temel ayrım:** + `None` → JSON'da bulunmayan alan (serileştirilmiyor) + Boş değer (`{}`, `[]`, `""`) → alan, boş bir değerle mevcut + Bu, anlamsal olarak önemlidir: "sağlanmadı" ile "açıkça boş" + Serileştirme arka uçları, `None` alanlarını atlamalı, bunları `null` olarak kodlamamalıdır. + +## Yaklaşım Taslağı 3: Uygulama Detayları + +### Genel Kuyruk Adlandırma Formatı + +Arka uçlara özgü kuyruk adlarını, arka uçların uygun şekilde eşleyebileceği genel bir formata dönüştürün. + +**Format:** `{qos}/{tenant}/{namespace}/{queue-name}` + +Nerede: +`qos`: Hizmet kalitesi seviyesi + `q0` = en iyi çaba (ateşle ve unut, onay yok) + `q1` = en az bir kez (onay gerektirir) + `q2` = tam olarak bir kez (iki aşamalı onay) +`tenant`: Çok kiracılılık için mantıksal gruplandırma +`namespace`: Kiracı içindeki alt gruplandırma +`queue-name`: Gerçek kuyruk/konu adı + +**Örnekler:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### Arka Uç Konu Eşlemesi + +Her arka uç, genel formatı kendi yerel formatına eşler: + +**Pulsar Arka Ucu:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**MQTT Altyapısı:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### Güncellenmiş Konu Yardımcı Fonksiyonu + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### Yapılandırma ve Başlatma + +**Komut Satırı Argümanları + Ortam Değişkenleri:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**Fabrika Fonksiyonu:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**AsyncProcessor'da Kullanım:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### Arka Uç Arayüzü + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### Mevcut Sınıfların Yeniden Düzenlenmesi + +Mevcut `Consumer`, `Producer`, `Publisher`, `Subscriber` sınıfları büyük ölçüde aynı kalacaktır: + +**Mevcut sorumluluklar (saklanacak):** +Asenkron iş parçacığı modeli ve görev grupları +Yeniden bağlantı mantığı ve tekrar deneme işleme +Ölçüm toplama +Hız sınırlama +Eşzamanlılık yönetimi + +**Gerekli değişiklikler:** +Doğrudan Pulsar içe aktarmalarını kaldırın (`pulsar.schema`, `pulsar.InitialPosition`, vb.) +`BackendProducer`/`BackendConsumer`'i Pulsar istemcisi yerine kullanın +Gerçek yayın/abonelik işlemlerini arka uç örneklerine devredin +Genel kavramları arka uç çağrılarına eşleyin + +**Örnek yeniden düzenleme:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### Arka Uç Özel Davranışlar + +**Pulsar Arka Uç:** +`q0`'ı `non-persistent://`'e, `q1`/`q2`'ü `persistent://`'e eşler. +Tüm tüketici türlerini (paylaşımlı, özel, yedekli) destekler. +Başlangıç konumunu (en erken/en son) destekler. +Yerel mesaj onayı. +Şema kayıt defteri desteği. + +**MQTT Arka Uç:** +`q0`/`q1`/`q2`'yi MQTT QoS seviyeleri 0/1/2'ye eşler. +Adlandırma için konu yoluna kiracı/isim alanı ekler. +Abonelik adlarından otomatik olarak istemci kimlikleri oluşturur. +Başlangıç konumunu yoksayar (temel MQTT'de mesaj geçmişi yoktur). +Tüketici türünü yoksayar (MQTT, tüketici grupları yerine istemci kimlikleri kullanır). +Basit yayın/abone modeli. + +### Tasarım Kararları Özeti + +1. ✅ **Genel kuyruk adlandırması**: `qos/tenant/namespace/queue-name` formatı +2. ✅ **Kuyruk kimliğindeki QoS**: Kuyruk tanımı tarafından belirlenir, yapılandırma ile değil. +3. ✅ **Yeniden bağlanma**: Tüketici/Üretici sınıfları tarafından işlenir, arka uçlar tarafından değil. +4. ✅ **MQTT konuları**: Doğru adlandırma için kiracı/isim alanı içerir. +5. ✅ **Mesaj geçmişi**: MQTT, `initial_position` parametresini yoksayar (gelecek geliştirmeler). +6. ✅ **İstemci kimlikleri**: MQTT arka ucu, abonelik adından otomatik olarak oluşturur. + +### Gelecek Geliştirmeler + +**MQTT mesaj geçmişi:** +İsteğe bağlı bir kalıcılık katmanı eklenebilir (örneğin, saklanan mesajlar, harici depolama). +`initial_position='earliest'`'ı desteklemeyi mümkün kılacaktır. +Başlangıç uygulamasında gerekli değildir. diff --git a/docs/tech-specs/pubsub.zh-cn.md b/docs/tech-specs/pubsub.zh-cn.md new file mode 100644 index 00000000..000fb702 --- /dev/null +++ b/docs/tech-specs/pubsub.zh-cn.md @@ -0,0 +1,965 @@ +--- +layout: default +title: "Pub/Sub 基础设施" +parent: "Chinese (Beta)" +--- + +# Pub/Sub 基础设施 + +> **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 代码库与 pub/sub 基础设施之间的所有连接。目前,系统是硬编码为使用 Apache Pulsar。此分析识别了所有集成点,以促进未来向可配置的 pub/sub 抽象的重构。 + +## 当前状态:Pulsar 集成点 + +### 1. 直接 Pulsar 客户端使用 + +**位置:** `trustgraph-flow/trustgraph/gateway/service.py` + +API 网关直接导入和实例化 Pulsar 客户端: + +**第 20 行:** `import pulsar` +**第 54-61 行:** 直接实例化 `pulsar.Client()`,带可选 `pulsar.AuthenticationToken()` +**第 33-35 行:** 从环境变量获取默认 Pulsar 主机配置 +**第 178-192 行:** CLI 参数,用于 `--pulsar-host`、`--pulsar-api-key` 和 `--pulsar-listener` +**第 78、124 行:** 将 `pulsar_client` 传递给 `ConfigReceiver` 和 `DispatcherManager` + +这是唯一直接在抽象层之外实例化 Pulsar 客户端的位置。 + +### 2. 基础处理器框架 + +**位置:** `trustgraph-base/trustgraph/base/async_processor.py` + +所有处理器的基本类提供 Pulsar 连接: + +**第 9 行:** `import _pulsar` (用于异常处理) +**第 18 行:** `from . pubsub import PulsarClient` +**第 38 行:** 创建 `pulsar_client_object = PulsarClient(**params)` +**第 104-108 行:** 暴露 `pulsar_host` 和 `pulsar_client` 的属性 +**第 250 行:** 静态方法 `add_args()` 调用 `PulsarClient.add_args(parser)` 以获取 CLI 参数 +**第 223-225 行:** `_pulsar.Interrupted` 的异常处理 + +所有处理器都继承自 `AsyncProcessor`,使其成为主要的集成点。 + +### 3. 消费者抽象 + +**位置:** `trustgraph-base/trustgraph/base/consumer.py` + +从队列中消耗消息并调用处理函数: + +**Pulsar 导入:** +**第 12 行:** `from pulsar.schema import JsonSchema` +**第 13 行:** `import pulsar` +**第 14 行:** `import _pulsar` + +**Pulsar 特定的用法:** +**第 100、102 行:** `pulsar.InitialPosition.Earliest` / `pulsar.InitialPosition.Latest` +**第 108 行:** `JsonSchema(self.schema)` 包装器 +**第 110 行:** `pulsar.ConsumerType.Shared` +**第 104-111 行:** `self.client.subscribe()`,带有 Pulsar 特定的参数 +**第 143、150、65 行:** `consumer.unsubscribe()` 和 `consumer.close()` 方法 +**第 162 行:** `_pulsar.Timeout` 异常 +**第 182、205、232 行:** `consumer.acknowledge()` / `consumer.negative_acknowledge()` + +**Spec 文件:** `trustgraph-base/trustgraph/base/consumer_spec.py` +**第 22 行:** 引用 `processor.pulsar_client` + +### 4. 生产者抽象 + +**位置:** `trustgraph-base/trustgraph/base/producer.py` + +向队列发送消息: + +**Pulsar 导入:** +**第 2 行:** `from pulsar.schema import JsonSchema` + +**Pulsar 特定的用法:** +**第 49 行:** `JsonSchema(self.schema)` 包装器 +**第 47-51 行:** `self.client.create_producer()`,带有 Pulsar 特定的参数 (topic, schema, chunking_enabled) +**第 31、76 行:** `producer.close()` 方法 +**第 64-65 行:** `producer.send()`,带有消息和属性 + +**Spec 文件:** `trustgraph-base/trustgraph/base/producer_spec.py` +**第 18 行:** 引用 `processor.pulsar_client` + +### 5. 发布者抽象 + +**位置:** `trustgraph-base/trustgraph/base/publisher.py` + +具有队列缓冲的异步消息发布: + +**Pulsar 导入:** +**第 2 行:** `from pulsar.schema import JsonSchema` +**第 6 行:** `import pulsar` + +**Pulsar 特定的用法:** +**第 52 行:** `JsonSchema(self.schema)` 包装器 +**第 50-54 行:** `self.client.create_producer()`,带有 Pulsar 特定的参数 +**第 101、103 行:** `producer.send()`,带有消息和可选属性 +**第 106-107 行:** `producer.flush()` 和 `producer.close()` 方法 + +### 6. 订阅者抽象 + +**位置:** `trustgraph-base/trustgraph/base/subscriber.py` + +提供从队列分发给多个接收者的消息功能: + +**Pulsar 导入:** +**第 6 行:** `from pulsar.schema import JsonSchema` +**第 8 行:** `import _pulsar` + +**Pulsar 特定的用法:** +**第 55 行:** `JsonSchema(self.schema)` 包装器 +**第 57 行:** `self.client.subscribe(**subscribe_args)` +**第 101、136、160、167-172 行:** Pulsar 异常:`_pulsar.Timeout`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +**第 159、166、170 行:** 消费者方法:`negative_acknowledge()`, `unsubscribe()`, `close()` +**第 247、251 行:** 消息确认:`acknowledge()`, `negative_acknowledge()` + +**Spec 文件:** `trustgraph-base/trustgraph/base/subscriber_spec.py` +**第 19 行:** 引用 `processor.pulsar_client` + +### 7. Schema 系统 (黑暗之心) + +**位置:** `trustgraph-base/trustgraph/schema/` + +系统中的每个消息模式都使用 Pulsar 的模式框架定义。 + +**核心原语:** `schema/core/primitives.py` +**第 2 行:** `from pulsar.schema import Record, String, Boolean, Array, Integer` +所有模式都继承自 Pulsar 的 `Record` 基类 +所有字段类型都是 Pulsar 类型:`String()`, `Integer()`, `Boolean()`, `Array()`, `Map()`, `Double()` + +**示例模式:** +`schema/services/llm.py` (第 2 行):`from pulsar.schema import Record, String, Array, Double, Integer, Boolean` +`schema/services/config.py` (第 2 行):`from pulsar.schema import Record, Bytes, String, Boolean, Array, Map, Integer` + +**主题命名:** `schema/core/topic.py` +**第 2-3 行:** 主题格式:`{kind}://{tenant}/{namespace}/{topic}` +此 URI 结构是 Pulsar 特定的(例如,`persistent://tg/flow/config`) + +**影响:** +代码库中所有请求/响应消息定义都使用 Pulsar 模式 +这包括用于:config、flow、llm、prompt、query、storage、agent、collection、diagnosis、library、lookup、nlp_query、objects_query、retrieval、structured_query 的服务 +模式定义被导入并广泛地用于所有处理器和服务中 + +## 总结 + +### Pulsar 依赖项按类别划分 + +1. **客户端实例化:** + 直接:`gateway/service.py` + 抽象:`async_processor.py` → `pubsub.py` (PulsarClient) + +2. **消息传输:** + 消费者:`consumer.py`, `consumer_spec.py` + 生产者:`producer.py`, `producer_spec.py` + 发布者:`publisher.py` + 订阅者:`subscriber.py`, `subscriber_spec.py` + +3. **模式系统:** + 基本类型:`schema/core/primitives.py` + 所有服务模式:`schema/services/*.py` + 主题命名:`schema/core/topic.py` + +4. **需要 Pulsar 特定的概念:** + 基于主题的消息 + 模式系统 (Record, 字段类型) + 共享订阅 + 消息确认 (肯定/否定) + 消费者定位 (最早/最新) + 消息属性 + 初始位置和消费者类型 + 分块支持 + 持久化与非持久化主题 + +### 重构挑战 + +好的消息:抽象层 (Consumer, Producer, Publisher, Subscriber) 提供了一个干净的 Pulsar 交互的封装。 + +挑战: +1. **模式系统的普遍性:** 每个消息定义都使用 `pulsar.schema.Record` 和 Pulsar 字段类型 +2. **Pulsar 特定的枚举:** `InitialPosition`, `ConsumerType` +3. **Pulsar 异常:** `_pulsar.Timeout`, `_pulsar.Interrupted`, `_pulsar.InvalidConfiguration`, `_pulsar.AlreadyClosed` +4. **方法签名:** `acknowledge()`, `negative_acknowledge()`, `subscribe()`, `create_producer()`, 等等。 +5. **主题 URI 格式:** Pulsar 的 `kind://tenant/namespace/topic` 结构 + +### 下一步 + +为了使 pub/sub 基础设施可配置,我们需要: + +1. 为客户端/模式系统创建抽象接口 +2. 抽象 Pulsar 特定的枚举和异常 +3. 创建模式包装器或替代模式定义 +4. 为 Pulsar 和其他系统(Kafka、RabbitMQ、Redis Streams 等)实现该接口 +5. 更新 `pubsub.py` 以使其可配置并支持多个后端 +6. 提供现有部署的迁移路径 + +## 方法草案 1:带模式转换层的适配器模式 + +### 关键洞察 +**模式系统** 是最深入的集成点 - 其他一切都由此而产生。 我们需要首先解决这个问题,否则我们将重写整个代码库。 + +### 策略:通过适配器实现最小的干扰 + +**1. 保持 Pulsar 模式作为内部表示** +不要重写所有的模式定义 +模式在内部仍然是 `pulsar.schema.Record` +使用适配器在我们的代码和发布/订阅后端之间的边界进行转换 + +**2. 创建一个发布/订阅抽象层:** + +``` +┌─────────────────────────────────────┐ +│ Existing Code (unchanged) │ +│ - Uses Pulsar schemas internally │ +│ - Consumer/Producer/Publisher │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - Creates backend-specific client │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────┐ ┌────▼─────────┐ +│ PulsarAdapter│ │ KafkaAdapter │ etc... +│ (passthrough)│ │ (translates) │ +└──────────────┘ └──────────────┘ +``` + +**3. 定义抽象接口:** +`PubSubClient` - 客户端连接 +`PubSubProducer` - 发送消息 +`PubSubConsumer` - 接收消息 +`SchemaAdapter` - 将 Pulsar 模式转换为 JSON 或后端特定的格式,反之亦然 + +**4. 实现细节:** + +对于 **Pulsar 适配器**: 几乎是直通模式,最小化转换 + +对于 **其他后端** (Kafka, RabbitMQ 等): +将 Pulsar Record 对象序列化为 JSON/字节 +映射概念,例如: + `InitialPosition.Earliest/Latest` → Kafka 的 auto.offset.reset + `acknowledge()` → Kafka 的 commit + `negative_acknowledge()` → 重试或 DLQ 模式 + Topic URI → 后端特定的主题名称 + +### 分析 + +**优点:** +✅ 对现有服务的代码更改最小 +✅ 模式保持不变 (无需大规模重写) +✅ 逐步迁移路径 +✅ Pulsar 用户不会看到任何差异 +✅ 通过适配器添加新的后端 + +**缺点:** +⚠️ 仍然依赖 Pulsar (用于模式定义) +⚠️ 在转换概念时存在一些阻抗不匹配 + +### 替代方案 + +创建一个 **TrustGraph 模式系统**,该系统与 pub/sub 无关 (使用 dataclasses 或 Pydantic),然后从该系统生成 Pulsar/Kafka/等的模式。 这需要重写每个模式文件,并且可能导致不兼容的更改。 + +### 草案 1 的建议 + +从 **适配器方法** 开始,因为: +1. 它实用 - 与现有代码兼容 +2. 以最小的风险验证概念 +3. 如果需要,可以演变为原生模式系统 +4. 基于配置:一个环境变量切换后端 + +## 草案 2 方法:具有 Dataclasses 的后端无关模式系统 + +### 核心概念 + +使用 Python **dataclasses** 作为中立的模式定义格式。 每个 pub/sub 后端都提供自己的序列化/反序列化,以处理 dataclasses,从而无需在代码库中保留 Pulsar 模式。 + +### 工厂级别的模式多态 + +而是翻译 Pulsar 模式,**每个后端都提供自己的模式处理**,该处理方式适用于标准的 Python dataclasses。 + +### 发布者流程 + +```python +# 1. Get the configured backend from factory +pubsub = get_pubsub() # Returns PulsarBackend, MQTTBackend, etc. + +# 2. Get schema class from the backend +# (Can be imported directly - backend-agnostic) +from trustgraph.schema.services.llm import TextCompletionRequest + +# 3. Create a producer/publisher for a specific topic +producer = pubsub.create_producer( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend what schema to use +) + +# 4. Create message instances (same API regardless of backend) +request = TextCompletionRequest( + system="You are helpful", + prompt="Hello world", + streaming=False +) + +# 5. Send the message +producer.send(request) # Backend serializes appropriately +``` + +### 消费者流程 + +```python +# 1. Get the configured backend +pubsub = get_pubsub() + +# 2. Create a consumer +consumer = pubsub.subscribe( + topic="text-completion-requests", + schema=TextCompletionRequest # Tells backend how to deserialize +) + +# 3. Receive and deserialize +msg = consumer.receive() +request = msg.value() # Returns TextCompletionRequest dataclass instance + +# 4. Use the data (type-safe access) +print(request.system) # "You are helpful" +print(request.prompt) # "Hello world" +print(request.streaming) # False +``` + +### 幕后发生了什么 + +**对于 Pulsar 后端:** +`create_producer()` → 创建具有 JSON 模式或动态生成的记录的 Pulsar 生产者。 +`send(request)` → 将数据类序列化为 JSON/Pulsar 格式,并发送到 Pulsar。 +`receive()` → 获取 Pulsar 消息,将其反序列化回数据类。 + +**对于 MQTT 后端:** +`create_producer()` → 连接到 MQTT 代理,无需注册模式。 +`send(request)` → 将数据类转换为 JSON,并发布到 MQTT 主题。 +`receive()` → 订阅 MQTT 主题,并将 JSON 反序列化为数据类。 + +**对于 Kafka 后端:** +`create_producer()` → 创建 Kafka 生产者,如果需要,注册 Avro 模式。 +`send(request)` → 将数据类序列化为 Avro 格式,并发送到 Kafka。 +`receive()` → 获取 Kafka 消息,并将 Avro 反序列化回数据类。 + +### 关键设计点 + +1. **模式对象创建:** 数据类实例 (`TextCompletionRequest(...)`) 无论后端如何都是相同的。 +2. **后端处理编码:** 每个后端都知道如何将数据类序列化为线格式。 +3. **在创建时定义模式:** 在创建生产者/消费者时,您指定模式类型。 +4. **保留类型安全:** 您会得到一个正确的 `TextCompletionRequest` 对象,而不是一个字典。 +5. **没有后端泄漏:** 应用程序代码永远不会导入特定于后端的库。 + +### 示例转换 + +**当前(特定于 Pulsar):** +```python +# schema/services/llm.py +from pulsar.schema import Record, String, Boolean, Integer + +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() +``` + +**新功能(与后端无关):** +```python +# schema/services/llm.py +from dataclasses import dataclass + +@dataclass +class TextCompletionRequest: + system: str + prompt: str + streaming: bool = False +``` + +### 后端集成 + +每个后端负责数据类的序列化/反序列化: + +**Pulsar 后端:** +从数据类动态生成 `pulsar.schema.Record` 类 +或者将数据类序列化为 JSON,并使用 Pulsar 的 JSON 模式 +保持与现有 Pulsar 部署的兼容性 + +**MQTT/Redis 后端:** +直接对数据类实例进行 JSON 序列化 +使用 `dataclasses.asdict()` / `from_dict()` +轻量级,无需模式注册表 + +**Kafka 后端:** +从数据类定义生成 Avro 模式 +使用 Confluent 的模式注册表 +具有模式演进支持的类型安全序列化 + +### 架构 + +``` +┌─────────────────────────────────────┐ +│ Application Code │ +│ - Uses dataclass schemas │ +│ - Backend-agnostic │ +└──────────────┬──────────────────────┘ + │ +┌──────────────┴──────────────────────┐ +│ PubSubFactory (configurable) │ +│ - get_pubsub() returns backend │ +└──────────────┬──────────────────────┘ + │ + ┌──────┴──────┐ + │ │ +┌───────▼─────────┐ ┌────▼──────────────┐ +│ PulsarBackend │ │ MQTTBackend │ +│ - JSON schema │ │ - JSON serialize │ +│ - or dynamic │ │ - Simple queues │ +│ Record gen │ │ │ +└─────────────────┘ └───────────────────┘ +``` + +### 实现细节 + +**1. 模式定义:** 使用带有类型提示的简单数据类 + `str`, `int`, `bool`, `float` 用于基本类型 + `list[T]` 用于数组 + `dict[str, T]` 用于映射 + 用于复杂类型的嵌套数据类 + +**2. 每个后端提供:** + 序列化器:`dataclass → bytes/wire format` + 反序列化器:`bytes/wire format → dataclass` + 模式注册(如果需要,例如 Pulsar/Kafka) + +**3. 消费者/生产者抽象:** + 已经存在 (consumer.py, producer.py) + 更新以使用后端的序列化 + 移除直接的 Pulsar 导入 + +**4. 类型映射:** + Pulsar `String()` → Python `str` + Pulsar `Integer()` → Python `int` + Pulsar `Boolean()` → Python `bool` + Pulsar `Array(T)` → Python `list[T]` + Pulsar `Map(K, V)` → Python `dict[K, V]` + Pulsar `Double()` → Python `float` + Pulsar `Bytes()` → Python `bytes` + +### 迁移路径 + +1. **创建所有模式的数据类版本**,位于 `trustgraph/schema/` +2. **更新后端类**(Consumer, Producer, Publisher, Subscriber),以使用后端提供的序列化 +3. **实现 PulsarBackend**,使用 JSON 模式或动态 Record 生成 +4. **使用 Pulsar 进行测试**,以确保与现有部署的向后兼容性 +5. **添加新的后端**(MQTT, Kafka, Redis 等),如果需要 +6. **从模式文件中移除 Pulsar 导入** + +### 优点 + +✅ **模式定义中没有 pub/sub 依赖** +✅ **标准 Python** - 易于理解、类型检查和记录 +✅ **现代工具** - 与 mypy、IDE 自动完成、linter 兼容 +✅ **后端优化** - 每个后端使用本机序列化 +✅ **没有翻译开销** - 直接序列化,没有适配器 +✅ **类型安全** - 具有正确类型的真实对象 +✅ **易于验证** - 如果需要,可以使用 Pydantic + +### 挑战与解决方案 + +**挑战:** Pulsar 的 `Record` 具有运行时字段验证 +**解决方案:** 如果需要,可以使用 Pydantic 数据类进行验证,或者使用 Python 3.10+ 数据类功能,并结合 `__post_init__` + +**挑战:** 一些 Pulsar 特定的功能(例如 `Bytes` 类型) +**解决方案:** 将其映射到数据类中的 `bytes` 类型,后端负责适当的编码 + +**挑战:** 主题命名(`persistent://tenant/namespace/topic`) +**解决方案:** 在模式定义中抽象主题名称,后端将其转换为正确的格式 + +**挑战:** 模式演化和版本控制 +**解决方案:** 每个后端根据其功能处理此问题(Pulsar 模式版本、Kafka 模式注册等) + +**挑战:** 嵌套的复杂类型 +**解决方案:** 使用嵌套的数据类,后端递归地序列化/反序列化 + +### 设计决策 + +1. **使用纯数据类还是 Pydantic?** + ✅ **决策:使用纯 Python 数据类** + 更简单,没有额外的依赖 + 实际上不需要验证 + 更容易理解和维护 + +2. **模式演化:** + ✅ **决策:不需要版本机制** + 模式是稳定且持久的 + 更新通常会添加新字段(向后兼容) + 后端根据其功能处理模式演化 + +3. **向后兼容性:** + ✅ **决策:进行主要版本更改,不需要向后兼容** + 这将是一个破坏性更改,并提供迁移说明 + 清理的断开允许更好的设计 + 将为现有部署提供迁移指南 + +4. **嵌套类型和复杂结构:** + ✅ **决策:自然地使用嵌套的数据类** + Python 数据类完美地处理嵌套 + `list[T]` 用于数组,`dict[K, V]` 用于映射 + 后端递归地序列化/反序列化 + 示例: + ```python + @dataclass + class Value: + value: str + is_uri: bool + + @dataclass + class Triple: + s: Value # Nested dataclass + p: Value + o: Value + + @dataclass + class GraphQuery: + triples: list[Triple] # Array of nested dataclasses + metadata: dict[str, str] + ``` + +5. **默认值和可选字段:** + ✅ **决策:强制、默认和可选字段的组合** + 强制字段:没有默认值 + 具有默认值的字段:始终存在,具有合理的默认值 + 真正可选的字段:`T | None = None`,当`None`时,从序列化中省略 + 示例: + ```python + @dataclass + class TextCompletionRequest: + system: str # Required, no default + prompt: str # Required, no default + streaming: bool = False # Optional with default value + metadata: dict | None = None # Truly optional, can be absent + ``` + + **重要的序列化语义:** + + 当 `metadata = None`: + ```json + { + "system": "...", + "prompt": "...", + "streaming": false + // metadata field NOT PRESENT + } + ``` + + 当 `metadata = {}` (显式为空): + ```json + { + "system": "...", + "prompt": "...", + "streaming": false, + "metadata": {} // Field PRESENT but empty + } + ``` + + **关键区别:** + `None` → JSON 中不存在的字段(未序列化) + 空值(`{}`, `[]`, `""`)→ 字段存在,但值为空 + 这在语义上很重要:“未提供”与“显式为空” + 序列化后端必须跳过 `None` 字段,而不是将其编码为 `null` + +## 方案草案 3:实现细节 + +### 通用队列命名格式 + +将后端特定的队列名称替换为一种通用格式,以便后端可以进行适当的映射。 + +**格式:** `{qos}/{tenant}/{namespace}/{queue-name}` + +其中: +`qos`:服务质量级别 + `q0` = 尽力而为(发送并忘记,无需确认) + `q1` = 至少一次(需要确认) + `q2` = 恰好一次(两阶段确认) +`tenant`:多租户逻辑分组 +`namespace`:租户内的子分组 +`queue-name`:实际的队列/主题名称 + +**示例:** +``` +q1/tg/flow/text-completion-requests +q2/tg/config/config-push +q0/tg/metrics/stats +``` + +### 后端主题映射 + +每个后端将通用格式映射到其原生格式: + +**Pulsar 后端:** +```python +def map_topic(self, generic_topic: str) -> str: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS to persistence + persistence = 'persistent' if qos in ['q1', 'q2'] else 'non-persistent' + + # Return Pulsar URI: persistent://tg/flow/text-completion-requests + return f"{persistence}://{tenant}/{namespace}/{queue}" +``` + +**MQTT 后端:** +```python +def map_topic(self, generic_topic: str) -> tuple[str, int]: + # Parse: q1/tg/flow/text-completion-requests + qos, tenant, namespace, queue = generic_topic.split('/', 3) + + # Map QoS level + qos_level = {'q0': 0, 'q1': 1, 'q2': 2}[qos] + + # Build MQTT topic including tenant/namespace for proper namespacing + mqtt_topic = f"{tenant}/{namespace}/{queue}" + + return mqtt_topic, qos_level +``` + +### 更新后的主题辅助函数 + +```python +# schema/core/topic.py +def topic(queue_name, qos='q1', tenant='tg', namespace='flow'): + """ + Create a generic topic identifier that can be mapped by backends. + + Args: + queue_name: The queue/topic name + qos: Quality of service + - 'q0' = best-effort (no ack) + - 'q1' = at-least-once (ack required) + - 'q2' = exactly-once (two-phase ack) + tenant: Tenant identifier for multi-tenancy + namespace: Namespace within tenant + + Returns: + Generic topic string: qos/tenant/namespace/queue_name + + Examples: + topic('my-queue') # q1/tg/flow/my-queue + topic('config', qos='q2', namespace='config') # q2/tg/config/config + """ + return f"{qos}/{tenant}/{namespace}/{queue_name}" +``` + +### 配置和初始化 + +**命令行参数 + 环境变量:** + +```python +# In base/async_processor.py - add_args() method +@staticmethod +def add_args(parser): + # Pub/sub backend selection + parser.add_argument( + '--pubsub-backend', + default=os.getenv('PUBSUB_BACKEND', 'pulsar'), + choices=['pulsar', 'mqtt'], + help='Pub/sub backend (default: pulsar, env: PUBSUB_BACKEND)' + ) + + # Pulsar-specific configuration + parser.add_argument( + '--pulsar-host', + default=os.getenv('PULSAR_HOST', 'pulsar://localhost:6650'), + help='Pulsar host (default: pulsar://localhost:6650, env: PULSAR_HOST)' + ) + + parser.add_argument( + '--pulsar-api-key', + default=os.getenv('PULSAR_API_KEY', None), + help='Pulsar API key (env: PULSAR_API_KEY)' + ) + + parser.add_argument( + '--pulsar-listener', + default=os.getenv('PULSAR_LISTENER', None), + help='Pulsar listener name (env: PULSAR_LISTENER)' + ) + + # MQTT-specific configuration + parser.add_argument( + '--mqtt-host', + default=os.getenv('MQTT_HOST', 'localhost'), + help='MQTT broker host (default: localhost, env: MQTT_HOST)' + ) + + parser.add_argument( + '--mqtt-port', + type=int, + default=int(os.getenv('MQTT_PORT', '1883')), + help='MQTT broker port (default: 1883, env: MQTT_PORT)' + ) + + parser.add_argument( + '--mqtt-username', + default=os.getenv('MQTT_USERNAME', None), + help='MQTT username (env: MQTT_USERNAME)' + ) + + parser.add_argument( + '--mqtt-password', + default=os.getenv('MQTT_PASSWORD', None), + help='MQTT password (env: MQTT_PASSWORD)' + ) +``` + +**工厂函数:** + +```python +# In base/pubsub.py or base/pubsub_factory.py +def get_pubsub(**config) -> PubSubBackend: + """ + Create and return a pub/sub backend based on configuration. + + Args: + config: Configuration dict from command-line args + Must include 'pubsub_backend' key + + Returns: + Backend instance (PulsarBackend, MQTTBackend, etc.) + """ + backend_type = config.get('pubsub_backend', 'pulsar') + + if backend_type == 'pulsar': + return PulsarBackend( + host=config.get('pulsar_host'), + api_key=config.get('pulsar_api_key'), + listener=config.get('pulsar_listener'), + ) + elif backend_type == 'mqtt': + return MQTTBackend( + host=config.get('mqtt_host'), + port=config.get('mqtt_port'), + username=config.get('mqtt_username'), + password=config.get('mqtt_password'), + ) + else: + raise ValueError(f"Unknown pub/sub backend: {backend_type}") +``` + +**在 AsyncProcessor 中的用法:** + +```python +# In async_processor.py +class AsyncProcessor: + def __init__(self, **params): + self.id = params.get("id") + + # Create backend from config (replaces PulsarClient) + self.pubsub = get_pubsub(**params) + + # Rest of initialization... +``` + +### 后端接口 + +```python +class PubSubBackend(Protocol): + """Protocol defining the interface all pub/sub backends must implement.""" + + def create_producer(self, topic: str, schema: type, **options) -> BackendProducer: + """ + Create a producer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + schema: Dataclass type for messages + options: Backend-specific options (e.g., chunking_enabled) + + Returns: + Backend-specific producer instance + """ + ... + + def create_consumer( + self, + topic: str, + subscription: str, + schema: type, + initial_position: str = 'latest', + consumer_type: str = 'shared', + **options + ) -> BackendConsumer: + """ + Create a consumer for a topic. + + Args: + topic: Generic topic format (qos/tenant/namespace/queue) + subscription: Subscription/consumer group name + schema: Dataclass type for messages + initial_position: 'earliest' or 'latest' (MQTT may ignore) + consumer_type: 'shared', 'exclusive', 'failover' (MQTT may ignore) + options: Backend-specific options + + Returns: + Backend-specific consumer instance + """ + ... + + def close(self) -> None: + """Close the backend connection.""" + ... +``` + +```python +class BackendProducer(Protocol): + """Protocol for backend-specific producer.""" + + def send(self, message: Any, properties: dict = {}) -> None: + """Send a message (dataclass instance) with optional properties.""" + ... + + def flush(self) -> None: + """Flush any buffered messages.""" + ... + + def close(self) -> None: + """Close the producer.""" + ... +``` + +```python +class BackendConsumer(Protocol): + """Protocol for backend-specific consumer.""" + + def receive(self, timeout_millis: int = 2000) -> Message: + """ + Receive a message from the topic. + + Raises: + TimeoutError: If no message received within timeout + """ + ... + + def acknowledge(self, message: Message) -> None: + """Acknowledge successful processing of a message.""" + ... + + def negative_acknowledge(self, message: Message) -> None: + """Negative acknowledge - triggers redelivery.""" + ... + + def unsubscribe(self) -> None: + """Unsubscribe from the topic.""" + ... + + def close(self) -> None: + """Close the consumer.""" + ... +``` + +```python +class Message(Protocol): + """Protocol for a received message.""" + + def value(self) -> Any: + """Get the deserialized message (dataclass instance).""" + ... + + def properties(self) -> dict: + """Get message properties/metadata.""" + ... +``` + +### 现有类的重构 + +现有的 `Consumer`、`Producer`、`Publisher`、`Subscriber` 类在很大程度上保持不变: + +**当前职责(保留):** +异步线程模型和任务组 +重连逻辑和重试处理 +指标收集 +速率限制 +并发管理 + +**需要更改的内容:** +移除直接的 Pulsar 导入(`pulsar.schema`、`pulsar.InitialPosition` 等) +接受 `BackendProducer`/`BackendConsumer` 而不是 Pulsar 客户端 +将实际的发布/订阅操作委托给后端实例 +将通用概念映射到后端调用 + +**重构示例:** + +```python +# OLD - consumer.py +class Consumer: + def __init__(self, client, topic, subscriber, schema, ...): + self.client = client # Direct Pulsar client + # ... + + async def consumer_run(self): + # Uses pulsar.InitialPosition, pulsar.ConsumerType + self.consumer = self.client.subscribe( + topic=self.topic, + schema=JsonSchema(self.schema), + initial_position=pulsar.InitialPosition.Earliest, + consumer_type=pulsar.ConsumerType.Shared, + ) + +# NEW - consumer.py +class Consumer: + def __init__(self, backend_consumer, schema, ...): + self.backend_consumer = backend_consumer # Backend-specific consumer + self.schema = schema + # ... + + async def consumer_run(self): + # Backend consumer already created with right settings + # Just use it directly + while self.running: + msg = await asyncio.to_thread( + self.backend_consumer.receive, + timeout_millis=2000 + ) + await self.handle_message(msg) +``` + +### 后端特定行为 + +**Pulsar 后端:** +将 `q0` 映射到 `non-persistent://`,将 `q1`/`q2` 映射到 `persistent://` +支持所有类型的消费者(共享、独占、故障转移) +支持初始位置(最早/最新) +原生消息确认 +模式注册支持 + +**MQTT 后端:** +将 `q0`/`q1`/`q2` 映射到 MQTT QoS 等级 0/1/2 +在主题路径中包含租户/命名空间,以进行命名空间划分 +根据订阅名称自动生成客户端 ID +忽略初始位置(基本的 MQTT 中没有消息历史) +忽略消费者类型(MQTT 使用客户端 ID,而不是消费者组) +简单的发布/订阅模型 + +### 设计决策摘要 + +1. ✅ **通用队列命名:** `qos/tenant/namespace/queue-name` 格式 +2. ✅ **队列 ID 中的 QoS:** 由队列定义确定,而不是配置 +3. ✅ **重连:** 由 Consumer/Producer 类处理,而不是后端 +4. ✅ **MQTT 主题:** 包含租户/命名空间以进行正确的命名空间划分 +5. ✅ **消息历史:** MQTT 忽略 `initial_position` 参数(未来增强) +6. ✅ **客户端 ID:** MQTT 后端根据订阅名称自动生成 + +### 未来增强 + +**MQTT 消息历史:** +可以添加可选的持久层(例如,保留的消息、外部存储) +将允许支持 `initial_position='earliest'` +不适用于初始实现 diff --git a/docs/tech-specs/python-api-refactor.ar.md b/docs/tech-specs/python-api-refactor.ar.md new file mode 100644 index 00000000..9b504d96 --- /dev/null +++ b/docs/tech-specs/python-api-refactor.ar.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "مواصفات فنية لإعادة هيكلة واجهة برمجة التطبيقات (API) الخاصة بـ Python" +parent: "Arabic (Beta)" +--- + +# مواصفات فنية لإعادة هيكلة واجهة برمجة التطبيقات (API) الخاصة بـ Python + +> **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. + +## نظرة عامة + +تصف هذه المواصفات إعادة هيكلة شاملة لمكتبة عميل واجهة برمجة التطبيقات (API) الخاصة بـ Python لـ TrustGraph لتحقيق التوافق مع واجهة برمجة التطبيقات (API) والبوابة وإضافة دعم لأنماط الاتصال في الوقت الفعلي الحديثة. + +تعالج عملية إعادة الهيكلة أربعة استخدامات رئيسية: + +1. **تفاعلات LLM المتدفقة**: تمكين التدفق في الوقت الفعلي لنتائج LLM (الوكيل، والبحث الدلالي في الرسم البياني، والبحث الدلالي في المستند، وإكمال النص، والموجهات) مع زمن انتقال أقل بنسبة 60 مرة (500 مللي ثانية مقابل 30 ثانية للرمز المميز الأول). +2. **عمليات البيانات المجمعة**: دعم الاستيراد/التصدير المجمع الفعال للثلاثيات، وتضمينات الرسم البياني، وتضمينات المستند لإدارة الرسوم البيانية المعرفية واسعة النطاق. +3. **التوافق مع واجهة برمجة التطبيقات (API)**: التأكد من أن كل نقطة نهاية في واجهة برمجة التطبيقات (API) والبوابة لديها طريقة واجهة برمجة تطبيقات (API) Python مقابلة، بما في ذلك استعلام تضمينات الرسم البياني. +4. **اتصالات مستمرة**: تمكين الاتصال المستند إلى WebSocket للطلبات متعددة المهام وتقليل النفقات العامة للاتصال. + +## الأهداف + +**التوافق مع واجهة برمجة التطبيقات (API)**: كل خدمة في واجهة برمجة التطبيقات (API) والبوابة لديها طريقة واجهة برمجة تطبيقات (API) Python مقابلة. +**دعم التدفق**: تدعم جميع الخدمات القادرة على التدفق (الوكيل، والبحث الدلالي، وإكمال النص، والموجه) التدفق في واجهة برمجة تطبيقات (API) Python. +**طبقة نقل WebSocket**: إضافة طبقة نقل WebSocket اختيارية للاتصالات المستمرة والتجميع. +**العمليات المجمعة**: إضافة استيراد/تصدير مجمع فعال للثلاثيات، وتضمينات الرسم البياني، وتضمينات المستند. +**دعم كامل غير متزامن**: تطبيق كامل لـ async/await لجميع الواجهات (REST، WebSocket، العمليات المجمعة، المقاييس). +**التوافق مع الإصدارات السابقة**: يستمر الكود الحالي في العمل دون تعديل. +**أمان النوع**: الحفاظ على واجهات آمنة من النوع باستخدام dataclasses وتلميحات النوع. +**التحسين التدريجي**: التدفق وغير المتزامن هما خياران ويمكن تفعيلهما من خلال اختيار الواجهة الصريح. +**الأداء**: تحقيق تحسين بنسبة 60٪ في زمن الانتقال لعمليات التدفق. +**Python حديثة**: دعم كل من نماذج المزامنة وغير المتزامنة لأقصى قدر من المرونة. + +## الخلفية + +### الحالة الحالية + +واجهة برمجة التطبيقات (API) الخاصة بـ Python (`trustgraph-base/trustgraph/api/`) هي مكتبة عميل REST فقط مع الوحدات التالية: + +`flow.py`: إدارة التدفق والخدمات ذات النطاق التدريجي (50 طريقة). +`library.py`: عمليات مكتبة المستندات (9 طرق). +`knowledge.py`: إدارة النواة الخاصة بالرسم البياني (4 طرق). +`collection.py`: بيانات وصف المجموعة (3 طرق). +`config.py`: إدارة التكوين (6 طرق). +`types.py`: تعريفات أنواع البيانات (5 dataclasses). + +**إجمالي العمليات**: 50/59 (تغطية بنسبة 85٪). + +### القيود الحالية + +**العمليات المفقودة**: +استعلام تضمينات الرسم البياني (البحث الدلالي عن كيانات الرسم البياني). +استيراد/تصدير مجمع للثلاثيات، وتضمينات الرسم البياني، وتضمينات المستند، وسياقات الكيانات، والكائنات. +نقطة نهاية المقاييس. + +**القدرات المفقودة**: +دعم البث لخدمات نماذج اللغة الكبيرة (LLM). +بروتوكول نقل WebSocket. +طلبات متزامنة متعددة. +اتصالات مستمرة. + +**مشكلات الأداء**: +زمن انتقال مرتفع لتفاعلات نماذج اللغة الكبيرة (حوالي 30 ثانية للرمز الأول). +نقل بيانات مجمعة غير فعال (طلب REST لكل عنصر). +تكلفة الاتصال لعمليات متسلسلة متعددة. + +**مشكلات تجربة المستخدم**: +عدم وجود ملاحظات في الوقت الفعلي أثناء توليد نماذج اللغة الكبيرة. +عدم القدرة على إلغاء العمليات الطويلة الأمد لنماذج اللغة الكبيرة. +قابلية توسع ضعيفة للعمليات المجمعة. + +### التأثير + +أدى التحسين الذي تم تقديمه في نوفمبر 2024 للبث في واجهة برمجة التطبيقات (API) للـ Gateway إلى تحسين زمن الانتقال بمقدار 60 مرة (500 مللي ثانية مقابل 30 ثانية للرمز الأول) لتفاعلات نماذج اللغة الكبيرة، ولكن مستخدمي واجهة برمجة التطبيقات Python لا يمكنهم الاستفادة من هذه الإمكانية. وهذا يخلق فجوة كبيرة في تجربة المستخدم بين مستخدمي Python وغير مستخدمي Python. + +## التصميم التقني + +### البنية + +تستخدم واجهة برمجة التطبيقات Python المعاد تصميمها **نهج واجهة معيارية** مع كائنات منفصلة لأنماط الاتصال المختلفة. تتوفر جميع الواجهات في كل من الإصدارات **المزامنة وغير المتزامنة**: + +1. **واجهة REST** (موجودة، مُحسّنة) + **المزامنة**: `api.flow()`، `api.library()`، `api.knowledge()`، `api.collection()`، `api.config()` + **غير متزامنة**: `api.async_flow()` + طلب/استجابة متزامنة/غير متزامنة. + نموذج اتصال بسيط. + الافتراضي للتوافق مع الإصدارات السابقة. + +2. **واجهة WebSocket** (جديدة) + **المزامنة**: `api.socket()` + **غير متزامنة**: `api.async_socket()` + اتصال مستمر. + طلبات متعددة. + دعم البث. + نفس توقيعات الأساليب مثل REST حيث تتداخل الوظائف. + +3. **واجهة العمليات المجمعة** (جديدة) + **المزامنة**: `api.bulk()` + **غير متزامنة**: `api.async_bulk()` + تعتمد على WebSocket للكفاءة. + استيراد/تصدير يعتمد على المكرر/AsyncIterator. + تتعامل مع مجموعات البيانات الكبيرة. + +4. **واجهة المقاييس** (جديدة) + **المزامنة**: `api.metrics()` + **غير متزامنة**: `api.async_metrics()` + الوصول إلى مقاييس Prometheus. + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**المبادئ الأساسية للتصميم:** +**نفس عنوان URL لجميع الواجهات:** `Api(url="http://localhost:8088/")` يعمل مع جميع الواجهات. +**التماثل بين المتزامن وغير المتزامن:** كل واجهة لديها إصدارات متزامنة وغير متزامنة مع توقيعات طرق متطابقة. +**توقيعات متطابقة:** حيث تتداخل الوظائف، تكون توقيعات الطرق متطابقة بين REST و WebSocket، والمتزامن وغير المتزامن. +**التحسين التدريجي:** اختر الواجهة بناءً على الاحتياجات (REST للعمليات البسيطة، WebSocket للبث، Bulk لمجموعات البيانات الكبيرة، وغير المتزامن للإطارات الحديثة). +**نية صريحة:** `api.socket()` يشير إلى WebSocket، و `api.async_socket()` يشير إلى WebSocket غير المتزامن. +**متوافق مع الإصدارات السابقة:** الكود الحالي لا يتغير. + +### المكونات + +#### 1. فئة واجهة برمجة التطبيقات الأساسية (معدلة) + +الوحدة: `trustgraph-base/trustgraph/api/api.py` + +**فئة واجهة برمجة التطبيقات المحسنة:** + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. عميل WebSocket المتزامن + +الوحدة: `trustgraph-base/trustgraph/api/socket_client.py` (جديد) + +**فئة SocketClient:** + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**الميزات الرئيسية:** +اتصال كسول (يتصل فقط عند إرسال الطلب الأول) +تعدد الطلبات (حتى 15 طلبًا متزامنًا) +إعادة الاتصال التلقائي عند الانفصال +تحليل الاستجابة المتدفقة +تشغيل آمن للخيوط +غلاف متزامن حول مكتبة WebSocket غير المتزامنة + +#### 3. عميل WebSocket غير المتزامن + +الوحدة: `trustgraph-base/trustgraph/api/async_socket_client.py` (جديد) + +**فئة AsyncSocketClient:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**الميزات الرئيسية:** +دعم أصلي لـ async/await. +فعال للتطبيقات غير المتزامنة (FastAPI, aiohttp). +لا يوجد حظر للخيوط. +نفس الواجهة مثل الإصدار المتزامن. +AsyncIterator للتدفق. + +#### 4. عميل العمليات المجمعة المتزامنة + +الوحدة: `trustgraph-base/trustgraph/api/bulk_client.py` (جديد) + +**فئة BulkClient:** + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**الميزات الرئيسية:** +يعتمد على التكرار لاستخدام ذاكرة ثابتة. +اتصالات WebSocket مخصصة لكل عملية. +تتبع التقدم (وظيفة رد اتصال اختيارية). +معالجة الأخطاء مع إمكانية الإبلاغ عن النجاح الجزئي. + +#### 5. عميل العمليات المجمعة غير المتزامنة + +الوحدة: `trustgraph-base/trustgraph/api/async_bulk_client.py` (جديد) + +**فئة AsyncBulkClient:** + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**الميزات الرئيسية:** +يعتمد على AsyncIterator للاستهلاك الثابت للذاكرة. +فعال للتطبيقات غير المتزامنة. +دعم أصلي لـ async/await. +نفس الواجهة مثل الإصدار المتزامن. + +#### 6. واجهة برمجة تطبيقات REST (متزامنة - دون تغيير) + +الوحدة: `trustgraph-base/trustgraph/api/flow.py` + +تظل واجهة برمجة تطبيقات REST **دون أي تغيير** لضمان التوافق مع الإصدارات السابقة. جميع الطرق الحالية تظل تعمل: + +`Flow.list()`، `Flow.start()`، `Flow.stop()`، إلخ. +`FlowInstance.agent()`، `FlowInstance.text_completion()`، `FlowInstance.graph_rag()`، إلخ. +تم الحفاظ على جميع التوقيعات وأنواع الإرجاع الحالية. + +**جديد:** إضافة `graph_embeddings_query()` إلى REST FlowInstance لتحقيق التوافق في الميزات: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. واجهة برمجة تطبيقات REST غير المتزامنة + +الوحدة: `trustgraph-base/trustgraph/api/async_flow.py` (جديد) + +**الفئات AsyncFlow و AsyncFlowInstance:** + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**الميزات الرئيسية:** +دعم غير متزامن لبروتوكول HTTP باستخدام `aiohttp` أو `httpx`. +نفس توقيعات الأساليب لواجهة برمجة تطبيقات REST المتزامنة. +لا يوجد بث (استخدم `async_socket()` للبث). +فعال للتطبيقات غير المتزامنة. + +#### 8. واجهة برمجة تطبيقات المقاييس + +الوحدة: `trustgraph-base/trustgraph/api/metrics.py` (جديد). + +**المقاييس المتزامنة:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**المقاييس غير المتزامنة:** + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. الأنواع المحسنة + +الوحدة: `trustgraph-base/trustgraph/api/types.py` (معدلة) + +**أنواع جديدة:** + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. واجهة برمجة التطبيقات (API) للمقاييس + +الوحدة: `trustgraph-base/trustgraph/api/metrics.py` (جديد) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### نهج التنفيذ + +#### المرحلة الأولى: تحسين واجهة برمجة التطبيقات الأساسية (الأسبوع الأول) + +1. إضافة طرق `socket()` و `bulk()` و `metrics()` إلى الفئة `Api` +2. تنفيذ التهيئة الكسولة لعملاء WebSocket والكمية الكبيرة +3. إضافة دعم لإدارة السياق (`__enter__`، `__exit__`) +4. إضافة طريقة `close()` للتنظيف +5. إضافة اختبارات وحدة لتحسينات فئة واجهة برمجة التطبيقات +6. التحقق من التوافق مع الإصدارات السابقة + +**التوافق مع الإصدارات السابقة**: لا توجد تغييرات تؤثر على الإصدارات السابقة. طرق جديدة فقط. + +#### المرحلة الثانية: عميل WebSocket (الأسبوعان الثاني والثالث) + +1. تنفيذ الفئة `SocketClient` مع إدارة الاتصال +2. تنفيذ `SocketFlowInstance` بنفس توقيعات الطرق مثل `FlowInstance` +3. إضافة دعم لتقسيم الطلبات (حتى 15 طلبًا متزامنًا) +4. إضافة تحليل استجابة التدفق لأنواع أجزاء مختلفة +5. إضافة منطق إعادة الاتصال التلقائي +6. إضافة اختبارات الوحدة والتكامل +7. توثيق أنماط استخدام WebSocket + +**التوافق مع الإصدارات السابقة**: واجهة جديدة فقط. لا يوجد تأثير على التعليمات البرمجية الحالية. + +#### المرحلة الثالثة: دعم التدفق (الأسبوعان الثالث والرابع) + +1. إضافة فئات أنواع أجزاء التدفق (`AgentThought`، `AgentObservation`، `AgentAnswer`، `RAGChunk`) +2. تنفيذ تحليل استجابة التدفق في `SocketClient` +3. إضافة معلمة التدفق إلى جميع طرق LLM في `SocketFlowInstance` +4. التعامل مع حالات الخطأ أثناء التدفق +5. إضافة اختبارات الوحدة والتكامل للتدفق +6. إضافة أمثلة التدفق إلى الوثائق + +**التوافق مع الإصدارات السابقة**: واجهة جديدة فقط. واجهة برمجة تطبيقات REST الحالية لم تتغير. + +#### المرحلة الرابعة: العمليات المجمعة (الأسبوعان الرابع والخامس) + +1. تنفيذ الفئة `BulkClient` +2. إضافة طرق الاستيراد/التصدير المجمعة للثلاثيات والتضمينات والسياقات والكائنات +3. تنفيذ المعالجة القائمة على المكرر للذاكرة الثابتة +4. إضافة تتبع التقدم (وظيفة رد اتصال اختيارية) +5. إضافة معالجة الأخطاء مع الإبلاغ عن النجاح الجزئي +6. إضافة اختبارات الوحدة والتكامل +7. إضافة أمثلة للعمليات المجمعة + +**التوافق مع الإصدارات السابقة**: واجهة جديدة فقط. لا يوجد تأثير على التعليمات البرمجية الحالية. + +#### المرحلة الخامسة: تحقيق التكافؤ والتحسين (الأسبوع الخامس) + +1. إضافة `graph_embeddings_query()` إلى REST `FlowInstance` +2. تنفيذ الفئة `Metrics` +3. إضافة اختبارات تكامل شاملة +4. قياس الأداء +5. تحديث جميع الوثائق +6. إنشاء دليل ترحيل + +**التوافق مع الإصدارات السابقة**: طرق جديدة فقط. لا يوجد تأثير على التعليمات البرمجية الحالية. + +### نماذج البيانات + +#### اختيار الواجهة + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### أنواع الاستجابة المتدفقة + +**تدفق الوكيل (Agent Streaming):** + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**البث المتدفق (RAG Streaming):** + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**العمليات المجمعة (المزامنة):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**العمليات المجمعة (غير متزامنة):** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**مثال REST غير المتزامن:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**مثال على بث WebSocket غير المتزامن:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### واجهات برمجة التطبيقات (APIs) + +#### واجهات برمجة تطبيقات جديدة + +1. **فئة واجهة برمجة التطبيقات الأساسية (Core API Class)**: + **متزامن (Synchronous)**: + `Api.socket()` - الحصول على عميل WebSocket متزامن + `Api.bulk()` - الحصول على عميل العمليات المجمعة متزامن + `Api.metrics()` - الحصول على عميل المقاييس متزامن + `Api.close()` - إغلاق جميع الاتصالات المتزامنة + دعم مدير السياق (`__enter__`, `__exit__`) + **غير متزامن (Asynchronous)**: + `Api.async_flow()` - الحصول على عميل تدفق REST غير متزامن + `Api.async_socket()` - الحصول على عميل WebSocket غير متزامن + `Api.async_bulk()` - الحصول على عميل العمليات المجمعة غير متزامن + `Api.async_metrics()` - الحصول على عميل المقاييس غير متزامن + `Api.aclose()` - إغلاق جميع الاتصالات غير المتزامنة + دعم مدير السياق غير المتزامن (`__aenter__`, `__aexit__`) + +2. **عميل WebSocket متزامن**: + `SocketClient.flow(flow_id)` - الحصول على مثيل تدفق WebSocket + `SocketFlowInstance.agent(..., streaming: bool = False)` - وكيل مع دعم اختياري للتدفق + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - إكمال النص مع دعم اختياري للتدفق + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - استعلام Graph RAG مع دعم اختياري للتدفق + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - استعلام Document RAG مع دعم اختياري للتدفق + `SocketFlowInstance.prompt(..., streaming: bool = False)` - استعلام Prompt مع دعم اختياري للتدفق + `SocketFlowInstance.graph_embeddings_query()` - استعلام تضمينات الرسم البياني + جميع طرق FlowInstance الأخرى بنفس التوقيعات + +3. **عميل WebSocket غير متزامن**: + `AsyncSocketClient.flow(flow_id)` - الحصول على مثيل تدفق WebSocket غير متزامن + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - وكيل غير متزامن مع دعم اختياري للتدفق + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - إكمال نص غير متزامن مع دعم اختياري للتدفق + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - استعلام Graph RAG غير متزامن مع دعم اختياري للتدفق + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - استعلام Document RAG غير متزامن مع دعم اختياري للتدفق + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - استعلام Prompt غير متزامن مع دعم اختياري للتدفق + `AsyncSocketFlowInstance.graph_embeddings_query()` - استعلام تضمينات الرسم البياني غير المتزامن + جميع طرق FlowInstance الأخرى كإصدارات غير متزامنة + +4. **عميل العمليات المجمعة متزامن**: + `BulkClient.import_triples(flow, triples)` - استيراد مجمع ثلاثيات + `BulkClient.export_triples(flow)` - تصدير مجمع ثلاثيات + `BulkClient.import_graph_embeddings(flow, embeddings)` - استيراد مجمع تضمينات الرسم البياني + `BulkClient.export_graph_embeddings(flow)` - تصدير مجمع تضمينات الرسم البياني + `BulkClient.import_document_embeddings(flow, embeddings)` - استيراد مجمع تضمينات المستندات + `BulkClient.export_document_embeddings(flow)` - تصدير مجمع تضمينات المستندات + `BulkClient.import_entity_contexts(flow, contexts)` - استيراد مجمع سياقات الكيانات + `BulkClient.export_entity_contexts(flow)` - تصدير مجمع سياقات الكيانات + `BulkClient.import_objects(flow, objects)` - استيراد مجمع الكائنات + +5. **عميل العمليات المجمعة غير المتزامن**: + `AsyncBulkClient.import_triples(flow, triples)` - استيراد مجمع ثلاثيات غير متزامن + `AsyncBulkClient.export_triples(flow)` - تصدير مجمع ثلاثيات غير متزامن + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - استيراد مجمع تضمينات الرسم البياني غير المتزامن + `AsyncBulkClient.export_graph_embeddings(flow)` - تصدير مجمع تضمينات الرسم البياني غير المتزامن + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - استيراد مجمع تضمينات المستندات غير المتزامن + `AsyncBulkClient.export_document_embeddings(flow)` - تصدير مجمع تضمينات المستندات غير المتزامن + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - استيراد مجمع سياقات الكيانات غير المتزامن + `AsyncBulkClient.export_entity_contexts(flow)` - تصدير مجمع سياقات الكيانات غير المتزامن + `AsyncBulkClient.import_objects(flow, objects)` - استيراد مجمع الكائنات غير المتزامن + +6. **عميل تدفق REST غير المتزامن**: + `AsyncFlow.list()` - سرد جميع التدفقات (غير متزامن) + `AsyncFlow.get(id)` - الحصول على تعريف التدفق (غير متزامن) + `AsyncFlow.start(...)` - بدء التدفق (غير متزامن) + `AsyncFlow.stop(id)` - إيقاف التدفق (غير متزامن) + `AsyncFlow.id(flow_id)` - الحصول على مثيل تدفق (غير متزامن) + `AsyncFlowInstance.agent(...)` - تنفيذ الوكيل (غير متزامن) + `AsyncFlowInstance.text_completion(...)` - إكمال النص (غير متزامن) + `AsyncFlowInstance.graph_rag(...)` - Graph RAG (غير متزامن) + جميع طرق FlowInstance الأخرى كإصدارات غير متزامنة + +7. **عملاء المقاييس**: + `Metrics.get()` - مقاييس Prometheus متزامنة + `AsyncMetrics.get()` - مقاييس Prometheus غير متزامنة + +8. **تحسين واجهة برمجة تطبيقات REST للتدفق**: + `FlowInstance.graph_embeddings_query()` - استعلام تضمينات الرسم البياني (للتوافق مع الميزات المتزامنة) + `AsyncFlowInstance.graph_embeddings_query()` - استعلام تضمينات الرسم البياني (للتوافق مع الميزات غير المتزامنة) + +#### واجهات برمجة تطبيقات معدلة + +1. **المنشئ (Constructor)** (تحسين طفيف): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + تمت إضافة المعامل `token` (اختياري، للمصادقة). + إذا لم يتم تحديد `None` (افتراضيًا): لم يتم استخدام أي مصادقة. + إذا تم تحديده: يتم استخدامه كرمز مميز (bearer token) لواجهة برمجة التطبيقات REST (`Authorization: Bearer `)، ومعامل استعلام لـ WebSocket (`?token=`). + لا توجد تغييرات أخرى - متوافق تمامًا مع الإصدارات السابقة. + +2. **لا توجد تغييرات جذرية**: + جميع طرق واجهة برمجة التطبيقات REST الحالية لم تتغير. + تمت الحفاظ على جميع التوقيعات الحالية. + تمت الحفاظ على جميع أنواع الإرجاع الحالية. + +### تفاصيل التنفيذ + +#### معالجة الأخطاء + +**أخطاء اتصال WebSocket**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**العودة السلسة:** +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**أخطاء البث الجزئي:** +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### إدارة الموارد + +**دعم مدير السياق:** +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### الترابط والتزامن + +**أمان الترابط**: +تحتفظ كل نسخة من `Api` باتصالها الخاص. +يستخدم نقل WebSocket الأقفال لعملية تعدد المهام الآمنة للطلبات. +يمكن للعديد من سلاسل العمل (threads) مشاركة نسخة واحدة من `Api` بأمان. +مُكررات التدفق (streaming iterators) ليست آمنة للترابط (يجب استهلاكها من سلسلة عمل واحدة). + +**دعم غير متزامن** (للمستقبل): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## اعتبارات الأمان + +### المصادقة + +**المعلمة الرمز:** +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**نقل REST:** +رمز مميز عبر رأس `Authorization` +يتم تطبيقه تلقائيًا على جميع طلبات REST +التنسيق: `Authorization: Bearer ` + +**نقل WebSocket:** +رمز مميز عبر معلمة الاستعلام المضافة إلى عنوان URL الخاص بـ WebSocket +يتم تطبيقه تلقائيًا أثناء إنشاء الاتصال +التنسيق: `ws://localhost:8088/api/v1/socket?token=` + +**التنفيذ:** +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**مثال:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### الاتصالات الآمنة + +يدعم كل من البروتوكولين WS (WebSocket) و WSS (WebSocket Secure). +التحقق من صحة شهادة TLS لاتصالات WSS. +تعطيل اختياري للتحقق من الشهادة لأغراض التطوير (مع تحذير). + +### التحقق من صحة البيانات المدخلة + +التحقق من صحة مخططات عناوين URL (http، https، ws، wss). +التحقق من صحة قيم معلمات النقل. +التحقق من صحة مجموعات معلمات التدفق. +التحقق من صحة أنواع بيانات الاستيراد المجمعة. + +## اعتبارات الأداء + +### تحسينات في زمن الاستجابة + +**عمليات LLM المتدفقة**: +**الوقت اللازم للحصول على أول رمز**: ~500 مللي ثانية (مقارنة بـ ~30 ثانية بدون تدفق). +**التحسين**: أداء أسرع بمقدار 60 مرة. +**ينطبق على**: الوكيل، و Graph RAG، و Document RAG، وإكمال النص، والموجه. + +**الاتصالات المستمرة**: +**تكلفة الاتصال**: يتم إلغاؤها للطلبات اللاحقة. +**مصافحة WebSocket**: تكلفة لمرة واحدة (~100 مللي ثانية). +**ينطبق على**: جميع العمليات عند استخدام نقل WebSocket. + +### تحسينات في الإنتاجية + +**العمليات المجمعة**: +**استيراد الثلاثيات**: ~10,000 ثلاثية/ثانية (مقارنة بـ ~100/ثانية باستخدام REST لكل عنصر). +**استيراد التضمينات**: ~5,000 تضمين/ثانية (مقارنة بـ ~50/ثانية باستخدام REST لكل عنصر). +**التحسين**: زيادة في الإنتاجية بمقدار 100 مرة للعمليات المجمعة. + +**تعدد الطلبات**: +**الطلبات المتزامنة**: تصل إلى 15 طلبًا متزامنًا عبر اتصال واحد. +**إعادة استخدام الاتصال**: لا توجد تكلفة إضافية للاتصال للعمليات المتزامنة. + +### اعتبارات الذاكرة + +**الاستجابات المتدفقة**: +استخدام ثابت للذاكرة (معالجة أجزاء البيانات عند وصولها). +لا يتم تخزين الاستجابة بأكملها في الذاكرة. +مناسب للإخراجات الطويلة جدًا (>1 ميجابايت). + +**العمليات المجمعة**: +معالجة قائمة (استخدام ثابت للذاكرة). +لا يتم تحميل مجموعة البيانات بأكملها في الذاكرة. +مناسب لمجموعات البيانات التي تحتوي على ملايين العناصر. + +### المقاييس (المتوقعة) + +| العملية | REST (الحالي) | WebSocket (تدفق) | التحسين | +|-----------|----------------|----------------------|-------------| +| الوكيل (الوقت اللازم للحصول على أول رمز) | 30 ثانية | 0.5 ثانية | 60x | +| Graph RAG (الوقت اللازم للحصول على أول رمز) | 25 ثانية | 0.5 ثانية | 50x | +| استيراد 10 آلاف ثلاثية | 100 ثانية | 1 ثانية | 100x | +| استيراد 1 مليون ثلاثية | 10,000 ثانية (2.7 ساعة) | 100 ثانية (1.6 دقيقة) | 100x | +| 10 طلبات صغيرة متزامنة | 5 ثوانٍ (تسلسلي) | 0.5 ثانية (متوازي) | 10x | + +## استراتيجية الاختبار + +### اختبارات الوحدة + +**طبقة النقل** (`test_transport.py`): +اختبار طلب/استجابة النقل REST +اختبار اتصال نقل WebSocket +اختبار إعادة اتصال نقل WebSocket +اختبار تعدد الطلبات +اختبار تحليل الاستجابة المتدفقة +محاكاة خادم WebSocket للاختبارات الحتمية + +**طرق واجهة برمجة التطبيقات (API)** (`test_flow.py`، `test_library.py`، إلخ): +اختبار الطرق الجديدة باستخدام النقل المُحاكى +اختبار معالجة المعلمات المتدفقة +اختبار مُكررات العمليات المجمعة +اختبار معالجة الأخطاء + +**الأنواع** (`test_types.py`): +اختبار أنواع الشرائح المتدفقة الجديدة +اختبار تسلسل/إلغاء تسلسل الأنواع + +### اختبارات التكامل + +**REST من طرف إلى طرف** (`test_integration_rest.py`): +اختبار جميع العمليات مقابل البوابة الحقيقية (وضع REST) +التحقق من التوافق مع الإصدارات السابقة +اختبار حالات الخطأ + +**WebSocket من طرف إلى طرف** (`test_integration_websocket.py`): +اختبار جميع العمليات مقابل البوابة الحقيقية (وضع WebSocket) +اختبار العمليات المتدفقة +اختبار العمليات المجمعة +اختبار الطلبات المتزامنة +اختبار استعادة الاتصال + +**خدمات التدفق** (`test_streaming_integration.py`): +اختبار تدفق الوكيل (الأفكار، والملاحظات، والإجابات) +اختبار تدفق RAG (أجزاء متزايدة) +اختبار تدفق إكمال النص (رمز تلو رمز) +اختبار تدفق المطالبات +اختبار معالجة الأخطاء أثناء التدفق + +**العمليات المجمعة** (`test_bulk_integration.py`): +اختبار استيراد/تصدير مجمّع للثلاثيات (1K، 10K، 100K عناصر) +اختبار استيراد/تصدير مجمّع للتضمينات +اختبار استخدام الذاكرة أثناء العمليات المجمعة +اختبار تتبع التقدم + +### اختبارات الأداء + +**معايير زمن الوصول** (`test_performance_latency.py`): +قياس الوقت اللازم للرمز الأول (تدفق مقابل عدم تدفق) +قياس النفقات العامة للاتصال (REST مقابل WebSocket) +مقارنة بالمعايير المتوقعة + +**معايير الإنتاجية** (`test_performance_throughput.py`): +قياس إنتاجية الاستيراد المجمّع +قياس كفاءة تعدد الطلبات +مقارنة بالمعايير المتوقعة + +### اختبارات التوافق + +**التوافق مع الإصدارات السابقة** (`test_backward_compatibility.py`): +تشغيل مجموعة الاختبار الحالية مقابل واجهة برمجة التطبيقات المعاد هيكلتها +التحقق من عدم وجود تغييرات فاصلة +اختبار مسار الترحيل للأنماط الشائعة + +## خطة الترحيل + +### المرحلة 1: الترحيل الشفاف (افتراضي) + +**لا يلزم إجراء أي تغييرات في التعليمات البرمجية**. يستمر التعليم البرمجي الحالي في العمل: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### المرحلة الثانية: البث الاختياري (بسيط) + +**استخدم واجهة `api.socket()` لتمكين البث:** + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**النقاط الرئيسية:** +نفس عنوان URL لكل من REST و WebSocket. +نفس توقيعات الطرق (سهولة الترحيل). +فقط أضف `.socket()` و `streaming=True`. + +### المرحلة الثالثة: العمليات المجمعة (قدرة جديدة). + +**استخدم واجهة `api.bulk()`** لمجموعات البيانات الكبيرة: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### تحديثات الوثائق + +1. **README.md**: إضافة أمثلة للبث و WebSocket +2. **مرجع واجهة برمجة التطبيقات (API Reference)**: توثيق جميع الطرق والمعلمات الجديدة +3. **دليل الترحيل (Migration Guide)**: دليل خطوة بخطوة لتمكين البث +4. **أمثلة (Examples)**: إضافة نصوص برمجية لأمثلة شائعة +5. **دليل الأداء (Performance Guide)**: توثيق التحسينات المتوقعة في الأداء + +### سياسة الإيقاف + +**لا يوجد إيقاف (No deprecations)**. تظل جميع واجهات برمجة التطبيقات الحالية مدعومة. هذا تحسين خالص. + +## الجدول الزمني + +### الأسبوع الأول: الأساس +طبقة تجريد النقل +إعادة هيكلة التعليمات البرمجية REST الحالية +اختبارات الوحدة لطبقة النقل +التحقق من التوافق مع الإصدارات السابقة + +### الأسبوع الثاني: نقل بيانات WebSocket +تنفيذ نقل بيانات WebSocket +إدارة الاتصال وإعادة الاتصال +تعدد الطلبات +اختبارات الوحدة والتكامل + +### الأسبوع الثالث: دعم البث +إضافة معلمة البث إلى طرق LLM +تنفيذ تحليل استجابة البث +إضافة أنواع أجزاء البث +اختبارات تكامل البث + +### الأسبوع الرابع: العمليات المجمعة +إضافة طرق الاستيراد/التصدير المجمعة +تنفيذ عمليات قائمة على المكرر +اختبار الأداء +اختبارات تكامل العمليات المجمعة + +### الأسبوع الخامس: تكافؤ الميزات والوثائق +إضافة استعلام تضمين الرسم البياني +إضافة واجهة برمجة تطبيقات المقاييس +وثائق شاملة +دليل الترحيل +إصدار مرشح + +### الأسبوع السادس: الإصدار +اختبار تكامل نهائي +قياس الأداء +وثائق الإصدار +إعلان للمجتمع + +**المدة الإجمالية**: 6 أسابيع + +## أسئلة مفتوحة + +### أسئلة تصميم واجهة برمجة التطبيقات + +1. **دعم غير متزامن (Async Support)**: ✅ **تم الحل (RESOLVED)** - تم تضمين الدعم الكامل غير المتزامن في الإصدار الأولي + تمت إضافة إصدارات غير متزامنة لجميع الواجهات: `async_flow()`، `async_socket()`، `async_bulk()`، `async_metrics()` + يوفر تناسقًا كاملاً بين واجهات برمجة التطبيقات المتزامنة وغير المتزامنة + ضروري لأطر العمل غير المتزامنة الحديثة (FastAPI, aiohttp) + +2. **تتبع التقدم (Progress Tracking)**: هل يجب أن تدعم العمليات المجمعة استدعيات رد اتصال للتقدم؟ + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **التوصية**: أضف في المرحلة الثانية. ليس ضروريًا للإصدار الأولي. + +3. **مهلة البث (Streaming Timeout)**: كيف يجب أن نتعامل مع المهلات لعمليات البث؟ + **التوصية**: استخدم نفس المهلة المستخدمة في العمليات غير المباشرة، ولكن أعد ضبطها عند استلام كل جزء. + +4. **تخزين الأجزاء مؤقتًا (Chunk Buffering)**: هل يجب علينا تخزين الأجزاء مؤقتًا أم إرجاعها على الفور؟ + **التوصية**: أرجعها على الفور لتقليل زمن الوصول. + +5. **الخدمات العامة عبر WebSocket**: هل يجب أن يدعم `api.socket()` الخدمات العامة (المكتبة، المعرفة، المجموعة، التكوين) أم فقط الخدمات الخاصة بالنطاق (flow-scoped)؟ + **التوصية**: ابدأ بالخدمات الخاصة بالنطاق فقط (حيث يكون البث مهمًا). أضف الخدمات العامة إذا لزم الأمر في المرحلة الثانية. + +### أسئلة التنفيذ + +1. **مكتبة WebSocket**: هل يجب أن نستخدم `websockets`، `websocket-client`، أو `aiohttp`؟ + **التوصية**: `websockets` (غير متزامن، ناضج، مدعوم جيدًا). قم بتغليفه في واجهة متزامنة باستخدام `asyncio.run()`. + +2. **تجميع الاتصالات (Connection Pooling)**: هل يجب أن ندعم مثيلات متعددة متزامنة من `Api` تشارك مجموعة اتصالات؟ + **التوصية**: تؤجل إلى المرحلة الثانية. كل مثيل من `Api` لديه اتصالات خاصة به في البداية. + +3. **إعادة استخدام الاتصال (Connection Reuse)**: هل يجب أن تشارك `SocketClient` و `BulkClient` نفس اتصال WebSocket، أم تستخدم اتصالات منفصلة؟ + **التوصية**: اتصالات منفصلة. تطبيق أبسط، وفصل واضح للمسؤوليات. + +4. **الاتصال الكسول مقابل الاتصال الحماسي (Lazy vs Eager Connection)**: هل يجب إنشاء اتصال WebSocket في `api.socket()` أم عند الطلب الأول؟ + **التوصية**: كسول (عند الطلب الأول). يتجنب تكلفة الاتصال إذا كان المستخدم يستخدم فقط طرق REST. + +### أسئلة الاختبار + +1. **بوابة وهمية (Mock Gateway)**: هل يجب علينا إنشاء بوابة وهمية خفيفة الوزن للاختبار، أم الاختبار مقابل البوابة الحقيقية؟ + **التوصية**: كلاهما. استخدم الوهميات للاختبارات الوحدوية، والبوابة الحقيقية للاختبارات التكاملية. + +2. **اختبارات الانحدار في الأداء (Performance Regression Tests)**: هل يجب علينا إضافة اختبارات أداء انحدار آلية إلى CI؟ + **التوصية**: نعم، ولكن مع حدود سماح كبيرة لمراعاة تباين بيئة CI. + +## المراجع + +### المواصفات التقنية ذات الصلة +`docs/tech-specs/streaming-llm-responses.md` - تطبيق البث في البوابة +`docs/tech-specs/rag-streaming-support.md` - دعم البث لـ RAG + +### ملفات التنفيذ +`trustgraph-base/trustgraph/api/` - مصدر واجهة برمجة التطبيقات (API) بلغة Python +`trustgraph-flow/trustgraph/gateway/` - مصدر البوابة +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - تطبيق مرجعي لتقسيم WebSocket + +### التوثيق +`docs/apiSpecification.md` - مرجع API كامل +`docs/api-status-summary.md` - ملخص حالة API +`README.websocket` - توثيق بروتوكول WebSocket +`STREAMING-IMPLEMENTATION-NOTES.txt` - ملاحظات حول تطبيق البث + +### المكتبات الخارجية +`websockets` - مكتبة WebSocket بلغة Python (https://websockets.readthedocs.io/) +`requests` - مكتبة HTTP بلغة Python (موجودة) diff --git a/docs/tech-specs/python-api-refactor.es.md b/docs/tech-specs/python-api-refactor.es.md new file mode 100644 index 00000000..08b87d15 --- /dev/null +++ b/docs/tech-specs/python-api-refactor.es.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Especificación Técnica de Refactorización de la API de Python" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Refactorización de la API de Python + +> **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 una refactorización integral de la biblioteca de cliente de la API de Python de TrustGraph para lograr la paridad de funciones con la API Gateway y agregar soporte para patrones de comunicación en tiempo real modernos. + +La refactorización aborda cuatro casos de uso principales: + +1. **Interacciones de LLM en Streaming**: Habilitar el streaming en tiempo real de las respuestas de LLM (agente, RAG de grafos, RAG de documentos, finalización de texto, prompts) con una latencia significativamente menor (~60 veces menor, 500 ms frente a 30 s para el primer token). +2. **Operaciones de Datos Masivos**: Soporte para la importación/exportación eficiente de triples, incrustaciones de grafos e incrustaciones de documentos para la gestión de grafos de conocimiento a gran escala. +3. **Paridad de Funciones**: Asegurar que cada punto final de la API Gateway tenga un método de API de Python correspondiente, incluidas las consultas de incrustaciones de grafos. +4. **Conexiones Persistentes**: Habilitar la comunicación basada en WebSocket para solicitudes multiplexadas y una menor sobrecarga de conexión. + +## Objetivos + +**Paridad de Funciones**: Cada servicio de la API Gateway tiene un método de API de Python correspondiente. +**Soporte de Streaming**: Todos los servicios capaces de streaming (agente, RAG, finalización de texto, prompt) admiten el streaming en la API de Python. +**Transporte WebSocket**: Agregar una capa de transporte WebSocket opcional para conexiones persistentes y multiplexación. +**Operaciones Masivas**: Agregar importación/exportación masiva eficiente para triples, incrustaciones de grafos e incrustaciones de documentos. +**Soporte Completo Async**: Implementación completa de async/await para todas las interfaces (REST, WebSocket, operaciones masivas, métricas). +**Compatibilidad con Versiones Anteriores**: El código existente continúa funcionando sin modificaciones. +**Seguridad de Tipos**: Mantener interfaces con seguridad de tipos utilizando dataclasses y sugerencias de tipo. +**Mejora Progresiva**: El streaming y el async son opcionales a través de la selección explícita de la interfaz. +**Rendimiento**: Lograr una mejora de latencia de 60 veces para las operaciones de streaming. +**Python Moderno**: Soporte para paradigmas tanto síncronos como asíncronos para una máxima flexibilidad. + +## Antecedentes + +### Estado Actual + +La API de Python (`trustgraph-base/trustgraph/api/`) es una biblioteca de cliente REST con los siguientes módulos: + +`flow.py`: Gestión de flujos y servicios con ámbito de flujo (50 métodos). +`library.py`: Operaciones de la biblioteca de documentos (9 métodos). +`knowledge.py`: Gestión central de grafos (4 métodos). +`collection.py`: Metadatos de colecciones (3 métodos). +`config.py`: Gestión de configuración (6 métodos). +`types.py`: Definiciones de tipos de datos (5 dataclasses). + +**Operaciones Totales**: 50/59 (cobertura del 85%). + +### Limitaciones Actuales + +**Operaciones Faltantes**: +Consulta de incrustaciones de grafos (búsqueda semántica sobre entidades de grafos). +Importación/exportación masiva para triples, incrustaciones de grafos, incrustaciones de documentos, contextos de entidades, objetos. +Punto final de métricas. + +**Capacidades Faltantes**: +Soporte de streaming para servicios de LLM. +Transporte WebSocket. +Solicitudes concurrentes multiplexadas. +Conexiones persistentes. + +**Problemas de Rendimiento**: +Alta latencia para las interacciones de LLM (~30 s para el primer token). +Transferencia de datos masiva ineficiente (solicitud REST por elemento). +Sobrecarga de conexión para múltiples operaciones secuenciales. + +**Problemas de Experiencia de Usuario**: +Sin retroalimentación en tiempo real durante la generación de LLM. +No se pueden cancelar las operaciones de LLM de larga duración. +Mala escalabilidad para las operaciones masivas. + +### Impacto + +La mejora de streaming de noviembre de 2024 en la API Gateway proporcionó una mejora de latencia de 60 veces (500 ms frente a 30 s para el primer token) para las interacciones de LLM, pero los usuarios de la API de Python no pueden aprovechar esta capacidad. Esto crea una brecha significativa de experiencia entre los usuarios de Python y los que no lo utilizan. + +## Diseño Técnico + +### Arquitectura + +La API de Python refactorizada utiliza un **enfoque de interfaz modular** con objetos separados para diferentes patrones de comunicación. Todas las interfaces están disponibles tanto en variantes **síncronas como asíncronas**: + +1. **Interfaz REST** (existente, mejorada). + **Sync**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()`. + **Async**: `api.async_flow()`. + Solicitud/respuesta síncrona/asíncrona. + Modelo de conexión simple. + Predeterminado para la compatibilidad con versiones anteriores. + +2. **Interfaz WebSocket** (nueva). + **Sync**: `api.socket()`. + **Async**: `api.async_socket()`. + Conexión persistente. + Solicitudes multiplexadas. + Soporte de streaming. + Mismas firmas de método que REST donde la funcionalidad se superpone. + +3. **Interfaz de Operaciones Masivas** (nueva). + **Sync**: `api.bulk()`. + **Async**: `api.async_bulk()`. + Basado en WebSocket para la eficiencia. + Importación/exportación basada en iterador/AsyncIterator. + Maneja conjuntos de datos grandes. + +4. **Interfaz de Métricas** (nueva). + **Sync**: `api.metrics()`. + **Async**: `api.async_metrics()`. + Acceso a métricas de Prometheus. + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**Principios clave de diseño:** +**Misma URL para todas las interfaces:** `Api(url="http://localhost:8088/")` funciona para todas. +**Simetría sincrónica/asincrónica:** Cada interfaz tiene variantes tanto sincrónicas como asincrónicas con firmas de método idénticas. +**Firmas idénticas:** Donde la funcionalidad se superpone, las firmas de los métodos son idénticas entre REST y WebSocket, sincrónicas y asincrónicas. +**Mejora progresiva:** Elija la interfaz según las necesidades (REST para tareas simples, WebSocket para transmisión, Bulk para conjuntos de datos grandes, asíncrono para marcos modernos). +**Intención explícita:** `api.socket()` indica WebSocket, `api.async_socket()` indica WebSocket asíncrono. +**Compatible con versiones anteriores:** El código existente no se modifica. + +### Componentes + +#### 1. Clase API principal (modificada) + +Módulo: `trustgraph-base/trustgraph/api/api.py` + +**Clase API mejorada:** + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. Cliente WebSocket Síncrono + +Módulo: `trustgraph-base/trustgraph/api/socket_client.py` (nuevo) + +**Clase SocketClient**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Características principales:** +Conexión perezosa (solo se conecta cuando se envía la primera solicitud) +Multiplexación de solicitudes (hasta 15 concurrentes) +Reconexión automática en caso de desconexión +Análisis de respuesta en streaming +Operación segura para subprocesos +Envoltorio sincrónico alrededor de la biblioteca de websockets asíncrona + +#### 3. Cliente WebSocket asíncrono + +Módulo: `trustgraph-base/trustgraph/api/async_socket_client.py` (nuevo) + +**Clase AsyncSocketClient:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Características principales**: +Soporte nativo para async/await +Eficiente para aplicaciones asíncronas (FastAPI, aiohttp) +Sin bloqueo de hilos +Misma interfaz que la versión síncrona +AsyncIterator para streaming + +#### 4. Cliente de Operaciones Masivas Síncronas + +Módulo: `trustgraph-base/trustgraph/api/bulk_client.py` (nuevo) + +**Clase BulkClient**: + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**Características principales:** +Basado en iteradores para un uso constante de memoria. +Conexiones WebSocket dedicadas por operación. +Seguimiento del progreso (callback opcional). +Manejo de errores con informes de éxito parcial. + +#### 5. Cliente de operaciones masivas asíncronas + +Módulo: `trustgraph-base/trustgraph/api/async_bulk_client.py` (nuevo) + +**Clase AsyncBulkClient:** + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**Características principales:** +Basado en AsyncIterator para un uso constante de memoria. +Eficiente para aplicaciones asíncronas. +Soporte nativo para async/await. +Misma interfaz que la versión síncrona. + +#### 6. API de flujo REST (Síncrono - Sin cambios) + +Módulo: `trustgraph-base/trustgraph/api/flow.py` + +La API de flujo REST permanece **completamente sin cambios** para la compatibilidad con versiones anteriores. Todos los métodos existentes siguen funcionando: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, etc. +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, etc. +Todas las firmas y tipos de retorno existentes se conservan. + +**Nuevo:** Agregar `graph_embeddings_query()` a REST FlowInstance para la paridad de funciones: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. API de flujo REST asíncrono + +Módulo: `trustgraph-base/trustgraph/api/async_flow.py` (nuevo) + +**Clases AsyncFlow y AsyncFlowInstance:** + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**Características principales:** +HTTP asíncrono nativo utilizando `aiohttp` o `httpx` +Mismas firmas de método que la API REST sincrónica +Sin transmisión (utilice `async_socket()` para la transmisión) +Eficiente para aplicaciones asíncronas + +#### 8. API de métricas + +Módulo: `trustgraph-base/trustgraph/api/metrics.py` (nuevo) + +**Métricas sincrónicas:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**Métricas Asíncronas**: + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. Tipos Mejorados + +Módulo: `trustgraph-base/trustgraph/api/types.py` (modificado) + +**Nuevos Tipos**: + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. API de métricas + +Módulo: `trustgraph-base/trustgraph/api/metrics.py` (nuevo) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### Enfoque de Implementación + +#### Fase 1: Mejora del API Central (Semana 1) + +1. Agregar métodos `socket()`, `bulk()` y `metrics()` a la clase `Api` +2. Implementar inicialización perezosa para WebSocket y clientes masivos +3. Agregar soporte para administrador de contexto (`__enter__`, `__exit__`) +4. Agregar método `close()` para limpieza +5. Agregar pruebas unitarias para las mejoras del API +6. Verificar compatibilidad con versiones anteriores + +**Compatibilidad con versiones anteriores**: No hay cambios que rompan la compatibilidad. Solo se agregan nuevos métodos. + +#### Fase 2: Cliente WebSocket (Semanas 2-3) + +1. Implementar clase `SocketClient` con gestión de conexión +2. Implementar `SocketFlowInstance` con las mismas firmas de método que `FlowInstance` +3. Agregar soporte para multiplexación de solicitudes (hasta 15 concurrentes) +4. Agregar análisis de respuesta en streaming para diferentes tipos de fragmentos +5. Agregar lógica de reconexión automática +6. Agregar pruebas unitarias e integrales +7. Documentar patrones de uso de WebSocket + +**Compatibilidad con versiones anteriores**: Nueva interfaz solamente. No tiene impacto en el código existente. + +#### Fase 3: Soporte de Streaming (Semanas 3-4) + +1. Agregar clases de tipo de fragmento de streaming (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. Implementar análisis de respuesta en streaming en `SocketClient` +3. Agregar parámetro de streaming a todos los métodos LLM en `SocketFlowInstance` +4. Manejar casos de error durante el streaming +5. Agregar pruebas unitarias e integrales para el streaming +6. Agregar ejemplos de streaming a la documentación + +**Compatibilidad con versiones anteriores**: Nueva interfaz solamente. El API REST existente no se modifica. + +#### Fase 4: Operaciones Masivas (Semanas 4-5) + +1. Implementar clase `BulkClient` +2. Agregar métodos de importación/exportación masiva para triples, incrustaciones, contextos, objetos +3. Implementar procesamiento basado en iterador para un uso constante de memoria +4. Agregar seguimiento de progreso (callback opcional) +5. Agregar manejo de errores con informes de éxito parcial +6. Agregar pruebas unitarias e integrales +7. Agregar ejemplos de operaciones masivas + +**Compatibilidad con versiones anteriores**: Nueva interfaz solamente. No tiene impacto en el código existente. + +#### Fase 5: Paridad de Funciones y Pulido (Semana 5) + +1. Agregar `graph_embeddings_query()` a REST `FlowInstance` +2. Implementar clase `Metrics` +3. Agregar pruebas de integración exhaustivas +4. Pruebas de rendimiento +5. Actualizar toda la documentación +6. Crear una guía de migración + +**Compatibilidad con versiones anteriores**: Nuevos métodos solamente. No tiene impacto en el código existente. + +### Modelos de Datos + +#### Selección de Interfaz + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### Tipos de respuesta de transmisión + +**Transmisión del agente**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**Transmisión RAG**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**Operaciones masivas (síncronas):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**Operaciones masivas (asíncronas):** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**Ejemplo de REST asíncrono**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**Ejemplo de transmisión WebSocket asíncrona:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### APIs + +#### New APIs + +1. **Clase API Core**: + **Síncrono**: + `Api.socket()` - Obtener cliente WebSocket síncrono + `Api.bulk()` - Obtener cliente de operaciones masivas síncrono + `Api.metrics()` - Obtener cliente de métricas síncrono + `Api.close()` - Cerrar todas las conexiones síncronas + Soporte de administrador de contexto (`__enter__`, `__exit__`) + **Asíncrono**: + `Api.async_flow()` - Obtener cliente de flujo REST asíncrono + `Api.async_socket()` - Obtener cliente WebSocket asíncrono + `Api.async_bulk()` - Obtener cliente de operaciones masivas asíncrono + `Api.async_metrics()` - Obtener cliente de métricas asíncrono + `Api.aclose()` - Cerrar todas las conexiones asíncronas + Soporte de administrador de contexto asíncrono (`__aenter__`, `__aexit__`) + +2. **Cliente WebSocket Síncrono**: + `SocketClient.flow(flow_id)` - Obtener instancia de flujo WebSocket + `SocketFlowInstance.agent(..., streaming: bool = False)` - Agente con transmisión opcional + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - Completar texto con transmisión opcional + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - RAG de gráfico con transmisión opcional + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - RAG de documento con transmisión opcional + `SocketFlowInstance.prompt(..., streaming: bool = False)` - Prompt con transmisión opcional + `SocketFlowInstance.graph_embeddings_query()` - Consulta de incrustaciones de gráfico + Todos los demás métodos de FlowInstance con firmas idénticas + +3. **Cliente WebSocket Asíncrono**: + `AsyncSocketClient.flow(flow_id)` - Obtener instancia de flujo WebSocket asíncrono + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - Agente asíncrono con transmisión opcional + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - Completar texto asíncrono con transmisión opcional + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - RAG de gráfico asíncrono con transmisión opcional + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - RAG de documento asíncrono con transmisión opcional + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - Prompt asíncrono con transmisión opcional + `AsyncSocketFlowInstance.graph_embeddings_query()` - Consulta de incrustaciones de gráfico asíncrona + Todos los demás métodos de FlowInstance como versiones asíncronas + +4. **Cliente de Operaciones Masivas Síncrono**: + `BulkClient.import_triples(flow, triples)` - Importación masiva de triples + `BulkClient.export_triples(flow)` - Exportación masiva de triples + `BulkClient.import_graph_embeddings(flow, embeddings)` - Importación masiva de incrustaciones de gráfico + `BulkClient.export_graph_embeddings(flow)` - Exportación masiva de incrustaciones de gráfico + `BulkClient.import_document_embeddings(flow, embeddings)` - Importación masiva de incrustaciones de documento + `BulkClient.export_document_embeddings(flow)` - Exportación masiva de incrustaciones de documento + `BulkClient.import_entity_contexts(flow, contexts)` - Importación masiva de contextos de entidades + `BulkClient.export_entity_contexts(flow)` - Exportación masiva de contextos de entidades + `BulkClient.import_objects(flow, objects)` - Importación masiva de objetos + +5. **Cliente de Operaciones Masivas Asíncrono**: + `AsyncBulkClient.import_triples(flow, triples)` - Importación asíncrona masiva de triples + `AsyncBulkClient.export_triples(flow)` - Exportación asíncrona masiva de triples + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - Importación asíncrona masiva de incrustaciones de gráfico + `AsyncBulkClient.export_graph_embeddings(flow)` - Exportación asíncrona masiva de incrustaciones de gráfico + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - Importación asíncrona masiva de incrustaciones de documento + `AsyncBulkClient.export_document_embeddings(flow)` - Exportación asíncrona masiva de incrustaciones de documento + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - Importación asíncrona masiva de contextos de entidades + `AsyncBulkClient.export_entity_contexts(flow)` - Exportación asíncrona masiva de contextos de entidades + `AsyncBulkClient.import_objects(flow, objects)` - Importación asíncrona masiva de objetos + +6. **Cliente de Flujo REST Asíncrono**: + `AsyncFlow.list()` - Listar todos los flujos de forma asíncrona + `AsyncFlow.get(id)` - Obtener definición de flujo de forma asíncrona + `AsyncFlow.start(...)` - Iniciar flujo de forma asíncrona + `AsyncFlow.stop(id)` - Detener flujo de forma asíncrona + `AsyncFlow.id(flow_id)` - Obtener instancia de flujo de forma asíncrona + `AsyncFlowInstance.agent(...)` - Ejecución de agente asíncrona + `AsyncFlowInstance.text_completion(...)` - Completar texto de forma asíncrona + `AsyncFlowInstance.graph_rag(...)` - RAG de gráfico asíncrono + Todos los demás métodos de FlowInstance como versiones asíncronas + +7. **Clientes de Métricas**: + `Metrics.get()` - Métricas de Prometheus síncronas + `AsyncMetrics.get()` - Métricas de Prometheus asíncronas + +8. **Mejora de la API REST de Flujo**: + `FlowInstance.graph_embeddings_query()` - Consulta de incrustaciones de gráfico (paridad de funciones síncronas) + `AsyncFlowInstance.graph_embeddings_query()` - Consulta de incrustaciones de gráfico (paridad de funciones asíncronas) + +#### APIs Modificadas + +1. **Constructor** (pequeña mejora): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + Se agregó el parámetro `token` (opcional, para autenticación). + Si `None` no se especifica (por defecto): No se utiliza autenticación. + Si se especifica: Se utiliza como token de tipo "bearer" para REST (`Authorization: Bearer `), parámetro de consulta para WebSocket (`?token=`). + No se realizaron otros cambios; es totalmente compatible con versiones anteriores. + +2. **Sin cambios que rompan la compatibilidad**: + Todos los métodos de la API REST existentes no se han modificado. + Todas las firmas existentes se han conservado. + Todos los tipos de retorno existentes se han conservado. + +### Detalles de implementación + +#### Manejo de errores + +**Errores de conexión WebSocket**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**Respaldo Elegante**: +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**Errores de transmisión parcial**: +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### Gestión de Recursos + +**Soporte para Administradores de Contexto**: +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### Concurrencia y Subprocesamiento + +**Seguridad de Subprocesos**: +Cada instancia de `Api` mantiene su propia conexión. +El transporte WebSocket utiliza bloqueos para el multiplexado de solicitudes, que es seguro para subprocesos. +Múltiples subprocesos pueden compartir una instancia de `Api` de forma segura. +Los iteradores de transmisión no son seguros para subprocesos (se deben consumir desde un solo subproceso). + +**Soporte Asíncrono** (consideración futura): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## Consideraciones de seguridad + +### Autenticación + +**Parámetro de token**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**Transporte REST**: +Token del portador a través del encabezado `Authorization` +Se aplica automáticamente a todas las solicitudes REST +Formato: `Authorization: Bearer ` + +**Transporte WebSocket**: +Token a través de un parámetro de consulta adjunto a la URL de WebSocket +Se aplica automáticamente durante el establecimiento de la conexión +Formato: `ws://localhost:8088/api/v1/socket?token=` + +**Implementación**: +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**Ejemplo:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### Comunicación Segura + +Soporta tanto los esquemas WS (WebSocket) como los de WSS (WebSocket Secure). +Validación de certificados TLS para conexiones WSS. +Verificación de certificados opcional para desarrollo (con advertencia). + +### Validación de Datos de Entrada + +Validar esquemas de URL (http, https, ws, wss). +Validar valores de parámetros de transporte. +Validar combinaciones de parámetros de transmisión. +Validar tipos de datos para la importación masiva. + +## Consideraciones de Rendimiento + +### Mejoras en la Latencia + +**Operaciones de LLM en Transmisión**: +**Tiempo hasta el primer token**: ~500ms (vs ~30s sin transmisión) +**Mejora**: 60 veces más rápido en términos de rendimiento percibido. +**Aplicable a**: Agente, Graph RAG, Document RAG, Completar Texto, Prompt. + +**Conexiones Persistentes**: +**Sobrecarga de la conexión**: Eliminada para solicitudes posteriores. +**Handshake de WebSocket**: Costo único (~100ms). +**Aplicable a**: Todas las operaciones al usar el transporte WebSocket. + +### Mejoras en el Rendimiento (Throughput) + +**Operaciones Masivas**: +**Importación de triples**: ~10,000 triples/segundo (vs ~100/segundo con REST por elemento). +**Importación de embeddings**: ~5,000 embeddings/segundo (vs ~50/segundo con REST por elemento). +**Mejora**: 100 veces más de rendimiento para operaciones masivas. + +**Multiplexación de Solicitudes**: +**Solicitudes concurrentes**: Hasta 15 solicitudes simultáneas sobre una sola conexión. +**Reutilización de la conexión**: Sin sobrecarga de conexión para operaciones concurrentes. + +### Consideraciones de Memoria + +**Respuestas en Transmisión**: +Uso constante de memoria (procesa los fragmentos a medida que llegan). +No se almacena en búfer la respuesta completa. +Adecuado para salidas muy largas (>1MB). + +**Operaciones Masivas**: +Procesamiento basado en iteradores (uso constante de memoria). +No se carga todo el conjunto de datos en la memoria. +Adecuado para conjuntos de datos con millones de elementos. + +### Pruebas de Rendimiento (Esperadas) + +| Operación | REST (existente) | WebSocket (en transmisión) | Mejora | +|-----------|----------------|----------------------|-------------| +| Agente (tiempo hasta el primer token) | 30s | 0.5s | 60x | +| Graph RAG (tiempo hasta el primer token) | 25s | 0.5s | 50x | +| Importar 10K triples | 100s | 1s | 100x | +| Importar 1M triples | 10,000s (2.7h) | 100s (1.6m) | 100x | +| 10 solicitudes pequeñas concurrentes | 5s (secuencial) | 0.5s (paralelo) | 10x | + +## Estrategia de Pruebas + +### Pruebas Unitarias + +**Capa de Transporte** (`test_transport.py`): +Probar la solicitud/respuesta de transporte REST +Probar la conexión de transporte WebSocket +Probar la reconexión de transporte WebSocket +Probar el multiplexado de solicitudes +Probar el análisis de la respuesta de transmisión +Simular un servidor WebSocket para pruebas deterministas + +**Métodos de la API** (`test_flow.py`, `test_library.py`, etc.): +Probar nuevos métodos con transporte simulado +Probar el manejo de parámetros de transmisión +Probar iteradores de operaciones masivas +Probar el manejo de errores + +**Tipos** (`test_types.py`): +Probar nuevos tipos de fragmentos de transmisión +Probar la serialización/deserialización de tipos + +### Pruebas de Integración + +**REST de Extremo a Extremo** (`test_integration_rest.py`): +Probar todas las operaciones contra la puerta de enlace real (modo REST) +Verificar la compatibilidad con versiones anteriores +Probar condiciones de error + +**WebSocket de Extremo a Extremo** (`test_integration_websocket.py`): +Probar todas las operaciones contra la puerta de enlace real (modo WebSocket) +Probar operaciones de transmisión +Probar operaciones masivas +Probar solicitudes concurrentes +Probar la recuperación de la conexión + +**Servicios de Transmisión** (`test_streaming_integration.py`): +Probar la transmisión de agentes (pensamientos, observaciones, respuestas) +Probar la transmisión de RAG (fragmentos incrementales) +Probar la transmisión de finalización de texto (token por token) +Probar la transmisión de indicaciones +Probar el manejo de errores durante la transmisión + +**Operaciones Masivas** (`test_bulk_integration.py`): +Probar la importación/exportación masiva de triples (1K, 10K, 100K elementos) +Probar la importación/exportación masiva de incrustaciones +Probar el uso de memoria durante las operaciones masivas +Probar el seguimiento del progreso + +### Pruebas de Rendimiento + +**Mediciones de Latencia** (`test_performance_latency.py`): +Medir el tiempo hasta el primer token (transmisión vs. no transmisión) +Medir la sobrecarga de la conexión (REST vs WebSocket) +Comparar con puntos de referencia esperados + +**Mediciones de Rendimiento** (`test_performance_throughput.py`): +Medir el rendimiento de la importación masiva +Medir la eficiencia del multiplexado de solicitudes +Comparar con puntos de referencia esperados + +### Pruebas de Compatibilidad + +**Compatibilidad con Versiones Anteriores** (`test_backward_compatibility.py`): +Ejecutar el conjunto de pruebas existente contra la API refactorizada +Verificar la ausencia de cambios que rompan la compatibilidad +Probar la ruta de migración para patrones comunes + +## Plan de Migración + +### Fase 1: Migración Transparente (Predeterminada) + +**No se requieren cambios en el código**. El código existente continúa funcionando: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### Fase 2: Transmisión por demanda (Simple) + +**Utilice la interfaz `api.socket()`** para habilitar la transmisión: + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**Puntos clave:** +La misma URL para REST y WebSocket. +Las mismas firmas de métodos (migración sencilla). +Simplemente agregue `.socket()` y `streaming=True`. + +### Fase 3: Operaciones masivas (Nueva funcionalidad) + +**Utilice la interfaz `api.bulk()`** para conjuntos de datos grandes: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### Actualizaciones de la documentación + +1. **README.md**: Agregar ejemplos de transmisión y WebSocket +2. **Referencia de la API**: Documentar todos los nuevos métodos y parámetros +3. **Guía de migración**: Guía paso a paso para habilitar la transmisión +4. **Ejemplos**: Agregar scripts de ejemplo para patrones comunes +5. **Guía de rendimiento**: Documentar las mejoras de rendimiento esperadas + +### Política de obsolescencia + +**No hay obsolescencias**. Todas las API existentes siguen siendo compatibles. Esto es una mejora pura. + +## Cronograma + +### Semana 1: Base +Capa de abstracción de transporte +Refactorizar código REST existente +Pruebas unitarias para la capa de transporte +Verificación de compatibilidad con versiones anteriores + +### Semana 2: Transporte WebSocket +Implementación del transporte WebSocket +Gestión de conexiones y reconexión +Multiplexación de solicitudes +Pruebas unitarias e de integración + +### Semana 3: Soporte de transmisión +Agregar parámetro de transmisión a los métodos de LLM +Implementar el análisis de respuestas de transmisión +Agregar tipos de fragmentos de transmisión +Pruebas de integración de transmisión + +### Semana 4: Operaciones masivas +Agregar métodos de importación/exportación masivos +Implementar operaciones basadas en iteradores +Pruebas de rendimiento +Pruebas de integración de operaciones masivas + +### Semana 5: Paridad de funciones y documentación +Agregar consulta de incrustaciones de grafos +Agregar API de métricas +Documentación completa +Guía de migración +Versión candidata + +### Semana 6: Lanzamiento +Pruebas de integración finales +Pruebas de referencia de rendimiento +Documentación de lanzamiento +Anuncio a la comunidad + +**Duración total**: 6 semanas + +## Preguntas abiertas + +### Preguntas de diseño de la API + +1. **Soporte asíncrono**: ✅ **RESUELTO** - Soporte asíncrono completo incluido en el lanzamiento inicial + Todas las interfaces tienen variantes asíncronas: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + Proporciona una simetría completa entre las API sincrónicas y asíncronas + Esencial para marcos de trabajo asíncronos modernos (FastAPI, aiohttp) + +2. **Seguimiento del progreso**: ¿Deben las operaciones masivas admitir devoluciones de llamada de progreso? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **Recomendación**: Agregar en la Fase 2. No es crítico para la versión inicial. + +3. **Tiempo de espera de la transmisión**: ¿Cómo debemos manejar los tiempos de espera para las operaciones de transmisión? + **Recomendación**: Utilizar el mismo tiempo de espera que para las operaciones no de transmisión, pero restablecerlo cada vez que se recibe un fragmento. + +4. **Almacenamiento en búfer de fragmentos**: ¿Debemos almacenar los fragmentos en búfer o devolverlos inmediatamente? + **Recomendación**: Devolverlos inmediatamente para lograr la menor latencia. + +5. **Servicios globales a través de WebSocket**: ¿Debería `api.socket()` admitir servicios globales (biblioteca, conocimiento, colección, configuración) o solo servicios específicos del flujo? + **Recomendación**: Comenzar solo con servicios específicos del flujo (donde la transmisión es importante). Agregar servicios globales si es necesario en la Fase 2. + +### Preguntas de implementación + +1. **Biblioteca de WebSocket**: ¿Debemos usar `websockets`, `websocket-client` o `aiohttp`? + **Recomendación**: `websockets` (asíncrono, maduro, bien mantenido). Envolverlo en una interfaz síncrona utilizando `asyncio.run()`. + +2. **Grupo de conexiones**: ¿Debemos admitir múltiples instancias concurrentes de `Api` que compartan un grupo de conexiones? + **Recomendación**: Dejar para la Fase 2. Cada instancia de `Api` tendrá sus propias conexiones inicialmente. + +3. **Reutilización de conexiones**: ¿Deben `SocketClient` y `BulkClient` compartir la misma conexión de WebSocket, o usar conexiones separadas? + **Recomendación**: Conexiones separadas. Implementación más sencilla, separación de responsabilidades más clara. + +4. **Conexión perezosa vs. activa**: ¿Se debe establecer la conexión de WebSocket en `api.socket()` o en la primera solicitud? + **Recomendación**: Perezosa (en la primera solicitud). Evita la sobrecarga de la conexión si el usuario solo utiliza métodos REST. + +### Preguntas de prueba + +1. **Pasarela de simulación**: ¿Debemos crear una pasarela de simulación ligera para las pruebas, o probar contra la pasarela real? + **Recomendación**: Ambos. Utilizar simulaciones para pruebas unitarias, y la pasarela real para pruebas de integración. + +2. **Pruebas de regresión de rendimiento**: ¿Debemos agregar pruebas de regresión de rendimiento automatizadas a CI? + **Recomendación**: Sí, pero con umbrales amplios para tener en cuenta la variabilidad del entorno de CI. + +## Referencias + +### Especificaciones técnicas relacionadas +`docs/tech-specs/streaming-llm-responses.md` - Implementación de transmisión en la pasarela +`docs/tech-specs/rag-streaming-support.md` - Soporte de transmisión RAG + +### Archivos de implementación +`trustgraph-base/trustgraph/api/` - Código fuente de la API de Python +`trustgraph-flow/trustgraph/gateway/` - Código fuente de la pasarela +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - Implementación de referencia de multiplexor de WebSocket + +### Documentación +`docs/apiSpecification.md` - Referencia completa de la API +`docs/api-status-summary.md` - Resumen del estado de la API +`README.websocket` - Documentación del protocolo WebSocket +`STREAMING-IMPLEMENTATION-NOTES.txt` - Notas de implementación de transmisión + +### Bibliotecas externas +`websockets` - Biblioteca de WebSocket de Python (https://websockets.readthedocs.io/) +`requests` - Biblioteca HTTP de Python (existente) diff --git a/docs/tech-specs/python-api-refactor.he.md b/docs/tech-specs/python-api-refactor.he.md new file mode 100644 index 00000000..7c313387 --- /dev/null +++ b/docs/tech-specs/python-api-refactor.he.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Python API Refactor Technical Specification" +parent: "Hebrew (Beta)" +--- + +# Python API Refactor 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 + +This specification describes a comprehensive refactor of the TrustGraph Python API client library to achieve feature parity with the API Gateway and add support for modern real-time communication patterns. + +The refactor addresses four primary use cases: + +1. **Streaming LLM Interactions**: Enable real-time streaming of LLM responses (agent, graph RAG, document RAG, text completion, prompts) with ~60x lower latency (500ms vs 30s for first token) +2. **Bulk Data Operations**: Support efficient bulk import/export of triples, graph embeddings, and document embeddings for large-scale knowledge graph management +3. **Feature Parity**: Ensure every API Gateway endpoint has a corresponding Python API method, including graph embeddings query +4. **Persistent Connections**: Enable WebSocket-based communication for multiplexed requests and reduced connection overhead + +## Goals + +**Feature Parity**: Every Gateway API service has a corresponding Python API method +**Streaming Support**: All streaming-capable services (agent, RAG, text completion, prompt) support streaming in Python API +**WebSocket Transport**: Add optional WebSocket transport layer for persistent connections and multiplexing +**Bulk Operations**: Add efficient bulk import/export for triples, graph embeddings, and document embeddings +**Full Async Support**: Complete async/await implementation for all interfaces (REST, WebSocket, bulk operations, metrics) +**Backward Compatibility**: Existing code continues to work without modification +**Type Safety**: Maintain type-safe interfaces with dataclasses and type hints +**Progressive Enhancement**: Streaming and async are opt-in via explicit interface selection +**Performance**: Achieve 60x latency improvement for streaming operations +**Modern Python**: Support for both sync and async paradigms for maximum flexibility + +## Background + +### Current State + +The Python API (`trustgraph-base/trustgraph/api/`) is a REST-only client library with the following modules: + +`flow.py`: Flow management and flow-scoped services (50 methods) +`library.py`: Document library operations (9 methods) +`knowledge.py`: KG core management (4 methods) +`collection.py`: Collection metadata (3 methods) +`config.py`: Configuration management (6 methods) +`types.py`: Data type definitions (5 dataclasses) + +**Total Operations**: 50/59 (85% coverage) + +### Current Limitations + +**Missing Operations**: +Graph embeddings query (semantic search over graph entities) +Bulk import/export for triples, graph embeddings, document embeddings, entity contexts, objects +Metrics endpoint + +**Missing Capabilities**: +Streaming support for LLM services +WebSocket transport +Multiplexed concurrent requests +Persistent connections + +**Performance Issues**: +High latency for LLM interactions (~30s time-to-first-token) +Inefficient bulk data transfer (REST request per item) +Connection overhead for multiple sequential operations + +**User Experience Issues**: +No real-time feedback during LLM generation +Cannot cancel long-running LLM operations +Poor scalability for bulk operations + +### Impact + +The November 2024 streaming enhancement to the Gateway API provided 60x latency improvement (500ms vs 30s first token) for LLM interactions, but Python API users cannot leverage this capability. This creates a significant experience gap between Python and non-Python users. + +## Technical Design + +### Architecture + +The refactored Python API uses a **modular interface approach** with separate objects for different communication patterns. All interfaces are available in both **synchronous and asynchronous** variants: + +1. **REST Interface** (existing, enhanced) + **Sync**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()` + **Async**: `api.async_flow()` + Synchronous/asynchronous request/response + Simple connection model + Default for backward compatibility + +2. **WebSocket Interface** (new) + **Sync**: `api.socket()` + **Async**: `api.async_socket()` + Persistent connection + Multiplexed requests + Streaming support + Same method signatures as REST where functionality overlaps + +3. **Bulk Operations Interface** (new) + **Sync**: `api.bulk()` + **Async**: `api.async_bulk()` + WebSocket-based for efficiency + Iterator/AsyncIterator-based import/export + Handles large datasets + +4. **Metrics Interface** (new) + **Sync**: `api.metrics()` + **Async**: `api.async_metrics()` + Prometheus metrics access + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**עקרונות עיצוב מרכזיים:** +**כתובת URL זהה לכל הממשקים:** `Api(url="http://localhost:8088/")` עובד עבור כל +**סימטריה בין סינכרוני/אסינכרוני:** לכל ממשק יש גרסאות סינכרוניות ואסינכרוניות עם חתימות מתודות זהות. +**חתימות זהות:** כאשר יש חפיפה בפונקציונליות, חתימות המתודות זהות בין REST ו-WebSocket, סינכרוני ואסינכרוני. +**שיפור הדרגתי:** בחרו ממשק בהתאם לצרכים (REST לפשוט, WebSocket לסטרימינג, Bulk עבור מערכי נתונים גדולים, אסינכרוני עבור מסגרות עבודה מודרניות). +**כוונת שימוש מפורשת:** `api.socket()` מציין WebSocket, `api.async_socket()` מציין WebSocket אסינכרוני. +**תואם לאחור:** קוד קיים אינו משתנה. + +### רכיבים + +#### 1. מחלקת API מרכזית (משופרת) + +מודול: `trustgraph-base/trustgraph/api/api.py` + +**מחלקת API משופרת:** + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. לקוח WebSocket סינכרוני + +מודול: `trustgraph-base/trustgraph/api/socket_client.py` (חדש) + +**מחלקה SocketClient**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**תכונות עיקריות:** +חיבור עצלני (מתחבר רק כאשר מתקבלת בקשה ראשונה) +ריבוב בקשות (עד 15 בקשות בו-זמנית) +חיבור מחדש אוטומטי במקרה של ניתוק +ניתוח תגובה בשיטת סטרימינג +פעולה בטוחה לשימוש ב-threads +עטיפה סינכרונית עבור ספריית websockets אסינכרונית + +#### 3. לקוח WebSocket אסינכרוני + +מודול: `trustgraph-base/trustgraph/api/async_socket_client.py` (חדש) + +**מחלקה AsyncSocketClient:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**תכונות עיקריות:** +תמיכה מובנית ב-async/await +יעיל עבור יישומים אסינכרוניים (FastAPI, aiohttp) +ללא חסימת תהליכים +ממשק זהה לגרסה הסינכרונית +AsyncIterator עבור סטרימינג + +#### 4. לקוח לפעולות סינכרוניות מרובות + +מודול: `trustgraph-base/trustgraph/api/bulk_client.py` (חדש) + +**מחלקה BulkClient:** + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**תכונות עיקריות:** +מבוסס על איטרטור לשימוש קבוע בזיכרון +חיבורי WebSocket ייעודיים לכל פעולה +מעקב אחר התקדמות (אופציונלי, באמצעות פונקציית החזרה) +טיפול בשגיאות עם דיווח על הצלחה חלקית + +#### 5. לקוח לפעולות אסינכרוניות מרובות + +מודול: `trustgraph-base/trustgraph/api/async_bulk_client.py` (חדש) + +**מחלקה: AsyncBulkClient**: + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**תכונות עיקריות:** +מבוסס על AsyncIterator לשימוש קבוע בזיכרון +יעיל עבור יישומים אסינכרוניים +תמיכה מובנית ב-async/await +אותו ממשק כמו הגרסה הסינכרונית + +#### 6. ממשק REST Flow (סינכרוני - ללא שינוי) + +מודול: `trustgraph-base/trustgraph/api/flow.py` + +ממשק REST Flow נשאר **ללא שינוי מוחלט** לצורך תאימות לאחור. כל השיטות הקיימות ממשיכות לעבוד: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, וכו'. +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, וכו'. +כל החתימות וטיפוסי ההחזרה הקיימים נשמרו + +**חדש:** הוספת `graph_embeddings_query()` ל-REST FlowInstance לצורך התאמה: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. ממשק REST אסינכרוני + +מודול: `trustgraph-base/trustgraph/api/async_flow.py` (חדש) + +**מחלקות AsyncFlow ו-AsyncFlowInstance**: + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**תכונות עיקריות:** +שימוש ב-HTTP אסינכרוני באמצעות `aiohttp` או `httpx` +אותם חתימות מתודות כמו ב-API REST סינכרוני +ללא סטרימינג (יש להשתמש ב-`async_socket()` עבור סטרימינג) +יעיל עבור יישומים אסינכרוניים + +#### 8. ממשק API למדדים + +מודול: `trustgraph-base/trustgraph/api/metrics.py` (חדש) + +**מדדים סינכרוניים:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**מדדי אסינכרוניים:** + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. סוגים משופרים + +מודול: `trustgraph-base/trustgraph/api/types.py` (ערוך) + +**סוגים חדשים**: + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. ממשק API למדדים + +מודול: `trustgraph-base/trustgraph/api/metrics.py` (חדש) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### גישת יישום + +#### שלב 1: שיפורי API מרכזיים (שבוע 1) + +1. הוספת שיטות `socket()`, `bulk()` ו-`metrics()` למחלקה `Api` +2. יישום אתחול עצלני עבור לקוחות WebSocket ו-bulk +3. הוספת תמיכה במנהל הקשר (`__enter__`, `__exit__`) +4. הוספת שיטה `close()` לניקוי +5. הוספת בדיקות יחידה לשיפורי מחלקת API +6. אימות תאימות לאחור + +**תאימות לאחור**: אין שינויים משמעותיים. רק שיטות חדשות. + +#### שלב 2: לקוח WebSocket (שבועות 2-3) + +1. יישום מחלקה `SocketClient` עם ניהול חיבור +2. יישום `SocketFlowInstance` עם אותם חתימות שיטה כמו `FlowInstance` +3. הוספת תמיכה בריבוי בקשות (עד 15 מקבילים) +4. הוספת ניתוח תגובה בסטרימינג עבור סוגי חלקים שונים +5. הוספת לוגיקת חיבור מחדש אוטומטית +6. הוספת בדיקות יחידה ושילוב +7. תיעוד דפוסי שימוש ב-WebSocket + +**תאימות לאחור**: ממשק חדש בלבד. ללא השפעה על קוד קיים. + +#### שלב 3: תמיכה בסטרימינג (שבועות 3-4) + +1. הוספת מחלקות סוגי חלקים בסטרימינג (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. יישום ניתוח תגובה בסטרימינג ב-`SocketClient` +3. הוספת פרמטר סטרימינג לכל שיטות LLM ב-`SocketFlowInstance` +4. טיפול במקרים שגויים במהלך סטרימינג +5. הוספת בדיקות יחידה ושילוב עבור סטרימינג +6. הוספת דוגמאות סטרימינג לתיעוד + +**תאימות לאחור**: ממשק חדש בלבד. API REST קיים ללא שינוי. + +#### שלב 4: פעולות Bulk (שבועות 4-5) + +1. יישום מחלקה `BulkClient` +2. הוספת שיטות ייבוא/ייצוא bulk עבור משולשות, הטבעות, הקשרים, אובייקטים +3. יישום עיבוד מבוסס איטרטור עבור זיכרון קבוע +4. הוספת מעקב התקדמות (callback אופציונלי) +5. הוספת טיפול בשגיאות עם דיווח על הצלחה חלקית +6. הוספת בדיקות יחידה ושילוב +7. הוספת דוגמאות לפעולות bulk + +**תאימות לאחור**: ממשק חדש בלבד. ללא השפעה על קוד קיים. + +#### שלב 5: התאמה וליטוש (שבוע 5) + +1. הוספת `graph_embeddings_query()` ל-REST `FlowInstance` +2. יישום מחלקה `Metrics` +3. הוספת בדיקות שילוב מקיפות +4. ביצועי benchmark +5. עדכון כל התיעוד +6. יצירת מדריך מעבר + +**תאימות לאחור**: שיטות חדשות בלבד. ללא השפעה על קוד קיים. + +### מודלים של נתונים + +#### בחירת ממשק + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### סוגי תגובות סטרימינג + +**סטרימינג של סוכן:** + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**סטרימינג RAG**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**פעולות מרובות (סינכרוניות):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**פעולות מרובות (אסינכרוניות):** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**דוגמה ל-REST אסינכרוני:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**דוגמה לסטרימינג WebSocket אסינכרוני:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### ממשקי API + +#### ממשקי API חדשים + +1. **מחלקה ראשית של ממשק API**: + **סינכרוני**: + `Api.socket()` - קבלת לקוח WebSocket סינכרוני + `Api.bulk()` - קבלת לקוח פעולות אצווה סינכרוני + `Api.metrics()` - קבלת לקוח מדדים סינכרוני + `Api.close()` - סגירת כל החיבורים הסינכרוניים + תמיכה במנהל הקשר (context manager) (`__enter__`, `__exit__`) + **אסינכרוני**: + `Api.async_flow()` - קבלת לקוח REST flow אסינכרוני + `Api.async_socket()` - קבלת לקוח WebSocket אסינכרוני + `Api.async_bulk()` - קבלת לקוח פעולות אצווה אסינכרוני + `Api.async_metrics()` - קבלת לקוח מדדים אסינכרוני + `Api.aclose()` - סגירת כל החיבורים האסינכרוניים + תמיכה במנהל הקשר אסינכרוני (`__aenter__`, `__aexit__`) + +2. **לקוח WebSocket סינכרוני**: + `SocketClient.flow(flow_id)` - קבלת מופע WebSocket + `SocketFlowInstance.agent(..., streaming: bool = False)` - סוכן עם סטרימינג אופציונלי + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - השלמת טקסט עם סטרימינג אופציונלי + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG עם סטרימינג אופציונלי + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG עם סטרימינג אופציונלי + `SocketFlowInstance.prompt(..., streaming: bool = False)` - הנחיה (prompt) עם סטרימינג אופציונלי + `SocketFlowInstance.graph_embeddings_query()` - שאילתת הטמעות גרף + כל שיטות FlowInstance אחרות עם חתימות זהות + +3. **לקוח WebSocket אסינכרוני**: + `AsyncSocketClient.flow(flow_id)` - קבלת מופע WebSocket אסינכרוני + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - סוכן אסינכרוני עם סטרימינג אופציונלי + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - השלמת טקסט אסינכרונית עם סטרימינג אופציונלי + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG אסינכרוני עם סטרימינג אופציונלי + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG אסינכרוני עם סטרימינג אופציונלי + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - הנחיה (prompt) אסינכרונית עם סטרימינג אופציונלי + `AsyncSocketFlowInstance.graph_embeddings_query()` - שאילתת הטמעות גרף אסינכרונית + כל שיטות FlowInstance אחרות כגרסאות אסינכרוניות + +4. **לקוח פעולות אצווה סינכרוני**: + `BulkClient.import_triples(flow, triples)` - ייבוא אצווה של משולשות + `BulkClient.export_triples(flow)` - ייצוא אצווה של משולשות + `BulkClient.import_graph_embeddings(flow, embeddings)` - ייבוא אצווה של הטמעות גרף + `BulkClient.export_graph_embeddings(flow)` - ייצוא אצווה של הטמעות גרף + `BulkClient.import_document_embeddings(flow, embeddings)` - ייבוא אצווה של הטמעות מסמכים + `BulkClient.export_document_embeddings(flow)` - ייצוא אצווה של הטמעות מסמכים + `BulkClient.import_entity_contexts(flow, contexts)` - ייבוא אצווה של הקשרים של ישויות + `BulkClient.export_entity_contexts(flow)` - ייצוא אצווה של הקשרים של ישויות + `BulkClient.import_objects(flow, objects)` - ייבוא אצווה של אובייקטים + +5. **לקוח פעולות אצווה אסינכרוני**: + `AsyncBulkClient.import_triples(flow, triples)` - ייבוא אצווה אסינכרוני של משולשות + `AsyncBulkClient.export_triples(flow)` - ייצוא אצווה אסינכרוני של משולשות + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - ייבוא אצווה אסינכרוני של הטמעות גרף + `AsyncBulkClient.export_graph_embeddings(flow)` - ייצוא אצווה אסינכרוני של הטמעות גרף + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - ייבוא אצווה אסינכרוני של הטמעות מסמכים + `AsyncBulkClient.export_document_embeddings(flow)` - ייצוא אצווה אסינכרוני של הטמעות מסמכים + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - ייבוא אצווה אסינכרוני של הקשרים של ישויות + `AsyncBulkClient.export_entity_contexts(flow)` - ייצוא אצווה אסינכרוני של הקשרים של ישויות + `AsyncBulkClient.import_objects(flow, objects)` - ייבוא אצווה אסינכרוני של אובייקטים + +6. **לקוח REST Flow אסינכרוני**: + `AsyncFlow.list()` - רשימת כל ה-flows (אסינכרוני) + `AsyncFlow.get(id)` - קבלת הגדרת flow (אסינכרוני) + `AsyncFlow.start(...)` - התחלת flow (אסינכרוני) + `AsyncFlow.stop(id)` - עצירת flow (אסינכרוני) + `AsyncFlow.id(flow_id)` - קבלת מופע flow (אסינכרוני) + `AsyncFlowInstance.agent(...)` - הרצת סוכן (אסינכרוני) + `AsyncFlowInstance.text_completion(...)` - השלמת טקסט (אסינכרונית) + `AsyncFlowInstance.graph_rag(...)` - Graph RAG (אסינכרוני) + כל שיטות FlowInstance אחרות כגרסאות אסינכרוניות + +7. **לקוחות מדדים**: + `Metrics.get()` - מדדי Prometheus סינכרוניים + `AsyncMetrics.get()` - מדדי Prometheus אסינכרוניים + +8. **שיפור ממשק API של REST Flow**: + `FlowInstance.graph_embeddings_query()` - שאילתת הטמעות גרף (תאימות תכונות סינכרונית) + `AsyncFlowInstance.graph_embeddings_query()` - שאילתת הטמעות גרף (תאימות תכונות אסינכרונית) + +#### ממשקי API שעברו שינוי + +1. **מבנה (Constructor)** (שיפור קל): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + הוסף פרמטר `token` (אופציונלי, לצורך אימות) + אם `None` (ברירת מחדל): לא נעשה שימוש באימות + אם צוין: משמש כטוקן bearer עבור REST (`Authorization: Bearer `), כפרמטר שאילתה עבור WebSocket (`?token=`) + לא בוצעו שינויים אחרים - תואם לאחור לחלוטין + +2. **ללא שינויים שמשנים את הפעולה**: + כל שיטות ה-API של REST הקיימות לא שונו + כל החתימות הקיימות נשמרו + כל סוגי ההחזרה הקיימים נשמרו + +### פרטי יישום + +#### טיפול בשגיאות + +**שגיאות חיבור WebSocket**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**מעבר חלק:** +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**שגיאות סטרימינג חלקיות**: +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### ניהול משאבים + +**תמיכה במנהל הקשר (Context Manager):** +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### תִּקְשׁוּר וּמְקַרְבֵּי מִקְבֵּל + +**בְּטִיחוּת מִתְקַרְבֵּי מִקְבֵּל**: +כל מופע של `Api` שומר על חיבור משלו. +תעבורת WebSocket משתמשת במנעולים עבור ריבוב בקשות בטוח לחוטים. +מספר חוטים יכולים לשתף מופע של `Api` בצורה בטוחה. +איטרטורים של סטרימינג אינם בטוחים לחוטים (יש לצרוך מהחוט היחיד). + +**תמיכה אסינכרונית** (שיקול עתידי): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## שיקולי אבטחה + +### אימות + +**פרמטר טוקן**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**שינוע REST**: +טוקן נושא דרך כותרת `Authorization` +מיושם אוטומטית על כל בקשות REST +פורמט: `Authorization: Bearer ` + +**שינוע WebSocket**: +טוקן דרך פרמטר שאילתה המצורף לכתובת ה-WebSocket +מיושם אוטומטית במהלך יצירת החיבור +פורמט: `ws://localhost:8088/api/v1/socket?token=` + +**יישום**: +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**דוגמה:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### תקשורת מאובטחת + +תמיכה הן בפרוטוקול WS (WebSocket) והן בפרוטוקול WSS (WebSocket Secure). +אימות תעודות TLS עבור חיבורי WSS. +אפשרות לביטול אימות תעודות לצורך פיתוח (עם אזהרה). + +### אימות קלט + +אימות סכימות כתובות URL (http, https, ws, wss). +אימות ערכי פרמטרים של העברת נתונים. +אימות שילובים של פרמטרים של העברה רציפה. +אימות סוגי נתונים לייבוא בכמות גדולה. + +## שיקולי ביצועים + +### שיפורי השהייה + +**פעולות LLM רציפות (Streaming)**: +**זמן עד לקבלת הטוקן הראשון**: ~500ms (לעומת ~30 שניות ללא העברה רציפה). +**שיפור**: ביצועים תפיסיים מהירים פי 60. +**מתאים ל**: סוכן, Graph RAG, Document RAG, השלמת טקסט, הנחיה. + +**חיבורים קבועים**: +**תקורה של חיבור**: מבוטלת עבור בקשות עוקבות. +**הדחיסה הראשונית של WebSocket**: עלות חד-פעמית (~100ms). +**מתאים ל**: כל הפעולות בעת שימוש בפרוטוקול WebSocket. + +### שיפורי תפוקה + +**פעולות בכמות גדולה**: +**ייבוא משולשות**: ~10,000 משולשות/שנייה (לעומת ~100/שנייה עם REST עבור כל פריט). +**ייבוא הטמעות (Embeddings)**: ~5,000 הטמעות/שנייה (לעומת ~50/שנייה עם REST עבור כל פריט). +**שיפור**: תפוקה גבוהה פי 100 עבור פעולות בכמות גדולה. + +**ריבוב בקשות (Request Multiplexing)**: +**בקשות מקבילות**: עד 15 בקשות בו-זמנית על גבי חיבור יחיד. +**שימוש חוזר בחיבור**: אין תקורה של חיבור עבור פעולות מקבילות. + +### שיקולי זיכרון + +**תגובות רציפות (Streaming)**: +שימוש קבוע בזיכרון (עיבוד מקטעים כשהם מגיעים). +אין אחסון זמני של תגובה שלמה. +מתאים לפלטים ארוכים מאוד (>1MB). + +**פעולות בכמות גדולה**: +עיבוד מבוסס איטרטור (שימוש קבוע בזיכרון). +אין טעינה של קבוצת נתונים שלמה לתוך הזיכרון. +מתאים לקבוצות נתונים עם מיליוני פריטים. + +### מדדי ביצוע (צפויים) + +| פעולה | REST (קיים) | WebSocket (העברה רציפה) | שיפור | +|-----------|----------------|----------------------|-------------| +| סוכן (זמן עד לקבלת הטוקן הראשון) | 30 שניות | 0.5 שניות | 60x | +| Graph RAG (זמן עד לקבלת הטוקן הראשון) | 25 שניות | 0.5 שניות | 50x | +| ייבוא 10K משולשות | 100 שניות | 1 שניה | 100x | +| ייבוא 1M משולשות | 10,000 שניות (2.7 שעות) | 100 שניות (1.6 דקות) | 100x | +| 10 בקשות קטנות במקביל | 5 שניות (רציף) | 0.5 שניות (מקביל) | 10x | + +## אסטרטגיית בדיקות + +### בדיקות יחידה + +**שכבת התעבורה** (`test_transport.py`): +בדיקת בקשה/תגובה של פרוטוקול REST +בדיקת חיבור פרוטוקול WebSocket +בדיקת חיבור מחדש של פרוטוקול WebSocket +בדיקת ריבוי בקשות +בדיקת ניתוח תגובה בסטרימינג +שרת WebSocket מדמה לבדיקות דטרמיניסטיות + +**שיטות API** (`test_flow.py`, `test_library.py`, וכו'): +בדיקת שיטות חדשות עם שכבת תעבורה מדמה +בדיקת טיפול בפרמטרים בסטרימינג +בדיקת איטרטורים לפעולות אצווה +בדיקת טיפול בשגיאות + +**טיפוסים** (`test_types.py`): +בדיקת טיפוסי סטרימינג חדשים +בדיקת סריאליזציה/דה-סריאליזציה של טיפוסים + +### בדיקות אינטגרציה + +**REST מקצה לקצה** (`test_integration_rest.py`): +בדיקת כל הפעולות מול שער אמיתי (מצב REST) +אימות תאימות לאחור +בדיקת תנאי שגיאה + +**WebSocket מקצה לקצה** (`test_integration_websocket.py`): +בדיקת כל הפעולות מול שער אמיתי (מצב WebSocket) +בדיקת פעולות סטרימינג +בדיקת פעולות אצווה +בדיקת בקשות מקבילות +בדיקת התאוששות חיבור + +**שירותי סטרימינג** (`test_streaming_integration.py`): +בדיקת סטרימינג של סוכן (מחשבות, תצפיות, תשובות) +בדיקת סטרימינג של RAG (חלקים מצטברים) +בדיקת סטרימינג של השלמת טקסט (טוקן אחר טוקן) +בדיקת סטרימינג של הנחיה +בדיקת טיפול בשגיאות במהלך סטרימינג + +**פעולות אצווה** (`test_bulk_integration.py`): +בדיקת ייבוא/ייצוא אצווה של טריפלטים (1K, 10K, 100K פריטים) +בדיקת ייבוא/ייצוא אצווה של הטמעות +בדיקת שימוש בזיכרון במהלך פעולות אצווה +בדיקת מעקב אחר התקדמות + +### בדיקות ביצועים + +**מדדי השהייה** (`test_performance_latency.py`): +מדידת זמן עד לטוקן הראשון (סטרימינג לעומת לא סטרימינג) +מדידת תקורה של חיבור (REST לעומת WebSocket) +השוואה למדדים צפויים + +**מדדי תפוקה** (`test_performance_throughput.py`): +מדידת תפוקת ייבוא אצווה +מדידת יעילות ריבוי בקשות +השוואה למדדים צפויים + +### בדיקות תאימות + +**תאימות לאחור** (`test_backward_compatibility.py`): +הרצת סט בדיקות קיים מול API שעבר שינוי מבני +אימות היעדר שינויים שוברים +בדיקת נתיב מעבר עבור תבניות נפוצות + +## תוכנית מעבר + +### שלב 1: מעבר שקוף (ברירת מחדל) + +**לא נדרשים שינויי קוד**. קוד קיים ממשיך לעבוד: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### שלב 2: הפעלת סטרימינג (פשוט) + +**השתמשו בממשק `api.socket()`** כדי להפעיל סטרימינג: + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**נקודות עיקריות:** +אותה כתובת URL עבור REST ו-WebSocket +אותם חתימות מתודות (מעבר קל) +פשוט הוסיפו את `.socket()` ו-`streaming=True` + +### שלב 3: פעולות בכמות גדולה (יכולת חדשה) + +**השתמשו בממשק `api.bulk()`** עבור מערכי נתונים גדולים: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### עדכוני תיעוד + +1. **README.md**: הוספת דוגמאות סטרימינג ו-WebSocket +2. **הפניה ל-API**: תיעוד של כל השיטות והפרמטרים החדשים +3. **מדריך מעבר**: מדריך שלב אחר שלב להפעלת סטרימינג +4. **דוגמאות**: הוספת סקריפטים לדוגמה לתבניות נפוצות +5. **מדריך ביצועים**: תיעוד של שיפורי ביצועים צפויים + +### מדיניות הפסקה + +**ללא הפסקות**. כל ה-APIs הקיימים נתמכים. זוהי שיפור משמעותי בלבד. + +## ציר זמן + +### שבוע 1: יסודות +שכבת הפשטה של העברת נתונים +שיפור קוד REST קיים +בדיקות יחידה לשכבת העברת הנתונים +אימות תאימות לאחור + +### שבוע 2: העברת WebSocket +יישום העברת WebSocket +ניהול חיבורים וחיבור מחדש +ריבוב בקשות +בדיקות יחידה ושילוב + +### שבוע 3: תמיכה בסטרימינג +הוספת פרמטר סטרימינג לשיטות LLM +יישום ניתוח תגובות סטרימינג +הוספת סוגי חלקי סטרימינג +בדיקות שילוב סטרימינג + +### שבוע 4: פעולות מרובות +הוספת שיטות ייבוא/ייצוא מרובות +יישום פעולות מבוססות איטרטור +בדיקות ביצועים +בדיקות שילוב לפעולות מרובות + +### שבוע 5: התאמה ותיעוד +הוספת שאילתת הטמעות גרף +הוספת API למדדים +תיעוד מקיף +מדריך מעבר +גרסה מועמדת + +### שבוע 6: שחרור +בדיקות שילוב סופיות +מדידת ביצועים +תיעוד לשחרור +הודעה לקהילה + +**משך כולל**: 6 שבועות + +## שאלות פתוחות + +### שאלות עיצוב API + +1. **תמיכה אסינכרונית**: ✅ **נפתר** - תמיכה אסינכרונית מלאה כלולה בשחרור הראשוני + לכל הממשקים יש גרסאות אסינכרוניות: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + מספק סימטריה מלאה בין ממשקי סנכרון ואסינכרון + חיוני למסגרות אסינכרוניות מודרניות (FastAPI, aiohttp) + +2. **מעקב אחר התקדמות**: האם פעולות מרובות צריכות לתמוך בפונקציות החזרה של התקדמות? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **המלצה**: להוסיף בשלב 2. לא קריטי לשחרור הראשוני. + +3. **זמן המתנה (Timeout) לסטרימינג**: איך עלינו לטפל בזמני המתנה עבור פעולות סטרימינג? + **המלצה**: להשתמש באותו זמן המתנה כמו בפעולות שאינן סטרימינג, אך לאפס אותו בכל פעם שמתקבל חלק. + +4. **ביצוע אחסון של חלקים (Chunk Buffering)**: האם עלינו לאחסן חלקים או להחזיר מידע מיד? + **המלצה**: להחזיר מיד כדי להשיג השהייה נמוכה ביותר. + +5. **שירותים גלובליים דרך WebSocket**: האם `api.socket()` צריך לתמוך בשירותים גלובליים (ספרייה, ידע, אוסף, תצורה) או רק בשירותים המוגבלים ל-flow? + **המלצה**: להתחיל רק עם שירותים המוגבלים ל-flow (שם הסטרימינג חשוב). להוסיף שירותים גלובליים במידת הצורך בשלב 2. + +### שאלות יישום + +1. **ספריית WebSocket**: האם עלינו להשתמש ב-`websockets`, `websocket-client`, או `aiohttp`? + **המלצה**: `websockets` (אסינכרוני, בשל, מתוחזק היטב). לעטוף בממשק סינכרוני באמצעות `asyncio.run()`. + +2. **ניהול חיבורים (Connection Pooling)**: האם עלינו לתמוך במספר מופעים מקבילים של `Api` המשתפים בריכת חיבורים? + **המלצה**: לדחות לשלב 2. לכל מופע של `Api` יהיו חיבורים משלו בתחילה. + +3. **שימוש חוזר בחיבורים**: האם `SocketClient` ו-`BulkClient` צריכים לשתף את אותו חיבור WebSocket, או להשתמש בחיבורים נפרדים? + **המלצה**: חיבורים נפרדים. יישום פשוט יותר, הפרדה ברורה יותר של נושאים. + +4. **חיבור עצלני לעומת חיבור מוקדם**: האם החיבור WebSocket צריך להיות מוקם ב-`api.socket()` או בבקשה הראשונה? + **המלצה**: עצלני (בבקשה הראשונה). נמנע מעלות נוספת של חיבור אם המשתמש משתמש רק בשיטות REST. + +### שאלות בדיקה + +1. **שער מדמה (Mock Gateway)**: האם עלינו ליצור שער מדמה קל משקל לבדיקות, או לבדוק מול שער אמיתי? + **המלצה**: שניהם. להשתמש במדמים לבדיקות יחידה, ושער אמיתי לבדיקות אינטגרציה. + +2. **בדיקות רגרסיה לביצועים**: האם עלינו להוסיף בדיקות רגרסיה אוטומטיות לביצועים ל-CI? + **המלצה**: כן, אך עם ספים נדיבים כדי להתחשב בשונות בסביבת ה-CI. + +## הפניות + +### מפרטי טכנולוגיה קשורים +`docs/tech-specs/streaming-llm-responses.md` - יישום סטרימינג בשער +`docs/tech-specs/rag-streaming-support.md` - תמיכה בסטרימינג של RAG + +### קבצי יישום +`trustgraph-base/trustgraph/api/` - קוד מקור של API בפייתון +`trustgraph-flow/trustgraph/gateway/` - קוד מקור של השער +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - יישום התייחסות של מולטיפלקסר WebSocket + +### תיעוד +`docs/apiSpecification.md` - הפניה מלאה ל-API +`docs/api-status-summary.md` - סיכום סטטוס API +`README.websocket` - תיעוד פרוטוקול WebSocket +`STREAMING-IMPLEMENTATION-NOTES.txt` - הערות על יישום סטרימינג + +### ספריות חיצוניות +`websockets` - ספריית WebSocket בפייתון (https://websockets.readthedocs.io/) +`requests` - ספריית HTTP בפייתון (קיימת) diff --git a/docs/tech-specs/python-api-refactor.hi.md b/docs/tech-specs/python-api-refactor.hi.md new file mode 100644 index 00000000..299d2efa --- /dev/null +++ b/docs/tech-specs/python-api-refactor.hi.md @@ -0,0 +1,1516 @@ +--- +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. **स्ट्रीमिंग एलएलएम इंटरैक्शन**: एलएलएम प्रतिक्रियाओं (एजेंट, ग्राफ आरएजी, दस्तावेज़ आरएजी, टेक्स्ट कंप्लीशन, प्रॉम्प्ट) का रीयल-टाइम स्ट्रीमिंग सक्षम करें, जिसमें ~60 गुना कम विलंबता हो (पहले टोकन के लिए 500ms बनाम 30s)। +2. **बल्क डेटा ऑपरेशन**: बड़े पैमाने पर नॉलेज ग्राफ प्रबंधन के लिए ट्रिपल, ग्राफ एम्बेडिंग और दस्तावेज़ एम्बेडिंग के कुशल बल्क आयात/निर्यात का समर्थन करें। +3. **सुविधा समानता**: सुनिश्चित करें कि प्रत्येक एपीआई गेटवे एंडपॉइंट के लिए एक संबंधित पायथन एपीआई विधि है, जिसमें ग्राफ एम्बेडिंग क्वेरी शामिल है। +4. **लगातार कनेक्शन**: मल्टीप्लेक्स अनुरोधों और कम कनेक्शन ओवरहेड के लिए वेबसॉकेट-आधारित संचार को सक्षम करें। + +## लक्ष्य + +**सुविधा समानता**: प्रत्येक गेटवे एपीआई सेवा के लिए एक संबंधित पायथन एपीआई विधि है। +**स्ट्रीमिंग समर्थन**: सभी स्ट्रीमिंग-सक्षम सेवाओं (एजेंट, आरएजी, टेक्स्ट कंप्लीशन, प्रॉम्प्ट) पायथन एपीआई में स्ट्रीमिंग का समर्थन करते हैं। +**वेबसॉकेट ट्रांसपोर्ट**: लगातार कनेक्शन और मल्टीप्लेक्सिंग के लिए वैकल्पिक वेबसॉकेट ट्रांसपोर्ट लेयर जोड़ें। +**बल्क ऑपरेशन**: ट्रिपल, ग्राफ एम्बेडिंग और दस्तावेज़ एम्बेडिंग के लिए कुशल बल्क आयात/निर्यात जोड़ें। +**पूर्ण एसिंक समर्थन**: सभी इंटरफेस (REST, वेबसॉकेट, बल्क ऑपरेशन, मेट्रिक्स) के लिए पूर्ण एसिंक/अवेट कार्यान्वयन। +**पिछला संगतता**: मौजूदा कोड बिना किसी संशोधन के काम करना जारी रखता है। +**टाइप सुरक्षा**: डेटाक्लासेस और टाइप हिंट के साथ टाइप-सुरक्षित इंटरफेस बनाए रखें। +**प्रगतिशील संवर्द्धन**: स्ट्रीमिंग और एसिंक स्पष्ट इंटरफेस चयन के माध्यम से वैकल्पिक हैं। +**प्रदर्शन**: स्ट्रीमिंग ऑपरेशनों के लिए 60 गुना विलंबता में सुधार प्राप्त करें। +**आधुनिक पायथन**: अधिकतम लचीलेपन के लिए सिंक और एसिंक दोनों प्रतिमानों के लिए समर्थन। + +## पृष्ठभूमि + +### वर्तमान स्थिति + +पायथन एपीआई (`trustgraph-base/trustgraph/api/`) एक REST-ओनली क्लाइंट लाइब्रेरी है जिसमें निम्नलिखित मॉड्यूल हैं: + +`flow.py`: फ्लो प्रबंधन और फ्लो-स्कोप सेवाओं (50 विधियाँ) +`library.py`: दस्तावेज़ लाइब्रेरी ऑपरेशन (9 विधियाँ) +`knowledge.py`: केजी कोर प्रबंधन (4 विधियाँ) +`collection.py`: संग्रह मेटाडेटा (3 विधियाँ) +`config.py`: कॉन्फ़िगरेशन प्रबंधन (6 विधियाँ) +`types.py`: डेटा टाइप परिभाषाएँ (5 डेटाक्लास) + +**कुल ऑपरेशन**: 50/59 (85% कवरेज) + +### वर्तमान सीमाएँ + +**गायब ऑपरेशन**: +ग्राफ एम्बेडिंग क्वेरी (ग्राफ संस्थाओं पर सिमेंटिक खोज) +ट्रिपल, ग्राफ एम्बेडिंग, दस्तावेज़ एम्बेडिंग, एंटिटी कॉन्टेक्स्ट, ऑब्जेक्ट के लिए बल्क आयात/निर्यात +मेट्रिक्स एंडपॉइंट + +**गायब क्षमताएँ**: +एलएलएम सेवाओं के लिए स्ट्रीमिंग समर्थन +वेबसॉकेट ट्रांसपोर्ट +मल्टीप्लेक्स समवर्ती अनुरोध +लगातार कनेक्शन + +**प्रदर्शन संबंधी समस्याएँ**: +एलएलएम इंटरैक्शन के लिए उच्च विलंबता (~30s समय-से-पहला-टोकन) +अक्षम बल्क डेटा ट्रांसफर (प्रति आइटम REST अनुरोध) +कई क्रमिक ऑपरेशनों के लिए कनेक्शन ओवरहेड + +**उपयोगकर्ता अनुभव संबंधी समस्याएँ**: +एलएलएम पीढ़ी के दौरान कोई रीयल-टाइम प्रतिक्रिया नहीं +लंबे समय तक चलने वाले एलएलएम ऑपरेशनों को रद्द नहीं किया जा सकता है +बल्क ऑपरेशनों के लिए खराब स्केलेबिलिटी + +### प्रभाव + +नवंबर 2024 में गेटवे एपीआई में स्ट्रीमिंग संवर्द्धन ने एलएलएम इंटरैक्शन के लिए 60 गुना विलंबता में सुधार (पहले टोकन के लिए 500ms बनाम 30s) प्रदान किया, लेकिन पायथन एपीआई उपयोगकर्ता इस क्षमता का लाभ नहीं उठा सकते हैं। इससे पायथन और गैर-पायथन उपयोगकर्ताओं के बीच एक महत्वपूर्ण अनुभव अंतर पैदा होता है। + +## तकनीकी डिजाइन + +### वास्तुकला + +रिफैक्टर किए गए पायथन एपीआई विभिन्न संचार पैटर्न के लिए अलग-अलग ऑब्जेक्ट के साथ एक **मॉड्यूलर इंटरफेस दृष्टिकोण** का उपयोग करता है। सभी इंटरफेस सिंक्रोनस और एसिंक्रोनस दोनों रूपों में उपलब्ध हैं: + +1. **REST इंटरफेस** (मौजूदा, संवर्धित) + **सिंक**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()` + **एसिंक**: `api.async_flow()` + सिंक्रोनस/एसिंक्रोनस अनुरोध/प्रतिक्रिया + सरल कनेक्शन मॉडल + पिछड़े संगतता के लिए डिफ़ॉल्ट + +2. **वेबसॉकेट इंटरफेस** (नया) + **सिंक**: `api.socket()` + **एसिंक**: `api.async_socket()` + लगातार कनेक्शन + मल्टीप्लेक्स अनुरोध + स्ट्रीमिंग समर्थन + जहां कार्यक्षमता ओवरलैप होती है, वहां REST के समान विधि हस्ताक्षर + +3. **बल्क ऑपरेशन इंटरफेस** (नया) + **सिंक**: `api.bulk()` + **एसिंक**: `api.async_bulk()` + दक्षता के लिए वेबसॉकेट-आधारित + आयात/निर्यात के लिए Iterator/AsyncIterator-आधारित + बड़े डेटासेट को संभालता है + +4. **मेट्रिक्स इंटरफेस** (नया) + **सिंक**: `api.metrics()` + **एसिंक**: `api.async_metrics()` + प्रोमेथियस मेट्रिक्स एक्सेस + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**मुख्य डिज़ाइन सिद्धांत:** +**सभी इंटरफेस के लिए समान URL:** `Api(url="http://localhost:8088/")` सभी के लिए काम करता है। +**सिंक/एसिंक्रोनस समरूपता:** प्रत्येक इंटरफेस में सिंक और एसिंक्रोनस दोनों संस्करण होते हैं, जिनमें समान मेथड सिग्नेचर होते हैं। +**समान सिग्नेचर:** जहां कार्यक्षमता ओवरलैप होती है, REST और WebSocket, सिंक और एसिंक्रोनस के बीच मेथड सिग्नेचर समान होते हैं। +**प्रगतिशील संवर्द्धन:** आवश्यकताओं के आधार पर इंटरफेस चुनें (सरल कार्यों के लिए REST, स्ट्रीमिंग के लिए WebSocket, बड़े डेटासेट के लिए बल्क, आधुनिक फ्रेमवर्क के लिए एसिंक्रोनस)। +**स्पष्ट इरादा:** `api.socket()` WebSocket को दर्शाता है, `api.async_socket()` एसिंक्रोनस WebSocket को दर्शाता है। +**पिछड़े संगत:** मौजूदा कोड अपरिवर्तित रहता है। + +### घटक + +#### 1. कोर एपीआई क्लास (संशोधित) + +मॉड्यूल: `trustgraph-base/trustgraph/api/api.py` + +**संवर्धित एपीआई क्लास:** + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. सिंक्रोनस वेबसॉकेट क्लाइंट + +मॉड्यूल: `trustgraph-base/trustgraph/api/socket_client.py` (नया) + +**SocketClient क्लास:** + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**मुख्य विशेषताएं:** +आलसी कनेक्शन (केवल पहले अनुरोध भेजे जाने पर कनेक्ट होता है) +अनुरोध मल्टीप्लेक्सिंग (एक साथ 15 तक) +डिस्कनेक्ट होने पर स्वचालित पुनः कनेक्शन +स्ट्रीमिंग प्रतिक्रिया पार्सिंग +थ्रेड-सुरक्षित संचालन +एसिंक्रोनस वेबसॉकेट लाइब्रेरी के चारों ओर सिंक्रोनस रैपर + +#### 3. एसिंक्रोनस वेबसॉकेट क्लाइंट + +मॉड्यूल: `trustgraph-base/trustgraph/api/async_socket_client.py` (नया) + +**AsyncSocketClient क्लास:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**मुख्य विशेषताएं:** +मूल एसिंक्रोनस/अवेट समर्थन +एसिंक्रोनस अनुप्रयोगों के लिए कुशल (फास्टएपीआई, एआईओएचटीटीपी) +कोई थ्रेड अवरोधन नहीं +सिंक्रोनस संस्करण के समान इंटरफ़ेस +स्ट्रीमिंग के लिए AsyncIterator + +#### 4. सिंक्रोनस बल्क ऑपरेशंस क्लाइंट + +मॉड्यूल: `trustgraph-base/trustgraph/api/bulk_client.py` (नया) + +**BulkClient क्लास:** + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**मुख्य विशेषताएं:** +निरंतर मेमोरी उपयोग के लिए इटरेटर-आधारित। +प्रत्येक ऑपरेशन के लिए समर्पित वेबसॉकेट कनेक्शन। +प्रगति ट्रैकिंग (वैकल्पिक कॉलबैक)। +आंशिक सफलता रिपोर्टिंग के साथ त्रुटि प्रबंधन। + +#### 5. एसिंक्रोनस बल्क ऑपरेशंस क्लाइंट + +मॉड्यूल: `trustgraph-base/trustgraph/api/async_bulk_client.py` (नया) + +**AsyncBulkClient क्लास:** + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**मुख्य विशेषताएं:** +निरंतर मेमोरी उपयोग के लिए AsyncIterator-आधारित। +एसिंक्रोनस अनुप्रयोगों के लिए कुशल। +मूल एसिंक्रोनस/अवेट समर्थन। +सिंक्रोनस संस्करण के समान इंटरफ़ेस। + +#### 6. REST फ्लो एपीआई (सिंक्रोनस - अपरिवर्तित) + +मॉड्यूल: `trustgraph-base/trustgraph/api/flow.py` + +REST फ्लो एपीआई पिछली अनुकूलता के लिए **पूरी तरह से अपरिवर्तित** रहता है। सभी मौजूदा विधियां काम करना जारी रखती हैं: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, आदि। +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, आदि। +सभी मौजूदा हस्ताक्षर और रिटर्न प्रकार संरक्षित। + +**नया:** सुविधा समानता के लिए REST फ्लोइंस्टेंस में `graph_embeddings_query()` जोड़ें: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. एसिंक्रोनस रेस्ट फ्लो एपीआई + +मॉड्यूल: `trustgraph-base/trustgraph/api/async_flow.py` (नया) + +**AsyncFlow और AsyncFlowInstance क्लास:** + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**मुख्य विशेषताएं:** +देशी एसिंक्रोनस HTTP, `aiohttp` या `httpx` का उपयोग करके। +सिंक्रोनस REST API के समान मेथड सिग्नेचर। +कोई स्ट्रीमिंग नहीं (स्ट्रीमिंग के लिए `async_socket()` का उपयोग करें)। +एसिंक्रोनस अनुप्रयोगों के लिए कुशल। + +#### 8. मेट्रिक्स एपीआई + +मॉड्यूल: `trustgraph-base/trustgraph/api/metrics.py` (नया) + +**सिंक्रोनस मेट्रिक्स:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**अतुल्यकालिक मेट्रिक्स:** + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. उन्नत प्रकार (Enhanced Types) + +मॉड्यूल: `trustgraph-base/trustgraph/api/types.py` (संशोधित) + +**नए प्रकार (New Types):** + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. मेट्रिक्स एपीआई + +मॉड्यूल: `trustgraph-base/trustgraph/api/metrics.py` (नया) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### कार्यान्वयन दृष्टिकोण + +#### चरण 1: मुख्य एपीआई संवर्धन (सप्ताह 1) + +1. `socket()`, `bulk()`, और `metrics()` विधियों को `Api` वर्ग में जोड़ें +2. वेबसॉकेट और बल्क क्लाइंट के लिए लेज़ी इनिशियलाइज़ेशन लागू करें +3. संदर्भ प्रबंधक समर्थन जोड़ें (`__enter__`, `__exit__`) +4. सफाई के लिए `close()` विधि जोड़ें +5. एपीआई वर्ग संवर्धनों के लिए यूनिट परीक्षण जोड़ें +6. पिछड़े अनुकूलता की जांच करें + +**पिछड़ी अनुकूलता**: कोई ब्रेकिंग परिवर्तन नहीं। केवल नई विधियाँ। + +#### चरण 2: वेबसॉकेट क्लाइंट (सप्ताह 2-3) + +1. कनेक्शन प्रबंधन के साथ `SocketClient` वर्ग लागू करें +2. `SocketFlowInstance` को `FlowInstance` के समान विधि हस्ताक्षर के साथ लागू करें +3. अनुरोध मल्टीप्लेक्सिंग समर्थन जोड़ें (अधिकतम 15 समवर्ती) +4. विभिन्न चंक प्रकारों के लिए स्ट्रीमिंग प्रतिक्रिया पार्सिंग जोड़ें +5. स्वचालित पुन: कनेक्शन तर्क जोड़ें +6. यूनिट और एकीकरण परीक्षण जोड़ें +7. वेबसॉकेट उपयोग पैटर्न का दस्तावेजीकरण करें + +**पिछड़ी अनुकूलता**: केवल नया इंटरफ़ेस। मौजूदा कोड पर कोई प्रभाव नहीं। + +#### चरण 3: स्ट्रीमिंग समर्थन (सप्ताह 3-4) + +1. स्ट्रीमिंग चंक प्रकार कक्षाएं जोड़ें (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. `SocketClient` में स्ट्रीमिंग प्रतिक्रिया पार्सिंग लागू करें +3. `SocketFlowInstance` में सभी एलएलएम विधियों में स्ट्रीमिंग पैरामीटर जोड़ें +4. स्ट्रीमिंग के दौरान त्रुटि मामलों को संभालें +5. स्ट्रीमिंग के लिए यूनिट और एकीकरण परीक्षण जोड़ें +6. दस्तावेज़ में स्ट्रीमिंग उदाहरण जोड़ें + +**पिछड़ी अनुकूलता**: केवल नया इंटरफ़ेस। मौजूदा रेस्ट एपीआई अपरिवर्तित। + +#### चरण 4: बल्क ऑपरेशन (सप्ताह 4-5) + +1. `BulkClient` वर्ग लागू करें +2. ट्रिपल, एम्बेडिंग, संदर्भ, ऑब्जेक्ट के लिए बल्क आयात/निर्यात विधियाँ जोड़ें +3. निरंतर मेमोरी के लिए इटरेटर-आधारित प्रसंस्करण लागू करें +4. प्रगति ट्रैकिंग जोड़ें (वैकल्पिक कॉलबैक) +5. आंशिक सफलता रिपोर्टिंग के साथ त्रुटि हैंडलिंग जोड़ें +6. यूनिट और एकीकरण परीक्षण जोड़ें +7. बल्क ऑपरेशन उदाहरण जोड़ें + +**पिछड़ी अनुकूलता**: केवल नया इंटरफ़ेस। मौजूदा कोड पर कोई प्रभाव नहीं। + +#### चरण 5: सुविधा समानता और पॉलिश (सप्ताह 5) + +1. रेस्ट `FlowInstance` में `graph_embeddings_query()` जोड़ें +2. `Metrics` वर्ग लागू करें +3. व्यापक एकीकरण परीक्षण जोड़ें +4. प्रदर्शन बेंचमार्किंग +5. सभी दस्तावेज़ों को अपडेट करें +6. माइग्रेशन गाइड बनाएं + +**पिछड़ी अनुकूलता**: केवल नई विधियाँ। मौजूदा कोड पर कोई प्रभाव नहीं। + +### डेटा मॉडल + +#### इंटरफ़ेस चयन + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### स्ट्रीमिंग प्रतिक्रिया प्रकार + +**एजेंट स्ट्रीमिंग**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**RAG स्ट्रीमिंग**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**बल्क ऑपरेशन (सिंक्रोनस):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**बल्क ऑपरेशन (असिंक्रोनस):** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**एसिंक्रोनस रेस्ट उदाहरण:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**एसिंक्रोनस वेबसॉकेट स्ट्रीमिंग का उदाहरण**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### एपीआई (APIs) + +#### नए एपीआई (New APIs) + +1. **कोर एपीआई क्लास (Core API Class):** + **सिंक्रोनस (Synchronous):** + `Api.socket()` - सिंक्रोनस वेबसॉकेट क्लाइंट प्राप्त करें (Get synchronous WebSocket client) + `Api.bulk()` - सिंक्रोनस बल्क ऑपरेशंस क्लाइंट प्राप्त करें (Get synchronous bulk operations client) + `Api.metrics()` - सिंक्रोनस मेट्रिक्स क्लाइंट प्राप्त करें (Get synchronous metrics client) + `Api.close()` - सभी सिंक्रोनस कनेक्शन बंद करें (Close all synchronous connections) + संदर्भ प्रबंधक समर्थन (Context manager support (`__enter__`, `__exit__`)) + **एसिंक्रोनस (Asynchronous):** + `Api.async_flow()` - एसिंक्रोनस रेस्ट फ्लो क्लाइंट प्राप्त करें (Get asynchronous REST flow client) + `Api.async_socket()` - एसिंक्रोनस वेबसॉकेट क्लाइंट प्राप्त करें (Get asynchronous WebSocket client) + `Api.async_bulk()` - एसिंक्रोनस बल्क ऑपरेशंस क्लाइंट प्राप्त करें (Get asynchronous bulk operations client) + `Api.async_metrics()` - एसिंक्रोनस मेट्रिक्स क्लाइंट प्राप्त करें (Get asynchronous metrics client) + `Api.aclose()` - सभी एसिंक्रोनस कनेक्शन बंद करें (Close all asynchronous connections) + एसिंक्रोनस संदर्भ प्रबंधक समर्थन (Async context manager support (`__aenter__`, `__aexit__`)) + +2. **सिंक्रोनस वेबसॉकेट क्लाइंट (Synchronous WebSocket Client):** + `SocketClient.flow(flow_id)` - वेबसॉकेट फ्लो इंस्टेंस प्राप्त करें (Get WebSocket flow instance) + `SocketFlowInstance.agent(..., streaming: bool = False)` - एजेंट, वैकल्पिक स्ट्रीमिंग के साथ (Agent with optional streaming) + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - टेक्स्ट कंप्लीशन, वैकल्पिक स्ट्रीमिंग के साथ (Text completion with optional streaming) + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - ग्राफ आरएजी, वैकल्पिक स्ट्रीमिंग के साथ (Graph RAG with optional streaming) + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - डॉक्यूमेंट आरएजी, वैकल्पिक स्ट्रीमिंग के साथ (Document RAG with optional streaming) + `SocketFlowInstance.prompt(..., streaming: bool = False)` - प्रॉम्प्ट, वैकल्पिक स्ट्रीमिंग के साथ (Prompt with optional streaming) + `SocketFlowInstance.graph_embeddings_query()` - ग्राफ एम्बेडिंग क्वेरी (Graph embeddings query) + सभी अन्य FlowInstance विधियाँ, समान हस्ताक्षर के साथ (All other FlowInstance methods with identical signatures) + +3. **एसिंक्रोनस वेबसॉकेट क्लाइंट (Asynchronous WebSocket Client):** + `AsyncSocketClient.flow(flow_id)` - एसिंक्रोनस वेबसॉकेट फ्लो इंस्टेंस प्राप्त करें (Get async WebSocket flow instance) + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - एसिंक्रोनस एजेंट, वैकल्पिक स्ट्रीमिंग के साथ (Async agent with optional streaming) + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - एसिंक्रोनस टेक्स्ट कंप्लीशन, वैकल्पिक स्ट्रीमिंग के साथ (Async text completion with optional streaming) + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - एसिंक्रोनस ग्राफ आरएजी, वैकल्पिक स्ट्रीमिंग के साथ (Async graph RAG with optional streaming) + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - एसिंक्रोनस डॉक्यूमेंट आरएजी, वैकल्पिक स्ट्रीमिंग के साथ (Async document RAG with optional streaming) + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - एसिंक्रोनस प्रॉम्प्ट, वैकल्पिक स्ट्रीमिंग के साथ (Async prompt with optional streaming) + `AsyncSocketFlowInstance.graph_embeddings_query()` - एसिंक्रोनस ग्राफ एम्बेडिंग क्वेरी (Async graph embeddings query) + सभी अन्य FlowInstance विधियाँ, एसिंक्रोनस संस्करण के रूप में (All other FlowInstance methods as async versions) + +4. **सिंक्रोनस बल्क ऑपरेशंस क्लाइंट (Synchronous Bulk Operations Client):** + `BulkClient.import_triples(flow, triples)` - बल्क ट्रिपल इम्पोर्ट (Bulk triple import) + `BulkClient.export_triples(flow)` - बल्क ट्रिपल एक्सपोर्ट (Bulk triple export) + `BulkClient.import_graph_embeddings(flow, embeddings)` - बल्क ग्राफ एम्बेडिंग इम्पोर्ट (Bulk graph embeddings import) + `BulkClient.export_graph_embeddings(flow)` - बल्क ग्राफ एम्बेडिंग एक्सपोर्ट (Bulk graph embeddings export) + `BulkClient.import_document_embeddings(flow, embeddings)` - बल्क डॉक्यूमेंट एम्बेडिंग इम्पोर्ट (Bulk document embeddings import) + `BulkClient.export_document_embeddings(flow)` - बल्क डॉक्यूमेंट एम्बेडिंग एक्सपोर्ट (Bulk document embeddings export) + `BulkClient.import_entity_contexts(flow, contexts)` - बल्क एंटिटी कॉन्टेक्स्ट इम्पोर्ट (Bulk entity contexts import) + `BulkClient.export_entity_contexts(flow)` - बल्क एंटिटी कॉन्टेक्स्ट एक्सपोर्ट (Bulk entity contexts export) + `BulkClient.import_objects(flow, objects)` - बल्क ऑब्जेक्ट्स इम्पोर्ट (Bulk objects import) + +5. **एसिंक्रोनस बल्क ऑपरेशंस क्लाइंट (Asynchronous Bulk Operations Client):** + `AsyncBulkClient.import_triples(flow, triples)` - एसिंक्रोनस बल्क ट्रिपल इम्पोर्ट (Async bulk triple import) + `AsyncBulkClient.export_triples(flow)` - एसिंक्रोनस बल्क ट्रिपल एक्सपोर्ट (Async bulk triple export) + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - एसिंक्रोनस बल्क ग्राफ एम्बेडिंग इम्पोर्ट (Async bulk graph embeddings import) + `AsyncBulkClient.export_graph_embeddings(flow)` - एसिंक्रोनस बल्क ग्राफ एम्बेडिंग एक्सपोर्ट (Async bulk graph embeddings export) + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - एसिंक्रोनस बल्क डॉक्यूमेंट एम्बेडिंग इम्पोर्ट (Async bulk document embeddings import) + `AsyncBulkClient.export_document_embeddings(flow)` - एसिंक्रोनस बल्क डॉक्यूमेंट एम्बेडिंग एक्सपोर्ट (Async bulk document embeddings export) + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - एसिंक्रोनस बल्क एंटिटी कॉन्टेक्स्ट इम्पोर्ट (Async bulk entity contexts import) + `AsyncBulkClient.export_entity_contexts(flow)` - एसिंक्रोनस बल्क एंटिटी कॉन्टेक्स्ट एक्सपोर्ट (Async bulk entity contexts export) + `AsyncBulkClient.import_objects(flow, objects)` - एसिंक्रोनस बल्क ऑब्जेक्ट्स इम्पोर्ट (Async bulk objects import) + +6. **एसिंक्रोनस रेस्ट फ्लो क्लाइंट (Asynchronous REST Flow Client):** + `AsyncFlow.list()` - सभी फ्लो की सूची (list all flows) + `AsyncFlow.get(id)` - फ्लो परिभाषा प्राप्त करें (get flow definition) + `AsyncFlow.start(...)` - फ्लो शुरू करें (start flow) + `AsyncFlow.stop(id)` - फ्लो रोकें (stop flow) + `AsyncFlow.id(flow_id)` - एसिंक्रोनस फ्लो इंस्टेंस प्राप्त करें (get async flow instance) + `AsyncFlowInstance.agent(...)` - एजेंट निष्पादन (agent execution) + `AsyncFlowInstance.text_completion(...)` - टेक्स्ट कंप्लीशन (text completion) + `AsyncFlowInstance.graph_rag(...)` - ग्राफ आरएजी (graph RAG) + सभी अन्य FlowInstance विधियाँ, एसिंक्रोनस संस्करण के रूप में (All other FlowInstance methods as async versions) + +7. **मेट्रिक्स क्लाइंट (Metrics Clients):** + `Metrics.get()` - सिंक्रोनस प्रोमीथियस मेट्रिक्स (Synchronous Prometheus metrics) + `AsyncMetrics.get()` - एसिंक्रोनस प्रोमीथियस मेट्रिक्स (Asynchronous Prometheus metrics) + +8. **रेस्ट फ्लो एपीआई एन्हांसमेंट (REST Flow API Enhancement):** + `FlowInstance.graph_embeddings_query()` - ग्राफ एम्बेडिंग क्वेरी (सिंक्रोनस फीचर समानता) (Graph embeddings query (sync feature parity)) + `AsyncFlowInstance.graph_embeddings_query()` - ग्राफ एम्बेडिंग क्वेरी (एसिंक्रोनस फीचर समानता) (Graph embeddings query (async feature parity)) + +#### संशोधित एपीआई (Modified APIs) + +1. **कंस्ट्रक्टर (Constructor)** (मामूली एन्हांसमेंट): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + `token` पैरामीटर जोड़ा गया (वैकल्पिक, प्रमाणीकरण के लिए) + यदि `None` (डिफ़ॉल्ट): कोई प्रमाणीकरण उपयोग नहीं किया गया + यदि निर्दिष्ट: REST के लिए इसे बेयरर टोकन के रूप में उपयोग किया जाता है (`Authorization: Bearer `), और WebSocket के लिए क्वेरी पैरामीटर के रूप में (`?token=`) + कोई अन्य परिवर्तन नहीं - पूरी तरह से पिछली संगतता + +2. **कोई महत्वपूर्ण परिवर्तन नहीं**: + सभी मौजूदा REST API विधियाँ अपरिवर्तित हैं + सभी मौजूदा हस्ताक्षर संरक्षित हैं + सभी मौजूदा रिटर्न प्रकार संरक्षित हैं + +### कार्यान्वयन विवरण + +#### त्रुटि प्रबंधन + +**WebSocket कनेक्शन त्रुटियाँ**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**सुगम प्रतिस्थापन**: +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**आंशिक स्ट्रीमिंग त्रुटियाँ**: +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### संसाधन प्रबंधन + +**संदर्भ प्रबंधक समर्थन**: +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### थ्रेडिंग और समवर्ती (Threading and Concurrency) + +**थ्रेड सुरक्षा (Thread Safety):** +प्रत्येक `Api` उदाहरण अपने स्वयं के कनेक्शन को बनाए रखता है। +WebSocket ट्रांसपोर्ट थ्रेड-सुरक्षित अनुरोध मल्टीप्लेक्सिंग के लिए लॉक्स का उपयोग करता है। +कई थ्रेड सुरक्षित रूप से एक `Api` उदाहरण को साझा कर सकते हैं। +स्ट्रीमिंग इटरेटर थ्रेड-सुरक्षित नहीं हैं (केवल एक थ्रेड से उपयोग करें)। + +**एसिंक्रोनस समर्थन (Async Support)** (भविष्य में विचार): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## सुरक्षा संबंधी विचार + +### प्रमाणीकरण + +**टोकन पैरामीटर**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**REST ट्रांसपोर्ट:** +बेयरर टोकन `Authorization` हेडर के माध्यम से +सभी REST अनुरोधों पर स्वचालित रूप से लागू होता है +प्रारूप: `Authorization: Bearer ` + +**वेबसोकेट ट्रांसपोर्ट:** +टोकन क्वेरी पैरामीटर के माध्यम से, जो वेबसोकेट यूआरएल में जोड़ा जाता है +कनेक्शन स्थापित करते समय स्वचालित रूप से लागू होता है +प्रारूप: `ws://localhost:8088/api/v1/socket?token=` + +**कार्यान्वयन:** +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**उदाहरण:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### सुरक्षित संचार + +WS (वेबसॉकेट) और WSS (वेबसॉकेट सिक्योर) दोनों योजनाओं का समर्थन करें। +WSS कनेक्शन के लिए टीएलएस प्रमाणपत्र सत्यापन। +विकास के लिए वैकल्पिक प्रमाणपत्र सत्यापन अक्षम करें (चेतावनी के साथ)। + +### इनपुट सत्यापन + +यूआरएल योजनाओं को मान्य करें (http, https, ws, wss)। +परिवहन पैरामीटर मानों को मान्य करें। +स्ट्रीमिंग पैरामीटर संयोजनों को मान्य करें। +बल्क आयात डेटा प्रकारों को मान्य करें। + +## प्रदर्शन संबंधी विचार + +### विलंबता में सुधार + +**स्ट्रीमिंग एलएलएम ऑपरेशन**: +**पहले टोकन तक का समय**: ~500ms (गैर-स्ट्रीमिंग के मुकाबले ~30s) +**सुधार**: 60 गुना तेज प्रदर्शन +**लागू**: एजेंट, ग्राफ आरएजी, दस्तावेज़ आरएजी, टेक्स्ट कंप्लीशन, प्रॉम्प्ट + +**स्थायी कनेक्शन**: +**कनेक्शन ओवरहेड**: बाद के अनुरोधों के लिए समाप्त +**वेबसॉकेट हैंडशेक**: एक बार की लागत (~100ms) +**लागू**: वेबसॉकेट परिवहन का उपयोग करते समय सभी ऑपरेशन + +### थ्रूपुट में सुधार + +**बल्क ऑपरेशन**: +**ट्रिपल्स आयात**: ~10,000 ट्रिपल्स/सेकंड (REST के साथ प्रति-आइटम ~100/सेकंड की तुलना में) +**एम्बेडिंग आयात**: ~5,000 एम्बेडिंग/सेकंड (REST के साथ प्रति-आइटम ~50/सेकंड की तुलना में) +**सुधार**: बल्क ऑपरेशन के लिए 100 गुना थ्रूपुट + +**अनुरोध मल्टीप्लेक्सिंग**: +**समवर्ती अनुरोध**: एक कनेक्शन पर 15 तक समवर्ती अनुरोध +**कनेक्शन पुन: उपयोग**: समवर्ती ऑपरेशन के लिए कोई कनेक्शन ओवरहेड नहीं + +### मेमोरी संबंधी विचार + +**स्ट्रीमिंग प्रतिक्रियाएं**: +स्थिर मेमोरी उपयोग (जैसे ही वे आते हैं, चंक्स को संसाधित करें) +पूरी प्रतिक्रिया का कोई बफरिंग नहीं +बहुत लंबी आउटपुट (>1MB) के लिए उपयुक्त + +**बल्क ऑपरेशन**: +इटरेटर-आधारित प्रसंस्करण (स्थिर मेमोरी) +संपूर्ण डेटासेट को मेमोरी में लोड नहीं किया जाता है +लाखों आइटम वाले डेटासेट के लिए उपयुक्त + +### बेंचमार्क (अपेक्षित) + +| ऑपरेशन | REST (मौजूदा) | वेबसॉकेट (स्ट्रीमिंग) | सुधार | +|-----------|----------------|----------------------|-------------| +| एजेंट (पहले टोकन तक का समय) | 30s | 0.5s | 60x | +| ग्राफ आरएजी (पहले टोकन तक का समय) | 25s | 0.5s | 50x | +| 10K ट्रिपल्स आयात करें | 100s | 1s | 100x | +| 1M ट्रिपल्स आयात करें | 10,000s (2.7h) | 100s (1.6m) | 100x | +| 10 समवर्ती छोटे अनुरोध | 5s (क्रमिक) | 0.5s (समानांतर) | 10x | + +## परीक्षण रणनीति + +### यूनिट टेस्ट + +**परिवहन परत** (`test_transport.py`): +REST परिवहन अनुरोध/प्रतिक्रिया का परीक्षण करें +WebSocket परिवहन कनेक्शन का परीक्षण करें +WebSocket परिवहन पुन: कनेक्शन का परीक्षण करें +अनुरोध मल्टीप्लेक्सिंग का परीक्षण करें +स्ट्रीमिंग प्रतिक्रिया पार्सिंग का परीक्षण करें +नियतात्मक परीक्षणों के लिए मॉक WebSocket सर्वर + +**API विधियाँ** (`test_flow.py`, `test_library.py`, आदि): +मॉक परिवहन के साथ नई विधियों का परीक्षण करें +स्ट्रीमिंग पैरामीटर हैंडलिंग का परीक्षण करें +बल्क ऑपरेशन इटरेटर का परीक्षण करें +त्रुटि हैंडलिंग का परीक्षण करें + +**प्रकार** (`test_types.py`): +नए स्ट्रीमिंग चंक प्रकारों का परीक्षण करें +प्रकार क्रमबद्धता/वि-क्रमबद्धता का परीक्षण करें + +### एकीकरण परीक्षण + +**एंड-टू-एंड REST** (`test_integration_rest.py`): +वास्तविक गेटवे (REST मोड) के खिलाफ सभी कार्यों का परीक्षण करें +पिछड़े अनुकूलता को सत्यापित करें +त्रुटि स्थितियों का परीक्षण करें + +**एंड-टू-एंड WebSocket** (`test_integration_websocket.py`): +वास्तविक गेटवे (WebSocket मोड) के खिलाफ सभी कार्यों का परीक्षण करें +स्ट्रीमिंग कार्यों का परीक्षण करें +बल्क कार्यों का परीक्षण करें +समवर्ती अनुरोधों का परीक्षण करें +कनेक्शन रिकवरी का परीक्षण करें + +**स्ट्रीमिंग सेवाएं** (`test_streaming_integration.py`): +एजेंट स्ट्रीमिंग का परीक्षण करें (विचार, अवलोकन, उत्तर) +RAG स्ट्रीमिंग का परीक्षण करें (क्रमिक चंक) +टेक्स्ट कंप्लीशन स्ट्रीमिंग का परीक्षण करें (टोकन-दर-टोकन) +प्रॉम्प्ट स्ट्रीमिंग का परीक्षण करें +स्ट्रीमिंग के दौरान त्रुटि हैंडलिंग का परीक्षण करें + +**बल्क ऑपरेशन** (`test_bulk_integration.py`): +ट्रिपल (1K, 10K, 100K आइटम) का बल्क आयात/निर्यात का परीक्षण करें +एम्बेडिंग का बल्क आयात/निर्यात का परीक्षण करें +बल्क कार्यों के दौरान मेमोरी उपयोग का परीक्षण करें +प्रगति ट्रैकिंग का परीक्षण करें + +### प्रदर्शन परीक्षण + +**विलंबता बेंचमार्क** (`test_performance_latency.py`): +पहले टोकन तक लगने वाले समय को मापें (स्ट्रीमिंग बनाम गैर-स्ट्रीमिंग) +कनेक्शन ओवरहेड को मापें (REST बनाम WebSocket) +अपेक्षित बेंचमार्क के विरुद्ध तुलना करें + +**थ्रूपुट बेंचमार्क** (`test_performance_throughput.py`): +बल्क आयात थ्रूपुट को मापें +अनुरोध मल्टीप्लेक्सिंग दक्षता को मापें +अपेक्षित बेंचमार्क के विरुद्ध तुलना करें + +### अनुकूलता परीक्षण + +**पिछड़ी अनुकूलता** (`test_backward_compatibility.py`): +मौजूदा परीक्षण सूट को रिफैक्टर किए गए API के खिलाफ चलाएं +शून्य ब्रेकिंग परिवर्तनों को सत्यापित करें +सामान्य पैटर्न के लिए माइग्रेशन पथ का परीक्षण करें + +## माइग्रेशन योजना + +### चरण 1: पारदर्शी माइग्रेशन (डिफ़ॉल्ट) + +**किसी कोड परिवर्तन की आवश्यकता नहीं है।** मौजूदा कोड काम करना जारी रखता है: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### चरण 2: ऑप्ट-इन स्ट्रीमिंग (सरल) + +**स्ट्रीमिंग को सक्षम करने के लिए `api.socket()` इंटरफ़ेस का उपयोग करें:** + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**मुख्य बातें:** +REST और WebSocket दोनों के लिए समान URL +समान मेथड सिग्नेचर (आसान माइग्रेशन) +बस `.socket()` और `streaming=True` जोड़ें + +### चरण 3: बल्क ऑपरेशन (नई क्षमता) + +बड़े डेटासेट के लिए `api.bulk()` इंटरफ़ेस का उपयोग करें: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### दस्तावेज़ अद्यतन + +1. **README.md**: स्ट्रीमिंग और वेबसॉकेट उदाहरण जोड़ें +2. **एपीआई संदर्भ**: सभी नए तरीकों और पैरामीटरों का दस्तावेजीकरण करें +3. **माइग्रेशन गाइड**: स्ट्रीमिंग को सक्षम करने के लिए चरण-दर-चरण मार्गदर्शिका +4. **उदाहरण**: सामान्य पैटर्न के लिए उदाहरण स्क्रिप्ट जोड़ें +5. **प्रदर्शन गाइड**: अपेक्षित प्रदर्शन सुधारों का दस्तावेजीकरण करें + +### अप्रचलन नीति + +**कोई अप्रचलन नहीं।** सभी मौजूदा एपीआई समर्थित रहते हैं। यह एक शुद्ध संवर्द्धन है। + +## समयरेखा + +### सप्ताह 1: आधार +परिवहन अमूर्त परत +मौजूदा REST कोड को पुनर्गठित करें +परिवहन परत के लिए यूनिट परीक्षण +पिछड़े अनुकूलता सत्यापन + +### सप्ताह 2: वेबसॉकेट परिवहन +वेबसॉकेट परिवहन कार्यान्वयन +कनेक्शन प्रबंधन और पुन: कनेक्शन +अनुरोध मल्टीप्लेक्सिंग +यूनिट और एकीकरण परीक्षण + +### सप्ताह 3: स्ट्रीमिंग समर्थन +एलएलएम विधियों में स्ट्रीमिंग पैरामीटर जोड़ें +स्ट्रीमिंग प्रतिक्रिया पार्सिंग को लागू करें +स्ट्रीमिंग चंक प्रकार जोड़ें +स्ट्रीमिंग एकीकरण परीक्षण + +### सप्ताह 4: बल्क ऑपरेशन +बल्क आयात/निर्यात विधियाँ जोड़ें +इटरेटर-आधारित संचालन को लागू करें +प्रदर्शन परीक्षण +बल्क ऑपरेशन एकीकरण परीक्षण + +### सप्ताह 5: सुविधा समानता और दस्तावेज़ +ग्राफ एम्बेडिंग क्वेरी जोड़ें +मेट्रिक्स एपीआई जोड़ें +व्यापक दस्तावेज़ +माइग्रेशन गाइड +रिलीज़ उम्मीदवार + +### सप्ताह 6: रिलीज़ +अंतिम एकीकरण परीक्षण +प्रदर्शन बेंचमार्किंग +रिलीज़ दस्तावेज़ +सामुदायिक घोषणा + +**कुल अवधि**: 6 सप्ताह + +## खुले प्रश्न + +### एपीआई डिज़ाइन प्रश्न + +1. **एसिंक्रोनस समर्थन**: ✅ **समाधान** - प्रारंभिक रिलीज़ में पूर्ण एसिंक्रोनस समर्थन शामिल है + सभी इंटरफेस में एसिंक्रोनस वेरिएंट हैं: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + सिंक और एसिंक्रोनस एपीआई के बीच पूर्ण समरूपता प्रदान करता है + आधुनिक एसिंक्रोनस फ्रेमवर्क (FastAPI, aiohttp) के लिए आवश्यक है + +2. **प्रगति ट्रैकिंग**: क्या बल्क ऑपरेशन प्रगति कॉलबैक का समर्थन करना चाहिए? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **सिफारिश**: चरण 2 में जोड़ें। प्रारंभिक रिलीज़ के लिए महत्वपूर्ण नहीं है। + +3. **स्ट्रीमिंग टाइमआउट**: हमें स्ट्रीमिंग कार्यों के लिए टाइमआउट को कैसे संभालना चाहिए? + **सिफारिश**: गैर-स्ट्रीमिंग के समान टाइमआउट का उपयोग करें, लेकिन प्रत्येक प्राप्त चंक पर इसे रीसेट करें। + +4. **चंक बफरिंग**: क्या हमें चंक्स को बफर करना चाहिए या तुरंत आउटपुट देना चाहिए? + **सिफारिश**: सबसे कम विलंबता के लिए तुरंत आउटपुट दें। + +5. **वेबसॉकेट के माध्यम से वैश्विक सेवाएं**: क्या `api.socket()` को वैश्विक सेवाओं (लाइब्रेरी, ज्ञान, संग्रह, कॉन्फ़िगरेशन) का समर्थन करना चाहिए या केवल फ़्लो-स्कोप सेवाओं का? + **सिफारिश**: केवल फ़्लो-स्कोप के साथ शुरुआत करें (जहां स्ट्रीमिंग मायने रखती है)। यदि आवश्यक हो तो चरण 2 में वैश्विक सेवाओं को जोड़ें। + +### कार्यान्वयन प्रश्न + +1. **वेबसॉकेट लाइब्रेरी**: क्या हमें `websockets`, `websocket-client`, या `aiohttp` का उपयोग करना चाहिए? + **सिफारिश**: `websockets` (एसिंक्रोनस, परिपक्व, अच्छी तरह से बनाए रखा गया)। `asyncio.run()` का उपयोग करके सिंक इंटरफ़ेस में लपेटें। + +2. **कनेक्शन पूलिंग**: क्या हमें कई समवर्ती `Api` उदाहरणों का समर्थन करना चाहिए जो एक कनेक्शन पूल साझा करते हैं? + **सिफारिश**: चरण 2 तक टालें। प्रत्येक `Api` उदाहरण में शुरू में अपने स्वयं के कनेक्शन होंगे। + +3. **कनेक्शन पुन: उपयोग**: क्या `SocketClient` और `BulkClient` एक ही वेबसॉकेट कनेक्शन साझा करेंगे, या अलग-अलग कनेक्शन का उपयोग करेंगे? + **सिफारिश**: अलग कनेक्शन। सरल कार्यान्वयन, चिंताओं का स्पष्ट अलगाव। + +4. **लेजी बनाम ईगर कनेक्शन**: क्या वेबसॉकेट कनेक्शन `api.socket()` में स्थापित किया जाना चाहिए या पहले अनुरोध पर? + **सिफारिश**: लेजी (पहले अनुरोध पर)। यदि उपयोगकर्ता केवल REST विधियों का उपयोग करता है तो कनेक्शन ओवरहेड से बचें। + +### परीक्षण प्रश्न + +1. **मॉक गेटवे**: क्या हमें परीक्षण के लिए एक हल्के मॉक गेटवे बनाना चाहिए, या वास्तविक गेटवे के खिलाफ परीक्षण करना चाहिए? + **सिफारिश**: दोनों। यूनिट परीक्षणों के लिए मॉक का उपयोग करें, एकीकरण परीक्षणों के लिए वास्तविक गेटवे का उपयोग करें। + +2. **प्रदर्शन प्रतिगमन परीक्षण**: क्या हमें CI में स्वचालित प्रदर्शन प्रतिगमन परीक्षण जोड़ना चाहिए? + **सिफारिश**: हाँ, लेकिन CI वातावरण की परिवर्तनशीलता को ध्यान में रखते हुए उदार सीमाओं के साथ। + +## संदर्भ + +### संबंधित तकनीकी विनिर्देश +`docs/tech-specs/streaming-llm-responses.md` - गेटवे में स्ट्रीमिंग कार्यान्वयन +`docs/tech-specs/rag-streaming-support.md` - RAG स्ट्रीमिंग समर्थन + +### कार्यान्वयन फ़ाइलें +`trustgraph-base/trustgraph/api/` - पायथन एपीआई स्रोत +`trustgraph-flow/trustgraph/gateway/` - गेटवे स्रोत +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - वेबसॉकेट मल्टीप्लेक्सर संदर्भ कार्यान्वयन + +### दस्तावेज़ +`docs/apiSpecification.md` - पूर्ण एपीआई संदर्भ +`docs/api-status-summary.md` - एपीआई स्थिति सारांश +`README.websocket` - वेबसॉकेट प्रोटोकॉल दस्तावेज़ +`STREAMING-IMPLEMENTATION-NOTES.txt` - स्ट्रीमिंग कार्यान्वयन नोट्स + +### बाहरी लाइब्रेरी +`websockets` - पायथन वेबसॉकेट लाइब्रेरी (https://websockets.readthedocs.io/) +`requests` - पायथन एचटीटीपी लाइब्रेरी (मौजूदा) diff --git a/docs/tech-specs/python-api-refactor.md b/docs/tech-specs/python-api-refactor.md index 215ed3d6..dd0022df 100644 --- a/docs/tech-specs/python-api-refactor.md +++ b/docs/tech-specs/python-api-refactor.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Python API Refactor Technical Specification" +parent: "Tech Specs" +--- + # Python API Refactor Technical Specification ## Overview diff --git a/docs/tech-specs/python-api-refactor.pt.md b/docs/tech-specs/python-api-refactor.pt.md new file mode 100644 index 00000000..020bcddd --- /dev/null +++ b/docs/tech-specs/python-api-refactor.pt.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Python API Refactor Technical Specification" +parent: "Portuguese (Beta)" +--- + +# Python API Refactor 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 + +Esta especificação descreve uma refatoração abrangente da biblioteca de cliente da API Python TrustGraph para alcançar a paridade de recursos com o API Gateway e adicionar suporte para padrões de comunicação em tempo real modernos. + +A refatoração aborda quatro casos de uso primários: + +1. **Interações de LLM em Streaming**: Habilitar o streaming em tempo real de respostas de LLM (agente, RAG de grafo, RAG de documento, conclusão de texto, prompts) com uma latência ~60 vezes menor (500ms vs 30s para o primeiro token). +2. **Operações em Lote**: Suportar a importação/exportação eficiente em lote de triplas, incorporações de grafos e incorporações de documentos para gerenciamento de grafos de conhecimento em grande escala. +3. **Paridade de Recursos**: Garantir que cada endpoint do API Gateway tenha um método de API Python correspondente, incluindo a consulta de incorporações de grafos. +4. **Conexões Persistentes**: Habilitar a comunicação baseada em WebSocket para solicitações multiplexadas e redução da sobrecarga de conexão. + +## Objetivos + +**Paridade de Recursos**: Cada serviço do Gateway API tem um método de API Python correspondente. +**Suporte para Streaming**: Todos os serviços capazes de streaming (agente, RAG, conclusão de texto, prompt) suportam streaming na API Python. +**Transporte WebSocket**: Adicionar uma camada de transporte WebSocket opcional para conexões persistentes e multiplexação. +**Operações em Lote**: Adicionar importação/exportação eficiente em lote para triplas, incorporações de grafos e incorporações de documentos. +**Suporte Completo Async**: Implementação completa de async/await para todas as interfaces (REST, WebSocket, operações em lote, métricas). +**Compatibilidade com Versões Anteriores**: O código existente continua a funcionar sem modificação. +**Segurança de Tipos**: Manter interfaces com segurança de tipos com dataclasses e dicas de tipo. +**Aprimoramento Progressivo**: Streaming e async são opcionais por meio da seleção explícita da interface. +**Desempenho**: Alcançar uma melhoria de latência de 60 vezes para operações de streaming. +**Python Moderno**: Suporte para paradigmas sync e async para máxima flexibilidade. + +## Contexto + +### Estado Atual + +A API Python (`trustgraph-base/trustgraph/api/`) é uma biblioteca de cliente REST somente com os seguintes módulos: + +`flow.py`: Gerenciamento de fluxo e serviços com escopo de fluxo (50 métodos). +`library.py`: Operações da biblioteca de documentos (9 métodos). +`knowledge.py`: Gerenciamento central do KG (4 métodos). +`collection.py`: Metadados da coleção (3 métodos). +`config.py`: Gerenciamento de configuração (6 métodos). +`types.py`: Definições de tipo de dados (5 dataclasses). + +**Operações Totais**: 50/59 (85% de cobertura). + +### Limitações Atuais + +**Operações Ausentes**: +Consulta de incorporações de grafos (busca semântica sobre entidades de grafos). +Importação/exportação em lote para triplas, incorporações de grafos, incorporações de documentos, contextos de entidades, objetos. +Endpoint de métricas. + +**Capacidades Ausentes**: +Suporte para streaming para serviços de LLM. +Transporte WebSocket. +Solicitações concorrentes multiplexadas. +Conexões persistentes. + +**Problemas de Desempenho**: +Alta latência para interações de LLM (~30s para o primeiro token). +Transferência de dados em lote ineficiente (requisição REST por item). +Sobrecarga de conexão para várias operações sequenciais. + +**Problemas de Experiência do Usuário**: +Sem feedback em tempo real durante a geração de LLM. +Não é possível cancelar operações de LLM em execução prolongada. +Má escalabilidade para operações em lote. + +### Impacto + +O aprimoramento de streaming do API Gateway em novembro de 2024 proporcionou uma melhoria de latência de 60 vezes (500ms vs 30s para o primeiro token) para interações de LLM, mas os usuários da API Python não podem aproveitar essa capacidade. Isso cria uma lacuna significativa de experiência entre usuários de Python e não usuários de Python. + +## Design Técnico + +### Arquitetura + +A API Python refatorada usa uma **abordagem de interface modular** com objetos separados para diferentes padrões de comunicação. Todas as interfaces estão disponíveis tanto em variantes **síncronas quanto assíncronas**: + +1. **Interface REST** (existente, aprimorada). + **Sync**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()`. + **Async**: `api.async_flow()`. + Requisição/resposta síncrona/assíncrona. + Modelo de conexão simples. + Padrão para compatibilidade com versões anteriores. + +2. **Interface WebSocket** (nova). + **Sync**: `api.socket()`. + **Async**: `api.async_socket()`. + Conexão persistente. + Solicitações multiplexadas. + Suporte para streaming. + Mesmas assinaturas de método do REST onde a funcionalidade se sobrepõe. + +3. **Interface de Operações em Lote** (nova). + **Sync**: `api.bulk()`. + **Async**: `api.async_bulk()`. + Baseado em WebSocket para eficiência. + Importação/exportação baseada em iterador/AsyncIterator. + Lida com grandes conjuntos de dados. + +4. **Interface de Métricas** (nova). + **Sync**: `api.metrics()`. + **Async**: `api.async_metrics()`. + Acesso a métricas Prometheus. + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**Princípios de Design Chave:** +**Mesmo URL para todas as interfaces:** `Api(url="http://localhost:8088/")` funciona para todas. +**Simetria Síncrona/Assíncrona:** Cada interface possui variantes síncronas e assíncronas com assinaturas de método idênticas. +**Assinaturas Idênticas:** Onde a funcionalidade se sobrepõe, as assinaturas dos métodos são idênticas entre REST e WebSocket, síncronas e assíncronas. +**Melhoria Progressiva:** Escolha a interface com base nas necessidades (REST para tarefas simples, WebSocket para streaming, Bulk para grandes conjuntos de dados, assíncrono para frameworks modernos). +**Intenção Explícita:** `api.socket()` sinaliza WebSocket, `api.async_socket()` sinaliza WebSocket assíncrono. +**Compatível com versões anteriores:** Código existente permanece inalterado. + +### Componentes + +#### 1. Classe de API Principal (Modificada) + +Módulo: `trustgraph-base/trustgraph/api/api.py` + +**Classe de API Aprimorada:** + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. Cliente WebSocket Síncrono + +Módulo: `trustgraph-base/trustgraph/api/socket_client.py` (novo) + +**Classe SocketClient**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Principais Características:** +Conexão preguiçosa (conecta apenas quando o primeiro pedido é enviado) +Multiplexação de requisições (até 15 simultâneas) +Reconexão automática em caso de desconexão +Análise de resposta em streaming +Operação thread-safe +Wrapper síncrono em torno da biblioteca assíncrona de WebSockets + +#### 3. Cliente WebSocket Assíncrono + +Módulo: `trustgraph-base/trustgraph/api/async_socket_client.py` (novo) + +**Classe AsyncSocketClient:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Principais Características:** +Suporte nativo para async/await +Eficiente para aplicações assíncronas (FastAPI, aiohttp) +Sem bloqueio de threads +Mesma interface da versão síncrona +AsyncIterator para streaming + +#### 4. Cliente de Operações em Lote Síncronas + +Módulo: `trustgraph-base/trustgraph/api/bulk_client.py` (novo) + +**Classe BulkClient:** + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**Principais Características:** +Baseado em iteradores para uso constante de memória. +Conexões WebSocket dedicadas por operação. +Rastreamento de progresso (callback opcional). +Tratamento de erros com relatórios de sucesso parcial. + +#### 5. Cliente de Operações em Massa Assíncronas + +Módulo: `trustgraph-base/trustgraph/api/async_bulk_client.py` (novo) + +**Classe AsyncBulkClient:** + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**Principais Características:** +Baseado em AsyncIterator para uso constante de memória +Eficiente para aplicações assíncronas +Suporte nativo para async/await +Mesma interface da versão síncrona + +#### 6. API REST Flow (Síncrona - Inalterada) + +Módulo: `trustgraph-base/trustgraph/api/flow.py` + +A API REST Flow permanece **completamente inalterada** para compatibilidade com versões anteriores. Todos os métodos existentes continuam a funcionar: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, etc. +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, etc. +Todas as assinaturas e tipos de retorno existentes preservados + +**Novo:** Adicione `graph_embeddings_query()` a REST FlowInstance para paridade de recursos: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. API de Fluxo REST Assíncrono + +Módulo: `trustgraph-base/trustgraph/api/async_flow.py` (novo) + +**Classes AsyncFlow e AsyncFlowInstance:** + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**Principais Características:** +HTTP assíncrono nativo usando `aiohttp` ou `httpx` +Mesmas assinaturas de método da API REST síncrona +Sem streaming (use `async_socket()` para streaming) +Eficiente para aplicações assíncronas + +#### 8. API de Métricas + +Módulo: `trustgraph-base/trustgraph/api/metrics.py` (novo) + +**Métricas Síncronas:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**Métricas Assíncronas**: + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. Tipos Aprimorados + +Módulo: `trustgraph-base/trustgraph/api/types.py` (modificado) + +**Novos Tipos**: + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. API de Métricas + +Módulo: `trustgraph-base/trustgraph/api/metrics.py` (novo) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### Abordagem de Implementação + +#### Fase 1: Aprimoramento da API Central (Semana 1) + +1. Adicionar métodos `socket()`, `bulk()` e `metrics()` à classe `Api` +2. Implementar inicialização preguiçosa para clientes WebSocket e em lote +3. Adicionar suporte a gerenciador de contexto (`__enter__`, `__exit__`) +4. Adicionar método `close()` para limpeza +5. Adicionar testes unitários para aprimoramentos da classe da API +6. Verificar compatibilidade com versões anteriores + +**Compatibilidade com versões anteriores**: Nenhuma alteração disruptiva. Apenas novos métodos. + +#### Fase 2: Cliente WebSocket (Semana 2-3) + +1. Implementar classe `SocketClient` com gerenciamento de conexão +2. Implementar `SocketFlowInstance` com as mesmas assinaturas de método de `FlowInstance` +3. Adicionar suporte para multiplexação de solicitações (até 15 simultâneas) +4. Adicionar análise de resposta em streaming para diferentes tipos de fragmentos +5. Adicionar lógica de reconexão automática +6. Adicionar testes unitários e de integração +7. Documentar padrões de uso do WebSocket + +**Compatibilidade com versões anteriores**: Nova interface apenas. Sem impacto no código existente. + +#### Fase 3: Suporte a Streaming (Semana 3-4) + +1. Adicionar classes de tipo de fragmento de streaming (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. Implementar análise de resposta em streaming em `SocketClient` +3. Adicionar parâmetro de streaming a todos os métodos LLM em `SocketFlowInstance` +4. Lidar com casos de erro durante o streaming +5. Adicionar testes unitários e de integração para streaming +6. Adicionar exemplos de streaming à documentação + +**Compatibilidade com versões anteriores**: Nova interface apenas. API REST existente inalterada. + +#### Fase 4: Operações em Lote (Semana 4-5) + +1. Implementar classe `BulkClient` +2. Adicionar métodos de importação/exportação em lote para triplas, incorporações, contextos, objetos +3. Implementar processamento baseado em iterador para uso de memória constante +4. Adicionar rastreamento de progresso (callback opcional) +5. Adicionar tratamento de erros com relatório de sucesso parcial +6. Adicionar testes unitários e de integração +7. Adicionar exemplos de operações em lote + +**Compatibilidade com versões anteriores**: Nova interface apenas. Sem impacto no código existente. + +#### Fase 5: Paridade de Recursos e Refinamento (Semana 5) + +1. Adicionar `graph_embeddings_query()` ao REST `FlowInstance` +2. Implementar classe `Metrics` +3. Adicionar testes de integração abrangentes +4. Teste de desempenho +5. Atualizar toda a documentação +6. Criar guia de migração + +**Compatibilidade com versões anteriores**: Novos métodos apenas. Sem impacto no código existente. + +### Modelos de Dados + +#### Seleção de Interface + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### Tipos de Resposta de Streaming + +**Streaming do Agente**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**Streaming RAG**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**Operações em Lote (Síncronas):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**Operações em Lote (Assíncronas):** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**Exemplo de REST Assíncrono:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**Exemplo de Streaming WebSocket Assíncrono:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### APIs + +#### New APIs + +1. **Classe de API Core**: + **Síncrono**: + `Api.socket()` - Obter cliente WebSocket síncrono + `Api.bulk()` - Obter cliente de operações em lote síncrono + `Api.metrics()` - Obter cliente de métricas síncrono + `Api.close()` - Fechar todas as conexões síncronas + Suporte a gerenciador de contexto (`__enter__`, `__exit__`) + **Assíncrono**: + `Api.async_flow()` - Obter cliente de fluxo REST assíncrono + `Api.async_socket()` - Obter cliente WebSocket assíncrono + `Api.async_bulk()` - Obter cliente de operações em lote assíncrono + `Api.async_metrics()` - Obter cliente de métricas assíncrono + `Api.aclose()` - Fechar todas as conexões assíncronas + Suporte a gerenciador de contexto assíncrono (`__aenter__`, `__aexit__`) + +2. **Cliente WebSocket Síncrono**: + `SocketClient.flow(flow_id)` - Obter instância de fluxo WebSocket + `SocketFlowInstance.agent(..., streaming: bool = False)` - Agente com streaming opcional + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - Conclusão de texto com streaming opcional + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG com streaming opcional + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG com streaming opcional + `SocketFlowInstance.prompt(..., streaming: bool = False)` - Prompt com streaming opcional + `SocketFlowInstance.graph_embeddings_query()` - Consulta de embeddings de grafo + Todos os outros métodos FlowInstance com assinaturas idênticas + +3. **Cliente WebSocket Assíncrono**: + `AsyncSocketClient.flow(flow_id)` - Obter instância de fluxo WebSocket assíncrono + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - Agente assíncrono com streaming opcional + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - Conclusão de texto assíncrona com streaming opcional + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG assíncrono com streaming opcional + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG assíncrono com streaming opcional + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - Prompt assíncrono com streaming opcional + `AsyncSocketFlowInstance.graph_embeddings_query()` - Consulta de embeddings de grafo assíncrona + Todos os outros métodos FlowInstance como versões assíncronas + +4. **Cliente de Operações em Lote Síncrono**: + `BulkClient.import_triples(flow, triples)` - Importação em lote de triplas + `BulkClient.export_triples(flow)` - Exportação em lote de triplas + `BulkClient.import_graph_embeddings(flow, embeddings)` - Importação em lote de embeddings de grafo + `BulkClient.export_graph_embeddings(flow)` - Exportação em lote de embeddings de grafo + `BulkClient.import_document_embeddings(flow, embeddings)` - Importação em lote de embeddings de documentos + `BulkClient.export_document_embeddings(flow)` - Exportação em lote de embeddings de documentos + `BulkClient.import_entity_contexts(flow, contexts)` - Importação em lote de contextos de entidades + `BulkClient.export_entity_contexts(flow)` - Exportação em lote de contextos de entidades + `BulkClient.import_objects(flow, objects)` - Importação em lote de objetos + +5. **Cliente de Operações em Lote Assíncrono**: + `AsyncBulkClient.import_triples(flow, triples)` - Importação assíncrona em lote de triplas + `AsyncBulkClient.export_triples(flow)` - Exportação assíncrona em lote de triplas + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - Importação assíncrona em lote de embeddings de grafo + `AsyncBulkClient.export_graph_embeddings(flow)` - Exportação assíncrona em lote de embeddings de grafo + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - Importação assíncrona em lote de embeddings de documentos + `AsyncBulkClient.export_document_embeddings(flow)` - Exportação assíncrona em lote de embeddings de documentos + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - Importação assíncrona em lote de contextos de entidades + `AsyncBulkClient.export_entity_contexts(flow)` - Exportação assíncrona em lote de contextos de entidades + `AsyncBulkClient.import_objects(flow, objects)` - Importação assíncrona em lote de objetos + +6. **Cliente de Fluxo REST Assíncrono**: + `AsyncFlow.list()` - Listar todos os fluxos de forma assíncrona + `AsyncFlow.get(id)` - Obter definição de fluxo de forma assíncrona + `AsyncFlow.start(...)` - Iniciar fluxo de forma assíncrona + `AsyncFlow.stop(id)` - Parar fluxo de forma assíncrona + `AsyncFlow.id(flow_id)` - Obter instância de fluxo de forma assíncrona + `AsyncFlowInstance.agent(...)` - Execução de agente assíncrona + `AsyncFlowInstance.text_completion(...)` - Conclusão de texto assíncrona + `AsyncFlowInstance.graph_rag(...)` - Graph RAG assíncrono + Todos os outros métodos FlowInstance como versões assíncronas + +7. **Clientes de Métricas**: + `Metrics.get()` - Métricas Prometheus síncronas + `AsyncMetrics.get()` - Métricas Prometheus assíncronas + +8. **Aprimoramento da API de Fluxo REST**: + `FlowInstance.graph_embeddings_query()` - Consulta de embeddings de grafo (paridade de recursos síncrona) + `AsyncFlowInstance.graph_embeddings_query()` - Consulta de embeddings de grafo (paridade de recursos assíncrona) + +#### APIs Modificadas + +1. **Construtor** (melhoria menor): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + Adicionado parâmetro `token` (opcional, para autenticação) + Se `None` (padrão): Nenhuma autenticação utilizada + Se especificado: Usado como token bearer para REST (`Authorization: Bearer `), parâmetro de consulta para WebSocket (`?token=`) + Nenhuma outra alteração - totalmente compatível com versões anteriores + +2. **Nenhuma Alteração Significativa**: + Todos os métodos da API REST existentes permanecem inalterados + Todas as assinaturas existentes são preservadas + Todos os tipos de retorno existentes são preservados + +### Detalhes da Implementação + +#### Tratamento de Erros + +**Erros de Conexão WebSocket**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**Fallback Elegante**: +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**Erros de Streaming Parcial:** +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### Gerenciamento de Recursos + +**Suporte a Gerenciadores de Contexto**: +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### Threads e Concorrência + +**Segurança de Threads**: +Cada instância de `Api` mantém sua própria conexão. +O transporte WebSocket usa bloqueios para multiplexação de solicitações com segurança de thread. +Múltiplas threads podem compartilhar uma instância de `Api` com segurança. +Iteradores de streaming não são seguros para threads (consumir de uma única thread). + +**Suporte Assíncrono** (consideração futura): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## Considerações de Segurança + +### Autenticação + +**Parâmetro de Token**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**Transporte REST**: +Token do transportador via cabeçalho `Authorization` +Aplicado automaticamente a todas as requisições REST +Formato: `Authorization: Bearer ` + +**Transporte WebSocket**: +Token via parâmetro de consulta anexado à URL do WebSocket +Aplicado automaticamente durante o estabelecimento da conexão +Formato: `ws://localhost:8088/api/v1/socket?token=` + +**Implementação**: +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**Exemplo**: +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### Comunicação Segura + +Suporta os esquemas WS (WebSocket) e WSS (WebSocket Secure). +Validação de certificado TLS para conexões WSS. +Verificação de certificado opcional para desenvolvimento (com aviso). + +### Validação de Entrada + +Valida esquemas de URL (http, https, ws, wss). +Valida valores de parâmetros de transporte. +Valida combinações de parâmetros de streaming. +Valida tipos de dados para importação em lote. + +## Considerações de Desempenho + +### Melhorias de Latência + +**Operações LLM em Streaming**: +**Tempo para o primeiro token**: ~500ms (vs ~30s sem streaming) +**Melhoria**: 60 vezes mais rápido em termos de desempenho percebido. +**Aplicável a**: Agente, Graph RAG, Document RAG, Geração de Texto, Prompt. + +**Conexões Persistentes**: +**Sobrecarga de conexão**: Eliminada para solicitações subsequentes. +**Handshake WebSocket**: Custo único (~100ms). +**Aplicável a**: Todas as operações ao usar o transporte WebSocket. + +### Melhorias de Throughput + +**Operações em Lote**: +**Importação de triplas**: ~10.000 triplas/segundo (vs ~100/segundo com REST por item). +**Importação de embeddings**: ~5.000 embeddings/segundo (vs ~50/segundo com REST por item). +**Melhoria**: 100 vezes mais rápido para operações em lote. + +**Multiplexação de Requisições**: +**Requisições concorrentes**: Até 15 requisições simultâneas sobre uma única conexão. +**Reutilização de conexão**: Sem sobrecarga de conexão para operações concorrentes. + +### Considerações de Memória + +**Respostas em Streaming**: +Uso constante de memória (processa os chunks à medida que chegam). +Sem bufferização da resposta completa. +Adequado para saídas muito longas (>1MB). + +**Operações em Lote**: +Processamento baseado em iterador (uso constante de memória). +Sem carregamento do conjunto de dados inteiro na memória. +Adequado para conjuntos de dados com milhões de itens. + +### Benchmarks (Esperados) + +| Operação | REST (existente) | WebSocket (streaming) | Melhoria | +|-----------|----------------|----------------------|-------------| +| Agente (tempo para o primeiro token) | 30s | 0.5s | 60x | +| Graph RAG (tempo para o primeiro token) | 25s | 0.5s | 50x | +| Importação de 10K triplas | 100s | 1s | 100x | +| Importação de 1M triplas | 10.000s (2.7h) | 100s (1.6m) | 100x | +| 10 requisições pequenas concorrentes | 5s (sequencial) | 0.5s (paralelo) | 10x | + +## Estratégia de Testes + +### Testes Unitários + +**Camada de Transporte** (`test_transport.py`): +Testar requisição/resposta de transporte REST +Testar conexão de transporte WebSocket +Testar reconexão de transporte WebSocket +Testar multiplexação de requisições +Testar análise de resposta em streaming +Simular um servidor WebSocket para testes determinísticos + +**Métodos da API** (`test_flow.py`, `test_library.py`, etc.): +Testar novos métodos com transporte simulado +Testar tratamento de parâmetros em streaming +Testar iteradores de operações em lote +Testar tratamento de erros + +**Tipos** (`test_types.py`): +Testar novos tipos de fragmentos em streaming +Testar serialização/desserialização de tipos + +### Testes de Integração + +**REST de Ponta a Ponta** (`test_integration_rest.py`): +Testar todas as operações contra o Gateway real (modo REST) +Verificar compatibilidade com versões anteriores +Testar condições de erro + +**WebSocket de Ponta a Ponta** (`test_integration_websocket.py`): +Testar todas as operações contra o Gateway real (modo WebSocket) +Testar operações de streaming +Testar operações em lote +Testar requisições concorrentes +Testar recuperação de conexão + +**Serviços de Streaming** (`test_streaming_integration.py`): +Testar streaming de agentes (pensamentos, observações, respostas) +Testar streaming RAG (fragmentos incrementais) +Testar streaming de conclusão de texto (token por token) +Testar streaming de prompts +Testar tratamento de erros durante o streaming + +**Operações em Lote** (`test_bulk_integration.py`): +Testar importação/exportação em lote de triplas (1K, 10K, 100K itens) +Testar importação/exportação em lote de embeddings +Testar o uso de memória durante operações em lote +Testar o rastreamento de progresso + +### Testes de Desempenho + +**Benchmarks de Latência** (`test_performance_latency.py`): +Medir o tempo para o primeiro token (streaming vs não streaming) +Medir a sobrecarga de conexão (REST vs WebSocket) +Comparar com benchmarks esperados + +**Benchmarks de Throughput** (`test_performance_throughput.py`): +Medir o throughput de importação em lote +Medir a eficiência da multiplexação de requisições +Comparar com benchmarks esperados + +### Testes de Compatibilidade + +**Compatibilidade com Versões Anteriores** (`test_backward_compatibility.py`): +Executar o conjunto de testes existente contra a API refatorada +Verificar a ausência de alterações que quebrem a compatibilidade +Testar o caminho de migração para padrões comuns + +## Plano de Migração + +### Fase 1: Migração Transparente (Padrão) + +**Não são necessárias alterações no código**. O código existente continua a funcionar: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### Fase 2: Streaming Opcional (Simples) + +**Use a interface `api.socket()`** para habilitar o streaming: + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**Pontos-chave:** +Mesma URL para REST e WebSocket +Mesmas assinaturas de método (fácil migração) +Basta adicionar `.socket()` e `streaming=True` + +### Fase 3: Operações em Lote (Nova Funcionalidade) + +**Use a interface `api.bulk()`** para grandes conjuntos de dados: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### Atualizações na Documentação + +1. **README.md**: Adicionar exemplos de streaming e WebSocket +2. **Referência da API**: Documentar todos os novos métodos e parâmetros +3. **Guia de Migração**: Guia passo a passo para habilitar o streaming +4. **Exemplos**: Adicionar scripts de exemplo para padrões comuns +5. **Guia de Desempenho**: Documentar as melhorias de desempenho esperadas + +### Política de Descontinuação + +**Nenhuma descontinuação**. Todas as APIs existentes permanecem suportadas. Esta é uma melhoria pura. + +## Cronograma + +### Semana 1: Fundação +Camada de abstração de transporte +Refatorar o código REST existente +Testes unitários para a camada de transporte +Verificação de compatibilidade com versões anteriores + +### Semana 2: Transporte WebSocket +Implementação do transporte WebSocket +Gerenciamento de conexão e reconexão +Multiplexação de requisições +Testes unitários e de integração + +### Semana 3: Suporte a Streaming +Adicionar parâmetro de streaming aos métodos LLM +Implementar análise de resposta de streaming +Adicionar tipos de fragmentos de streaming +Testes de integração de streaming + +### Semana 4: Operações em Lote +Adicionar métodos de importação/exportação em lote +Implementar operações baseadas em iteradores +Testes de desempenho +Testes de integração de operações em lote + +### Semana 5: Paridade de Recursos e Documentação +Adicionar consulta de incorporações de grafos +Adicionar API de métricas +Documentação abrangente +Guia de migração +Versão candidata + +### Semana 6: Lançamento +Testes de integração finais +Benchmarking de desempenho +Documentação de lançamento +Anúncio para a comunidade + +**Duração Total**: 6 semanas + +## Perguntas Abertas + +### Perguntas de Design da API + +1. **Suporte Assíncrono**: ✅ **RESOLVIDO** - Suporte assíncrono completo incluído no lançamento inicial + Todas as interfaces possuem variantes assíncronas: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + Fornece total simetria entre as APIs síncronas e assíncronas + Essencial para frameworks assíncronos modernos (FastAPI, aiohttp) + +2. **Rastreamento de Progresso**: As operações em lote devem suportar callbacks de progresso? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **Recomendação**: Adicionar na Fase 2. Não é crítico para a versão inicial. + +3. **Tempo Limite de Streaming**: Como devemos tratar os tempos limite para operações de streaming? + **Recomendação**: Usar o mesmo tempo limite que as operações não-streaming, mas resetar a cada bloco recebido. + +4. **Bufferização de Blocos**: Devemos bufferizar os blocos ou retornar imediatamente? + **Recomendação**: Retornar imediatamente para a menor latência. + +5. **Serviços Globais via WebSocket**: `api.socket()` deve suportar serviços globais (biblioteca, conhecimento, coleção, configuração) ou apenas serviços específicos do fluxo? + **Recomendação**: Começar apenas com serviços específicos do fluxo (onde o streaming é importante). Adicionar serviços globais, se necessário, na Fase 2. + +### Perguntas de Implementação + +1. **Biblioteca WebSocket**: Devemos usar `websockets`, `websocket-client` ou `aiohttp`? + **Recomendação**: `websockets` (assíncrono, maduro, bem mantido). Envolver em uma interface síncrona usando `asyncio.run()`. + +2. **Pool de Conexões**: Devemos suportar múltiplas instâncias concorrentes de `Api` compartilhando um pool de conexões? + **Recomendação**: Adiar para a Fase 2. Cada instância de `Api` terá suas próprias conexões inicialmente. + +3. **Reutilização de Conexões**: `SocketClient` e `BulkClient` devem compartilhar a mesma conexão WebSocket, ou usar conexões separadas? + **Recomendação**: Conexões separadas. Implementação mais simples, separação mais clara de responsabilidades. + +4. **Conexão Preguiçosa vs. Ansiosa**: A conexão WebSocket deve ser estabelecida em `api.socket()` ou na primeira requisição? + **Recomendação**: Preguiçosa (na primeira requisição). Evita a sobrecarga da conexão se o usuário usar apenas métodos REST. + +### Perguntas de Teste + +1. **Gateway Mock**: Devemos criar um Gateway mock leve para testes, ou testar contra o Gateway real? + **Recomendação**: Ambos. Usar mocks para testes unitários, Gateway real para testes de integração. + +2. **Testes de Regressão de Desempenho**: Devemos adicionar testes de regressão de desempenho automatizados ao CI? + **Recomendação**: Sim, mas com limites generosos para levar em conta a variabilidade do ambiente do CI. + +## Referências + +### Especificações Técnicas Relacionadas +`docs/tech-specs/streaming-llm-responses.md` - Implementação de streaming no Gateway +`docs/tech-specs/rag-streaming-support.md` - Suporte de streaming RAG + +### Arquivos de Implementação +`trustgraph-base/trustgraph/api/` - Código fonte da API Python +`trustgraph-flow/trustgraph/gateway/` - Código fonte do Gateway +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - Implementação de referência de multiplexador WebSocket + +### Documentação +`docs/apiSpecification.md` - Referência completa da API +`docs/api-status-summary.md` - Resumo do status da API +`README.websocket` - Documentação do protocolo WebSocket +`STREAMING-IMPLEMENTATION-NOTES.txt` - Notas sobre a implementação de streaming + +### Bibliotecas Externas +`websockets` - Biblioteca WebSocket Python (https://websockets.readthedocs.io/) +`requests` - Biblioteca HTTP Python (existente) diff --git a/docs/tech-specs/python-api-refactor.ru.md b/docs/tech-specs/python-api-refactor.ru.md new file mode 100644 index 00000000..48e2ed1a --- /dev/null +++ b/docs/tech-specs/python-api-refactor.ru.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Python API Refactor Technical Specification" +parent: "Russian (Beta)" +--- + +# Python API Refactor 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 + +This specification describes a comprehensive refactor of the TrustGraph Python API client library to achieve feature parity with the API Gateway and add support for modern real-time communication patterns. + +The refactor addresses four primary use cases: + +1. **Streaming LLM Interactions**: Enable real-time streaming of LLM responses (agent, graph RAG, document RAG, text completion, prompts) with ~60x lower latency (500ms vs 30s for first token) +2. **Bulk Data Operations**: Support efficient bulk import/export of triples, graph embeddings, and document embeddings for large-scale knowledge graph management +3. **Feature Parity**: Ensure every API Gateway endpoint has a corresponding Python API method, including graph embeddings query +4. **Persistent Connections**: Enable WebSocket-based communication for multiplexed requests and reduced connection overhead + +## Goals + +**Feature Parity**: Every Gateway API service has a corresponding Python API method +**Streaming Support**: All streaming-capable services (agent, RAG, text completion, prompt) support streaming in Python API +**WebSocket Transport**: Add optional WebSocket transport layer for persistent connections and multiplexing +**Bulk Operations**: Add efficient bulk import/export for triples, graph embeddings, and document embeddings +**Full Async Support**: Complete async/await implementation for all interfaces (REST, WebSocket, bulk operations, metrics) +**Backward Compatibility**: Existing code continues to work without modification +**Type Safety**: Maintain type-safe interfaces with dataclasses and type hints +**Progressive Enhancement**: Streaming and async are opt-in via explicit interface selection +**Performance**: Achieve 60x latency improvement for streaming operations +**Modern Python**: Support for both sync and async paradigms for maximum flexibility + +## Background + +### Current State + +The Python API (`trustgraph-base/trustgraph/api/`) is a REST-only client library with the following modules: + +`flow.py`: Flow management and flow-scoped services (50 methods) +`library.py`: Document library operations (9 methods) +`knowledge.py`: KG core management (4 methods) +`collection.py`: Collection metadata (3 methods) +`config.py`: Configuration management (6 methods) +`types.py`: Data type definitions (5 dataclasses) + +**Total Operations**: 50/59 (85% coverage) + +### Current Limitations + +**Missing Operations**: +Graph embeddings query (semantic search over graph entities) +Bulk import/export for triples, graph embeddings, document embeddings, entity contexts, objects +Metrics endpoint + +**Missing Capabilities**: +Streaming support for LLM services +WebSocket transport +Multiplexed concurrent requests +Persistent connections + +**Performance Issues**: +High latency for LLM interactions (~30s time-to-first-token) +Inefficient bulk data transfer (REST request per item) +Connection overhead for multiple sequential operations + +**User Experience Issues**: +No real-time feedback during LLM generation +Cannot cancel long-running LLM operations +Poor scalability for bulk operations + +### Impact + +The November 2024 streaming enhancement to the Gateway API provided 60x latency improvement (500ms vs 30s first token) for LLM interactions, but Python API users cannot leverage this capability. This creates a significant experience gap between Python and non-Python users. + +## Technical Design + +### Architecture + +The refactored Python API uses a **modular interface approach** with separate objects for different communication patterns. All interfaces are available in both **synchronous and asynchronous** variants: + +1. **REST Interface** (existing, enhanced) + **Sync**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()` + **Async**: `api.async_flow()` + Synchronous/asynchronous request/response + Simple connection model + Default for backward compatibility + +2. **WebSocket Interface** (new) + **Sync**: `api.socket()` + **Async**: `api.async_socket()` + Persistent connection + Multiplexed requests + Streaming support + Same method signatures as REST where functionality overlaps + +3. **Bulk Operations Interface** (new) + **Sync**: `api.bulk()` + **Async**: `api.async_bulk()` + WebSocket-based for efficiency + Iterator/AsyncIterator-based import/export + Handles large datasets + +4. **Metrics Interface** (new) + **Sync**: `api.metrics()` + **Async**: `api.async_metrics()` + Prometheus metrics access + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**Основные принципы проектирования**: +**Одинаковый URL для всех интерфейсов**: `Api(url="http://localhost:8088/")` работает для всех. +**Симметрия синхронной/асинхронной работы**: Каждый интерфейс имеет как синхронные, так и асинхронные варианты с идентичными сигнатурами методов. +**Идентичные сигнатуры**: Там, где функциональность перекрывается, сигнатуры методов одинаковы для REST и WebSocket, а также для синхронных и асинхронных операций. +**Постепенное улучшение**: Выберите интерфейс в зависимости от потребностей (REST для простых задач, WebSocket для потоковой передачи данных, Bulk для больших наборов данных, асинхронный режим для современных фреймворков). +**Явное указание**: `api.socket()` указывает на WebSocket, `api.async_socket()` указывает на асинхронный WebSocket. +**Обратная совместимость**: Существующий код не изменяется. + +### Компоненты + +#### 1. Класс API (модифицированный) + +Модуль: `trustgraph-base/trustgraph/api/api.py` + +**Улучшенный класс API**: + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. Синхронный WebSocket-клиент + +Модуль: `trustgraph-base/trustgraph/api/socket_client.py` (новый) + +**Класс SocketClient**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Основные характеристики:** +Ленивое подключение (устанавливается только при отправке первого запроса) +Мультиплексирование запросов (до 15 одновременных) +Автоматическое переподключение при разрыве соединения +Потоковая обработка ответа +Потокобезопасная работа +Синхронная обертка вокруг асинхронной библиотеки веб-сокетов + +#### 3. Асинхронный клиент WebSocket + +Модуль: `trustgraph-base/trustgraph/api/async_socket_client.py` (новый) + +**Класс AsyncSocketClient:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Основные характеристики:** +Встроенная поддержка async/await +Эффективно для асинхронных приложений (FastAPI, aiohttp) +Отсутствие блокировок потоков +Тот же интерфейс, что и у синхронной версии +AsyncIterator для потоковой передачи + +#### 4. Клиент для синхронных пакетных операций + +Модуль: `trustgraph-base/trustgraph/api/bulk_client.py` (новый) + +**Класс BulkClient:** + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**Основные характеристики:** +Основан на итераторах для постоянного использования памяти. +Выделенные WebSocket-соединения для каждой операции. +Отслеживание прогресса (необязательный обратный вызов). +Обработка ошибок с частичным сообщением об успехе. + +#### 5. Асинхронный клиент массовых операций + +Модуль: `trustgraph-base/trustgraph/api/async_bulk_client.py` (новый) + +**Класс AsyncBulkClient:** + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**Основные характеристики:** +Основан на AsyncIterator для постоянного использования памяти. +Эффективен для асинхронных приложений. +Поддержка нативных асинхронных операций async/await. +Тот же интерфейс, что и у синхронной версии. + +#### 6. REST Flow API (Синхронный - Без изменений) + +Модуль: `trustgraph-base/trustgraph/api/flow.py` + +REST Flow API остается **полностью неизменным** для обеспечения обратной совместимости. Все существующие методы продолжают работать: + +`Flow.list()`, `Flow.start()`, `Flow.stop()` и т.д. +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()` и т.д. +Все существующие сигнатуры и типы возвращаемых значений сохранены. + +**Новое:** Добавьте `graph_embeddings_query()` в REST FlowInstance для обеспечения соответствия функциональности: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. Асинхронный REST API + +Модуль: `trustgraph-base/trustgraph/api/async_flow.py` (новый) + +**Классы AsyncFlow и AsyncFlowInstance**: + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**Основные характеристики:** +Асинхронные HTTP-запросы с использованием `aiohttp` или `httpx` +Те же сигнатуры методов, что и у синхронного REST API +Без потоковой передачи (используйте `async_socket()` для потоковой передачи) +Эффективно для асинхронных приложений + +#### 8. API метрик + +Модуль: `trustgraph-base/trustgraph/api/metrics.py` (новый) + +**Синхронные метрики:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**Асинхронные метрики**: + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. Улучшенные типы + +Модуль: `trustgraph-base/trustgraph/api/types.py` (изменен) + +**Новые типы**: + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. API метрик + +Модуль: `trustgraph-base/trustgraph/api/metrics.py` (новый) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### Подход к реализации + +#### Этап 1: Улучшение основного API (1 неделя) + +1. Добавить методы `socket()`, `bulk()` и `metrics()` в класс `Api` +2. Реализовать ленивую инициализацию для WebSocket и пакетных клиентов +3. Добавить поддержку менеджеров контекста (`__enter__`, `__exit__`) +4. Добавить метод `close()` для очистки +5. Добавить модульные тесты для улучшений API +6. Проверить обратную совместимость + +**Обратная совместимость**: Отсутствуют критические изменения. Только новые методы. + +#### Этап 2: WebSocket клиент (2-3 недели) + +1. Реализовать класс `SocketClient` с управлением подключением +2. Реализовать `SocketFlowInstance` с теми же сигнатурами методов, что и у `FlowInstance` +3. Добавить поддержку множественной отправки запросов (до 15 одновременных) +4. Добавить парсинг потоковых ответов для различных типов фрагментов +5. Добавить логику автоматического переподключения +6. Добавить модульные и интеграционные тесты +7. Добавить документацию по использованию WebSocket + +**Обратная совместимость**: Новый интерфейс. Отсутствует влияние на существующий код. + +#### Этап 3: Поддержка потоковой передачи (3-4 недели) + +1. Добавить классы для типов фрагментов потоковой передачи (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. Реализовать парсинг потоковых ответов в `SocketClient` +3. Добавить параметр потоковой передачи ко всем методам LLM в `SocketFlowInstance` +4. Обрабатывать ошибки во время потоковой передачи +5. Добавить модульные и интеграционные тесты для потоковой передачи +6. Добавить примеры потоковой передачи в документацию + +**Обратная совместимость**: Новый интерфейс. Существующий REST API не изменен. + +#### Этап 4: Пакетные операции (4-5 недели) + +1. Реализовать класс `BulkClient` +2. Добавить методы пакетного импорта/экспорта для троек, векторов, контекстов, объектов +3. Реализовать обработку с использованием итераторов для экономии памяти +4. Добавить отслеживание прогресса (необязательный обратный вызов) +5. Добавить обработку ошибок с отчетом о частичном успехе +6. Добавить модульные и интеграционные тесты +7. Добавить примеры пакетных операций + +**Обратная совместимость**: Новый интерфейс. Отсутствует влияние на существующий код. + +#### Этап 5: Обеспечение совместимости и доработка (5 неделя) + +1. Добавить `graph_embeddings_query()` в REST `FlowInstance` +2. Реализовать класс `Metrics` +3. Добавить комплексные интеграционные тесты +4. Проведение бенчмаркинга производительности +5. Обновить всю документацию +6. Создать руководство по миграции + +**Обратная совместимость**: Только новые методы. Отсутствует влияние на существующий код. + +### Модели данных + +#### Выбор интерфейса + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### Типы ответов потоковой передачи + +**Потоковая передача от агента**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**Потоковая передача RAG**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**Массовые операции (синхронные):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**Массовые операции (асинхронные):** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**Пример асинхронного REST:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**Пример асинхронной потоковой передачи данных через WebSocket:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### APIs + +#### New APIs + +1. **Класс API для основных операций**: + **Синхронный**: + `Api.socket()` - Получить синхронного клиента WebSocket + `Api.bulk()` - Получить синхронного клиента для пакетных операций + `Api.metrics()` - Получить синхронного клиента для метрик + `Api.close()` - Закрыть все синхронные соединения + Поддержка менеджера контекста (`__enter__`, `__exit__`) + **Асинхронный**: + `Api.async_flow()` - Получить асинхронного клиента REST flow + `Api.async_socket()` - Получить асинхронного клиента WebSocket + `Api.async_bulk()` - Получить асинхронного клиента для пакетных операций + `Api.async_metrics()` - Получить асинхронного клиента для метрик + `Api.aclose()` - Закрыть все асинхронные соединения + Поддержка асинхронного менеджера контекста (`__aenter__`, `__aexit__`) + +2. **Синхронный клиент WebSocket**: + `SocketClient.flow(flow_id)` - Получить экземпляр WebSocket flow + `SocketFlowInstance.agent(..., streaming: bool = False)` - Агент с опциональной потоковой передачей + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - Завершение текста с опциональной потоковой передачей + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG с опциональной потоковой передачей + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG с опциональной потоковой передачей + `SocketFlowInstance.prompt(..., streaming: bool = False)` - Prompt с опциональной потоковой передачей + `SocketFlowInstance.graph_embeddings_query()` - Запрос graph embeddings + Все остальные методы FlowInstance с идентичными сигнатурами + +3. **Асинхронный клиент WebSocket**: + `AsyncSocketClient.flow(flow_id)` - Получить асинхронный экземпляр WebSocket flow + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - Асинхронный агент с опциональной потоковой передачей + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - Асинхронное завершение текста с опциональной потоковой передачей + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - Асинхронный graph RAG с опциональной потоковой передачей + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - Асинхронный document RAG с опциональной потоковой передачей + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - Асинхронный prompt с опциональной потоковой передачей + `AsyncSocketFlowInstance.graph_embeddings_query()` - Асинхронный запрос graph embeddings + Все остальные методы FlowInstance как асинхронные версии + +4. **Синхронный клиент для пакетных операций**: + `BulkClient.import_triples(flow, triples)` - Пакетный импорт триплетов + `BulkClient.export_triples(flow)` - Пакетный экспорт триплетов + `BulkClient.import_graph_embeddings(flow, embeddings)` - Пакетный импорт graph embeddings + `BulkClient.export_graph_embeddings(flow)` - Пакетный экспорт graph embeddings + `BulkClient.import_document_embeddings(flow, embeddings)` - Пакетный импорт document embeddings + `BulkClient.export_document_embeddings(flow)` - Пакетный экспорт document embeddings + `BulkClient.import_entity_contexts(flow, contexts)` - Пакетный импорт entity contexts + `BulkClient.export_entity_contexts(flow)` - Пакетный экспорт entity contexts + `BulkClient.import_objects(flow, objects)` - Пакетный импорт объектов + +5. **Асинхронный клиент для пакетных операций**: + `AsyncBulkClient.import_triples(flow, triples)` - Асинхронный пакетный импорт триплетов + `AsyncBulkClient.export_triples(flow)` - Асинхронный пакетный экспорт триплетов + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - Асинхронный пакетный импорт graph embeddings + `AsyncBulkClient.export_graph_embeddings(flow)` - Асинхронный пакетный экспорт graph embeddings + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - Асинхронный пакетный импорт document embeddings + `AsyncBulkClient.export_document_embeddings(flow)` - Асинхронный пакетный экспорт document embeddings + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - Асинхронный пакетный импорт entity contexts + `AsyncBulkClient.export_entity_contexts(flow)` - Асинхронный пакетный экспорт entity contexts + `AsyncBulkClient.import_objects(flow, objects)` - Асинхронный пакетный импорт объектов + +6. **Асинхронный клиент REST Flow API**: + `AsyncFlow.list()` - Асинхронный список всех flows + `AsyncFlow.get(id)` - Асинхронное получение определения flow + `AsyncFlow.start(...)` - Асинхронный запуск flow + `AsyncFlow.stop(id)` - Асинхронная остановка flow + `AsyncFlow.id(flow_id)` - Получить асинхронный экземпляр flow + `AsyncFlowInstance.agent(...)` - Асинхронное выполнение агента + `AsyncFlowInstance.text_completion(...)` - Асинхронное завершение текста + `AsyncFlowInstance.graph_rag(...)` - Асинхронный graph RAG + Все остальные методы FlowInstance как асинхронные версии + +7. **Клиенты для метрик**: + `Metrics.get()` - Синхронные метрики Prometheus + `AsyncMetrics.get()` - Асинхронные метрики Prometheus + +8. **Улучшение REST Flow API**: + `FlowInstance.graph_embeddings_query()` - Запрос graph embeddings (синхронная функциональность) + `AsyncFlowInstance.graph_embeddings_query()` - Запрос graph embeddings (асинхронная функциональность) + +#### Измененные API + +1. **Конструктор** (незначительное улучшение): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + Добавлен параметр `token` (необязательный, для аутентификации). + Если `None` не указан (по умолчанию): аутентификация не используется. + Если указан: используется как токен доступа для REST (`Authorization: Bearer `), параметр запроса для WebSocket (`?token=`). + Других изменений нет - полностью обратно совместимо. + +2. **Отсутствие изменений, нарушающих обратную совместимость**: + Все существующие методы REST API не изменены. + Все существующие сигнатуры сохранены. + Все существующие типы возвращаемых значений сохранены. + +### Детали реализации + +#### Обработка ошибок + +**Ошибки подключения WebSocket**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**Плавный переход на резервный вариант**: +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**Частичные ошибки потоковой передачи**: +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### Управление ресурсами + +**Поддержка контекстных менеджеров**: +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### Многопоточность и параллелизм + +**Потоковая безопасность**: +Каждый экземпляр `Api` поддерживает собственное соединение. +Транспорт WebSocket использует блокировки для потокобезопасной мультиплексирования запросов. +Несколько потоков могут безопасно совместно использовать экземпляр `Api`. +Потоковые итераторы не являются потокобезопасными (используйте из одного потока). + +**Асинхронная поддержка** (планируется к реализации в будущем): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## Соображения безопасности + +### Аутентификация + +**Параметр токена**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**REST-транспорт:** +Токен передается через заголовок `Authorization` +Применяется автоматически ко всем REST-запросам +Формат: `Authorization: Bearer ` + +**WebSocket-транспорт:** +Токен передается через параметр запроса, добавляемый к URL WebSocket +Применяется автоматически во время установления соединения +Формат: `ws://localhost:8088/api/v1/socket?token=` + +**Реализация:** +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**Пример:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### Безопасная связь + +Поддержка схем WS (WebSocket) и WSS (WebSocket Secure). +Проверка сертификатов TLS для соединений WSS. +Опциональное отключение проверки сертификатов для разработки (с предупреждением). + +### Валидация входных данных + +Проверка схем URL (http, https, ws, wss). +Проверка значений параметров передачи данных. +Проверка комбинаций параметров потоковой передачи. +Проверка типов данных для массового импорта. + +## Вопросы производительности + +### Оптимизация задержки + +**Потоковые операции с LLM**: +**Время получения первого токена**: ~500 мс (против ~30 секунд без потоковой передачи). +**Улучшение**: Воспринимаемая производительность увеличена в 60 раз. +**Применимо к**: Agent, Graph RAG, Document RAG, Text Completion, Prompt. + +**Постоянные соединения**: +**Накладные расходы на соединение**: Устранены для последующих запросов. +**Установление WebSocket-соединения**: Единоразовая операция (~100 мс). +**Применимо к**: Всем операциям при использовании транспорта WebSocket. + +### Оптимизация пропускной способности + +**Массовые операции**: +**Импорт триплетов**: ~10 000 триплетов/секунду (против ~100/секунду с REST для каждого элемента). +**Импорт векторов**: ~5 000 векторов/секунду (против ~50/секунду с REST для каждого элемента). +**Улучшение**: Пропускная способность увеличена в 100 раз для массовых операций. + +**Множественная отправка запросов**: +**Параллельные запросы**: До 15 одновременных запросов через одно соединение. +**Повторное использование соединения**: Отсутствуют накладные расходы на соединение для параллельных операций. + +### Вопросы использования памяти + +**Потоковые ответы**: +Постоянное использование памяти (обработка фрагментов по мере их поступления). +Отсутствует буферизация полного ответа. +Подходит для очень длинных ответов (>1 МБ). + +**Массовые операции**: +Обработка с использованием итераторов (постоянное использование памяти). +Отсутствует загрузка всего набора данных в память. +Подходит для наборов данных с миллионами элементов. + +### Результаты тестирования (ожидаемые) + +| Операция | REST (существующий) | WebSocket (потоковая передача) | Улучшение | +|-----------|----------------|----------------------|-------------| +| Agent (время получения первого токена) | 30с | 0.5с | 60x | +| Graph RAG (время получения первого токена) | 25с | 0.5с | 50x | +| Импорт 10K триплетов | 100с | 1с | 100x | +| Импорт 1M триплетов | 10 000с (2.7ч) | 100с (1.6м) | 100x | +| 10 параллельных небольших запросов | 5с (последовательно) | 0.5с (параллельно) | 10x | + +## Стратегия тестирования + +### Модульные тесты + +**Транспортный уровень** (`test_transport.py`): +Проверка запросов и ответов REST +Проверка подключения WebSocket +Проверка повторного подключения WebSocket +Проверка мультиплексирования запросов +Проверка разбора потоковых ответов +Эмуляция WebSocket-сервера для детерминированных тестов + +**Методы API** (`test_flow.py`, `test_library.py` и т.д.): +Проверка новых методов с использованием эмулированного транспорта +Проверка обработки потоковых параметров +Проверка итераторов для пакетных операций +Проверка обработки ошибок + +**Типы данных** (`test_types.py`): +Проверка новых типов данных для потоковой передачи +Проверка сериализации/десериализации типов данных + +### Интеграционные тесты + +**Комплексные тесты REST** (`test_integration_rest.py`): +Проверка всех операций против реального шлюза (режим REST) +Проверка обратной совместимости +Проверка условий ошибок + +**Комплексные тесты WebSocket** (`test_integration_websocket.py`): +Проверка всех операций против реального шлюза (режим WebSocket) +Проверка операций потоковой передачи +Проверка пакетных операций +Проверка одновременных запросов +Проверка восстановления соединения + +**Сервисы потоковой передачи** (`test_streaming_integration.py`): +Проверка потоковой передачи данных агента (мысли, наблюдения, ответы) +Проверка потоковой передачи данных RAG (инкрементные фрагменты) +Проверка потоковой передачи текста (по токенам) +Проверка потоковой передачи запросов +Проверка обработки ошибок во время потоковой передачи + +**Пакетные операции** (`test_bulk_integration.py`): +Проверка пакетного импорта/экспорта троек (1K, 10K, 100K элементов) +Проверка пакетного импорта/экспорта векторных представлений +Проверка использования памяти во время пакетных операций +Проверка отслеживания прогресса + +### Тесты производительности + +**Бенчмарки задержки** (`test_performance_latency.py`): +Измерение времени до первого токена (потоковая передача против не потоковой передачи) +Измерение накладных расходов на подключение (REST против WebSocket) +Сравнение с ожидаемыми результатами + +**Бенчмарки пропускной способности** (`test_performance_throughput.py`): +Измерение пропускной способности пакетного импорта +Измерение эффективности мультиплексирования запросов +Сравнение с ожидаемыми результатами + +### Тесты совместимости + +**Обратная совместимость** (`test_backward_compatibility.py`): +Запуск существующего набора тестов против рефакторингованного API +Проверка отсутствия изменений, нарушающих обратную совместимость +Проверка пути миграции для распространенных сценариев + +## План миграции + +### Этап 1: Прозрачная миграция (по умолчанию) + +**Не требуется внесения изменений в код**. Существующий код продолжает работать: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### Фаза 2: Опциональная потоковая передача (простая) + +**Используйте интерфейс `api.socket()`** для включения потоковой передачи: + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**Основные моменты:** +Один и тот же URL для REST и WebSocket. +Одинаковые сигнатуры методов (простое переключение). +Просто добавьте `.socket()` и `streaming=True`. + +### Фаза 3: Массовые операции (Новая функциональность) + +**Используйте интерфейс `api.bulk()`** для больших наборов данных: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### Обновления документации + +1. **README.md**: Добавить примеры потоковой передачи и WebSockets +2. **Справочник API**: Описать все новые методы и параметры +3. **Руководство по миграции**: Пошаговое руководство по включению потоковой передачи +4. **Примеры**: Добавить примеры скриптов для распространенных сценариев +5. **Руководство по производительности**: Описать ожидаемые улучшения производительности + +### Политика устаревания + +**Нет устаревших функций**. Все существующие API остаются поддерживаемыми. Это чистое улучшение. + +## План + +### Неделя 1: Основа +Абстрактный слой транспорта +Рефакторинг существующего REST-кода +Юнит-тесты для слоя транспорта +Проверка обратной совместимости + +### Неделя 2: Транспорт WebSockets +Реализация транспорта WebSockets +Управление соединениями и повторное подключение +Мультиплексирование запросов +Юнит-тесты и интеграционные тесты + +### Неделя 3: Поддержка потоковой передачи +Добавить параметр потоковой передачи к методам LLM +Реализовать разбор потоковых ответов +Добавить типы потоковых фрагментов +Интеграционные тесты потоковой передачи + +### Неделя 4: Массовые операции +Добавить методы массового импорта/экспорта +Реализовать операции на основе итераторов +Тестирование производительности +Интеграционные тесты массовых операций + +### Неделя 5: Функциональная совместимость и документация +Добавить запрос графовых вложений +Добавить API метрик +Комплексная документация +Руководство по миграции +Кандидат в релиз + +### Неделя 6: Релиз +Заключительное интеграционное тестирование +Бенчмаркинг производительности +Документация к релизу +Объявление для сообщества + +**Общая продолжительность**: 6 недель + +## Открытые вопросы + +### Вопросы проектирования API + +1. **Поддержка асинхронности**: ✅ **РЕШЕНО** - Полная поддержка асинхронности включена в первоначальный релиз + Все интерфейсы имеют асинхронные варианты: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + Обеспечивает полную симметрию между синхронными и асинхронными API + Необходимо для современных асинхронных фреймворков (FastAPI, aiohttp) + +2. **Отслеживание прогресса**: Должны ли массовые операции поддерживать обратные вызовы для отслеживания прогресса? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **Рекомендация**: Добавить на Фазе 2. Не критично для первоначального релиза. + +3. **Таймаут потоковой передачи**: Как нам обрабатывать таймауты для операций потоковой передачи? + **Рекомендация**: Использовать тот же таймаут, что и для не-потоковой передачи, но сбрасывать его при получении каждого фрагмента. + +4. **Буферизация фрагментов**: Следует ли нам буферизовать фрагменты или выдавать их немедленно? + **Рекомендация**: Выдавать немедленно для достижения минимальной задержки. + +5. **Глобальные сервисы через WebSocket**: Должен ли `api.socket()` поддерживать глобальные сервисы (библиотека, знания, коллекция, конфигурация) или только сервисы, привязанные к потоку? + **Рекомендация**: Начать только с сервисов, привязанных к потоку (где важна потоковая передача). Добавить глобальные сервисы, если это потребуется, на Фазе 2. + +### Вопросы реализации + +1. **Библиотека WebSocket**: Следует ли нам использовать `websockets`, `websocket-client` или `aiohttp`? + **Рекомендация**: `websockets` (асинхронная, зрелая, хорошо поддерживаемая). Обернуть в синхронный интерфейс с использованием `asyncio.run()`. + +2. **Пул соединений**: Следует ли нам поддерживать несколько одновременных экземпляров `Api`, использующих общий пул соединений? + **Рекомендация**: Отложить до Фазы 2. Изначально каждый экземпляр `Api` имеет свои собственные соединения. + +3. **Повторное использование соединений**: Должны ли `SocketClient` и `BulkClient` использовать одно и то же WebSocket-соединение или отдельные соединения? + **Рекомендация**: Отдельные соединения. Более простая реализация, более четкое разделение ответственности. + +4. **Ленивое vs. Активное соединение**: Должно ли WebSocket-соединение устанавливаться в `api.socket()` или при первом запросе? + **Рекомендация**: Ленивое (при первом запросе). Избегает накладных расходов на соединение, если пользователь использует только методы REST. + +### Вопросы тестирования + +1. **Моковый шлюз**: Следует ли нам создать легковесный моковый шлюз для тестирования или тестировать против реального шлюза? + **Рекомендация**: Оба варианта. Использовать моки для модульных тестов и реальный шлюз для интеграционных тестов. + +2. **Автоматизированные тесты регрессии производительности**: Следует ли нам добавить автоматизированные тесты регрессии производительности в CI? + **Рекомендация**: Да, но с достаточно большими допусками, чтобы учитывать изменчивость среды CI. + +## Ссылки + +### Связанные технические спецификации +`docs/tech-specs/streaming-llm-responses.md` - Реализация потоковой передачи в шлюзе +`docs/tech-specs/rag-streaming-support.md` - Поддержка потоковой передачи RAG + +### Файлы реализации +`trustgraph-base/trustgraph/api/` - Исходный код API на Python +`trustgraph-flow/trustgraph/gateway/` - Исходный код шлюза +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - Пример реализации мультиплексора WebSocket + +### Документация +`docs/apiSpecification.md` - Полная справочная документация API +`docs/api-status-summary.md` - Краткое описание статуса API +`README.websocket` - Документация протокола WebSocket +`STREAMING-IMPLEMENTATION-NOTES.txt` - Заметки о реализации потоковой передачи + +### Внешние библиотеки +`websockets` - Библиотека WebSocket на Python (https://websockets.readthedocs.io/) +`requests` - HTTP-библиотека на Python (существующая) diff --git a/docs/tech-specs/python-api-refactor.sw.md b/docs/tech-specs/python-api-refactor.sw.md new file mode 100644 index 00000000..c7889b64 --- /dev/null +++ b/docs/tech-specs/python-api-refactor.sw.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Vipangilio vya Kisaikolojia la API ya Python" +parent: "Swahili (Beta)" +--- + +# Vipangilio vya Kisaikolojia la API ya Python + +> **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 + +Vipangilio hivi vinaelezea marekebisho kamili ya maktaba ya mteja wa API ya Python ya TrustGraph ili kufikia utendaji sawa na API Gateway na kuongeza ufuatiliaji wa mitindo ya kisasa ya mawasiliano ya muda halisi. + +Marekebisho haya yanashughulikia matumizi manne makuu: + +1. **Mwingiliano wa LLM wa Msururu**: Ruhusu utiririshaji wa wakati halisi wa majibu ya LLM (wakala, RAG ya chati, RAG ya hati, kukamilisha maandishi, maagizo) na kuchelewesha chini ya ~60x (500ms dhidi ya 30s kwa tokeni ya kwanza) +2. **Operesheni za Data za Kiasi**: Unga uingizaji/utoaji wa data nyingi wa triples, uingizaji wa chati, na uingizaji wa hati kwa usimamizi wa grafu kubwa. +3. **Ulinganishi wa Vipengele**: Hakikisha kila mwisho wa API Gateway una mbinu inayolingana ya API ya Python, pamoja na swali la uingizaji wa chati. +4. **Miunganisho ya Kudumu**: Ruhusu mawasiliano ya WebSocket kwa maombi ya kuzingatia na kupunguza gharama ya muunganisho. + +## Lengo + +**Ulinganishi wa Vipengele**: Huduma kila Gateway API ina mbinu inayolingana ya API ya Python +**Ufuatiliaji**: Huduma zote za ufuatiliaji (wakala, RAG, kukamilisha maandishi, agizo) zinaunga mkono ufuatiliaji katika API ya Python +**Usafirishaji wa WebSocket**: Ongeza safu ya usafirishaji ya hiari ya WebSocket kwa miunganisho ya kudumu na kuzingatia +**Operesheni za Kiasi**: Ongeza uingizaji/utoaji wa data nyingi wa triples, uingizaji wa chati, na uingizaji wa hati +**Ufuatiliaji Kamili**: Utekelezaji kamili wa async/wait kwa interfaces zote (REST, WebSocket, operesheni za kiasi, metrics) +**Ulinganisho na Msimu wa Uendeshaji**: Msimu wa uendeshaji wa sasa unaendelea kufanya kazi bila mabadiliko +**Usalama wa Aina**: Dumishe interfaces za usalama wa aina na dataclasses na vidokezo vya aina +**Uboreshaji wa Hatua kwa Hatua**: Ufuatiliaji na async ni chaguo kupitia uteuzi wa wazi wa interface +**Utendaji**: Pata uboreshaji wa kuchelewesha wa 60x kwa operesheni za ufuatiliaji +**Python ya Kisasa**: Usaidizi wa paradigm za sync na async kwa uwezekano mwingi + +## Asili + +### Hali ya Sasa + +API ya Python (`trustgraph-base/trustgraph/api/`) ni maktaba ya mteja ya REST pekee na moduli zifuatazo: + +`flow.py`: Usimamizi wa mtiririko na huduma za mtiririko (mbinu 50) +`library.py`: Operesheni za maktaba ya hati (mbinu 9) +`knowledge.py`: Usimamizi wa msingi wa KG (mbinu 4) +`collection.py`: Metadata ya mkusanyiko (mbinu 3) +`config.py`: Usimamizi wa usanidi (mbinu 6) +`types.py`: Ufafanuzi wa aina ya data (dataclasses 5) + +**Operesheni Jumla**: 50/59 (ufafanuzi wa 85%) + +### Mapungufu ya Sasa + +**Operesheni Zinazokosekana**: +Swali la uingizaji wa chati (utafutaji wa kiufundi juu ya vitu vya chati) +Uingizaji/utoaji wa data nyingi wa triples, uingizaji wa chati, uingizaji wa hati, muktadha wa vitu, vitu +Mwisho wa metrics + +**Uwezekano Usio Kutosha**: +Usaidizi wa utiririshaji kwa huduma za LLM +Usafirishaji wa WebSocket +Maombi mengi yanayotendua wakati mmoja +Muunganisho unaoendelea + +**Matatizo ya Utendaji**: +Kuchelewesha kwa muda kwa mwingiliano wa LLM (~sekunde 30 hadi tokeni ya kwanza) +Usafirishaji usio na ufanisi wa data kwa wingi (ombi la REST kwa kila kipengele) +Mizigo ya muunganisho kwa operesheni nyingi mfululizo + +**Matatizo ya Uzoefu wa Mtumiaji**: +Hakuna maoni ya wakati halisi wakati wa uzalishaji wa LLM +Haiwezekani kughairi operesheni ndefu za LLM +Uwezo duni wa kuongezeka kwa operesheni kwa wingi + +### Athari + +Uboresho wa utiririshaji wa Novemba 2024 kwa API ya Gateway uliweka uboreshaji wa ucheleweshaji wa mara 60 (ms 500 dhidi ya sekunde 30 ya tokeni ya kwanza) kwa mwingiliano wa LLM, lakini watumiaji wa API ya Python hawawezi kutumia uwezo huu. Hii huunda pengo kubwa la uzoefu kati ya watumiaji wa Python na wasio wa Python. + +## Muundo wa Kiufundi + +### Usanifu + +API ya Python iliyoboreshwa hutumia **mbinu ya kiolesura ya moduli** na vitu tofauti kwa mifumo tofauti ya mawasiliano. Violesho vyote vinapatikana katika matoleo **ya wakati mmoja na ya isiyo ya wakati mmoja**: + +1. **Kiolesho cha REST** (kipo, kimeboreshwa) + **Sync**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()` + **Async**: `api.async_flow()` + Ombi/jibu la wakati mmoja/la isiyo ya wakati mmoja + Mfumo rahisi wa muunganisho + Chaguo-msingi kwa utangamano wa nyuma + +2. **Kiolesho cha WebSocket** (kipo) + **Sync**: `api.socket()` + **Async**: `api.async_socket()` + Muunganisho unaoendelea + Maombi yaliyounganishwa + Usaidizi wa utiririshaji + Alama sawa za mbinu kama REST ambapo utendaji unapanuka + +3. **Kiolesho cha Operesheni kwa Wingi** (kipo) + **Sync**: `api.bulk()` + **Async**: `api.async_bulk()` + Kulingana na WebSocket kwa ufanisi + Import/export kulingana na Iterator/AsyncIterator + Hushughulikia data kubwa + +4. **Kiolesho cha Metrics** (kipo) + **Sync**: `api.metrics()` + **Async**: `api.async_metrics()` + Ufikiaji wa metrics ya Prometheus + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**Kanuni Muhimu za Ubunifu**: +**URL moja kwa kila aina ya muunganisho**: `Api(url="http://localhost:8088/")` inafanya kazi kwa aina zote. +**Ulinganisho kati ya utendaji wa papo hapo na usio wa papo hapo**: Kila aina ya muunganisho ina matoleo ya utendaji wa papo hapo na yasiyo wa papo hapo yenye saini sawa za mbinu. +**Saini sawa**: Pale ambapo utendaji unapanuka, saini za mbinu ni sawa kati ya REST na WebSocket, utendaji wa papo hapo na usio wa papo hapo. +**Uboreshaji wa hatua kwa hatua**: Chagua aina ya muunganisho kulingana na mahitaji (REST kwa mambo rahisi, WebSocket kwa utiririshaji, Bulk kwa data kubwa, utendaji usio wa papo hapo kwa mifumo ya kisasa). +**Lengo lililo wazi**: `api.socket()` inaonyesha WebSocket, `api.async_socket()` inaonyesha WebSocket ya utendaji usio wa papo hapo. +**Inafaa na mifumo ya zamani**: Msimbo uliopo haubahatishwi. + +### Vipengele + +#### 1. Darasa la API Kuu (Imebadilishwa) + +Moduli: `trustgraph-base/trustgraph/api/api.py` + +**Darasa la API Lililoboreshwa**: + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. Mteja wa WebSocket wa Moja kwa Moja + +Moduli: `trustgraph-base/trustgraph/api/socket_client.py` (mpya) + +**Darasa la SocketClient**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Sifa Muhimu**: +Muunganisho wa polepole (unaunganisha tu wakati ombi la kwanza lilitumwa) +Uunganishaji wa ombi ( hadi 15 ufuatiliaji) +Muunganisho wa kiotomatiki unapokatika +Uchanganuzi wa jibu la utiririshaji +Uendeshaji salama wa uzi +Kifungashio cha usawisi kwa maktaba ya websockets isiyo na usawisi + +#### 3. Mteja wa WebSocket Usio na Usawisi + +Moduli: `trustgraph-base/trustgraph/api/async_socket_client.py` (mpya) + +**Darasa la AsyncSocketClient**: + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Sifa Muhimu**: +Usaidizi wa asilia wa async/await. +Ufanisi kwa matumizi ya async (FastAPI, aiohttp). +Hakuna kuzuiliwa kwa uzi. +Muundo sawa na toleo la sync. +AsyncIterator kwa utiririshaji. + +#### 4. Mteja wa Operesheni za Kiasi za Synchronous + +Moduli: `trustgraph-base/trustgraph/api/bulk_client.py` (mpya) + +**Darasa la BulkClient**: + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**Sifa Muhimu**: +Inatumia itereja ili kuhakikisha matumizi thabiti ya kumbukumbu. +Miunganisho maalum ya WebSocket kwa kila operesheni. +Ufuatiliaji wa maendeleo (rudisho la hiari). +Usimamizi wa makosa na ripoti ya mafanikio ya kiasi. + +#### 5. Mteja wa Operesheni za Kiasi za Asynchronous + +Moduli: `trustgraph-base/trustgraph/api/async_bulk_client.py` (mpya) + +**Darasa la AsyncBulkClient**: + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**Sifa Muhimu**: +Inatumia AsyncIterator kwa matumizi thabiti ya kumbukumbu. +Inafaa kwa matumizi ya asynchronous. +Inasaidia natively async/await. +Ina interface sawa na toleo la synchronous. + +#### 6. API ya Mtiririko wa REST (Synchronous - Haibadiliki) + +Moduli: `trustgraph-base/trustgraph/api/flow.py` + +API ya Mtiririko wa REST inabaki **haiibadiliki kabisa** kwa utangamano wa nyuma. Njia zote zilizopo zinaendelea kufanya kazi: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, n.k. +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, n.k. +Alama zote zilizopo na aina za kurudi zimehifadhiwa. + +**Mpya**: Ongeza `graph_embeddings_query()` kwenye REST FlowInstance kwa utangamano wa vipengele: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. API ya Mtiririko wa REST Asynchronous + +Moduli: `trustgraph-base/trustgraph/api/async_flow.py` (mpya) + +**Darasa za AsyncFlow na AsyncFlowInstance**: + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**Vipengele Muhimu**: +Matumizi ya HTTP ya asinkroniki kwa kutumia `aiohttp` au `httpx` +Sauti sawa za mbinu kama API ya REST ya taslimu +Hakuna utiririshaji (tumia `async_socket()` kwa utiririshaji) +Inafaa kwa programu za asinkroniki + +#### 8. API ya Vipimo + +Moduli: `trustgraph-base/trustgraph/api/metrics.py` (mpya) + +**Vipimo vya Taslimu**: + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**Vipimo Visivyokuwa na Tatizo la Muda (Asynchronous)**: + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. Aina Zilizoboreshwa + +Moduli: `trustgraph-base/trustgraph/api/types.py` (iliyorekebishwa) + +**Aina Mpya**: + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. API ya Vipimo + +Moduli: `trustgraph-base/trustgraph/api/metrics.py` (mpya) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### Mbinu ya Utendaji + +#### Awamu ya 1: Kuboresha API Kuu (Wiki ya 1) + +1. Ongeza mbinu za `socket()`, `bulk()`, na `metrics()` kwenye darasa la `Api` +2. Lenga utekelezaji wa lazima kwa wateja wa WebSocket na wa wingi +3. Ongeza usaidizi wa meneja wa muktadha (`__enter__`, `__exit__`) +4. Ongeza mbinu ya `close()` kwa usafi +5. Ongeza vipimo vya kitengo kwa maboresho ya darasa la API +6. Hakikisha utangamano wa nyuma + +**Utangamano wa Nyuma**: Hakuna mabadiliko ya kuvunja. Mbinu mpya tu. + +#### Awamu ya 2: Mteja wa WebSocket (Wiki ya 2-3) + +1. Lenga darasa la `SocketClient` na usimamizi wa muunganisho +2. Lenga `SocketFlowInstance` na maelezo sawa kama `FlowInstance` +3. Ongeza usaidizi wa uongezaji wa ombi ( hadi 15 sambamba) +4. Ongeza uchanganuzi wa jibu la utiririsho kwa aina tofauti za sehemu +5. Ongeza mantiki ya kuunganisha tena kiotomatiki +6. Ongeza vipimo na ujumuishaji +7. Andika mifumo ya matumizi ya WebSocket + +**Utangamano wa Nyuma**: Kiolesura kipya tu. Hakuna athari kwenye msimbo uliopo. + +#### Awamu ya 3: Usaidizi wa Utiririsho (Wiki ya 3-4) + +1. Ongeza darasa za aina ya sehemu ya utiririsho (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. Lenga uchanganuzi wa jibu la utiririsho katika `SocketClient` +3. Ongeza parameter ya utiririsho kwa mbinu zote za LLM katika `SocketFlowInstance` +4. Shughulikia hali za hitilafu wakati wa utiririsho +5. Ongeza vipimo na ujumuishaji kwa utiririsho +6. Ongeza mifano ya utiririsho kwenye hati + +**Utangamano wa Nyuma**: Kiolesura kipya tu. API ya REST iliyopo haibadiliki. + +#### Awamu ya 4: Operesheni za Wingi (Wiki ya 4-5) + +1. Lenga darasa la `BulkClient` +2. Ongeza mbinu za uagizaji/uangavu wa wingi kwa triples, embeddings, muktadha, vitu +3. Lenga usindikaji unaotegemea iterator kwa kumbukumbu thabiti +4. Ongeza ufuatiliaji wa maendeleo (callback ya hiari) +5. Ongeza ushughulikiaji wa hitilafu na ripoti ya mafanikio ya sehemu +6. Ongeza vipimo na ujumuishaji +7. Ongeza mifano ya operesheni za wingi + +**Utangamano wa Nyuma**: Kiolesura kipya tu. Hakuna athari kwenye msimbo uliopo. + +#### Awamu ya 5: Ulinganishi wa Vipengele na Uboreshaji (Wiki ya 5) + +1. Ongeza `graph_embeddings_query()` kwa `FlowInstance` ya REST +2. Lenga darasa la `Metrics` +3. Ongeza vipimo vya ujumuishaji vya kina +4. Upimaji wa utendaji +5. Sasisha hati zote +6. Unda mwongozo wa uhamishaji + +**Utangamano wa Nyuma**: Mbinu mpya tu. Hakuna athari kwenye msimbo uliopo. + +### Mifano ya Data + +#### Uchaguzi wa Kiolesura + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### Aina za Majibu ya Utiririshaji + +**Utiririshaji wa Wakala:** + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**Utiririshaji wa RAG**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**Operesheni za Kiasi (Zinazofanya kazi kwa wakati mmoja):** + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**Operesheni za Kiasi (Zisizo za Moja kwa Moja)**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**Mfano wa REST Asynchronous**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**Mfano wa Utiririshaji wa WebSocket Asynchronous**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### APIs + +#### New APIs + +1. **Darasa la API Kuu**: + **Synchronous (Moja kwa Moja)**: + `Api.socket()` - Pata mteja wa WebSocket moja kwa moja + `Api.bulk()` - Pata mteja wa shughuli kubwa moja kwa moja + `Api.metrics()` - Pata mteja wa metriki moja kwa moja + `Api.close()` - Funga miunganisho yote moja kwa moja + Usaidizi wa meneja wa muktadha (`__enter__`, `__exit__`) + **Asynchronous (Isiyo Moja kwa Moja)**: + `Api.async_flow()` - Pata mteja wa mtiririko wa REST isiyo moja kwa moja + `Api.async_socket()` - Pata mteja wa WebSocket isiyo moja kwa moja + `Api.async_bulk()` - Pata mteja wa shughuli kubwa isiyo moja kwa moja + `Api.async_metrics()` - Pata mteja wa metriki isiyo moja kwa moja + `Api.aclose()` - Funga miunganisho yote isiyo moja kwa moja + Usaidizi wa meneja wa muktadha isiyo moja kwa moja (`__aenter__`, `__aexit__`) + +2. **Mteja wa WebSocket Moja kwa Moja**: + `SocketClient.flow(flow_id)` - Pata mfano wa mtiririko wa WebSocket + `SocketFlowInstance.agent(..., streaming: bool = False)` - Wakala na utiririshaji wa hiari + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - Kukamilisha maandishi na utiririshaji wa hiari + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG na utiririshaji wa hiari + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG na utiririshaji wa hiari + `SocketFlowInstance.prompt(..., streaming: bool = False)` - Ombi na utiririshaji wa hiari + `SocketFlowInstance.graph_embeddings_query()` - Uchunguzi wa embeddings ya grafu + Njia zingine zote za FlowInstance na saini sawa + +3. **Mteja wa WebSocket Isiyo Moja kwa Moja**: + `AsyncSocketClient.flow(flow_id)` - Pata mfano wa mtiririko wa WebSocket isiyo moja kwa moja + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - Wakala isiyo moja kwa moja na utiririshaji wa hiari + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - Kukamilisha maandishi isiyo moja kwa moja na utiririshaji wa hiari + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - Async graph RAG na utiririshaji wa hiari + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - Async document RAG na utiririshaji wa hiari + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - Ombi isiyo moja kwa moja na utiririshaji wa hiari + `AsyncSocketFlowInstance.graph_embeddings_query()` - Uchunguzi wa embeddings ya grafu isiyo moja kwa moja + Njia zingine zote za FlowInstance kama matoleo isiyo moja kwa moja + +4. **Mteja wa Shughuli Kubwa Moja kwa Moja**: + `BulkClient.import_triples(flow, triples)` - Uingizaji wa triple kubwa + `BulkClient.export_triples(flow)` - Utoaji wa triple kubwa + `BulkClient.import_graph_embeddings(flow, embeddings)` - Uingizaji wa embeddings kubwa ya grafu + `BulkClient.export_graph_embeddings(flow)` - Utoaji wa embeddings kubwa ya grafu + `BulkClient.import_document_embeddings(flow, embeddings)` - Uingizaji wa embeddings kubwa za hati + `BulkClient.export_document_embeddings(flow)` - Utoaji wa embeddings kubwa za hati + `BulkClient.import_entity_contexts(flow, contexts)` - Uingizaji wa muktadha mkubwa wa vitu + `BulkClient.export_entity_contexts(flow)` - Utoaji wa muktadha mkubwa wa vitu + `BulkClient.import_objects(flow, objects)` - Uingizaji wa vitu kubwa + +5. **Mteja wa Shughuli Kubwa Isiyo Moja kwa Moja**: + `AsyncBulkClient.import_triples(flow, triples)` - Uingizaji wa triple kubwa isiyo moja kwa moja + `AsyncBulkClient.export_triples(flow)` - Utoaji wa triple kubwa isiyo moja kwa moja + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - Uingizaji wa embeddings kubwa ya grafu isiyo moja kwa moja + `AsyncBulkClient.export_graph_embeddings(flow)` - Utoaji wa embeddings kubwa ya grafu isiyo moja kwa moja + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - Uingizaji wa embeddings kubwa za hati isiyo moja kwa moja + `AsyncBulkClient.export_document_embeddings(flow)` - Utoaji wa embeddings kubwa za hati isiyo moja kwa moja + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - Uingizaji wa muktadha mkubwa wa vitu isiyo moja kwa moja + `AsyncBulkClient.export_entity_contexts(flow)` - Utoaji wa muktadha mkubwa wa vitu isiyo moja kwa moja + `AsyncBulkClient.import_objects(flow, objects)` - Uingizaji wa vitu kubwa isiyo moja kwa moja + +6. **Mteja wa Mtiririko wa REST Isiyo Moja kwa Moja**: + `AsyncFlow.list()` - Orodha ya mtiririko wote isiyo moja kwa moja + `AsyncFlow.get(id)` - Pata ufafanuzi wa mtiririko + `AsyncFlow.start(...)` - Anzisha mtiririko + `AsyncFlow.stop(id)` - Simamisha mtiririko + `AsyncFlow.id(flow_id)` - Pata mfano wa mtiririko + `AsyncFlowInstance.agent(...)` - Utendaji wa wakala + `AsyncFlowInstance.text_completion(...)` - Kukamilisha maandishi + `AsyncFlowInstance.graph_rag(...)` - Graph RAG + Njia zingine zote za FlowInstance kama matoleo isiyo moja kwa moja + +7. **Wateja wa Metriki**: + `Metrics.get()` - Metriki za Prometheus moja kwa moja + `AsyncMetrics.get()` - Metriki za Prometheus isiyo moja kwa moja + +8. **Uboreshaji wa API ya Mtiririko wa REST**: + `FlowInstance.graph_embeddings_query()` - Uchunguzi wa embeddings ya grafu (ufanano wa kipengele cha moja kwa moja) + `AsyncFlowInstance.graph_embeddings_query()` - Uchunguzi wa embeddings ya grafu (ufanano wa kipengele cha isiyo moja kwa moja) + +#### APIs Iliyorekebishwa + +1. **Mawasiliano** (uboreshaji mdogo): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + Imeongezwa parameter `token` (hiari, kwa ajili ya uthibitishaji). + Ikiwa `None` (kiwango chachilia): Hakuna uthibitishaji unaotumika. + Ikiwa imeingizwa: Inatumika kama tokeni ya "bearer" kwa REST (`Authorization: Bearer `), parameter ya swali kwa WebSocket (`?token=`). + Hakuna mabadiliko mengine - inafaa kabisa na matoleo ya awali. + +2. **Hakuna Mabadiliko Yanayoweza Kusababisha Tatizo**: + Njia zote za API za REST zilizopo hazijabadilika. + Alama zote zilizopo zimehifadhiwa. + Aina zote za matokeo zilizopo zimehifadhiwa. + +### Maelezo ya Utendaji + +#### Usimamizi wa Madhira + +**Madhira ya Muunganisho wa WebSocket**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**Rudi Nyuma kwa Ufasaha**: +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**Hitilafu za Uhamisho wa Takwimu:** +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### Usimamizi wa Rasilimali + +**Usaidizi wa Kidhibiti wa Mazingira:** +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### Uunganishaji na Uendeshaji Sambamba + +**Ulinzi wa Mfumo wa Uendeshaji (Thread Safety)**: +Kila mfano wa `Api` huendeleza muunganisho wake mwenyewe. +Usafirishaji wa WebSocket hutumia kufuli kwa ajili ya uunganishaji salama wa ombi. +Mitandao mingi inaweza kushiriki mfano wa `Api` kwa usalama. +Iterators za utiririshaji hazina ulinzi wa mfumo wa uendeshaji (zinatumika kutoka kwenye mtandao mmoja). + +**Usaidizi wa Async** (tazama baadaye): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## Mambo ya Kuzingatia ya Usalama + +### Uthibitisho + +**Parameta ya Tokeni**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**Usafirishaji (Transport) wa REST:** +Alama ya utambulisho (Bearer token) kupitia kichwa (header) cha `Authorization` +Inatumika kiotomatiki kwa ombi zote za REST +Muundo: `Authorization: Bearer ` + +**Usafirishaji (Transport) wa WebSocket:** +Alama ya utambulisho (Token) kupitia parameter ya swali (query parameter) iliyoongezwa kwenye URL ya WebSocket +Inatumika kiotomatiki wakati wa kuunganisha +Muundo: `ws://localhost:8088/api/v1/socket?token=` + +**Utekelezaji (Implementation):** +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**Mfano**: +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### Mawasiliano Salama + +Inasaidia mifumo ya WS (WebSocket) na WSS (WebSocket Secure). +Uthibitisho wa cheti cha TLS kwa miunganisho ya WSS. +Uthibitisho wa cheti unaweza kuzimwa (hiari) kwa ajili ya maendeleo (na onyo). + +### Uthibitisho wa Data + +Uthibitisho wa aina za URL (http, https, ws, wss). +Uthibitisho wa thamani za vigezo vya usafirishaji. +Uthibitisho wa mchanganyiko wa vigezo vya utiririshaji. +Uthibitisho wa aina za data za uagizaji wa jumla. + +## Masuala ya Utendaji + +### Uboreshaji wa Ucheleweshaji + +**Operesheni za LLM za Utiririshaji**: +**Wakati wa tokeni ya kwanza**: ~500ms (dhidi ya ~30s bila utiririshaji) +**Uboreshaji**: Mara 60 haraka kuliko utendaji unaohisiwa. +**Inatumika kwa**: Wakala, Graph RAG, Document RAG, Kukamilisha Nakala, Ombi. + +**Miunganisho ya Kudumu**: +**Mzigo wa muunganisho**: Huondolewa kwa ombi zijazo. +**Utambulisho wa WebSocket**: Gharama ya mara moja (~100ms). +**Inatumika kwa**: Operesheni zote wakati wa kutumia usafirishaji wa WebSocket. + +### Uboreshaji wa Kiasi + +**Operesheni za Jumla**: +**Uagizaji wa triples**: ~10,000 triples/sekunde (dhidi ya ~100/sekunde na REST kwa kila kipengele). +**Uagizaji wa embeddings**: ~5,000 embeddings/sekunde (dhidi ya ~50/sekunde na REST kwa kila kipengele). +**Uboreshaji**: Mara 100 ya kasi kwa operesheni za jumla. + +**Uongezaji wa Maombi**: +**Maombi sambamba**: Hadi maombi 15 sambamba juu ya muunganisho mmoja. +**Matumizi ya muunganisho**: Hakuna mzigo wa muunganisho kwa operesheni sambamba. + +### Masuala ya Kumbukumbu + +**Majibu ya Utiririshaji**: +Matumizi ya kumbukumbu thabiti (prosesa vipande kadri wanavyofika). +Hakuna kuhifadhi kwa jibu kamili. +Inafaa kwa matokeo marefu sana (>1MB). + +**Operesheni za Jumla**: +Uchakataji wa msingi (matumizi ya kumbukumbu thabiti). +Hakuna kupakia kwa seti data yote kwenye kumbukumbu. +Inafaa kwa seti data zilizo na milioni ya vipengele. + +### Vipimo (Yanatarajiwa) + +| Operesheni | REST (ya sasa) | WebSocket (ya utiririshaji) | Uboreshaji | +|-----------|----------------|----------------------|-------------| +| Wakala (wakati wa tokeni ya kwanza) | 30s | 0.5s | 60x | +| Graph RAG (wakati wa tokeni ya kwanza) | 25s | 0.5s | 50x | +| Uagizaji wa triples 10K | 100s | 1s | 100x | +| Uagizaji wa triples 1M | 10,000s (2.7h) | 100s (1.6m) | 100x | +| Maombi madogo 10 sambamba | 5s (mfululizo) | 0.5s (sambamba) | 10x | + +## Mkakati wa Majaribio + +### Majaribio ya Kitengo + +**Safu ya Usafirishaji** (`test_transport.py`): +Jaribu ombi na majibu ya usafirishaji wa REST +Jaribu muunganisho wa usafirishaji wa WebSocket +Jaribu muunganisho wa upya wa usafirishaji wa WebSocket +Jaribu uunganishaji wa ombi +Jaribu uchanganuzi wa majibu ya utiririshaji +Unda seva bandia ya WebSocket kwa vipimo vya uhakika + +**Mbinu za API** (`test_flow.py`, `test_library.py`, n.k.): +Jaribu mbinu mpya ukitumia usafirishaji bandia +Jaribu usimamizi wa vigezo vya utiririshaji +Jaribu vichanganuzi vya operesheni za wingi +Jaribu usimamizi wa makosa + +**Aina** (`test_types.py`): +Jaribu aina mpya za vipande vya utiririshaji +Jaribu userikali/kusierikisha aina + +### Vipimo vya Uunganisho + +**REST Kamili** (`test_integration_rest.py`): +Jaribu operesheni zote dhidi ya Lango halisi (mode ya REST) +Hakikisha utangamano wa nyuma +Jaribu hali za makosa + +**WebSocket Kamili** (`test_integration_websocket.py`): +Jaribu operesheni zote dhidi ya Lango halisi (mode ya WebSocket) +Jaribu operesheni za utiririshaji +Jaribu operesheni za wingi +Jaribu ombi la wakati mmoja +Jaribu urejesho wa muunganisho + +**Huduma za Utiririshaji** (`test_streaming_integration.py`): +Jaribu utiririshaji wa wakala (mawazo, uchunguzi, majibu) +Jaribu utiririshaji wa RAG (vipande vya hatua kwa hatua) +Jaribu utiririshaji wa kukamilisha maandishi (token kwa token) +Jaribu utiririshaji wa ombi +Jaribu usimamizi wa makosa wakati wa utiririshaji + +**Operesheni za Wingi** (`test_bulk_integration.py`): +Jaribu uingizaji/utoaji wa wingi wa vitri (vitu 1K, 10K, 100K) +Jaribu uingizaji/utoaji wa wingi wa uainishaji +Jaribu matumizi ya kumbukumbu wakati wa operesheni za wingi +Jaribu ufuatiliaji wa maendeleo + +### Vipimo vya Utendaji + +**Viashiria vya Kuchelewesha** (`test_performance_latency.py`): +Pima muda wa tokeni ya kwanza (utiririshaji dhidi ya usio na utiririshaji) +Pima gharama ya muunganisho (REST dhidi ya WebSocket) +Linganisha na viashiria vya kutarajiwa + +**Viashiria vya Ufanisi** (`test_performance_throughput.py`): +Pima ufanisi wa uingizaji wa wingi +Pima ufanisi wa uunganishaji wa ombi +Linganisha na viashiria vya kutarajiwa + +### Vipimo vya Utangamano + +**Utangamano wa Nyuma** (`test_backward_compatibility.py`): +Endesha seti ya vipimo iliyopo dhidi ya API iliyobadilishwa +Hakikisha hakuna mabadiliko ya kuvunja utangamano +Jaribu njia ya uhamishaji kwa mifumo ya kawaida + +## Mpango wa Uhamishaji + +### Awamu ya 1: Uhamishaji Wazi (Chaguo-msingi) + +**Hakuna mabadiliko ya msimbo yanayohitajika**. Msimbo uliopo unaendelea kufanya kazi: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### Awamu ya 2: Uidhinishaji wa Utiririshaji (Rahisi) + +**Tumia kiolesura `api.socket()`** ili kuwezesha utiririshaji: + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**Pointi Muhimu**: +URL sawa kwa REST na WebSocket. +Saini sawa za mbinu (rahisi kuhamisha). +Ongeza tu `.socket()` na `streaming=True`. + +### Awamu ya 3: Operesheni za Kiasi (Uwezo Mpya) + +**Tumia kiolesura cha `api.bulk()`** kwa data kubwa: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### Sasisho la Nyaraka + +1. **README.md**: Ongeza mifano ya utiririshaji na WebSocket +2. **Marejeleo ya API**: Andika mbinu na vigezo vyote vipya +3. **Mwongozo wa Uhamishaji**: Mwongozo wa hatua kwa hatua wa kuwezesha utiririshaji +4. **Mifano**: Ongeza skripti ya mfano kwa mifumo ya kawaida +5. **Mwongozo wa Utendaji**: Andika uboreshaji uliotarajiwa wa utendaji + +### Sera ya Kutolewa + +**Hakuna kutolewa**. API zote zilizopo zinaendelea kuungwa mkono. Hii ni uboreshaji safi. + +## Ratiba + +### Wiki ya 1: Msingi +Safu ya abstraction ya usafirishaji +Tengeneza upya msimbo wa REST uliopo +Vipimo vya kitengo kwa safu ya usafirishaji +Uthibitisho wa utangamano wa nyuma + +### Wiki ya 2: Usafirishaji wa WebSocket +Utendaji wa usafirishaji wa WebSocket +Usimamizi wa muunganisho na muunganisho upya +Ufuatiliaji wa ombi +Vipimo vya kitengo na ushirikiano + +### Wiki ya 3: Usaidizi wa Utiririshaji +Ongeza kiparamu cha utiririshaji kwa mbinu za LLM +Tengeneza utiririshaji wa jibu +Ongeza aina za vipande vya utiririshaji +Vipimo vya ushirikiano vya utiririshaji + +### Wiki ya 4: Operesheni za Kiasi +Ongeza mbinu za kuingiza/kutoa kwa wingi +Tengeneza operesheni zinazotegemea iterator +Upimaji wa utendaji +Vipimo vya ushirikiano vya operesheni za wingi + +### Wiki ya 5: Ulinganisho wa Vipengele na Nyaraka +Ongeza swali la uingizaji wa michoro +Ongeza API ya metriki +Nyaraka kamili +Mwongozo wa uhamishaji +Mfumo wa majaribio + +### Wiki ya 6: Toa +Vipimo vya mwisho vya ushirikiano +Upimaji wa utendaji +Nyaraka za kutolewa +Tangazo la jumuiya + +**Jumla ya Muda**: wiki 6 + +## Maswali ya Wazi + +### Maswali ya Ubunifu wa API + +1. **Usaidizi wa Async**: ✅ **IMEONGELEWA** - Usaidizi kamili wa async umejumuishwa katika toleo la awali + Interfeisi zote zina matoleo ya async: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + Hutoa usawa kamili kati ya API za sync na async + Muhimu kwa mifumo ya kisasa ya async (FastAPI, aiohttp) + +2. **Ufuatiliaji wa Maendeleo**: Je, operesheni za wingi zinapaswa kusaidia callbacks za maendeleo? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **Pendekezo**: Ongezewe katika Hatua ya 2. Si muhimu kwa toleo la awali. + +3. **Mipangilio ya Muda wa Kitendo cha Uhamisho (Streaming)**: Je, tunapaswa kushughulikia vipi vipindi vya muda ambavyo vitatokea wakati wa vitendo vya uhamishaji? + **Pendekezo**: Tumia muda sawa kama vitendo visivyohusisha uhamishaji, lakini uweke upya kila wakati unapopokea sehemu (chunk). + +4. **Uwekaji Hifadhi wa Sehemu (Chunk Buffering)**: Je, tunapaswa kuweka sehemu katika hifadhi au kuzitoa mara moja? + **Pendekezo**: Zitoa mara moja ili kupunguza zaidi kuchelewesha. + +5. **Huduma za Kimataifa kupitia WebSocket**: Je, `api.socket()` inapaswa kusaidia huduma za kimataifa (maktaba, maarifa, mkusanyiko, usanidi) au tu huduma zinazohusiana na kila uhamishaji? + **Pendekezo**: Anza tu na huduma zinazohusiana na kila uhamishaji (ambapo uhamishaji una umuhimu). Ongeza huduma za kimataifa ikiwa ni lazima katika Hatua ya 2. + +### Maswali ya Utendaji + +1. **Maktaba ya WebSocket**: Je, tunapaswa kutumia `websockets`, `websocket-client`, au `aiohttp`? + **Pendekezo**: `websockets` (ya kisasa, iliyokamilika, na inayohudumiwa vizuri). Ifunike katika muundo wa kazi (synchronous) kwa kutumia `asyncio.run()`. + +2. **Uunganishaji wa Pamoja (Connection Pooling)**: Je, tunapaswa kusaidia mifano mingi ya `Api` inayoshiriki muunganisho mmoja? + **Pendekezo**: Acha hadi Hatua ya 2. Kila mfano wa `Api` una muunganisho wake mwenyewe mwanzo. + +3. **Matumizi ya Muunganisho**: Je, `SocketClient` na `BulkClient` zinapaswa kushiriki muunganisho mmoja wa WebSocket, au kutumia muunganisho tofauti? + **Pendekezo**: Muunganisho tofauti. Utendaji rahisi, upeo wa wazi. + +4. **Muunganisho wa Kwanza au wa Baadaye**: Je, muunganisho wa WebSocket unapaswa kuundwa katika `api.socket()` au wakati wa ombi la kwanza? + **Pendekezo**: Muunganisho wa baadaye (wakati wa ombi la kwanza). Inazuia gharama ya muunganisho ikiwa mtumiaji hutumia tu mbinu za REST. + +### Maswali ya Majaribio + +1. **Lango la Majaribio (Mock Gateway)**: Je, tunapaswa kuunda lango la majaribio (mock) ambalo ni rahisi kwa ajili ya majaribio, au tujaribu dhidi ya lango halisi? + **Pendekezo**: Zote. Tumia lango la majaribio kwa majaribio ya kitengo, na lango halisi kwa majaribio ya ujumuishaji. + +2. **Majaribio ya Utendaji (Performance Regression Tests)**: Je, tunapaswa kuongeza majaribio ya utendaji (performance) ya kiotomatiki katika mfumo wa CI (Continuous Integration)? + **Pendekezo**: Ndiyo, lakini na viwango vikubwa vya uvumilivu ili kuzingatia tofauti katika mazingira ya CI. + +## Marejeleo + +### Vipimo vya Teknolojia Vilivyohusiana +`docs/tech-specs/streaming-llm-responses.md` - Utaratibu wa utiririshaji katika lango. +`docs/tech-specs/rag-streaming-support.md` - Usaidizi wa utiririshaji wa RAG. + +### Faili za Utendaji +`trustgraph-base/trustgraph/api/` - Chanzo cha API ya Python. +`trustgraph-flow/trustgraph/gateway/` - Chanzo cha lango. +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - Utaratibu wa marejeleo wa mchanganyiko wa WebSocket. + +### Nyaraka +`docs/apiSpecification.md` - Marejeleo kamili ya API. +`docs/api-status-summary.md` - Muhtasari wa hali ya API. +`README.websocket` - Nyaraka za itifaki ya WebSocket. +`STREAMING-IMPLEMENTATION-NOTES.txt` - Maelezo kuhusu utaratibu wa utiririshaji. + +### Maktabu ya Nje +`websockets` - Maktaba ya WebSocket ya Python (https://websockets.readthedocs.io/). +`requests` - Maktaba ya HTTP ya Python (ilipo tayari). diff --git a/docs/tech-specs/python-api-refactor.tr.md b/docs/tech-specs/python-api-refactor.tr.md new file mode 100644 index 00000000..e484cd9a --- /dev/null +++ b/docs/tech-specs/python-api-refactor.tr.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Python API Yeniden Düzenleme Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Python API Yeniden Düzenleme 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 Python API istemci kitaplığının, API Gateway ile özellik uyumluluğu sağlamak ve modern gerçek zamanlı iletişim kalıplarına destek eklemek için kapsamlı bir şekilde yeniden düzenlenmesini açıklamaktadır. + +Bu yeniden düzenleme, dört birincil kullanım durumunu ele almaktadır: + +1. **Akışlı LLM Etkileşimleri**: LLM yanıtlarının (ajan, grafik RAG, belge RAG, metin tamamlama, istemler) gerçek zamanlı olarak akışını etkinleştirin ve ilk belirteç için ~60 kat daha düşük gecikme süresi sağlayın (30 saniye yerine 500 ms). +2. **Toplu Veri İşlemleri**: Büyük ölçekli bilgi grafiği yönetimi için üçlülerin, grafik gömülme ve belge gömülme verilerinin verimli toplu olarak aktarılmasını ve dışa aktarılmasını destekleyin. +3. **Özellik Uyumluluğu**: Her API Gateway uç noktasının, grafik gömülme sorgusu da dahil olmak üzere, karşılık gelen bir Python API yöntemine sahip olduğundan emin olun. +4. **Sürekli Bağlantılar**: Çoklu istekler ve azaltılmış bağlantı yükü için WebSocket tabanlı iletişimi etkinleştirin. + +## Hedefler + +**Özellik Uyumluluğu**: Her Gateway API hizmetinin karşılık gelen bir Python API yöntemi vardır. +**Akış Desteği**: Tüm akış özellikli hizmetler (ajan, RAG, metin tamamlama, istem), Python API'de akışı destekler. +**WebSocket Taşıyıcı Katmanı**: Kalıcı bağlantılar ve çoklama için isteğe bağlı bir WebSocket taşıyıcı katmanı ekleyin. +**Toplu İşlemler**: Üçlüler, grafik gömülme ve belge gömülme için verimli toplu aktarım/dışa aktarma ekleyin. +**Tam Asenkron Desteği**: Tüm arayüzler (REST, WebSocket, toplu işlemler, ölçümler) için eksiksiz asenkron/bekleme uygulaması. +**Geriye Dönük Uyumluluk**: Mevcut kod, herhangi bir değişiklik yapılmadan çalışmaya devam eder. +**Tip Güvenliği**: Veri sınıfları ve tip ipuçlarıyla tip güvenli arayüzleri koruyun. +**Aşamalı Geliştirme**: Akış ve asenkron, açık arayüz seçimi yoluyla isteğe bağlıdır. +**Performans**: Akış işlemlerinde 60 kat gecikme iyileştirmesi elde edin. +**Modern Python**: Maksimum esneklik için hem senkron hem de asenkron paradigmaları destekleyin. + +## Arka Plan + +### Mevcut Durum + +Python API'si (`trustgraph-base/trustgraph/api/`), aşağıdaki modüllere sahip REST tabanlı bir istemci kitaplığıdır: + +`flow.py`: Akış yönetimi ve akış kapsamlı hizmetler (50 yöntem) +`library.py`: Belge kitaplığı işlemleri (9 yöntem) +`knowledge.py`: KG çekirdek yönetimi (4 yöntem) +`collection.py`: Koleksiyon meta verileri (3 yöntem) +`config.py`: Yapılandırma yönetimi (6 yöntem) +`types.py`: Veri türü tanımları (5 veri sınıfı) + +**Toplam İşlem**: 50/59 (%85 kapsama) + +### Mevcut Sınırlamalar + +**Eksik İşlemler**: +Grafik gömülme sorgusu (grafik varlıkları üzerindeki semantik arama) +Üçlüler, grafik gömülme, belge gömülme, varlık bağlamları, nesneler için toplu aktarım/dışa aktarma +Ölçüm uç noktası + +**Eksik Yetenekler**: +LLM hizmetleri için akış desteği +WebSocket taşıyıcısı +Çoklu eşzamanlı istekler +Kalıcı bağlantılar + +**Performans Sorunları**: +LLM etkileşimleri için yüksek gecikme süresi (~30 saniye ilk belirteç) +Toplu veri aktarımı için verimsiz (her öğe için REST isteği) +Birden çok sıralı işlem için bağlantı yükü + +**Kullanıcı Deneyimi Sorunları**: +LLM oluşturma sırasında gerçek zamanlı geri bildirim yok +Uzun süren LLM işlemlerini iptal edememe +Toplu işlemler için zayıf ölçeklenebilirlik + +### Etki + +Kasım 2024'te Gateway API'ye yapılan akış geliştirmesi, LLM etkileşimleri için 60 kat gecikme iyileştirmesi (30 saniye yerine 500 ms ilk belirteç) sağladı, ancak Python API kullanıcıları bu yeteneği kullanamıyor. Bu, Python ve Python dışı kullanıcılar arasında önemli bir deneyim boşluğuna yol açmaktadır. + +## Teknik Tasarım + +### Mimari + +Yeniden düzenlenmiş Python API'si, farklı iletişim kalıpları için ayrı nesneler kullanan **modüler bir arayüz yaklaşımı** kullanır. Tüm arayüzler hem **senkron hem de asenkron** varyantlarda mevcuttur: + +1. **REST Arayüzü** (mevcut, geliştirilmiş) + **Senkron**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()` + **Asenkron**: `api.async_flow()` + Senkron/asenkron istek/yanıt + Basit bağlantı modeli + Geriye dönük uyumluluk için varsayılan + +2. **WebSocket Arayüzü** (yeni) + **Senkron**: `api.socket()` + **Asenkron**: `api.async_socket()` + Kalıcı bağlantı + Çoklu istekler + Akış desteği + İşlevselliğin örtüştüğü yerlerde REST ile aynı yöntem imzaları + +3. **Toplu İşlemler Arayüzü** (yeni) + **Senkron**: `api.bulk()` + **Asenkron**: `api.async_bulk()` + Verimlilik için WebSocket tabanlı + Iterator/AsyncIterator tabanlı aktarım/dışa aktarma + Büyük veri kümelerini işler + +4. **Ölçüm Arayüzü** (yeni) + **Senkron**: `api.metrics()` + **Asenkron**: `api.async_metrics()` + Prometheus ölçümleri erişimi + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**Temel Tasarım Prensipleri**: +**Tüm arayüzler için aynı URL**: `Api(url="http://localhost:8088/")`, tüm arayüzler için geçerlidir. +**Senkron/Asenkron simetri**: Her arayüzün hem senkron hem de asenkron varyantları vardır ve yöntem imzaları aynıdır. +**Aynı imzalar**: İşlevsellik örtüşüyorsa, REST ve WebSocket, senkron ve asenkron arasında yöntem imzaları aynıdır. +**Aşamalı iyileştirme**: İhtiyaçlara göre arayüzü seçin (basit işlemler için REST, akış için WebSocket, büyük veri kümeleri için Bulk, modern çerçeveler için asenkron). +**Açık niyet**: `api.socket()`, WebSocket'i belirtir, `api.async_socket()`, asenkron WebSocket'i belirtir. +**Geriye uyumlu**: Mevcut kod değişmeden kalır. + +### Bileşenler + +#### 1. Temel API Sınıfı (Değiştirilmiş) + +Modül: `trustgraph-base/trustgraph/api/api.py` + +**Geliştirilmiş API Sınıfı**: + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. Senkron WebSocket İstemcisi + +Modül: `trustgraph-base/trustgraph/api/socket_client.py` (yeni) + +**SocketClient Sınıfı**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Temel Özellikler**: +Tembel bağlantı (yalnızca ilk istek gönderildiğinde bağlantı kurulur) +İstek çoklama (en fazla 15 eşzamanlı) +Bağlantı kesildiğinde otomatik yeniden bağlanma +Akış yanıtı ayrıştırma +İş parçacığı güvenli çalışma +Asenkron WebSocket kütüphanesi için senkron sarmalayıcı + +#### 3. Asenkron WebSocket İstemcisi + +Modül: `trustgraph-base/trustgraph/api/async_socket_client.py` (yeni) + +**AsyncSocketClient Sınıfı**: + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**Temel Özellikler**: +Yerleşik async/await desteği +Asenkron uygulamalar için verimli (FastAPI, aiohttp) +İş parçacığı engellemesi yok +Senkron sürümle aynı arayüz +Akış için AsyncIterator + +#### 4. Senkron Toplu İşlemler İstemcisi + +Modül: `trustgraph-base/trustgraph/api/bulk_client.py` (yeni) + +**BulkClient Sınıfı**: + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**Temel Özellikler**: +Sabit bellek kullanımı için yineleyici tabanlı. +Her işlem için özel WebSocket bağlantıları. +İlerleme takibi (isteğe bağlı geri çağırma). +Kısmi başarı raporlamasıyla hata yönetimi. + +#### 5. Asenkron Toplu İşlemler İstemcisi + +Modül: `trustgraph-base/trustgraph/api/async_bulk_client.py` (yeni) + +**AsyncBulkClient Sınıfı**: + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**Temel Özellikler**: +Sabit bellek kullanımı için AsyncIterator tabanlı. +Asenkron uygulamalar için verimli. +Yerel asenkron/bekle destek. +Senkron sürümle aynı arayüz. + +#### 6. REST Akışı API'si (Senkron - Değişmedi) + +Modül: `trustgraph-base/trustgraph/api/flow.py` + +REST Akışı API'si, geriye dönük uyumluluk için **tamamen değişmeden** kalmıştır. Tüm mevcut yöntemler çalışmaya devam etmektedir: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, vb. +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, vb. +Tüm mevcut imzalar ve dönüş türleri korunmuştur. + +**Yeni**: Özellik uyumluluğu için `graph_embeddings_query()`'ı REST FlowInstance'a ekleyin: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. Asenkron REST Akışı API'si + +Modül: `trustgraph-base/trustgraph/api/async_flow.py` (yeni) + +**AsyncFlow ve AsyncFlowInstance Sınıfları:** + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**Temel Özellikler**: +`aiohttp` veya `httpx` kullanarak yerel asenkron HTTP +Senkron REST API'si ile aynı yöntem imzaları +Akış yok (akış için `async_socket()`'ı kullanın) +Asenkron uygulamalar için verimli + +#### 8. Ölçüm API'si + +Modül: `trustgraph-base/trustgraph/api/metrics.py` (yeni) + +**Senkron Ölçümler**: + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**Asenkron Metrikler**: + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. Gelişmiş Tipler + +Modül: `trustgraph-base/trustgraph/api/types.py` (değiştirildi) + +**Yeni Tipler**: + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. Metrik API + +Modül: `trustgraph-base/trustgraph/api/metrics.py` (yeni) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### Uygulama Yaklaşımı + +#### 1. Aşama: Temel API Geliştirmeleri (1. Hafta) + +1. `socket()`, `bulk()` ve `metrics()` yöntemlerini `Api` sınıfına ekleyin +2. WebSocket ve toplu iş yükleri için tembel başlatmayı uygulayın +3. Bağlam yöneticisi desteğini ekleyin (`__enter__`, `__exit__`) +4. Temizleme için `close()` yöntemini ekleyin +5. API sınıfı geliştirmeleri için birim testleri ekleyin +6. Geriye dönük uyumluluğu doğrulayın + +**Geriye Dönük Uyumluluk**: Herhangi bir uyumsuz değişiklik yok. Sadece yeni yöntemler. + +#### 2. Aşama: WebSocket İstemcisi (2-3. Haftalar) + +1. Bağlantı yönetimi için `SocketClient` sınıfını uygulayın +2. `SocketFlowInstance`'ı `FlowInstance` ile aynı yöntem imzalarına sahip olacak şekilde uygulayın +3. İstek çoklama desteğini ekleyin (en fazla 15 eşzamanlı) +4. Farklı parça türleri için akış yanıtı ayrıştırmasını ekleyin +5. Otomatik yeniden bağlantı mantığını ekleyin +6. Birim ve entegrasyon testlerini ekleyin +7. WebSocket kullanım kalıplarını belgeleyin + +**Geriye Dönük Uyumluluk**: Sadece yeni bir arayüz. Mevcut kod üzerinde hiçbir etkisi yok. + +#### 3. Aşama: Akış Desteği (3-4. Haftalar) + +1. Akış parça türü sınıflarını ekleyin (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. `SocketClient` içinde akış yanıtı ayrıştırmasını uygulayın +3. `SocketFlowInstance` içindeki tüm LLM yöntemlerine akış parametresini ekleyin +4. Akış sırasında hata durumlarını işleyin +5. Akış için birim ve entegrasyon testlerini ekleyin +6. Belgelerdeki akış örneklerini ekleyin + +**Geriye Dönük Uyumluluk**: Sadece yeni bir arayüz. Mevcut REST API değişmedi. + +#### 4. Aşama: Toplu İşlemler (4-5. Haftalar) + +1. `BulkClient` sınıfını uygulayın +2. Üçlüler, gömülü veriler, bağlamlar, nesneler için toplu içe/dışa aktarma yöntemlerini ekleyin +3. Sabit bellek için yineleyici tabanlı işleme uygulayın +4. İlerleme takibini ekleyin (isteğe bağlı geri çağırma) +5. Kısmi başarı raporlamasıyla hata işleme ekleyin +6. Birim ve entegrasyon testlerini ekleyin +7. Toplu işlem örneklerini ekleyin + +**Geriye Dönük Uyumluluk**: Sadece yeni bir arayüz. Mevcut kod üzerinde hiçbir etkisi yok. + +#### 5. Aşama: Özellik Eşitliği ve İyileştirmeler (5. Hafta) + +1. REST `FlowInstance`'ine `graph_embeddings_query()`'ı ekleyin +2. `Metrics` sınıfını uygulayın +3. Kapsamlı entegrasyon testlerini ekleyin +4. Performans karşılaştırması +5. Tüm belgeleri güncelleyin +6. Geçiş kılavuzu oluşturun + +**Geriye Dönük Uyumluluk**: Sadece yeni yöntemler. Mevcut kod üzerinde hiçbir etkisi yok. + +### Veri Modelleri + +#### Arayüz Seçimi + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### Akış Yanıt Türleri + +**Ajan Akışı:** + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**RAG Akışı:** + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**Toplu İşlemler (Senkron)**: + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**Toplu İşlemler (Asenkron)**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**Asenkron REST Örneği**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**Asenkron WebSocket Akışı Örneği**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### API'ler + +#### Yeni API'ler + +1. **Temel API Sınıfı**: + **Senkron**: + `Api.socket()` - Senkron WebSocket istemcisini al + `Api.bulk()` - Senkron toplu işlem istemcisini al + `Api.metrics()` - Senkron ölçüm istemcisini al + `Api.close()` - Tüm senkron bağlantıları kapat + Bağlam yöneticisi desteği (`__enter__`, `__exit__`) + **Asenkron**: + `Api.async_flow()` - Asenkron REST akışı istemcisini al + `Api.async_socket()` - Asenkron WebSocket istemcisini al + `Api.async_bulk()` - Asenkron toplu işlem istemcisini al + `Api.async_metrics()` - Asenkron ölçüm istemcisini al + `Api.aclose()` - Tüm asenkron bağlantıları kapat + Asenkron bağlam yöneticisi desteği (`__aenter__`, `__aexit__`) + +2. **Senkron WebSocket İstemcisi**: + `SocketClient.flow(flow_id)` - WebSocket akışı örneğini al + `SocketFlowInstance.agent(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte aracı + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte metin tamamlama + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte grafik RAG + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte belge RAG + `SocketFlowInstance.prompt(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte istem + `SocketFlowInstance.graph_embeddings_query()` - Grafik gömme sorgusu + Aynı imzaya sahip diğer tüm FlowInstance yöntemleri + +3. **Asenkron WebSocket İstemcisi**: + `AsyncSocketClient.flow(flow_id)` - Asenkron WebSocket akışı örneğini al + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte asenkron aracı + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte asenkron metin tamamlama + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte asenkron grafik RAG + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte asenkron belge RAG + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - İsteğe bağlı akışla birlikte asenkron istem + `AsyncSocketFlowInstance.graph_embeddings_query()` - Asenkron grafik gömme sorgusu + Diğer tüm FlowInstance yöntemleri asenkron versiyonlardır + +4. **Senkron Toplu İşlem İstemcisi**: + `BulkClient.import_triples(flow, triples)` - Toplu üçlü içe aktarma + `BulkClient.export_triples(flow)` - Toplu üçlü dışa aktarma + `BulkClient.import_graph_embeddings(flow, embeddings)` - Toplu grafik gömme içe aktarma + `BulkClient.export_graph_embeddings(flow)` - Toplu grafik gömme dışa aktarma + `BulkClient.import_document_embeddings(flow, embeddings)` - Toplu belge gömme içe aktarma + `BulkClient.export_document_embeddings(flow)` - Toplu belge gömme dışa aktarma + `BulkClient.import_entity_contexts(flow, contexts)` - Toplu varlık bağlamları içe aktarma + `BulkClient.export_entity_contexts(flow)` - Toplu varlık bağlamları dışa aktarma + `BulkClient.import_objects(flow, objects)` - Toplu nesneler içe aktarma + +5. **Asenkron Toplu İşlem İstemcisi**: + `AsyncBulkClient.import_triples(flow, triples)` - Asenkron toplu üçlü içe aktarma + `AsyncBulkClient.export_triples(flow)` - Asenkron toplu üçlü dışa aktarma + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - Asenkron toplu grafik gömme içe aktarma + `AsyncBulkClient.export_graph_embeddings(flow)` - Asenkron toplu grafik gömme dışa aktarma + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - Asenkron toplu belge gömme içe aktarma + `AsyncBulkClient.export_document_embeddings(flow)` - Asenkron toplu belge gömme dışa aktarma + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - Asenkron toplu varlık bağlamları içe aktarma + `AsyncBulkClient.export_entity_contexts(flow)` - Asenkron toplu varlık bağlamları dışa aktarma + `AsyncBulkClient.import_objects(flow, objects)` - Asenkron toplu nesneler içe aktarma + +6. **Asenkron REST Akışı İstemcisi**: + `AsyncFlow.list()` - Tüm akışları listele (asenkron) + `AsyncFlow.get(id)` - Akış tanımını al (asenkron) + `AsyncFlow.start(...)` - Akışı başlat (asenkron) + `AsyncFlow.stop(id)` - Akışı durdur (asenkron) + `AsyncFlow.id(flow_id)` - Asenkron akış örneğini al + `AsyncFlowInstance.agent(...)` - Asenkron aracı yürütme + `AsyncFlowInstance.text_completion(...)` - Asenkron metin tamamlama + `AsyncFlowInstance.graph_rag(...)` - Asenkron grafik RAG + Diğer tüm FlowInstance yöntemleri asenkron versiyonlardır + +7. **Ölçüm İstemcileri**: + `Metrics.get()` - Senkron Prometheus ölçümleri + `AsyncMetrics.get()` - Asenkron Prometheus ölçümleri + +8. **REST Akışı API Geliştirmesi**: + `FlowInstance.graph_embeddings_query()` - Grafik gömme sorgusu (senkron özellik uyumluluğu) + `AsyncFlowInstance.graph_embeddings_query()` - Grafik gömme sorgusu (asenkron özellik uyumluluğu) + +#### Değiştirilen API'ler + +1. **Kurucu** (küçük bir iyileştirme): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + `token` parametresi eklendi (isteğe bağlı, kimlik doğrulama için) + Eğer `None` belirtilmemişse (varsayılan): Kimlik doğrulama kullanılmıyor + Eğer belirtilmişse: REST için bearer token olarak kullanılır (`Authorization: Bearer `), WebSocket için sorgu parametresi olarak kullanılır (`?token=`) + Başka bir değişiklik yok - tamamen geriye dönük uyumlu + +2. **Kırıcı Değişiklikler Yok**: + Tüm mevcut REST API yöntemleri değişmedi + Tüm mevcut imzalar korunmuş + Tüm mevcut dönüş türleri korunmuş + +### Uygulama Detayları + +#### Hata Yönetimi + +**WebSocket Bağlantı Hataları**: +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**Zarif Yedekleme:** +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**Kısmi Akış Hataları**: +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### Kaynak Yönetimi + +**Bağlam Yöneticisi Desteği**: +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### İş parçacığı ve Eşzamanlılık + +**İş Parçacığı Güvenliği**: +Her `Api` örneği kendi bağlantısını korur. +WebSocket taşıma katmanı, iş parçacığı güvenli istek çoklama için kilitler kullanır. +Birden fazla iş parçacığı, bir `Api` örneğini güvenli bir şekilde paylaşabilir. +Akış iteratörleri iş parçacığı güvenli değildir (tek iş parçacığından tüketilir). + +**Asenkron Destek** (gelecek planlar): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## Güvenlik Hususları + +### Kimlik Doğrulama + +**Token Parametresi**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**REST İletim Yöntemi**: +Taşıyıcı belirteci, `Authorization` başlığı aracılığıyla +Tüm REST isteklerine otomatik olarak uygulanır +Format: `Authorization: Bearer ` + +**WebSocket İletim Yöntemi**: +Belirteç, WebSocket URL'sine eklenen bir sorgu parametresi aracılığıyla +Bağlantı kurulması sırasında otomatik olarak uygulanır +Format: `ws://localhost:8088/api/v1/socket?token=` + +**Uygulama**: +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**Örnek:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### Güvenli İletişim + +Hem WS (WebSocket) hem de WSS (WebSocket Secure) şemalarını destekler. +WSS bağlantıları için TLS sertifika doğrulaması. +Geliştirme için isteğe bağlı sertifika doğrulama devre dışı bırakma (uyarı ile). + +### Girdi Doğrulama + +URL şemalarını (http, https, ws, wss) doğrula. +Taşıma parametre değerlerini doğrula. +Akış parametre kombinasyonlarını doğrula. +Toplu veri türlerini doğrula. + +## Performans Hususları + +### Gecikme İyileştirmeleri + +**Akışlı LLM İşlemleri**: +**İlk token'a ulaşma süresi**: ~500ms (akışsız ise ~30 saniye) +**İyileşme**: Algılanan performansta 60 kat daha hızlı. +**Kullanım alanları**: Ajan, Grafik RAG, Belge RAG, Metin Tamamlama, İstek. + +**Sürekli Bağlantılar**: +**Bağlantı ek yükü**: Sonraki istekler için ortadan kaldırılmıştır. +**WebSocket el sıkışması**: Tek seferlik maliyet (~100ms). +**Kullanım alanları**: WebSocket taşıma yöntemini kullanırken tüm işlemler için geçerlidir. + +### Verim İyileştirmeleri + +**Toplu İşlemler**: +**Üçlü veri aktarımı**: ~10.000 üçlü/saniye (REST ile tek öğe için ~100/saniye) +**Gömme veri aktarımı**: ~5.000 gömme/saniye (REST ile tek öğe için ~50/saniye) +**İyileşme**: Toplu işlemler için 100 kat daha yüksek verim. + +**İstek Çoklama**: +**Eşzamanlı istekler**: Tek bağlantı üzerinden 15'e kadar eşzamanlı istek. +**Bağlantı yeniden kullanımı**: Eşzamanlı işlemler için bağlantı ek yükü yok. + +### Bellek Hususları + +**Akışlı Yanıtlar**: +Sabit bellek kullanımı (parçalar geldiği gibi işlenir). +Tam yanıtın tamponlanması yok. +Çok uzun çıktılar (>1MB) için uygundur. + +**Toplu İşlemler**: +Yineleyici tabanlı işleme (sabit bellek). +Tüm veri kümesinin belleğe yüklenmesi yok. +Milyonlarca öğeye sahip veri kümeleri için uygundur. + +### Karşılaştırmalar (Beklenen) + +| İşlem | REST (mevcut) | WebSocket (akışlı) | İyileşme | +|-----------|----------------|----------------------|-------------| +| Ajan (ilk token'a ulaşma süresi) | 30s | 0.5s | 60x | +| Grafik RAG (ilk token'a ulaşma süresi) | 25s | 0.5s | 50x | +| 10K üçlü aktarımı | 100s | 1s | 100x | +| 1M üçlü aktarımı | 10.000s (2.7h) | 100s (1.6m) | 100x | +| 10 eşzamanlı küçük istek | 5s (sıralı) | 0.5s (paralel) | 10x | + +## Test Stratejisi + +### Birim Testleri + +**Taşıma Katmanı** (`test_transport.py`): +REST taşıma isteklerini/yanıtlarını test et +WebSocket taşıma bağlantısını test et +WebSocket taşıma bağlantısının yeniden kurulmasını test et +İstek çoklama işlemini test et +Akış yanıtı ayrıştırmasını test et +Belirli testler için sahte WebSocket sunucusu oluştur + +**API Yöntemleri** (`test_flow.py`, `test_library.py`, vb.): +Sahte taşıma ile yeni yöntemleri test et +Akış parametrelerinin işlenmesini test et +Toplu işlem yineleyicilerini test et +Hata işleme işlemlerini test et + +**Türler** (`test_types.py`): +Yeni akış parçacık türlerini test et +Tür serileştirme/deserileştirme işlemlerini test et + +### Entegrasyon Testleri + +**Uçtan Uca REST** (`test_integration_rest.py`): +Tüm işlemleri gerçek Ağ geçidine karşı test et (REST modu) +Geriye dönük uyumluluğu doğrula +Hata koşullarını test et + +**Uçtan Uca WebSocket** (`test_integration_websocket.py`): +Tüm işlemleri gerçek Ağ geçidine karşı test et (WebSocket modu) +Akış işlemlerini test et +Toplu işlemleri test et +Eşzamanlı istekleri test et +Bağlantı kurtarma işlemlerini test et + +**Akış Hizmetleri** (`test_streaming_integration.py`): +Ajan akışını (düşünceler, gözlemler, yanıtlar) test et +RAG akışını (artımlı parçalar) test et +Metin tamamlama akışını (token-by-token) test et +İstem akışını test et +Akış sırasında hata işleme işlemlerini test et + +**Toplu İşlemler** (`test_bulk_integration.py`): +Üçlülerin toplu olarak aktarılmasını/dışa aktarılmasını test et (1K, 10K, 100K öğe) +Gömme verilerinin toplu olarak aktarılmasını/dışa aktarılmasını test et +Toplu işlemler sırasında bellek kullanımını test et +İlerleme takibini test et + +### Performans Testleri + +**Gecikme Ölçümleri** (`test_performance_latency.py`): +İlk tokene kadar geçen süreyi ölç (akışlı vs. akışsız) +Bağlantı ek yükünü ölç (REST vs WebSocket) +Beklenen ölçümlerle karşılaştır + +**Verim Ölçümleri** (`test_performance_throughput.py`): +Toplu aktarım verimini ölç +İstek çoklama verimliliğini ölç +Beklenen ölçümlerle karşılaştır + +### Uyumluluk Testleri + +**Geriye Dönük Uyumluluk** (`test_backward_compatibility.py`): +Mevcut test paketini yeniden düzenlenmiş API'ye karşı çalıştır +Herhangi bir uyumsuz değişikliğin olmadığını doğrulayın +Yaygın kalıplar için geçiş yolunu test edin + +## Geçiş Planı + +### 1. Aşama: Şeffaf Geçiş (Varsayılan) + +**Kodda herhangi bir değişiklik gerekli değil**. Mevcut kod çalışmaya devam ediyor: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### 2. Aşama: İsteğe Bağlı Yayın (Basit) + +**Yayınlamayı etkinleştirmek için `api.socket()` arayüzünü kullanın:** + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**Önemli Noktalar**: +Hem REST hem de WebSocket için aynı URL +Aynı yöntem imzaları (kolay geçiş) +Sadece `.socket()` ve `streaming=True` ekleyin + +### 3. Aşama: Toplu İşlemler (Yeni Özellik) + +Büyük veri kümeleri için `api.bulk()` arayüzünü kullanın: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### Dokümantasyon Güncellemeleri + +1. **README.md**: Akış ve WebSocket örnekleri ekleyin +2. **API Referansı**: Tüm yeni yöntemleri ve parametreleri belgeleyin +3. **Yükseltme Kılavuzu**: Akışı etkinleştirmek için adım adım kılavuz +4. **Örnekler**: Yaygın kalıplar için örnek betikler ekleyin +5. **Performans Kılavuzu**: Beklenen performans iyileştirmelerini belgeleyin + +### Kullanımdan Kaldırma Politikası + +**Herhangi bir kullanımdan kaldırma yok**. Tüm mevcut API'ler desteklenmeye devam ediyor. Bu, yalnızca bir geliştirmedir. + +## Zaman Çizelgesi + +### 1. Hafta: Temel +Taşıma soyutlama katmanı +Mevcut REST kodunu yeniden düzenleyin +Taşıma katmanı için birim testleri +Geriye dönük uyumluluk doğrulaması + +### 2. Hafta: WebSocket Taşıyıcısı +WebSocket taşıyıcısı uygulaması +Bağlantı yönetimi ve yeniden bağlanma +İstek çoklama +Birim ve entegrasyon testleri + +### 3. Hafta: Akış Desteği +LLM yöntemlerine akış parametresi ekleyin +Akış yanıtı ayrıştırmasını uygulayın +Akış parçacığı türleri ekleyin +Akış entegrasyon testleri + +### 4. Hafta: Toplu İşlemler +Toplu içe/dışa aktarma yöntemleri ekleyin +Yineleyici tabanlı işlemleri uygulayın +Performans testi +Toplu işlem entegrasyon testleri + +### 5. Hafta: Özellik Eşdeğerliği ve Dokümantasyon +Grafik gömme sorgusu ekleyin +Ölçüm API'si ekleyin +Kapsamlı dokümantasyon +Yükseltme kılavuzu +Yayın adayı + +### 6. Hafta: Yayın +Son entegrasyon testleri +Performans karşılaştırması +Yayın dokümantasyonu +Topluluk duyurusu + +**Toplam Süre**: 6 hafta + +## Açık Sorular + +### API Tasarımı Soruları + +1. **Asenkron Destek**: ✅ **ÇÖZÜLDÜ** - Tam asenkron destek, ilk sürümde dahil edilmiştir + Tüm arayüzlerin asenkron varyantları vardır: `async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + Senkron ve asenkron API'ler arasında tam bir simetri sağlar + Modern asenkron çerçeveler (FastAPI, aiohttp) için gereklidir + +2. **İlerleme İzleme**: Toplu işlemler, ilerleme geri çağırmalarını desteklemeli mi? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **Öneri**: 2. Faz'da ekleyin. İlk sürüm için kritik değil. + +3. **Akış Zaman Aşımı**: Akış işlemlerinde zaman aşımını nasıl ele almalıyız? + **Öneri**: Akış dışı işlemler için aynı zaman aşımını kullanın, ancak her parça alındığında sıfırlayın. + +4. **Parça Önbelleği**: Parçaları önbelleğe almalı mıyız yoksa hemen geri mi vermeliyiz? + **Öneri**: En düşük gecikme için hemen geri verin. + +5. **WebSocket Üzerinden Küresel Hizmetler**: `api.socket()`, küresel hizmetleri (kütüphane, bilgi, koleksiyon, yapılandırma) desteklemeli mi yoksa yalnızca akışla ilgili hizmetleri mi? + **Öneri**: Başlangıçta yalnızca akışla ilgili hizmetlerle başlayın (akışın önemli olduğu yerlerde). Gerekirse 2. Faz'da küresel hizmetleri ekleyin. + +### Uygulama Soruları + +1. **WebSocket Kütüphanesi**: `websockets`, `websocket-client` veya `aiohttp`'yi kullanmalı mıyız? + **Öneri**: `websockets` (asenkron, olgun, iyi bakılan). `asyncio.run()` kullanarak senkron bir arayüzle sarın. + +2. **Bağlantı Havuzu**: Birden çok eşzamanlı `Api` örneğinin bir bağlantı havuzunu paylaşmasına izin vermeli miyiz? + **Öneri**: 2. Faz'a bırakın. Her `Api` örneğinin başlangıçta kendi bağlantıları vardır. + +3. **Bağlantı Geri Dönüşümü**: `SocketClient` ve `BulkClient` aynı WebSocket bağlantısını mı kullanmalı, yoksa ayrı bağlantılar mı kullanmalı? + **Öneri**: Ayrı bağlantılar. Daha basit uygulama, daha net sorumluluk ayrımı. + +4. **Gecikmeli vs. Hızlı Bağlantı**: WebSocket bağlantısı `api.socket()` içinde mi yoksa ilk istekte mi kurulmalı? + **Öneri**: Gecikmeli (ilk istekte). Kullanıcı yalnızca REST yöntemlerini kullanıyorsa, bağlantı ek yükünden kaçının. + +### Test Soruları + +1. **Sahte Ağ Geçidi**: Test için hafif bir sahte Ağ Geçidi mi oluşturmalıyız, yoksa gerçek Ağ Geçidi üzerinde mi test yapmalıyız? + **Öneri**: Her ikisi de. Birim testleri için sahte nesneler kullanın, entegrasyon testleri için gerçek Ağ Geçidi'ni kullanın. + +2. **Performans Geri Dönüşüm Testleri**: Otomatik performans geri dönüşüm testlerini CI'a eklemeli miyiz? + **Öneri**: Evet, ancak CI ortamındaki değişkenliği hesaba katmak için cömert eşiklerle. + +## Referanslar + +### İlgili Teknik Özellikler +`docs/tech-specs/streaming-llm-responses.md` - Ağ Geçidi'ndeki akış uygulaması +`docs/tech-specs/rag-streaming-support.md` - RAG akış desteği + +### Uygulama Dosyaları +`trustgraph-base/trustgraph/api/` - Python API kaynağı +`trustgraph-flow/trustgraph/gateway/` - Ağ Geçidi kaynağı +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - WebSocket çoklayıcı referans uygulaması + +### Belgeler +`docs/apiSpecification.md` - Tam API referansı +`docs/api-status-summary.md` - API durumu özeti +`README.websocket` - WebSocket protokolü belgeleri +`STREAMING-IMPLEMENTATION-NOTES.txt` - Akış uygulama notları + +### Harici Kütüphaneler +`websockets` - Python WebSocket kütüphanesi (https://websockets.readthedocs.io/) +`requests` - Python HTTP kütüphanesi (mevcut) diff --git a/docs/tech-specs/python-api-refactor.zh-cn.md b/docs/tech-specs/python-api-refactor.zh-cn.md new file mode 100644 index 00000000..31a65c85 --- /dev/null +++ b/docs/tech-specs/python-api-refactor.zh-cn.md @@ -0,0 +1,1516 @@ +--- +layout: default +title: "Python API 重构技术规范" +parent: "Chinese (Beta)" +--- + +# Python API 重构技术规范 + +> **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 Python API 客户端库的全面重构,旨在实现与 API 网关的功能对齐,并添加对现代实时通信模式的支持。 + +该重构解决了四个主要用例: + +1. **流式 LLM 交互**: 启用 LLM 响应的实时流式传输(代理、图 RAG、文档 RAG、文本补全、提示),延迟降低约 60 倍(第一个 token 为 500 毫秒,而不是 30 秒)。 +2. **批量数据操作**: 支持高效的大规模知识图谱管理的 triples、图嵌入和文档嵌入的批量导入/导出。 +3. **功能对齐**: 确保每个 API 网关端点都有相应的 Python API 方法,包括图嵌入查询。 +4. **持久连接**: 启用基于 WebSocket 的通信,以实现多路复用请求和降低连接开销。 + +## 目标 + +**功能对齐**: 每个网关 API 服务都有相应的 Python API 方法。 +**流式支持**: 所有支持流式传输的服务(代理、RAG、文本补全、提示)在 Python API 中支持流式传输。 +**WebSocket 传输**: 添加可选的 WebSocket 传输层,用于持久连接和多路复用。 +**批量操作**: 添加 triples、图嵌入和文档嵌入的高效批量导入/导出功能。 +**完全异步支持**: 为所有接口(REST、WebSocket、批量操作、指标)实现完整的 async/await。 +**向后兼容性**: 现有代码无需修改即可继续工作。 +**类型安全**: 维护类型安全的接口,使用 dataclasses 和类型提示。 +**渐进式增强**: 流式传输和异步是可选的,通过显式接口选择启用。 +**性能**: 实现流式操作的 60 倍延迟改进。 +**现代 Python**: 支持同步和异步范式,以实现最大的灵活性。 + +## 背景 + +### 当前状态 + +Python API (`trustgraph-base/trustgraph/api/`) 是一个仅支持 REST 的客户端库,包含以下模块: + +`flow.py`: 流管理和流范围服务(50 个方法)。 +`library.py`: 文档库操作(9 个方法)。 +`knowledge.py`: KG 核心管理(4 个方法)。 +`collection.py`: 集合元数据(3 个方法)。 +`config.py`: 配置管理(6 个方法)。 +`types.py`: 数据类型定义(5 个 dataclasses)。 + +**总操作**: 50/59 (覆盖率 85%) + +### 当前限制 + +**缺失的操作**: +图嵌入查询(图实体上的语义搜索)。 +triples、图嵌入、文档嵌入、实体上下文、对象的批量导入/导出。 +指标端点。 + +**缺失的功能**: +LLM 服务的流式传输支持。 +WebSocket 传输。 +多路复用的并发请求。 +持久连接。 + +**性能问题**: +LLM 交互的延迟高(第一个 token 需要 30 秒)。 +批量数据传输效率低下(每个项目一个 REST 请求)。 +多个连续操作的连接开销。 + +**用户体验问题**: +LLM 生成过程中没有实时反馈。 +无法取消长时间运行的 LLM 操作。 +批量操作的可扩展性差。 + +### 影响 + +2024 年 11 月对网关 API 的流式增强,将 LLM 交互的延迟提高了 60 倍(第一个 token 为 500 毫秒,而不是 30 秒),但 Python API 用户无法利用此功能。 这在 Python 用户和非 Python 用户之间造成了显著的体验差距。 + +## 技术设计 + +### 架构 + +重构的 Python API 采用 **模块化接口方法**,具有用于不同通信模式的单独对象。 所有接口都提供 **同步和异步** 两种版本: + +1. **REST 接口** (现有,增强) + **同步**: `api.flow()`, `api.library()`, `api.knowledge()`, `api.collection()`, `api.config()` + **异步**: `api.async_flow()` + 同步/异步请求/响应。 + 简单的连接模型。 + 默认用于向后兼容。 + +2. **WebSocket 接口** (新) + **同步**: `api.socket()` + **异步**: `api.async_socket()` + 持久连接。 + 多路复用的请求。 + 流式传输支持。 + 功能重叠时,方法签名与 REST 相同。 + +3. **批量操作接口** (新) + **同步**: `api.bulk()` + **异步**: `api.async_bulk()` + 基于 WebSocket,提高效率。 + 基于 Iterator/AsyncIterator 的导入/导出。 + 处理大型数据集。 + +4. **指标接口** (新) + **同步**: `api.metrics()` + **异步**: `api.async_metrics()` + Prometheus 指标访问。 + +```python +import asyncio + +# Synchronous interfaces +api = Api(url="http://localhost:8088/") + +# REST (existing, unchanged) +flow = api.flow().id("default") +response = flow.agent(question="...", user="...") + +# WebSocket (new) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="...", user="...") +for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk) + +# Bulk operations (new) +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Asynchronous interfaces +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST (new) + flow = api.async_flow().id("default") + response = await flow.agent(question="...", user="...") + + # Async WebSocket (new) + socket_flow = api.async_socket().flow("default") + async for chunk in socket_flow.agent(question="...", streaming=True): + print(chunk) + + # Async bulk operations (new) + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + +asyncio.run(main()) +``` + +**关键设计原则**: +**所有接口使用相同的URL**: `Api(url="http://localhost:8088/")` 对所有接口都有效。 +**同步/异步对称**: 每个接口都具有同步和异步变体,方法签名相同。 +**相同的签名**: 当功能重叠时,REST 和 WebSocket 之间的同步和异步方法签名相同。 +**渐进式增强**: 根据需求选择接口(REST 用于简单操作,WebSocket 用于流式传输,Bulk 用于大型数据集,async 用于现代框架)。 +**明确意图**: `api.socket()` 表示 WebSocket,`api.async_socket()` 表示异步 WebSocket。 +**向后兼容**: 现有代码保持不变。 + +### 组件 + +#### 1. 核心 API 类 (修改版) + +模块: `trustgraph-base/trustgraph/api/api.py` + +**增强的 API 类**: + +```python +class Api: + def __init__(self, url: str, timeout: int = 60, token: Optional[str] = None): + self.url = url + self.timeout = timeout + self.token = token # Optional bearer token for REST, query param for WebSocket + self._socket_client = None + self._bulk_client = None + self._async_flow = None + self._async_socket_client = None + self._async_bulk_client = None + + # Existing synchronous methods (unchanged) + def flow(self) -> Flow: + """Synchronous REST-based flow interface""" + pass + + def library(self) -> Library: + """Synchronous REST-based library interface""" + pass + + def knowledge(self) -> Knowledge: + """Synchronous REST-based knowledge interface""" + pass + + def collection(self) -> Collection: + """Synchronous REST-based collection interface""" + pass + + def config(self) -> Config: + """Synchronous REST-based config interface""" + pass + + # New synchronous methods + def socket(self) -> SocketClient: + """Synchronous WebSocket-based interface for streaming operations""" + if self._socket_client is None: + self._socket_client = SocketClient(self.url, self.timeout, self.token) + return self._socket_client + + def bulk(self) -> BulkClient: + """Synchronous bulk operations interface for import/export""" + if self._bulk_client is None: + self._bulk_client = BulkClient(self.url, self.timeout, self.token) + return self._bulk_client + + def metrics(self) -> Metrics: + """Synchronous metrics interface""" + return Metrics(self.url, self.timeout, self.token) + + # New asynchronous methods + def async_flow(self) -> AsyncFlow: + """Asynchronous REST-based flow interface""" + if self._async_flow is None: + self._async_flow = AsyncFlow(self.url, self.timeout, self.token) + return self._async_flow + + def async_socket(self) -> AsyncSocketClient: + """Asynchronous WebSocket-based interface for streaming operations""" + if self._async_socket_client is None: + self._async_socket_client = AsyncSocketClient(self.url, self.timeout, self.token) + return self._async_socket_client + + def async_bulk(self) -> AsyncBulkClient: + """Asynchronous bulk operations interface for import/export""" + if self._async_bulk_client is None: + self._async_bulk_client = AsyncBulkClient(self.url, self.timeout, self.token) + return self._async_bulk_client + + def async_metrics(self) -> AsyncMetrics: + """Asynchronous metrics interface""" + return AsyncMetrics(self.url, self.timeout, self.token) + + # Resource management + def close(self) -> None: + """Close all synchronous connections""" + if self._socket_client: + self._socket_client.close() + if self._bulk_client: + self._bulk_client.close() + + async def aclose(self) -> None: + """Close all asynchronous connections""" + if self._async_socket_client: + await self._async_socket_client.aclose() + if self._async_bulk_client: + await self._async_bulk_client.aclose() + if self._async_flow: + await self._async_flow.aclose() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + async def __aenter__(self): + return self + + async def __aexit__(self, *args): + await self.aclose() +``` + +#### 2. 同步 WebSocket 客户端 + +模块:`trustgraph-base/trustgraph/api/socket_client.py` (新) + +**SocketClient 类**: + +```python +class SocketClient: + """Synchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> SocketFlowInstance: + """Get flow instance for WebSocket operations""" + return SocketFlowInstance(self, flow_id) + + def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Uses asyncio.run() internally to wrap async websockets library + pass + + def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + # Synchronous wrapper around async WebSocket calls + pass + + def close(self) -> None: + """Close WebSocket connection""" + pass + +class SocketFlowInstance: + """Synchronous WebSocket flow instance with same interface as REST FlowInstance""" + def __init__(self, client: SocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance + def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, Iterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**主要特性:** +延迟连接(仅在首次发送请求时建立连接) +请求复用(最多 15 个并发请求) +断开连接时自动重连 +流式响应解析 +线程安全操作 +异步 WebSocket 库的同步封装 + +#### 3. 异步 WebSocket 客户端 + +模块:`trustgraph-base/trustgraph/api/async_socket_client.py` (新) + +**AsyncSocketClient 类:** + +```python +class AsyncSocketClient: + """Asynchronous WebSocket client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + self._connection = None + self._request_counter = 0 + + def flow(self, flow_id: str) -> AsyncSocketFlowInstance: + """Get async flow instance for WebSocket operations""" + return AsyncSocketFlowInstance(self, flow_id) + + async def _connect(self) -> WebSocket: + """Establish WebSocket connection (lazy)""" + # Native async websockets library + pass + + async def _send_request( + self, + service: str, + flow: Optional[str], + request: Dict[str, Any], + streaming: bool = False + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Send request and handle response/streaming""" + pass + + async def aclose(self) -> None: + """Close WebSocket connection""" + pass + +class AsyncSocketFlowInstance: + """Asynchronous WebSocket flow instance""" + def __init__(self, client: AsyncSocketClient, flow_id: str): + self.client = client + self.flow_id = flow_id + + # Same method signatures as FlowInstance (but async) + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + streaming: bool = False, + **kwargs + ) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]: + """Agent with optional streaming""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + streaming: bool = False, + **kwargs + ) -> Union[str, AsyncIterator[str]]: + """Text completion with optional streaming""" + pass + + # ... similar for graph_rag, document_rag, prompt, etc. +``` + +**主要特性:** +原生支持 async/await +适用于异步应用程序(FastAPI, aiohttp) +无线程阻塞 +与同步版本具有相同的接口 +AsyncIterator 用于流式传输 + +#### 4. 同步批量操作客户端 + +模块:`trustgraph-base/trustgraph/api/bulk_client.py` (新) + +**BulkClient 类:** + +```python +class BulkClient: + """Synchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + def import_triples( + self, + flow: str, + triples: Iterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + def export_triples( + self, + flow: str, + **kwargs + ) -> Iterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + def import_graph_embeddings( + self, + flow: str, + embeddings: Iterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> Iterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + def close(self) -> None: + """Close connections""" + pass +``` + +**主要特性:** +基于迭代器,内存占用恒定 +每个操作都使用专用的 WebSocket 连接 +进度跟踪(可选的回调函数) +错误处理,支持部分成功报告 + +#### 5. 异步批量操作客户端 + +模块:`trustgraph-base/trustgraph/api/async_bulk_client.py` (新) + +**AsyncBulkClient 类:** + +```python +class AsyncBulkClient: + """Asynchronous bulk operations client""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = self._convert_to_ws_url(url) + self.timeout = timeout + self.token = token + + async def import_triples( + self, + flow: str, + triples: AsyncIterator[Triple], + **kwargs + ) -> None: + """Bulk import triples via WebSocket""" + pass + + async def export_triples( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Triple]: + """Bulk export triples via WebSocket""" + pass + + async def import_graph_embeddings( + self, + flow: str, + embeddings: AsyncIterator[Dict[str, Any]], + **kwargs + ) -> None: + """Bulk import graph embeddings via WebSocket""" + pass + + async def export_graph_embeddings( + self, + flow: str, + **kwargs + ) -> AsyncIterator[Dict[str, Any]]: + """Bulk export graph embeddings via WebSocket""" + pass + + # ... similar for document embeddings, entity contexts, objects + + async def aclose(self) -> None: + """Close connections""" + pass +``` + +**主要特性:** +基于 AsyncIterator,内存占用恒定 +适用于异步应用程序,效率高 +原生支持 async/await +与同步版本具有相同的接口 + +#### 6. REST Flow API (同步 - 未改变) + +模块:`trustgraph-base/trustgraph/api/flow.py` + +REST Flow API 保持 **完全不变**,以确保向后兼容。所有现有方法均可继续使用: + +`Flow.list()`, `Flow.start()`, `Flow.stop()`, 等等。 +`FlowInstance.agent()`, `FlowInstance.text_completion()`, `FlowInstance.graph_rag()`, 等等。 +所有现有签名和返回类型均已保留 + +**新增:** 为了实现功能对等,向 REST FlowInstance 添加 `graph_embeddings_query()`: + +```python +class FlowInstance: + # All existing methods unchanged... + + # New: Graph embeddings query (REST) + def graph_embeddings_query( + self, + text: str, + user: str, + collection: str, + limit: int = 10, + **kwargs + ) -> List[Dict[str, Any]]: + """Query graph embeddings for semantic search""" + # Calls POST /api/v1/flow/{flow}/service/graph-embeddings + pass +``` + +#### 7. 异步 REST 流程 API + +模块:`trustgraph-base/trustgraph/api/async_flow.py` (新) + +**AsyncFlow 和 AsyncFlowInstance 类:** + +```python +class AsyncFlow: + """Asynchronous REST-based flow interface""" + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def list(self) -> List[Dict[str, Any]]: + """List all flows""" + pass + + async def get(self, id: str) -> Dict[str, Any]: + """Get flow definition""" + pass + + async def start(self, class_name: str, id: str, description: str, parameters: Dict) -> None: + """Start a flow""" + pass + + async def stop(self, id: str) -> None: + """Stop a flow""" + pass + + def id(self, flow_id: str) -> AsyncFlowInstance: + """Get async flow instance""" + return AsyncFlowInstance(self.url, self.timeout, self.token, flow_id) + + async def aclose(self) -> None: + """Close connection""" + pass + +class AsyncFlowInstance: + """Asynchronous REST flow instance""" + + async def agent( + self, + question: str, + user: str, + state: Optional[Dict[str, Any]] = None, + group: Optional[str] = None, + history: Optional[List[Dict[str, Any]]] = None, + **kwargs + ) -> Dict[str, Any]: + """Async agent execution""" + pass + + async def text_completion( + self, + system: str, + prompt: str, + **kwargs + ) -> str: + """Async text completion""" + pass + + async def graph_rag( + self, + question: str, + user: str, + collection: str, + **kwargs + ) -> str: + """Async graph RAG""" + pass + + # ... all other FlowInstance methods as async versions +``` + +**主要特性:** +使用 `aiohttp` 或 `httpx` 实现原生异步 HTTP。 +方法签名与同步 REST API 相同。 +不支持流式传输(使用 `async_socket()` 进行流式传输)。 +适用于异步应用程序。 + +#### 8. Metrics API + +模块:`trustgraph-base/trustgraph/api/metrics.py` (新) + +**同步 Metrics:** + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +**异步指标:** + +```python +class AsyncMetrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + async def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +#### 9. 增强的类型 + +模块:`trustgraph-base/trustgraph/api/types.py` (已修改) + +**新类型:** + +```python +from typing import Iterator, Union, Dict, Any +import dataclasses + +@dataclasses.dataclass +class StreamingChunk: + """Base class for streaming chunks""" + content: str + end_of_message: bool = False + +@dataclasses.dataclass +class AgentThought(StreamingChunk): + """Agent reasoning chunk""" + chunk_type: str = "thought" + +@dataclasses.dataclass +class AgentObservation(StreamingChunk): + """Agent tool observation chunk""" + chunk_type: str = "observation" + +@dataclasses.dataclass +class AgentAnswer(StreamingChunk): + """Agent final answer chunk""" + chunk_type: str = "final-answer" + end_of_dialog: bool = False + +@dataclasses.dataclass +class RAGChunk(StreamingChunk): + """RAG streaming chunk""" + end_of_stream: bool = False + error: Optional[Dict[str, str]] = None + +# Type aliases for clarity +AgentStream = Iterator[Union[AgentThought, AgentObservation, AgentAnswer]] +RAGStream = Iterator[RAGChunk] +CompletionStream = Iterator[str] +``` + +#### 6. 指标 API + +模块:`trustgraph-base/trustgraph/api/metrics.py` (新) + +```python +class Metrics: + def __init__(self, url: str, timeout: int, token: Optional[str]): + self.url = url + self.timeout = timeout + self.token = token + + def get(self) -> str: + """Get Prometheus metrics as text""" + # Call GET /api/metrics + pass +``` + +### 实现方案 + +#### 第一阶段:核心 API 增强 (第一周) + +1. 向 `Api` 类添加 `socket()`、`bulk()` 和 `metrics()` 方法 +2. 实现 WebSocket 和批量客户端的延迟初始化 +3. 添加上下文管理器支持 (`__enter__`, `__exit__`) +4. 添加 `close()` 方法进行清理 +5. 为 API 类增强添加单元测试 +6. 验证向后兼容性 + +**向后兼容性**: 没有破坏性更改。仅添加了新方法。 + +#### 第二阶段:WebSocket 客户端 (第二周 - 第三周) + +1. 实现 `SocketClient` 类,用于连接管理 +2. 实现 `SocketFlowInstance`,方法签名与 `FlowInstance` 相同 +3. 添加请求复用支持 (最多 15 个并发) +4. 添加流式响应解析,支持不同的分块类型 +5. 添加自动重连逻辑 +6. 添加单元和集成测试 +7. 记录 WebSocket 使用模式 + +**向后兼容性**: 仅为新接口。对现有代码没有影响。 + +#### 第三阶段:流式支持 (第三周 - 第四周) + +1. 添加流式分块类型类 (`AgentThought`, `AgentObservation`, `AgentAnswer`, `RAGChunk`) +2. 在 `SocketClient` 中实现流式响应解析 +3. 将流式参数添加到 `SocketFlowInstance` 中的所有 LLM 方法 +4. 处理流式过程中的错误情况 +5. 添加流式功能的单元和集成测试 +6. 在文档中添加流式示例 + +**向后兼容性**: 仅为新接口。现有 REST API 未改变。 + +#### 第四阶段:批量操作 (第四周 - 第五周) + +1. 实现 `BulkClient` 类 +2. 添加三元组、嵌入、上下文、对象的批量导入/导出方法 +3. 实现基于迭代器的处理,以实现恒定内存 +4. 添加进度跟踪 (可选的回调) +5. 添加错误处理,并报告部分成功 +6. 添加单元和集成测试 +7. 添加批量操作示例 + +**向后兼容性**: 仅为新接口。对现有代码没有影响。 + +#### 第五阶段:功能完善与优化 (第五周) + +1. 向 REST `FlowInstance` 添加 `graph_embeddings_query()` +2. 实现 `Metrics` 类 +3. 添加全面的集成测试 +4. 性能基准测试 +5. 更新所有文档 +6. 创建迁移指南 + +**向后兼容性**: 仅添加新方法。对现有代码没有影响。 + +### 数据模型 + +#### 接口选择 + +```python +# Single API instance, same URL for all interfaces +api = Api(url="http://localhost:8088/") + +# Synchronous interfaces +rest_flow = api.flow().id("default") # Sync REST +socket_flow = api.socket().flow("default") # Sync WebSocket +bulk = api.bulk() # Sync bulk operations +metrics = api.metrics() # Sync metrics + +# Asynchronous interfaces +async_rest_flow = api.async_flow().id("default") # Async REST +async_socket_flow = api.async_socket().flow("default") # Async WebSocket +async_bulk = api.async_bulk() # Async bulk operations +async_metrics = api.async_metrics() # Async metrics +``` + +#### 流式响应类型 + +**代理流式传输**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - non-streaming (same signature) +socket_flow = api.socket().flow("default") +response = socket_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# WebSocket interface - streaming (new) +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentThought): + print(f"Thinking: {chunk.content}") + elif isinstance(chunk, AgentObservation): + print(f"Observed: {chunk.content}") + elif isinstance(chunk, AgentAnswer): + print(f"Answer: {chunk.content}") + if chunk.end_of_dialog: + break +``` + +**RAG 流式传输**: + +```python +api = Api(url="http://localhost:8088/") + +# REST interface - non-streaming (existing) +rest_flow = api.flow().id("default") +response = rest_flow.graph_rag(question="What is Python?", user="user123", collection="default") +print(response) + +# WebSocket interface - streaming (new) +socket_flow = api.socket().flow("default") +for chunk in socket_flow.graph_rag( + question="What is Python?", + user="user123", + collection="default", + streaming=True +): + print(chunk.content, end="", flush=True) + if chunk.end_of_stream: + break +``` + +**批量操作 (同步)**: + +```python +api = Api(url="http://localhost:8088/") + +# Bulk import triples +def triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + +bulk = api.bulk() +bulk.import_triples(flow="default", triples=triple_generator()) + +# Bulk export triples +for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") +``` + +**批量操作(异步)**: + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async bulk import triples + async def async_triple_generator(): + yield Triple(s="http://ex.com/alice", p="http://ex.com/type", o="Person") + yield Triple(s="http://ex.com/alice", p="http://ex.com/name", o="Alice") + yield Triple(s="http://ex.com/bob", p="http://ex.com/type", o="Person") + + bulk = api.async_bulk() + await bulk.import_triples(flow="default", triples=async_triple_generator()) + + # Async bulk export triples + async for triple in bulk.export_triples(flow="default"): + print(f"{triple.s} -> {triple.p} -> {triple.o}") + +asyncio.run(main()) +``` + +**异步 REST 示例:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async REST flow operations + flow = api.async_flow().id("default") + response = await flow.agent(question="What is ML?", user="user123") + print(response["response"]) + +asyncio.run(main()) +``` + +**异步 WebSocket 流式传输示例:** + +```python +import asyncio + +async def main(): + api = Api(url="http://localhost:8088/") + + # Async WebSocket streaming + socket = api.async_socket() + flow = socket.flow("default") + + async for chunk in flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) + if chunk.end_of_dialog: + break + +asyncio.run(main()) +``` + +### APIs + +#### New APIs + +1. **Core API Class**: + **Synchronous**: + `Api.socket()` - Get synchronous WebSocket client + `Api.bulk()` - Get synchronous bulk operations client + `Api.metrics()` - Get synchronous metrics client + `Api.close()` - Close all synchronous connections + Context manager support (`__enter__`, `__exit__`) + **Asynchronous**: + `Api.async_flow()` - Get asynchronous REST flow client + `Api.async_socket()` - Get asynchronous WebSocket client + `Api.async_bulk()` - Get asynchronous bulk operations client + `Api.async_metrics()` - Get asynchronous metrics client + `Api.aclose()` - Close all asynchronous connections + Async context manager support (`__aenter__`, `__aexit__`) + +2. **Synchronous WebSocket Client**: + `SocketClient.flow(flow_id)` - Get WebSocket flow instance + `SocketFlowInstance.agent(..., streaming: bool = False)` - Agent with optional streaming + `SocketFlowInstance.text_completion(..., streaming: bool = False)` - Text completion with optional streaming + `SocketFlowInstance.graph_rag(..., streaming: bool = False)` - Graph RAG with optional streaming + `SocketFlowInstance.document_rag(..., streaming: bool = False)` - Document RAG with optional streaming + `SocketFlowInstance.prompt(..., streaming: bool = False)` - Prompt with optional streaming + `SocketFlowInstance.graph_embeddings_query()` - Graph embeddings query + All other FlowInstance methods with identical signatures + +3. **Asynchronous WebSocket Client**: + `AsyncSocketClient.flow(flow_id)` - Get async WebSocket flow instance + `AsyncSocketFlowInstance.agent(..., streaming: bool = False)` - Async agent with optional streaming + `AsyncSocketFlowInstance.text_completion(..., streaming: bool = False)` - Async text completion with optional streaming + `AsyncSocketFlowInstance.graph_rag(..., streaming: bool = False)` - Async graph RAG with optional streaming + `AsyncSocketFlowInstance.document_rag(..., streaming: bool = False)` - Async document RAG with optional streaming + `AsyncSocketFlowInstance.prompt(..., streaming: bool = False)` - Async prompt with optional streaming + `AsyncSocketFlowInstance.graph_embeddings_query()` - Async graph embeddings query + All other FlowInstance methods as async versions + +4. **Synchronous Bulk Operations Client**: + `BulkClient.import_triples(flow, triples)` - Bulk triple import + `BulkClient.export_triples(flow)` - Bulk triple export + `BulkClient.import_graph_embeddings(flow, embeddings)` - Bulk graph embeddings import + `BulkClient.export_graph_embeddings(flow)` - Bulk graph embeddings export + `BulkClient.import_document_embeddings(flow, embeddings)` - Bulk document embeddings import + `BulkClient.export_document_embeddings(flow)` - Bulk document embeddings export + `BulkClient.import_entity_contexts(flow, contexts)` - Bulk entity contexts import + `BulkClient.export_entity_contexts(flow)` - Bulk entity contexts export + `BulkClient.import_objects(flow, objects)` - Bulk objects import + +5. **Asynchronous Bulk Operations Client**: + `AsyncBulkClient.import_triples(flow, triples)` - Async bulk triple import + `AsyncBulkClient.export_triples(flow)` - Async bulk triple export + `AsyncBulkClient.import_graph_embeddings(flow, embeddings)` - Async bulk graph embeddings import + `AsyncBulkClient.export_graph_embeddings(flow)` - Async bulk graph embeddings export + `AsyncBulkClient.import_document_embeddings(flow, embeddings)` - Async bulk document embeddings import + `AsyncBulkClient.export_document_embeddings(flow)` - Async bulk document embeddings export + `AsyncBulkClient.import_entity_contexts(flow, contexts)` - Async bulk entity contexts import + `AsyncBulkClient.export_entity_contexts(flow)` - Async bulk entity contexts export + `AsyncBulkClient.import_objects(flow, objects)` - Async bulk objects import + +6. **Asynchronous REST Flow Client**: + `AsyncFlow.list()` - Async list all flows + `AsyncFlow.get(id)` - Async get flow definition + `AsyncFlow.start(...)` - Async start flow + `AsyncFlow.stop(id)` - Async stop flow + `AsyncFlow.id(flow_id)` - Get async flow instance + `AsyncFlowInstance.agent(...)` - Async agent execution + `AsyncFlowInstance.text_completion(...)` - Async text completion + `AsyncFlowInstance.graph_rag(...)` - Async graph RAG + All other FlowInstance methods as async versions + +7. **Metrics Clients**: + `Metrics.get()` - Synchronous Prometheus metrics + `AsyncMetrics.get()` - Asynchronous Prometheus metrics + +8. **REST Flow API Enhancement**: + `FlowInstance.graph_embeddings_query()` - Graph embeddings query (sync feature parity) + `AsyncFlowInstance.graph_embeddings_query()` - Graph embeddings query (async feature parity) + +#### Modified APIs + +1. **Constructor** (minor enhancement): + ```python + Api(url: str, timeout: int = 60, token: Optional[str] = None) + ``` + 添加了 `token` 参数(可选,用于身份验证) + 如果未指定 `None`(默认):未使用身份验证 + 如果已指定:用作 REST 的 bearer token(`Authorization: Bearer `),用作 WebSocket 的查询参数(`?token=`) + 没有其他更改 - 完全向后兼容 + +2. **无破坏性更改:** + 所有现有的 REST API 方法未更改 + 所有现有的签名均保留 + 所有现有的返回类型均保留 + +### 实现细节 + +#### 错误处理 + +**WebSocket 连接错误:** +```python +try: + api = Api(url="http://localhost:8088/") + socket = api.socket() + socket_flow = socket.flow("default") + response = socket_flow.agent(question="...", user="user123") +except ConnectionError as e: + print(f"WebSocket connection failed: {e}") + print("Hint: Ensure Gateway is running and WebSocket endpoint is accessible") +``` + +**优雅的降级方案**: +```python +api = Api(url="http://localhost:8088/") + +try: + # Try WebSocket streaming first + socket_flow = api.socket().flow("default") + for chunk in socket_flow.agent(question="...", user="...", streaming=True): + print(chunk.content) +except ConnectionError: + # Fall back to REST non-streaming + print("WebSocket unavailable, falling back to REST") + rest_flow = api.flow().id("default") + response = rest_flow.agent(question="...", user="...") + print(response["response"]) +``` + +**部分流式错误:** +```python +api = Api(url="http://localhost:8088/") +socket_flow = api.socket().flow("default") + +accumulated = [] +try: + for chunk in socket_flow.graph_rag(question="...", streaming=True): + accumulated.append(chunk.content) + if chunk.error: + print(f"Error occurred: {chunk.error}") + print(f"Partial response: {''.join(accumulated)}") + break +except Exception as e: + print(f"Streaming error: {e}") + print(f"Partial response: {''.join(accumulated)}") +``` + +#### 资源管理 + +**上下文管理器支持:** +```python +# Automatic cleanup +with Api(url="http://localhost:8088/") as api: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +# All connections automatically closed + +# Manual cleanup +api = Api(url="http://localhost:8088/") +try: + socket_flow = api.socket().flow("default") + response = socket_flow.agent(question="...", user="user123") +finally: + api.close() # Explicitly close all connections (WebSocket, bulk, etc.) +``` + +#### 线程和并发 + +**线程安全**: +每个 `Api` 实例维护自己的连接。 +WebSocket 传输使用锁进行线程安全的请求复用。 +多个线程可以安全地共享一个 `Api` 实例。 +流式迭代器不具备线程安全特性(只能从单个线程消费)。 + +**异步支持**(未来考虑): +```python +# Phase 2 enhancement (not in initial scope) +import asyncio + +async def main(): + api = await AsyncApi(url="ws://localhost:8088/") + flow = api.flow().id("default") + + async for chunk in flow.agent(question="...", streaming=True): + print(chunk.content) + + await api.close() + +asyncio.run(main()) +``` + +## 安全注意事项 + +### 身份验证 + +**令牌参数**: +```python +# No authentication (default) +api = Api(url="http://localhost:8088/") + +# With authentication +api = Api(url="http://localhost:8088/", token="mytoken") +``` + +**REST 传输:** +通过 `Authorization` 头部传递认证令牌 +自动应用于所有 REST 请求 +格式:`Authorization: Bearer ` + +**WebSocket 传输:** +通过附加到 WebSocket URL 的查询参数传递认证令牌 +在连接建立期间自动应用 +格式:`ws://localhost:8088/api/v1/socket?token=` + +**实现:** +```python +class SocketClient: + def _connect(self) -> WebSocket: + # Construct WebSocket URL with optional token + ws_url = f"{self.url}/api/v1/socket" + if self.token: + ws_url = f"{ws_url}?token={self.token}" + # Connect to WebSocket + return websocket.connect(ws_url) +``` + +**示例:** +```python +# REST with auth +api = Api(url="http://localhost:8088/", token="mytoken") +flow = api.flow().id("default") +# All REST calls include: Authorization: Bearer mytoken + +# WebSocket with auth +socket = api.socket() +# Connects to: ws://localhost:8088/api/v1/socket?token=mytoken +``` + +### 安全通信 + +支持 WS (WebSocket) 和 WSS (WebSocket Secure) 两种协议。 +WSS 连接的 TLS 证书验证。 +可选的开发环境下的证书验证禁用(带有警告)。 + +### 输入验证 + +验证 URL 协议 (http, https, ws, wss)。 +验证传输参数值。 +验证流式传输参数组合。 +验证批量导入的数据类型。 + +## 性能考虑 + +### 延迟优化 + +**流式 LLM 操作**: +**首次 token 时间**: ~500 毫秒 (vs ~30 秒 非流式) +**改进**: 性能提升 60 倍 +**适用范围**: Agent, Graph RAG, Document RAG, 文本补全, Prompt + +**持久连接**: +**连接开销**: 后续请求消除连接开销 +**WebSocket 握手**: 一次性成本 (~100 毫秒) +**适用范围**: 使用 WebSocket 传输的所有操作 + +### 吞吐量优化 + +**批量操作**: +**三元组导入**: ~10,000 三元组/秒 (vs ~100/秒 使用 REST 单个项目) +**嵌入向量导入**: ~5,000 嵌入向量/秒 (vs ~50/秒 使用 REST 单个项目) +**改进**: 批量操作的吞吐量提升 100 倍 + +**请求复用**: +**并发请求**: 单个连接可支持最多 15 个并发请求 +**连接重用**: 并发操作无需连接开销 + +### 内存考虑 + +**流式响应**: +恒定内存使用 (按接收到的块处理) +不缓冲完整的响应 +适用于非常长的输出 (>1MB) + +**批量操作**: +基于迭代器的处理 (恒定内存) +不将整个数据集加载到内存中 +适用于包含数百万项的数据集 + +### 基准测试 (预期) + +| 操作 | REST (现有) | WebSocket (流式传输) | 改进 | +|-----------|----------------|----------------------|-------------| +| Agent (首次 token 时间) | 30 秒 | 0.5 秒 | 60 倍 | +| Graph RAG (首次 token 时间) | 25 秒 | 0.5 秒 | 50 倍 | +| 导入 10K 三元组 | 100 秒 | 1 秒 | 100 倍 | +| 导入 1M 三元组 | 10,000 秒 (2.7 小时) | 100 秒 (1.6 分钟) | 100 倍 | +| 10 个并发小请求 | 5 秒 (顺序) | 0.5 秒 (并行) | 10 倍 | + +## 测试策略 + +### 单元测试 + +**传输层** (`test_transport.py`): +测试 REST 传输的请求/响应 +测试 WebSocket 传输连接 +测试 WebSocket 传输重连 +测试请求复用 +测试流式响应解析 +模拟 WebSocket 服务器以进行确定性测试 + +**API 方法** (`test_flow.py`, `test_library.py`, 等): +使用模拟传输测试新方法 +测试流式参数处理 +测试批量操作迭代器 +测试错误处理 + +**类型** (`test_types.py`): +测试新的流式分块类型 +测试类型序列化/反序列化 + +### 集成测试 + +**端到端 REST** (`test_integration_rest.py`): +测试所有操作,针对真实的网关(REST 模式) +验证向后兼容性 +测试错误条件 + +**端到端 WebSocket** (`test_integration_websocket.py`): +测试所有操作,针对真实的网关(WebSocket 模式) +测试流式操作 +测试批量操作 +测试并发请求 +测试连接恢复 + +**流式服务** (`test_streaming_integration.py`): +测试代理流式传输(想法、观察、答案) +测试 RAG 流式传输(增量分块) +测试文本补全流式传输(逐个 token) +测试提示流式传输 +测试流式传输过程中的错误处理 + +**批量操作** (`test_bulk_integration.py`): +测试三元组的批量导入/导出(1K、10K、100K 个条目) +测试嵌入的批量导入/导出 +测试批量操作期间的内存使用情况 +测试进度跟踪 + +### 性能测试 + +**延迟基准测试** (`test_performance_latency.py`): +测量第一个 token 的时间(流式传输与非流式传输) +测量连接开销(REST 与 WebSocket) +与预期基准进行比较 + +**吞吐量基准测试** (`test_performance_throughput.py`): +测量批量导入吞吐量 +测量请求复用效率 +与预期基准进行比较 + +### 兼容性测试 + +**向后兼容性** (`test_backward_compatibility.py`): +运行现有测试套件,针对重构的 API +验证没有破坏性更改 +测试常见模式的迁移路径 + +## 迁移计划 + +### 第一阶段:透明迁移(默认) + +**无需任何代码更改**。 现有代码继续工作: + +```python +# Existing code works unchanged +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") +response = flow.agent(question="What is ML?", user="user123") +``` + +### 第二阶段:选择加入的流媒体(简单) + +**使用 `api.socket()` 接口** 启用流媒体: + +```python +# Before: Non-streaming REST +api = Api(url="http://localhost:8088/") +rest_flow = api.flow().id("default") +response = rest_flow.agent(question="What is ML?", user="user123") +print(response["response"]) + +# After: Streaming WebSocket (same parameters!) +api = Api(url="http://localhost:8088/") # Same URL +socket_flow = api.socket().flow("default") + +for chunk in socket_flow.agent(question="What is ML?", user="user123", streaming=True): + if isinstance(chunk, AgentAnswer): + print(chunk.content, end="", flush=True) +``` + +**关键点:** +REST 和 WebSocket 都使用相同的 URL +相同的函数签名(易于迁移) +只需要添加 `.socket()` 和 `streaming=True` + +### 第三阶段:批量操作(新功能) + +**使用 `api.bulk()` 接口** 处理大型数据集: + +```python +# Before: Inefficient per-item operations +api = Api(url="http://localhost:8088/") +flow = api.flow().id("default") + +for triple in my_large_triple_list: + # Slow per-item operations + # (no direct bulk insert in REST API) + pass + +# After: Efficient bulk loading +api = Api(url="http://localhost:8088/") # Same URL +bulk = api.bulk() + +# This is fast (10,000 triples/second) +bulk.import_triples(flow="default", triples=iter(my_large_triple_list)) +``` + +### 文档更新 + +1. **README.md**: 添加流式传输和 WebSocket 示例 +2. **API 参考**: 记录所有新的方法和参数 +3. **迁移指南**: 启用流式传输的分步指南 +4. **示例**: 添加常用模式的示例脚本 +5. **性能指南**: 记录预期的性能改进 + +### 弃用策略 + +**无弃用**. 所有现有的 API 均继续支持。 这是一个纯粹的增强。 + +## 时间线 + +### 第一周:基础 +传输抽象层 +重构现有的 REST 代码 +传输层的单元测试 +向后兼容性验证 + +### 第二周:WebSocket 传输 +WebSocket 传输实现 +连接管理和重连 +请求复用 +单元和集成测试 + +### 第三周:流式传输支持 +向 LLM 方法添加流式传输参数 +实现流式响应解析 +添加流式传输块类型 +流式传输集成测试 + +### 第四周:批量操作 +添加批量导入/导出方法 +实现基于迭代器的操作 +性能测试 +批量操作集成测试 + +### 第五周:功能对齐与文档 +添加图嵌入查询 +添加指标 API +综合文档 +迁移指南 +候选版本 + +### 第六周:发布 +最终集成测试 +性能基准测试 +发布文档 +社区公告 + +**总时长**: 6 周 + +## 开放问题 + +### API 设计问题 + +1. **异步支持**: ✅ **已解决** - 异步支持已包含在初始版本中 + 所有接口都具有异步变体:`async_flow()`, `async_socket()`, `async_bulk()`, `async_metrics()` + 为同步和异步 API 提供完全的对称性 + 对于现代异步框架(FastAPI, aiohttp)至关重要 + +2. **进度跟踪**: 批量操作是否应支持进度回调? + ```python + def progress_callback(processed: int, total: Optional[int]): + print(f"Processed {processed} items") + + bulk.import_triples(flow="default", triples=triples, on_progress=progress_callback) + ``` + **建议**: 在第二阶段添加。对于初始发布,这不是关键。 + +3. **流式传输超时**: 我们应该如何处理流式传输操作的超时? + **建议**: 使用与非流式传输相同的超时时间,但在接收每个数据块时重置。 + +4. **数据块缓冲**: 我们应该缓冲数据块,还是立即返回? + **建议**: 立即返回,以获得最低延迟。 + +5. **WebSocket 上的全局服务**: `api.socket()` 是否应该支持全局服务(库、知识、集合、配置),或者仅支持作用域服务? + **建议**: 仅从作用域服务开始(流式传输相关)。如果需要,可以在第二阶段添加全局服务。 + +### 实现问题 + +1. **WebSocket 库**: 我们应该使用 `websockets`、`websocket-client` 还是 `aiohttp`? + **建议**: `websockets` (异步,成熟,维护良好)。使用 `asyncio.run()` 包装成同步接口。 + +2. **连接池**: 我们是否应该支持多个并发的 `Api` 实例共享连接池? + **建议**: 延期到第二阶段。最初,每个 `Api` 实例都有自己的连接。 + +3. **连接重用**: `SocketClient` 和 `BulkClient` 是否应该共享同一个 WebSocket 连接,或者使用单独的连接? + **建议**: 使用单独的连接。实现更简单,职责分离更清晰。 + +4. **延迟连接 vs 立即连接**: WebSocket 连接是在 `api.socket()` 中建立,还是在首次请求时建立? + **建议**: 延迟到首次请求时建立。避免连接开销,如果用户仅使用 REST 方法。 + +### 测试问题 + +1. **模拟网关**: 我们是否应该创建一个轻量级的模拟网关进行测试,或者直接测试真实网关? + **建议**: 都应该。使用模拟进行单元测试,使用真实网关进行集成测试。 + +2. **性能回归测试**: 我们是否应该将自动化性能回归测试添加到 CI 中? + **建议**: 是的,但应设置宽松的阈值,以考虑 CI 环境的差异。 + +## 引用 + +### 相关技术规范 +`docs/tech-specs/streaming-llm-responses.md` - 网关中的流式传输实现 +`docs/tech-specs/rag-streaming-support.md` - RAG 流式传输支持 + +### 实现文件 +`trustgraph-base/trustgraph/api/` - Python API 源代码 +`trustgraph-flow/trustgraph/gateway/` - 网关源代码 +`trustgraph-flow/trustgraph/gateway/dispatch/mux.py` - WebSocket 多路复用参考实现 + +### 文档 +`docs/apiSpecification.md` - 完整的 API 参考 +`docs/api-status-summary.md` - API 状态摘要 +`README.websocket` - WebSocket 协议文档 +`STREAMING-IMPLEMENTATION-NOTES.txt` - 流式传输实现说明 + +### 外部库 +`websockets` - Python WebSocket 库 (https://websockets.readthedocs.io/) +`requests` - Python HTTP 库 (现有) diff --git a/docs/tech-specs/query-time-explainability.ar.md b/docs/tech-specs/query-time-explainability.ar.md new file mode 100644 index 00000000..49a67fc5 --- /dev/null +++ b/docs/tech-specs/query-time-explainability.ar.md @@ -0,0 +1,271 @@ +--- +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. + +## الحالة + +تم التنفيذ + +## نظرة عامة + +يصف هذا المواصفات كيفية تسجيل GraphRAG وتوصيل بيانات الشرح أثناء تنفيذ الاستعلام. الهدف هو التتبع الكامل: من الإجابة النهائية إلى الحواف المحددة ثم إلى المستندات المصدر. + +يمثل الشرح في وقت الاستعلام ما قام به مسار عمل GraphRAG أثناء عملية الاستدلال. وهو مرتبط ببيانات المصدر التي تم تسجيلها في وقت الاستخراج، والتي تسجل أصل حقائق الرسم البياني المعرفي. + +## المصطلحات + +| المصطلح | التعريف | +|------|------------| +| **الشرح** | سجل لكيفية اشتقاق نتيجة | +| **الجلسة** | تنفيذ استعلام GraphRAG واحد | +| **اختيار الحواف** | اختيار الحواف ذات الصلة المدفوع بالنماذج اللغوية الكبيرة مع الاستدلال | +| **سلسلة المصدر** | مسار من الحافة → الجزء → الصفحة → المستند | + +## البنية + +### تدفق الشرح + +``` +GraphRAG Query + │ + ├─► Session Activity + │ └─► Query text, timestamp + │ + ├─► Retrieval Entity + │ └─► All edges retrieved from subgraph + │ + ├─► Selection Entity + │ └─► Selected edges with LLM reasoning + │ └─► Each edge links to extraction provenance + │ + └─► Answer Entity + └─► Reference to synthesized response (in librarian) +``` + +### خط أنابيب GraphRAG ثنائي المراحل + +1. **اختيار الحواف**: يقوم نموذج اللغة الكبيرة (LLM) باختيار الحواف ذات الصلة من الرسم البياني الفرعي، مع تقديم مبررات لكل حافة. +2. **التوليف**: يقوم نموذج اللغة الكبيرة (LLM) بإنشاء الإجابة من الحواف المحددة فقط. + +هذا الفصل يمكّن من إمكانية التفسير - نحن نعرف بالضبط أي الحواف ساهمت. + +### التخزين + +يتم تخزين ثلاثيات إمكانية التفسير في مجموعة قابلة للتكوين (افتراضي: `explainability`). +يستخدم علم الوجود PROV-O للعلاقات المتعلقة بالأصل. +إعادة تمثيل RDF-star للمراجع إلى الحواف. +يتم تخزين محتوى الإجابة في خدمة "المكتبار" (وليس مضمنًا - كبير جدًا). + +### البث في الوقت الفعلي + +يتم بث أحداث إمكانية التفسير إلى العميل أثناء تنفيذ الاستعلام: + +1. تم إنشاء جلسة → تم إرسال حدث. +2. تم استرداد الحواف → تم إرسال حدث. +3. تم تحديد الحواف مع التبرير → تم إرسال حدث. +4. تم توليف الإجابة → تم إرسال حدث. + +يتلقى العميل `explain_id` و `explain_collection` لاسترداد التفاصيل الكاملة. + +## هيكل URI + +تستخدم جميع عناوين URI مساحة الاسم `urn:trustgraph:` مع معرفات UUID: + +| الكيان | نمط URI | +|--------|-------------| +| الجلسة | `urn:trustgraph:session:{uuid}` | +| الاسترداد | `urn:trustgraph:prov:retrieval:{uuid}` | +| التحديد | `urn:trustgraph:prov:selection:{uuid}` | +| الإجابة | `urn:trustgraph:prov:answer:{uuid}` | +| تحديد الحواف | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## نموذج RDF (PROV-O) + +### نشاط الجلسة + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG query session" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### الكيان الخاص بالاسترجاع + +```turtle + a prov:Entity ; + rdfs:label "Retrieved edges" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### الكيان المحدد + +```turtle + a prov:Entity ; + rdfs:label "Selected edges" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### إجابة الكيان + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG answer" ; + prov:wasDerivedFrom ; + tg:document . +``` + +يشير الرمز `tg:document` إلى الإجابة المخزنة في خدمة أمين المكتبة. + +## ثوابت مساحة الاسم + +معرفة في `trustgraph-base/trustgraph/provenance/namespaces.py`: + +| الثابت | عنوان URI | +|----------|-----| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## مخطط GraphRagResponse + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### أنواع الرسائل + +| نوع الرسالة | الغرض | +|--------------|---------| +| `chunk` | نص الاستجابة (متدفق أو نهائي) | +| `explain` | حدث قابل للتفسير مع مرجع IRI | + +### دورة حياة الجلسة + +1. رسائل `explain` متعددة (جلسة، استرجاع، اختيار، إجابة) +2. رسائل `chunk` متعددة (استجابة متدفقة) +3. رسالة `chunk` نهائية مع `end_of_session=True` + +## تنسيق اختيار الحافة + +يقوم نموذج اللغة الكبيرة بإرجاع JSONL مع الحواف المحددة: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +الرمز `id` هو تجزئة لـ `(labeled_s, labeled_p, labeled_o)` تم حسابه بواسطة `edge_id()`. + +## الحفاظ على عنوان URI + +### المشكلة + +يعرض GraphRAG تسميات قابلة للقراءة للبشر لنظام LLM، ولكن الشفافية تتطلب عناوين URI أصلية لتتبع الأصل. + +### الحل + +`get_labelgraph()` يُرجع كلاً من: +`labeled_edges`: قائمة بـ `(label_s, label_p, label_o)` لنظام LLM +`uri_map`: قاموس يربط بين `edge_id(labels)` و `(uri_s, uri_p, uri_o)` + +عند تخزين بيانات الشفافية، تُستخدم عناوين URI من `uri_map`. + +## تتبع الأصل + +### من الحافة إلى المصدر + +يمكن تتبع الحواف المحددة إلى المستندات المصدر: + +1. الاستعلام عن الرسم البياني الفرعي الذي يحتوي عليها: `?subgraph tg:contains <>` +2. تتبع سلسلة `prov:wasDerivedFrom` إلى المستند الجذر +3. كل خطوة في السلسلة: جزء → صفحة → مستند + +### دعم ثلاثيات Cassandra المقتبسة + +يدعم خدمة استعلام Cassandra مطابقة ثلاثيات مقتبسة: + +```python +# In get_term_value(): +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +هذا يتيح إجراء استعلامات مثل: +``` +?subgraph tg:contains <> +``` + +## استخدام واجهة سطر الأوامر + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +### تنسيق الإخراج + +``` +[session] urn:trustgraph:session:abc123 + +[retrieval] urn:trustgraph:prov:retrieval:abc123 + +[selection] urn:trustgraph:prov:selection:abc123 + Selected 12 edge(s) + Edge: (Guantanamo, definition, A detention facility...) + Reason: Directly connects Guantanamo to the War on Terror + Source: Chunk 1 → Page 2 → Beyond the Vigilant State + +[answer] urn:trustgraph:prov:answer:abc123 + +Based on the provided knowledge statements... +``` + +### الميزات + +أحداث تفسيرية في الوقت الفعلي أثناء الاستعلام. +حل التسميات للمكونات الطرفية عبر `rdfs:label`. +تتبع سلسلة المصدر عبر `prov:wasDerivedFrom`. +تخزين مؤقت للتسميات لتجنب الاستعلامات المتكررة. + +## الملفات المنفذة + +| الملف | الغرض | +|------|---------| +| `trustgraph-base/trustgraph/provenance/uris.py` | مولدات URI | +| `trustgraph-base/trustgraph/provenance/namespaces.py` | ثوابت مساحة الاسم RDF | +| `trustgraph-base/trustgraph/provenance/triples.py` | أدوات بناء الثلاثيات | +| `trustgraph-base/trustgraph/schema/services/retrieval.py` | مخطط GraphRagResponse | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` | GraphRAG الأساسي مع الحفاظ على URI | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` | خدمة مع تكامل أمين المكتبة | +| `trustgraph-flow/trustgraph/query/triples/cassandra/service.py` | دعم الاستعلام عن الثلاثيات المقتبسة | +| `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` | واجهة سطر أوامر مع عرض التفسير | + +## المراجع + +PROV-O (علم الوجود W3C): https://www.w3.org/TR/prov-o/ +RDF-star: https://w3c.github.io/rdf-star/ +علم الوجود في وقت الاستخراج: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.es.md b/docs/tech-specs/query-time-explainability.es.md new file mode 100644 index 00000000..2fce646d --- /dev/null +++ b/docs/tech-specs/query-time-explainability.es.md @@ -0,0 +1,208 @@ +--- +layout: default +title: "Explicabilidad en Tiempo de Consulta" +parent: "Spanish (Beta)" +--- + +# Explicabilidad en Tiempo de Consulta + +> **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 + +Implementado + +## Descripción General + +Esta especificación describe cómo GraphRAG registra y comunica datos de explicabilidad durante la ejecución de consultas. El objetivo es una trazabilidad completa: desde la respuesta final, a través de los bordes seleccionados, hasta los documentos de origen. + +La explicabilidad en tiempo de consulta captura lo que hizo la tubería de GraphRAG durante el razonamiento. Se conecta con la trazabilidad de la extracción de tiempo, que registra de dónde provienen los hechos del grafo de conocimiento. + +## Terminología + +| Término | Definición | +|---|---| +| **Explicabilidad** | El registro de cómo se derivó un resultado | +| **Sesión** | Una ejecución de consulta de GraphRAG | +| **Selección de borde** | Selección de bordes relevantes basada en LLM, con razonamiento | +| **Cadena de trazabilidad** | Ruta desde el borde → fragmento → página → documento | + +## Arquitectura + +### Flujo de Explicabilidad + +``` +Consulta de GraphRAG + │ + ├─► Actividad de la Sesión + │ └─► Texto de la consulta, marca de tiempo + │ + ├─► Entidad de Recuperación + │ └─► Todos los bordes recuperados del subgrafo + │ + ├─► Entidad de Selección + │ └─► Bordes seleccionados con razonamiento del LLM + │ └─► Cada borde enlaza con la trazabilidad de extracción + │ + └─► Entidad de Respuesta + └─► Referencia a la respuesta sintetizada (en el bibliotecario) +``` + +### Tubería de GraphRAG de Dos Etapas + +1. **Selección de borde:** El LLM selecciona bordes relevantes del subgrafo, proporcionando una justificación para cada uno +2. **Síntesis:** El LLM genera la respuesta a partir de los bordes seleccionados + +Esta separación permite la explicabilidad: sabemos exactamente qué bordes contribuyeron. + +### Almacenamiento + +- Los triples de explicabilidad se almacenan en una colección configurable (por defecto: `explainability`) +- Utiliza la ontología PROV-O para las relaciones de trazabilidad +- Reificación RDF para referencias a bordes +- El contenido de la respuesta se almacena en el servicio del bibliotecario (no en línea, demasiado grande) + +### Streaming en Tiempo Real + +Los eventos de explicabilidad se transmiten al cliente a medida que se ejecuta la consulta: + +1. Se crea la sesión → se emite un evento +2. Se recuperan los bordes → se emite un evento +3. Se seleccionan los bordes con razonamiento → se emite un evento +4. Se sintetiza la respuesta → se emite un evento + +El cliente recibe `explain_id` y `explain_collection` para obtener los detalles completos. + +## Estructura de URI + +Todos los URI utilizan el espacio de nombres `urn:trustgraph:` con UUIDs: + +| Entidad | Patrón de URI | +|---|---| +| Sesión | `urn:trustgraph:session:{uuid}` | +| Recuperación | `urn:trustgraph:prov:retrieval:{uuid}` | +| Selección | `urn:trustgraph:prov:selection:{uuid}` | +| Respuesta | `urn:trustgraph:prov:answer:{uuid}` | +| Selección de borde | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## Modelo RDF (PROV-O) + +### Actividad de la Sesión + +```turtle + a prov:Activity ; + rdfs:label "Sesión de consulta GraphRAG" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "¿Cuál fue la Guerra contra el Terrorismo?" . +``` + +### Entidad de Recuperación + +```turtle + a prov:Entity ; + rdfs:label "Bordes recuperados" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### Entidad de Selección + +```turtle + a prov:Entity ; + rdfs:label "Bordes seleccionados" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "Este borde establece la relación clave..." . +``` + +### Entidad de Respuesta + +```turtle + a prov:Entity ; + rdfs:label "Respuesta de GraphRAG" ; + prov:wasDerivedFrom ; + tg:document . +``` + +La `tg:document` hace referencia a la respuesta almacenada en el servicio del bibliotecario. + +## Constantes de Espacio de Nombres + +Definidas en `trustgraph-base/trustgraph/provenance/namespaces.py`: + +| Constante | URI | +|---|---| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## Esquema GraphRagResponse + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### Tipos de Mensaje + +| message_type | Propósito | +|---|---| +| `chunk` | Texto de la respuesta (streaming o final) | +| `explain` | Evento de explicabilidad con referencia IRI | + +### Ciclo de Vida de la Sesión + +1. Múltiples mensajes `explain` (sesión, recuperación, selección, respuesta) +2. Múltiples mensajes `chunk` (respuesta en streaming) +3. Final `chunk` con `end_of_session=True` + +## Formato de Selección de Bordes + +El LLM devuelve un JSONL con los bordes seleccionados: + +```jsonl +{"id": "edge-hash-1", "reasoning": "Este borde muestra la relación clave..."} +{"id": "edge-hash-2", "reasoning": "Proporciona evidencia de apoyo..."} +``` + +El `id` es un hash de `(labeled_s, labeled_p, labeled_o)` calculado por `edge_id()`. + +## Preservación de URI + +### El Problema + +GraphRAG muestra etiquetas legibles para el LLM, pero la explicabilidad necesita los URI originales para el rastreo de la trazabilidad. + +### Solución + +`get_labelgraph()` devuelve: +- `labeled_edges`: Lista de `(label_s, label_p, label_o)` para el LLM +- `uri_map`: Diccionario que mapea `edge_id(labels)` → `(uri_s, uri_p, uri_o)` + +Cuando se guarda la información de explicabilidad, se utilizan los URI de `uri_map`. + +## Rastreando la Trazabilidad + +### Desde el borde hasta la fuente + +Se pueden rastrear los bordes seleccionados de vuelta a la fuente: + +### Referencias + +- PROV-O (W3C Provenance Ontology): https://www.w3.org/TR/prov-o/ +- RDF-star: https://w3c.github.io/rdf-star/ +- Trazabilidad de tiempo de extracción: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.he.md b/docs/tech-specs/query-time-explainability.he.md new file mode 100644 index 00000000..5fd3152d --- /dev/null +++ b/docs/tech-specs/query-time-explainability.he.md @@ -0,0 +1,187 @@ +--- +layout: default +title: "Query Time Explainability.He" +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. + +## הסבר על יכולת הסבר בזמן שאילתה + +## סטטוס + +יישום + +## סקירה כללית + +מפרט זה מתאר כיצד GraphRAG מתעד ומעביר נתוני הסבר במהלך ביצוע שאילתה. המטרה היא מעקב מלא: מהתשובה הסופית בחזרה דרך הקצוות שנבחרו לתיקי המסמכים המקוריים. + +הסבר בזמן שאילתה לוכד מה שהצינור של GraphRAG עשה במהלך ההיגיון. הוא מתחבר להקשר של ביצוע שאילתה, אשר מתעד היכן העובדות בגרף הידע מקורות. + +## מונחים + +| מונח | הגדרה | +|---|---| +| **הסבר** | תיעוד של איך התוצאה הושגה | +| **סשן** | ביצוע שאילתה בודד של GraphRAG | +| **בחירת קצה** | בחירה מבוססת LLM של קצוות רלוונטיים עם היגיון | +| **שרשרת הקשר** | נתיב מ-קצה → חתיכה → עמוד → מסמך | + +## ארכיטקטורה + +### זרימת הסבר + +``` +שאילת GraphRAG + │ + ├─► פעילות סשן + │ └─► טקסט שאילתה, חותם זמן + │ + ├─► ישות אחזור + │ └─► כל הקצוות שנשלפו מהסובגרף + │ + ├─► ישות בחירה + │ └─► קצוות שנבחרו עם היגיון LLM + │ └─► כל קצה מקושר להקשר של הסרת מידע + │ + └─► ישות תשובה + └─► הפניה לתשובה שנוצרה (בספריית הניהול) +``` + +### צינור GraphRAG בשני שלבים + +1. **בחירת קצה:** LLM בוחר קצוות רלוונטיים מהסובגרף, ומספק הסבר לכל אחד +2. **סינתזה:** LLM מייצר תשובה מקצוות שנבחרו בלבד + +ההפרדה מאפשרת הסבר - אנחנו יודעים בדיוק אילו קצוות תרמו. + +### אחסון + +- טריפלי הסבר מאוחסנים בספרייה שניתן להגדיר (ברירת מחדל: `explainability`) +- משתמש ב-אונטולוגיה של PROV-O ליחסי הקשר +- ייצוג RDF-star עבור הפניות לקצוות +- תוכן התשובה מאוחסן בשירות הספרייה (לא באופן ישיר - גדול מדי) + +### סטרימינג בזמן אמת + +אירועי הסבר זורמים ללקוח בזמן ביצוע השאילתה: + +1. סשן נוצר → הודעה נשלחת +2. קצוות נשלפים → הודעה נשלחת +3. קצוות נבחרו עם הסבר → הודעה נשלחת +4. תשובה נוצרה → הודעה נשלחת + +הלקוח מקבל `explain_id` ו-`explain_collection` כדי לשלוף פרטים מלאים. + +## מבנה URI + +כל ה-URIs משתמשים בשם מרחב שמות `urn:trustgraph:`, עם UUIDs: + +| ישות | תבנית URI | +|---|---| +| סשן | `urn:trustgraph:session:{uuid}` | +| אחזור | `urn:trustgraph:prov:retrieval:{uuid}` | +| בחירה | `urn:trustgraph:prov:selection:{uuid}` | +| תשובה | `urn:trustgraph:prov:answer:{uuid}` | +| בחירת קצה | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## מודל RDF (PROV-O) + +### פעילות סשן + +```turtle + a prov:Activity ; + rdfs:label "שאילת GraphRAG" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "מה היה מלחמת הטרור?" . +``` + +### ישות אחזור + +```turtle + a prov:Entity ; + rdfs:label "קצוות שאובים" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### ישות בחירה + +```turtle + a prov:Entity ; + rdfs:label "קצוות שנבחרו" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "קצה זה מייצג את הקשר המרכזי..." . +``` + +### ישות תשובה + +```turtle + a prov:Entity ; + rdfs:label "תשובת GraphRAG" ; + prov:wasDerivedFrom ; + tg:document . +``` + +הפניה `tg:document` מתייחסת לתשובה המאוחסנת בשירות הספרייה. + +## קבועי מרחב שמות + +מוגדרים ב-`trustgraph-base/trustgraph/provenance/namespaces.py`: + +| קבוע | URI | +|---|---| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## תרשים GraphRagResponse + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### סוגי הודעות + +| message_type | מטרת | +|---|---| +| `chunk` | טקסט תגובה (זרם או סופי) | +| `explain` | אירוע הסבר עם הפניה IRI | + +### מחזור חיים של סשן + +1. מספר הודעות `explain` (סשן, אחזור, בחירה, תשובה) +2. מספר הודעות `chunk` (טקסט זרם) +3. הודעת `chunk` סופית עם `end_of_session=True` + +## פורמט בחירת קצה + +LLM מחזיר JSONL עם הקצוות שנבחרו: + +```jsonl +{"id": "edge-hash-1", "reasoning": "קצה זה מראה את הקשר המרכזי..."} +{"id": "edge-hash-2", "reasoning": "מספק ראיות תומכות..."} +``` + +ה-`id` הוא פאש של `(labeled_s, labeled_p, labeled_o)` +ה-`reasoning` הוא הסבר של ה-LLM. + +## יישומים + +- `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.hi.md b/docs/tech-specs/query-time-explainability.hi.md new file mode 100644 index 00000000..a992443b --- /dev/null +++ b/docs/tech-specs/query-time-explainability.hi.md @@ -0,0 +1,271 @@ +--- +layout: default +title: "क्वेरी-टाइम एक्सप्लेनेबिलिटी (Query-Time Explainability)" +parent: "Hindi (Beta)" +--- + +# क्वेरी-टाइम एक्सप्लेनेबिलिटी (Query-Time 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. + +## स्थिति (Status) + +कार्यान्वित (Implemented) + +## अवलोकन (Overview) + +यह विनिर्देश बताता है कि GraphRAG क्वेरी निष्पादन के दौरान एक्सप्लेनेबिलिटी डेटा को कैसे रिकॉर्ड और संचारित करता है। इसका लक्ष्य पूर्ण पता लगाने की क्षमता है: अंतिम उत्तर से लेकर चयनित किनारों तक और फिर स्रोत दस्तावेजों तक। + +क्वेरी-टाइम एक्सप्लेनेबिलिटी यह कैप्चर करती है कि GraphRAG पाइपलाइन तर्क के दौरान क्या करती है। यह निष्कर्षण-समय के प्रमाण से जुड़ा है, जो रिकॉर्ड करता है कि ज्ञान ग्राफ तथ्यों की उत्पत्ति कहाँ से हुई। + +## शब्दावली (Terminology) + +| शब्द | परिभाषा | +|------|------------| +| **एक्सप्लेनेबिलिटी (Explainability)** | यह रिकॉर्ड है कि एक परिणाम कैसे प्राप्त किया गया | +| **सेशन (Session)** | एक एकल GraphRAG क्वेरी निष्पादन | +| **एज सिलेक्शन (Edge Selection)** | तर्क के साथ प्रासंगिक किनारों का LLM-संचालित चयन | +| **प्रूवेनेंस चेन (Provenance Chain)** | किनारे → चंक → पृष्ठ → दस्तावेज़ से पथ | + +## आर्किटेक्चर (Architecture) + +### एक्सप्लेनेबिलिटी फ्लो (Explainability Flow) + +``` +GraphRAG Query + │ + ├─► Session Activity + │ └─► Query text, timestamp + │ + ├─► Retrieval Entity + │ └─► All edges retrieved from subgraph + │ + ├─► Selection Entity + │ └─► Selected edges with LLM reasoning + │ └─► Each edge links to extraction provenance + │ + └─► Answer Entity + └─► Reference to synthesized response (in librarian) +``` + +### दो-चरणीय ग्राफआरएजी पाइपलाइन + +1. **एज चयन**: एलएलएम सबग्राफ से प्रासंगिक किनारों का चयन करता है, प्रत्येक के लिए तर्क प्रदान करता है। +2. **संश्लेषण**: एलएलएम केवल चयनित किनारों से उत्तर उत्पन्न करता है। + +यह अलगाव व्याख्यात्मकता को सक्षम बनाता है - हमें ठीक से पता है कि किन किनारों ने योगदान दिया। + +### भंडारण + +व्याख्यात्मकता ट्रिपल कॉन्फ़िगर करने योग्य संग्रह में संग्रहीत हैं (डिफ़ॉल्ट: `explainability`)। +यह स्रोत संबंधों के लिए प्रोवी-ओ ऑन्टोलॉजी का उपयोग करता है। +किनारे संदर्भों के लिए आरडीएफ-स्टार रीफिकेशन। +उत्तर सामग्री लाइब्रेरियन सेवा में संग्रहीत है (इनलाइन नहीं - बहुत बड़ा)। + +### वास्तविक समय स्ट्रीमिंग + +व्याख्यात्मकता घटनाएँ क्लाइंट को क्वेरी निष्पादित होने के दौरान स्ट्रीम की जाती हैं: + +1. सत्र बनाया गया → घटना उत्सर्जित। +2. किनारे पुनर्प्राप्त किए गए → घटना उत्सर्जित। +3. तर्क के साथ किनारे चुने गए → घटना उत्सर्जित। +4. उत्तर संश्लेषित → घटना उत्सर्जित। + +क्लाइंट को `explain_id` और `explain_collection` प्राप्त होते हैं ताकि पूर्ण विवरण प्राप्त किए जा सकें। + +## यूआरआई संरचना + +सभी यूआरआई `urn:trustgraph:` नेमस्पेस का उपयोग करते हैं जिसमें यूयूआईडी शामिल हैं: + +| इकाई | यूआरआई पैटर्न | +|--------|-------------| +| सत्र | `urn:trustgraph:session:{uuid}` | +| पुनर्प्राप्ति | `urn:trustgraph:prov:retrieval:{uuid}` | +| चयन | `urn:trustgraph:prov:selection:{uuid}` | +| उत्तर | `urn:trustgraph:prov:answer:{uuid}` | +| किनारे का चयन | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## आरडीएफ मॉडल (प्रोवी-ओ) + +### सत्र गतिविधि + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG query session" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### पुनर्प्राप्ति इकाई + +```turtle + a prov:Entity ; + rdfs:label "Retrieved edges" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### चयन इकाई + +```turtle + a prov:Entity ; + rdfs:label "Selected edges" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### उत्तर इकाई + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG answer" ; + prov:wasDerivedFrom ; + tg:document . +``` + +`tg:document` संदर्भ लाइब्रेरियन सेवा में संग्रहीत उत्तर को दर्शाता है। + +## नेमस्पेस स्थिरांक + +`trustgraph-base/trustgraph/provenance/namespaces.py` में परिभाषित: + +| स्थिरांक | यूआरआई | +|----------|-----| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## GraphRagResponse स्कीमा + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### संदेश प्रकार + +| संदेश_प्रकार | उद्देश्य | +|--------------|---------| +| `chunk` | प्रतिक्रिया पाठ (स्ट्रीमिंग या अंतिम) | +| `explain` | आईआरआई संदर्भ के साथ व्याख्यात्मक घटना | + +### सत्र जीवनचक्र + +1. कई `explain` संदेश (सत्र, पुनर्प्राप्ति, चयन, उत्तर) +2. कई `chunk` संदेश (स्ट्रीमिंग प्रतिक्रिया) +3. `end_of_session=True` के साथ अंतिम `chunk` + +## एज चयन प्रारूप + +एलएलएम चयनित किनारों के साथ JSONL लौटाता है: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +`id`, `(labeled_s, labeled_p, labeled_o)` का एक हैश है, जिसकी गणना `edge_id()` द्वारा की जाती है। + +## यूआरआई का संरक्षण + +### समस्या + +GraphRAG, एलएलएम को समझने योग्य लेबल प्रदर्शित करता है, लेकिन स्पष्टीकरण के लिए मूल यूआरआई की आवश्यकता होती है ताकि स्रोत का पता लगाया जा सके। + +### समाधान + +`get_labelgraph()` दोनों लौटाता है: +`labeled_edges`: एलएलएम के लिए `(label_s, label_p, label_o)` की सूची +`uri_map`: एक डिक्शनरी जो `edge_id(labels)` को `(uri_s, uri_p, uri_o)` से जोड़ती है। + +जब व्याख्यात्मक डेटा संग्रहीत किया जाता है, तो `uri_map` से यूआरआई का उपयोग किया जाता है। + +## उत्पत्ति अनुरेखण + +### किनारे से स्रोत तक + +चयनित किनारों को मूल दस्तावेजों तक वापस ट्रेस किया जा सकता है: + +1. समाहित उपग्राफ के लिए क्वेरी करें: `?subgraph tg:contains <>` +2. मूल दस्तावेज़ तक `prov:wasDerivedFrom` श्रृंखला का पालन करें +3. श्रृंखला में प्रत्येक चरण: खंड → पृष्ठ → दस्तावेज़ + +### कैसेंड्रा उद्धृत त्रिक समर्थन + +कैसेंड्रा क्वेरी सेवा उद्धृत त्रिकों के मिलान का समर्थन करती है: + +```python +# In get_term_value(): +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +यह इस तरह के प्रश्नों को सक्षम करता है: +``` +?subgraph tg:contains <> +``` + +## कमांड लाइन इंटरफेस (CLI) का उपयोग + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +### आउटपुट प्रारूप + +``` +[session] urn:trustgraph:session:abc123 + +[retrieval] urn:trustgraph:prov:retrieval:abc123 + +[selection] urn:trustgraph:prov:selection:abc123 + Selected 12 edge(s) + Edge: (Guantanamo, definition, A detention facility...) + Reason: Directly connects Guantanamo to the War on Terror + Source: Chunk 1 → Page 2 → Beyond the Vigilant State + +[answer] urn:trustgraph:prov:answer:abc123 + +Based on the provided knowledge statements... +``` + +### विशेषताएं + +क्वेरी के दौरान वास्तविक समय में व्याख्यात्मक घटनाएं। +`rdfs:label` के माध्यम से एज घटकों के लिए लेबल समाधान। +`prov:wasDerivedFrom` के माध्यम से स्रोत श्रृंखला का पता लगाना। +बार-बार क्वेरी से बचने के लिए लेबल कैशिंग। + +## कार्यान्वित फाइलें + +| फ़ाइल | उद्देश्य | +|------|---------| +| `trustgraph-base/trustgraph/provenance/uris.py` | यूआरआई जनरेटर | +| `trustgraph-base/trustgraph/provenance/namespaces.py` | आरडीएफ नेमस्पेस स्थिरांक | +| `trustgraph-base/trustgraph/provenance/triples.py` | ट्रिपल बिल्डर | +| `trustgraph-base/trustgraph/schema/services/retrieval.py` | GraphRagResponse स्कीमा | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` | यूआरआई संरक्षण के साथ मुख्य GraphRAG | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` | लाइब्रेरियन एकीकरण के साथ सेवा | +| `trustgraph-flow/trustgraph/query/triples/cassandra/service.py` | उद्धृत ट्रिपल क्वेरी समर्थन | +| `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` | व्याख्यात्मक प्रदर्शन के साथ सीएलआई | + +## संदर्भ + +PROV-O (डब्ल्यू3सी प्रोवेनेंस ऑन्टोलॉजी): https://www.w3.org/TR/prov-o/ +RDF-star: https://w3c.github.io/rdf-star/ +निष्कर्षण-समय प्रोवेनेंस: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.md b/docs/tech-specs/query-time-explainability.md index 052b9619..02598563 100644 --- a/docs/tech-specs/query-time-explainability.md +++ b/docs/tech-specs/query-time-explainability.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Query-Time Explainability" +parent: "Tech Specs" +--- + # Query-Time Explainability ## Status diff --git a/docs/tech-specs/query-time-explainability.pt.md b/docs/tech-specs/query-time-explainability.pt.md new file mode 100644 index 00000000..42ab0021 --- /dev/null +++ b/docs/tech-specs/query-time-explainability.pt.md @@ -0,0 +1,271 @@ +--- +layout: default +title: "Explicabilidade em Tempo de Consulta" +parent: "Portuguese (Beta)" +--- + +# Explicabilidade em Tempo de Consulta + +> **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 + +Implementado + +## Visão Geral + +Esta especificação descreve como o GraphRAG registra e comunica dados de explicabilidade durante a execução da consulta. O objetivo é a rastreabilidade completa: desde a resposta final, passando pelas arestas selecionadas, até aos documentos de origem. + +A explicabilidade em tempo de consulta captura o que o pipeline do GraphRAG fez durante o raciocínio. Isso se conecta à rastreabilidade em tempo de extração, que registra a origem dos fatos do grafo de conhecimento. + +## Terminologia + +| Termo | Definição | +|------|------------| +| **Explicabilidade** | O registro de como um resultado foi derivado | +| **Sessão** | Uma única execução de consulta do GraphRAG | +| **Seleção de Arestas** | Seleção de arestas relevantes impulsionada por LLM, com raciocínio | +| **Cadeia de Rastreabilidade** | Caminho de aresta → trecho → página → documento | + +## Arquitetura + +### Fluxo de Explicabilidade + +``` +GraphRAG Query + │ + ├─► Session Activity + │ └─► Query text, timestamp + │ + ├─► Retrieval Entity + │ └─► All edges retrieved from subgraph + │ + ├─► Selection Entity + │ └─► Selected edges with LLM reasoning + │ └─► Each edge links to extraction provenance + │ + └─► Answer Entity + └─► Reference to synthesized response (in librarian) +``` + +### Pipeline de GraphRAG em Duas Etapas + +1. **Seleção de Arestas**: O LLM seleciona as arestas relevantes do subgrafo, fornecendo a justificativa para cada uma. +2. **Síntese**: O LLM gera a resposta a partir das arestas selecionadas. + +Essa separação permite a explicabilidade - sabemos exatamente quais arestas contribuíram. + +### Armazenamento + +Triplas de explicabilidade armazenadas em uma coleção configurável (padrão: `explainability`). +Utiliza a ontologia PROV-O para relações de procedência. +Reificação RDF-star para referências de arestas. +O conteúdo da resposta é armazenado no serviço de bibliotecário (não inline - muito grande). + +### Streaming em Tempo Real + +Os eventos de explicabilidade são transmitidos ao cliente enquanto a consulta é executada: + +1. Sessão criada → evento emitido. +2. Arestas recuperadas → evento emitido. +3. Arestas selecionadas com justificativa → evento emitido. +4. Resposta sintetizada → evento emitido. + +O cliente recebe `explain_id` e `explain_collection` para buscar detalhes completos. + +## Estrutura de URI + +Todos os URIs usam o namespace `urn:trustgraph:` com UUIDs: + +| Entidade | Padrão de URI | +|--------|-------------| +| Sessão | `urn:trustgraph:session:{uuid}` | +| Recuperação | `urn:trustgraph:prov:retrieval:{uuid}` | +| Seleção | `urn:trustgraph:prov:selection:{uuid}` | +| Resposta | `urn:trustgraph:prov:answer:{uuid}` | +| Seleção de Aresta | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## Modelo RDF (PROV-O) + +### Atividade da Sessão + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG query session" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### Entidade de Recuperação + +```turtle + a prov:Entity ; + rdfs:label "Retrieved edges" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### Entidade de Seleção + +```turtle + a prov:Entity ; + rdfs:label "Selected edges" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### Entidade de Resposta + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG answer" ; + prov:wasDerivedFrom ; + tg:document . +``` + +A `tg:document` referencia a resposta armazenada no serviço de bibliotecário. + +## Constantes do Namespace + +Definido em `trustgraph-base/trustgraph/provenance/namespaces.py`: + +| Constante | URI | +|----------|-----| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## Esquema GraphRagResponse + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### Tipos de Mensagem + +| message_type | Propósito | +|--------------|---------| +| `chunk` | Texto de resposta (em fluxo ou final) | +| `explain` | Evento de explicabilidade com referência IRI | + +### Ciclo de Vida da Sessão + +1. Múltiplas mensagens `explain` (sessão, recuperação, seleção, resposta) +2. Múltiplas mensagens `chunk` (resposta em fluxo) +3. Mensagem `chunk` final com `end_of_session=True` + +## Formato de Seleção de Arestas + +O LLM retorna JSONL com as arestas selecionadas: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +O `id` é um hash de `(labeled_s, labeled_p, labeled_o)` calculado por `edge_id()`. + +## Preservação de URIs + +### O Problema + +O GraphRAG exibe rótulos legíveis para humanos para o LLM, mas a explicabilidade precisa de URIs originais para rastreamento de origem. + +### Solução + +`get_labelgraph()` retorna ambos: +`labeled_edges`: Lista de `(label_s, label_p, label_o)` para o LLM +`uri_map`: Dicionário mapeando `edge_id(labels)` → `(uri_s, uri_p, uri_o)` + +Ao armazenar dados de explicabilidade, os URIs de `uri_map` são usados. + +## Rastreamento de Origem + +### Do Borda à Fonte + +As arestas selecionadas podem ser rastreadas de volta aos documentos de origem: + +1. Consulta para o subgrafo contendo: `?subgraph tg:contains <>` +2. Siga a cadeia `prov:wasDerivedFrom` até o documento raiz +3. Cada etapa na cadeia: chunk → página → documento + +### Suporte de Triplas Citadas do Cassandra + +O serviço de consulta do Cassandra suporta a correspondência de triplas citadas: + +```python +# In get_term_value(): +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +Isso permite consultas como: +``` +?subgraph tg:contains <> +``` + +## Uso da Interface de Linha de Comando (CLI) + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +### Formato de Saída + +``` +[session] urn:trustgraph:session:abc123 + +[retrieval] urn:trustgraph:prov:retrieval:abc123 + +[selection] urn:trustgraph:prov:selection:abc123 + Selected 12 edge(s) + Edge: (Guantanamo, definition, A detention facility...) + Reason: Directly connects Guantanamo to the War on Terror + Source: Chunk 1 → Page 2 → Beyond the Vigilant State + +[answer] urn:trustgraph:prov:answer:abc123 + +Based on the provided knowledge statements... +``` + +### Recursos + +Eventos de explicabilidade em tempo real durante a consulta. +Resolução de rótulos para componentes de borda via `rdfs:label`. +Rastreamento da cadeia de origem via `prov:wasDerivedFrom`. +Cache de rótulos para evitar consultas repetidas. + +## Arquivos Implementados + +| Arquivo | Propósito | +|------|---------| +| `trustgraph-base/trustgraph/provenance/uris.py` | Geradores de URI | +| `trustgraph-base/trustgraph/provenance/namespaces.py` | Constantes de namespace RDF | +| `trustgraph-base/trustgraph/provenance/triples.py` | Construtores de triplas | +| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Esquema GraphRagResponse | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` | Núcleo GraphRAG com preservação de URI | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` | Serviço com integração de bibliotecário | +| `trustgraph-flow/trustgraph/query/triples/cassandra/service.py` | Suporte para consultas de triplas entre aspas | +| `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` | CLI com exibição de explicabilidade | + +## Referências + +PROV-O (Ontologia de Proveniência W3C): https://www.w3.org/TR/prov-o/ +RDF-star: https://w3c.github.io/rdf-star/ +Proveniência no momento da extração: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.ru.md b/docs/tech-specs/query-time-explainability.ru.md new file mode 100644 index 00000000..3be1bb7d --- /dev/null +++ b/docs/tech-specs/query-time-explainability.ru.md @@ -0,0 +1,271 @@ +--- +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. + +## Статус + +Реализовано + +## Обзор + +Эта спецификация описывает, как GraphRAG записывает и передает данные об объяснимости во время выполнения запроса. Цель - полная отслеживаемость: от окончательного ответа до выбранных ребер и исходных документов. + +Объяснимость во время выполнения запроса фиксирует действия, которые выполняет конвейер GraphRAG во время рассуждений. Она связана с информацией о происхождении, которая записывается во время извлечения и фиксирует, откуда взялись факты графа знаний. + +## Терминология + +| Термин | Определение | +|------|------------| +| **Объяснимость** | Запись о том, как был получен результат | +| **Сессия** | Одиночное выполнение запроса GraphRAG | +| **Выбор ребра** | Выбор релевантных ребер с использованием LLM и обоснованием | +| **Цепь происхождения** | Путь от ребра → фрагмента → страницы → документа | + +## Архитектура + +### Поток объяснимости + +``` +GraphRAG Query + │ + ├─► Session Activity + │ └─► Query text, timestamp + │ + ├─► Retrieval Entity + │ └─► All edges retrieved from subgraph + │ + ├─► Selection Entity + │ └─► Selected edges with LLM reasoning + │ └─► Each edge links to extraction provenance + │ + └─► Answer Entity + └─► Reference to synthesized response (in librarian) +``` + +### Двухэтапная конвейерная обработка GraphRAG + +1. **Выбор ребер**: LLM выбирает релевантные ребра из подграфа, предоставляя обоснование для каждого. +2. **Синтез**: LLM генерирует ответ, используя только выбранные ребра. + +Такое разделение обеспечивает объяснимость - мы точно знаем, какие ребра внесли вклад. + +### Хранилище + +Тройки, обеспечивающие объяснимость, хранятся в настраиваемой коллекции (по умолчанию: `explainability`). +Используется онтология PROV-O для отношений происхождения. +RDF-star для ссылок на ребра. +Содержимое ответа хранится в сервисе librarian (не встроено - слишком большой объем). + +### Потоковая передача в реальном времени + +События, обеспечивающие объяснимость, передаются клиенту в процессе выполнения запроса: + +1. Создание сессии → событие отправлено. +2. Получение ребер → событие отправлено. +3. Выбор ребер с обоснованием → событие отправлено. +4. Синтез ответа → событие отправлено. + +Клиент получает `explain_id` и `explain_collection` для получения полной информации. + +## Структура URI + +Все URI используют пространство имен `urn:trustgraph:` с UUID: + +| Сущность | Шаблон URI | +|--------|-------------| +| Сессия | `urn:trustgraph:session:{uuid}` | +| Получение | `urn:trustgraph:prov:retrieval:{uuid}` | +| Выбор | `urn:trustgraph:prov:selection:{uuid}` | +| Ответ | `urn:trustgraph:prov:answer:{uuid}` | +| Выбор ребра | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## Модель RDF (PROV-O) + +### Сессия активности + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG query session" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### Получение сущности + +```turtle + a prov:Entity ; + rdfs:label "Retrieved edges" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### Выбор сущности + +```turtle + a prov:Entity ; + rdfs:label "Selected edges" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### Ответная сущность + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG answer" ; + prov:wasDerivedFrom ; + tg:document . +``` + +`tg:document` ссылается на ответ, хранящийся в сервисе librarian. + +## Константы пространства имен + +Определены в `trustgraph-base/trustgraph/provenance/namespaces.py`: + +| Константа | URI | +|----------|-----| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## Схема GraphRagResponse + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### Типы сообщений + +| message_type | Назначение | +|--------------|---------| +| `chunk` | Текстовый ответ (потоковый или окончательный) | +| `explain` | Событие, связанное с объяснимостью, с ссылкой IRI | + +### Жизненный цикл сессии + +1. Несколько сообщений `explain` (сессия, получение, выбор, ответ) +2. Несколько сообщений `chunk` (потоковый ответ) +3. Окончательное сообщение `chunk` с `end_of_session=True` + +## Формат выбора ребер + +LLM возвращает JSONL с выбранными ребрами: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +`id` является хешем `(labeled_s, labeled_p, labeled_o)`, вычисленным с помощью `edge_id()`. + +## Сохранение URI + +### Проблема + +GraphRAG отображает для LLM удобочитаемые метки, но для отслеживания происхождения необходимы исходные URI. + +### Решение + +`get_labelgraph()` возвращает следующее: +`labeled_edges`: Список `(label_s, label_p, label_o)` для LLM +`uri_map`: Словарь, сопоставляющий `edge_id(labels)` → `(uri_s, uri_p, uri_o)` + +При хранении данных для объяснения используются URI из `uri_map`. + +## Отслеживание происхождения + +### От узла к источнику + +Выбранные узлы можно проследить до исходных документов: + +1. Запрос для получения содержащего подграфа: `?subgraph tg:contains <>` +2. Переход по цепочке `prov:wasDerivedFrom` к корневому документу +3. Каждый шаг в цепочке: фрагмент → страница → документ + +### Поддержка тройных наборов в Cassandra + +Сервис запросов Cassandra поддерживает сопоставление тройных наборов: + +```python +# In get_term_value(): +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +Это позволяет выполнять запросы, такие как: +``` +?subgraph tg:contains <> +``` + +## Использование интерфейса командной строки + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +### Формат вывода + +``` +[session] urn:trustgraph:session:abc123 + +[retrieval] urn:trustgraph:prov:retrieval:abc123 + +[selection] urn:trustgraph:prov:selection:abc123 + Selected 12 edge(s) + Edge: (Guantanamo, definition, A detention facility...) + Reason: Directly connects Guantanamo to the War on Terror + Source: Chunk 1 → Page 2 → Beyond the Vigilant State + +[answer] urn:trustgraph:prov:answer:abc123 + +Based on the provided knowledge statements... +``` + +### Особенности + +События объяснения в реальном времени во время запроса. +Разрешение меток для компонентов ребер с помощью `rdfs:label`. +Отслеживание цепочки источников с помощью `prov:wasDerivedFrom`. +Кэширование меток для предотвращения повторных запросов. + +## Реализованные файлы + +| Файл | Назначение | +|------|---------| +| `trustgraph-base/trustgraph/provenance/uris.py` | Генераторы URI | +| `trustgraph-base/trustgraph/provenance/namespaces.py` | Константы пространства имен RDF | +| `trustgraph-base/trustgraph/provenance/triples.py` | Конструкторы троек | +| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Схема GraphRagResponse | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` | Основной GraphRAG с сохранением URI | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` | Сервис с интеграцией с библиотекарем | +| `trustgraph-flow/trustgraph/query/triples/cassandra/service.py` | Поддержка запросов троек в кавычках | +| `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` | CLI с отображением объяснений | + +## Ссылки + +PROV-O (W3C Provenance Ontology): https://www.w3.org/TR/prov-o/ +RDF-star: https://w3c.github.io/rdf-star/ +Происхождение во время извлечения: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.sw.md b/docs/tech-specs/query-time-explainability.sw.md new file mode 100644 index 00000000..190c0a59 --- /dev/null +++ b/docs/tech-specs/query-time-explainability.sw.md @@ -0,0 +1,271 @@ +--- +layout: default +title: "Ufafanuzi wa Wakati wa Uchunguzi" +parent: "Swahili (Beta)" +--- + +# Ufafanuzi wa Wakati wa Uchunguzi + +> **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 + +Imetekelezwa + +## Muhtasari + +Maelekezo haya yanaelezea jinsi GraphRAG inavyorekodi na kuwasilisha data ya ufafanuzi wakati wa utekelezaji wa uchunguzi. Lengo ni ufuatiliaji kamili: kutoka kwa jibu la mwisho, kiasi kupitia miunganisho iliyochaguliwa, hadi kwa nyaraka za asili. + +Ufafanuzi wa wakati wa uchunguzi unaeleza kile ambacho mstari wa GraphRAG ulifanya wakati wa utaratibu. Inahusiana na uhifadhi wa wakati wa uchimbaji ambao unarekodi mahali ambapo ukweli wa grafu ya maarifa ulitoka. + +## Dhana + +| Neno | Ufafanuzi | +|------|------------| +| **Ufafanuzi** | Rekodi ya jinsi matokeo yalivyopatikana | +| **Kipindi** | Utendaji mmoja wa GraphRAG | +| **Uchaguzi wa Miunganisho** | Uchaguzi wa miunganisho inayofaa inayodumishwa na LLM pamoja na utaratibu | +| **Mnyororo wa Uhifadhi** | Njia kutoka kwa miunganisho → kipande → ukurasa → nyaraka | + +## Muundo + +### Mtiririko wa Ufafanuzi + +``` +GraphRAG Query + │ + ├─► Session Activity + │ └─► Query text, timestamp + │ + ├─► Retrieval Entity + │ └─► All edges retrieved from subgraph + │ + ├─► Selection Entity + │ └─► Selected edges with LLM reasoning + │ └─► Each edge links to extraction provenance + │ + └─► Answer Entity + └─► Reference to synthesized response (in librarian) +``` + +### Mfumo wa Hatua Mbili wa GraphRAG + +1. **Uchaguzi wa Njia (Edge)**: LLM huangalia njia muhimu kutoka kwenye sehemu ndogo ya grafu, hutoa maelezo kwa kila moja. +2. **Uunganisho (Synthesis)**: LLM huunda jibu kutoka kwa njia zilizochaguliwa pekee. + +Tofauti hii inaruhusu uelewaji - tunajua hasa ni njia zipi zilizochangia. + +### Uhifadhi + +Matriki ya uelewaji yaliyohifadhiwa katika mkusanyiko unaoweza kusanidiwa (kiwango chake: `explainability`) +Hutumia ontolojia ya PROV-O kwa uhusiano wa asili. +Ufafanuzi wa RDF-star kwa marejeleo ya njia. +Yaliyomo ya jibu yamehifadhiwa katika huduma ya "librarian" (hayapo ndani - ni makubwa). + +### Uhamishaji wa Muda Halisi + +Matukio ya uelewaji huhamishwa kwa mteja wakati swali linapojibiwa: + +1. Kipindi kimeanzishwa → tukio limehamishwa +2. Njia zimepatikana → tukio limehamishwa +3. Njia zimechaguliwa pamoja na maelezo → tukio limehamishwa +4. Jibu limeunganishwa → tukio limehamishwa + +Mteja hupokea `explain_id` na `explain_collection` ili kupata maelezo kamili. + +## Muundo wa URI + +URI zote hutumia nafasi ya `urn:trustgraph:` pamoja na UUIDs: + +| Kitu | Muundo wa URI | +|--------|-------------| +| Kipindi | `urn:trustgraph:session:{uuid}` | +| Kupata | `urn:trustgraph:prov:retrieval:{uuid}` | +| Uchaguzi | `urn:trustgraph:prov:selection:{uuid}` | +| Jibu | `urn:trustgraph:prov:answer:{uuid}` | +| Uchaguzi wa Njia | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## Mfumo wa RDF (PROV-O) + +### Shughuli ya Kipindi + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG query session" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### Kitengo cha Upatikanaji + +```turtle + a prov:Entity ; + rdfs:label "Retrieved edges" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### Kitengo cha Uchaguzi + +```turtle + a prov:Entity ; + rdfs:label "Selected edges" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### Jibu la Kitu + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG answer" ; + prov:wasDerivedFrom ; + tg:document . +``` + +`tg:document` inarejelea jibu lililohifadhiwa katika huduma ya msimamizi. + +## Mara kwa Mara za Nafasi + +Zimefafumiwa katika `trustgraph-base/trustgraph/provenance/namespaces.py`: + +| Mara kwa Mara | URI | +|----------|-----| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## Muundo wa GraphRagResponse + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### Aina za Ujumbe + +| aina_ya_ujumbe | Madhumuni | +|--------------|---------| +| `chunk` | Nakala ya majibu (ya mtiririko au ya mwisho) | +| `explain` | Tukio la kufafanua na rejea ya IRI | + +### Mzunguko wa Kisesheni + +1. Ujumbe mwingi wa `explain` (kisesheni, upataji, uchaguzi, jibu) +2. Ujumbe mwingi wa `chunk` (jibu la mtiririko) +3. `chunk` ya mwisho na `end_of_session=True` + +## Muundo wa Uchaguzi wa Njia + +LLM hurudisha JSONL na njia zilizochaguliwa: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +`id` ni hash ya `(labeled_s, labeled_p, labeled_o)` iliyohesabiwa na `edge_id()`. + +## Uhifadhi wa URI + +### Tatizo + +GraphRAG huonyesha lebo zinazoweza kusomwa na binadamu kwa LLM, lakini uelewaji unahitaji URI za asili kwa ajili ya kufuatilia asili. + +### Suluhisho + +`get_labelgraph()` hurudisha vitu viwili: +`labeled_edges`: Orodha ya `(label_s, label_p, label_o)` kwa ajili ya LLM +`uri_map`: Kamusi inayoeleanisha `edge_id(labels)` → `(uri_s, uri_p, uri_o)` + +Wakati wa kuhifadhi data ya uelewaji, URI kutoka `uri_map` hutumiwa. + +## Kufuatilia Asili + +### Kutoka Kwenye Njia hadi Chanzo + +Njia zilizochaguliwa zinaweza kufuatiliwa hadi kwenye hati za asili: + +1. Tafuta subgraph inayoyajumuisha: `?subgraph tg:contains <>` +2. Fuata mnyororo wa `prov:wasDerivedFrom` hadi kwenye hati ya msingi +3. Kila hatua katika mnyororo: kipande → ukurasa → hati + +### Usaidizi wa Triple Zilizotiwa Nukuu wa Cassandra + +Huduma ya utafutaji ya Cassandra inasaidia kulinganisha triple zilizotiwa nukuu: + +```python +# In get_term_value(): +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +Hii inawezesha maswali kama vile: +``` +?subgraph tg:contains <> +``` + +## Matumizi ya Kifaa Kikuu (CLI) + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +### Muundo wa Matokeo + +``` +[session] urn:trustgraph:session:abc123 + +[retrieval] urn:trustgraph:prov:retrieval:abc123 + +[selection] urn:trustgraph:prov:selection:abc123 + Selected 12 edge(s) + Edge: (Guantanamo, definition, A detention facility...) + Reason: Directly connects Guantanamo to the War on Terror + Source: Chunk 1 → Page 2 → Beyond the Vigilant State + +[answer] urn:trustgraph:prov:answer:abc123 + +Based on the provided knowledge statements... +``` + +### Vipengele + +Matukio ya uwazi wa matendo kwa wakati halisi wakati wa swali. +Utatuzi wa lebo kwa vipengele vya pembe kupitia `rdfs:label` +Ufuatiliaji wa mnyororo wa chanzo kupitia `prov:wasDerivedFrom` +Kumbukumbu ya lebo ili kuepuka maswali yanayorudiwa. + +## Faili Zilizotumiwa + +| Faili | Madhumuni | +|------|---------| +| `trustgraph-base/trustgraph/provenance/uris.py` | Vitu vya kuunda URI | +| `trustgraph-base/trustgraph/provenance/namespaces.py` | Mara kwa mara ya nafasi ya RDF | +| `trustgraph-base/trustgraph/provenance/triples.py` | Vitu vya kuunda triple | +| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Mpango wa GraphRagResponse | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` | GraphRAG ya msingi na uhifadhi wa URI | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` | Huduma na ujumuishaji wa msimamizi | +| `trustgraph-flow/trustgraph/query/triples/cassandra/service.py` | Usaidizi wa swali la triple lililotiwa nukuu | +| `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` | CLI na onyesho la uwazi | + +## Marejeleo + +PROV-O (Ontolojia ya Asili ya W3C): https://www.w3.org/TR/prov-o/ +RDF-star: https://w3c.github.io/rdf-star/ +Asili ya wakati wa uondoaji: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.tr.md b/docs/tech-specs/query-time-explainability.tr.md new file mode 100644 index 00000000..c8d38490 --- /dev/null +++ b/docs/tech-specs/query-time-explainability.tr.md @@ -0,0 +1,271 @@ +--- +layout: default +title: "Sorgu Zamanı Açıklanabilirlik" +parent: "Turkish (Beta)" +--- + +# Sorgu Zamanı Açıklanabilirlik + +> **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 + +Uygulandı + +## Genel Bakış + +Bu özellik, GraphRAG'ın sorgu yürütülmesi sırasında açıklanabilirlik verilerini nasıl kaydettiğini ve ilettiğini açıklamaktadır. Amaç, nihai cevaptan başlayarak, seçilen kenarlara ve kaynak belgelere kadar tam bir izlenebilirlik sağlamaktır. + +Sorgu zamanı açıklanabilirliği, GraphRAG boru hattının akıl yürütme sırasında neler yaptığını yakalar. Bu, bilginin nereden geldiğini kaydeden, çıkarma zamanı köken bilgilerine bağlanır. + +## Terminoloji + +| Terim | Tanım | +|------|------------| +| **Açıklanabilirlik** | Bir sonucun nasıl elde edildiğinin kaydı | +| **Oturum** | Tek bir GraphRAG sorgu yürütmesi | +| **Kenar Seçimi** | Akıl yürütmeyle ilgili kenarların LLM tarafından seçilmesi | +| **Köken Zinciri** | Kenar → parça → sayfa → belge yolu | + +## Mimari + +### Açıklanabilirlik Akışı + +``` +GraphRAG Query + │ + ├─► Session Activity + │ └─► Query text, timestamp + │ + ├─► Retrieval Entity + │ └─► All edges retrieved from subgraph + │ + ├─► Selection Entity + │ └─► Selected edges with LLM reasoning + │ └─► Each edge links to extraction provenance + │ + └─► Answer Entity + └─► Reference to synthesized response (in librarian) +``` + +### İki Aşamalı GraphRAG İşlem Hattı + +1. **Kenar Seçimi**: LLM, alt grafikten ilgili kenarları seçer ve her biri için bir gerekçe sunar. +2. **Sentez**: LLM, yalnızca seçilen kenarlardan cevap oluşturur. + +Bu ayrım, açıklanabilirliği sağlar - hangi kenarların katkıda bulunduğunu tam olarak biliyoruz. + +### Depolama + +Açıklanabilirlik üçlüleri, yapılandırılabilir bir koleksiyonda saklanır (varsayılan: `explainability`). +Kaynak ilişkileri için PROV-O ontolojisi kullanılır. +Kenar referansları için RDF-star yeniden tanımlaması. +Cevap içeriği, kütüphaneci hizmetinde saklanır (satır içi değil - çok büyük). + +### Gerçek Zamanlı Akış + +Açıklanabilirlik olayları, sorgu yürütüldüğü sırada istemciye akış olarak gönderilir: + +1. Oturum oluşturuldu → olay gönderildi. +2. Kenarlar alındı → olay gönderildi. +3. Gerekçeyle birlikte kenarlar seçildi → olay gönderildi. +4. Cevap oluşturuldu → olay gönderildi. + +İstemci, `explain_id` ve `explain_collection`'i tam ayrıntıları almak için kullanır. + +## URI Yapısı + +Tüm URI'ler, UUID'lerle birlikte `urn:trustgraph:` ad alanını kullanır: + +| Varlık | URI Kalıbı | +|--------|-------------| +| Oturum | `urn:trustgraph:session:{uuid}` | +| Alma | `urn:trustgraph:prov:retrieval:{uuid}` | +| Seçim | `urn:trustgraph:prov:selection:{uuid}` | +| Cevap | `urn:trustgraph:prov:answer:{uuid}` | +| Kenar Seçimi | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## RDF Modeli (PROV-O) + +### Oturum Etkinliği + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG query session" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### Veri Alma Varlığı + +```turtle + a prov:Entity ; + rdfs:label "Retrieved edges" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### Seçim Varlığı + +```turtle + a prov:Entity ; + rdfs:label "Selected edges" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### Cevap Varlığı + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG answer" ; + prov:wasDerivedFrom ; + tg:document . +``` + +`tg:document`, kütüphaneci hizmetinde saklanan cevabı referans alır. + +## Ad Alanı Sabitleri + +`trustgraph-base/trustgraph/provenance/namespaces.py` içinde tanımlanmıştır: + +| Sabit | URI | +|----------|-----| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## GraphRagResponse Şeması + +```python +@dataclass +class GraphRagResponse: + error: Error | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" or "explain" + end_of_session: bool = False +``` + +### Mesaj Türleri + +| mesaj_türü | Amaç | +|--------------|---------| +| `chunk` | Yanıt metni (akış veya son) | +| `explain` | IRI referansıyla açıklanabilirlik olayı | + +### Oturum Yaşam Döngüsü + +1. Birden fazla `explain` mesajı (oturum, alma, seçim, yanıt) +2. Birden fazla `chunk` mesajı (akış yanıtı) +3. `end_of_session=True` ile birlikte son `chunk` + +## Kenar Seçim Formatı + +LLM, seçilen kenarlarla birlikte JSONL döndürür: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +`id`, `(labeled_s, labeled_p, labeled_o)`'nin `edge_id()` tarafından hesaplanan bir karma değeridir. + +## URI'nin Korunması + +### Sorun + +GraphRAG, LLM'ye okunabilir etiketler gösterir, ancak açıklanabilirlik, köken takibi için orijinal URI'lere ihtiyaç duyar. + +### Çözüm + +`get_labelgraph()`, şunları döndürür: +`labeled_edges`: LLM için `(label_s, label_p, label_o)` listesi +`uri_map`: `edge_id(labels)` → `(uri_s, uri_p, uri_o)` eşlemesini içeren sözlük + +Açıklanabilirlik verilerini saklarken, `uri_map`'dan gelen URI'ler kullanılır. + +## Köken Takibi + +### Kaynaktan Kenara + +Seçilen kenarlar, kaynak belgelere kadar izlenebilir: + +1. İçeren alt grafiği sorgulayın: `?subgraph tg:contains <>` +2. Kök belgeye kadar `prov:wasDerivedFrom` zincirini izleyin +3. Zincirdeki her adım: parça → sayfa → belge + +### Cassandra Tırnaklı Üçlü Desteği + +Cassandra sorgu hizmeti, tırnaklı üçlüleri eşleştirmeyi destekler: + +```python +# In get_term_value(): +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +Bu, şu tür sorguları mümkün kılar: +``` +?subgraph tg:contains <> +``` + +## CLI Kullanımı + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +### Çıktı Formatı + +``` +[session] urn:trustgraph:session:abc123 + +[retrieval] urn:trustgraph:prov:retrieval:abc123 + +[selection] urn:trustgraph:prov:selection:abc123 + Selected 12 edge(s) + Edge: (Guantanamo, definition, A detention facility...) + Reason: Directly connects Guantanamo to the War on Terror + Source: Chunk 1 → Page 2 → Beyond the Vigilant State + +[answer] urn:trustgraph:prov:answer:abc123 + +Based on the provided knowledge statements... +``` + +### Özellikler + +Sorgu sırasında gerçek zamanlı açıklanabilirlik olayları +`rdfs:label` aracılığıyla kenar bileşenleri için etiket çözümü +`prov:wasDerivedFrom` aracılığıyla kaynak zinciri takibi +Tekrarlanan sorguları önlemek için etiket önbelleği + +## Uygulanan Dosyalar + +| Dosya | Amaç | +|------|---------| +| `trustgraph-base/trustgraph/provenance/uris.py` | URI oluşturucular | +| `trustgraph-base/trustgraph/provenance/namespaces.py` | RDF ad alanı sabitleri | +| `trustgraph-base/trustgraph/provenance/triples.py` | Üçlü oluşturucular | +| `trustgraph-base/trustgraph/schema/services/retrieval.py` | GraphRagResponse şeması | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` | URI korumasıyla temel GraphRAG | +| `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` | Kütüphaneci entegrasyonlu hizmet | +| `trustgraph-flow/trustgraph/query/triples/cassandra/service.py` | Tırnaklı üçlü sorgu desteği | +| `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py` | Açıklanabilirlik gösterimiyle CLI | + +## Referanslar + +PROV-O (W3C Provenance Ontology): https://www.w3.org/TR/prov-o/ +RDF-star: https://w3c.github.io/rdf-star/ +Çıkarma zamanı kökeni: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/query-time-explainability.zh-cn.md b/docs/tech-specs/query-time-explainability.zh-cn.md new file mode 100644 index 00000000..2fe3269d --- /dev/null +++ b/docs/tech-specs/query-time-explainability.zh-cn.md @@ -0,0 +1,233 @@ +--- +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. + +## 状态 + +已实现 + +## 概述 + +本规范描述了 GraphRAG 如何记录和在查询执行期间传递可解释性数据。目标是实现完全的可追溯性:从最终答案,再到选择的边,最后到源文档。 + +查询时可解释性捕获了 GraphRAG 管道在推理过程中的行为。它与提取时的来源信息相关联,该信息记录了知识图谱事实的来源。 + +## 术语 + +| 术语 | 定义 | +|---|---| +| **可解释性** | 结果的推导方式 | +| **会话** | 单个 GraphRAG 查询执行 | +| **边选择** | 使用 LLM 进行相关边的选择,并提供推理 | +| **来源链** | 从边 → 块 → 页面 → 文档 | + +## 架构 + +### 可解释性流程 + +``` +GraphRAG 查询 + │ + ├─► 会话活动 + │ └─► 查询文本,时间戳 + │ + ├─► 检索实体 + │ └─► 从子图检索的所有边 + │ + ├─► 选择实体 + │ └─► 使用 LLM 推理选择的边 + │ └─► 每条边都与提取来源关联 + │ + └─► 答案实体 + └─► 指向合成响应 (在库员中) +``` + +### 两阶段 GraphRAG 管道 + +1. **边选择**:LLM 从子图中选择相关的边,并提供每个边的推理 +2. **合成**:LLM 从选择的边生成答案 + +这种分离实现了可解释性:我们知道哪些边贡献了结果。 + +### 存储 + +- 可解释性三元组存储在可配置的集合中 (默认:`explainability`) +- 使用 PROV-O 语义网进行来源关系 +- 使用 RDF-star 重新表达进行边引用 +- 答案内容存储在库员服务中 (不在内联位置 - 过于庞大) + +### 实时流 + +可解释性事件在查询执行时流式传输到客户端: + +1. 创建会话 → 发出事件 +2. 检索边 → 发出事件 +3. 使用推理选择边 → 发出事件 +4. 答案合成 → 发出事件 + +客户端接收 `explain_id` 和 `explain_collection` 以获取完整详细信息。 + +## URI 结构 + +所有 URI 使用 `urn:trustgraph:` 命名空间和 UUID: + +| 实体 | URI 模式 | +|---|---| +| 会话 | `urn:trustgraph:session:{uuid}` | +| 检索 | `urn:trustgraph:prov:retrieval:{uuid}` | +| 选择 | `urn:trustgraph:prov:selection:{uuid}` | +| 答案 | `urn:trustgraph:prov:answer:{uuid}` | +| 边选择 | `urn:trustgraph:prov:edge:{uuid}:{index}` | + +## RDF 模型 (PROV-O) + +### 会话活动 + +```turtle + a prov:Activity ; + rdfs:label "GraphRAG 查询会话" ; + prov:startedAtTime "2024-01-15T10:30:00Z" ; + tg:query "What was the War on Terror?" . +``` + +### 检索实体 + +```turtle + a prov:Entity ; + rdfs:label "检索的边" ; + prov:wasGeneratedBy ; + tg:edgeCount 50 . +``` + +### 选择实体 + +```turtle + a prov:Entity ; + rdfs:label "选择的边" ; + prov:wasDerivedFrom ; + tg:selectedEdge ; + tg:selectedEdge . + + tg:edge <<

>> ; + tg:reasoning "This edge establishes the key relationship..." . +``` + +### 答案实体 + +```turtle + a prov:Entity ; + rdfs:label "GraphRAG 答案" ; + prov:wasDerivedFrom ; + tg:document . +``` + +`tg:document` 引用库员服务中存储的答案。 + +## 名称空间常量 + +定义在 `trustgraph-base/trustgraph/provenance/namespaces.py`: + +| 常量 | URI | +|---|---| +| `TG_QUERY` | `https://trustgraph.ai/ns/query` | +| `TG_EDGE_COUNT` | `https://trustgraph.ai/ns/edgeCount` | +| `TG_SELECTED_EDGE` | `https://trustgraph.ai/ns/selectedEdge` | +| `TG_EDGE` | `https://trustgraph.ai/ns/edge` | +| `TG_REASONING` | `https://trustgraph.ai/ns/reasoning` | +| `TG_CONTENT` | `https://trustgraph.ai/ns/content` | +| `TG_DOCUMENT` | `https://trustgraph.ai/ns/document` | + +## GraphRagResponse 模式 + +```python +@dataclass +class GraphRagResponse: + error: None | None = None + response: str = "" + end_of_stream: bool = False + explain_id: str | None = None + explain_collection: str | None = None + message_type: str = "" # "chunk" 或 "explain" + end_of_session: bool = False +``` + +### 消息类型 + +| message_type | 目的 | +|---|---| +| `chunk` | 响应文本 (流式或最终) | +| `explain` | 可解释性事件,包含 IRI 引用 | + +### 会话生命周期 + +1. 多个 `explain` 消息 (会话、检索、选择、答案) +2. 多个 `chunk` 消息 (流式响应) +3. 最终的 `chunk`,`end_of_session=True` + +## 边选择格式 + +LLM 返回 JSONL 格式的边: + +```jsonl +{"id": "edge-hash-1", "reasoning": "This edge shows the key relationship..."} +{"id": "edge-hash-2", "reasoning": "Provides supporting evidence..."} +``` + +`id` 是使用 `edge_id()` 计算的 `(labeled_s, labeled_p, labeled_o)` 的哈希值。 + +## URI 保留 + +### 问题 + +GraphRAG 向 LLM 显示了人类可读的标签,但为了可追溯性,需要原始 URI。 + +### 解决方案 + +`get_labelgraph()` 返回: +- `labeled_edges`: 包含 `(label_s, label_p, label_o)` 的列表,供 LLM 使用 +- `uri_map`: 将 `edge_id(labels)` 映射到 `(uri_s, uri_p, uri_o)` 的字典 + +在存储可解释性数据时,使用 `uri_map` 中的 URI。 + +## 来源追踪 + +### 从边到源 + +可以追踪选择的边: + +1. 查询包含的子图:`?subgraph tg:contains <>` +2. 遵循 `prov:wasDerivedFrom` 链,找到根文档 +3. 每个步骤中的链:块 → 页面 → 文档 + +### 支持 Cassandra 引用 + +Cassandra 查询服务支持引用: + +```python +# 在 get_term_value() 中: +elif term.type == TRIPLE: + return serialize_triple(term.triple) +``` + +这允许查询: +``` +?subgraph tg:contains <> +``` + +## CLI 使用 + +```bash +tg-invoke-graph-rag --explainable -q "What was the War on Terror?" +``` + +## 参考 + +- PROV-O (W3C Provenance Ontology): https://www.w3.org/TR/prov-o/ +- RDF-star: https://w3c.github.io/rdf-star/ +- 提取时的来源信息: `docs/tech-specs/extraction-time-provenance.md` diff --git a/docs/tech-specs/rag-streaming-support.ar.md b/docs/tech-specs/rag-streaming-support.ar.md new file mode 100644 index 00000000..19f75ad2 --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.ar.md @@ -0,0 +1,174 @@ +--- +layout: default +title: "مواصفات فنية لدعم التدفق في RAG" +parent: "Arabic (Beta)" +--- + +# مواصفات فنية لدعم التدفق في RAG + +> **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. + +## نظرة عامة + +تصف هذه المواصفات إضافة دعم التدفق إلى خدمات GraphRAG و DocumentRAG، مما يمكّن من الحصول على استجابات على شكل أجزاء (token-by-token) في الوقت الفعلي للاستعلامات المتعلقة باسترجاع المعرفة ورؤوس المستندات. هذا يوسع البنية المعمارية الحالية للتدفق، والتي تم تنفيذها بالفعل لخدمات إكمال النص، والتعليمات البرمجية، ووكلاء LLM. + +## الأهداف + +- **تجربة تدفق متسقة**: توفير تجربة تدفق متسقة عبر جميع خدمات TrustGraph. +- **تغييرات واجهة برمجة تطبيقات (API) قليلة**: إضافة دعم التدفق باستخدام علامة واحدة (`streaming`)، وفقًا للأنماط المتبعة. +- **التوافق مع الإصدارات السابقة**: الحفاظ على سلوك غير تدفق بشكل افتراضي. +- **استخدام البنية التحتية الحالية**: الاستفادة من تدفق PromptClient المطبق بالفعل. +- **دعم البوابة**: تمكين التدفق من خلال بوابة websocket للتطبيقات العميلة. + +## الخلفية + +خدمات التدفق الحالية: +- **خدمة إكمال النص للـ LLM**: المرحلة 1 - التدفق من مزودي LLM. +- **خدمة التعليمات البرمجية**: المرحلة 2 - التدفق من خلال قوالب التعليمات البرمجية. +- **خدمة الوكيل**: المراحل 3-4 - استجابات ReAct مع أجزاء فكرية/ملاحظات/إجابات متزايدة. + +قيود الحالية لخدمات RAG: +- GraphRAG و DocumentRAG تدعم فقط الاستجابات المتوقفة. +- يجب على المستخدمين الانتظار حتى استلام الرد الكامل من LLM قبل رؤية أي مخرجات. +- تجربة مستخدم (UX) سيئة للاستجابات الطويلة من استعلامات الرسم البياني المعرفي أو المستندات. +- تجربة غير متسقة مقارنة بـ خدمات TrustGraph الأخرى. + +تستجيب هذه المواصفات لهذه الثغرات من خلال إضافة دعم التدفق إلى GraphRAG و DocumentRAG. من خلال تمكين الاستجابات على شكل أجزاء، يمكن لـ TrustGraph: +- توفير تجربة تدفق متسقة عبر جميع أنواع الاستعلام. +- تقليل التأخير المتوقع في استعلامات RAG. +- تمكين ملاحظات تقدم أفضل للاستعلامات الطويلة الأمد. +- دعم العرض في الوقت الفعلي في تطبيقات العملاء. + +## التصميم الفني + +### البنية + +يستفيد تنفيذ التدفق في RAG من البنية التحتية الحالية: + +1. **تدفق PromptClient** (مطبق بالفعل) + - يستقبل `kg_prompt()` و `document_prompt()` بالفعل معلمات `streaming` و `chunk_callback`. + - تستدعي هذه `prompt()` داخليًا مع دعم التدفق. + - لا يلزم إجراء أي تغييرات على PromptClient. + + الوحدة: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **خدمة GraphRAG** (تحتاج إلى تمرير معلمة التدفق) + - إضافة معلمة `streaming` إلى طريقة `query()`. + - تمرير علامة التدفق والوظائف المرجعية إلى `prompt_client.kg_prompt()`. + - يجب أن يحتوي مخطط GraphRag على حقل `streaming`. + + الوحدات: + - `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + - `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (المعالجة) + - `trustgraph-base/trustgraph/schema/graph_rag.py` (مخطط الطلب) + - `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (البوابة) + +3. **خدمة DocumentRAG** (تحتاج إلى تمرير معلمة التدفق) + - إضافة معلمة `streaming` إلى طريقة `query()`. + - تمرير علامة التدفق والوظائف المرجعية إلى `prompt_client.document_prompt()`. + - يجب أن يحتوي مخطط DocumentRag على حقل `streaming`. + + الوحدات: + - `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + - `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (المعالجة) + - `trustgraph-base/trustgraph/schema/document_rag.py` (مخطط الطلب) + - `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (البوابة) + +### تدفق البيانات + +**غير تدفق (الحالي)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + رد كامل + ↓ +Client ← Gateway ← RAG Service ← الرد +``` + +**تدفق (مقترح)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + جزء → وظيفة مرجعية → رد RAG (جزء) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── رد التدفق +``` + +### واجهات برمجة التطبيقات (APIs) + +**تغييرات GraphRAG**: + +1. **GraphRag.query()** - إضافة معلمات التدفق +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... كود موجود ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **مخطط GraphRagRequest** - إضافة حقل التدفق +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **مخطط GraphRagResponse** - إضافة حقول التدفق (اتبع نمط الوكيل) +```python +class GraphRagResponse(Record): + response = String() + metadata = dict + # ... حقول أخرى ... +``` + +**تغييرات DocumentRAG**: +(نفس التغييرات الموضحة أعلاه) + +### التغييرات في البوابة + +(نفس التغييرات الموضحة أعلاه) + +## خطة النقل + +لا توجد حاجة لنقل: +- التدفق هو خيار، وتكون القيمة الافتراضية هي False. +- لا تزال العملاء الحالية تعمل بشكل طبيعي. +- يمكن للعملاء الجدد اختيار التدفق. + +## الجدول الزمني + +الوقت المقدر للتنفيذ: 4-6 ساعات +- المرحلة 1 (2 ساعات): دعم التدفق في GraphRAG +- المرحلة 2 (2 ساعات): دعم التدفق في DocumentRAG +- المرحلة 3 (1-2 ساعات): تحديثات البوابة وعلامات سطر الأوامر (CLI) +- الاختبار: تم تضمينه في كل مرحلة + +## الأسئلة المفتوحة + +- هل يجب إضافة دعم التدفق لخدمة NLP Query أيضًا؟ +- هل نريد تدفق خطوات وسيطة (مثل "جاري استرداد الكيانات..."، "استعلام عن الرسم البياني") أم فقط مخرجات LLM؟ +- هل يجب تضمين بيانات وصفية للجزء (مثل رقم الجزء، العدد الإجمالي المتوقع) في استجابات GraphRAG/DocumentRAG؟ + +## المراجع + +- التنفيذ الحالي: `docs/tech-specs/streaming-llm-responses.md` +- تدفق PromptClient: `trustgraph-base/trustgraph/base/prompt_client.py` +- تدفق الوكيل: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` diff --git a/docs/tech-specs/rag-streaming-support.es.md b/docs/tech-specs/rag-streaming-support.es.md new file mode 100644 index 00000000..60e4cc9a --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.es.md @@ -0,0 +1,196 @@ +--- +layout: default +title: "Especificación Técnica de Soporte de Streaming para RAG" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Soporte de Streaming para RAG + +> **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. + +## Visión general + +Esta especificación describe la adición de soporte de streaming a los servicios GraphRAG y DocumentRAG, permitiendo respuestas en tiempo real, token por token, para consultas de recuperación de conocimiento y documentos. Esto extiende la arquitectura de streaming existente, ya implementada para servicios de completado de texto, prompts y agentes de LLM. + +## Objetivos + +- **Experiencia de usuario consistente**: Proporcionar la misma experiencia de streaming en todos los servicios TrustGraph. +- **Cambios mínimos en la API**: Añadir soporte de streaming con una única bandera `streaming`, siguiendo patrones establecidos. +- **Compatibilidad hacia atrás**: Mantener el comportamiento no de streaming existente como predeterminado. +- **Reutilizar la infraestructura existente**: Aprovechar el streaming ya implementado en PromptClient. +- **Soporte de Gateway**: Permitir el streaming a través de un gateway websocket para aplicaciones cliente. + +## Antecedentes + +Servicios de streaming actualmente implementados: + +- **Servicio de completado de texto de LLM**: Fase 1 - Streaming desde proveedores de LLM. +- **Servicio de prompts**: Fase 2 - Streaming a través de plantillas de prompts. +- **Servicio de agente**: Fase 3-4 - Streaming de respuestas ReAct con fragmentos incrementales de "pensamiento/observación/respuesta". + +Limitaciones actuales para servicios RAG: + +- GraphRAG y DocumentRAG solo soportan respuestas de bloqueo. +- Los usuarios deben esperar a que la respuesta completa del LLM antes de ver cualquier salida. +- Mala experiencia de usuario para respuestas largas de consultas de conocimiento o documentos. +- Experiencia inconsistente en comparación con otros servicios de TrustGraph. + +Esta especificación aborda estas limitaciones añadiendo soporte de streaming a GraphRAG y DocumentRAG. Al permitir respuestas token por token, TrustGraph puede: + +- Proporcionar una experiencia de usuario consistente de streaming para todos los tipos de consultas. +- Reducir la latencia percibida para las consultas RAG. +- Facilitar una mejor retroalimentación del progreso para las consultas de ejecución prolongada. +- Soporte para visualización en tiempo real en aplicaciones cliente. + +## Diseño Técnico + +### Arquitectura + +La implementación de streaming de RAG aprovecha la infraestructura existente: + +1. **Streaming de PromptClient** (Ya implementado) + - `kg_prompt()` y `document_prompt()` ya aceptan los parámetros `streaming` y `chunk_callback`. + - Estos llaman `prompt()` internamente con soporte de streaming. + - No se necesitan cambios en PromptClient. + - Módulo: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **Servicio GraphRAG** (Necesita pasar el parámetro `streaming`) + - Añadir el parámetro `streaming` al método `query()`. + - Pasar la bandera de streaming y los callbacks a `prompt_client.kg_prompt()`. + - El esquema GraphRagRequest debe incluir el campo `streaming`. + - Módulos: + - `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + - `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (Procesador) + - `trustgraph-base/trustgraph/schema/graph_rag.py` (Esquema de solicitud) + - `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Gateway) + +3. **Servicio DocumentRAG** (Necesita pasar el parámetro `streaming`) + - Añadir el parámetro `streaming` al método `query()`. + - Pasar la bandera de streaming y los callbacks a `prompt_client.document_prompt()`. + - El esquema DocumentRagRequest debe incluir el campo `streaming`. + - Módulos: + - `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + - `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (Procesador) + - `trustgraph-base/trustgraph/schema/document_rag.py` (Esquema de solicitud) + - `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Gateway) + +### Flujo de datos + +**No de streaming (actual)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + Respuesta completa + ↓ +Client ← Gateway ← RAG Service ← Respuesta +``` + +**Streaming (propuesto)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + Fragmento → callback → Respuesta RAG (fragmento) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── Flujo de respuesta +``` + +### APIs + +**Cambios en GraphRAG**: + +1. **GraphRag.query()** - Añadir parámetros de streaming +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NUEVO +): + # ... código existente de recuperación de entidades/triples ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **Esquema GraphRagRequest** - Añadir campo de streaming +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NUEVO +``` + +3. **Esquema GraphRagResponse** - Añadir campos de streaming (seguir el patrón de Agent) +```python +class GraphRagResponse(Record): + response = String() # LEGADO: respuesta completa + chunk = String() # NUEVO: fragmento de streaming + end_of_stream = Boolean() # NUEVO: indica el último fragmento +``` + +4. **Procesador** - Pasar el streaming a través +```python +async def handle(self, msg): + # ... código existente ... + + async def send_chunk(chunk): + await self.respond(GraphRagResponse( + chunk=chunk, + end_of_stream=False, + response=None + )) + + if request.streaming: + resp = await self.prompt_client.kg_prompt( + request.query, + request.context, + streaming=True + ) + else: + resp = await self.prompt_client.kg_prompt( + request.query, + request.context + ) + + # Procesar respuesta + # ... +``` + +### Plan de migración + +No se requiere migración: + +- El soporte de streaming es opcional a través del parámetro `streaming` (predeterminado a False). +- Los clientes existentes siguen funcionando sin cambios. +- Los nuevos clientes pueden optar por habilitar el streaming. + +## Cronograma + +Tiempo estimado de implementación: 4-6 horas. +- Fase 1 (2 horas): Soporte de streaming para GraphRAG. +- Fase 2 (2 horas): Soporte de streaming para DocumentRAG. +- Fase 3 (1-2 horas): Actualizaciones del Gateway y banderas de la CLI. +- Pruebas: Integradas en cada fase. + +## Preguntas abiertas + +- ¿Deberíamos añadir soporte de streaming al servicio NLP Query también? +- ¿Queremos transmitir solo los pasos intermedios (por ejemplo, "Recuperando entidades...", "Consultando el gráfico...") o también la salida del LLM? +- ¿Debería GraphRAG/DocumentRAG incluir metadatos del fragmento (por ejemplo, número de fragmento, número total esperado)? + +## Referencias + +- Implementación existente: `docs/tech-specs/streaming-llm-responses.md` +- Streaming de PromptClient: `trustgraph-base/trustgraph/base/prompt_client.py` +- Streaming de Agent: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` diff --git a/docs/tech-specs/rag-streaming-support.he.md b/docs/tech-specs/rag-streaming-support.he.md new file mode 100644 index 00000000..38de6cdd --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.he.md @@ -0,0 +1,176 @@ +--- +layout: default +title: "תמיכה בסטרימינג של RAG - ספציפיציה טכנית" +parent: "Hebrew (Beta)" +--- + +# תמיכה בסטרימינג של RAG - ספציפיציה טכנית + +> **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. + +## סקירה כללית + +מסמך זה מתאר את הוספת תמיכה בסטרימינג לשירותי GraphRAG ו-DocumentRAG, המאפשרות תגובות בזמן אמת, שוט אחר שוט, עבור שאילתות שליפה של גרפי ידע ומסמכים. זה מרחיב את הארכיטקטורה הסטנדרטית לסטרימינג, אשר כבר מיושמת עבור שירותי LLM להשלמת טקסט, בקשות וסוכנים. + +## מטרות + +- **חוויית משתמש סטנדרטית בסטרימינג**: לספק חוויית סטרימינג אחידה בכל שירותי TrustGraph. +- **שינויים מינימליים בממשק API**: להוסיף תמיכה בסטרימינג באמצעות דגל `streaming` יחיד, תוך עמידה בדפוסי העבודה הקיימים. +- **תאימות לאחור**: לשמור על התנהגות לא סטנדרטית קיימת כברירת מחדל. +- **ניצול תשתית קיימת**: להשתמש בסטרימינג הקיים, אשר כבר מיושם עבור ה-PromptClient. +- **תמיכה בדגלים**: לאפשר סטרימינג באמצעות דגל websocket עבור יישומי לקוח. + +## רקע + +שירותי סטרימינג קיימים: +- **שירות השלמת טקסט של LLM**: שלב 1 - סטרימינג מספקי LLM +- **שירות בקשות**: שלב 2 - סטרימינג באמצעות תבניות בקשות +- **שירות סוכן**: שלבים 3-4 - סטרימינג של תגובות ReAct עם חלקים של מחשבה/תצפית/תשובה + +מגבלות נוכחיות לשירותי RAG: +- GraphRAG ו-DocumentRAG תומכים רק בתגובות בלתי סטנדרטיות. +- משתמשים צריכים לחכות לתגובה שלמה של LLM לפני קבלת כל תוצאה. +- חוויית משתמש גרועה עבור תגובות ארוכות לשאילתות של גרפי ידע או מסמכים. +- חוויה לא עקבית בהשוואה לשירותי TrustGraph אחרים. + +מסמך זה מטפל בבעיות אלו על ידי הוספת תמיכה בסטרימינג ל-GraphRAG ו-DocumentRAG. על ידי אפשרות תגובות שוט אחר שוט, TrustGraph יכול: +- לספק חוויית משתמש סטנדרטית בסטרימינג עבור כל סוגי השאילתות. +- להפחית את הפיגור הרגשי עבור שאילתות RAG. +- לאפשר משוב מתקדם עבור שאילתות ארוכות. +- לתמוך בהצגה בזמן אמת ביישומים של לקוח. + +## עיצוב טכני + +### ארכיטקטורה + +היישום הסטנדרטי של RAG של מנצל את התשתית הקיימת: + +1. **סטרימינג של PromptClient** (כבר מיושם) + - הפרמטרים `kg_prompt()` ו-`document_prompt()` כבר מקבלים את הפרמטרים `streaming` ו-`chunk_callback`. + - הפרמטרים אלו קוראים לפונקציה `prompt()` עם תמיכה בסטרימינג. + - אין צורך לשנות את ה-PromptClient. + - מודול: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **שירות GraphRAG** (דורש העברת פרמטר סטרימינג) + - להוסיף את הפרמטר `streaming` למתודה `query()`. + - להעביר את הדגל הסטרימינג ואת ה-callbacks ל-`prompt_client.kg_prompt()`. + - סכימת ה-GraphRagRequest צריכה לכלול את השדה `streaming`. + - מודולים: + - `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + - `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (Processor) + - `trustgraph-base/trustgraph/schema/graph_rag.py` (סכימת בקשה) + - `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Gateway) + +3. **שירות DocumentRAG** (דורש העברת פרמטר סטרימינג) + - להוסיף את הפרמטר `streaming` למתודה `query()`. + - להעביר את הדגל הסטרימינג ואת ה-callbacks ל-`prompt_client.document_prompt()`. + - סכימת ה-DocumentRagRequest צריכה לכלול את השדה `streaming`. + - מודולים: + - `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + - `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (Processor) + - `trustgraph-base/trustgraph/schema/document_rag.py` (סכימת בקשה) + - `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Gateway) + +### זרימת נתונים + +**לא סטנדרטי (נוכחי)**: +``` +לקוח → דגל → שירות RAG → PromptClient.kg_prompt(streaming=False) + ↓ +שירות בקשות → LLM + ↓ +תגובה שלמה + ↓ +לקוח ← דגל ← שירות RAG ← תגובה +``` + +**סטנדרטי (מוצע)**: +``` +לקוח → דגל → שירות RAG → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ +שירות בקשות → LLM (סטרימינג) + ↓ +חלק → Callback → תגובת RAG (חלק) + ↓ ↓ +לקוח ← דגל ← ────────────────────────────────── זרם תגובה +``` + +### ממשקי API + +**שינויים ב-GraphRAG**: + +1. **GraphRag.query()** - הוספת פרמטרים סטרימינג +```python +async def query( + self, query, user, collection, + streaming=False, chunk_callback=None +): + # ... +``` +2. **שינויים ב-DocumentRAG**: + - כפי שמתואר עבור GraphRAG. + +### בדיקות + +**בדיקות יחידות**: +- בדיקת GraphRag.query() עם `streaming=True/False`. +- בדיקת DocumentRAG.query() עם `streaming=True/False`. +- שימוש ב-Mock עבור PromptClient כדי לבדוק את קריאות ה-callbacks. + +**בדיקות אינטגרציה**: +- בדיקת זרימת הסטרימינג המלאה של GraphRAG (בדיקות דומות לבדיקות סטרימינג של סוכן קיימות). +- בדיקת זרימת הסטרימינג המלאה של DocumentRAG. +- בדיקת העברת דגל ה-סטרימינג. +- בדיקת הפלט של ה-CLI עם סטרימינג. + +**בדיקות ידניות**: +- `tg-invoke-graph-rag -q "מהו למידת מכונה?"` (סטרימינג כברירת מחדל). +- `tg-invoke-document-rag -q "סכם את המסמכים על AI"` (סטרימינג כברירת מחדל). +- `tg-invoke-graph-rag --no-streaming -q "..."` (בדיקת מצב לא סטנדרטי). +- בדיקה שהחלקים מופיעים בסטרימינג. + +## תכנון בדיקות + +**בדיקות יחידות**: +- בדיקת GraphRag.query() עם `streaming=True/False`. +- בדיקת DocumentRAG.query() עם `streaming=True/False`. +- שימוש ב-Mock עבור PromptClient כדי לבדוק את קריאות ה-callbacks. + +**בדיקות אינטגרציה**: +- בדיקת זרימת הסטרימינג המלאה של GraphRAG (בדיקות דומות לבדיקות סטרימינג של סוכן קיימות). +- בדיקת זרימת הסטרימינג המלאה של DocumentRAG. +- בדיקת העברת דגל ה-סטרימינג. +- בדיקת הפלט של ה-CLI עם סטרימינג. + +**בדיקות ידניות**: +- `tg-invoke-graph-rag -q "מהו למידת מכונה?"` (סטרימינג כברירת מחדל). +- `tg-invoke-document-rag -q "סכם את המסמכים על AI"` (סטרימינג כברירת מחדל). +- `tg-invoke-graph-rag --no-streaming -q "..."` (בדיקת מצב לא סטנדרטי). +- בדיקה שהחלקים מופיעים בסטרימינג. + +## תכנון המיגרציה + +אין צורך במיגרציה: +- הסטרימינג הוא "אופציונלי" באמצעות הפרמטר `streaming` (ברירת מחדל היא False). +- לקוחות קיימים ממשיכים לעבוד ללא שינוי. +- לקוחות חדשים יכולים לבחור בסטרימינג. + +## לוח זמנים + +הערכת זמן ליישום: 4-6 שעות +- שלב 1 (2 שעות): תמיכה בסטרימינג של GraphRAG. +- שלב 2 (2 שעות): תמיכה בסטרימינג של DocumentRAG. +- שלב 3 (1-2 שעות): עדכוני דגל ו-CLI. +- בדיקות: בונה לתוך כל שלב. + +## שאלות פתוחות + +- האם עלינו להוסיף תמיכה בסטרימינג לשירות ה-NLP Query גם כן? +- האם עלינו להזרים גם את השלבים הביניים (לדוגמה, "שליפת ישויות...", "שאילתה על הגרף...") או רק את הפלט של ה-LLM? +- האם עלינו לכלול מידע על החלקים בתגובות של RAG (לדוגמה, מספר החלק, מספר כולל צפוי)? + +## מקורות + +- יישום קיימת: `docs/tech-specs/streaming-llm-responses.md` +- סטרימינג של PromptClient: `trustgraph-base/trustgraph/base/prompt_client.py` +- סטרימינג של סוכן: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` diff --git a/docs/tech-specs/rag-streaming-support.hi.md b/docs/tech-specs/rag-streaming-support.hi.md new file mode 100644 index 00000000..a6bb7bc9 --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.hi.md @@ -0,0 +1,296 @@ +--- +layout: default +title: "RAG स्ट्रीमिंग सपोर्ट तकनीकी विनिर्देश" +parent: "Hindi (Beta)" +--- + +# RAG स्ट्रीमिंग सपोर्ट तकनीकी विनिर्देश + +> **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. + +## अवलोकन + +यह विनिर्देश ग्राफआरएजी और डॉक्यूमेंटआरएजी सेवाओं में स्ट्रीमिंग सपोर्ट जोड़ने का वर्णन करता है, जो नॉलेज ग्राफ और डॉक्यूमेंट रिट्रीवल क्वेरी के लिए वास्तविक समय में टोकन-दर-टोकन प्रतिक्रियाएं सक्षम करता है। यह एलएलएम टेक्स्ट-कंप्लीशन, प्रॉम्प्ट और एजेंट सेवाओं के लिए पहले से लागू किए गए मौजूदा स्ट्रीमिंग आर्किटेक्चर का विस्तार करता है। + +## लक्ष्य + +**संगत स्ट्रीमिंग यूएक्स**: सभी ट्रस्टग्राफ सेवाओं में समान स्ट्रीमिंग अनुभव प्रदान करें। +**न्यूनतम एपीआई परिवर्तन**: एक ही `streaming` फ़्लैग के साथ स्ट्रीमिंग सपोर्ट जोड़ें, स्थापित पैटर्न का पालन करें। +**पिछड़ा संगतता**: मौजूदा गैर-स्ट्रीमिंग व्यवहार को डिफ़ॉल्ट के रूप में बनाए रखें। +**मौजूदा बुनियादी ढांचे का पुन: उपयोग**: पहले से लागू प्रॉम्प्टक्लाइंट स्ट्रीमिंग का लाभ उठाएं। +**गेटवे सपोर्ट**: क्लाइंट एप्लिकेशन के लिए वेबसॉकेट गेटवे के माध्यम से स्ट्रीमिंग सक्षम करें। + +## पृष्ठभूमि + +वर्तमान में लागू की गई स्ट्रीमिंग सेवाएं: +**एलएलएम टेक्स्ट-कंप्लीशन सेवा**: चरण 1 - एलएलएम प्रदाताओं से स्ट्रीमिंग। +**प्रॉम्प्ट सेवा**: चरण 2 - प्रॉम्प्ट टेम्प्लेट के माध्यम से स्ट्रीमिंग। +**एजेंट सेवा**: चरण 3-4 - इंक्रीमेंटल थॉट/ऑब्जर्वेशन/एन्सर चंक्स के साथ रीएक्ट प्रतिक्रियाओं को स्ट्रीमिंग करना। + +आरएजी सेवाओं के लिए वर्तमान सीमाएं: +ग्राफआरएजी और डॉक्यूमेंटआरएजी केवल ब्लॉकिंग प्रतिक्रियाओं का समर्थन करते हैं। +उपयोगकर्ताओं को किसी भी आउटपुट को देखने से पहले एलएलएम प्रतिक्रिया पूरी होने तक इंतजार करना होगा। +नॉलेज ग्राफ या डॉक्यूमेंट क्वेरी से लंबी प्रतिक्रियाओं के लिए खराब यूएक्स। +अन्य ट्रस्टग्राफ सेवाओं की तुलना में असंगत अनुभव। + +यह विनिर्देश ग्राफआरएजी और डॉक्यूमेंटआरएजी में स्ट्रीमिंग सपोर्ट जोड़कर इन कमियों को दूर करता है। टोकन-दर-टोकन प्रतिक्रियाओं को सक्षम करके, ट्रस्टग्राफ: +सभी क्वेरी प्रकारों में संगत स्ट्रीमिंग यूएक्स प्रदान कर सकता है। +आरएजी क्वेरी के लिए कथित विलंबता को कम कर सकता है। +लंबी अवधि की क्वेरी के लिए बेहतर प्रगति प्रतिक्रिया प्रदान कर सकता है। +क्लाइंट एप्लिकेशन में वास्तविक समय प्रदर्शन का समर्थन कर सकता है। + +## तकनीकी डिजाइन + +### आर्किटेक्चर + +आरएजी स्ट्रीमिंग कार्यान्वयन मौजूदा बुनियादी ढांचे का लाभ उठाता है: + +1. **प्रॉम्प्टक्लाइंट स्ट्रीमिंग** (पहले से लागू) + `kg_prompt()` और `document_prompt()` पहले से ही `streaming` और `chunk_callback` पैरामीटर स्वीकार करते हैं। + ये आंतरिक रूप से स्ट्रीमिंग सपोर्ट के साथ `prompt()` को कॉल करते हैं। + प्रॉम्प्टक्लाइंट में कोई बदलाव आवश्यक नहीं है। + + मॉड्यूल: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **ग्राफआरएजी सेवा** (स्ट्रीमिंग पैरामीटर पास-थ्रू की आवश्यकता है) + `query()` विधि में `streaming` पैरामीटर जोड़ें। + `prompt_client.kg_prompt()` और कॉलबैक को `prompt_client.kg_prompt()` में पास करें। + ग्राफआरैग रिक्वेस्ट स्कीमा में `streaming` फ़ील्ड की आवश्यकता है। + + मॉड्यूल: + `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (प्रोसेसर) + `trustgraph-base/trustgraph/schema/graph_rag.py` (रिक्वेस्ट स्कीमा) + `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (गेटवे) + +3. **डॉक्यूमेंटआरएजी सेवा** (स्ट्रीमिंग पैरामीटर पास-थ्रू की आवश्यकता है) + `query()` विधि में `streaming` पैरामीटर जोड़ें। + `prompt_client.document_prompt()` और कॉलबैक को `prompt_client.document_prompt()` में पास करें। + डॉक्यूमेंटआरैग रिक्वेस्ट स्कीमा में `streaming` फ़ील्ड की आवश्यकता है। + + मॉड्यूल: + `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (प्रोसेसर) + `trustgraph-base/trustgraph/schema/document_rag.py` (रिक्वेस्ट स्कीमा) + `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (गेटवे) + +### डेटा फ्लो + +**गैर-स्ट्रीमिंग (वर्तमान)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + Complete response + ↓ +Client ← Gateway ← RAG Service ← Response +``` + +**स्ट्रीमिंग (प्रस्तावित):** +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + Chunk → callback → RAG Response (chunk) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── Response stream +``` + +### एपीआई (APIs) + +**ग्राफआरएजी (GraphRAG) में बदलाव**: + +1. **GraphRag.query()** - स्ट्रीमिंग पैरामीटर जोड़े गए। +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... existing entity/triple retrieval ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **ग्राफराग रिक्वेस्ट स्कीमा** - स्ट्रीमिंग फ़ील्ड जोड़ें। +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **ग्राफराग रिस्पांस स्कीमा** - स्ट्रीमिंग फ़ील्ड जोड़ें (एजेंट पैटर्न का पालन करें)। +```python +class GraphRagResponse(Record): + response = String() # Legacy: complete response + chunk = String() # NEW: streaming chunk + end_of_stream = Boolean() # NEW: indicates last chunk +``` + +4. **प्रोसेसर** - डेटा को लगातार प्रवाहित करें। +```python +async def handle(self, msg): + # ... existing code ... + + async def send_chunk(chunk): + await self.respond(GraphRagResponse( + chunk=chunk, + end_of_stream=False, + response=None + )) + + if request.streaming: + full_response = await self.rag.query( + query=request.query, + user=request.user, + collection=request.collection, + streaming=True, + chunk_callback=send_chunk + ) + # Send final message + await self.respond(GraphRagResponse( + chunk=None, + end_of_stream=True, + response=full_response + )) + else: + # Existing non-streaming path + response = await self.rag.query(...) + await self.respond(GraphRagResponse(response=response)) +``` + +**डॉक्यूमेंटआरएजी में परिवर्तन**: + +ग्राफआरएजी के समान पैटर्न: +1. `streaming` और `chunk_callback` पैरामीटर को `DocumentRag.query()` में जोड़ें। +2. `streaming` फ़ील्ड को `DocumentRagRequest` में जोड़ें। +3. `chunk` और `end_of_stream` फ़ील्ड को `DocumentRagResponse` में जोड़ें। +4. प्रोसेसर को कॉलबैक के साथ स्ट्रीमिंग को संभालने के लिए अपडेट करें। + +**गेटवे में परिवर्तन**: + +गेटवे/डिस्पैच में `graph_rag.py` और `document_rag.py` दोनों को वेबसॉकेट पर स्ट्रीमिंग चंक्स को अग्रेषित करने के लिए अपडेट की आवश्यकता है: + +```python +async def handle(self, message, session, websocket): + # ... existing code ... + + if request.streaming: + async def recipient(resp): + if resp.chunk: + await websocket.send(json.dumps({ + "id": message["id"], + "response": {"chunk": resp.chunk}, + "complete": resp.end_of_stream + })) + return resp.end_of_stream + + await self.rag_client.request(request, recipient=recipient) + else: + # Existing non-streaming path + resp = await self.rag_client.request(request) + await websocket.send(...) +``` + +### कार्यान्वयन विवरण + +**कार्यान्वयन क्रम**: +1. स्कीमा फ़ील्ड जोड़ें (RAG सेवाओं दोनों के लिए अनुरोध + प्रतिक्रिया) +2. GraphRag.query() और DocumentRag.query() विधियों को अपडेट करें +3. प्रोसेसर को स्ट्रीमिंग को संभालने के लिए अपडेट करें +4. गेटवे डिस्पैच हैंडलर को अपडेट करें +5. `--no-streaming` ध्वज `tg-invoke-graph-rag` और `tg-invoke-document-rag` में जोड़ें (डिफ़ॉल्ट रूप से स्ट्रीमिंग सक्षम, एजेंट CLI पैटर्न का अनुसरण करते हुए) + +**कॉलबैक पैटर्न**: +एजेंट स्ट्रीमिंग में स्थापित समान एसिंक्रोनस कॉल बैक पैटर्न का पालन करें: +प्रोसेसर `async def send_chunk(chunk)` कॉल बैक को परिभाषित करता है +कॉल बैक को RAG सेवा को पास करता है +RAG सेवा कॉल बैक को PromptClient को पास करती है +PromptClient प्रत्येक LLM टुकड़े के लिए कॉल बैक को लागू करता है +प्रोसेसर प्रत्येक टुकड़े के लिए स्ट्रीमिंग प्रतिक्रिया संदेश भेजता है + +**त्रुटि प्रबंधन**: +स्ट्रीमिंग के दौरान होने वाली त्रुटियों को `end_of_stream=True` के साथ त्रुटि प्रतिक्रिया भेजनी चाहिए +एजेंट स्ट्रीमिंग से मौजूदा त्रुटि प्रसार पैटर्न का पालन करें + +## सुरक्षा संबंधी विचार + +मौजूदा RAG सेवाओं से परे कोई नया सुरक्षा संबंधी विचार नहीं: +स्ट्रीमिंग प्रतिक्रियाएं समान उपयोगकर्ता/संग्रह अलगाव का उपयोग करती हैं +प्रमाणीकरण या प्राधिकरण में कोई बदलाव नहीं +टुकड़े की सीमाएं संवेदनशील डेटा को उजागर नहीं करती हैं + +## प्रदर्शन संबंधी विचार + +**लाभ**: +कथित विलंबता में कमी (पहले टोकन तेजी से आते हैं) +लंबे उत्तरों के लिए बेहतर UX +कम मेमोरी उपयोग (पूरे उत्तर को बफर करने की आवश्यकता नहीं है) + +**संभावित चिंताएं**: +स्ट्रीमिंग प्रतिक्रियाओं के लिए अधिक Pulsar संदेश +टुकड़ा करने/कॉल बैक ओवरहेड के लिए थोड़ा अधिक CPU +स्ट्रीमिंग वैकल्पिक है, डिफ़ॉल्ट गैर-स्ट्रीमिंग रहता है, जिससे इसे कम किया जा सकता है + +**परीक्षण संबंधी विचार**: +बड़ी नॉलेज ग्राफ (कई त्रिगुण) के साथ परीक्षण करें +कई पुनर्प्राप्त दस्तावेज़ों के साथ परीक्षण करें +स्ट्रीमिंग बनाम गैर-स्ट्रीमिंग के ओवरहेड को मापें + +## परीक्षण रणनीति + +**इकाई परीक्षण**: +streaming=True/False के साथ GraphRag.query() का परीक्षण करें +streaming=True/False के साथ DocumentRag.query() का परीक्षण करें +कॉल बैक कार्यान्वयन को सत्यापित करने के लिए PromptClient को मॉक करें + +**एकीकरण परीक्षण**: +पूर्ण GraphRAG स्ट्रीमिंग प्रवाह का परीक्षण करें (मौजूदा एजेंट स्ट्रीमिंग परीक्षणों के समान) +पूर्ण DocumentRAG स्ट्रीमिंग प्रवाह का परीक्षण करें +गेटवे स्ट्रीमिंग अग्रेषण का परीक्षण करें +CLI स्ट्रीमिंग आउटपुट का परीक्षण करें + +**मैन्युअल परीक्षण**: +`tg-invoke-graph-rag -q "What is machine learning?"` (डिफ़ॉल्ट रूप से स्ट्रीमिंग) +`tg-invoke-document-rag -q "Summarize the documents about AI"` (डिफ़ॉल्ट रूप से स्ट्रीमिंग) +`tg-invoke-graph-rag --no-streaming -q "..."` (गैर-स्ट्रीमिंग मोड का परीक्षण करें) +सत्यापित करें कि स्ट्रीमिंग मोड में वृद्धिशील आउटपुट दिखाई दे रहा है + +## माइग्रेशन योजना + +माइग्रेशन की आवश्यकता नहीं: +`streaming` पैरामीटर (डिफ़ॉल्ट रूप से False) के माध्यम से स्ट्रीमिंग वैकल्पिक है +मौजूदा क्लाइंट अपरिवर्तित रहते हैं +नए क्लाइंट स्ट्रीमिंग को अपना सकते हैं + +## समयरेखा + +अनुमानित कार्यान्वयन: 4-6 घंटे +चरण 1 (2 घंटे): GraphRAG स्ट्रीमिंग समर्थन +चरण 2 (2 घंटे): DocumentRAG स्ट्रीमिंग समर्थन +चरण 3 (1-2 घंटे): गेटवे अपडेट और CLI ध्वज +परीक्षण: प्रत्येक चरण में शामिल + +## खुले प्रश्न + +क्या हमें NLP क्वेरी सेवा में भी स्ट्रीमिंग समर्थन जोड़ना चाहिए? +क्या हम केवल LLM आउटपुट या मध्यवर्ती चरणों (जैसे, "इकाइयों को पुनर्प्राप्त करना...", "ग्राफ को क्वेरी करना...") को स्ट्रीम करना चाहते हैं? +क्या GraphRAG/DocumentRAG प्रतिक्रियाओं में टुकड़े मेटाडेटा (जैसे, टुकड़े संख्या, कुल अपेक्षित) शामिल होना चाहिए? + +## संदर्भ + +मौजूदा कार्यान्वयन: `docs/tech-specs/streaming-llm-responses.md` +एजेंट स्ट्रीमिंग: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` +PromptClient स्ट्रीमिंग: `trustgraph-base/trustgraph/base/prompt_client.py` diff --git a/docs/tech-specs/rag-streaming-support.md b/docs/tech-specs/rag-streaming-support.md index ab5e12ab..6a205b19 100644 --- a/docs/tech-specs/rag-streaming-support.md +++ b/docs/tech-specs/rag-streaming-support.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "RAG Streaming Support Technical Specification" +parent: "Tech Specs" +--- + # RAG Streaming Support Technical Specification ## Overview diff --git a/docs/tech-specs/rag-streaming-support.pt.md b/docs/tech-specs/rag-streaming-support.pt.md new file mode 100644 index 00000000..9285044f --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.pt.md @@ -0,0 +1,296 @@ +--- +layout: default +title: "Especificação Técnica de Suporte a Streaming RAG" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Suporte a Streaming RAG + +> **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 a adição de suporte a streaming aos serviços GraphRAG e DocumentRAG, permitindo respostas em tempo real, token por token, para consultas de grafos de conhecimento e recuperação de documentos. Isso estende a arquitetura de streaming existente já implementada para serviços de preenchimento de texto, prompt e agente LLM. + +## Objetivos + +**Experiência de streaming consistente**: Fornecer a mesma experiência de streaming em todos os serviços TrustGraph. +**Alterações mínimas na API**: Adicionar suporte a streaming com um único sinalizador `streaming`, seguindo padrões estabelecidos. +**Compatibilidade com versões anteriores**: Manter o comportamento padrão existente sem streaming. +**Reutilizar infraestrutura existente**: Aproveitar o streaming do PromptClient já implementado. +**Suporte a gateway**: Permitir o streaming através do gateway WebSocket para aplicativos cliente. + +## Contexto + +Serviços de streaming atualmente implementados: +**Serviço de preenchimento de texto LLM**: Fase 1 - streaming de provedores LLM. +**Serviço de prompt**: Fase 2 - streaming através de modelos de prompt. +**Serviço de agente**: Fase 3-4 - streaming de respostas ReAct com fragmentos incrementais de pensamento/observação/resposta. + +Limitações atuais para serviços RAG: +GraphRAG e DocumentRAG suportam apenas respostas bloqueadas. +Os usuários devem esperar pela resposta completa do LLM antes de ver qualquer saída. +Má experiência do usuário para respostas longas de grafos de conhecimento ou consultas de documentos. +Experiência inconsistente em comparação com outros serviços TrustGraph. + +Esta especificação aborda essas lacunas adicionando suporte a streaming ao GraphRAG e ao DocumentRAG. Ao permitir respostas token por token, o TrustGraph pode: +Fornecer uma experiência de streaming consistente em todos os tipos de consulta. +Reduzir a latência percebida para consultas RAG. +Permitir um melhor feedback de progresso para consultas de longa duração. +Suportar a exibição em tempo real em aplicativos cliente. + +## Design Técnico + +### Arquitetura + +A implementação de streaming RAG aproveita a infraestrutura existente: + +1. **Streaming do PromptClient** (Já implementado) + `kg_prompt()` e `document_prompt()` já aceitam parâmetros `streaming` e `chunk_callback`. + Isso chama `prompt()` internamente com suporte a streaming. + Não são necessárias alterações no PromptClient. + + Módulo: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **Serviço GraphRAG** (Precisa de passagem de parâmetro de streaming) + Adicionar parâmetro `streaming` ao método `query()`. + Passar o sinalizador de streaming e os callbacks para `prompt_client.kg_prompt()`. + O esquema GraphRagRequest precisa do campo `streaming`. + + Módulos: + `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (Processador) + `trustgraph-base/trustgraph/schema/graph_rag.py` (Esquema de solicitação) + `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Gateway) + +3. **Serviço DocumentRAG** (Precisa de passagem de parâmetro de streaming) + Adicionar parâmetro `streaming` ao método `query()`. + Passar o sinalizador de streaming e os callbacks para `prompt_client.document_prompt()`. + O esquema DocumentRagRequest precisa do campo `streaming`. + + Módulos: + `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (Processador) + `trustgraph-base/trustgraph/schema/document_rag.py` (Esquema de solicitação) + `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Gateway) + +### Fluxo de Dados + +**Não streaming (atual)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + Complete response + ↓ +Client ← Gateway ← RAG Service ← Response +``` + +**Streaming (proposto):** +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + Chunk → callback → RAG Response (chunk) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── Response stream +``` + +### APIs + +**Alterações no GraphRAG**: + +1. **GraphRag.query()** - Adicionar parâmetros de streaming +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... existing entity/triple retrieval ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **Esquema GraphRagRequest** - Adicionar campo de streaming. +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **Esquema GraphRagResponse** - Adicionar campos de streaming (seguir o padrão do Agente). +```python +class GraphRagResponse(Record): + response = String() # Legacy: complete response + chunk = String() # NEW: streaming chunk + end_of_stream = Boolean() # NEW: indicates last chunk +``` + +4. **Processador** - Permitir a passagem de dados em fluxo contínuo. +```python +async def handle(self, msg): + # ... existing code ... + + async def send_chunk(chunk): + await self.respond(GraphRagResponse( + chunk=chunk, + end_of_stream=False, + response=None + )) + + if request.streaming: + full_response = await self.rag.query( + query=request.query, + user=request.user, + collection=request.collection, + streaming=True, + chunk_callback=send_chunk + ) + # Send final message + await self.respond(GraphRagResponse( + chunk=None, + end_of_stream=True, + response=full_response + )) + else: + # Existing non-streaming path + response = await self.rag.query(...) + await self.respond(GraphRagResponse(response=response)) +``` + +**Alterações no DocumentRAG:** + +Padrão idêntico ao GraphRAG: +1. Adicionar parâmetros `streaming` e `chunk_callback` a `DocumentRag.query()` +2. Adicionar campo `streaming` a `DocumentRagRequest` +3. Adicionar campos `chunk` e `end_of_stream` a `DocumentRagResponse` +4. Atualizar o Processador para lidar com streaming com callbacks + +**Alterações no Gateway:** + +Tanto `graph_rag.py` quanto `document_rag.py` no gateway/dispatch precisam de atualizações para encaminhar trechos de streaming para o websocket: + +```python +async def handle(self, message, session, websocket): + # ... existing code ... + + if request.streaming: + async def recipient(resp): + if resp.chunk: + await websocket.send(json.dumps({ + "id": message["id"], + "response": {"chunk": resp.chunk}, + "complete": resp.end_of_stream + })) + return resp.end_of_stream + + await self.rag_client.request(request, recipient=recipient) + else: + # Existing non-streaming path + resp = await self.rag_client.request(request) + await websocket.send(...) +``` + +### Detalhes de Implementação + +**Ordem de implementação**: +1. Adicionar campos de esquema (Request + Response para ambos os serviços RAG) +2. Atualizar os métodos GraphRag.query() e DocumentRag.query() +3. Atualizar Processadores para lidar com streaming +4. Atualizar manipuladores de despacho do Gateway +5. Adicionar `--no-streaming` flags a `tg-invoke-graph-rag` e `tg-invoke-document-rag` (streaming habilitado por padrão, seguindo o padrão da CLI do agente) + +**Padrão de callback**: +Seguir o mesmo padrão de callback assíncrono estabelecido no streaming do Agente: +O Processador define o `async def send_chunk(chunk)` callback +Passa o callback para o serviço RAG +O serviço RAG passa o callback para o PromptClient +O PromptClient invoca o callback para cada chunk do LLM +O Processador envia uma mensagem de resposta de streaming para cada chunk + +**Tratamento de erros**: +Erros durante o streaming devem enviar uma resposta de erro com `end_of_stream=True` +Seguir os padrões existentes de propagação de erros do streaming do Agente + +## Considerações de Segurança + +Não há novas considerações de segurança além dos serviços RAG existentes: +As respostas de streaming usam o mesmo isolamento de usuário/coleção +Não há alterações na autenticação ou autorização +Os limites de chunk não expõem dados sensíveis + +## Considerações de Desempenho + +**Benefícios**: +Latência percebida reduzida (os primeiros tokens chegam mais rápido) +Melhor experiência do usuário para respostas longas +Menor uso de memória (não é necessário armazenar em buffer a resposta completa) + +**Preocupações potenciais**: +Mais mensagens Pulsar para respostas de streaming +Ligeiramente maior uso de CPU para a sobrecarga de chunking/callback +Mitigado por: o streaming é opcional, o padrão permanece não-streaming + +**Considerações de teste**: +Testar com grafos de conhecimento grandes (muitos triplos) +Testar com muitos documentos recuperados +Medir a sobrecarga do streaming versus não-streaming + +## Estratégia de Teste + +**Testes unitários**: +Testar GraphRag.query() com streaming=True/False +Testar DocumentRag.query() com streaming=True/False +Simular o PromptClient para verificar as invocações de callback + +**Testes de integração**: +Testar o fluxo completo de streaming do GraphRAG (semelhante aos testes existentes de streaming do agente) +Testar o fluxo completo de streaming do DocumentRAG +Testar o encaminhamento de streaming do Gateway +Testar a saída de streaming da CLI + +**Testes manuais**: +`tg-invoke-graph-rag -q "What is machine learning?"` (streaming por padrão) +`tg-invoke-document-rag -q "Summarize the documents about AI"` (streaming por padrão) +`tg-invoke-graph-rag --no-streaming -q "..."` (testar o modo não-streaming) +Verificar se a saída incremental aparece no modo de streaming + +## Plano de Migração + +Nenhuma migração necessária: +O streaming é opcional por meio do parâmetro `streaming` (o padrão é Falso) +Os clientes existentes continuam a funcionar sem alterações +Novos clientes podem optar por usar o streaming + +## Cronograma + +Tempo estimado de implementação: 4-6 horas +Fase 1 (2 horas): suporte de streaming do GraphRAG +Fase 2 (2 horas): suporte de streaming do DocumentRAG +Fase 3 (1-2 horas): atualizações do Gateway e flags da CLI +Testes: integrados em cada fase + +## Perguntas Abertas + +Devemos adicionar suporte de streaming ao serviço de consulta NLP também? +Queremos transmitir etapas intermediárias (por exemplo, "Recuperando entidades...", "Consultando o grafo...") ou apenas a saída do LLM? +As respostas do GraphRAG/DocumentRAG devem incluir metadados do chunk (por exemplo, número do chunk, total esperado)? + +## Referências + +Implementação existente: `docs/tech-specs/streaming-llm-responses.md` +Streaming do Agente: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` +Streaming do PromptClient: `trustgraph-base/trustgraph/base/prompt_client.py` diff --git a/docs/tech-specs/rag-streaming-support.ru.md b/docs/tech-specs/rag-streaming-support.ru.md new file mode 100644 index 00000000..483f22dc --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.ru.md @@ -0,0 +1,180 @@ +--- +layout: default +title: "Техническая спецификация поддержки потоковой передачи для RAG" +parent: "Russian (Beta)" +--- + +# Техническая спецификация поддержки потоковой передачи для RAG + +> **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. + +## Обзор + +Эта спецификация описывает добавление поддержки потоковой передачи для сервисов GraphRAG и DocumentRAG, позволяя получать ответы по частям (токен за токеном) для запросов из графа знаний и документов. Это расширяет существующую архитектуру потоковой передачи, уже реализованную для LLM-сервисов для завершения текста, запросов и агентов. + +## Цели + +- **Консистентный UX потоковой передачи**: Обеспечить одинаковый опыт потоковой передачи для всех сервисов TrustGraph. +- **Минимальные изменения API**: Добавить поддержку потоковой передачи с помощью одного флага `streaming`, следуя установленным шаблонам. +- **Совместимость со старыми версиями**: Поддерживать существующее поведение без потоковой передачи по умолчанию. +- **Использование существующей инфраструктуры**: Использовать существующую функциональность потоковой передачи PromptClient. +- **Поддержка Gateways**: Включить потоковую передачу через websocket Gateway для клиентских приложений. + +## Предыстория + +Текущие сервисы, поддерживающие потоковую передачу: +- **Сервис завершения текста LLM**: Фаза 1 - потоковая передача от LLM-провайдеров. +- **Сервис запросов**: Фаза 2 - потоковая передача через шаблоны запросов. +- **Сервис агента**: Фазы 3-4 - потоковая передача ReAct с последовательными частями/данными/ответами. + +Текущие ограничения для сервисов RAG: +- GraphRAG и DocumentRAG поддерживают только не потоковые ответы. +- Пользователям необходимо ждать полного ответа LLM, прежде чем видеть какой-либо результат. +- Плохой UX для длинных ответов из запросов к графу знаний или документам. +- Несогласованный опыт по сравнению с другими сервисами TrustGraph. + +Эта спецификация решает эти проблемы, добавляя поддержку потоковой передачи для GraphRAG и DocumentRAG. Благодаря потоковой передаче по частям, TrustGraph может: +- Обеспечить консистентный UX потоковой передачи для всех типов запросов. +- Снизить воспринимаемую задержку для запросов RAG. +- Обеспечить лучший прогресс для длительных запросов. +- Поддерживать отображение в реальном времени в клиентских приложениях. + +## Технический дизайн + +### Архитектура + +Реализация потоковой передачи для RAG использует существующую инфраструктуру: + +1. **PromptClient Streaming** (Уже реализовано) + - `kg_prompt()` и `document_prompt()` уже принимают параметры `streaming` и `chunk_callback`. + - Эти вызывают `prompt()` с поддержкой потоковой передачи. + - Изменения не требуются для PromptClient. + + Модуль: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **Сервис GraphRAG** (Требуется передача параметра `streaming`) + - Добавить параметр `streaming` к методу `query()`. + - Передавать флаг `streaming` и обратные вызовы в `prompt_client.kg_prompt()`. + - Схема GraphRagRequest должна иметь поле `streaming`. + + Модули: + - `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + - `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (Обработчик) + - `trustgraph-base/trustgraph/schema/graph_rag.py` (Схема запроса) + - `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Gateway) + +3. **Сервис DocumentRAG** (Требуется передача параметра `streaming`) + - Добавить параметр `streaming` к методу `query()`. + - Передавать флаг `streaming` и обратные вызовы в `prompt_client.document_prompt()`. + - Схема DocumentRagRequest должна иметь поле `streaming`. + + Модули: + - `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + - `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (Обработчик) + - `trustgraph-base/trustgraph/schema/document_rag.py` (Схема запроса) + - `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Gateway) + +### Поток данных + +**Не потоковая передача (текущая)**: +``` +Клиент → Gateway → Сервис RAG → PromptClient.kg_prompt(streaming=False) + ↓ + Сервис запросов → LLM + ↓ + Полный ответ + ↓ +Клиент ← Gateway ← Сервис RAG ← Ответ +``` + +**Потоковая передача (предлагаемая)**: +``` +Клиент → Gateway → Сервис RAG → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Сервис запросов → LLM (streaming) + ↓ + Часть → обратный вызов → Ответ RAG (часть) + ↓ ↓ +Клиент ← Gateway ← ────────────────────────────────── Поток ответа +``` + +### API + +**Изменения для GraphRAG**: + +1. **GraphRag.query()** - Добавлены параметры потоковой передачи +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... существующая работа с сущностями/триплетами ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **GraphRagRequest schema** - Добавлен параметр `streaming` +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **GraphRagResponse schema** - Добавлены поля для потоковой передачи (следовать паттерну Agent) +```python +class GraphRagResponse(Record): + response = String() # Legacy: полный ответ + chunk = String() # NEW: часть для потоковой передачи + end_of_stream = Boolean() # NEW: указывает, что это последняя часть +``` + +4. **Обработчик** - Передача потоковой передачи +```python +async def handle(self, ...): + # ... существующий код ... + response = await self.query(...) + if response and streaming: + # ... логика для отправки части + else: + # ... логика для отправки полного ответа +``` + +**Изменения для DocumentRAG**: Аналогично GraphRAG. + +## График миграции + +Не требуется миграция: +- Поддержка потоковой передачи является опцией (по умолчанию отключена) +- Существующие клиенты продолжают работать без изменений. +- Новые клиенты могут включить поддержку потоковой передачи. + +## Сроки + +Оценка времени реализации: 4-6 часов +- Фаза 1 (2 часа): Поддержка потоковой передачи для GraphRAG. +- Фаза 2 (2 часа): Поддержка потоковой передачи для DocumentRAG. +- Фаза 3 (1-2 часа): Обновления Gateway и флаги командной строки. +- Тестирование: Встроено в каждую фазу. + +## Открытые вопросы + +- Должна ли также поддерживаться потоковая передача для сервиса NLP Query? +- Хотим ли мы передавать только выход LLM (например, "Извлечь сущности...", "Запрос к графу...") или только его? +- Должны ли ответы GraphRAG/DocumentRAG содержать метаданные части (например, номер части, общее количество)? + +## Ссылки + +- Существующая реализация: `docs/tech-specs/streaming-llm-responses.md` +- Потоковая передача LLM: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` +- Потоковая передача PromptClient: `trustgraph-base/trustgraph/base/prompt_client.py` diff --git a/docs/tech-specs/rag-streaming-support.sw.md b/docs/tech-specs/rag-streaming-support.sw.md new file mode 100644 index 00000000..c8d7339f --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.sw.md @@ -0,0 +1,296 @@ +--- +layout: default +title: "Vigezo vya Ufundi kwa Usaidizi wa Utiririshaji (Streaming)" +parent: "Swahili (Beta)" +--- + +# Vigezo vya Ufundi kwa Usaidizi wa Utiririshaji (Streaming) + +> **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 + +Vigezo hivi vinaelezea kuongeza usaidizi wa utiririshaji kwa huduma za GraphRAG na DocumentRAG, na hivyo kuruhusu majibu ya wakati halisi, token kwa token, kwa maswali ya chati ya maarifa na utafutaji wa nyaraka. Hii inaongeza usanifu uliopo wa utiririshaji ambao tayari umetumiwa kwa huduma za kukamilisha maandishi, matamshi, na wakala (agent) za LLM. + +## Lengo + +**Uzoefu sawa wa utiririshaji**: Kutoa uzoefu sawa wa utiririshaji katika huduma zote za TrustGraph. +**Mabadiliko madogo ya API**: Kuongeza usaidizi wa utiririshaji kwa bendera moja `streaming`, kufuata mifumo iliyopo. +**Ulinganifu na matumizi ya awali**: Kuhifadhi tabia ya sasa isiyo ya utiririshaji kama chaguo-msingi. +**Kutumia miundombinu iliyopo**: Kutumia utiririshaji wa PromptClient ambao tayari umetumiwa. +**Usaidizi wa lango (gateway)**: Kuruhusu utiririshaji kupitia lango la websocket kwa programu za wateja. + +## Asili + +Huduma za utiririshaji zilizotumiwa kwa sasa: +**Huduma ya kukamilisha maandishi ya LLM**: Awamu ya 1 - utiririshaji kutoka kwa watoa huduma wa LLM. +**Huduma ya matamshi**: Awamu ya 2 - utiririshaji kupitia vipatacho vya matamshi. +**Huduma ya wakala**: Awamu ya 3-4 - utiririshaji wa majibu ya ReAct kwa vipande vya hatua/angalifu/jibu. + +Mapungufu ya sasa kwa huduma za RAG: +GraphRAG na DocumentRAG zinaunga mkono tu majibu ya kukomesha. +Watumiaji lazima wasubiri majibu kamili ya LLM kabla ya kuona matokeo yoyote. +Uzoefu mbaya kwa majibu marefu kutoka kwa chati ya maarifa au maswali ya nyaraka. +Uzoefu usio sawa na huduma zingine za TrustGraph. + +Vigezo hivi vinashughulikia pengo hizi kwa kuongeza usaidizi wa utiririshaji kwa GraphRAG na DocumentRAG. Kwa kuruhusu majibu ya token kwa token, TrustGraph inaweza: +Kutoa uzoefu sawa wa utiririshaji kwa aina zote za maswali. +Kupunguza muda uliodhaniwa wa maswali ya RAG. +Kuruhusu maoni bora ya maendeleo kwa maswali yanayoendelea. +Kusaidia onyesho la wakati halisi katika programu za wateja. + +## Muundo wa Ufundi + +### Usanifu + +Utumiaji wa utiririshaji wa RAG hutumia miundombinu iliyopo: + +1. **Utiririshaji wa PromptClient** (Tayari umetumiwa) + `kg_prompt()` na `document_prompt()` tayari hupokea vigezo vya `streaming` na `chunk_callback`. + Haya huita `prompt()` ndani na usaidizi wa utiririshaji. + Hakuna mabadiliko yanayohitajika kwa PromptClient. + + Moduli: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **Huduma ya GraphRAG** (Inahitaji kupitisha parameter ya utiririshaji) + Ongeza parameter ya `streaming` kwa njia ya `query()`. + Pasa bendera ya utiririshaji na vipengele vya kurudisha (callbacks) kwa `prompt_client.kg_prompt()`. + Schema ya GraphRagRequest inahitaji sehemu ya `streaming`. + + Moduli: + `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (Mchakato) + `trustgraph-base/trustgraph/schema/graph_rag.py` (Schema ya ombi) + `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Lango) + +3. **Huduma ya DocumentRAG** (Inahitaji kupitisha parameter ya utiririshaji) + Ongeza parameter ya `streaming` kwa njia ya `query()`. + Pasa bendera ya utiririshaji na vipengele vya kurudisha (callbacks) kwa `prompt_client.document_prompt()`. + Schema ya DocumentRagRequest inahitaji sehemu ya `streaming`. + + Moduli: + `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (Mchakato) + `trustgraph-base/trustgraph/schema/document_rag.py` (Schema ya ombi) + `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Lango) + +### Mtiririko wa Data + +**Usiokuwa na utiririshaji (sasa)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + Complete response + ↓ +Client ← Gateway ← RAG Service ← Response +``` + +**Utiririshaji (kupendekezwa):** +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + Chunk → callback → RAG Response (chunk) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── Response stream +``` + +### API + +**Mabadiliko ya GraphRAG**: + +1. **GraphRag.query()** - Ongeza vigezo vya utiririshaji +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... existing entity/triple retrieval ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **Muundo wa GraphRagRequest** - Ongeza sehemu ya utiririshaji. +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **Muundo wa GraphRagResponse** - Ongeza sehemu za utiririshaji (fuata mfumo wa Wakala). +```python +class GraphRagResponse(Record): + response = String() # Legacy: complete response + chunk = String() # NEW: streaming chunk + end_of_stream = Boolean() # NEW: indicates last chunk +``` + +4. **Mchakato** - Ruhusu mtiririko kupita. +```python +async def handle(self, msg): + # ... existing code ... + + async def send_chunk(chunk): + await self.respond(GraphRagResponse( + chunk=chunk, + end_of_stream=False, + response=None + )) + + if request.streaming: + full_response = await self.rag.query( + query=request.query, + user=request.user, + collection=request.collection, + streaming=True, + chunk_callback=send_chunk + ) + # Send final message + await self.respond(GraphRagResponse( + chunk=None, + end_of_stream=True, + response=full_response + )) + else: + # Existing non-streaming path + response = await self.rag.query(...) + await self.respond(GraphRagResponse(response=response)) +``` + +**Mabadiliko ya DocumentRAG**: + +Muundo sawa na GraphRAG: +1. Ongeza vigezo `streaming` na `chunk_callback` kwenye `DocumentRag.query()` +2. Ongeza sehemu `streaming` kwenye `DocumentRagRequest` +3. Ongeza sehemu `chunk` na `end_of_stream` kwenye `DocumentRagResponse` +4. Sasisha Processor ili kushughulikia utiririshaji pamoja na arifa + +**Mabadiliko ya Gateway**: + +Zote `graph_rag.py` na `document_rag.py` katika gateway/dispatch zinahitaji sasisho ili kusambaza vipande vya utiririshaji hadi kwenye websocket: + +```python +async def handle(self, message, session, websocket): + # ... existing code ... + + if request.streaming: + async def recipient(resp): + if resp.chunk: + await websocket.send(json.dumps({ + "id": message["id"], + "response": {"chunk": resp.chunk}, + "complete": resp.end_of_stream + })) + return resp.end_of_stream + + await self.rag_client.request(request, recipient=recipient) + else: + # Existing non-streaming path + resp = await self.rag_client.request(request) + await websocket.send(...) +``` + +### Maelekezo ya Utendaji + +**Utaratibu wa utendaji**: +1. Ongeza sehemu za schema (Ombi + Jibu kwa huduma zote za RAG) +2. Sasisha mbinu za GraphRag.query() na DocumentRag.query() +3. Sasisha Wasindikaji ili kushughulikia utiririshaji +4. Sasisha vichakavu vya usambazaji +5. Ongeza `--no-streaming` bendera kwenye `tg-invoke-graph-rag` na `tg-invoke-document-rag` (utiririshaji umeanzishwa kwa chaguizi, kufuatia mtindo wa CLI ya wakala) + +**Mfumo wa kurudisha matokeo**: +Fuata mfumo sawa wa kurudisha matokeo wa async uliopo katika utiririshaji wa Wakala: +Wasindikaji hufafanua `async def send_chunk(chunk)` kurudisha matokeo +Hutuma kurudisha matokeo kwa huduma ya RAG +Huduma ya RAG hutuma kurudisha matokeo kwa PromptClient +PromptClient huita kurudisha matokeo kwa kila kipande cha LLM +Wasindikaji hutuma ujumbe wa utiririshaji wa jibu kwa kila kipande + +**Usimamizi wa makosa**: +Makosa wakati wa utiririshaji yanapaswa kutuma jibu la makosa na `end_of_stream=True` +Fuata mifumo iliyopo ya usambazaji wa makosa kutoka kwa utiririshaji wa Wakala + +## Masuala ya Usalama + +Hakuna masuala mapya ya usalama zaidi ya huduma zilizopo za RAG: +Majibu ya utiririshaji hutumia kutengwa sawa kwa mtumiaji/mkusanyiko +Hakuna mabadiliko ya uthibitishaji au idhini +Hifadhi za vipande hazifichui data nyeti + +## Masuala ya Utendaji + +**Faida**: +Kupunguza latensi iliyohisiwa (vipande vya kwanza vinakuja haraka) +Uzoefu bora wa mtumiaji kwa majibu marefu +Matumizi ya chini ya kumbukumbu (hakuna haja ya kuhifadhi jibu kamili) + +**Masuala yanayoweza kutokea**: +Ujumbe zaidi wa Pulsar kwa majibu ya utiririshaji +CPU kidogo ya juu kwa gharama ya vipande/kurudisha matokeo +Imepunguzwa na: utiririshaji ni chaguo, chaguo-msingi inabaki bila utiririshaji + +**Masuala ya upimaji**: +Pima na vielelezo vikubwa vya maarifa (triple nyingi) +Pima na hati nyingi zilizopatikana +Pima gharama ya utiririshaji dhidi ya utiririshaji usio na utiririshaji + +## Mkakati wa Upimaji + +**Majaribio ya kitengo**: +Pima GraphRag.query() na streaming=True/False +Pima DocumentRag.query() na streaming=True/False +Fanya PromptClient kuwa bandia ili kuhakikisha utendaji wa kurudisha matokeo + +**Majaribio ya ujumuu**: +Pima mtiririko kamili wa GraphRAG wa utiririshaji (sawa na majaribio ya sasa ya utiririshaji wa wakala) +Pima mtiririko kamili wa DocumentRAG wa utiririshaji +Pima usambazaji wa utiririshaji wa Gateway +Pima pato la utiririshaji la CLI + +**Upimaji wa mwongozo**: +`tg-invoke-graph-rag -q "What is machine learning?"` (utiririshaji kwa chaguizi) +`tg-invoke-document-rag -q "Summarize the documents about AI"` (utiririshaji kwa chaguizi) +`tg-invoke-graph-rag --no-streaming -q "..."` (pima hali ya utiririshaji usio na utiririshaji) +Hakikisha pato linaloongezwa linaonekana katika hali ya utiririshaji + +## Mpango wa Uhamisho + +Hakuna uhamishaji unaohitajika: +Utiririshaji ni chaguo kupitia parameter ya `streaming` (ina chaguizi kuwa Fele) +Wateja wenyewe wanaendelea kufanya kazi bila mabadiliko +Wateja wapya wanaweza kuchagua utiririshaji + +## Muda + +Muda uliokadiriwa wa utekelezaji: saa 4-6 +Awamu ya 1 (saa 2): Usaidizi wa utiririshaji wa GraphRAG +Awamu ya 2 (saa 2): Usaidizi wa utiririshaji wa DocumentRAG +Awamu ya 3 (saa 1-2): Madaisho ya Gateway na bendera za CLI +Upimaji: Umejumuishwa katika kila awamu + +## Maswali yaliyofunguliwa + +Je, tunapaswa kuongeza usaidizi wa utiririshaji kwa huduma ya NLP Query pia? +Je, tunataka kuonyesha hatua za kati (k.m., "Kupata vyombo vya habari...", "Kusahihisha grafu...") au tu pato la LLM? +Je, majibu ya GraphRAG/DocumentRAG yanapaswa kujumuisha metadata ya kipande (k.m., nambari ya kipande, jumla inayotarajiwa)? + +## Marejeleo + +Utekelezaji uliopo: `docs/tech-specs/streaming-llm-responses.md` +Utiririshaji wa Wakala: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` +PromptClient utiririshaji: `trustgraph-base/trustgraph/base/prompt_client.py` diff --git a/docs/tech-specs/rag-streaming-support.tr.md b/docs/tech-specs/rag-streaming-support.tr.md new file mode 100644 index 00000000..36e56b53 --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.tr.md @@ -0,0 +1,296 @@ +--- +layout: default +title: "RAG Akış Desteği Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# RAG Akış Desteği 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, GraphRAG ve DocumentRAG hizmetlerine akış desteği eklemeyi tanımlar. Bu, bilgi grafiği ve belge sorguları için gerçek zamanlı, token bazlı yanıtlar sağlar. Bu, LLM metin tamamlama, istem ve ajan hizmetleri için zaten uygulanan mevcut akış mimarisini genişletir. + +## Hedefler + +**Tutarlı akış kullanıcı deneyimi**: Tüm TrustGraph hizmetlerinde aynı akış deneyimini sağlayın. +**Minimum API değişiklikleri**: Akış desteğini, yerleşik kalıpları izleyerek tek bir `streaming` bayrağıyla ekleyin. +**Geriye dönük uyumluluk**: Mevcut, akış olmayan davranışı varsayılan olarak koruyun. +**Mevcut altyapıyı yeniden kullanın**: Zaten uygulanan PromptClient akışını kullanın. +**Gateway desteği**: İstemci uygulamaları için websocket gateway üzerinden akışı etkinleştirin. + +## Arka Plan + +Şu anda uygulanan akış hizmetleri: +**LLM metin tamamlama hizmeti**: 1. Aşama - LLM sağlayıcılardan akış. +**İstem hizmeti**: 2. Aşama - istem şablonları aracılığıyla akış. +**Ajan hizmeti**: 3.-4. Aşama - ReAct yanıtlarını, artımlı düşünce/gözlem/cevap parçalarıyla akış. + +RAG hizmetleri için mevcut sınırlamalar: +GraphRAG ve DocumentRAG yalnızca engellenen yanıtları destekler. +Kullanıcılar, herhangi bir çıktı görmeden önce LLM'den gelen tamamlanmış yanıtı beklemelidir. +Bilgi grafiği veya belge sorgularından gelen uzun yanıtlar için kötü kullanıcı deneyimi. +Diğer TrustGraph hizmetlerine kıyasla tutarsız deneyim. + +Bu özellik, GraphRAG ve DocumentRAG'a akış desteği ekleyerek bu boşlukları giderir. Token bazlı yanıtları etkinleştirerek, TrustGraph şunları yapabilir: +Tüm sorgu türleri için tutarlı bir akış kullanıcı deneyimi sağlayın. +RAG sorguları için algılanan gecikmeyi azaltın. +Uzun süren sorgular için daha iyi ilerleme geri bildirimi sağlayın. +İstemci uygulamalarında gerçek zamanlı görüntülemeyi destekleyin. + +## Teknik Tasarım + +### Mimari + +RAG akış uygulaması, mevcut altyapıyı kullanır: + +1. **PromptClient Akışı** (Zaten uygulandı) + `kg_prompt()` ve `document_prompt()` zaten `streaming` ve `chunk_callback` parametrelerini kabul eder. + Bunlar dahili olarak akış desteğiyle `prompt()`'ı çağırır. + PromptClient'ta herhangi bir değişiklik yapılmasına gerek yoktur. + + Modül: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **GraphRAG Hizmeti** (Akış parametresi geçişi gereklidir) + `query()` yöntemine `streaming` parametresini ekleyin. + Akış bayrağını ve geri çağırmaları `prompt_client.kg_prompt()`'a geçirin. + GraphRagRequest şemasının `streaming` alanına ihtiyacı vardır. + + Modüller: + `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (İşlemci) + `trustgraph-base/trustgraph/schema/graph_rag.py` (İstek şeması) + `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Gateway) + +3. **DocumentRAG Hizmeti** (Akış parametresi geçişi gereklidir) + `query()` yöntemine `streaming` parametresini ekleyin. + Akış bayrağını ve geri çağırmaları `prompt_client.document_prompt()`'a geçirin. + DocumentRagRequest şemasının `streaming` alanına ihtiyacı vardır. + + Modüller: + `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (İşlemci) + `trustgraph-base/trustgraph/schema/document_rag.py` (İstek şeması) + `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Gateway) + +### Veri Akışı + +**Engellenmeyen (mevcut)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + Complete response + ↓ +Client ← Gateway ← RAG Service ← Response +``` + +**Akış (önerilen)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + Chunk → callback → RAG Response (chunk) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── Response stream +``` + +### API'ler + +**GraphRAG Değişiklikleri**: + +1. **GraphRag.query()** - Akış parametreleri eklendi. +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... existing entity/triple retrieval ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **GraphRagRequest şeması** - Akış alanı ekleyin. +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **GraphRagResponse şeması** - Akış alanlarını ekleyin (Agent modelini takip edin). +```python +class GraphRagResponse(Record): + response = String() # Legacy: complete response + chunk = String() # NEW: streaming chunk + end_of_stream = Boolean() # NEW: indicates last chunk +``` + +4. **İşlemci** - Veriyi sürekli akış halinde ilet. +```python +async def handle(self, msg): + # ... existing code ... + + async def send_chunk(chunk): + await self.respond(GraphRagResponse( + chunk=chunk, + end_of_stream=False, + response=None + )) + + if request.streaming: + full_response = await self.rag.query( + query=request.query, + user=request.user, + collection=request.collection, + streaming=True, + chunk_callback=send_chunk + ) + # Send final message + await self.respond(GraphRagResponse( + chunk=None, + end_of_stream=True, + response=full_response + )) + else: + # Existing non-streaming path + response = await self.rag.query(...) + await self.respond(GraphRagResponse(response=response)) +``` + +**DocumentRAG Değişiklikleri**: + +GraphRAG ile aynı yapı: +1. `streaming` ve `chunk_callback` parametrelerini `DocumentRag.query()`'ye ekleyin. +2. `streaming` alanını `DocumentRagRequest`'e ekleyin. +3. `chunk` ve `end_of_stream` alanlarını `DocumentRagResponse`'ye ekleyin. +4. İşlemciyi, geri çağırmalarla akışı işleyebilecek şekilde güncelleyin. + +**Gateway Değişiklikleri**: + +Hem `graph_rag.py` hem de `document_rag.py`, gateway/dispatch içinde, akış parçacıklarını websocket'e iletebilmesi için güncellenmelidir: + +```python +async def handle(self, message, session, websocket): + # ... existing code ... + + if request.streaming: + async def recipient(resp): + if resp.chunk: + await websocket.send(json.dumps({ + "id": message["id"], + "response": {"chunk": resp.chunk}, + "complete": resp.end_of_stream + })) + return resp.end_of_stream + + await self.rag_client.request(request, recipient=recipient) + else: + # Existing non-streaming path + resp = await self.rag_client.request(request) + await websocket.send(...) +``` + +### Uygulama Detayları + +**Uygulama sırası**: +1. Şema alanlarını ekleyin (Hem RAG hizmetleri için İstek + Yanıt) +2. GraphRag.query() ve DocumentRag.query() yöntemlerini güncelleyin +3. Akışı işlemek için İşleyicileri güncelleyin +4. Ağ geçidi yönlendirme işleyicilerini güncelleyin +5. `--no-streaming` bayraklarını `tg-invoke-graph-rag` ve `tg-invoke-document-rag`'ye ekleyin (akış varsayılan olarak etkindir, ajan CLI kalıbını takip eder) + +**Geri çağırma kalıbı**: +Ajan akışında oluşturulan aynı asenkron geri çağırma kalıbını izleyin: +İşleyici, `async def send_chunk(chunk)` geri çağrısını tanımlar +Geri çağrıyı RAG hizmetine iletir +RAG hizmeti, geri çağrıyı PromptClient'a iletir +PromptClient, her LLM parçası için geri çağrıyı çağırır +İşleyici, her parça için akış yanıt mesajını gönderir + +**Hata işleme**: +Akış sırasında oluşan hatalar, `end_of_stream=True` ile hata yanıtı göndermelidir +Ajan akışından mevcut hata yayılım kalıplarını izleyin + +## Güvenlik Hususları + +Mevcut RAG hizmetlerinin ötesinde yeni güvenlik hususları yoktur: +Akış yanıtları, aynı kullanıcı/toplam izolasyonunu kullanır +Kimlik doğrulama veya yetkilendirmede herhangi bir değişiklik yoktur +Parça sınırları, hassas verileri ortaya çıkarmaz + +## Performans Hususları + +**Faydaları**: +Algılanan gecikmenin azaltılması (ilk belirteçler daha hızlı gelir) +Uzun yanıtlar için daha iyi kullanıcı deneyimi +Daha düşük bellek kullanımı (tam yanıtı tamponlamaya gerek yoktur) + +**Olası endişeler**: +Akış yanıtları için daha fazla Pulsar mesajı +Parçalama/geri çağırma ek yükü için biraz daha yüksek CPU +Akış, isteğe bağlıdır, varsayılan olarak akış etkin değildir, bu nedenle bu sorunlar hafifletilmiştir + +**Test hususları**: +Çok sayıda üçlü içeren büyük bilgi grafikleriyle test edin +Çok sayıda alınmış belgeyle test edin +Akışın ve akış dışı durumun ek yükünü ölçün + +## Test Stratejisi + +**Birim testleri**: +GraphRag.query()'yi streaming=True/False ile test edin +DocumentRag.query()'yi streaming=True/False ile test edin +Geri çağırma çağrılarını doğrulamak için PromptClient'ı taklit edin + +**Entegrasyon testleri**: +Tam GraphRAG akışını test edin (mevcut ajan akış testlerine benzer) +Tam DocumentRAG akışını test edin +Ağ geçidi akış yönlendirmesini test edin +CLI akış çıktısını test edin + +**Manuel testler**: +`tg-invoke-graph-rag -q "What is machine learning?"` (akış varsayılan olarak etkindir) +`tg-invoke-document-rag -q "Summarize the documents about AI"` (akış varsayılan olarak etkindir) +`tg-invoke-graph-rag --no-streaming -q "..."` (akış dışı modu test edin) +Akış modunda kademeli çıktının göründüğünü doğrulayın + +## Geçiş Planı + +Herhangi bir geçişe gerek yoktur: +Akış, `streaming` parametresi aracılığıyla isteğe bağlıdır (varsayılan olarak False) +Mevcut istemciler, herhangi bir değişiklik olmadan çalışmaya devam eder +Yeni istemciler, akışı kullanabilir + +## Zaman Çizelgesi + +Tahmini uygulama süresi: 4-6 saat +1. Aşama (2 saat): GraphRAG akış desteği +2. Aşama (2 saat): DocumentRAG akış desteği +3. Aşama (1-2 saat): Ağ geçidi güncellemeleri ve CLI bayrakları +Test: Her aşamaya entegre edilmiştir + +## Açık Sorular + +NLP Sorgu hizmetine de akış desteği eklemeli miyiz? +Ara adımları (örneğin, "Varlıkların alınması...", "Grafiğin sorgulanması...") mi yoksa sadece LLM çıktısını mı akışa vermeliyiz? +GraphRAG/DocumentRAG yanıtları, parça meta verilerini (örneğin, parça numarası, toplam beklenen) içermeli mi? + +## Referanslar + +Mevcut uygulama: `docs/tech-specs/streaming-llm-responses.md` +Ajan akışı: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` +PromptClient akışı: `trustgraph-base/trustgraph/base/prompt_client.py` diff --git a/docs/tech-specs/rag-streaming-support.zh-cn.md b/docs/tech-specs/rag-streaming-support.zh-cn.md new file mode 100644 index 00000000..16c50989 --- /dev/null +++ b/docs/tech-specs/rag-streaming-support.zh-cn.md @@ -0,0 +1,199 @@ +--- +layout: default +title: "RAG 实时支持技术规范" +parent: "Chinese (Beta)" +--- + +# RAG 实时支持技术规范 + +> **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. + +## 概述 + +本规范描述了为 GraphRAG 和 DocumentRAG 服务添加实时支持的方法,从而实现知识图谱和文档检索查询的实时分块响应。 这扩展了现有的实时架构,该架构已针对 LLM 文本补全、提示和代理服务实施。 + +## 目标 + +- **一致的实时体验**: 在所有 TrustGraph 服务中提供相同的时间体验 +- **最小的 API 更改**: 通过单个 `streaming` 标志添加实时支持,遵循已建立的模式 +- **保持现有兼容性**: 保持现有非实时行为作为默认 +- **重用现有基础设施**: 利用 PromptClient 现有的实时功能 +- **网关支持**: 通过 websocket 网关为客户端应用程序启用实时 + +## 背景 + +当前已实现的实时服务: +- **LLM 文本补全服务**: 第一阶段 - 从 LLM 提供商获取 +- **提示服务**: 第二阶段 - 通过提示模板进行流式传输 +- **代理服务**: 第三阶段 - 使用 ReAct 响应和分块的思考/观察/答案进行流式传输 + +RAG 服务的当前限制: +- GraphRAG 和 DocumentRAG 仅支持块响应 +- 用户必须等待 LLM 响应完成才能看到任何输出 +- 针对知识图谱或文档查询的较长响应给用户体验带来不便 +- 与其他 TrustGraph 服务相比,体验不一致 + +本规范通过为 GraphRAG 和 DocumentRAG 添加实时支持来解决这些问题。 通过实现分块响应,TrustGraph 可以: +- 在所有查询类型中提供一致的实时体验 +- 减少 RAG 查询的感知延迟 +- 允许长时间运行查询的更好进度反馈 +- 客户端应用程序支持实时显示 + +## 技术设计 + +### 架构 + +RAG 实时实现利用了现有的基础设施: + +1. **PromptClient 实时** (已实现) + - `kg_prompt()` 和 `document_prompt()` 已经接受 `streaming` 和 `chunk_callback` 参数 + - 这些调用 `prompt()` 内部,并启用实时功能 + - PromptClient 不需要任何更改 + + 模块: `trustgraph-base/trustgraph/base/prompt_client.py` + +2. **GraphRAG 服务** (需要传递实时参数) + - 将 `streaming` 参数添加到 `query()` 方法 + - 将实时标志和回调函数传递给 `prompt_client.kg_prompt()` + - GraphRagRequest 模式需要包含 `streaming` 字段 + + 模块: + - `trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py` + - `trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (处理器) + - `trustgraph-base/trustgraph/schema/graph_rag.py` (Request 模式) + - `trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (网关) + +3. **DocumentRAG 服务** (需要传递实时参数) + - 将 `streaming` 参数添加到 `query()` 方法 + - 将实时标志和回调函数传递给 `prompt_client.document_prompt()` + - DocumentRagRequest 模式需要包含 `streaming` 字段 + + 模块: + - `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` + - `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (处理器) + - `trustgraph-base/trustgraph/schema/document_rag.py` (Request 模式) + - `trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (网关) + +### 数据流 + +**非实时 (当前)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False) + ↓ + Prompt Service → LLM + ↓ + 完整响应 + ↓ +Client ← Gateway ← RAG Service ← Response +``` + +**实时 (提案)**: +``` +Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb) + ↓ + Prompt Service → LLM (streaming) + ↓ + 块 → 回调 → RAG 响应 (块) + ↓ ↓ +Client ← Gateway ← ────────────────────────────────── 响应流 +``` + +### API + +**GraphRAG 更改**: + +1. **GraphRag.query()** - 添加实时参数 +```python +async def query( + self, query, user, collection, + verbose=False, streaming=False, chunk_callback=None # NEW +): + # ... 现有实体/三元组检索 ... + + if streaming and chunk_callback: + resp = await self.prompt_client.kg_prompt( + query, kg, + streaming=True, + chunk_callback=chunk_callback + ) + else: + resp = await self.prompt_client.kg_prompt(query, kg) + + return resp +``` + +2. **GraphRagRequest 模式** - 添加实时字段 +```python +class GraphRagRequest(Record): + query = String() + user = String() + collection = String() + streaming = Boolean() # NEW +``` + +3. **GraphRagResponse 模式** - 添加实时字段 (遵循 Agent 模式) +```python +class GraphRagResponse(Record): + response = String() # Legacy: complete response + chunk = String() # NEW: streaming chunk + end_of_stream = Boolean() # NEW: indicates last chunk +``` + +4. **Processor** - 传递实时 +```python +async def handle(self, msg): + # ... 现有代码 ... + + async def send_chunk(chunk): + await self.respond(GraphRagResponse( + chunk=chunk, + end_of_stream=False, + response=None + )) + + if request.streaming: + full_response = await self.rag.query( + query=request.query, + user=request.user, + collection=request.collection, + streaming=True, + chunk_callback=send_chunk + ) + # 发送最终消息 + await self.respond(GraphRagResponse( + chunk=None, + end_of_stream=True, + response=full_response + )) + else: + # 现有非实时路径 + response = await self.rag.query(...) + await self.respond(GraphRagResponse(response=response)) +``` + +**DocumentRAG 更改**: + +与 GraphRAG 相同模式: +1. 将 `streaming` 和 `chunk_callback` 参数添加到 `DocumentRag.query()` +2. 将 `streaming` 字段添加到 `DocumentRagRequest` +3. 将 `streaming` 字段添加到 `DocumentRagResponse` + +### 时间线 + +估计实现时间:4-6 小时 +- 第一阶段 (2 小时): GraphRAG 实时支持 +- 第二阶段 (2 小时): DocumentRAG 实时支持 +- 第三阶段 (1-2 小时): 网关更新和 CLI 标志 +- 测试: 已包含在每个阶段 + +## 开放问题 + +- 是否应该为 NLP 查询服务添加实时支持? +- 我们是否只想要实时输出中间步骤 (例如 "检索实体..."、"查询图..."),还是也想要实时输出? +- GraphRAG/DocumentRAG 响应是否应该包含块元数据 (例如块编号、预期总数)? + +## 参考 + +- 现有实现: `docs/tech-specs/streaming-llm-responses.md` +- Agent 实时: `trustgraph-flow/trustgraph/agent/react/agent_manager.py` +- PromptClient 实时: `trustgraph-base/trustgraph/base/prompt_client.py` diff --git a/docs/tech-specs/schema-refactoring-proposal.ar.md b/docs/tech-specs/schema-refactoring-proposal.ar.md new file mode 100644 index 00000000..5de2f0f8 --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.ar.md @@ -0,0 +1,99 @@ +--- +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. + +## المشاكل الحالية + +1. **هيكل مسطح** - وجود جميع المخططات في مجلد واحد يجعل من الصعب فهم العلاقات +2. **مزيج من المعايير** - أنواع أساسية، كائنات مجال، وعقود واجهة برمجة تطبيقات كلها مدمجة معًا +3. **أسماء غير واضحة** - الملفات مثل "object.py"، "types.py"، "topic.py" لا تشير بوضوح إلى الغرض منها +4. **لا يوجد تباين واضح** - من الصعب معرفة ما يعتمد على ماذا + +## الهيكل المقترح + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # أنواع أساسية أولية مستخدمة في كل مكان +│ ├── __init__.py +│ ├── primitives.py # Error, Value, Triple, Field, RowSchema +│ ├── metadata.py # سجل البيانات الوصفية +│ └── topic.py # أدوات الموضوع +│ +├── knowledge/ # نماذج مجال المعرفة واستخراجها +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # Document, TextDocument, Chunk +│ ├── knowledge.py # أنواع استخراج المعرفة +│ ├── embeddings.py # جميع أنواع الاستعلامات المتعلقة بالاستعلام (تم نقلها من ملفات متعددة) +│ └── nlp.py # أنواع Definition, Topic, Relationship, Fact +│ +└── services/ # عقود طلب/استجابة الخدمة + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Tool requests/responses + ├── retrieval.py # GraphRAG, DocumentRAG queries/responses + ├── query.py # GraphEmbeddingsRequest/Response, DocumentEmbeddingsRequest/Response + ├── agent.py # Agent requests/responses + ├── flow.py # Flow requests/responses + ├── prompt.py # طلبات/استجابات خدمة Prompt + ├── config.py # خدمة التكوين + ├── library.py # خدمة المكتبة + └── lookup.py # خدمة البحث +``` + +## التغييرات الرئيسية + +1. **تنظيم هرمي** - فصل واضح بين الأنواع الأساسية، نماذج المعرفة، وعقود الخدمة +2. **أسماء أفضل**: + - `types.py` → `core/primitives.py` (الغرض أكثر وضوحًا) + - `object.py` → تقسيم بين الملفات المناسبة بناءً على المحتوى الفعلي + - `documents.py` → `knowledge/document.py` (فردي، متسق) + - `models.py` → `services/llm.py` (نوع النماذج أكثر وضوحًا) + - `prompt.py` → تقسيم: أجزاء الخدمة إلى `services/prompt.py`، أنواع البيانات إلى `knowledge/nlp.py` + +3. **تجميع منطقي**: + - جميع أنواع الاستعلامات مجمعة في `knowledge/embeddings.py` + - جميع العقود المتعلقة بالخدمة LLM في `services/llm.py` + - فصل واضح لزوجات الطلب/الاستجابة في دليل الخدمة + - تجميع أنواع استخراج المعرفة مع نماذج المعرفة الأخرى + +4. **وضوح الاعتماد**: + - الأنواع الأساسية ليس لها تبعيات + - تعتمد نماذج المعرفة فقط على الأساس + - يمكن أن تعتمد عقود الخدمة على كل من الأساس ونماذج المعرفة + +## فوائد الهجرة + +1. **سهولة التنقل** - يمكن للمطورين العثور بسرعة على ما يحتاجون إليه +2. **تحسين الوحدات** - حدود واضحة بين مختلف المعايير +3. **استيراد أبسط** - مسارات استيراد أكثر بديهية +4. **قابلية التوسع** - من السهل إضافة أنواع معرف أو خدمات جديدة دون تضييق + +## أمثلة على تغييرات الاستيراد + +```python +# قبل +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# بعد +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## ملاحظات التنفيذ + +1. الحفاظ على التوافق مع الإصدارات السابقة عن طريق الحفاظ على الاستيرادات في `__init__.py` الجذر +2. نقل الملفات تدريجيًا، مع تحديث الاستيرادات حسب الحاجة +3. ضع في اعتبارك إضافة `legacy.py` الذي يستورد كل شيء لفاصل زمني الانتقال +4. تحديث الوثائق لتعكس الهيكل الجديد + + + +[{"id": "1", "content": "Examination of the current schema directory structure", "status": "completed", "priority": "high"}, {"id": "2", "content": "Analyze schema files and their purposes", "status": "completed", "priority": "high"}, {"id": "3", "content": "Propose improved naming and structure", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.es.md b/docs/tech-specs/schema-refactoring-proposal.es.md new file mode 100644 index 00000000..63e530dc --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.es.md @@ -0,0 +1,99 @@ +--- +layout: default +title: "Propuesta de Refactorización del Directorio de Esquemas" +parent: "Spanish (Beta)" +--- + +# Propuesta de Refactorización del Directorio de Esquemas + +> **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. + +## Problemas Actuales + +1. **Estructura plana** - Tener todos los esquemas en un solo directorio dificulta la comprensión de las relaciones. +2. **Preocupaciones mixtas** - Tipos centrales, objetos de dominio y contratos de API mezclados. +3. **Nombres poco claros** - Archivos como "object.py", "types.py", "topic.py" no indican claramente su propósito. +4. **Sin capa clara** - No es fácil ver qué depende de qué. + +## Estructura Propuesta + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # Tipos primitivos centrales utilizados en todas partes +│ ├── __init__.py +│ ├── primitives.py # Error, Value, Triple, Field, RowSchema +│ ├── metadata.py # Registro de metadatos +│ └── topic.py # Utilitarios de tema +│ +├── knowledge/ # Modelos del dominio de conocimiento y extracción +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # Document, TextDocument, Chunk +│ ├── knowledge.py # Tipos de extracción de conocimiento +│ ├── embeddings.py # Todos los tipos relacionados con la incorporación (movidos de múltiples archivos) +│ └── nlp.py # Tipos de Definición, Tema, Relación, Hecho +│ +└── services/ # Contratos de solicitud/respuesta de servicios + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Solicitudes/respuestas de Herramientas + ├── retrieval.py # Consultas/respuestas de GraphRAG, DocumentRAG + ├── query.py # Consultas/respuestas de GraphEmbeddingsRequest, DocumentEmbeddingsRequest + ├── agent.py # Solicitudes/respuestas del agente + ├── flow.py # Solicitudes/respuestas de flujo + ├── prompt.py # Solicitudes/respuestas del servicio de prompt + ├── config.py # Servicio de configuración + ├── library.py # Servicio de bibliotecario + └── lookup.py # Servicio de búsqueda +``` + +## Cambios Clave + +1. **Organización jerárquica** - Separación clara entre tipos centrales, modelos de conocimiento y contratos de servicio. +2. **Nombres mejorados**: + - `types.py` → `core/primitives.py` (propósito más claro) + - `object.py` → Dividir entre archivos apropiados según el contenido real + - `documents.py` → `knowledge/document.py` (singular, consistente) + - `models.py` → `services/llm.py` (qué tipo de modelos) + - `prompt.py` → Dividir: partes del servicio a `services/prompt.py`, tipos de datos a `knowledge/nlp.py` + +3. **Agrupamiento lógico**: + - Todos los tipos de incorporación consolidados en `knowledge/embeddings.py` + - Todos los contratos de servicio relacionados con LLM en `services/llm.py` + - Separación clara de pares de solicitud/respuesta en el directorio de servicios + - Grupos de tipos de extracción de conocimiento con otros modelos de dominio de conocimiento + +4. **Claridad de dependencias**: + - Los tipos centrales no tienen dependencias + - Los modelos de conocimiento dependen solo de los centrales + - Los contratos de servicio pueden depender de los centrales y de los modelos de conocimiento + +## Beneficios de la Migración + +1. **Navegación más fácil** - Los desarrolladores pueden encontrar rápidamente lo que necesitan. +2. **Mejor modularidad** - Límites claros entre diferentes preocupaciones. +3. **Importaciones más simples** - Rutas de importación más intuitivas. +4. **Futurizable** - Fácil de agregar nuevos tipos de conocimiento o servicios sin desorden. + +## Cambios de Importación de Ejemplo + +```python +# Antes +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# Después +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## Notas de Implementación + +1. Mantener la compatibilidad hacia atrás manteniendo las importaciones en el `__init__.py` raíz. +2. Mover los archivos gradualmente, actualizando las importaciones según sea necesario. +3. Considerar agregar un `legacy.py` que importe todo para el período de transición. +4. Actualizar la documentación para reflejar la nueva estructura. + + + +[{"id": "1", "content": "Examinar la estructura actual del directorio de esquemas", "status": "completed", "priority": "high"}, {"id": "2", "content": "Analizar los archivos de esquema y sus propósitos", "status": "completed", "priority": "high"}, {"id": "3", "content": "Proponer una estructura y nombres mejorados", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.he.md b/docs/tech-specs/schema-refactoring-proposal.he.md new file mode 100644 index 00000000..785b6a3b --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.he.md @@ -0,0 +1,99 @@ +--- +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. **מבנה שטוח** - כל הסכימות במקום אחד מקשות על הבנת הקשרים +2. **שילוב דאגות** - סוגי ליבה, אובייקטים של תחום, וחוזים של API משולבים יחד +3. **שמות לא ברורים** - קבצים כמו "object.py", "types.py", "topic.py" לא מציינים בבירור את מטרתם +4. **ללא שכבות ברורות** - קשה לראות מה תלוי במה + +## מבנה מוצע + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # סוגי ליבה בסיסיים המשמשים בכל מקום +│ ├── __init__.py +│ ├── primitives.py # שגיאה, ערך, טריפל, שדה, סכימת שורה +│ ├── metadata.py # רשומת מטא-דאטה +│ └── topic.py # כלי לטיפול בנושאים +│ +├── knowledge/ # מודלים של תחום ידע ואיסוף +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # מסמך, TextDocument, חתיכה +│ ├── knowledge.py # סוגי איסוף ידע +│ ├── embeddings.py # כל סוגי הסתמכות הקשורים (הועברו מקבצים רבים) +│ └── nlp.py # סוגי הגדרה, נושא, קשר, עובדה +│ +└── services/ # חוזים של בקשות/תגובות שירות + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, בקשות/תגובות של כלי + ├── retrieval.py # שאילתות/תגובות של GraphRAG, DocumentRAG + ├── query.py # בקשות/תגובות של GraphEmbeddings, DocumentEmbeddings + ├── agent.py # בקשות/תגובות של סוכן + ├── flow.py # בקשות/תגובות של זרימה + ├── prompt.py # בקשות/תגובות של שירות בקשות + ├── config.py # שירות תצורה + ├── library.py # שירות ספרייה + └── lookup.py # שירות חיפוש +``` + +## שינויים מרכזיים + +1. **ארגון היררכי** - הפרדה ברורה בין סוגים ליבה, מודלים של ידע, וחוזים של שירות +2. **שמות טובים יותר**: + - `types.py` → `core/primitives.py` (מטרה ברורה יותר) + - `object.py` → פירוק בין קבצים מתאימים בהתאם לתוכן + - `documents.py` → `knowledge/document.py` (יחיד, עקבי) + - `models.py` → `services/llm.py` (סוגי מודלים ברורים יותר) + - `prompt.py` → פירוק: חלקי שירות ל- `services/prompt.py`, סוגי נתונים ל- `knowledge/nlp.py` + +3. **קבוצות לוגיות**: + - כל סוגי ההסתמכות הועברו ל- `knowledge/embeddings.py` + - כל חוזי השירות הקשורים ל-LLM ב- `services/llm.py` + - הפרדה ברורה של זוגות בקשות/תגובות בספריית השירותים + - סוגי איסוף ידע מקובצים עם מודלים אחרים של תחום ידע + +4. **בהירות תלות**: + - סוגים ליבה אין תלות + - מודלים של ידע תלויים רק בסוגים ליבה + - חוזי שירות יכולים להיות תלויים בשני סוגים ליבה ומודלים של ידע + +## יתרונות המעבר + +1. **ניווט קל יותר** - מפתחים יכולים למצוא במהירות את מה שהם צריכים +2. **מודולריות טובה יותר** - גבולות ברורים בין דאגות שונות +3. **ייבוא פשוט יותר** - מסלולי ייבוא אינטואיטיביים יותר +4. **עתידי** - קל להוסיף סוגי ידע חדשים או שירותים ללא בלבול + +## שינויים דוגמה לייבוא + +```python +# לפני +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# אחרי +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## הערות ליישום + +1. שמירה על תאימות אחורה על ידי שמירה על ייבוא ב- `__init__.py` +2. העברת קבצים בהדרגה, תוך עדכון ייבוא לפי הצורך +3. שקול להוסיף קובץ `legacy.py` שיבוא הכל עבור תקופת המעבר +4. עדכון תיעוד כדי לשקף את המבנה החדש + + + +[{"id": "1", "content": "להעריך את מבנה תיקיית הסכימה הנוכחי", "status": "completed", "priority": "high"}, {"id": "2", "content": "לנתח את הקבצים של הסכימה ולמטרות שלהם", "status": "completed", "priority": "high"}, {"id": "3", "content": "להציע מבנה ושמות טובים יותר", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.hi.md b/docs/tech-specs/schema-refactoring-proposal.hi.md new file mode 100644 index 00000000..950076d7 --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.hi.md @@ -0,0 +1,99 @@ +--- +layout: default +title: "पहले" +parent: "Hindi (Beta)" +--- + +## स्कीमा निर्देशिका का पुनर्गठन प्रस्ताव + +## वर्तमान मुद्दे + +1. **सममित संरचना** - सभी स्कीमा एक ही निर्देशिका में होने से उनके बीच के संबंधों को समझना मुश्किल हो जाता है +2. **विभिन्न चिंताएं** - कोर प्रकार, डोमेन ऑब्जेक्ट और एपीआई अनुबंध सभी एक साथ +3. **अस्पष्ट नामकरण** - फ़ाइलें जैसे "object.py", "types.py", "topic.py" स्पष्ट रूप से उनकी propósito नहीं दर्शाती हैं +4. **स्पष्ट परतें नहीं** - यह स्पष्ट नहीं है कि कौन सी चीज़ किससे जुड़ी है + +## प्रस्तावित संरचना + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # हर जगह उपयोग किए जाने वाले कोर मूल प्रकार +│ ├── __init__.py +│ ├── primitives.py # त्रुटि, मूल्य, त्रिक, फ़ील्ड, पंक्ति स्कीमा +│ ├── metadata.py # मेटाडेटा रिकॉर्ड +│ └── topic.py # विषय उपयोगिताएं +│ +├── knowledge/ # ज्ञान डोमेन मॉडल और निष्कर्षण +│ ├── __init__.py +│ ├── graph.py # एंटिटीसंदर्भ, एंटिटी एम्बेडिंग, त्रिक +│ ├── document.py # दस्तावेज़, टेक्स्टदस्तावेज़, टुकड़ा +│ ├── knowledge.py # ज्ञान निष्कर्षण प्रकार +│ ├── embeddings.py # सभी एम्बेडिंग संबंधित प्रकार (कई फ़ाइलों से स्थानांतरित) +│ └── nlp.py # परिभाषा, विषय, संबंध, तथ्य प्रकार +│ +└── services/ # सेवा अनुरोध/प्रतिक्रिया अनुबंध + ├── __init__.py + ├── llm.py # टेक्स्टकम्प्लीशन, एम्बेडिंग, टूल अनुरोध/प्रतिक्रिया + ├── retrieval.py # ग्राफ़RAG, दस्तावेज़RAG क्वेरी/प्रतिक्रिया + ├── query.py # ग्राफ़एम्बेडिंग अनुरोध/प्रतिक्रिया, दस्तावेज़एम्बेडिंग अनुरोध/प्रतिक्रिया + ├── agent.py # एजेंट अनुरोध/प्रतिक्रिया + ├── flow.py # फ़्लो अनुरोध/प्रतिक्रिया + ├── prompt.py # प्रॉम्प्ट सेवा अनुरोध/प्रतिक्रिया + ├── config.py # कॉन्फ़िगरेशन सेवा + ├── library.py # लाइब्रेरियन सेवा + └── lookup.py # लुकअप सेवा +``` + +## मुख्य परिवर्तन + +1. **पदानुक्रमित संगठन** - स्पष्ट विभाजन कोर प्रकारों, ज्ञान मॉडल और सेवा अनुबंधों के बीच +2. **बेहतर नामकरण**: + - `types.py` → `core/primitives.py` (अधिक स्पष्ट उद्देश्य) + - `object.py` → वास्तविक सामग्री के आधार पर उचित फ़ाइलों में विभाजित + - `documents.py` → `knowledge/document.py` (एकल, सुसंगत) + - `models.py` → `services/llm.py` (अधिक स्पष्ट रूप से किस प्रकार के मॉडल) + - `prompt.py` → विभाजित: सेवा भागों को `services/prompt.py` में, डेटा प्रकारों को `knowledge/nlp.py` में + +3. **तार्किक समूहीकरण**: + - सभी एम्बेडिंग प्रकारों को `knowledge/embeddings.py` में समेकित किया गया है + - सभी LLM-संबंधित सेवा अनुबंधों को `services/llm.py` में रखा गया है + - सेवाओं की निर्देशिका में अनुरोध/प्रतिक्रिया जोड़े का स्पष्ट विभाजन + - ज्ञान निष्कर्षण प्रकारों को अन्य ज्ञान डोमेन मॉडल के साथ समूहीकृत किया गया है + +4. **निर्भरता स्पष्टता**: + - कोर प्रकारों में कोई निर्भरता नहीं है + - ज्ञान मॉडल केवल कोर पर निर्भर होते हैं + - सेवा अनुबंध कोर और ज्ञान मॉडल दोनों पर निर्भर हो सकते हैं + +## माइग्रेशन के लाभ + +1. **आसान नेविगेशन** - डेवलपर्स आसानी से वह ढूंढ सकते हैं जिसकी उन्हें आवश्यकता है +2. **बेहतर मॉड्यूलरिटी** - विभिन्न चिंताओं के बीच स्पष्ट सीमाएं +3. **सरल आयात** - अधिक सहज आयात पथ +4. **भविष्य के लिए तैयार** - बिना किसी अव्यवस्था के, नई ज्ञान प्रकारों या सेवाओं को आसानी से जोड़ा जा सकता है + +## उदाहरण आयात परिवर्तन + +```python +# पहले + +> **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. +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# बाद में +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## कार्यान्वयन नोट्स + +1. मूल `__init__.py` में आयात को बनाए रखकर पिछड़े अनुकूलता बनाए रखें +2. धीरे-धीरे फ़ाइलों को स्थानांतरित करें, आवश्यक अनुसार आयात को अपडेट करें +3. एक `legacy.py` जोड़ने पर विचार करें जो एक संक्रमण अवधि के लिए सब कुछ आयात करता है +4. नए संरचना को दर्शाने के लिए दस्तावेज़ अपडेट करें + + + +[{"id": "1", "content": "वर्तमान स्कीमा निर्देशिका संरचना की जाँच करें", "status": "पूर्ण", "प्राथमिकता": "उच्च"}, {"id": "2", "content": "स्कीमा फ़ाइलों और उनके उद्देश्यों का विश्लेषण करें", "status": "पूर्ण", "प्राथमिकता": "उच्च"}, {"id": "3", "content": "बेहतर नामकरण और संरचना का प्रस्ताव", "status": "पूर्ण", "प्राथमिकता": "उच्च"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.md b/docs/tech-specs/schema-refactoring-proposal.md index 07265e6c..16c94296 100644 --- a/docs/tech-specs/schema-refactoring-proposal.md +++ b/docs/tech-specs/schema-refactoring-proposal.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Schema Directory Refactoring Proposal" +parent: "Tech Specs" +--- + # Schema Directory Refactoring Proposal ## Current Issues @@ -88,4 +94,4 @@ from trustgraph.schema.services import TextCompletionRequest -[{"id": "1", "content": "Examine current schema directory structure", "status": "completed", "priority": "high"}, {"id": "2", "content": "Analyze schema files and their purposes", "status": "completed", "priority": "high"}, {"id": "3", "content": "Propose improved naming and structure", "status": "completed", "priority": "high"}] \ No newline at end of file +[{"id": "1", "content": "Examine current schema directory structure", "status": "completed", "priority": "high"}, {"id": "2", "content": "Analyze schema files and their purposes", "status": "completed", "priority": "high"}, {"id": "3", "content": "Propose improved naming and structure", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.pt.md b/docs/tech-specs/schema-refactoring-proposal.pt.md new file mode 100644 index 00000000..70384033 --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.pt.md @@ -0,0 +1,99 @@ +--- +layout: default +title: "Proposta de Refatoração do Diretório de Esquemas" +parent: "Portuguese (Beta)" +--- + +# Proposta de Refatoração do Diretório de Esquemas + +> **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. + +## Problemas Atuais + +1. **Estrutura plana** - Todos os esquemas em um único diretório dificultam a compreensão das relações. +2. **Preocupações misturadas** - Tipos principais, objetos de domínio e contratos de API todos misturados. +3. **Nomenclatura pouco clara** - Arquivos como "object.py", "types.py", "topic.py" não indicam claramente seu propósito. +4. **Ausência de camadas claras** - Não é fácil ver o que depende do quê. + +## Estrutura Proposta + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # Core primitive types used everywhere +│ ├── __init__.py +│ ├── primitives.py # Error, Value, Triple, Field, RowSchema +│ ├── metadata.py # Metadata record +│ └── topic.py # Topic utilities +│ +├── knowledge/ # Knowledge domain models and extraction +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # Document, TextDocument, Chunk +│ ├── knowledge.py # Knowledge extraction types +│ ├── embeddings.py # All embedding-related types (moved from multiple files) +│ └── nlp.py # Definition, Topic, Relationship, Fact types +│ +└── services/ # Service request/response contracts + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Tool requests/responses + ├── retrieval.py # GraphRAG, DocumentRAG queries/responses + ├── query.py # GraphEmbeddingsRequest/Response, DocumentEmbeddingsRequest/Response + ├── agent.py # Agent requests/responses + ├── flow.py # Flow requests/responses + ├── prompt.py # Prompt service requests/responses + ├── config.py # Configuration service + ├── library.py # Librarian service + └── lookup.py # Lookup service +``` + +## Principais Alterações + +1. **Organização hierárquica** - Separação clara entre tipos principais, modelos de conhecimento e contratos de serviço. +2. **Melhores nomes:** + `types.py` → `core/primitives.py` (propósito mais claro) + `object.py` → Divisão entre arquivos apropriados com base no conteúdo real. + `documents.py` → `knowledge/document.py` (singular, consistente) + `models.py` → `services/llm.py` (mais claro que tipo de modelos) + `prompt.py` → Divisão: partes de serviço para `services/prompt.py`, tipos de dados para `knowledge/nlp.py` + +3. **Agrupamento lógico:** + Todos os tipos de incorporação consolidados em `knowledge/embeddings.py` + Todos os contratos de serviço relacionados a LLM em `services/llm.py` + Separação clara de pares de solicitação/resposta no diretório de serviços. + Tipos de extração de conhecimento agrupados com outros modelos de domínio de conhecimento. + +4. **Clareza das dependências:** + Tipos principais não têm dependências. + Modelos de conhecimento dependem apenas do núcleo. + Contratos de serviço podem depender tanto do núcleo quanto dos modelos de conhecimento. + +## Benefícios da Migração + +1. **Navegação mais fácil** - Os desenvolvedores podem encontrar rapidamente o que precisam. +2. **Melhor modularidade** - Limites claros entre diferentes aspectos. +3. **Importações mais simples** - Caminhos de importação mais intuitivos. +4. **Preparado para o futuro** - Fácil de adicionar novos tipos de conhecimento ou serviços sem causar desordem. + +## Exemplos de Alterações de Importação + +```python +# Before +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# After +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## Notas de Implementação + +1. Mantenha a compatibilidade com versões anteriores, mantendo as importações no diretório raiz `__init__.py`. +2. Mova os arquivos gradualmente, atualizando as importações conforme necessário. +3. Considere adicionar um `legacy.py` que importe tudo para o período de transição. +4. Atualize a documentação para refletir a nova estrutura. + + + +[{"id": "1", "content": "Examinar a estrutura de diretórios do esquema atual", "status": "completed", "priority": "high"}, {"id": "2", "content": "Analisar os arquivos de esquema e seus propósitos", "status": "completed", "priority": "high"}, {"id": "3", "content": "Propor nomenclatura e estrutura aprimoradas", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.ru.md b/docs/tech-specs/schema-refactoring-proposal.ru.md new file mode 100644 index 00000000..23cef82c --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.ru.md @@ -0,0 +1,99 @@ +--- +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. **Плоская структура** - Все схемы в одном каталоге затрудняют понимание взаимосвязей +2. **Смешанные задачи** - Ядро типов, объекты домена и контракты API смешаны вместе +3. **Неясное наименование** - Файлы, такие как "object.py", "types.py", "topic.py", не указывают четко их назначение +4. **Отсутствие четкого уровня** - Трудно понять, на что зависит что + +## Предлагаемая структура + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # Основные примитивные типы, используемые везде +│ ├── __init__.py +│ ├── primitives.py # Ошибка, Значение, Трипл, Поле, Схема строк +│ ├── metadata.py # Запись метаданных +│ └── topic.py # Утилиты для тем +│ +├── knowledge/ # Модели домена знаний и извлечение +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Триплы +│ ├── document.py # Документ, TextDocument, Chunk +│ ├── knowledge.py # Типы извлечения знаний +│ ├── embeddings.py # Все типы, связанные с встраиванием (перенесены из нескольких файлов) +│ └── nlp.py # Типы Определение, Тема, Отношение, Факты +│ +└── services/ # Контракты запросов/ответов сервисов + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Запросы/ответы инструментов + ├── retrieval.py # Запросы/ответы GraphRAG, DocumentRAG + ├── query.py # Запросы/ответы GraphEmbeddingsRequest/Response, DocumentEmbeddingsRequest/Response + ├── agent.py # Запросы/ответы агента + ├── flow.py # Запросы/ответы потока + ├── prompt.py # Запросы/ответы сервиса подсказок + ├── config.py # Конфигурационный сервис + ├── library.py # Сервис библиотека + └── lookup.py # Сервис поиска +``` + +## Ключевые изменения + +1. **Иерархическая организация** - Четкое разделение между основными типами, моделями знаний и контрактами сервисов +2. **Улучшенное наименование:** + - `types.py` → `core/primitives.py` (более четкое назначение) + - `object.py` → Разделение на соответствующие файлы на основе фактического содержимого + - `documents.py` → `knowledge/document.py` (одинаковое, согласованное) + - `models.py` → `services/llm.py` (более четко, какие модели) + - `prompt.py` → Разделение: части сервиса в `services/prompt.py`, типы данных в `knowledge/nlp.py` + +3. **Логическая группировка:** + - Все типы встраивания консолидированы в `knowledge/embeddings.py` + - Все контракты сервисов LLM в `services/llm.py` + - Четкое разделение пар запросов/ответов в каталоге сервисов + - Типы извлечения знаний сгруппированы с другими моделями домена знаний + +4. **Ясность зависимостей:** + - Основные типы не имеют зависимостей + - Модели знаний зависят только от основных + - Контракты сервисов могут зависеть как от основных, так и от моделей знаний + +## Преимущества миграции + +1. **Легче навигация** - Разработчики могут быстро найти то, что им нужно +2. **Улучшенная модульность** - Четкие границы между разными задачами +3. **Проще импорт** - Более интуитивные пути импорта +4. **Готовность к будущему** - Легко добавлять новые типы знаний или сервисы, не загромождая + +## Пример изменений импорта + +```python +# Изначально +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# После +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## Заметки по реализации + +1. Сохраняйте обратную совместимость, поддерживая импорт в корневом файле `__init__.py` +2. Перемещайте файлы постепенно, обновляя импорты по мере необходимости +3. Рассмотрите возможность добавления файла `legacy.py`, который импортирует всё для переходного периода +4. Обновите документацию, чтобы отразить новую структуру + + + +[{"id": "1", "content": "Оценить текущую структуру каталога схемы", "status": "completed", "priority": "high"}, {"id": "2", "content": "Проанализировать файлы схемы и их назначение", "status": "completed", "priority": "high"}, {"id": "3", "content": "Предложить улучшенное наименование и структуру", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.sw.md b/docs/tech-specs/schema-refactoring-proposal.sw.md new file mode 100644 index 00000000..28ab776a --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.sw.md @@ -0,0 +1,99 @@ +--- +layout: default +title: "Pendekezo la Urekebishaji wa Saraka ya Mfumo" +parent: "Swahili (Beta)" +--- + +# Pendekezo la Urekebishaji wa Saraka ya Mfumo + +> **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. + +## Masuala Yanayoendelea + +1. **Muundo tambarare** - Saraka moja inayokuwa na mifumo yote inafanya iwe ngumu kuelewa uhusiano. +2. **Mambo mchanganyikano** - Aina za msingi, vitu vya kikoa, na mikatiba ya API yote yamechanganywa. +3. **Majina yasiyo wazi** - Faili kama vile "object.py", "types.py", "topic.py" hazionyeshi wazi madhumuni yake. +4. **Hakuna tabaka wazi** - Haiwezekani kuona kwa urahisi nini kinategemea nini. + +## Muundo Ulio Pendekezwa + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # Core primitive types used everywhere +│ ├── __init__.py +│ ├── primitives.py # Error, Value, Triple, Field, RowSchema +│ ├── metadata.py # Metadata record +│ └── topic.py # Topic utilities +│ +├── knowledge/ # Knowledge domain models and extraction +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # Document, TextDocument, Chunk +│ ├── knowledge.py # Knowledge extraction types +│ ├── embeddings.py # All embedding-related types (moved from multiple files) +│ └── nlp.py # Definition, Topic, Relationship, Fact types +│ +└── services/ # Service request/response contracts + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Tool requests/responses + ├── retrieval.py # GraphRAG, DocumentRAG queries/responses + ├── query.py # GraphEmbeddingsRequest/Response, DocumentEmbeddingsRequest/Response + ├── agent.py # Agent requests/responses + ├── flow.py # Flow requests/responses + ├── prompt.py # Prompt service requests/responses + ├── config.py # Configuration service + ├── library.py # Librarian service + └── lookup.py # Lookup service +``` + +## Mabadiliko Muhimu + +1. **Mpangilio wa kimfumo** - Tofauti wazi kati ya aina kuu, modeli za maarifa, na mikatiba ya huduma. +2. **Majina bora zaidi**: + `types.py` → `core/primitives.py` (lengo lililoboreshwa) + `object.py` → Kugawanywa katika faili zinazofaa kulingana na yaliyomo halisi. + `documents.py` → `knowledge/document.py` (moja, thabiti) + `models.py` → `services/llm.py` (wazi zaidi ni aina gani ya modeli) + `prompt.py` → Kugawanywa: sehemu za huduma hadi `services/prompt.py`, aina za data hadi `knowledge/nlp.py` + +3. **Punguzo la mantiki**: + Aina zote za kuingiza zimeunganishwa katika `knowledge/embeddings.py` + Mikatiba yote ya huduma inayohusiana na LLM iko katika `services/llm.py` + Tofauti wazi ya jozi za ombi/jibu katika saraka ya huduma. + Aina za utoaji wa maarifa zimepangwa pamoja na modeli zingine za uwanja wa maarifa. + +4. **Ufafanuzi wa utegemezi**: + Aina kuu hazina utegemezi wowote. + Modeli za maarifa hutegemea tu aina kuu. + Mikatiba ya huduma inaweza kutegemea aina kuu na modeli za maarifa. + +## Faida za Uhamisho + +1. **Uramaji rahisi** - Wasanidi programu wanaweza kupata haraka kile wanachohitaji. +2. **Uunganishaji bora zaidi** - Mipaka wazi kati ya masuala tofauti. +3. **Uingizaji rahisi zaidi** - Njia za uingizaji ambazo ni za angavu zaidi. +4. **Inaweza kudumu kwa muda mrefu** - Rahisi kuongeza aina mpya za maarifa au huduma bila kusumbua. + +## Mfano wa Mabadiliko ya Uingizaji + +```python +# Before +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# After +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## Maelezo ya Utendaji + +1. Hakikisha utangamano wa zamani kwa kudumisha uingizaji wa faili katika sehemu kuu `__init__.py` +2. Hamisha faili hatua kwa hatua, na usasishe uingizaji wa faili kama inavyohitajika +3. Fikiria kuongeza `legacy.py` ambayo huingiza kila kitu kwa kipindi cha mpito +4. Sasisha nyaraka ili kuonyesha muundo mpya + + + +[{"id": "1", "content": "Fanyia uchunguzi muundo wa sasa wa saraka ya schema", "status": "imekamilika", "priority": "juu"}, {"id": "2", "content": "Changanua faili za schema na madhumuni yao", "status": "imekamilika", "priority": "juu"}, {"id": "3", "content": "Pendekeza jina na muundo uliobora", "status": "imekamilika", "priority": "juu"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.tr.md b/docs/tech-specs/schema-refactoring-proposal.tr.md new file mode 100644 index 00000000..f4c3e50c --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.tr.md @@ -0,0 +1,99 @@ +--- +layout: default +title: "Şema Dizini Yeniden Düzenleme Önerisi" +parent: "Turkish (Beta)" +--- + +# Şema Dizini Yeniden Düzenleme Önerisi + +> **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. + +## Mevcut Sorunlar + +1. **Düz yapı** - Tüm şemaların tek bir dizinde olması, ilişkileri anlamayı zorlaştırıyor. +2. **Karışık konular** - Temel tipler, alan nesneleri ve API sözleşmeleri bir arada bulunuyor. +3. **Belirsiz adlandırma** - "object.py", "types.py", "topic.py" gibi dosyalar, amaçlarını açıkça belirtmiyor. +4. **Açık katmanlama yok** - Neyin neye bağlı olduğunu kolayca görmek mümkün değil. + +## Önerilen Yapı + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # Core primitive types used everywhere +│ ├── __init__.py +│ ├── primitives.py # Error, Value, Triple, Field, RowSchema +│ ├── metadata.py # Metadata record +│ └── topic.py # Topic utilities +│ +├── knowledge/ # Knowledge domain models and extraction +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # Document, TextDocument, Chunk +│ ├── knowledge.py # Knowledge extraction types +│ ├── embeddings.py # All embedding-related types (moved from multiple files) +│ └── nlp.py # Definition, Topic, Relationship, Fact types +│ +└── services/ # Service request/response contracts + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Tool requests/responses + ├── retrieval.py # GraphRAG, DocumentRAG queries/responses + ├── query.py # GraphEmbeddingsRequest/Response, DocumentEmbeddingsRequest/Response + ├── agent.py # Agent requests/responses + ├── flow.py # Flow requests/responses + ├── prompt.py # Prompt service requests/responses + ├── config.py # Configuration service + ├── library.py # Librarian service + └── lookup.py # Lookup service +``` + +## Temel Değişiklikler + +1. **Hiyerarşik organizasyon** - Temel tipler, bilgi modelleri ve hizmet sözleşmeleri arasında net bir ayrım. +2. **Daha iyi adlandırma**: + `types.py` → `core/primitives.py` (daha açık amaç) + `object.py` → Gerçek içeriğe göre uygun dosyalara ayrım + `documents.py` → `knowledge/document.py` (tekil, tutarlı) + `models.py` → `services/llm.py` (hangi tür modeller olduğu daha açık) + `prompt.py` → Ayrım: hizmet kısımları `services/prompt.py`'e, veri tipleri `knowledge/nlp.py`'ye + +3. **Mantıksal gruplandırma**: + Tüm gömme türleri `knowledge/embeddings.py` içinde toplandı. + Tüm LLM ile ilgili hizmet sözleşmeleri `services/llm.py` içinde. + Hizmetler dizininde istek/yanıt çiftlerinin net bir şekilde ayrılması. + Bilgi çıkarma türleri, diğer bilgi alanı modelleriyle gruplandırıldı. + +4. **Bağımlılık netliği**: + Temel tiplerin hiçbir bağımlılığı yoktur. + Bilgi modelleri yalnızca temel bağımlılıklarına sahiptir. + Hizmet sözleşmeleri hem temel hem de bilgi modellerine bağımlı olabilir. + +## Geçiş Faydaları + +1. **Daha kolay gezinme** - Geliştiriciler ihtiyaç duyduklarını hızla bulabilir. +2. **Daha iyi modülerlik** - Farklı konular arasındaki sınırlar nettir. +3. **Daha basit içe aktarmalar** - Daha sezgisel içe aktarma yolları. +4. **Geleceğe yönelik** - Yeni bilgi türleri veya hizmetler eklemek, karmaşayı önleyecek şekilde kolaydır. + +## Örnek İçe Aktarma Değişiklikleri + +```python +# Before +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# After +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## Uygulama Notları + +1. Kök dizindeki `__init__.py` içindeki import'ları koruyarak geriye dönük uyumluluğu sağlayın. +2. Dosyaları kademeli olarak taşıyın ve gerektiğinde import'ları güncelleyin. +3. Geçiş dönemi için her şeyi import eden bir `legacy.py` eklemeyi düşünün. +4. Yeni yapıyı yansıtacak şekilde dokümantasyonu güncelleyin. + + + +[{"id": "1", "content": "Mevcut şema dizin yapısını inceleyin", "status": "tamamlandı", "priority": "yüksek"}, {"id": "2", "content": "Şema dosyalarını ve amaçlarını analiz edin", "status": "tamamlandı", "priority": "yüksek"}, {"id": "3", "content": "Geliştirilmiş adlandırma ve yapı önerin", "status": "tamamlandı", "priority": "yüksek"}] diff --git a/docs/tech-specs/schema-refactoring-proposal.zh-cn.md b/docs/tech-specs/schema-refactoring-proposal.zh-cn.md new file mode 100644 index 00000000..fa22e36a --- /dev/null +++ b/docs/tech-specs/schema-refactoring-proposal.zh-cn.md @@ -0,0 +1,99 @@ +--- +layout: default +title: "方案:Schema 目录重构" +parent: "Chinese (Beta)" +--- + +# 方案:Schema 目录重构 + +> **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. **扁平结构** - 所有 Schema 都位于同一目录下,难以理解它们之间的关系 +2. **混杂的关注点** - 核心类型、领域对象和 API 契约都混合在一起 +3. **不明确的命名** - 文件如 "object.py", "types.py", "topic.py" 并不能清晰地表明其用途 +4. **缺乏明确的层级** - 无法轻松地看出哪些依赖于哪些 + +## 建议的结构 + +``` +trustgraph-base/trustgraph/schema/ +├── __init__.py +├── core/ # 核心基本类型,在所有地方使用 +│ ├── __init__.py +│ ├── primitives.py # Error, Value, Triple, Field, RowSchema +│ ├── metadata.py # 元数据记录 +│ └── topic.py # Topic 工具 +│ +├── knowledge/ # 知识领域模型和提取 +│ ├── __init__.py +│ ├── graph.py # EntityContext, EntityEmbeddings, Triples +│ ├── document.py # Document, TextDocument, Chunk +│ ├── knowledge.py # 知识提取类型 +│ ├── embeddings.py # 所有与嵌入相关的类型(从多个文件中移动) +│ └── nlp.py # Definition, Topic, Relationship, Fact 类型 +│ +└── services/ # 服务请求/响应契约 + ├── __init__.py + ├── llm.py # TextCompletion, Embeddings, Tool 请求/响应 + ├── retrieval.py # GraphRAG, DocumentRAG 查询/响应 + ├── query.py # GraphEmbeddingsRequest/Response, DocumentEmbeddingsRequest/Response + ├── agent.py # Agent 请求/响应 + ├── flow.py # Flow 请求/响应 + ├── prompt.py # Prompt 服务请求/响应 + ├── config.py # 配置服务 + ├── library.py # 库服务 + └── lookup.py # 查找服务 +``` + +## 关键变更 + +1. **分层组织** - 清晰地将核心类型、知识模型和服务契约分开 +2. **更好的命名**: + - `types.py` → `core/primitives.py` (更清晰的用途) + - `object.py` → 根据实际内容将文件拆分 + - `documents.py` → `knowledge/document.py` (单数,一致) + - `models.py` → `services/llm.py` (更清晰地表明模型类型) + - `prompt.py` → 拆分:服务部分到 `services/prompt.py`,数据类型到 `knowledge/nlp.py` + +3. **逻辑分组**: + - 所有嵌入类型集中在 `knowledge/embeddings.py` + - 所有与 LLM 相关的服务契约在 `services/llm.py` + - 在 services 目录中明确区分请求/响应对 + - 知识提取类型与其它知识领域模型分组 + +4. **依赖关系清晰**: + - 核心类型没有依赖 + - 知识模型仅依赖核心 + - 服务契约可以依赖核心和知识模型 + +## 迁移的好处 + +1. **更轻松的导航** - 开发者可以快速找到所需的内容 +2. **更好的模块化** - 区分不同关注点更清晰 +3. **更简单的导入** - 更有意义的导入路径 +4. **更具未来性** - 轻松添加新的知识类型或服务,而无需增加混乱 + +## 示例导入变更 + +```python +# 之前 +from trustgraph.schema import Error, Triple, GraphEmbeddings, TextCompletionRequest + +# 之后 +from trustgraph.schema.core import Error, Triple +from trustgraph.schema.knowledge import GraphEmbeddings +from trustgraph.schema.services import TextCompletionRequest +``` + +## 实施说明 + +1. 通过在根的 `__init__.py` 中保持导入,保持与以前的兼容性 +2. 逐步移动文件,并在需要时更新导入 +3. 考虑添加一个 `legacy.py`,用于在过渡期间导入所有内容 +4. 更新文档以反映新的结构 + + + +[{"id": "1", "content": "检查当前 Schema 目录结构", "status": "completed", "priority": "high"}, {"id": "2", "content": "分析 Schema 文件及其用途", "status": "completed", "priority": "high"}, {"id": "3", "content": "提出改进的命名和结构", "status": "completed", "priority": "high"}] diff --git a/docs/tech-specs/sparql-query.md b/docs/tech-specs/sparql-query.md index 97e7e115..88241125 100644 --- a/docs/tech-specs/sparql-query.md +++ b/docs/tech-specs/sparql-query.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "SPARQL Query Service Technical Specification" +parent: "Tech Specs" +--- + # SPARQL Query Service Technical Specification ## Overview diff --git a/docs/tech-specs/streaming-llm-responses.ar.md b/docs/tech-specs/streaming-llm-responses.ar.md new file mode 100644 index 00000000..d15f0ab5 --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.ar.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "المواصفات الفنية لخدمة بث استجابات نماذج اللغة الكبيرة (LLM)" +parent: "Arabic (Beta)" +--- + +# المواصفات الفنية لخدمة بث استجابات نماذج اللغة الكبيرة (LLM) + +> **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. يتيح البث التسليم في الوقت الفعلي للرموز (tokens) أثناء إنتاجها بواسطة نموذج اللغة الكبيرة، بدلاً من الانتظار حتى اكتمال توليد الاستجابة. + +يدعم هذا التنفيذ حالات الاستخدام التالية: + + +1. **واجهات مستخدم في الوقت الفعلي**: بث الرموز إلى واجهة المستخدم أثناء إنشائها، مما يوفر ملاحظات مرئية فورية. + +2. **تقليل وقت ظهور الرمز الأول**: يرى المستخدمون الإخراج على الفور بدلاً من الانتظار حتى اكتمال التوليد. + +3. **التعامل مع الاستجابات الطويلة**: التعامل مع المخرجات الطويلة جدًا التي قد تتسبب خلاف ذلك في انتهاء المهلة أو تجاوز حدود الذاكرة. + +4. **التطبيقات التفاعلية**: تمكين واجهات الدردشة والوكلاء المستجيبة. + +## الأهداف + + +**التوافق مع الإصدارات السابقة**: تستمر العملاء الحاليون الذين لا يستخدمون البث في العمل دون تعديل. + + **تصميم واجهة برمجة تطبيقات (API) متسق**: يستخدم البث والواجهات غير المتدفقة نفس أنماط المخططات مع اختلافات قليلة. + + **مرونة مزود الخدمة**: دعم البث عند توفره، مع توفير آلية بديلة سلسة عند عدم توفره. + + **التطبيق المرحلي**: تطبيق تدريجي لتقليل المخاطر. + +**دعم شامل**: دعم البث من مزود نموذج اللغة الكبيرة إلى تطبيقات العميل عبر Pulsar و Gateway API و Python API. + +## الخلفية + +### البنية الحالية + + +تعمل عملية إكمال النص الحالية لنماذج اللغة الكبيرة على النحو التالي: + +1. يرسل العميل `TextCompletionRequest` مع حقول `system` و `prompt`. +2. تعالج خدمة نموذج اللغة الكبيرة الطلب وتنتظر اكتمال التوليد. +3. يتم إرجاع `TextCompletionResponse` واحد مع سلسلة `response` كاملة. + +المخطط الحالي (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### القيود الحالية + +**زمن الوصول (Latency)**: يجب على المستخدمين الانتظار حتى اكتمال الإنشاء قبل رؤية أي نتيجة. +**خطر انتهاء المهلة (Timeout)**: قد تتجاوز عمليات الإنشاء الطويلة حدود انتهاء المهلة الخاصة بالعميل. +**تجربة مستخدم سيئة (Poor UX)**: عدم وجود أي ملاحظات أثناء الإنشاء يخلق انطباعًا بالبطء. +**استخدام الموارد (Resource Usage)**: يجب تخزين الاستجابات الكاملة في الذاكرة. + +تعالج هذه المواصفات هذه القيود من خلال تمكين التسليم التدريجي للاستجابة مع الحفاظ على التوافق الكامل مع الإصدارات السابقة. + + +## التصميم التقني + +### المرحلة الأولى: البنية التحتية + +تضع المرحلة الأولى الأساس للبث عن طريق تعديل المخططات وواجهات برمجة التطبيقات (APIs) وأدوات سطر الأوامر (CLI). + + +#### تغييرات المخططات + +##### مخطط LLM (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**تغييرات الطلبات:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: عندما `true`، يتم طلب تسليم الاستجابة بتدفق. +الافتراضي: `false` (يتم الحفاظ على السلوك الحالي). + +**تغييرات في الاستجابة:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: عندما `true`، يشير هذا إلى أن هذا هو الرد النهائي (أو الوحيد). +للطلبات غير المتدفقة: رد واحد مع `end_of_stream=true`. +للطلبات المتدفقة: ردود متعددة، جميعها مع `end_of_stream=false`. + باستثناء الرد النهائي. + +##### مخطط المطالبة (`trustgraph-base/trustgraph/schema/services/prompt.py`). + +خدمة المطالبة تغلف إكمال النص، وبالتالي فهي تعكس نفس النمط: + +**تغييرات الطلب:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**التغييرات في الاستجابة:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### التغييرات في واجهة برمجة التطبيقات (API) الخاصة بالبوابة. + +يجب أن تعرض واجهة برمجة التطبيقات (API) الخاصة بالبوابة إمكانات البث لعملاء HTTP/WebSocket. + +**تحديثات واجهة برمجة التطبيقات (API) REST:** + +`POST /api/v1/text-completion`: قبول المعامل `streaming` في نص الطلب. +يعتمد سلوك الاستجابة على علامة البث: + `streaming=false`: استجابة JSON واحدة (السلوك الحالي). + `streaming=true`: تدفق أحداث من الخادم (SSE) أو رسائل WebSocket. + +**تنسيق الاستجابة (البث):** + +يتبع كل جزء مُبث نفس هيكل المخطط. +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +الجزء الأخير: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### تغييرات في واجهة برمجة التطبيقات (API) الخاصة بـ Python + +يجب أن تدعم واجهة برمجة التطبيقات (API) الخاصة بعميل Python كلاً من الأوضاع المتدفقة وغير المتدفقة +مع الحفاظ على التوافق مع الإصدارات السابقة. + +**تحديثات لـ LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**تحديثات PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +نمط مشابه مع المعامل `streaming` وإصدار مولد غير متزامن. + +#### تغييرات في أداة سطر الأوامر + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +تفعيل البث افتراضيًا لتحسين تجربة المستخدم التفاعلية. +العلم `--no-streaming` يعطل البث. +عند تفعيل البث: إخراج الرموز إلى الإخراج القياسي (stdout) فور وصولها. +عند عدم تفعيل البث: الانتظار حتى اكتمال الاستجابة، ثم إخراجها. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +نفس النمط مثل `tg-invoke-llm`. + +#### تغييرات في الفئة الأساسية لخدمة نماذج اللغة الكبيرة (LLM). + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### المرحلة الثانية: إثبات المفهوم لـ VertexAI + +تنفذ المرحلة الثانية البث في مزود واحد (VertexAI) للتحقق من صحة +البنية التحتية وتمكين الاختبار الشامل. + +#### تنفيذ VertexAI + +**الوحدة:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**التغييرات:** + +1. تجاوز `supports_streaming()` لإرجاع `True` +2. تنفيذ مُولّد غير متزامن `generate_content_stream()` +3. التعامل مع نماذج Gemini و Claude (عبر واجهة برمجة تطبيقات VertexAI Anthropic) + +**البث باستخدام Gemini:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**كلود (عبر VertexAI من شركة Anthropic) - البث:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### الاختبار + +اختبارات الوحدة لتجميع الاستجابات المتدفقة. +اختبارات التكامل مع VertexAI (Gemini و Claude). +اختبارات شاملة: سطر الأوامر -> البوابة -> Pulsar -> VertexAI -> العودة. +اختبارات التوافق مع الإصدارات السابقة: لا تزال طلبات عدم التدفق تعمل. + +-- + +### المرحلة الثالثة: جميع مزودي نماذج اللغة الكبيرة + +تمتد المرحلة الثالثة لدعم التدفق إلى جميع مزودي نماذج اللغة الكبيرة في النظام. + +#### حالة تنفيذ المزود + +يجب على كل مزود إما: +1. **دعم كامل للتدفق**: تنفيذ `generate_content_stream()` +2. **وضع التوافق**: التعامل مع علامة `end_of_stream` بشكل صحيح + (إرجاع استجابة واحدة مع `end_of_stream=true`) + +| المزود | الحزمة | دعم التدفق | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| Claude/Anthropic | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| Ollama | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| Cohere | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| Mistral | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| Azure OpenAI | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| Google AI Studio | trustgraph-flow | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| VertexAI | trustgraph-vertexai | كامل (المرحلة الثانية) | +| Bedrock | trustgraph-bedrock | كامل (واجهة برمجة تطبيقات تدفق أصلية) | +| LM Studio | trustgraph-flow | كامل (متوافق مع OpenAI) | +| LlamaFile | trustgraph-flow | كامل (متوافق مع OpenAI) | +| vLLM | trustgraph-flow | كامل (متوافق مع OpenAI) | +| TGI | trustgraph-flow | قيد التحديد | +| Azure | trustgraph-flow | قيد التحديد | + +#### نمط التنفيذ + +بالنسبة لمزودي نماذج اللغة الكبيرة المتوافقين مع OpenAI (OpenAI، LM Studio، LlamaFile، vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### المرحلة الرابعة: واجهة برمجة التطبيقات (API) للوكيل + +المرحلة الرابعة توسع البث ليشمل واجهة برمجة التطبيقات (API) للوكيل. هذا أكثر تعقيدًا لأن +واجهة برمجة التطبيقات (API) للوكيل هي بالفعل متعددة الرسائل بطبيعتها (فكرة ← إجراء ← ملاحظة +← تكرار ← إجابة نهائية). + +#### مخطط الوكيل الحالي + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### التغييرات المقترحة في مخطط الوكيل. + +**طلب التغييرات:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**التغييرات في الاستجابة:** + +ينتج الوكيل أنواعًا متعددة من المخرجات خلال دورة التفكير الخاصة به: +الأفكار (التفكير) +الإجراءات (استدعاءات الأدوات) +الملاحظات (نتائج الأدوات) +الإجابة (الاستجابة النهائية) +الأخطاء + +نظرًا لأن `chunk_type` يحدد نوع المحتوى الذي يتم إرساله، يمكن دمج الحقول المنفصلة +`answer`، `error`، `thought`، و `observation` في +حقل واحد وهو `content`: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**المعاني الدلالية للحقول:** + +`chunk_type`: يشير إلى نوع المحتوى الموجود في حقل `content`. + `"thought"`: تفكير/استنتاج الوكيل. + `"action"`: الأداة/الإجراء المستخدم. + `"observation"`: النتيجة من تنفيذ الأداة. + `"answer"`: الإجابة النهائية لسؤال المستخدم. + `"error"`: رسالة الخطأ. + +`content`: المحتوى المتدفق الفعلي، والذي يتم تفسيره بناءً على `chunk_type`. + +`end_of_message`: عندما `true`، يكون نوع الجزء الحالي مكتملًا. + مثال: تم إرسال جميع الرموز الخاصة بالتفكير الحالي. + يسمح للعملاء بمعرفة متى ينتقلون إلى المرحلة التالية. + +`end_of_dialog`: عندما `true`، يكون التفاعل بأكمله مع الوكيل قد اكتمل. + هذه هي الرسالة الأخيرة في التدفق. + +#### سلوك التدفق الخاص بالوكيل + +عندما `streaming=true`: + +1. **تدفق الأفكار:** + أجزاء متعددة مع `chunk_type="thought"`، `end_of_message=false`. + الجزء الأخير من التفكير يحتوي على `end_of_message=true`. +2. **إشعار الإجراء:** + جزء واحد مع `chunk_type="action"`، `end_of_message=true`. +3. **الملاحظة:** + جزء (أجزاء) مع `chunk_type="observation"`، والجزء الأخير يحتوي على `end_of_message=true`. +4. **كرر** الخطوات من 1 إلى 3 أثناء قيام الوكيل بالتفكير. +5. **الإجابة النهائية:** + `chunk_type="answer"` مع الإجابة النهائية في `content`. + الجزء الأخير يحتوي على `end_of_message=true`، `end_of_dialog=true`. + +**تسلسل التدفق النموذجي:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +عندما `streaming=false`: +الحفاظ على السلوك الحالي +استجابة واحدة مع إجابة كاملة +`end_of_message=true`، `end_of_dialog=true` + +#### بوابة وواجهة برمجة تطبيقات بايثون + +البوابة: نقطة نهاية SSE/WebSocket جديدة لبث الوكيل +واجهة برمجة تطبيقات بايثون: طريقة مُولِّد غير متزامن جديدة `agent_stream()` + +-- + +## اعتبارات الأمان + +**لا توجد نقاط ضعف جديدة**: يستخدم البث نفس آليات المصادقة/التفويض +**تحديد المعدل**: تطبيق حدود معدل لكل رمز أو لكل جزء إذا لزم الأمر +**معالجة الاتصال**: إنهاء التدفقات بشكل صحيح عند قطع اتصال العميل +**إدارة المهلة الزمنية**: تحتاج طلبات البث إلى معالجة مناسبة للمهلة الزمنية + +## اعتبارات الأداء + +**الذاكرة**: يقلل البث من استخدام الذاكرة القصوى (بدون تخزين مؤقت للاستجابة الكاملة) +**زمن الوصول**: تم تقليل زمن الوصول إلى الرمز الأول بشكل كبير +**نفقات الاتصال**: تحتوي اتصالات SSE/WebSocket على نفقات صيانة الاتصال +**إنتاجية بولسار**: رسائل صغيرة متعددة مقابل رسالة كبيرة واحدة + مقايضة + +## استراتيجية الاختبار + +### اختبارات الوحدة +تسلسل/إلغاء تسلسل المخطط مع الحقول الجديدة +التوافق مع الإصدارات السابقة (تستخدم الحقول المفقودة القيم الافتراضية) +منطق تجميع الأجزاء + +### اختبارات التكامل +تطبيق كل مزود LLM لتنفيذ البث +نقاط نهاية البث لواجهة برمجة تطبيقات البوابة +طرق البث لعميل بايثون + +### اختبارات شاملة +إخراج أداة سطر الأوامر (CLI) للبث +التدفق الكامل: العميل → البوابة → بولسار → LLM → العودة +أحمال عمل مختلطة (بث/غير بث) + +### اختبارات التوافق مع الإصدارات السابقة +تعمل العملاء الحاليون دون تعديل +تتصرف طلبات عدم البث بشكل مماثل + +## خطة الترحيل + +### المرحلة الأولى: البنية التحتية +نشر تغييرات المخطط (متوافقة مع الإصدارات السابقة) +نشر تحديثات واجهة برمجة تطبيقات البوابة +نشر تحديثات واجهة برمجة تطبيقات بايثون +إصدار تحديثات أداة سطر الأوامر (CLI) + +### المرحلة الثانية: VertexAI +نشر تطبيق VertexAI للبث. +التحقق من صحته باستخدام أحمال العمل التجريبية. + +### المرحلة الثالثة: جميع المزودين. +نشر تحديثات المزودين بشكل تدريجي. +مراقبة المشكلات. + +### المرحلة الرابعة: واجهة برمجة تطبيقات الوكيل. +نشر تغييرات مخطط الوكيل. +نشر تطبيق البث للوكيل. +تحديث الوثائق. + +## الجدول الزمني. + +| المرحلة | الوصف | التبعيات | +|-------|-------------|--------------| +| المرحلة الأولى | البنية التحتية | لا يوجد | +| المرحلة الثانية | نموذج VertexAI الأولي | المرحلة الأولى | +| المرحلة الثالثة | جميع المزودين | المرحلة الثانية | +| المرحلة الرابعة | واجهة برمجة تطبيقات الوكيل | المرحلة الثالثة | + +## قرارات التصميم. + +تمت معالجة الأسئلة التالية أثناء التحديد: + +1. **عدد الرموز في البث**: عدد الرموز هو الفروق، وليس المجاميع التراكمية. + يمكن للمستهلكين جمعها إذا لزم الأمر. يتطابق هذا مع كيفية قيام معظم المزودين بالإبلاغ + عن الاستخدام ويبسط التنفيذ. + +2. **معالجة الأخطاء في التدفقات**: في حالة حدوث خطأ، يتم ملء الحقل `error` + ولا يلزم وجود أي حقول أخرى. الخطأ هو دائمًا آخر رسالة - لا يُسمح بإرسال أو استقبال رسائل لاحقة بعد ذلك. + أو توقعها. + خطأ. بالنسبة لتدفقات نماذج اللغة الكبيرة/التعليمات، `end_of_stream=true`. بالنسبة لتدفقات الوكلاء، + `chunk_type="error"` مع `end_of_dialog=true`. + +3. **استعادة الاستجابات الجزئية**: بروتوكول المراسلة (Pulsار) يتميز بالمرونة، + لذلك لا توجد حاجة إلى إعادة محاولة الرسائل على مستوى الرسالة. إذا فقد العميل تتبع التدفق + أو انقطع الاتصال، فيجب عليه إعادة محاولة الطلب بأكمله من البداية. + +4. **خدمة الاستجابة السريعة المتدفقة**: تدعم البث فقط للنصوص (`text`). + الاستجابات، وليس الاستجابات المنظمة (`object`). تعرف خدمة الاستجابة السريعة في + البداية ما إذا كانت المخرجات ستكون بتنسيق JSON أو نص بناءً على قالب + الاستعلام. إذا تم إجراء طلب بث لاستعلام ينتج عنه مخرجات بتنسيق JSON، فإن + يجب أن يقوم الخدمة إما: + بإرجاع كائن JSON كامل في استجابة واحدة باستخدام `end_of_stream=true`، أو + برفض طلب البث مع وجود خطأ. + +## الأسئلة المفتوحة + +لا يوجد أسئلة في الوقت الحالي. + +## المراجع + +مخطط نموذج اللغة الكبير الحالي: `trustgraph-base/trustgraph/schema/services/llm.py` +مخطط المطالبة الحالي: `trustgraph-base/trustgraph/schema/services/prompt.py` +مخطط الوكيل الحالي: `trustgraph-base/trustgraph/schema/services/agent.py` +الخدمة الأساسية لنموذج اللغة الكبير: `trustgraph-base/trustgraph/base/llm_service.py` +مزود VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +واجهة برمجة التطبيقات (API) للواجهة: `trustgraph-base/trustgraph/api/` +أدوات سطر الأوامر (CLI): `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.es.md b/docs/tech-specs/streaming-llm-responses.es.md new file mode 100644 index 00000000..f5409985 --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.es.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "Especificación Técnica de Respuestas de LLM en Streaming" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Respuestas de LLM en Streaming + +> **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 la implementación del soporte de streaming para respuestas de LLM +en TrustGraph. El streaming permite la entrega en tiempo real de tokens generados +a medida que son producidos por el LLM, en lugar de esperar a que se complete +la generación de la respuesta. + +Esta implementación admite los siguientes casos de uso: + +1. **Interfaces de Usuario en Tiempo Real**: Transmite tokens a la interfaz de usuario a medida que se generan, + proporcionando retroalimentación visual inmediata. +2. **Reducción del Tiempo Hasta el Primer Token**: Los usuarios ven la salida inmediatamente + en lugar de esperar a que se complete la generación. +3. **Manejo de Respuestas Largas**: Maneja salidas muy largas que de otro modo + podrían provocar un tiempo de espera o exceder los límites de memoria. +4. **Aplicaciones Interactivas**: Permite interfaces de chat y agentes receptivas. + +## Objetivos + +**Compatibilidad con Versiones Anteriores**: Los clientes existentes que no utilizan streaming continúan funcionando + sin modificaciones. +**Diseño de API Consistente**: El streaming y el no streaming utilizan los mismos patrones de esquema + con una divergencia mínima. +**Flexibilidad del Proveedor**: Soporte de streaming cuando esté disponible, con una + alternativa gradual cuando no esté disponible. +**Implementación por Fases**: Implementación incremental para reducir el riesgo. +**Soporte de Extremo a Extremo**: Streaming desde el proveedor de LLM hasta las aplicaciones cliente + a través de Pulsar, la API de Gateway y la API de Python. + +## Antecedentes + +### Arquitectura Actual + +El flujo actual de finalización de texto de LLM funciona de la siguiente manera: + +1. El cliente envía `TextCompletionRequest` con los campos `system` y `prompt`. +2. El servicio de LLM procesa la solicitud y espera a que se complete la generación. +3. Se devuelve un único `TextCompletionResponse` con la cadena `response` completa. + +Esquema actual (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### Limitaciones actuales + +**Latencia**: Los usuarios deben esperar a que se complete la generación antes de ver cualquier resultado. +**Riesgo de tiempo de espera**: Las generaciones largas pueden exceder los umbrales de tiempo de espera del cliente. +**Mala experiencia de usuario**: La falta de retroalimentación durante la generación crea la percepción de lentitud. +**Uso de recursos**: Las respuestas completas deben almacenarse en búfer en la memoria. + +Esta especificación aborda estas limitaciones al permitir la entrega incremental de respuestas, manteniendo la compatibilidad total con versiones anteriores. + + +## Diseño técnico + +### Fase 1: Infraestructura + +La Fase 1 establece la base para la transmisión mediante la modificación de esquemas, API y herramientas de línea de comandos. + + +#### Cambios en el esquema + +##### Esquema de LLM (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**Cambios en la solicitud:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: Cuando `true`, solicita la entrega de la respuesta en modo de transmisión. +Predeterminado: `false` (el comportamiento existente se mantiene). + +**Cambios en la respuesta:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: Cuando `true`, indica que esta es la respuesta final (o única). +Para solicitudes no de transmisión: Respuesta única con `end_of_stream=true`. +Para solicitudes de transmisión: Múltiples respuestas, todas con `end_of_stream=false` + excepto la última. + +##### Esquema de la solicitud (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +El servicio de solicitud envuelve la finalización de texto, por lo que refleja el mismo patrón: + +**Cambios en la solicitud:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**Cambios en la respuesta:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### Cambios en la API de Gateway + +La API de Gateway debe exponer capacidades de transmisión a clientes HTTP/WebSocket. + +**Actualizaciones de la API REST:** + +`POST /api/v1/text-completion`: Aceptar el parámetro `streaming` en el cuerpo de la solicitud. +El comportamiento de la respuesta depende de la bandera de transmisión: + `streaming=false`: Respuesta JSON única (comportamiento actual). + `streaming=true`: Flujo de eventos enviados por el servidor (SSE) o mensajes WebSocket. + +**Formato de respuesta (transmisión):** + +Cada fragmento transmitido sigue la misma estructura de esquema: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +Fragmento final: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### Cambios en la API de Python + +La API del cliente de Python debe soportar tanto modos de transmisión como no de transmisión +manteniendo la compatibilidad con versiones anteriores. + +**Actualizaciones de LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**Actualizaciones de PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +Patrón similar con el parámetro `streaming` y la variante de generador asíncrono. + +#### Cambios en la herramienta de línea de comandos + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +La transmisión está habilitada de forma predeterminada para una mejor experiencia de usuario interactiva. +La opción `--no-streaming` desactiva la transmisión. +Cuando la transmisión está habilitada: envía los tokens a la salida estándar a medida que llegan. +Cuando la transmisión no está habilitada: espera la respuesta completa y luego la muestra. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +El mismo patrón que `tg-invoke-llm`. + +#### Cambios en la Clase Base del Servicio LLM + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### Fase 2: Prueba de concepto de VertexAI + +La Fase 2 implementa el streaming en un único proveedor (VertexAI) para validar la +infraestructura y habilitar pruebas de extremo a extremo. + +#### Implementación de VertexAI + +**Módulo:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**Cambios:** + +1. Sobreescribir `supports_streaming()` para devolver `True` +2. Implementar generador asíncrono `generate_content_stream()` +3. Manejar tanto los modelos Gemini como Claude (a través de la API de VertexAI Anthropic) + +**Streaming de Gemini:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**Claude (a través de VertexAI Anthropic) en modo de transmisión:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### Pruebas + +Pruebas unitarias para el ensamblaje de respuestas en streaming. +Pruebas de integración con VertexAI (Gemini y Claude). +Pruebas de extremo a extremo: CLI -> Gateway -> Pulsar -> VertexAI -> back. +Pruebas de compatibilidad con versiones anteriores: Las solicitudes no en streaming aún funcionan. + +-- + +### Fase 3: Todos los proveedores de LLM + +La fase 3 extiende el soporte de streaming a todos los proveedores de LLM en el sistema. + +#### Estado de implementación del proveedor + +Cada proveedor debe: +1. **Soporte completo de streaming**: Implementar `generate_content_stream()` +2. **Modo de compatibilidad**: Manejar la bandera `end_of_stream` correctamente + (devolver una única respuesta con `end_of_stream=true`) + +| Proveedor | Paquete | Soporte de streaming | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | Completo (API de streaming nativo) | +| Claude/Anthropic | trustgraph-flow | Completo (API de streaming nativo) | +| Ollama | trustgraph-flow | Completo (API de streaming nativo) | +| Cohere | trustgraph-flow | Completo (API de streaming nativo) | +| Mistral | trustgraph-flow | Completo (API de streaming nativo) | +| Azure OpenAI | trustgraph-flow | Completo (API de streaming nativo) | +| Google AI Studio | trustgraph-flow | Completo (API de streaming nativo) | +| VertexAI | trustgraph-vertexai | Completo (Fase 2) | +| Bedrock | trustgraph-bedrock | Completo (API de streaming nativo) | +| LM Studio | trustgraph-flow | Completo (compatible con OpenAI) | +| LlamaFile | trustgraph-flow | Completo (compatible con OpenAI) | +| vLLM | trustgraph-flow | Completo (compatible con OpenAI) | +| TGI | trustgraph-flow | Por determinar | +| Azure | trustgraph-flow | Por determinar | + +#### Patrón de implementación + +Para proveedores compatibles con OpenAI (OpenAI, LM Studio, LlamaFile, vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### Fase 4: API del Agente + +La Fase 4 extiende la transmisión a la API del Agente. Esto es más complejo porque +la API del Agente ya es inherentemente multi-mensaje (pensamiento → acción → observación +→ repetir → respuesta final). + +#### Esquema actual del Agente + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### Cambios Propuestos al Esquema del Agente + +**Solicitar Cambios:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**Cambios en la respuesta:** + +El agente produce múltiples tipos de salida durante su ciclo de razonamiento: +Pensamientos (razonamiento) +Acciones (llamadas a herramientas) +Observaciones (resultados de las herramientas) +Respuesta (respuesta final) +Errores + +Dado que `chunk_type` identifica qué tipo de contenido se está enviando, los campos separados +`answer`, `error`, `thought` y `observation` se pueden combinar en +un único campo `content`: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**Semántica de los campos:** + +`chunk_type`: Indica qué tipo de contenido se encuentra en el campo `content` + `"thought"`: Razonamiento/pensamiento del agente + `"action"`: Herramienta/acción que se está invocando + `"observation"`: Resultado de la ejecución de la herramienta + `"answer"`: Respuesta final a la pregunta del usuario + `"error"`: Mensaje de error + +`content`: El contenido transmitido real, interpretado según `chunk_type` + +`end_of_message`: Cuando `true`, el tipo de fragmento actual está completo + Ejemplo: Todos los tokens para el pensamiento actual han sido enviados + Permite a los clientes saber cuándo pasar a la siguiente etapa + +`end_of_dialog`: Cuando `true`, la interacción completa del agente ha finalizado + Este es el mensaje final en la transmisión + +#### Comportamiento de la transmisión del agente + +Cuando `streaming=true`: + +1. **Transmisión de pensamientos:** + Múltiples fragmentos con `chunk_type="thought"`, `end_of_message=false` + El fragmento final del pensamiento tiene `end_of_message=true` +2. **Notificación de acción:** + Un solo fragmento con `chunk_type="action"`, `end_of_message=true` +3. **Observación:** + Fragmento(s) con `chunk_type="observation"`, el final tiene `end_of_message=true` +4. **Repetir** los pasos 1-3 mientras el agente razona +5. **Respuesta final:** + `chunk_type="answer"` con la respuesta final en `content` + El último fragmento tiene `end_of_message=true`, `end_of_dialog=true` + +**Secuencia de ejemplo de la transmisión:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +Cuando `streaming=false`: +Comportamiento actual preservado +Respuesta única con respuesta completa +`end_of_message=true`, `end_of_dialog=true` + +#### Gateway y API de Python + +Gateway: Nuevo punto final SSE/WebSocket para la transmisión de agentes +API de Python: Nuevo método de generador asíncrono `agent_stream()` + +-- + +## Consideraciones de seguridad + +**Sin nueva superficie de ataque**: La transmisión utiliza la misma autenticación/autorización +**Limitación de velocidad**: Aplicar límites de velocidad por token o por fragmento si es necesario +**Manejo de conexiones**: Terminar correctamente las transmisiones en caso de desconexión del cliente +**Gestión de tiempos de espera**: Las solicitudes de transmisión requieren un manejo adecuado de los tiempos de espera + +## Consideraciones de rendimiento + +**Memoria**: La transmisión reduce el uso máximo de memoria (sin almacenamiento en búfer de la respuesta completa) +**Latencia**: El tiempo hasta el primer token se reduce significativamente +**Sobrecarga de conexión**: Las conexiones SSE/WebSocket tienen una sobrecarga de mantenimiento activo +**Rendimiento de Pulsar**: Múltiples mensajes pequeños frente a un mensaje grande único + tradeoff + +## Estrategia de pruebas + +### Pruebas unitarias +Serialización/deserialización de esquema con nuevos campos +Compatibilidad con versiones anteriores (los campos faltantes utilizan los valores predeterminados) +Lógica de ensamblaje de fragmentos + +### Pruebas de integración +Implementación de transmisión de cada proveedor de LLM +Puntos finales de transmisión de la API de Gateway +Métodos de transmisión del cliente de Python + +### Pruebas de extremo a extremo +Salida de transmisión de la herramienta de línea de comandos +Flujo completo: Cliente → Gateway → Pulsar → LLM → de vuelta +Cargas de trabajo mixtas de transmisión/no transmisión + +### Pruebas de compatibilidad con versiones anteriores +Los clientes existentes funcionan sin modificaciones +Las solicitudes no de transmisión se comportan de la misma manera + +## Plan de migración + +### Fase 1: Infraestructura +Implementar cambios de esquema (compatible con versiones anteriores) +Implementar actualizaciones de la API de Gateway +Implementar actualizaciones de la API de Python +Lanzar actualizaciones de la herramienta de línea de comandos + +### Fase 2: VertexAI +Implementar la implementación de transmisión de VertexAI +Validar con cargas de trabajo de prueba + +### Fase 3: Todos los proveedores +Implementar las actualizaciones de los proveedores de forma incremental +Monitorear problemas + +### Fase 4: API de agente +Implementar cambios de esquema de agente +Implementar la implementación de transmisión de agente +Actualizar la documentación + +## Cronograma + +| Fase | Descripción | Dependencias | +|-------|-------------|--------------| +| Fase 1 | Infraestructura | Ninguna | +| Fase 2 | PoC de VertexAI | Fase 1 | +| Fase 3 | Todos los proveedores | Fase 2 | +| Fase 4 | API de agente | Fase 3 | + +## Decisiones de diseño + +Las siguientes preguntas se resolvieron durante la especificación: + +1. **Conteo de tokens en la transmisión**: Los conteos de tokens son deltas, no totales acumulados. + Los consumidores pueden sumarlos si es necesario. Esto coincide con la forma en que la mayoría de los proveedores informan + el uso y simplifica la implementación. + +2. **Manejo de errores en la transmisión**: Si ocurre un error, el campo `error` se + completa y no se necesitan otros campos. Un error siempre es la comunicación final + no se permiten ni se esperan mensajes posteriores después de + un error. Para las transmisiones de LLM/Prompt, `end_of_stream=true`. Para las transmisiones de agente, + `chunk_type="error"` con `end_of_dialog=true`. + +3. **Recuperación de respuesta parcial**: El protocolo de mensajería (Pulsar) es resistente, + por lo que no se necesita reintento a nivel de mensaje. Si un cliente pierde el seguimiento de la transmisión + o se desconecta, debe reintentar la solicitud completa desde cero. + +4. **Transmisión del servicio de prompt**: La transmisión solo es compatible con texto (`text`) + respuestas, no respuestas estructuradas (`object`). El servicio de prompt lo sabe desde + el principio si la salida será JSON o texto según la plantilla del prompt. Si se realiza una + solicitud de transmisión para un prompt de salida JSON, el + servicio debe: + Devolver el JSON completo en una sola respuesta con `end_of_stream=true`, o + Rechazar la solicitud de transmisión con un error + +## Preguntas abiertas + +Ninguna en este momento. + +## Referencias + +Esquema de LLM actual: `trustgraph-base/trustgraph/schema/services/llm.py` +Esquema de prompt actual: `trustgraph-base/trustgraph/schema/services/prompt.py` +Esquema de agente actual: `trustgraph-base/trustgraph/schema/services/agent.py` +Base del servicio de LLM: `trustgraph-base/trustgraph/base/llm_service.py` +Proveedor de VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +API de Gateway: `trustgraph-base/trustgraph/api/` +Herramientas de CLI: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.he.md b/docs/tech-specs/streaming-llm-responses.he.md new file mode 100644 index 00000000..60300bbd --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.he.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "מפרט טכני לתגובות LLM בסטרימינג" +parent: "Hebrew (Beta)" +--- + +# מפרט טכני לתגובות LLM בסטרימינג + +> **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. + +## סקירה כללית + +מפרט זה מתאר את יישום התמיכה בסטרימינג עבור תגובות LLM +ב-TrustGraph. סטרימינג מאפשר העברה בזמן אמת של טוקנים שנוצרו +ככל שהם מיוצרים על ידי ה-LLM, במקום לחכות להשלמת יצירת +התגובה. + +יישום זה תומך בתרחישי שימוש הבאים: + +1. **ממשקי משתמש בזמן אמת**: העברת טוקנים לממשק המשתמש בזמן יצירתם, + תוך מתן משוב ויזואלי מיידי. +2. **זמן עד לטוקן הראשון מופחת**: המשתמש רואה את הפלט מיד + ולא מחכה ליצירה מלאה. +3. **טיפול בתגובות ארוכות**: טיפול בפלטים ארוכים מאוד שעלולים + אחרת לגרום לחריגה מהזמן או לחרוג ממגבלות הזיכרון. +4. **יישומים אינטראקטיביים**: אפשור ממשקי צ'אט וסוכנים מגיבים. + +## מטרות + +**תאימות לאחור**: לקוחות קיימים שאינם משתמשים בסטרימינג ממשיכים + לעבוד ללא שינוי. +**עיצוב API עקבי**: סטרימינג ולא סטרימינג משתמשים באותם דפוסי + סכימה עם סטייה מינימלית. +**גמישות ספק**: תמיכה בסטרימינג כאשר הוא זמין, מעבר חלק + כאשר הוא אינו זמין. +**פריסה מדורגת**: יישום הדרגתי להפחתת סיכונים. +**תמיכה מקצה לקצה**: סטרימינג מספק ה-LLM דרך ליישומי לקוח + באמצעות Pulsar, Gateway API ו-Python API. + +## רקע + +### ארכיטקטורה נוכחית + +זרימת השלמת הטקסט הנוכחית של ה-LLM פועלת באופן הבא: + +1. לקוח שולח `TextCompletionRequest` עם שדות `system` ו-`prompt`. +2. שירות ה-LLM מעבד את הבקשה וממתין להשלמת היצירה. +3. `TextCompletionResponse` יחיד מוחזר עם מחרוזת `response` מלאה. + +סכימה נוכחית (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### מגבלות נוכחיות + +**השהייה (Latency)**: משתמשים חייבים לחכות לסיום יצירת התוכן לפני שהם רואים פלט כלשהו. +**סיכון לחריגת זמן (Timeout)**: יצירת תוכן ארוכה עלולה לחרוג מספי זמן המוגדר בלקוח. +**חוויית משתמש ירודה (Poor UX)**: היעדר משוב במהלך היצירה יוצר תחושה של איטיות. +**שימוש במשאבים**: תגובות מלאות חייבות להיות מאוחסנות בזיכרון. + +מפרט זה מתייחס למגבלות אלה על ידי אפשור העברת תגובה הדרגתית תוך שמירה על תאימות מלאה לאחור. + + +## עיצוב טכני + +### שלב 1: תשתית + +שלב 1 מקיים את הבסיס להעברה באמצעות שינוי סכימות, ממשקי API וכלי שורת פקודה. + + +#### שינויים בסכימה + +##### סכימת LLM (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**שינויים בבקשה:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: כאשר `true`, מבקשים משלוח תגובה בסטרימינג. +ברירת מחדל: `false` (ההתנהגות הקיימת נשמרת). + +**שינויים בתגובה:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: כאשר `true`, מציין שזו התגובה הסופית (או היחידה). +עבור בקשות שאינן סטרימינג: תגובה יחידה עם `end_of_stream=true`. +עבור בקשות סטרימינג: מספר תגובות, כולן עם `end_of_stream=false`. + מלבד התגובה האחרונה. + +##### סכימת הפרומפט (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +שירות הפרומפט עוטף השלמת טקסט, ולכן הוא משקף את אותו דפוס: + +**שינויים בבקשה:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**שינויים בתגובה:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### שינויים בממשק ה-Gateway API + +ממשק ה-Gateway API חייב לחשוף יכולות סטרימינג ללקוחות HTTP/WebSocket. + +**עדכונים לממשק ה-REST API:** + +`POST /api/v1/text-completion`: קבלת פרמטר `streaming` בגוף הבקשה +התנהגות התגובה תלויה בדגל הסטרימינג: + `streaming=false`: תגובת JSON בודדת (ההתנהגות הנוכחית) + `streaming=true`: זרם Server-Sent Events (SSE) או הודעות WebSocket + +**פורמט תגובה (סטרימינג):** + +כל חלק בזרם עוקב אחר מבנה הסכימה זהה: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +חלק אחרון: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### שינויים בממשק ה-API של Python + +ממשק ה-API של הלקוח ב-Python חייב לתמוך הן במצב סטרימינג והן במצב לא-סטרימינג +תוך שמירה על תאימות לאחור. + +**עדכונים ל-LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**עדכונים עבור PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +דפוס דומה עם הפרמטר `streaming` וגרסה אסינכרונית של מחולל. + +#### שינויים בכלי שורת הפקודה + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +הפעלת סטרימינג כברירת מחדל לשיפור חוויית משתמש אינטראקטיבית. +הדגל `--no-streaming` משבית את הסטרימינג. +כאשר הסטרימינג מופעל: פלט טוקנים לפלט סטנדרטי כשהם מגיעים. +כאשר הסטרימינג אינו מופעל: ממתינים לתגובה מלאה, ולאחר מכן מבצעים פלט. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +אותו דפוס כמו `tg-invoke-llm`. + +#### שינויים במחלקת הבסיס של שירות מודל שפה גדול (LLM). + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### שלב 2: הוכחת היתכנות של VertexAI + +שלב 2 מיישם סטרימינג בספק יחיד (VertexAI) כדי לאמת את +התשתית ולאפשר בדיקות מקצה לקצה. + +#### יישום VertexAI + +**מודול:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**שינויים:** + +1. החלפה של `supports_streaming()` כדי להחזיר `True` +2. יישום מחולל אסינכרוני `generate_content_stream()` +3. טיפול גם במודלים של Gemini וגם של Claude (דרך ממשק ה-API של VertexAI Anthropic) + +**סטרימינג של Gemini:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**קלוד (דרך VertexAI של חברת Anthropic) - סטרימינג:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### בדיקות + +בדיקות יחידה עבור הרכבת תגובות סטרימינג +בדיקות אינטגרציה עם VertexAI (Gemini ו-Claude) +בדיקות מקצה לקצה: CLI -> Gateway -> Pulsar -> VertexAI -> חזרה +בדיקות תאימות לאחור: בקשות שאינן סטרימינג עדיין עובדות + +-- + +### שלב 3: כל ספקי מודלי שפה גדולים (LLM) + +שלב 3 מרחיב את תמיכת הסטרימינג לכל ספקי מודלי השפה הגדולים במערכת. + +#### סטטוס יישום ספק + +כל ספק חייב לבצע אחת מהפעולות הבאות: +1. **תמיכה מלאה בסטרימינג**: ליישם `generate_content_stream()` +2. **מצב תאימות**: לטפל בדגל `end_of_stream` בצורה נכונה + (להחזיר תגובה בודדת עם `end_of_stream=true`) + +| ספק | חבילה | תמיכה בסטרימינג | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| Claude/Anthropic | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| Ollama | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| Cohere | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| Mistral | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| Azure OpenAI | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| Google AI Studio | trustgraph-flow | מלא (ממשק סטרימינג מקורי) | +| VertexAI | trustgraph-vertexai | מלא (שלב 2) | +| Bedrock | trustgraph-bedrock | מלא (ממשק סטרימינג מקורי) | +| LM Studio | trustgraph-flow | מלא (תואם ל-OpenAI) | +| LlamaFile | trustgraph-flow | מלא (תואם ל-OpenAI) | +| vLLM | trustgraph-flow | מלא (תואם ל-OpenAI) | +| TGI | trustgraph-flow | מצומצם | +| Azure | trustgraph-flow | מצומצם | + +#### תבנית יישום + +עבור ספקים התואמים ל-OpenAI (OpenAI, LM Studio, LlamaFile, vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### שלב 4: ממשק API של הסוכן + +שלב 4 מרחיב את הסטרימינג לממשק ה-API של הסוכן. זה מורכב יותר מכיוון שה- +ממשק ה-API של הסוכן הוא כבר מטבעו רב-הודעות (מחשבה → פעולה → תצפית +→ חזור → תשובה סופית). + +#### הסכימה הנוכחית של הסוכן + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### שינויים מוצעים בסכימת הסוכן + +**בקשות לשינויים:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**שינויים בתגובה:** + +הסוכן מייצר סוגים שונים של פלט במהלך מחזור החשיבה שלו: +מחשבות (היגיון) +פעולות (קריאות לכלי) +תצפיות (תוצאות של כלי) +תשובה (תגובה סופית) +שגיאות + +מכיוון ש-`chunk_type` מציין איזה סוג תוכן נשלח, השדות הנפרדים +`answer`, `error`, `thought` ו-`observation` יכולים להיות מקובצים לשדה +`content` יחיד: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**סמנטיקה של שדות:** + +`chunk_type`: מציין איזה סוג תוכן נמצא בשדה `content` + `"thought"`: חשיבה/היגיון של הסוכן + `"action"`: כלי/פעולה המופעלת + `"observation"`: תוצאה מהפעלת הכלי + `"answer"`: תשובה סופית לשאלה של המשתמש + `"error"`: הודעת שגיאה + +`content`: התוכן המועבר בפועל, המפורש בהתאם ל-`chunk_type` + +`end_of_message`: כאשר `true`, סוג החלק הנוכחי הושלם + דוגמה: כל הטוקנים עבור המחשבה הנוכחית נשלחו + מאפשר ללקוחות לדעת מתי לעבור לשלב הבא + +`end_of_dialog`: כאשר `true`, האינטראקציה כולה של הסוכן הושלמה + זו ההודעה האחרונה בזרם + +#### התנהגות סטרימינג של הסוכן + +כאשר `streaming=true`: + +1. **סטרימינג של מחשבות:** + מספר חלקים עם `chunk_type="thought"`, `end_of_message=false` + החלק האחרון של המחשבה מכיל `end_of_message=true` +2. **הודעת פעולה:** + חלק יחיד עם `chunk_type="action"`, `end_of_message=true` +3. **תצפית:** + חלק/ים עם `chunk_type="observation"`, האחרון מכיל `end_of_message=true` +4. **חזור** על שלבים 1-3 כאשר הסוכן מסיק מסקנות +5. **תשובה סופית:** + `chunk_type="answer"` עם התגובה הסופית ב-`content` + החלק האחרון מכיל `end_of_message=true`, `end_of_dialog=true` + +**רצף סטרימינג לדוגמה:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +כאשר `streaming=false`: +התנהגות נוכחית נשמרת +תגובה אחת עם תשובה מלאה +`end_of_message=true`, `end_of_dialog=true` + +#### שער (Gateway) ו-API בפייתון + +שער: נקודת קצה חדשה של SSE/WebSocket עבור סטרימינג של סוכן +API בפייתון: שיטת גנרטור אסינכרונית חדשה `agent_stream()` + +-- + +## שיקולי אבטחה + +**ללא נקודות תורפה חדשות**: סטרימינג משתמש באותה אימות/הרשאה +**הגבלת קצב**: יש להחיל מגבלות קצב פר-טוקן או פר-חלק במידת הצורך +**טיפול בחיבורים**: יש לסיים חיבורים בצורה תקינה בעת ניתוק הלקוח +**ניהול תזמון**: בקשות סטרימינג דורשות טיפול מתאים בתזמון + +## שיקולי ביצועים + +**זיכרון**: סטרימינג מפחית את השימוש בזיכרון המקסימלי (ללא אחסון מלא של התגובה) +**השהיה**: זמן עד לקבלת הטוקן הראשון קטן משמעותית +**תקורה של חיבורים**: לחיבורי SSE/WebSocket יש תקורה של שמירה על חיבור פעיל +**תפוקת Pulsar**: מספר הודעות קטנות לעומת הודעה גדולה אחת + פשרה + +## אסטרטגיית בדיקות + +### בדיקות יחידה +סריאליזציה/דה-סריאליזציה של סכימה עם שדות חדשים +תאימות לאחור (שדות חסרים משתמשים בערכי ברירת מחדל) +לוגיקת הרכבת חלקים + +### בדיקות אינטגרציה +יישום הסטרימינג של כל ספק מודלי שפה גדולים (LLM) +נקודות קצה של סטרימינג של API בשער +שיטות סטרימינג של לקוח בפייתון + +### בדיקות מקצה לקצה +פלט סטרימינג של כלי שורת הפקודה (CLI) +זרימה מלאה: לקוח → שער → Pulsar → LLM → חזרה +עומסי עבודה מעורבים של סטרימינג/לא סטרימינג + +### בדיקות תאימות לאחור +לקוחות קיימים עובדים ללא שינוי +בקשות לא סטרימינג מתנהגות באופן זהה + +## תוכנית מעבר + +### שלב 1: תשתית +פריסת שינויי סכימה (תואמת לאחור) +פריסת עדכוני API בשער +פריסת עדכוני API בפייתון +שחרור עדכוני כלי שורת הפקודה + +### שלב 2: VertexAI +הטמעת יישום סטרימינג של VertexAI +אימות באמצעות עומסי עבודה לבדיקה + +### שלב 3: כל הספקים +הטמעת עדכוני ספק באופן הדרגתי +ניטור לאיתור בעיות + +### שלב 4: ממשק API של סוכן +הטמעת שינויים בסכימת הסוכן +הטמעת יישום סטרימינג של סוכן +עדכון התיעוד + +## ציר זמן + +| שלב | תיאור | תלויות | +|-------|-------------|--------------| +| שלב 1 | תשתית | אין | +| שלב 2 | הוכחת היתכנות של VertexAI | שלב 1 | +| שלב 3 | כל הספקים | שלב 2 | +| שלב 4 | ממשק API של סוכן | שלב 3 | + +## החלטות עיצוב + +השאלות הבאות נפתרו במהלך המפרט: + +1. **ספירת טוקנים בסטרימינג**: ספירת הטוקנים היא הפרשים, ולא סכומים מצטברים. + צרכנים יכולים לחבר אותם אם יש צורך. זה תואם לאופן שבו רוב הספקים מדווחים + על שימוש ומפשט את היישום. + +2. **טיפול בשגיאות בזרמים**: אם מתרחשת שגיאה, השדה `error` מאוכלס ושאר השדות אינם נחוצים. שגיאה היא תמיד ההודעה האחרונה - אסור לשלוח או לצפות להודעות נוספות לאחר מכן. + + + שגיאה. עבור זרמי מודלים שפתיים (LLM) / הנחיות, `end_of_stream=true`. עבור זרמי סוכנים, + `chunk_type="error"` עם `end_of_dialog=true`. + +3. **התאוששות מתגובה חלקית**: פרוטוקול העברת ההודעות (Pulsar) עמיד, + ולכן אין צורך בניסיונות חוזרים ברמת ההודעה. אם לקוח מאבד את המעקב אחר הזרם + או מתנתק, עליו לנסות שוב את כל הבקשה מההתחלה. + +4. **שירות מהיר עם סטרימינג**: סטרימינג נתמך רק עבור טקסט (`text`) + תשובות, ולא עבור תשובות מובנות (`object`). שירות הפרומפט יודע מראש + האם הפלט יהיה JSON או טקסט, בהתבסס על תבנית הפרומפט. אם מתבצעת + בקשת סטרימינג עבור פרומפט שפלטו הוא JSON, אז... + השירות צריך או: + להחזיר את קובץ ה-JSON השלם בתגובה אחת עם `end_of_stream=true`, או + לדחות את בקשת הסטרימינג עם שגיאה + +## שאלות פתוחות + +אין כרגע. + +## הפניות + +סכימת מודל שפה גדול (LLM) נוכחית: `trustgraph-base/trustgraph/schema/services/llm.py` +סכימת הנחיה נוכחית: `trustgraph-base/trustgraph/schema/services/prompt.py` +סכימת סוכן נוכחית: `trustgraph-base/trustgraph/schema/services/agent.py` +שירות LLM בסיסי: `trustgraph-base/trustgraph/base/llm_service.py` +ספק VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +ממשק API של שער: `trustgraph-base/trustgraph/api/` +כלי שורת פקודה: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.hi.md b/docs/tech-specs/streaming-llm-responses.hi.md new file mode 100644 index 00000000..211be3fb --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.hi.md @@ -0,0 +1,578 @@ +--- +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. **वास्तविक समय उपयोगकर्ता इंटरफेस**: उत्पन्न होने पर टोकन को UI में भेजें, + जिससे तत्काल दृश्य प्रतिक्रिया प्रदान की जा सके। +2. **पहले टोकन के लिए कम समय**: उपयोगकर्ता तुरंत आउटपुट देखना शुरू करते हैं, + पूर्ण पीढ़ी की प्रतीक्षा करने के बजाय। +3. **लंबी प्रतिक्रिया प्रबंधन**: बहुत लंबी आउटपुट को संभालें जो अन्यथा + समय समाप्त हो सकते हैं या मेमोरी सीमा से अधिक हो सकते हैं। +4. **इंटरैक्टिव एप्लिकेशन**: उत्तरदायी चैट और एजेंट इंटरफेस को सक्षम करें। + +## लक्ष्य + +**पिछड़ा संगतता (Backward Compatibility)**: मौजूदा, गैर-स्ट्रीमिंग क्लाइंट बिना किसी बदलाव के काम करते रहते हैं। + बिना किसी बदलाव के। +**संगत एपीआई डिज़ाइन (Consistent API Design)**: स्ट्रीमिंग और गैर-स्ट्रीमिंग दोनों समान स्कीमा पैटर्न का उपयोग करते हैं, जिसमें न्यूनतम विचलन होता है। + होता है। +**प्रदाता लचीलापन (Provider Flexibility)**: जहां उपलब्ध हो, वहां स्ट्रीमिंग का समर्थन करें, और जहां उपलब्ध न हो, वहां सुचारू रूप से वापस आएं। + वापस आएं। +**चरणबद्ध कार्यान्वयन (Phased Rollout)**: जोखिम को कम करने के लिए क्रमिक कार्यान्वयन। +**एंड-टू-एंड समर्थन (End-to-End Support)**: एलएलएम प्रदाता से लेकर क्लाइंट तक स्ट्रीमिंग, पल्सर, गेटवे एपीआई और पायथन एपीआई के माध्यम से एप्लिकेशन तक। + एप्लिकेशन तक। + +## पृष्ठभूमि (Background) + +### वर्तमान आर्किटेक्चर (Current Architecture) + +वर्तमान एलएलएम टेक्स्ट कंप्लीशन प्रवाह इस प्रकार काम करता है: + +1. क्लाइंट `TextCompletionRequest` भेजता है जिसमें `system` और `prompt` फ़ील्ड होते हैं। +2. एलएलएम सेवा अनुरोध को संसाधित करती है और पूर्ण पीढ़ी की प्रतीक्षा करती है। +3. पूर्ण `response` स्ट्रिंग के साथ एक `TextCompletionResponse` वापस किया जाता है। + +वर्तमान स्कीमा (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### वर्तमान सीमाएँ + +**विलंबता (Latency)**: उपयोगकर्ताओं को किसी भी आउटपुट को देखने से पहले पूर्ण पीढ़ी के पूरा होने का इंतजार करना पड़ता है। +**समय-सीमा (Timeout) का जोखिम**: लंबी पीढ़ी क्लाइंट समय-सीमा सीमाओं से अधिक हो सकती है। +**खराब उपयोगकर्ता अनुभव (Poor UX)**: पीढ़ी के दौरान कोई प्रतिक्रिया नहीं होने से धीमेपन का आभास होता है। +**संसाधन उपयोग (Resource Usage)**: पूर्ण प्रतिक्रियाओं को मेमोरी में बफर किया जाना चाहिए। + +यह विनिर्देश क्रमिक प्रतिक्रिया को सक्षम करके इन सीमाओं को संबोधित करता है, जबकि पूर्ण पश्च संगतता (backward compatibility) बनाए रखता है। + + +## तकनीकी डिज़ाइन + +### चरण 1: बुनियादी ढांचा + +चरण 1, स्ट्रीमिंग के लिए आधार तैयार करता है, जिसमें स्कीमा, एपीआई और सीएलआई टूल में संशोधन शामिल हैं। + + +#### स्कीमा परिवर्तन + +##### एलएलएम स्कीमा (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**अनुरोध परिवर्तन:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: जब `true`, तो स्ट्रीमिंग प्रतिक्रिया डिलीवरी का अनुरोध करता है। +डिफ़ॉल्ट: `false` (मौजूदा व्यवहार संरक्षित)। + +**प्रतिक्रिया में परिवर्तन:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: जब `true`, तो यह दर्शाता है कि यह अंतिम (या एकमात्र) प्रतिक्रिया है। +गैर-स्ट्रीमिंग अनुरोधों के लिए: `end_of_stream=true` के साथ एकल प्रतिक्रिया। +स्ट्रीमिंग अनुरोधों के लिए: `end_of_stream=false` के साथ कई प्रतिक्रियाएँ, + अंतिम प्रतिक्रिया को छोड़कर। + +##### प्रॉम्प्ट स्कीमा (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +प्रॉम्प्ट सेवा टेक्स्ट कंप्लीशन को लपेटती है, इसलिए यह समान पैटर्न को प्रतिबिंबित करती है: + +**अनुरोध परिवर्तन:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**प्रतिक्रिया में परिवर्तन:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### गेटवे एपीआई में बदलाव + +गेटवे एपीआई को एचटीटीपी/वेबसोकेट क्लाइंट्स के लिए स्ट्रीमिंग क्षमताएं प्रदान करनी होंगी। + +**रेस्ट एपीआई अपडेट:** + +`POST /api/v1/text-completion`: अनुरोध बॉडी में `streaming` पैरामीटर स्वीकार करें +प्रतिक्रिया व्यवहार स्ट्रीमिंग फ़्लैग पर निर्भर करता है: + `streaming=false`: एकल JSON प्रतिक्रिया (वर्तमान व्यवहार) + `streaming=true`: सर्वर-सेंट इवेंट्स (एसएसई) स्ट्रीम या वेबसोकेट संदेश + +**प्रतिक्रिया प्रारूप (स्ट्रीमिंग):** + +प्रत्येक स्ट्रीम किए गए भाग में समान स्कीमा संरचना होती है: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +अंतिम भाग: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### पायथन एपीआई में बदलाव + +पायथन क्लाइंट एपीआई को स्ट्रीमिंग और नॉन-स्ट्रीमिंग दोनों मोड का समर्थन करना चाहिए +साथ ही पिछली अनुकूलता बनाए रखनी चाहिए। + +**LlmClient अपडेट** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**प्रॉम्प्टक्लाइंट अपडेट** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +`streaming` पैरामीटर और एसिंक्रोनस जेनरेटर संस्करण के साथ समान पैटर्न। + +#### सीएलआई टूल में बदलाव + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +डिफ़ॉल्ट रूप से बेहतर इंटरैक्टिव यूएक्स के लिए स्ट्रीमिंग सक्षम है। +`--no-streaming` ध्वज स्ट्रीमिंग को अक्षम करता है। +जब स्ट्रीमिंग हो: आउटपुट टोकन को stdout पर तब भेजें जब वे आएं। +जब स्ट्रीमिंग न हो: पूर्ण प्रतिक्रिया की प्रतीक्षा करें, फिर आउटपुट करें। + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +`tg-invoke-llm` के समान पैटर्न। + +#### एलएलएम सर्विस बेस क्लास में बदलाव + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### चरण 2: वर्टेक्सएआई प्रूफ ऑफ कॉन्सेप्ट + +चरण 2, सत्यापन के लिए एक ही प्रदाता (वर्टेक्सएआई) में स्ट्रीमिंग को लागू करता है और एंड-टू-एंड परीक्षण को सक्षम करता है। +बुनियादी ढांचे। + +#### वर्टेक्सएआई कार्यान्वयन + +**मॉड्यूल:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**परिवर्तन:** + +1. `supports_streaming()` को `True` लौटाने के लिए ओवरराइड करें। +2. `generate_content_stream()` एसिंक्रोनस जेनरेटर को लागू करें। +3. जेमिनी और क्लाउड दोनों मॉडलों को संभालें (वर्टेक्सएआई एंथ्रोपिक एपीआई के माध्यम से)। + +**जेमिनी स्ट्रीमिंग:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**क्लाउड (वर्टेक्सएआई एंथ्रोपिक) स्ट्रीमिंग:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### परीक्षण + +स्ट्रीमिंग प्रतिक्रिया असेंबली के लिए यूनिट परीक्षण +वर्टेक्सएआई (जेमिनी और क्लाउड) के साथ एकीकरण परीक्षण +एंड-टू-एंड परीक्षण: CLI -> गेटवे -> पल्सर -> वर्टेक्सएआई -> बैक +पिछड़े संगतता परीक्षण: गैर-स्ट्रीमिंग अनुरोध अभी भी काम करते हैं + +-- + +### चरण 3: सभी एलएलएम प्रदाता + +चरण 3 सिस्टम में सभी एलएलएम प्रदाताओं के लिए स्ट्रीमिंग समर्थन का विस्तार करता है। + +#### प्रदाता कार्यान्वयन स्थिति + +प्रत्येक प्रदाता को या तो: +1. **पूर्ण स्ट्रीमिंग समर्थन**: `generate_content_stream()` को लागू करें +2. **संगतता मोड**: `end_of_stream` ध्वज को सही ढंग से संभालें + (एकल प्रतिक्रिया लौटाएं जिसमें `end_of_stream=true` हो) + +| प्रदाता | पैकेज | स्ट्रीमिंग समर्थन | +|----------|---------|-------------------| +| ओपनएआई | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| क्लाउड/एंथ्रोपिक | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| ओलामा | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| कोहेर | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| मिस्ट्रल | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| एज़्योर ओपनएआई | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| गूगल एआई स्टूडियो | trustgraph-flow | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| वर्टेक्सएआई | trustgraph-vertexai | पूर्ण (चरण 2) | +| बेडरोक | trustgraph-bedrock | पूर्ण (मूल स्ट्रीमिंग एपीआई) | +| एलएम स्टूडियो | trustgraph-flow | पूर्ण (ओपनएआई-संगत) | +| लैमाफाइल | trustgraph-flow | पूर्ण (ओपनएआई-संगत) | +| वीएलएलएम | trustgraph-flow | पूर्ण (ओपनएआई-संगत) | +| टीजीआई | trustgraph-flow | तय किया जाना है | +| एज़्योर | trustgraph-flow | तय किया जाना है | + +#### कार्यान्वयन पैटर्न + +ओपनएआई-संगत प्रदाताओं (ओपनएआई, एलएम स्टूडियो, लैमाफाइल, वीएलएलएम) के लिए: + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### चरण 4: एजेंट एपीआई + +चरण 4, एजेंट एपीआई तक स्ट्रीमिंग का विस्तार करता है। यह अधिक जटिल है क्योंकि +एजेंट एपीआई स्वभाव से ही मल्टी-मैसेज है (विचार → क्रिया → अवलोकन +→ दोहराव → अंतिम उत्तर)। + +#### वर्तमान एजेंट स्कीमा + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### प्रस्तावित एजेंट स्कीमा में परिवर्तन + +**परिवर्तन का अनुरोध:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**प्रतिक्रिया में परिवर्तन:** + +एजेंट अपनी तर्क प्रक्रिया के दौरान कई प्रकार के आउटपुट उत्पन्न करता है: +विचार (तर्क) +क्रियाएं (उपकरण कॉल) +अवलोकन (उपकरण परिणाम) +उत्तर (अंतिम प्रतिक्रिया) +त्रुटियाँ + +चूँकि `chunk_type` यह बताता है कि किस प्रकार की सामग्री भेजी जा रही है, इसलिए अलग-अलग +`answer`, `error`, `thought`, और `observation` फ़ील्ड को एक साथ मिलाया जा सकता है। +एक एकल `content` फ़ील्ड: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**फ़ील्ड सिमेंटिक्स:** + +`chunk_type`: यह इंगित करता है कि `content` फ़ील्ड में किस प्रकार की सामग्री है + `"thought"`: एजेंट की तर्क/सोच + `"action"`: उपयोग किए जा रहे टूल/क्रिया + `"observation"`: टूल निष्पादन का परिणाम + `"answer"`: उपयोगकर्ता के प्रश्न का अंतिम उत्तर + `"error"`: त्रुटि संदेश + +`content`: वास्तविक स्ट्रीम की सामग्री, जिसे `chunk_type` के आधार पर व्याख्यायित किया जाता है + +`end_of_message`: जब `true`, तो वर्तमान चंक प्रकार पूरा हो गया है + उदाहरण: वर्तमान विचार के लिए सभी टोकन भेजे जा चुके हैं + यह क्लाइंट को यह जानने की अनुमति देता है कि अगले चरण पर कब जाना है + +`end_of_dialog`: जब `true`, तो संपूर्ण एजेंट इंटरैक्शन पूरा हो गया है + यह स्ट्रीम में अंतिम संदेश है + +#### एजेंट स्ट्रीमिंग व्यवहार + +जब `streaming=true`: + +1. **विचार स्ट्रीमिंग:** + `chunk_type="thought"`, `end_of_message=false` के साथ कई चंक + अंतिम विचार चंक में `end_of_message=true` होता है +2. **एक्शन नोटिफिकेशन:** + `chunk_type="action"`, `end_of_message=true` के साथ एक चंक +3. **अवलोकन:** + `chunk_type="observation"` के साथ चंक(s), अंतिम में `end_of_message=true` होता है +4. **चरण 1-3 को दोहराएं** क्योंकि एजेंट तर्क करता है +5. **अंतिम उत्तर:** + `chunk_type="answer"` जिसमें `content` में अंतिम प्रतिक्रिया है + अंतिम चंक में `end_of_message=true`, `end_of_dialog=true` होता है + +**उदाहरण स्ट्रीम अनुक्रम:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +जब `streaming=false`: +वर्तमान व्यवहार संरक्षित +पूर्ण उत्तर के साथ एकल प्रतिक्रिया +`end_of_message=true`, `end_of_dialog=true` + +#### गेटवे और पायथन एपीआई + +गेटवे: एजेंट स्ट्रीमिंग के लिए नया एसएसई/वेबसोकेट एंडपॉइंट +पायथन एपीआई: नया `agent_stream()` एसिंक्रोनस जेनरेटर विधि + +-- + +## सुरक्षा संबंधी विचार + +**कोई नया आक्रमण सतह नहीं**: स्ट्रीमिंग समान प्रमाणीकरण/प्राधिकरण का उपयोग करती है +**दर सीमा**: यदि आवश्यक हो तो प्रति-टोकन या प्रति-खंड दर सीमा लागू करें +**कनेक्शन हैंडलिंग**: क्लाइंट डिस्कनेक्ट होने पर स्ट्रीम को ठीक से समाप्त करें +**टाइमआउट प्रबंधन**: स्ट्रीमिंग अनुरोधों के लिए उचित टाइमआउट हैंडलिंग की आवश्यकता होती है + +## प्रदर्शन संबंधी विचार + +**मेमोरी**: स्ट्रीमिंग से पीक मेमोरी उपयोग कम होता है (कोई पूर्ण प्रतिक्रिया बफरिंग नहीं) +**विलंबता**: पहले टोकन तक का समय काफी कम हो जाता है +**कनेक्शन ओवरहेड**: एसएसई/वेबसोकेट कनेक्शन में कीप-अलाइव ओवरहेड होता है +**पल्सर थ्रूपुट**: एक बड़े संदेश के मुकाबले कई छोटे संदेशों का व्यापार + ट्रेडऑफ़ + +## परीक्षण रणनीति + +### यूनिट टेस्ट +नए फ़ील्ड के साथ स्कीमा सीरियलाइज़ेशन/डीसेरियलाइज़ेशन +पिछड़ा संगतता (गायब फ़ील्ड डिफ़ॉल्ट का उपयोग करते हैं) +चंक असेंबली लॉजिक + +### एकीकरण परीक्षण +प्रत्येक एलएलएम प्रदाता का स्ट्रीमिंग कार्यान्वयन +गेटवे एपीआई स्ट्रीमिंग एंडपॉइंट +पायथन क्लाइंट स्ट्रीमिंग विधियाँ + +### एंड-टू-एंड टेस्ट +सीएलआई टूल स्ट्रीमिंग आउटपुट +पूर्ण प्रवाह: क्लाइंट → गेटवे → पल्सर → एलएलएम → वापस +मिश्रित स्ट्रीमिंग/गैर-स्ट्रीमिंग वर्कलोड + +### पिछड़ा संगतता परीक्षण +मौजूदा क्लाइंट बिना किसी संशोधन के काम करते हैं +गैर-स्ट्रीमिंग अनुरोध समान रूप से व्यवहार करते हैं + +## माइग्रेशन योजना + +### चरण 1: बुनियादी ढांचा +स्कीमा परिवर्तन तैनात करें (पिछड़ा संगत) +गेटवे एपीआई अपडेट तैनात करें +पायथन एपीआई अपडेट तैनात करें +सीएलआई टूल अपडेट जारी करें + +### चरण 2: वर्टेक्सएआई +वर्टेक्सएआई स्ट्रीमिंग कार्यान्वयन को तैनात करें। +परीक्षण वर्कलोड के साथ सत्यापन करें। + +### चरण 3: सभी प्रदाता +प्रदाता अपडेट को धीरे-धीरे लागू करें। +समस्याओं की निगरानी करें। + +### चरण 4: एजेंट एपीआई +एजेंट स्कीमा परिवर्तनों को तैनात करें। +एजेंट स्ट्रीमिंग कार्यान्वयन को तैनात करें। +दस्तावेज़ को अपडेट करें। + +## समयरेखा + +| चरण | विवरण | निर्भरताएँ | +|-------|-------------|--------------| +| चरण 1 | बुनियादी ढांचा | कोई नहीं | +| चरण 2 | वर्टेक्सएआई प्रूफ ऑफ कॉन्सेप्ट | चरण 1 | +| चरण 3 | सभी प्रदाता | चरण 2 | +| चरण 4 | एजेंट एपीआई | चरण 3 | + +## डिज़ाइन निर्णय + +निम्नलिखित प्रश्नों को विनिर्देश के दौरान हल किया गया था: + +1. **स्ट्रीमिंग में टोकन गणना**: टोकन गणनाएँ अंतर हैं, न कि चल रही कुल। + उपभोक्ता आवश्यकतानुसार उन्हें जोड़ सकते हैं। यह अधिकांश प्रदाता द्वारा उपयोग की रिपोर्टिंग के तरीके से मेल खाता है + और कार्यान्वयन को सरल बनाता है। + +2. **स्ट्रीम में त्रुटि प्रबंधन**: यदि कोई त्रुटि होती है, तो `error` फ़ील्ड भरा जाता है और अन्य फ़ील्ड की आवश्यकता नहीं होती है। त्रुटि हमेशा अंतिम संचार होती है - इसके बाद कोई अन्य संदेश अनुमत या अपेक्षित नहीं हैं। + 2. **स्ट्रीम में त्रुटि प्रबंधन**: यदि कोई त्रुटि होती है, तो ⟦CODE_0⟧ फ़ील्ड भरा जाता है और अन्य फ़ील्ड की आवश्यकता नहीं होती है। त्रुटि हमेशा अंतिम संचार होती है - इसके बाद कोई अन्य संदेश अनुमत या अपेक्षित नहीं हैं। + 2. **स्ट्रीम में त्रुटि प्रबंधन**: यदि कोई त्रुटि होती है, तो ⟦CODE_0⟧ फ़ील्ड भरा जाता है और अन्य फ़ील्ड की आवश्यकता नहीं होती है। त्रुटि हमेशा अंतिम संचार होती है - इसके बाद कोई अन्य संदेश अनुमत या अपेक्षित नहीं हैं। + एक त्रुटि। एलएलएम/प्रॉम्प्ट स्ट्रीम के लिए, `end_of_stream=true`। एजेंट स्ट्रीम के लिए, + `chunk_type="error"` को `end_of_dialog=true` के साथ। + +3. **आंशिक प्रतिक्रिया पुनर्प्राप्ति**: संदेश प्रोटोकॉल (पल्सर) मजबूत है, + इसलिए संदेश-स्तर पर पुनः प्रयास की आवश्यकता नहीं है। यदि कोई क्लाइंट स्ट्रीम को खो देता है + या डिस्कनेक्ट हो जाता है, तो उसे पूरी अनुरोध को शुरुआत से फिर से प्रयास करना होगा। + +4. **त्वरित सेवा स्ट्रीमिंग**: स्ट्रीमिंग केवल टेक्स्ट (`text`) के लिए समर्थित है। + प्रतिक्रियाओं के लिए, संरचित (`object`) प्रतिक्रियाओं के लिए नहीं। त्वरित सेवा पहले से ही जानती है कि + आउटपुट JSON होगा या टेक्स्ट-आधारित, यह प्रॉम्प्ट टेम्पलेट पर निर्भर करता है। यदि JSON-आउटपुट प्रॉम्प्ट के लिए + एक स्ट्रीमिंग अनुरोध किया जाता है, तो + सेवा को या तो: + `end_of_stream=true` के साथ एक ही प्रतिक्रिया में पूरा JSON वापस करना चाहिए, या + त्रुटि के साथ स्ट्रीमिंग अनुरोध को अस्वीकार करना चाहिए + +## खुले प्रश्न + +फिलहाल कोई नहीं। + +## संदर्भ + +वर्तमान एलएलएम स्कीमा: `trustgraph-base/trustgraph/schema/services/llm.py` +वर्तमान प्रॉम्प्ट स्कीमा: `trustgraph-base/trustgraph/schema/services/prompt.py` +वर्तमान एजेंट स्कीमा: `trustgraph-base/trustgraph/schema/services/agent.py` +एलएलएम सेवा आधार: `trustgraph-base/trustgraph/base/llm_service.py` +वर्टेक्सएआई प्रदाता: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +गेटवे एपीआई: `trustgraph-base/trustgraph/api/` +सीएलआई उपकरण: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.md b/docs/tech-specs/streaming-llm-responses.md index 950610ee..5f6d9877 100644 --- a/docs/tech-specs/streaming-llm-responses.md +++ b/docs/tech-specs/streaming-llm-responses.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Streaming LLM Responses Technical Specification" +parent: "Tech Specs" +--- + # Streaming LLM Responses Technical Specification ## Overview diff --git a/docs/tech-specs/streaming-llm-responses.pt.md b/docs/tech-specs/streaming-llm-responses.pt.md new file mode 100644 index 00000000..2397cfe4 --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.pt.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "Especificação Técnica de Respostas de LLM em Streaming" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Respostas de LLM em Streaming + +> **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 a implementação do suporte a streaming para respostas de LLM +no TrustGraph. O streaming permite a entrega em tempo real de tokens gerados +à medida que são produzidos pelo LLM, em vez de esperar pela geração completa +da resposta. + +Esta implementação suporta os seguintes casos de uso: + +1. **Interfaces de Usuário em Tempo Real**: Transmita tokens para a interface do usuário à medida que são gerados, + fornecendo feedback visual imediato. +2. **Tempo de Primeiro Token Reduzido**: Os usuários veem a saída começando imediatamente + em vez de esperar pela geração completa. +3. **Tratamento de Respostas Longas**: Lidar com saídas muito longas que, de outra forma, + poderiam causar timeout ou exceder os limites de memória. +4. **Aplicações Interativas**: Permitir interfaces de bate-papo e agentes responsivas. + +## Objetivos + +**Compatibilidade com Versões Anteriores**: Os clientes existentes que não utilizam streaming continuam a funcionar + sem modificação. +**Design de API Consistente**: O streaming e o uso sem streaming utilizam os mesmos padrões de esquema + com mínima divergência. +**Flexibilidade do Provedor**: Suporte ao streaming quando disponível, com uma alternativa + suave quando não disponível. +**Implementação Gradual**: Implementação incremental para reduzir o risco. +**Suporte de Ponta a Ponta**: Streaming do provedor de LLM até as aplicações do cliente + via Pulsar, Gateway API e Python API. + +## Contexto + +### Arquitetura Atual + +O fluxo atual de conclusão de texto de LLM opera da seguinte forma: + +1. O cliente envia `TextCompletionRequest` com os campos `system` e `prompt`. +2. O serviço de LLM processa a solicitação e espera pela geração completa. +3. Um único `TextCompletionResponse` é retornado com a string `response` completa. + +Esquema atual (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### Limitações Atuais + +**Latência**: Os usuários devem esperar pela geração completa antes de ver qualquer resultado. +**Risco de Timeout**: Gerações longas podem exceder os limites de tempo de espera do cliente. +**Má Experiência do Usuário**: A falta de feedback durante a geração cria a percepção de lentidão. +**Uso de Recursos**: As respostas completas devem ser armazenadas em memória. + +Esta especificação aborda essas limitações, permitindo a entrega incremental de respostas, mantendo total compatibilidade com versões anteriores. + + +## Design Técnico + +### Fase 1: Infraestrutura + +A Fase 1 estabelece a base para o streaming, modificando esquemas, APIs e ferramentas de linha de comando. + + +#### Alterações no Esquema + +##### Esquema LLM (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**Alterações na Requisição:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: Quando `true`, solicita a entrega de resposta em fluxo. +Padrão: `false` (o comportamento existente é preservado). + +**Alterações na Resposta:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: Quando `true`, indica que esta é a resposta final (ou única). +Para solicitações não em fluxo contínuo: Resposta única com `end_of_stream=true`. +Para solicitações em fluxo contínuo: Múltiplas respostas, todas com `end_of_stream=false` + exceto a última. + +##### Esquema do Prompt (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +O serviço de prompt envolve a conclusão de texto, portanto, ele segue o mesmo padrão: + +**Alterações na Solicitação:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**Alterações na Resposta:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### Alterações na API Gateway + +A API Gateway deve expor capacidades de streaming para clientes HTTP/WebSocket. + +**Atualizações da API REST:** + +`POST /api/v1/text-completion`: Aceitar o parâmetro `streaming` no corpo da requisição +O comportamento da resposta depende da flag de streaming: + `streaming=false`: Resposta JSON única (comportamento atual) + `streaming=true`: Fluxo de eventos enviados pelo servidor (SSE) ou mensagens WebSocket + +**Formato da Resposta (Streaming):** + +Cada bloco transmitido segue a mesma estrutura de esquema: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +Trecho final: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### Alterações na API Python + +A API do cliente Python deve suportar tanto o modo de streaming quanto o modo não-streaming, +mantendo a compatibilidade com versões anteriores. + +**Atualizações do LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**Atualizações do PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +Padrão semelhante com o parâmetro `streaming` e a variante de gerador assíncrono. + +#### Alterações na Ferramenta de Linha de Comando (CLI) + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +Streaming habilitado por padrão para uma melhor experiência de usuário interativa. +A flag `--no-streaming` desabilita o streaming. +Quando o streaming está habilitado: Envie os tokens para a saída padrão (stdout) à medida que chegam. +Quando o streaming não está habilitado: Aguarde a resposta completa e, em seguida, envie. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +Mesmo padrão que `tg-invoke-llm`. + +#### Alterações na Classe Base do Serviço LLM + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### Fase 2: Prova de Conceito do VertexAI + +A Fase 2 implementa o streaming em um único provedor (VertexAI) para validar a +infraestrutura e permitir testes de ponta a ponta. + +#### Implementação do VertexAI + +**Módulo:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**Alterações:** + +1. Substituir `supports_streaming()` para retornar `True` +2. Implementar gerador assíncrono `generate_content_stream()` +3. Lidar com modelos Gemini e Claude (via API Anthropic do VertexAI) + +**Streaming do Gemini:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**Claude (via VertexAI Anthropic) Streaming:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### Testes + +Testes unitários para a montagem da resposta em streaming +Testes de integração com o VertexAI (Gemini e Claude) +Testes de ponta a ponta: CLI -> Gateway -> Pulsar -> VertexAI -> de volta +Testes de compatibilidade com versões anteriores: as solicitações não em streaming ainda funcionam + +-- + +### Fase 3: Todos os Provedores de LLM + +A Fase 3 estende o suporte a streaming para todos os provedores de LLM no sistema. + +#### Status de Implementação do Provedor + +Cada provedor deve: +1. **Suporte Completo a Streaming**: Implementar `generate_content_stream()` +2. **Modo de Compatibilidade**: Lidar com a flag `end_of_stream` corretamente + (retornar uma única resposta com `end_of_stream=true`) + +| Provedor | Pacote | Suporte a Streaming | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | Completo (API de streaming nativa) | +| Claude/Anthropic | trustgraph-flow | Completo (API de streaming nativa) | +| Ollama | trustgraph-flow | Completo (API de streaming nativa) | +| Cohere | trustgraph-flow | Completo (API de streaming nativa) | +| Mistral | trustgraph-flow | Completo (API de streaming nativa) | +| Azure OpenAI | trustgraph-flow | Completo (API de streaming nativa) | +| Google AI Studio | trustgraph-flow | Completo (API de streaming nativa) | +| VertexAI | trustgraph-vertexai | Completo (Fase 2) | +| Bedrock | trustgraph-bedrock | Completo (API de streaming nativa) | +| LM Studio | trustgraph-flow | Completo (compatível com OpenAI) | +| LlamaFile | trustgraph-flow | Completo (compatível com OpenAI) | +| vLLM | trustgraph-flow | Completo (compatível com OpenAI) | +| TGI | trustgraph-flow | A ser definido | +| Azure | trustgraph-flow | A ser definido | + +#### Padrão de Implementação + +Para provedores compatíveis com OpenAI (OpenAI, LM Studio, LlamaFile, vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### Fase 4: API do Agente + +A Fase 4 estende o streaming para a API do Agente. Isso é mais complexo porque a +API do Agente já é inerentemente multi-mensagem (pensamento → ação → observação +→ repetir → resposta final). + +#### Esquema Atual do Agente + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### Alterações Propostas no Esquema do Agente + +**Solicitar Alterações:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**Alterações na Resposta:** + +O agente produz múltiplos tipos de saída durante seu ciclo de raciocínio: +Pensamentos (raciocínio) +Ações (chamadas de ferramentas) +Observações (resultados das ferramentas) +Resposta (resposta final) +Erros + +Como `chunk_type` identifica o tipo de conteúdo que está sendo enviado, os campos separados +`answer`, `error`, `thought` e `observation` podem ser combinados em +um único campo `content`: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**Semântica dos Campos:** + +`chunk_type`: Indica o tipo de conteúdo presente no campo `content` + `"thought"`: Raciocínio/pensamento do agente + `"action"`: Ferramenta/ação sendo invocada + `"observation"`: Resultado da execução da ferramenta + `"answer"`: Resposta final à pergunta do usuário + `"error"`: Mensagem de erro + +`content`: O conteúdo transmitido, interpretado com base em `chunk_type` + +`end_of_message`: Quando `true`, o tipo de bloco atual está completo + Exemplo: Todos os tokens para o pensamento atual foram enviados + Permite que os clientes saibam quando avançar para a próxima etapa + +`end_of_dialog`: Quando `true`, toda a interação do agente está completa + Esta é a mensagem final no fluxo + +#### Comportamento de Streaming do Agente + +Quando `streaming=true`: + +1. **Streaming de pensamento:** + Múltiplos blocos com `chunk_type="thought"`, `end_of_message=false` + O bloco final do pensamento tem `end_of_message=true` +2. **Notificação de ação:** + Um único bloco com `chunk_type="action"`, `end_of_message=true` +3. **Observação:** + Bloco(s) com `chunk_type="observation"`, o final tem `end_of_message=true` +4. **Repita** as etapas 1-3 enquanto o agente raciocina +5. **Resposta final:** + `chunk_type="answer"` com a resposta final em `content` + O último bloco tem `end_of_message=true`, `end_of_dialog=true` + +**Exemplo de Sequência de Streaming:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +Quando `streaming=false`: +Comportamento atual preservado +Resposta única com resposta completa +`end_of_message=true`, `end_of_dialog=true` + +#### Gateway e API Python + +Gateway: Novo endpoint SSE/WebSocket para streaming de agentes +API Python: Novo método gerador assíncrono `agent_stream()` + +-- + +## Considerações de Segurança + +**Nenhuma nova superfície de ataque**: O streaming usa a mesma autenticação/autorização +**Limitação de taxa**: Aplique limites de taxa por token ou por bloco, se necessário +**Gerenciamento de conexão**: Termine corretamente os streams em caso de desconexão do cliente +**Gerenciamento de tempo limite**: As solicitações de streaming precisam de um tratamento de tempo limite adequado + +## Considerações de Desempenho + +**Memória**: O streaming reduz o uso máximo de memória (sem bufferização completa da resposta) +**Latência**: O tempo para o primeiro token é significativamente reduzido +**Sobrecarga de conexão**: As conexões SSE/WebSocket têm uma sobrecarga de keep-alive +**Throughput do Pulsar**: Múltiplas mensagens pequenas vs. uma única mensagem grande + tradeoff + +## Estratégia de Testes + +### Testes Unitários +Serialização/desserialização de esquema com novos campos +Compatibilidade com versões anteriores (campos ausentes usam valores padrão) +Lógica de montagem de blocos + +### Testes de Integração +Implementação de streaming de cada provedor de LLM +Pontos finais de streaming da API Gateway +Métodos de streaming do cliente Python + +### Testes de Ponta a Ponta +Saída de streaming da ferramenta CLI +Fluxo completo: Cliente → Gateway → Pulsar → LLM → de volta +Cargas de trabalho mistas de streaming/não streaming + +### Testes de Compatibilidade com Versões Anteriores +Clientes existentes funcionam sem modificação +As solicitações não de streaming se comportam de forma idêntica + +## Plano de Migração + +### Fase 1: Infraestrutura +Implante as alterações de esquema (compatível com versões anteriores) +Implante as atualizações da API Gateway +Implante as atualizações da API Python +Lance as atualizações da ferramenta CLI + +### Fase 2: VertexAI +Implementar a implementação de streaming do VertexAI +Validar com cargas de trabalho de teste + +### Fase 3: Todos os Provedores +Implementar as atualizações do provedor de forma incremental +Monitorar para identificar problemas + +### Fase 4: API do Agente +Implementar as alterações do esquema do agente +Implementar a implementação de streaming do agente +Atualizar a documentação + +## Cronograma + +| Fase | Descrição | Dependências | +|-------|-------------|--------------| +| Fase 1 | Infraestrutura | Nenhum | +| Fase 2 | Prova de Conceito do VertexAI | Fase 1 | +| Fase 3 | Todos os Provedores | Fase 2 | +| Fase 4 | API do Agente | Fase 3 | + +## Decisões de Design + +As seguintes perguntas foram resolvidas durante a especificação: + +1. **Contagem de Tokens no Streaming**: As contagens de tokens são diferenças, não totais cumulativos. + Os consumidores podem somá-las, se necessário. Isso corresponde à forma como a maioria dos provedores relata + o uso e simplifica a implementação. + +2. **Tratamento de Erros em Streams**: Se ocorrer um erro, o campo `error` é + preenchido e nenhum outro campo é necessário. Um erro é sempre a comunicação final - nenhuma mensagem subsequente é permitida ou esperada após + isso. + um erro. Para fluxos de LLM/Prompt, `end_of_stream=true`. Para fluxos de Agente, + `chunk_type="error"` com `end_of_dialog=true`. + +3. **Recuperação Parcial de Respostas**: O protocolo de mensagens (Pulsar) é resiliente, + portanto, a repetição em nível de mensagem não é necessária. Se um cliente perder o controle do fluxo + ou desconectar, ele deve repetir a solicitação completa do zero. + +4. **Streaming de Respostas Rápidas**: O streaming é suportado apenas para respostas de texto (`text`). + As respostas estruturadas (`object`) não são suportadas. O serviço de respostas rápidas sabe, + desde o início, se a saída será JSON ou texto, com base no modelo da solicitação. Se + uma solicitação de streaming for feita para uma solicitação de saída JSON, o + serviço deve: + Retornar o JSON completo em uma única resposta com `end_of_stream=true`, ou + Rejeitar a solicitação de streaming com um erro. + +## Perguntas Abertas + +Nenhum neste momento. + +## Referências + +Esquema atual do LLM: `trustgraph-base/trustgraph/schema/services/llm.py` +Esquema atual do prompt: `trustgraph-base/trustgraph/schema/services/prompt.py` +Esquema atual do agente: `trustgraph-base/trustgraph/schema/services/agent.py` +Serviço base do LLM: `trustgraph-base/trustgraph/base/llm_service.py` +Provedor VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +API de gateway: `trustgraph-base/trustgraph/api/` +Ferramentas de linha de comando: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.ru.md b/docs/tech-specs/streaming-llm-responses.ru.md new file mode 100644 index 00000000..9b4f618c --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.ru.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "Техническая спецификация потоковой передачи ответов LLM" +parent: "Russian (Beta)" +--- + +# Техническая спецификация потоковой передачи ответов LLM + +> **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. + +## Обзор + +Эта спецификация описывает реализацию поддержки потоковой передачи для ответов LLM +в TrustGraph. Потоковая передача обеспечивает доставку сгенерированных +токенов в режиме реального времени по мере их создания LLM, а не после +завершения полной генерации ответа. + +Эта реализация поддерживает следующие сценарии использования: + +1. **Интерфейсы пользователя в реальном времени**: Передавайте токены в пользовательский интерфейс по мере их генерации, + обеспечивая немедленную визуальную обратную связь. +2. **Сокращение времени до первого токена**: Пользователи видят вывод сразу, + а не после полной генерации. +3. **Обработка очень длинных ответов**: Обрабатывайте очень длинные ответы, которые в противном случае + могли бы привести к таймаутам или превышению лимитов памяти. +4. **Интерактивные приложения**: Обеспечьте отзывчивые чат-интерфейсы и интерфейсы агентов. + +## Цели + +**Обратная совместимость**: Существующие клиенты, не использующие потоковую передачу, продолжают работать + без изменений. +**Согласованный дизайн API**: Потоковая передача и не потоковая передача используют одни и те же схемы + с минимальными отклонениями. +**Гибкость для поставщиков**: Поддержка потоковой передачи, где это возможно, и плавный + переход к не потоковой передаче, где это невозможно. +**Поэтапное внедрение**: Постепенная реализация для снижения рисков. +**Комплексная поддержка**: Потоковая передача от поставщика LLM до клиентских + приложений через Pulsar, Gateway API и Python API. + +## Обзор + +### Текущая архитектура + +Текущий процесс текстового завершения LLM работает следующим образом: + +1. Клиент отправляет `TextCompletionRequest` с полями `system` и `prompt`. +2. Сервис LLM обрабатывает запрос и ожидает полной генерации. +3. Возвращается один `TextCompletionResponse` с полной строкой `response`. + +Текущая схема (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### Текущие ограничения + +**Задержка**: Пользователи должны ждать завершения генерации, прежде чем увидеть какой-либо результат. +**Риск превышения времени ожидания**: Длительная генерация может превысить лимиты времени ожидания клиента. +**Плохой пользовательский опыт**: Отсутствие обратной связи во время генерации создает ощущение медленной работы. +**Использование ресурсов**: Полные ответы должны быть буферизованы в памяти. + +Эта спецификация решает эти ограничения, обеспечивая постепенную передачу ответа, при этом сохраняя полную обратную совместимость. + + +## Техническое проектирование + +### Фаза 1: Инфраструктура + +Фаза 1 закладывает основу для потоковой передачи путем изменения схем, API и инструментов командной строки. + + +#### Изменения в схемах + +##### Схема LLM (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**Изменения в запросах:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: Когда `true`, запрашивается потоковая доставка ответа. +По умолчанию: `false` (сохранено существующее поведение). + +**Изменения в ответе:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: Когда `true`, указывает на то, что это окончательный (или единственный) ответ. +Для нестриминговых запросов: Один ответ с `end_of_stream=true`. +Для стриминговых запросов: Множественные ответы, все с `end_of_stream=false`, + за исключением последнего. + +##### Схема запроса (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +Сервис запросов оборачивает завершение текста, поэтому он следует той же схеме: + +**Изменения в запросе:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**Изменения в ответе:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### Изменения API шлюза + +API шлюз должен предоставлять возможности потоковой передачи данных для клиентов HTTP/WebSocket. + +**Обновления REST API:** + +`POST /api/v1/text-completion`: Принимать параметр `streaming` в теле запроса +Поведение ответа зависит от флага потоковой передачи: + `streaming=false`: Одиночный ответ в формате JSON (текущее поведение) + `streaming=true`: Поток событий от сервера (SSE) или сообщения WebSocket + +**Формат ответа (потоковая передача):** + +Каждый фрагмент, передаваемый потоком, имеет одинаковую структуру схемы: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +Заключительный раздел: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### Изменения в API Python + +API клиента Python должен поддерживать как потоковый, так и не потоковый режимы, +при этом сохраняя обратную совместимость. + +**Обновления LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**Обновления PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +Аналогичный шаблон с параметром `streaming` и вариантом асинхронного генератора. + +#### Изменения инструмента командной строки + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +По умолчанию включен режим потоковой передачи для улучшения интерактивного пользовательского опыта. +Флаг `--no-streaming` отключает режим потоковой передачи. +В режиме потоковой передачи: выводите токены в стандартный вывод по мере их поступления. +В режиме, когда потоковая передача отключена: дождитесь получения полного ответа, а затем выведите его. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +Такой же шаблон, как у `tg-invoke-llm`. + +#### Изменения базового класса LLM Service. + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### Фаза 2: Проверка концепции VertexAI + +Фаза 2 реализует потоковую передачу данных в одном провайдере (VertexAI) для проверки +инфраструктуры и обеспечения сквозного тестирования. + +#### Реализация VertexAI + +**Модуль:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**Изменения:** + +1. Переопределить `supports_streaming()` для возврата `True` +2. Реализовать асинхронный генератор `generate_content_stream()` +3. Поддержка моделей Gemini и Claude (через VertexAI Anthropic API) + +**Потоковая передача данных Gemini:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**Claude (через VertexAI Anthropic) в режиме потоковой передачи:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### Тестирование + +Юнит-тесты для сборки потоковых ответов +Интеграционные тесты с VertexAI (Gemini и Claude) +Комплексные тесты: CLI -> Gateway -> Pulsar -> VertexAI -> back +Тесты обратной совместимости: Непотоковые запросы по-прежнему работают + +-- + +### Фаза 3: Все провайдеры LLM + +Фаза 3 расширяет поддержку потоковой передачи для всех провайдеров LLM в системе. + +#### Статус реализации для каждого провайдера + +Каждый провайдер должен либо: +1. **Полная поддержка потоковой передачи**: Реализовать `generate_content_stream()` +2. **Режим совместимости**: Правильно обрабатывать флаг `end_of_stream` + (возвращать единый ответ с `end_of_stream=true`) + +| Провайдер | Пакет | Поддержка потоковой передачи | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | Полная (нативная API потоковой передачи) | +| Claude/Anthropic | trustgraph-flow | Полная (нативная API потоковой передачи) | +| Ollama | trustgraph-flow | Полная (нативная API потоковой передачи) | +| Cohere | trustgraph-flow | Полная (нативная API потоковой передачи) | +| Mistral | trustgraph-flow | Полная (нативная API потоковой передачи) | +| Azure OpenAI | trustgraph-flow | Полная (нативная API потоковой передачи) | +| Google AI Studio | trustgraph-flow | Полная (нативная API потоковой передачи) | +| VertexAI | trustgraph-vertexai | Полная (Фаза 2) | +| Bedrock | trustgraph-bedrock | Полная (нативная API потоковой передачи) | +| LM Studio | trustgraph-flow | Полная (совместима с OpenAI) | +| LlamaFile | trustgraph-flow | Полная (совместима с OpenAI) | +| vLLM | trustgraph-flow | Полная (совместима с OpenAI) | +| TGI | trustgraph-flow | Будет определено | +| Azure | trustgraph-flow | Будет определено | + +#### Шаблон реализации + +Для провайдеров, совместимых с OpenAI (OpenAI, LM Studio, LlamaFile, vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### Фаза 4: API агента + +Фаза 4 расширяет потоковую передачу на API агента. Это более сложный процесс, поскольку +API агента изначально предназначен для работы с несколькими сообщениями (мысль → действие → наблюдение +→ повтор → окончательный ответ). + +#### Текущая схема агента + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### Предлагаемые изменения схемы агента + +**Запрос изменений:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**Изменения в ответах:** + +Агент генерирует несколько типов выходных данных в процессе рассуждения: +Мысли (рассуждения) +Действия (вызовы инструментов) +Наблюдения (результаты работы инструментов) +Ответ (окончательный ответ) +Ошибки + +Поскольку `chunk_type` указывает на тип передаваемого контента, отдельные +поля `answer`, `error`, `thought` и `observation` можно объединить в +одно поле `content`: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**Семантика полей:** + +`chunk_type`: Указывает, какой тип содержимого находится в поле `content` + `"thought"`: Рассуждения/мысли агента + `"action"`: Используемый инструмент/действие + `"observation"`: Результат выполнения инструмента + `"answer"`: Окончательный ответ на вопрос пользователя + `"error"`: Сообщение об ошибке + +`content`: Фактическое потоковое содержимое, интерпретируемое на основе `chunk_type` + +`end_of_message`: Когда `true`, текущий тип фрагмента завершен + Пример: Все токены для текущей мысли были отправлены + Позволяет клиентам знать, когда переходить к следующему этапу + +`end_of_dialog`: Когда `true`, все взаимодействие с агентом завершено + Это последнее сообщение в потоке + +#### Поведение потоковой передачи агента + +Когда `streaming=true`: + +1. **Потоковая передача мыслей:** + Несколько фрагментов с `chunk_type="thought"`, `end_of_message=false` + Последний фрагмент мысли содержит `end_of_message=true` +2. **Уведомление о действии:** + Один фрагмент с `chunk_type="action"`, `end_of_message=true` +3. **Наблюдение:** + Один или несколько фрагментов с `chunk_type="observation"`, последний содержит `end_of_message=true` +4. **Повторяйте** шаги 1-3, пока агент рассуждает +5. **Окончательный ответ:** + `chunk_type="answer"` с окончательным ответом в `content` + Последний фрагмент содержит `end_of_message=true`, `end_of_dialog=true` + +**Пример последовательности потоковой передачи:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +Когда `streaming=false`: +Текущее поведение сохранено +Единый ответ с полным ответом +`end_of_message=true`, `end_of_dialog=true` + +#### Шлюз и Python API + +Шлюз: Новый SSE/WebSocket endpoint для потоковой передачи данных от агента +Python API: Новый асинхронный генератор `agent_stream()` + +-- + +## Соображения безопасности + +**Отсутствие новых уязвимостей**: Потоковая передача использует ту же аутентификацию/авторизацию +**Ограничение скорости**: При необходимости применяйте ограничения скорости на токен или на фрагмент +**Обработка соединений**: Правильно завершайте потоки при отключении клиента +**Управление временем ожидания**: Запросы потоковой передачи требуют соответствующей обработки времени ожидания + +## Соображения производительности + +**Память**: Потоковая передача снижает пиковое использование памяти (без полной буферизации ответа) +**Задержка**: Время до первого токена значительно сокращено +**Накладные расходы на соединение**: Соединения SSE/WebSocket имеют накладные расходы на поддержание соединения +**Производительность Pulsar**: Несколько небольших сообщений против одного большого сообщения - компромисс + tradeoff + +## Стратегия тестирования + +### Юнит-тесты +Сериализация/десериализация схемы с новыми полями +Обратная совместимость (отсутствующие поля используют значения по умолчанию) +Логика сборки фрагментов + +### Интеграционные тесты +Реализация потоковой передачи каждого поставщика LLM +Потоковые конечные точки API шлюза +Методы потоковой передачи клиента на Python + +### Комплексные тесты +Вывод потоковой передачи инструмента командной строки +Полный поток: Клиент → Шлюз → Pulsar → LLM → обратно +Смешанные потоковые и не потоковые рабочие нагрузки + +### Тесты обратной совместимости +Существующие клиенты работают без изменений +Запросы без потоковой передачи ведут себя идентично + +## План миграции + +### Фаза 1: Инфраструктура +Развертывание изменений схемы (обратная совместимость) +Развертывание обновлений API шлюза +Развертывание обновлений Python API +Выпуск обновлений инструмента командной строки + +### Фаза 2: VertexAI +Развернуть поточную реализацию VertexAI. +Проверить с помощью тестовых нагрузок. + +### Фаза 3: Все провайдеры +Постепенно внедрять обновления для провайдеров. +Отслеживать наличие проблем. + +### Фаза 4: API агента +Развернуть изменения схемы агента. +Развернуть поточную реализацию агента. +Обновить документацию. + +## График + +| Фаза | Описание | Зависимости | +|-------|-------------|--------------| +| Фаза 1 | Инфраструктура | Отсутствуют | +| Фаза 2 | VertexAI, пилотный проект | Фаза 1 | +| Фаза 3 | Все провайдеры | Фаза 2 | +| Фаза 4 | API агента | Фаза 3 | + +## Принятые решения по проектированию + +В процессе разработки спецификации были решены следующие вопросы: + +1. **Количество токенов в потоке**: Количество токенов указывается как разница, а не как текущая сумма. + Потребители могут суммировать их, если это необходимо. Это соответствует тому, как большинство провайдеров + сообщают об использовании и упрощает реализацию. + +2. **Обработка ошибок в потоках**: В случае возникновения ошибки, поле `error` + заполняется, и другие поля не требуются. Ошибка всегда является последним + сообщением - после ошибки не допускаются и не ожидаются последующие сообщения. + Для потоков LLM/Prompt: `end_of_stream=true`. Для потоков Agent: + `chunk_type="error"` с `end_of_dialog=true`. + +3. **Восстановление после частичного ответа**: Протокол обмена сообщениями (Pulsar) устойчив, + поэтому повторная отправка сообщений на уровне отдельных сообщений не требуется. + Если клиент теряет отслеживание потока или отключается, он должен повторить +полный запрос с самого начала. +4. **Быстрая потоковая передача**: Потоковая передача поддерживается только для текстовых ответов (`text`). + ответы, а не для структурированных (`object`) ответов. Сервис запросов знает заранее, + будет ли вывод в формате JSON или текста, в зависимости от шаблона запроса. Если + выполняется запрос на потоковую передачу для запроса, предназначенного для вывода JSON, + сервис должен либо: + Вернуть полный JSON в одном ответе с `end_of_stream=true`, или + Отклонить запрос на потоковую передачу с ошибкой. + +## Открытые вопросы + +На данный момент их нет. + +## Ссылки + +Текущая схема LLM: `trustgraph-base/trustgraph/schema/services/llm.py` +Текущая схема запросов: `trustgraph-base/trustgraph/schema/services/prompt.py` +Текущая схема агента: `trustgraph-base/trustgraph/schema/services/agent.py` +Базовый URL службы LLM: `trustgraph-base/trustgraph/base/llm_service.py` +Провайдер VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +API шлюза: `trustgraph-base/trustgraph/api/` +Инструменты CLI: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.sw.md b/docs/tech-specs/streaming-llm-responses.sw.md new file mode 100644 index 00000000..0e637be5 --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.sw.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "Vigezo vya Kiufundi vya Utoaji wa Majibu ya LLM kwa Kutiririsha" +parent: "Swahili (Beta)" +--- + +# Vigezo vya Kiufundi vya Utoaji wa Majibu ya LLM kwa Kutiririsha + +> **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 + +Vigezo hivi vinaelezea utekelezaji wa msaada wa utiririshaji kwa majibu ya LLM +katika TrustGraph. Utiririshaji unawezesha utoaji wa wakati halisi wa alama (tokens) +zinazozalishwa na LLM, badala ya kusubiri hadi majibu kamili yatengenezwe. + + +Utendaji huu unaunga mkono matumizi yafuatayo: + +1. **Mawasiliano ya Mtumiaji ya Kawaida**: Tuma alama kwenye UI wakati zinaozalishwa, + huku ukitoa maoni ya kuonekana mara moja. +2. **Punguuzo la Muda wa Alama ya Kwanza**: Watumiaji huona matokeo mara moja + badala ya kusubiri hadi utengenezaji kamili utimalike. +3. **Usimamizi wa Majibu Marefu**: Shirikisha matokeo marefu sana ambayo vinginevyo + yanaweza kusababisha kukatika au kuzidi mipaka ya kumbukumbu. +4. **Matumizi Tendo**: Wezesha mawasiliano na mawakala yenye majibu. + +## Lengo + +**Ulinganishaji na Mifumo ya Zamani**: Wateja wa zamani ambao hawatumiwi teknolojia ya utiririshaji wanaendelea kufanya kazi + bila mabadiliko. +**Muundo wa API Unaofuata Kanuni**: Utiririshaji na mfumo ambao hautiririshi hutumia muundo sawa + na tofauti ndogo. +**Uwezo wa Mtoa Huduma**: Kusaidia utiririshaji pale unapopatikana, na + utaratibu wa kurejesha pale unapokosekana. +**Utekelezaji Hatua kwa Hatua**: Utaratibu wa kutekeleza hatua kwa hatua ili kupunguza hatari. +**Usaidizi Kamili**: Utiririshaji kutoka kwa mtoa huduma wa LLM hadi kwa programu + za mteja kupitia Pulsar, Gateway API, na Python API. + +## Asili + +### Muundo wa Sasa + +Mchakato wa sasa wa kukamilisha maandishi wa LLM unafanya kazi kama ifuatavyo: + +1. Mteja hutuma `TextCompletionRequest` pamoja na sehemu za `system` na `prompt`. +2. Huduma ya LLM huchakata ombi na kusubiri uzalishaji kamili. +3. `TextCompletionResponse` moja inarejeshwa pamoja na `response` kamili. + +Muundo wa sasa (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### Marekebisho ya Sasa + +**Ucheleweshaji**: Watumiaji lazima wasubiri hadi utengenezaji kukamilika kabisa kabla ya kuona matokeo yoyote. +**Hatari ya Muda wa Kufikia (Timeout)**: Utengenezaji mrefu unaweza kuzidi mipaka ya muda wa kufikia ya mteja. +**Uzoefu duni wa mtumiaji (UX)**: Hakuna maelezo wakati wa utengenezaji huunda hisia ya utaratibu polepole. +**Matumizi ya Rasilimali**: Majibu kamili lazima yakahifadhiwe katika kumbukumbu. + +Maelekezo haya yanashughulikia mapungufu haya kwa kuwezesha utoaji wa majibu kwa hatua, +huku ikiendelea kudumisha utangamano kamili wa zamani. + +## Muundo wa Kiufundi + +### Awamu ya 1: Miundombinu + +Awamu ya 1 huunda msingi wa utiririshaji kwa kufanya mabadiliko katika muundo, API, +na zana za CLI. + +#### Mabadiliko ya Muundo + +##### Muundo wa LLM (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**Mabadiliko ya Ombi:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: Wakati `true`, huomba utoaji wa majibu kwa njia ya mtiririko. +Chaguya: `false` (tabia iliyopo inahifadhiwa). + +**Mabadiliko ya Majibu:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: Wakati `true`, inaonyesha kwamba hii ndiyo jibu la mwisho (au pekee). +Kwa ombi lisilo la utiririshaji: Jibu moja na `end_of_stream=true`. +Kwa ombi la utiririshaji: Majibu mengi, yote na `end_of_stream=false`. + isipokuwa jibu la mwisho. + +##### Muundo wa Ombi (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +Huduma ya ombi inajumuisha kukamilisha maandishi, kwa hivyo inafuata muundo sawa: + +**Mabadiliko ya Ombi:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**Mabadiliko ya Majibu:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### Mabadiliko ya API ya Langara + +API ya Langara lazima iweze kuonyesha uwezo wa utiririshaji kwa wateja wa HTTP/WebSocket. + +**Sasisho za API ya REST:** + +`POST /api/v1/text-completion`: Kukubali parameter `streaming` katika mwili wa ombi +Tabia ya majibu inategemea bendera ya utiririshaji: + `streaming=false`: Jibu moja la JSON (tabia ya sasa) + `streaming=true`: Mto wa Matukio Yanayotumwa na Server (SSE) au ujumbe wa WebSocket + +**Muundo wa Majibu (Utiririshaji):** + +Kila sehemu iliyoyirishwa ifuataye muundo sawa: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +Sehemu ya mwisho: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### Mabadiliko ya API ya Python + +API ya mteja wa Python lazima iunge mkono njia zote mbili za utiririshaji na zisizo za utiririshaji +huku ikiendelea kutoa utangamano na matoleo ya awali. + +**Sasisho za LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**Sasisho za PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +Mfumo sawa na parameter ya `streaming` na toleo la jenereta isiyo na usumbufu. + +#### Mabadiliko ya Zana ya CLI + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +Uhamishaji (streaming) huwezeshwa kwa chagu kuendana na uzoefu bora wa mtumiaji. +Bendera `--no-streaming` inazuia uhamishaji. +Wakati uhamishaji unafanya kazi: Tuma alama (tokens) kwenye stdout kadri zinavyofika. +Wakati uhamishaji haufanyi kazi: Subiri jibu kamili, kisha toa. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +Mfumo sawa na `tg-invoke-llm`. + +#### Mabadiliko ya Darasa Msingi la Huduma ya LLM. + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### Awamu ya 2: Uthibitisho wa Dhana wa VertexAI + +Awamu ya 2 inatekeleza utiririshaji katika mtoa huduma mmoja (VertexAI) ili kuthibitisha +miundombinu na kuwezesha majaribio ya mwisho hadi mwisho. + +#### Utendaji wa VertexAI + +**Moduli:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**Mabadiliko:** + +1. Badilisha `supports_streaming()` ili irudishe `True` +2. Leta mtayarishaji wa async `generate_content_stream()` +3. Shiriki modeli zote za Gemini na Claude (kupitia API ya VertexAI Anthropic) + +**Utiririshaji wa Gemini:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**Claude (kupitia VertexAI Anthropic) Uhamishaji wa Data:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### Mtihani + +Majaribio ya kitengo kwa ajili ya kusanyiko la majibu ya utiririshaji +Majaribio ya ujumuishaji na VertexAI (Gemini na Claude) +Majaribio kamili: CLI -> Gateway -> Pulsar -> VertexAI -> nyuma +Majaribio ya utangamano: Maombi ya isiyo ya utiririshaji bado hufanya kazi + +-- + +### Awamu ya 3: Watoa Huduma Wote wa LLM + +Awamu ya 3 inaongeza utiifu wa utiririshaji kwa watoa huduma wote wa LLM katika mfumo. + +#### Hali ya Utumiaji wa Mtoa Huduma + +Kila mtoa huduma lazima ifanye mojawapo ya yafuatayo: +1. **Utiifu Kamili wa Utiririshaji**: Tengeneza `generate_content_stream()` +2. **Njia ya Utangamano**: Shikilia bendera ya `end_of_stream` kwa usahihi + (irudishe jibu moja na `end_of_stream=true`) + +| Mtoa Huduma | Kifurushi | Utiifu wa Utiririshaji | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| Claude/Anthropic | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| Ollama | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| Cohere | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| Mistral | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| Azure OpenAI | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| Google AI Studio | trustgraph-flow | Kamili (API ya asili ya utiririshaji) | +| VertexAI | trustgraph-vertexai | Kamili (Awamu ya 2) | +| Bedrock | trustgraph-bedrock | Kamili (API ya asili ya utiririshaji) | +| LM Studio | trustgraph-flow | Kamili (Inafaa na OpenAI) | +| LlamaFile | trustgraph-flow | Kamili (Inafaa na OpenAI) | +| vLLM | trustgraph-flow | Kamili (Inafaa na OpenAI) | +| TGI | trustgraph-flow | Itatolewa baadaye | +| Azure | trustgraph-flow | Itatolewa baadaye | + +#### Mfumo wa Utumiaji + +Kwa watoa huduma wanaofaa na OpenAI (OpenAI, LM Studio, LlamaFile, vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### Awamu ya 4: API ya Wakala + +Awamu ya 4 inaongeza utiririshaji kwenye API ya Wakala. Hii ni ngumu zaidi kwa sababu +API ya Wakala tayari ni mfumo wa ujumbe mwingi (fikra → kitendo → uchunguzi +→ rudia → jibu la mwisho). + +#### Mpango wa Sasa wa Wakala + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### Mabadiliko Yanayopendekezwa ya Muundo wa Wakala + +**Omba Mabadiliko:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**Mabadiliko ya Majibu:** + +Wakala hutengeneza aina nyingi za matokeo wakati wa mchakato wake wa kufikiri: +Mawazo (ufikiri) +Vitendo (simu za zana) +Uchunguzi (matokeo ya zana) +Jibu (jibu la mwisho) +Madosa + +Kwa kuwa `chunk_type` inaonyesha aina gani ya maudhui yanatumiwa, nafasi tofauti +za `answer`, `error`, `thought`, na `observation` zinaweza kuunganishwa katika +nafasi moja ya `content`: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**Maana ya Viwanja:** + +`chunk_type`: Inaonyesha aina ya yaliyomo katika sehemu `content` + `"thought"`: Tafakari/fikra za wakala + `"action"`: Chombo/kitendo kinachotumika + `"observation"`: Matokeo ya utekelezaji wa chombo + `"answer"`: Jibu la mwisho kwa swali la mtumiaji + `"error"`: Ujumbe wa kosa + +`content`: Yaliyomo halisi yanayotiririshwa, ambayo hutafsiriwa kulingana na `chunk_type` + +`end_of_message`: Wakati `true`, aina ya sehemu ya sasa imekamilika + Mfano: Alama zote za fikra ya sasa zimetumwa + Inaruhusu wateja kujua wakati wa kuendelea na hatua inayofuata + +`end_of_dialog`: Wakati `true`, mwingiliano wote wa wakala umekamilika + Hii ndio ujumbe wa mwisho katika mtiririko + +#### Tabia ya Utiririshaji wa Wakala + +Wakati `streaming=true`: + +1. **Utiririshaji wa fikra:** + Sehemu nyingi zenye `chunk_type="thought"`, `end_of_message=false` + Sehemu ya mwisho ya fikra ina `end_of_message=true` +2. **Arifa ya kitendo:** + Sehemu moja yenye `chunk_type="action"`, `end_of_message=true` +3. **Uchunguzi:** + Sehemu(ma) yenye `chunk_type="observation"`, ya mwisho ina `end_of_message=true` +4. **Rudia** hatua za 1-3 wakati wakala anafikiri +5. **Jibu la mwisho:** + `chunk_type="answer"` yenye jibu la mwisho katika `content` + Sehemu ya mwisho ina `end_of_message=true`, `end_of_dialog=true` + +**Mfululizo wa Mfano wa Mtiririko:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +Wakati `streaming=false`: +Tabia ya sasa inahifadhiwa +Jibu moja lenye jibu kamili +`end_of_message=true`, `end_of_dialog=true` + +#### Bandari na API ya Python + +Bandari: Njia mpya ya SSE/WebSocket kwa utiririshaji wa wakala +API ya Python: Njia mpya ya `agent_stream()` ya jenereta ya async + +-- + +## Masuala ya Usalama + +**Hakuna eneo jipya la shambulio**: Utiririshaji hutumia uthibitishaji/idhini sawa +**Mipaka ya kasi**: Tumia mipaka ya kasi kwa kila tokeni au kila sehemu ikiwa inahitajika +**Usimamizi wa muunganisho**: Vunjeni kwa usahihi mitiririsho wakati mteja anakatiza +**Usimamizi wa muda**: Maombi ya utiririshaji yanahitaji usimamizi sahihi wa muda + +## Masuala ya Utendaji + +**Kumbukumbu**: Utiririshaji hupunguza matumizi ya juu ya kumbukumbu (hakuna buffering kamili ya jibu) +**Ucheleweshaji**: Muda wa hadi tokeni ya kwanza umepunguzwa sana +**Mzigo wa muunganisho**: Muunganisho wa SSE/WebSocket una mzigo wa kudumisha muunganisho +**Uwezo wa Pulsar**: Ujumbe mdogo mwingi dhidi ya ujumbe mmoja mkubwa + mbadala + +## Mkakati wa Majaribio + +### Majaribio ya Kitengo +Usanidi/uondoaji wa schema na sehemu mpya +Utangamano wa nyuma (sehemu zilizopotea hutumia chaguo-msingi) +Mantiki ya kusanyiko ya sehemu + +### Majaribio ya Uunganisho +Utaratibu wa utiririshaji wa kila mtoa huduma wa LLM +Njia za utiririshaji za API ya Bandari +Njia za utiririshaji za mteja wa Python + +### Majaribio ya Ukingo hadi Ukingo +Pato la utiririshaji la zana ya CLI +Mchakato kamili: Mteja → Bandari → Pulsar → LLM → kurudi +Mizigo mchanganyiko ya utiririshaji/isiyo ya utiririshaji + +### Majaribio ya Utangamano wa Nyuma +Wateja wazima hufanya kazi bila mabadiliko +Maombi ya utiririshaji hayatendeshwi sawa + +## Mpango wa Uhamishaji + +### Awamu ya 1: Miundombinu +Weka mabadiliko ya schema (utangamano wa nyuma) +Weka sasisho za API ya Bandari +Weka sasisho za API ya Python +Toa sasisho za zana ya CLI + +### Awamu ya 2: VertexAI +Tuma utekelezaji wa VertexAI unaotumia mtiririko. +Thibitisha kwa kutumia majaribio. + +### Awamu ya 3: Watoa Huduma Wote +Toa sasisho za watoa huduma hatua kwa hatua. +Fuatilia masuala yaliyotokea. + +### Awamu ya 4: API ya Wakala +Tuma mabadiliko ya muundo wa wakala. +Tuma utekelezaji wa mtiririko wa wakala. +Sasisha nyaraka. + +## Ratiba + +| Awamu | Maelezo | Utendaji | +|-------|-------------|--------------| +| Awamu ya 1 | Miundombinu | Hakuna | +| Awamu ya 2 | Jaribio la VertexAI | Awamu ya 1 | +| Awamu ya 3 | Watoa Huduma Wote | Awamu ya 2 | +| Awamu ya 4 | API ya Wakala | Awamu ya 3 | + +## Maamuzi ya Ubunifu + +Maswali yafuatayo yaliyulizwa yamejibiwa wakati wa maelezo: + +1. **Hesabu za Tokeni katika Mtiririko**: Hesabu za tokeni ni tofauti, sio jumla. + Wateja wanaweza kuzijumlisha ikiwa ni lazima. Hii inalingana na jinsi watoa huduma wengi wanavyoripoti + matumizi na inarahisisha utekelezaji. + +2. **Usimamizi wa Madhira katika Mitiririko**: Ikiwa hitilafu itatokea, sehemu ya `error` + itajazwa na sehemu zingine hazihitajiki. Hitilafu daima ndio mawasiliano ya mwisho + jumbe zingine za baadae haziruhusiwi au zinatarajiwa baada ya + hitilafu. Kwa mitiririko ya LLM/Prompt, `end_of_stream=true`. Kwa mitiririko ya Wakala, + `chunk_type="error"` pamoja na `end_of_dialog=true`. + +3. **Urekebishaji wa Majibu ya Kawaida**: Itifaki ya mawasiliano (Pulsar) ni thabiti, + kwa hivyo, kujaribu tena jumbe za mtu binafsi haihitajiki. Ikiwa mteja unapoteza + uhusiano wa mtiririko au kukatika, lazima ujaribu tena ombi lote kutoka mwanzo. + +4. **Mtiririko wa Huduma ya Prompt**: Mtiririko unaoendeshwa tu kwa maandishi (`text`) + majibu, sio majibu yaliyopangwa (`object`). Huduma ya prompt inajua + mapema ikiwa pato itakuwa JSON au maandishi kulingana na kiolezo cha prompt. + Ikiwa ombi la mtiririko lilitolewa kwa prompt ya pato ya JSON, huduma + inapaswa: + Kurudisha JSON kamili katika jibu moja pamoja na `end_of_stream=true`, au + Kukataa ombi la mtiririko na hitilafu + +## Maswali Yaliyobaki + +Hakuna kwa sasa. + +## Marejeleo + +Muundo wa sasa wa LLM: `trustgraph-base/trustgraph/schema/services/llm.py` +Muundo wa sasa wa prompt: `trustgraph-base/trustgraph/schema/services/prompt.py` +Muundo wa sasa wa wakala: `trustgraph-base/trustgraph/schema/services/agent.py` +Msingi wa huduma ya LLM: `trustgraph-base/trustgraph/base/llm_service.py` +Mtoa huduma wa VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +API ya lango: `trustgraph-base/trustgraph/api/` +Zana za CLI: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.tr.md b/docs/tech-specs/streaming-llm-responses.tr.md new file mode 100644 index 00000000..d452cb52 --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.tr.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "Akışlı LLM Yanıtları Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Akışlı LLM Yanıtları 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'ta LLM yanıtları için akış desteğinin uygulanmasını tanımlar. Akış, üretilen token'ların LLM tarafından üretildikleri anda gerçek zamanlı olarak iletilmesini sağlar, böylece tamamlanmış bir yanıtın oluşturulmasını beklemez. + +Bu uygulama aşağıdaki kullanım senaryolarını destekler: + + +1. **Gerçek Zamanlı Kullanıcı Arayüzleri**: Token'ları, oluşturuldukları anda kullanıcı arayüzüne aktarın ve böylece anında görsel geri bildirim sağlayın. + +2. **İlk Token'a Ulaşma Süresinin Azaltılması**: Kullanıcılar, tam oluşturma beklemeden çıktıyı hemen görmeye başlar. + +3. **Uzun Yanıtların İşlenmesi**: Aksi takdirde zaman aşımına uğrayabilecek veya bellek sınırlarını aşabilecek çok uzun çıktıları işleyin. + +4. **Etkileşimli Uygulamalar**: Duyarlı sohbet ve ajan arayüzlerini etkinleştirin. + +## Hedefler + + +**Geriye Dönük Uyumluluk**: Mevcut, akış kullanmayan istemciler, herhangi bir değişiklik yapılmadan çalışmaya devam etmelidir. + + **Tutarlı API Tasarımı**: Akışlı ve akışsız kullanım, minimum farklılıklarla aynı şema kalıplarını kullanır. + + **Sağlayıcı Esnekliği**: Akış mevcut olduğunda akışı destekleyin, aksi takdirde zarif bir şekilde geri dönün. + + **Aşamalı Dağıtım**: Riski azaltmak için kademeli uygulama. + +**Uçtan Uca Destek**: LLM sağlayıcısından Pulsar, Gateway API ve Python API aracılığıyla istemci uygulamalarına kadar akış desteği. + +## Arka Plan + +### Mevcut Mimari + + +Mevcut LLM metin tamamlama akışı aşağıdaki gibi çalışır: + +1. İstemci, `TextCompletionRequest` ile `system` ve `prompt` alanlarını gönderir. +2. LLM hizmeti, isteği işler ve tamamlanmış bir oluşturmayı bekler. +3. Tamamlanmış `response` dizesiyle tek bir `TextCompletionResponse` döndürülür. + +Mevcut şema (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### Mevcut Sınırlamalar + +**Gecikme**: Kullanıcılar, herhangi bir çıktı görmeden önce, tamamlanmış bir üretimi beklemelidir. +**Zaman Aşımı Riski**: Uzun üretmeler, istemci zaman aşımı eşiklerini aşabilir. +**Kötü Kullanıcı Deneyimi**: Üretim sırasında geri bildirim olmaması, yavaşlık algısı yaratır. +**Kaynak Kullanımı**: Tam yanıtlar bellekte tamponlanmalıdır. + +Bu özellik, art arda yanıt verme özelliğini etkinleştirerek bu sınırlamalara çözüm getirir ve aynı zamanda tam geriye dönük uyumluluğu korur. + + +## Teknik Tasarım + +### Aşama 1: Altyapı + +Aşama 1, şemaları, API'leri ve komut satırı araçlarını değiştirerek akış için temel altyapıyı oluşturur. + + +#### Şema Değişiklikleri + +##### LLM Şeması (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**İstek Değişiklikleri:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`: `true` olduğunda, akışlı yanıt gönderimi talep eder. +Varsayılan: `false` (mevcut davranış korunmuştur). + +**Yanıt Değişiklikleri:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`: `true` olduğunda, bunun son (veya tek) yanıt olduğunu gösterir. +Akış olmayan istekler için: `end_of_stream=true` ile tek bir yanıt. +Akış istekleri için: `end_of_stream=false` ile birden fazla yanıt (son yanıt hariç). + hariç. + +##### İstek Şeması (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +İstek hizmeti, metin tamamlama işlemini kapsar, bu nedenle aynı kalıbı yansıtır: + +**İstek Değişiklikleri:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**Değişiklikler:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### Ağ Geçidi API Değişiklikleri + +Ağ Geçidi API'sinin, HTTP/WebSocket istemcilerine akış yeteneklerini sunması gerekir. + +**REST API Güncellemeleri:** + +`POST /api/v1/text-completion`: İstek gövdesinde `streaming` parametresini kabul et +Yanıt davranışı, akış bayrağına bağlıdır: + `streaming=false`: Tek JSON yanıtı (mevcut davranış) + `streaming=true`: Sunucu Tarafından Gönderilen Olaylar (SSE) akışı veya WebSocket mesajları + +**Yanıt Formatı (Akış):** + +Her akış parçası, aynı şema yapısını izler: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +Son bölüm: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### Python API Değişiklikleri + +Python istemci API'si, geriye dönük uyumluluğu korurken hem akışlı hem de akışsız modları desteklemelidir. + + +**LlmClient Güncellemeleri** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**PromptClient Güncellemeleri** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +`streaming` parametresi ve asenkron üreteç varyantıyla benzer yapı. + +#### CLI Aracı Değişiklikleri + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +Daha iyi etkileşimli kullanıcı deneyimi için, akış varsayılan olarak etkindir. +`--no-streaming` bayrağı, akışı devre dışı bırakır. +Akış açıkken: Token'ları geldikleri gibi standart çıktıya yazdırın. +Akış kapalıyken: Tam yanıtı bekleyin, ardından çıktı verin. + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +`tg-invoke-llm` ile aynı kalıp. + +#### LLM Hizmeti Temel Sınıfındaki Değişiklikler + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### 2. Aşama: VertexAI Prova Çalışması + +2. Aşama, altyapıyı doğrulamak ve uçtan uca testleri sağlamak için tek bir sağlayıcıda (VertexAI) akışı uygulamaktadır. + + +#### VertexAI Uygulaması + +**Modül:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**Değişiklikler:** + +1. `supports_streaming()`'ı `True` değerini döndürecek şekilde geçersiz kılın. +2. `generate_content_stream()` asenkron oluşturucusunu uygulayın. +3. Hem Gemini hem de Claude modellerini (VertexAI Anthropic API aracılığıyla) işleyin. + +**Gemini Akışı:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**Claude (VertexAI Anthropic) Akışı:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### Test Etme + +Akış yanıtı birleştirme için birim testleri +VertexAI (Gemini ve Claude) ile entegrasyon testleri +Uçtan uca testler: CLI -> Ağ Geçidi -> Pulsar -> VertexAI -> geri +Geriye dönük uyumluluk testleri: Akış olmayan istekler hala çalışıyor + +-- + +### 3. Aşama: Tüm LLM Sağlayıcıları + +3. Aşama, akış desteğini sistemdeki tüm LLM sağlayıcılarına genişletir. + +#### Sağlayıcı Uygulama Durumu + +Her sağlayıcı aşağıdaki seçeneklerden birini uygulamalıdır: +1. **Tam Akış Desteği**: `generate_content_stream()`'ı uygulayın +2. **Uyumluluk Modu**: `end_of_stream` bayrağını doğru şekilde işleyin + (tek bir yanıt döndürün `end_of_stream=true` ile birlikte) + +| Sağlayıcı | Paket | Akış Desteği | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | Tam (yerel akış API'si) | +| Claude/Anthropic | trustgraph-flow | Tam (yerel akış API'si) | +| Ollama | trustgraph-flow | Tam (yerel akış API'si) | +| Cohere | trustgraph-flow | Tam (yerel akış API'si) | +| Mistral | trustgraph-flow | Tam (yerel akış API'si) | +| Azure OpenAI | trustgraph-flow | Tam (yerel akış API'si) | +| Google AI Studio | trustgraph-flow | Tam (yerel akış API'si) | +| VertexAI | trustgraph-vertexai | Tam (2. Aşama) | +| Bedrock | trustgraph-bedrock | Tam (yerel akış API'si) | +| LM Studio | trustgraph-flow | Tam (OpenAI ile uyumlu) | +| LlamaFile | trustgraph-flow | Tam (OpenAI ile uyumlu) | +| vLLM | trustgraph-flow | Tam (OpenAI ile uyumlu) | +| TGI | trustgraph-flow | Belirlenecek | +| Azure | trustgraph-flow | Belirlenecek | + +#### Uygulama Modeli + +OpenAI ile uyumlu sağlayıcılar (OpenAI, LM Studio, LlamaFile, vLLM) için: + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### 4. Aşama: Ajan API'si + +4. Aşama, akışı Ajan API'sine genişletmektedir. Bu, Ajan API'sinin doğası gereği zaten çok mesajlı olması nedeniyle daha karmaşıktır (düşünce → eylem → gözlem +→ tekrar → son yanıt). + + +#### Mevcut Ajan Şeması + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### Önerilen Ajan Şema Değişiklikleri + +**Değişiklik İstekleri:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**Cevap Değişiklikleri:** + +Ajan, akıl yürütme döngüsü sırasında çeşitli türde çıktılar üretir: +Düşünceler (akıl yürütme) +Eylemler (araç çağrıları) +Gözlemler (araç sonuçları) +Cevap (sonuç yanıtı) +Hatalar + +`chunk_type`, gönderilen içeriğin türünü tanımladığı için, ayrı +`answer`, `error`, `thought` ve `observation` alanları tek bir alana dönüştürülebilir. +Tek bir `content` alanı: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**Alan Anlamı:** + +`chunk_type`: `content` alanında bulunan içeriğin türünü belirtir. + `"thought"`: Aracın muhakemesi/düşüncesi. + `"action"`: Çağrılan araç/eylem. + `"observation"`: Araç çalıştırmasından elde edilen sonuç. + `"answer"`: Kullanıcının sorusuna verilen nihai cevap. + `"error"`: Hata mesajı. + +`content`: `chunk_type`'e göre yorumlanan, gerçek akış içeriği. + +`end_of_message`: `true` olduğunda, mevcut parça türü tamamlanmıştır. + Örnek: Mevcut düşünce için tüm belirteçler gönderilmiştir. + İstemcilerin bir sonraki aşamaya ne zaman geçmeleri gerektiğini bilmesini sağlar. + +`end_of_dialog`: `true` olduğunda, tüm aracı etkileşimi tamamlanmıştır. + Bu, akıştaki son mesajdır. + +#### Aracı Akış Davranışı + +`streaming=true` olduğunda: + +1. **Düşünce akışı:** + `chunk_type="thought"` ve `end_of_message=false` ile birden fazla parça. + Son düşünce parçası `end_of_message=true`'a sahiptir. +2. **Eylem bildirimi:** + `chunk_type="action"` ve `end_of_message=true` ile tek bir parça. +3. **Gözlem:** + `chunk_type="observation"` ile parçalar, son parça `end_of_message=true`'e sahiptir. +4. Aracı muhakeme ederken 1-3 adımlarını tekrarlayın. +5. **Son cevap:** + `content` içindeki son yanıtla `chunk_type="answer"`. + Son parça `end_of_message=true` ve `end_of_dialog=true`'e sahiptir. + +**Örnek Akış Sırası:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +`streaming=false` olduğunda: +Mevcut davranış korunmuştur +Tam bir cevap içeren tek bir yanıt +`end_of_message=true`, `end_of_dialog=true` + +#### Ağ Geçidi ve Python API'si + +Ağ Geçidi: Ajan akışı için yeni SSE/WebSocket uç noktası +Python API'si: Yeni `agent_stream()` asenkron oluşturucu metodu + +-- + +## Güvenlik Hususları + +**Yeni bir saldırı yüzeyi yok**: Akış, aynı kimlik doğrulama/yetkilendirme mekanizmalarını kullanır +**Hız sınırlaması**: Gerekirse, her jeton veya her parça için hız sınırları uygulayın +**Bağlantı yönetimi**: İstemci bağlantısının kesilmesi durumunda akışları düzgün bir şekilde sonlandırın +**Zaman aşımı yönetimi**: Akış istekleri için uygun zaman aşımı işleme gereklidir + +## Performans Hususları + +**Bellek**: Akış, tepe bellek kullanımını azaltır (tam yanıt tamponlama yok) +**Gecikme**: İlk jetona ulaşma süresi önemli ölçüde azaltılmıştır +**Bağlantı ek yükü**: SSE/WebSocket bağlantılarının devamlılık ek yükü vardır +**Pulsar verim**: Tek büyük mesaj yerine çok sayıda küçük mesaj + dengesi + +## Test Stratejisi + +### Birim Testleri +Yeni alanlarla şema serileştirme/deserileştirme +Geriye dönük uyumluluk (eksik alanlar için varsayılan değerler kullanılır) +Parça birleştirme mantığı + +### Entegrasyon Testleri +Her LLM sağlayıcısının akış uygulaması +Ağ Geçidi API akış uç noktaları +Python istemci akış metotları + +### Uçtan Uca Testler +CLI aracının akış çıktısı +Tam akış: İstemci → Ağ Geçidi → Pulsar → LLM → geri +Karışık akış/akış dışı iş yükleri + +### Geriye Dönük Uyumluluk Testleri +Mevcut istemciler değişiklik yapılmadan çalışır +Akış dışı istekler aynı şekilde davranır + +## Geçiş Planı + +### 1. Aşama: Altyapı +Şema değişikliklerini dağıtın (geriye dönük uyumlu) +Ağ Geçidi API güncellemelerini dağıtın +Python API güncellemelerini dağıtın +CLI aracı güncellemelerini yayınlayın + +### 2. Aşama: VertexAI +VertexAI akış uygulamasını dağıtın +Test iş yükleriyle doğrulayın + +### 3. Aşama: Tüm Sağlayıcılar +Sağlayıcı güncellemelerini aşamalı olarak yayınlayın +Sorunlar için izleyin + +### 4. Aşama: Ajan API'si +Ajan şema değişikliklerini dağıtın +Ajan akış uygulamasını dağıtın +Belgeleri güncelleyin + +## Zaman Çizelgesi + +| Aşama | Açıklama | Bağımlılıklar | +|-------|-------------|--------------| +| 1. Aşama | Altyapı | Yok | +| 2. Aşama | VertexAI PoC | 1. Aşama | +| 3. Aşama | Tüm Sağlayıcılar | 2. Aşama | +| 4. Aşama | Ajan API'si | 3. Aşama | + +## Tasarım Kararları + +Aşağıdaki sorular, belirtim sırasında çözülmüştür: + +1. **Akıştaki Jeton Sayıları**: Jeton sayıları, toplamlar değil, artışlardır. + Tüketiciler, gerekirse bunları toplayabilir. Bu, çoğu sağlayıcının kullanım + raporlama şekliyle eşleşir ve uygulamayı basitleştirir. + +2. **Akışlardaki Hata İşleme**: Bir hata oluşursa, `error` alanı + doldurulur ve diğer alanlara ihtiyaç duyulmaz. Bir hata her zaman son + iletişimdir; hata sonrasında başka mesajlara izin verilmez veya beklenmez. + LLM/İstem akışları için `end_of_stream=true`. Ajan akışları için, + `chunk_type="error"` ile `end_of_dialog=true`. + +3. **Kısmi Yanıt Kurtarma**: Mesajlaşma protokolü (Pulsar) dayanıklıdır, + bu nedenle mesaj düzeyinde yeniden deneme gerekli değildir. Bir istem, akışı + takip edemezse veya bağlantısı kesilirse, isteği baştan yeniden denemesi gerekir. + +4. **İstem Hizmeti Akışı**: Akış yalnızca metin (`text`) yanıtları için + desteklenir, yapılandırılmış (`object`) yanıtlar için değil. İstem hizmeti, + çıktının JSON mu yoksa metin tabanlı mı olacağını, istem şablonuna göre + önceden bilir. Bir akış isteği, JSON çıktılı bir istem için yapılırsa, + hizmet şunlardan birini yapmalıdır: + Tam JSON'ı tek bir yanıtla `end_of_stream=true` ile döndürün veya + Akış isteğini bir hata ile reddedin + +## Açık Sorular + +Şu anda yok. + +## Referanslar + +Mevcut LLM şeması: `trustgraph-base/trustgraph/schema/services/llm.py` +Mevcut istem şeması: `trustgraph-base/trustgraph/schema/services/prompt.py` +Mevcut ajan şeması: `trustgraph-base/trustgraph/schema/services/agent.py` +LLM hizmeti tabanı: `trustgraph-base/trustgraph/base/llm_service.py` +VertexAI sağlayıcısı: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +Ağ Geçidi API'si: `trustgraph-base/trustgraph/api/` +CLI araçları: `trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/streaming-llm-responses.zh-cn.md b/docs/tech-specs/streaming-llm-responses.zh-cn.md new file mode 100644 index 00000000..9668713a --- /dev/null +++ b/docs/tech-specs/streaming-llm-responses.zh-cn.md @@ -0,0 +1,578 @@ +--- +layout: default +title: "流式LLM响应技术规范" +parent: "Chinese (Beta)" +--- + +# 流式LLM响应技术规范 + +> **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中实现LLM响应的流式支持。流式传输允许实时交付由LLM生成的token,而不是等待完整的响应生成。 +流式传输允许实时交付由LLM生成的token,而不是等待完整的响应生成。 +流式传输允许实时交付由LLM生成的token,而不是等待完整的响应生成。 +流式传输允许实时交付由LLM生成的token,而不是等待完整的响应生成。 + +此实现支持以下用例: + +1. **实时用户界面**: 将生成的令牌流式传输到用户界面, + 从而提供即时的视觉反馈。 +2. **减少首次令牌时间**: 用户立即看到输出, + 而不是等待完整生成。 +3. **处理长响应**: 处理可能导致超时或超出内存限制的非常长的输出。 + 4. **交互式应用程序**: 启用响应迅速的聊天和代理界面。 + + +## 目标 + +**向后兼容性:** 现有的非流式客户端继续工作 + 无需修改。 +**一致的 API 设计:** 流式和非流式使用相同的模式,差异最小。 + +**提供商的灵活性:** 在可用时支持流式传输,在不可用时提供优雅的 + 回退方案。 +**分阶段推出:** 逐步实施以降低风险。 +**端到端支持:** 从 LLM 提供商到客户端 + 应用程序,通过 Pulsar、Gateway API 和 Python API 提供支持。 + +## 背景 + +### 当前架构 + +当前 LLM 文本补全流程如下: + +1. 客户端发送 `TextCompletionRequest`,包含 `system` 和 `prompt` 字段。 +2. LLM 服务处理请求并等待完整生成。 +3. 返回单个 `TextCompletionResponse`,包含完整的 `response` 字符串。 + +当前模式 (`trustgraph-base/trustgraph/schema/services/llm.py`): + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() +``` + +### 当前限制 + +**延迟:** 用户必须等待完整生成后才能看到任何输出。 +**超时风险:** 较长的生成过程可能超出客户端超时阈值。 +**糟糕的用户体验:** 在生成过程中没有反馈,会让人产生缓慢的感觉。 +**资源使用:** 完整的响应必须缓存在内存中。 + +本规范通过启用增量响应来解决这些限制,同时保持完全的向后兼容性。 + + +## 技术设计 + +### 第一阶段:基础设施 + +第一阶段通过修改模式、API 和 CLI 工具,为流式传输奠定基础。 + + +#### 模式更改 + +##### LLM 模式 (`trustgraph-base/trustgraph/schema/services/llm.py`) + +**请求更改:** + +```python +class TextCompletionRequest(Record): + system = String() + prompt = String() + streaming = Boolean() # NEW: Default false for backward compatibility +``` + +`streaming`:当 `true` 时,请求流式响应传输。 +默认:`false`(保留现有行为)。 + +**响应变更:** + +```python +class TextCompletionResponse(Record): + error = Error() + response = String() + in_token = Integer() + out_token = Integer() + model = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +`end_of_stream`:当 `true` 时,表示这是最终(或唯一的)响应。 +对于非流式请求:单个响应,包含 `end_of_stream=true`。 +对于流式请求:多个响应,全部包含 `end_of_stream=false`。 + 除了最后一个响应。 + +##### 提示模式 (`trustgraph-base/trustgraph/schema/services/prompt.py`) + +提示服务包装了文本补全功能,因此它遵循相同的模式: + +**请求更改:** + +```python +class PromptRequest(Record): + id = String() + terms = Map(String()) + streaming = Boolean() # NEW: Default false +``` + +**响应变更:** + +```python +class PromptResponse(Record): + error = Error() + text = String() + object = String() + end_of_stream = Boolean() # NEW: Indicates final message +``` + +#### 网关 API 变更 + +网关 API 必须向 HTTP/WebSocket 客户端暴露流式传输功能。 + +**REST API 更新:** + +`POST /api/v1/text-completion`: 接受请求体中的 `streaming` 参数 +响应行为取决于流式传输标志: + `streaming=false`: 单个 JSON 响应(当前行为) + `streaming=true`: 服务器发送事件 (SSE) 流或 WebSocket 消息 + +**响应格式(流式传输):** + +每个流式传输的数据块都遵循相同的模式结构: +```json +{ + "response": "partial text...", + "end_of_stream": false, + "model": "model-name" +} +``` + +最终部分: +```json +{ + "response": "final text chunk", + "end_of_stream": true, + "in_token": 150, + "out_token": 500, + "model": "model-name" +} +``` + +#### Python API 变更 + +Python 客户端 API 必须同时支持流式和非流式模式, +同时保持向后兼容性。 + +**LlmClient 更新** (`trustgraph-base/trustgraph/clients/llm_client.py`): + +```python +class LlmClient(BaseClient): + def request(self, system, prompt, timeout=300, streaming=False): + """ + Non-streaming request (backward compatible). + Returns complete response string. + """ + # Existing behavior when streaming=False + + async def request_stream(self, system, prompt, timeout=300): + """ + Streaming request. + Yields response chunks as they arrive. + """ + # New async generator method +``` + +**PromptClient 更新** (`trustgraph-base/trustgraph/base/prompt_client.py`): + +类似于使用 `streaming` 参数和异步生成器的变体。 + +#### CLI 工具更改 + +**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`): + +``` +tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id] +``` + +默认启用流式传输,以获得更好的交互式用户体验。 +`--no-streaming` 标志禁用流式传输。 +当启用流式传输时:将生成的 token 输出到标准输出,并在它们到达时立即输出。 +当禁用流式传输时:等待完整的响应,然后输出。 + +**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`): + +``` +tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id] +``` + +与 `tg-invoke-llm` 相同的模式。 + +#### LLM 服务基础类更改 + +**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`): + +```python +class LlmService(FlowProcessor): + async def on_request(self, msg, consumer, flow): + request = msg.value() + streaming = getattr(request, 'streaming', False) + + if streaming and self.supports_streaming(): + async for chunk in self.generate_content_stream(...): + await self.send_response(chunk, end_of_stream=False) + await self.send_response(final_chunk, end_of_stream=True) + else: + response = await self.generate_content(...) + await self.send_response(response, end_of_stream=True) + + def supports_streaming(self): + """Override in subclass to indicate streaming support.""" + return False + + async def generate_content_stream(self, system, prompt, model, temperature): + """Override in subclass to implement streaming.""" + raise NotImplementedError() +``` + +-- + +### 第二阶段:VertexAI 概念验证 + +第二阶段在单个提供商(VertexAI)中实现流式传输,以验证 +基础设施并实现端到端测试。 + +#### VertexAI 实施 + +**模块:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` + +**变更:** + +1. 覆盖 `supports_streaming()` 以返回 `True` +2. 实现 `generate_content_stream()` 异步生成器 +3. 处理 Gemini 和 Claude 模型(通过 VertexAI Anthropic API) + +**Gemini 流式传输:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + model_instance = self.get_model(model, temperature) + response = model_instance.generate_content( + [system, prompt], + stream=True # Enable streaming + ) + for chunk in response: + yield LlmChunk( + text=chunk.text, + in_token=None, # Available only in final chunk + out_token=None, + ) + # Final chunk includes token counts from response.usage_metadata +``` + +**Claude (通过 VertexAI Anthropic) 流式传输:** + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + with self.anthropic_client.messages.stream(...) as stream: + for text in stream.text_stream: + yield LlmChunk(text=text) + # Token counts from stream.get_final_message() +``` + +#### 测试 + +流式响应组装的单元测试 +与 VertexAI (Gemini 和 Claude) 的集成测试 +端到端测试:CLI -> 网关 -> Pulsar -> VertexAI -> 回调 +向后兼容性测试:非流式请求仍然有效 + +-- + +### 第三阶段:所有 LLM 提供商 + +第三阶段将流式支持扩展到系统中的所有 LLM 提供商。 + +#### 提供商实施状态 + +每个提供商必须: +1. **完全流式支持**: 实施 `generate_content_stream()` +2. **兼容模式**: 正确处理 `end_of_stream` 标志 + (返回单个响应,包含 `end_of_stream=true`) + +| 提供商 | 包 | 流式支持 | +|----------|---------|-------------------| +| OpenAI | trustgraph-flow | 完全 (原生流式 API) | +| Claude/Anthropic | trustgraph-flow | 完全 (原生流式 API) | +| Ollama | trustgraph-flow | 完全 (原生流式 API) | +| Cohere | trustgraph-flow | 完全 (原生流式 API) | +| Mistral | trustgraph-flow | 完全 (原生流式 API) | +| Azure OpenAI | trustgraph-flow | 完全 (原生流式 API) | +| Google AI Studio | trustgraph-flow | 完全 (原生流式 API) | +| VertexAI | trustgraph-vertexai | 完全 (第二阶段) | +| Bedrock | trustgraph-bedrock | 完全 (原生流式 API) | +| LM Studio | trustgraph-flow | 完全 (与 OpenAI 兼容) | +| LlamaFile | trustgraph-flow | 完全 (与 OpenAI 兼容) | +| vLLM | trustgraph-flow | 完全 (与 OpenAI 兼容) | +| TGI | trustgraph-flow | 待定 | +| Azure | trustgraph-flow | 待定 | + +#### 实施模式 + +对于与 OpenAI 兼容的提供商 (OpenAI, LM Studio, LlamaFile, vLLM): + +```python +async def generate_content_stream(self, system, prompt, model, temperature): + response = await self.client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt} + ], + temperature=temperature, + stream=True + ) + async for chunk in response: + if chunk.choices[0].delta.content: + yield LlmChunk(text=chunk.choices[0].delta.content) +``` + +-- + +### 第四阶段:代理 API + +第四阶段将流式传输扩展到代理 API。 这更加复杂,因为 +代理 API 本身就是多消息的(思考 → 行动 → 观察 +→ 重复 → 最终答案)。 + +#### 当前代理模式 + +```python +class AgentStep(Record): + thought = String() + action = String() + arguments = Map(String()) + observation = String() + user = String() + +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + +class AgentResponse(Record): + answer = String() + error = Error() + thought = String() + observation = String() +``` + +#### 建议的代理模式变更 + +**请求变更:** + +```python +class AgentRequest(Record): + question = String() + state = String() + group = Array(String()) + history = Array(AgentStep()) + user = String() + streaming = Boolean() # NEW: Default false +``` + +**响应变化:** + +代理在推理过程中会产生多种类型的输出: +想法(推理) +动作(工具调用) +观察结果(工具结果) +答案(最终回复) +错误 + +由于 `chunk_type` 标识了正在发送的内容类型,因此可以合并单独的 +`answer`、`error`、`thought` 和 `observation` 字段, +从而将其合并到一个 `content` 字段中: + +```python +class AgentResponse(Record): + chunk_type = String() # "thought", "action", "observation", "answer", "error" + content = String() # The actual content (interpretation depends on chunk_type) + end_of_message = Boolean() # Current thought/action/observation/answer is complete + end_of_dialog = Boolean() # Entire agent dialog is complete +``` + +**字段语义:** + +`chunk_type`: 指示 `content` 字段中包含的内容类型。 + `"thought"`: 代理的推理/思考。 + `"action"`: 正在调用的工具/动作。 + `"observation"`: 来自工具执行的结果。 + `"answer"`: 对用户问题的最终答案。 + `"error"`: 错误消息。 + +`content`: 实际的流式内容,根据 `chunk_type` 进行解释。 + +`end_of_message`: 当 `true` 时,当前块类型已完成。 + 示例:当前思考的所有 token 都已发送。 + 允许客户端知道何时进入下一个阶段。 + +`end_of_dialog`: 当 `true` 时,整个代理交互已完成。 + 这是一个流中的最终消息。 + +#### 代理流式行为 + +当 `streaming=true` 时: + +1. **思考流式传输:** + 具有 `chunk_type="thought"`、`end_of_message=false` 的多个块。 + 最终的思考块具有 `end_of_message=true`。 +2. **动作通知:** + 具有 `chunk_type="action"`、`end_of_message=true` 的单个块。 +3. **观察:** + 具有 `chunk_type="observation"` 的块(块),最终块具有 `end_of_message=true`。 +4. **重复** 1-3 步骤,直到代理完成推理。 +5. **最终答案:** + `chunk_type="answer"` 包含最终的响应,位于 `content` 中。 + 最后一个块具有 `end_of_message=true`、`end_of_dialog=true`。 + +**示例流序列:** + +``` +{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false} +{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false} +{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false} +{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false} +{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false} +{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true} +``` + +当 `streaming=false`: +当前行为保持不变 +提供完整的答案的单个响应 +`end_of_message=true`, `end_of_dialog=true` + +#### 网关和 Python API + +网关:用于代理流的新 SSE/WebSocket 端点 +Python API:新的 `agent_stream()` 异步生成器方法 + +-- + +## 安全注意事项 + +**没有新的攻击面**:流式传输使用相同的身份验证/授权机制 +**速率限制**:如果需要,请应用每个令牌或每个分块的速率限制 +**连接处理**:在客户端断开连接时,正确终止流 +**超时管理**:流式传输请求需要适当的超时处理 + +## 性能注意事项 + +**内存**:流式传输减少了峰值内存使用量(没有完整的响应缓冲) +**延迟**:首次令牌的时间显著减少 +**连接开销**:SSE/WebSocket 连接具有保活开销 +**Pulsar 吞吐量**:多个小消息与单个大消息之间的权衡 + tradeoff + +## 测试策略 + +### 单元测试 +使用新字段的模式序列化/反序列化 +向后兼容性(缺少字段使用默认值) +分块组装逻辑 + +### 集成测试 +每个 LLM 提供商的流式传输实现 +网关 API 流式传输端点 +Python 客户端流式传输方法 + +### 端到端测试 +CLI 工具的流式传输输出 +完整流程:客户端 → 网关 → Pulsar → LLM → 返回 +混合流式传输/非流式传输工作负载 + +### 向后兼容性测试 +现有客户端无需修改即可工作 +非流式传输请求的行为与之前相同 + +## 迁移计划 + +### 第一阶段:基础设施 +部署模式更改(向后兼容) +部署网关 API 更新 +部署 Python API 更新 +发布 CLI 工具更新 + +### 第二阶段:VertexAI +部署 VertexAI 流式实现。 +使用测试工作负载进行验证。 + +### 第三阶段:所有提供商 +逐步推广提供商更新。 +监控问题。 + +### 第四阶段:Agent API +部署 Agent 模式变更。 +部署 Agent 流式实现。 +更新文档。 + +## 时间线 + +| 阶段 | 描述 | 依赖项 | +|-------|-------------|--------------| +| 第一阶段 | 基础设施 | 无 | +| 第二阶段 | VertexAI 概念验证 | 第一阶段 | +| 第三阶段 | 所有提供商 | 第二阶段 | +| 第四阶段 | Agent API | 第三阶段 | + +## 设计决策 + +在规范过程中,解决了以下问题: + +1. **流式传输中的 Token 计数**: Token 计数是增量值,而不是累计总数。 + 消费者可以根据需要对其进行求和。这与大多数提供商报告的使用方式一致,并简化了实现。 + + +2. **流中的错误处理:** 如果发生错误,则会填充 `error` 字段,并且不需要填充其他字段。 错误始终是最终的 + 通信 - 在发生错误后,不允许也不期望发送任何后续消息。 + 通信 - 在此之后,不允许也不需要发送任何后续消息。 + 一个错误。对于 LLM/Prompt 流,`end_of_stream=true`。对于 Agent 流, + `chunk_type="error"` 与 `end_of_dialog=true`。 + +3. **部分响应恢复:** 消息协议(Pulsar)具有容错性, + 因此不需要消息级别的重试。如果客户端丢失了流的信息 + 或断开连接,则必须从头开始重试整个请求。 + +4. **快速响应流式传输**: 流式传输仅支持文本 (`text`) + 响应,不支持结构化 (`object`) 响应。 提示服务在开始时就知道输出将是 JSON 还是文本,这取决于提示 + 模板。 如果对 JSON 输出提示执行流式传输请求,则 + 会出现问题。 + 服务应该要么: + 返回完整的 JSON 数据,以单个响应的形式,包含 `end_of_stream=true`,或者 + 拒绝流式传输请求,并返回错误。 + +## 开放问题 + +目前没有。 + +## 参考文献 + +当前 LLM 模式:`trustgraph-base/trustgraph/schema/services/llm.py` +当前提示词模式:`trustgraph-base/trustgraph/schema/services/prompt.py` +当前代理模式:`trustgraph-base/trustgraph/schema/services/agent.py` +LLM 服务基础地址:`trustgraph-base/trustgraph/base/llm_service.py` +VertexAI 提供商:`trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py` +网关 API:`trustgraph-base/trustgraph/api/` +CLI 工具:`trustgraph-cli/trustgraph/cli/` diff --git a/docs/tech-specs/structured-data-2.ar.md b/docs/tech-specs/structured-data-2.ar.md new file mode 100644 index 00000000..a860de18 --- /dev/null +++ b/docs/tech-specs/structured-data-2.ar.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "المواصفات الفنية للبيانات المهيكلة (الجزء 2)" +parent: "Arabic (Beta)" +--- + +# المواصفات الفنية للبيانات المهيكلة (الجزء 2) + +> **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، كما هو موضح في `structured-data.md`. + +## بيان المشكلات + +### 1. عدم اتساق في التسمية: "كائن" مقابل "صف" + +يستخدم التنفيذ الحالي مصطلح "كائن" في جميع أنحائه (على سبيل المثال، `ExtractedObject`، واستخراج الكائنات، وتضمينات الكائنات). هذا المصطلح عام جدًا ويسبب ارتباكًا: + +مصطلح "كائن" مصطلح عام ومزدحم في البرمجيات (كائنات بايثون، كائنات JSON، إلخ). +البيانات التي يتم التعامل معها هي في الأساس بيانات جدولية - صفوف في الجداول ذات المخططات المحددة. +مصطلح "صف" يصف نموذج البيانات بشكل أكثر دقة ويتوافق مع مصطلحات قواعد البيانات. + +يظهر هذا التناقض في أسماء الوحدات، وأسماء الفئات، وأنواع الرسائل، والوثائق. + +### 2. قيود استعلامات تخزين الصفوف + +يحتوي تنفيذ تخزين الصفوف الحالي على قيود استعلام كبيرة: + +**عدم تطابق مع اللغة الطبيعية**: تواجه الاستعلامات صعوبة في التعامل مع الاختلافات في البيانات الواقعية. على سبيل المثال: +من الصعب العثور على قاعدة بيانات الشوارع التي تحتوي على `"CHESTNUT ST"` عند السؤال عن `"Chestnut Street"`. +تكسر الاختصارات، والاختلافات في الأحرف الكبيرة والصغيرة، وتغيرات التنسيق استعلامات المطابقة التامة. +يتوقع المستخدمون فهمًا دلاليًا، لكن المستودع يوفر مطابقة حرفية. + +**مشكلات تطور المخطط**: يؤدي تغيير المخططات إلى حدوث مشكلات: +قد لا تتوافق البيانات الموجودة مع المخططات المحدثة. +يمكن أن تؤدي تغييرات هيكل الجدول إلى تعطيل الاستعلامات وتكامل البيانات. +لا توجد مسار ترحيل واضح لتحديثات المخطط. + +### 3. مطلوب تضمينات الصفوف + +بالإضافة إلى المشكلة رقم 2، يحتاج النظام إلى تضمينات متجهة لبيانات الصفوف لتمكين: + +البحث الدلالي عبر البيانات المهيكلة (العثور على "شارع تشيستنوت" عندما تحتوي البيانات على "CHESTNUT ST"). +مطابقة التشابه للاستعلامات الغامضة. +البحث الهجين الذي يجمع بين المرشحات المهيكلة ومطابقة التشابه الدلالي. +دعم أفضل للغة الطبيعية. + +تم تحديد خدمة التضمين ولكن لم يتم تنفيذها. + +### 4. استيعاب بيانات الصفوف غير مكتمل + +مسار استيعاب البيانات المهيكلة ليس فعالًا بالكامل: + +توجد مطالبات تشخيصية لتصنيف تنسيقات الإدخال (CSV، JSON، إلخ). +خدمة الاستيعاب التي تستخدم هذه المطالبات غير متصلة بالنظام. +لا يوجد مسار شامل لتحميل البيانات المهيكلة مسبقًا إلى مستودع الصفوف. + +## الأهداف + +**مرونة المخطط**: تمكين تطور المخطط دون تعطل البيانات الموجودة أو الحاجة إلى عمليات ترحيل. +**تسمية متسقة**: توحيد مصطلح "صف" في جميع أنحاء قاعدة التعليمات البرمجية. +**قابلية الاستعلام الدلالي**: دعم المطابقة الغامضة / الدلالية عبر تضمينات الصفوف. +**مسار استيعاب كامل**: توفير مسار شامل لتحميل البيانات المهيكلة. + +## التصميم الفني + +### مخطط تخزين صفوف موحد + +أنشأ التنفيذ السابق جدول Cassandra منفصل لكل مخطط. تسبب ذلك في حدوث مشكلات عند تطور المخططات، حيث تتطلب تغييرات هيكل الجدول عمليات ترحيل. + +يستخدم التصميم الجديد جدولًا موحدًا واحدًا لجميع بيانات الصفوف: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### تعريفات الأعمدة + +| العمود | النوع | الوصف | +|--------|------|-------------| +| `collection` | `text` | معرف جمع البيانات/الاستيراد (من البيانات الوصفية) | +| `schema_name` | `text` | اسم المخطط الذي يتوافق معه هذا الصف | +| `index_name` | `text` | اسم الحقل/الحقول المفهرسة، مفصولة بفاصلة للحقول المركبة | +| `index_value` | `frozen>` | قيم الفهرس كقائمة | +| `data` | `map` | بيانات الصف كأزواج مفتاح-قيمة | +| `source` | `text` | عنوان URI اختياري يربط بمعلومات المصدر في الرسم البياني المعرفي. السلسلة الفارغة أو NULL تشير إلى عدم وجود مصدر. | + +#### معالجة الفهرس + +يتم تخزين كل صف عدة مرات - مرة واحدة لكل حقل مفهرس معرف في المخطط. يتم التعامل مع حقول المفتاح الأساسي كفهرس بدون علامة خاصة، مما يوفر مرونة مستقبلية. + +**مثال على الفهرس ذي الحقل الواحد:** +يحدد المخطط `email` كحقل مفهرس +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**مثال على الفهرس المركب:** +يحدد المخطط فهرسًا مركبًا على `region` و `status` +`index_name = "region,status"` (أسماء الحقول مرتبة ومفصولة بفاصلة) +`index_value = ['US', 'active']` (القيم بنفس ترتيب أسماء الحقول) + +**مثال على المفتاح الأساسي:** +يحدد المخطط `customer_id` كمفتاح أساسي +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### أنماط الاستعلام + +تتبع جميع الاستعلامات نفس النمط بغض النظر عن الفهرس المستخدم: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### المقايضات التصميمية + +**المزايا:** +التغييرات في المخطط لا تتطلب تغييرات في هيكل الجدول. +البيانات الموجودة في الصفوف غير مرئية لـ Cassandra - إضافة أو إزالة الحقول تكون شفافة. +نمط استعلام متسق لجميع طرق الوصول. +لا توجد فهارس ثانوية لـ Cassandra (والتي يمكن أن تكون بطيئة على نطاق واسع). +أنواع Cassandra الأصلية في جميع أنحاء النظام (`map`، `frozen`). + +**المقايضات:** +تضخيم الكتابة: كل إدخال صف = N إدخالات (واحد لكل حقل مفهرس). +تكلفة تخزين إضافية بسبب تكرار بيانات الصفوف. +يتم تخزين معلومات النوع في تكوين المخطط، ويتم التحويل في طبقة التطبيق. + +#### نموذج الاتساق + +التصميم يقبل بعض التبسيط: + +1. **لا توجد تحديثات للصفوف**: النظام مخصص للإضافة فقط. هذا يلغي مخاوف الاتساق المتعلقة بتحديث نسخ متعددة من نفس الصف. + +2. **تحمل تغيير المخطط**: عند تغيير المخططات (على سبيل المثال، إضافة أو إزالة الفهارس)، تحتفظ الصفوف الموجودة بفهرستها الأصلية. لن يتمكن المستخدمون من اكتشاف الصفوف القديمة عبر الفهارس الجديدة. يمكن للمستخدمين حذف وإعادة إنشاء مخطط لضمان الاتساق إذا لزم الأمر. + +### تتبع الأقسام والحذف + +#### المشكلة + +باستخدام مفتاح التقسيم `(collection, schema_name, index_name)`، يتطلب الحذف الفعال معرفة جميع مفاتيح التقسيم المراد حذفها. يتطلب الحذف باستخدام `collection` أو `collection + schema_name` معرفة جميع قيم `index_name` التي تحتوي على بيانات. + +#### جدول تتبع الأقسام + +جدول بحث ثانوي يتتبع الأقسام الموجودة: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +هذا يتيح اكتشافًا فعالًا للأقسام لعمليات الحذف. + +#### سلوك كاتب الصفوف + +يحتفظ كاتب الصفوف بخزن مؤقت في الذاكرة لأزواج `(collection, schema_name)` المسجلة. عند معالجة صف: + +1. تحقق مما إذا كانت `(collection, schema_name)` موجودة في الذاكرة المؤقتة. +2. إذا لم تكن موجودة في الذاكرة المؤقتة (أول صف لهذه الزوج): + ابحث في تكوين المخطط للحصول على جميع أسماء الفهارس. + أدخل إدخالات في `row_partitions` لكل `(collection, schema_name, index_name)`. + أضف الزوج إلى الذاكرة المؤقتة. +3. تابع بكتابة بيانات الصف. + +يراقب كاتب الصفوف أيضًا أحداث تغيير تكوين المخطط. عند حدوث تغيير في المخطط، يتم مسح إدخالات الذاكرة المؤقتة ذات الصلة بحيث يؤدي الصف التالي إلى إعادة التسجيل باستخدام أسماء الفهارس المحدثة. + +يضمن هذا النهج: +تتم كتابة جداول البحث مرة واحدة لكل زوج `(collection, schema_name)`، وليس لكل صف. +يعكس جدول البحث الفهارس التي كانت نشطة عند كتابة البيانات. +يتم اكتشاف تغييرات المخطط في منتصف الاستيراد بشكل صحيح. + +#### عمليات الحذف + +**حذف المجموعة:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**حذف المجموعة والمخطط:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### تضمينات الصفوف + +تتيح تضمينات الصفوف المطابقة الدلالية/التقريبية على القيم المفهرسة، مما يحل مشكلة عدم تطابق اللغة الطبيعية (على سبيل المثال، العثور على "CHESTNUT ST" عند البحث عن "Chestnut Street"). + +#### نظرة عامة على التصميم + +يتم تضمين كل قيمة مفهرسة وتخزينها في مخزن متجه (Qdrant). في وقت الاستعلام، يتم تضمين الاستعلام، ويتم العثور على المتجهات المشابهة، ويتم استخدام البيانات الوصفية المرتبطة للبحث عن الصفوف الفعلية في Cassandra. + +#### هيكل مجموعة Qdrant + +مجموعة Qdrant واحدة لكل مجموعة `(user, collection, schema_name, dimension)`: + +**تسمية المجموعة:** `rows_{user}_{collection}_{schema_name}_{dimension}` +يتم تنظيف الأسماء (يتم استبدال الأحرف غير الأبجدية الرقمية بـ `_`، وتحويلها إلى أحرف صغيرة، وتتم إضافة بادئة رقمية بـ `r_`) +**السبب:** يتيح حذف مثيل `(user, collection, schema_name)` بشكل نظيف عن طريق حذف مجموعات Qdrant المطابقة؛ تسمح لاحقة الأبعاد لوجود نماذج تضمين مختلفة. + +#### ما الذي يتم تضمينه + +التمثيل النصي لقيم الفهرس: + +| نوع الفهرس | مثال `index_value` | النص المراد تضمينه | +|------------|----------------------|---------------| +| حقل واحد | `['foo@bar.com']` | `"foo@bar.com"` | +| مركب | `['US', 'active']` | `"US active"` (مفصولة بمسافات) | + +#### هيكل النقطة + +تحتوي كل نقطة Qdrant على: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| حقل الحمولة | الوصف | +|---------------|-------------| +| `index_name` | الحقول المفهرسة التي يمثلها هذا التضمين. | +| `index_value` | القائمة الأصلية للقيم (للبحث في Cassandra). | +| `text` | النص الذي تم تضمينه (للتصحيح/العرض). | + +ملاحظة: `user`، و `collection`، و `schema_name` مستمدة ضمنيًا من اسم مجموعة Qdrant. + +#### مسار الاستعلام + +1. يقوم المستخدم بالاستعلام عن "Chestnut Street" ضمن المستخدم U، والمجموعة X، والمخطط Y. +2. تضمين نص الاستعلام. +3. تحديد اسم(أسماء) مجموعة Qdrant التي تتطابق مع البادئة `rows_U_X_Y_`. +4. البحث في مجموعة(مجموعات) Qdrant المطابقة عن أقرب المتجهات. +5. الحصول على النقاط المطابقة التي تحتوي على حمولات تحتوي على `index_name` و `index_value`. +6. الاستعلام عن Cassandra: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. إرجاع الصفوف المطابقة. + +#### اختياري: التصفية حسب اسم الفهرس. + +يمكن للاستعلامات اختيارياً أن تقوم بالتصفية باستخدام `index_name` في Qdrant للبحث في حقول محددة فقط: + +**"ابحث عن أي حقل يطابق 'Chestnut'"** → ابحث في جميع المتجهات في المجموعة. +**"ابحث عن 'street_name' الذي يطابق 'Chestnut'"** → قم بالتصفية حيث `payload.index_name = 'street_name'`. + +#### البنية. + +تتبع تضمينات الصف النمط **المكون من مرحلتين** المستخدم في GraphRAG (تضمينات الرسم البياني، تضمينات المستندات): + +**المرحلة 1: حساب التضمين** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - تستهلك `ExtractedObject`، وتحسب التضمينات عبر خدمة التضمينات، وتُخرج `RowEmbeddings`. +**المرحلة 2: تخزين التضمين** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - تستهلك `RowEmbeddings`، وتكتب المتجهات إلى Qdrant. + +كاتب صف Cassandra هو مستهلك متوازي منفصل: + +**كاتب صف Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - يستهلك `ExtractedObject`، ويكتب الصفوف إلى Cassandra. + +تستهلك جميع الخدمات الثلاثة من نفس التدفق، مما يحافظ عليها منفصلة. هذا يسمح: +بتوسيع نطاق كتابة Cassandra بشكل مستقل عن إنشاء التضمينات وتخزين المتجهات. +يمكن تعطيل خدمات التضمين إذا لم تكن مطلوبة. +لا تؤثر الأعطال في خدمة واحدة على الخدمات الأخرى. +بنية متسقة مع مسارات GraphRAG. + +#### مسار الكتابة. + +**المرحلة 1 (معالج تضمينات الصف):** عند استقبال `ExtractedObject`: + +1. ابحث عن المخطط للعثور على الحقول المفهرسة. +2. لكل حقل مفهرس: + قم بإنشاء التمثيل النصي لقيمة الفهرس. + احسب التضمين عبر خدمة التضمينات. +3. أخرج رسالة `RowEmbeddings` تحتوي على جميع المتجهات المحسوبة. + +**المرحلة 2 (كتابة تضمينات الصف إلى Qdrant):** عند استقبال `RowEmbeddings`: + +1. لكل تضمين في الرسالة: + حدد مجموعة Qdrant من `(user, collection, schema_name, dimension)`. + قم بإنشاء المجموعة إذا لزم الأمر (إنشاء كسول في الكتابة الأولى). + قم بتحديث النقطة باستخدام المتجه والحمولة. + +#### أنواع الرسائل. + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### دمج الحذف + +يتم اكتشاف مجموعات Qdrant من خلال مطابقة البادئة مع نمط اسم المجموعة: + +**حذف `(user, collection)`:** +1. قائمة بجميع مجموعات Qdrant التي تتطابق مع البادئة `rows_{user}_{collection}_` +2. حذف كل مجموعة مطابقة +3. حذف أقسام صفوف Cassandra (كما هو موثق أعلاه) +4. تنظيف إدخالات `row_partitions` + +**حذف `(user, collection, schema_name)`:** +1. قائمة بجميع مجموعات Qdrant التي تتطابق مع البادئة `rows_{user}_{collection}_{schema_name}_` +2. حذف كل مجموعة مطابقة (يتعامل مع أبعاد متعددة) +3. حذف أقسام صفوف Cassandra +4. تنظيف `row_partitions` + +#### مواقع الوحدات + +| المرحلة | الوحدة | نقطة الدخول | +|-------|--------|-------------| +| المرحلة 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| المرحلة 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### واجهة برمجة تطبيقات استعلام تضمينات الصفوف + +استعلام تضمينات الصفوف هو **واجهة برمجة تطبيقات منفصلة** عن خدمة استعلام الصفوف GraphQL: + +| واجهة برمجة التطبيقات | الغرض | الواجهة الخلفية | +|-----|---------|---------| +| استعلام الصفوف (GraphQL) | مطابقة دقيقة في الحقول المفهرسة | Cassandra | +| استعلام تضمينات الصفوف | مطابقة تقريبية/دلالية | Qdrant | + +هذا الفصل يحافظ على الفصل بين المهام: +خدمة GraphQL تركز على الاستعلامات الدقيقة والمنظمة +واجهة برمجة تطبيقات التضمينات تتعامل مع التشابه الدلالي +سير عمل المستخدم: بحث تقريبي عبر التضمينات للعثور على المرشحين، ثم استعلام دقيق للحصول على بيانات الصف الكاملة + +#### مخطط الطلب/الاستجابة + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### معالج الاستعلامات + +الوحدة: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +نقطة الدخول: `row-embeddings-query-qdrant` + +المعالج: +1. يتلقى `RowEmbeddingsRequest` مع متجهات الاستعلام. +2. يجد مجموعة Qdrant المناسبة عن طريق مطابقة البادئة. +3. يبحث عن أقرب المتجهات مع مرشح `index_name` اختياري. +4. يُرجع `RowEmbeddingsResponse` مع معلومات الفهرس المطابقة. + +#### تكامل بوابة واجهة برمجة التطبيقات (API Gateway) + +تعرض البوابة استعلامات تضمينات الصفوف عبر النمط القياسي للطلب/الاستجابة: + +| المكون | الموقع | +|-----------|----------| +| الموزع | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| التسجيل | أضف `"row-embeddings"` إلى `request_response_dispatchers` في `manager.py` | + +اسم واجهة التدفق: `row-embeddings` + +تعريف الواجهة في مخطط التدفق: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### دعم حزمة تطوير البرمجيات (SDK) الخاصة بـ Python + +توفر حزمة تطوير البرمجيات (SDK) طرقًا للاستعلام عن تضمينات الصفوف: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### أداة سطر الأوامر + +الأمر: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### النمط النموذجي للاستخدام + +عادةً ما يتم استخدام استعلام تضمينات الصفوف كجزء من تدفق بحث تقريبي إلى دقيق: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +هذا النمط المكون من خطوتين يمكّن: +العثور على "CHESTNUT ST" عندما يبحث المستخدم عن "Chestnut Street" +استرجاع بيانات الصف بأكملها مع جميع الحقول +الجمع بين التشابه الدلالي والوصول إلى البيانات المنظمة + +### استيعاب بيانات الصف + +سيتم تأجيله إلى مرحلة لاحقة. سيتم تصميمه جنبًا إلى جنب مع تغييرات الاستيعاب الأخرى. + +## التأثير على التنفيذ + +### تحليل الحالة الحالية + +يحتوي التنفيذ الحالي على مكونين رئيسيين: + +| المكون | الموقع | الأسطر | الوصف | +|-----------|----------|-------|-------------| +| خدمة الاستعلام | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | كتلة واحدة: توليد مخطط GraphQL، تحليل المرشحات، استعلامات Cassandra، معالجة الطلبات | +| الكاتب | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | إنشاء جدول لكل مخطط، فهارس ثانوية، إدراج/حذف | + +**نمط الاستعلام الحالي:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**نمط استعلام جديد:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### التغييرات الرئيسية + +1. **تبسيط دلالات الاستعلام**: المخطط الجديد يدعم فقط المطابقات الدقيقة على `index_value`. مرشحات GraphQL الحالية (`gt`، `lt`، `contains`، إلخ) إما: + تصبح تصفية لاحقة على البيانات المُرجعة (إذا كانت لا تزال مطلوبة) + يتم إزالتها لصالح استخدام واجهة برمجة تطبيقات التضمينات للمطابقة التقريبية + +2. **كود GraphQL مرتبط ارتباطًا وثيقًا**: يحتوي `service.py` الحالي على توليد أنواع Strawberry، وتحليل المرشحات، والاستعلامات الخاصة بـ Cassandra. إضافة قاعدة بيانات أخرى ستؤدي إلى تكرار حوالي 400 سطر من كود GraphQL. + +### إعادة الهيكلة المقترحة + +تتكون إعادة الهيكلة من جزأين: + +#### 1. فصل كود GraphQL + +استخراج مكونات GraphQL القابلة لإعادة الاستخدام إلى وحدة مشتركة: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +هذا يتيح: +إعادة الاستخدام عبر خلفيات تخزين الصفوف المختلفة. +فصل أوضح للمسؤوليات. +اختبار منطق GraphQL بسهولة أكبر بشكل مستقل. + +#### 2. تنفيذ مخطط الجدول الجديد + +إعادة هيكلة التعليمات البرمجية الخاصة بـ Cassandra لاستخدام الجدول الموحد: + +**الكاتب** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +جدول `rows` واحد بدلاً من الجداول الخاصة بكل مخطط. +كتابة N من النسخ لكل صف (واحد لكل فهرس). +التسجيل في جدول `row_partitions`. +إنشاء جدول أبسط (إعداد لمرة واحدة). + +**خدمة الاستعلام** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +الاستعلام عن جدول `rows` الموحد. +استخدام الوحدة النمطية GraphQL المستخرجة لإنشاء المخطط. +تبسيط معالجة المرشحات (مطابقة تامة فقط على مستوى قاعدة البيانات). + +### تغيير أسماء الوحدات النمطية + +كجزء من عملية تنظيف أسماء "object" → "row": + +| الحالي | الجديد | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### وحدات نمطية جديدة + +| الوحدة النمطية | الغرض | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | أدوات GraphQL مشتركة | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | واجهة برمجة تطبيقات استعلام تضمينات الصفوف | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | حساب تضمينات الصفوف (المرحلة 1) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | تخزين تضمينات الصفوف (المرحلة 2) | + +## المراجع + +[مواصفات البيانات المنظمة](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.es.md b/docs/tech-specs/structured-data-2.es.md new file mode 100644 index 00000000..c48635ad --- /dev/null +++ b/docs/tech-specs/structured-data-2.es.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "Especificación Técnica de Datos Estructurados (Parte 2)" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Datos Estructurados (Parte 2) + +> **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 aborda los problemas y las deficiencias identificadas durante la implementación inicial de la integración de datos estructurados de TrustGraph, como se describe en `structured-data.md`. + +## Declaraciones del Problema + +### 1. Inconsistencia en la Nomenclatura: "Objeto" vs "Fila" + +La implementación actual utiliza la terminología de "objeto" en todo (por ejemplo, `ExtractedObject`, extracción de objetos, incrustaciones de objetos). Esta nomenclatura es demasiado genérica y causa confusión: + +"Objeto" es un término ambiguo en el software (objetos de Python, objetos JSON, etc.) +Los datos que se están manejando son fundamentalmente tabulares: filas en tablas con esquemas definidos. +"Fila" describe con mayor precisión el modelo de datos y se alinea con la terminología de la base de datos. + +Esta inconsistencia aparece en los nombres de los módulos, los nombres de las clases, los tipos de mensajes y la documentación. + +### 2. Limitaciones de Consulta de la Tienda de Filas + +La implementación actual de la tienda de filas tiene limitaciones de consulta significativas: + +**Desajuste con el Lenguaje Natural**: Las consultas tienen dificultades con las variaciones de datos del mundo real. Por ejemplo: +Es difícil encontrar una base de datos de calles que contenga `"CHESTNUT ST"` cuando se pregunta por `"Chestnut Street"`. +Las abreviaturas, las diferencias de mayúsculas y minúsculas y las variaciones de formato interrumpen las consultas de coincidencia exacta. +Los usuarios esperan una comprensión semántica, pero la tienda proporciona una coincidencia literal. + +**Problemas de Evolución del Esquema**: Los cambios en los esquemas causan problemas: +Los datos existentes pueden no cumplir con los esquemas actualizados. +Los cambios en la estructura de la tabla pueden romper las consultas y la integridad de los datos. +No hay una ruta de migración clara para las actualizaciones del esquema. + +### 3. Se Requieren Incrustaciones de Filas + +Relacionado con el problema 2, el sistema necesita incrustaciones vectoriales para los datos de las filas para permitir: + +Búsqueda semántica en datos estructurados (encontrar "Chestnut Street" cuando los datos contienen "CHESTNUT ST"). +Coincidencia de similitud para consultas difusas. +Búsqueda híbrida que combina filtros estructurados con similitud semántica. +Mejor soporte para consultas en lenguaje natural. + +El servicio de incrustación se especificó pero no se implementó. + +### 4. Ingesta de Datos de Filas Incompleta + +La canalización de ingesta de datos estructurados no está completamente operativa: + +Existen indicaciones de diagnóstico para clasificar los formatos de entrada (CSV, JSON, etc.). +El servicio de ingesta que utiliza estas indicaciones no está integrado en el sistema. +No hay una ruta de extremo a extremo para cargar datos preestructurados en la tienda de filas. + +## Objetivos + +**Flexibilidad del Esquema**: Permitir la evolución del esquema sin romper los datos existentes ni requerir migraciones. +**Nomenclatura Consistente**: Estandarizar la terminología de "fila" en todo el código base. +**Consultas Semánticas**: Compatibilidad con la coincidencia difusa/semántica a través de incrustaciones de filas. +**Canalización de Ingesta Completa**: Proporcionar una ruta de extremo a extremo para cargar datos estructurados. + +## Diseño Técnico + +### Esquema Unificado de Almacenamiento de Filas + +La implementación anterior creó una tabla de Cassandra separada para cada esquema. Esto causó problemas cuando los esquemas evolucionaron, ya que los cambios en la estructura de la tabla requerían migraciones. + +El nuevo diseño utiliza una única tabla unificada para todos los datos de filas: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### Definiciones de columnas + +| Columna | Tipo | Descripción | +|--------|------|-------------| +| `collection` | `text` | Identificador de recolección/importación de datos (procedente de metadatos) | +| `schema_name` | `text` | Nombre del esquema al que se ajusta esta fila | +| `index_name` | `text` | Nombre del(los) campo(s) indexado(s), unidos por comas para compuestos | +| `index_value` | `frozen>` | Valor(es) del índice como una lista | +| `data` | `map` | Datos de la fila como pares clave-valor | +| `source` | `text` | URI opcional que enlaza a información de procedencia en el grafo de conocimiento. Una cadena vacía o NULL indica que no hay fuente. | + +#### Manejo de índices + +Cada fila se almacena varias veces: una vez por cada campo indexado definido en el esquema. Los campos de clave primaria se tratan como un índice sin un marcador especial, lo que proporciona flexibilidad futura. + +**Ejemplo de índice de un solo campo:** +El esquema define `email` como indexado +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**Ejemplo de índice compuesto:** +El esquema define un índice compuesto en `region` y `status` +`index_name = "region,status"` (nombres de los campos ordenados y unidos por comas) +`index_value = ['US', 'active']` (valores en el mismo orden que los nombres de los campos) + +**Ejemplo de clave primaria:** +El esquema define `customer_id` como clave primaria +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### Patrones de consulta + +Todas las consultas siguen el mismo patrón, independientemente del índice que se utilice: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### Compensaciones de diseño + +**Ventajas:** +Los cambios de esquema no requieren cambios en la estructura de la tabla. +Los datos de las filas son opacos para Cassandra; las adiciones/eliminaciones de campos son transparentes. +Patrón de consulta consistente para todos los métodos de acceso. +No hay índices secundarios de Cassandra (que pueden ser lentos a escala). +Tipos nativos de Cassandra en todo momento (`map`, `frozen`). + +**Compensaciones:** +Amplificación de escritura: cada inserción de fila = N inserciones (una por cada campo indexado). +Sobrecarga de almacenamiento debido a la duplicación de datos de las filas. +La información del tipo se almacena en la configuración del esquema, la conversión se realiza en la capa de la aplicación. + +#### Modelo de consistencia + +El diseño acepta ciertas simplificaciones: + +1. **Sin actualizaciones de filas**: El sistema es de solo escritura. Esto elimina las preocupaciones de coherencia sobre la actualización de múltiples copias de la misma fila. + +2. **Tolerancia a los cambios de esquema**: Cuando los esquemas cambian (por ejemplo, se agregan o eliminan índices), las filas existentes conservan su indexación original. Las filas antiguas no se podrán descubrir a través de nuevos índices. Los usuarios pueden eliminar y recrear un esquema para garantizar la coherencia si es necesario. + +### Seguimiento y eliminación de particiones + +#### El problema + +Con la clave de partición `(collection, schema_name, index_name)`, la eliminación eficiente requiere conocer todas las claves de partición para eliminar. Eliminar solo por `collection` o `collection + schema_name` requiere conocer todos los valores de `index_name` que tienen datos. + +#### Tabla de seguimiento de particiones + +Una tabla de búsqueda secundaria realiza un seguimiento de qué particiones existen: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +Esto permite una detección eficiente de particiones para operaciones de eliminación. + +#### Comportamiento del Escritor de Filas + +El escritor de filas mantiene una caché en memoria de pares registrados de `(collection, schema_name)`. Al procesar una fila: + +1. Comprobar si `(collection, schema_name)` está en la caché. +2. Si no está en la caché (primera fila para este par): + Buscar la configuración del esquema para obtener todos los nombres de índice. + Insertar entradas en `row_partitions` para cada `(collection, schema_name, index_name)`. + Agregar el par a la caché. +3. Continuar con la escritura de los datos de la fila. + +El escritor de filas también supervisa los eventos de cambio de configuración del esquema. Cuando cambia un esquema, las entradas de caché relevantes se eliminan para que la siguiente fila active un nuevo registro con los nombres de índice actualizados. + +Este enfoque garantiza: +Las escrituras de la tabla de búsqueda se realizan una vez por par de `(collection, schema_name)`, no por fila. +La tabla de búsqueda refleja los índices que estaban activos cuando se escribieron los datos. +Los cambios de esquema durante la importación se detectan correctamente. + +#### Operaciones de Eliminación + +**Eliminar colección:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**Eliminar colección + esquema:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### Incrustaciones de Filas + +Las incrustaciones de filas permiten la coincidencia semántica/difusa en los valores indexados, resolviendo el problema de la falta de coincidencia del lenguaje natural (por ejemplo, encontrar "CHESTNUT ST" al buscar "Chestnut Street"). + +#### Descripción General del Diseño + +Cada valor indexado se incrusta y se almacena en un almacén de vectores (Qdrant). En el momento de la consulta, la consulta se incrusta, se encuentran vectores similares y los metadatos asociados se utilizan para buscar las filas reales en Cassandra. + +#### Estructura de la Colección Qdrant + +Una colección Qdrant por tupla `(user, collection, schema_name, dimension)`: + +**Nombre de la colección:** `rows_{user}_{collection}_{schema_name}_{dimension}` +Los nombres se limpian (los caracteres no alfanuméricos se reemplazan con `_`, se convierten a minúsculas, los prefijos numéricos reciben el prefijo `r_`) +**Justificación:** Permite la eliminación limpia de una instancia `(user, collection, schema_name)` eliminando las colecciones Qdrant correspondientes; el sufijo de dimensión permite que diferentes modelos de incrustación coexistan. + +#### Qué se Incrusta + +La representación de texto de los valores de índice: + +| Tipo de Índice | Ejemplo `index_value` | Texto a Incrustar | +|------------|----------------------|---------------| +| Campo único | `['foo@bar.com']` | `"foo@bar.com"` | +| Compuesto | `['US', 'active']` | `"US active"` (unidos por espacios) | + +#### Estructura del Punto + +Cada punto Qdrant contiene: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| Campo de carga útil | Descripción | +|---------------|-------------| +| `index_name` | Los campos indexados que representa esta incrustación. | +| `index_value` | La lista original de valores (para la búsqueda en Cassandra). | +| `text` | El texto que se incrustó (para depuración/visualización). | + +Nota: `user`, `collection` y `schema_name` se derivan implícitamente del nombre de la colección de Qdrant. + +#### Flujo de consulta + +1. El usuario consulta "Chestnut Street" dentro del usuario U, la colección X, el esquema Y. +2. Incrusta el texto de la consulta. +3. Determina el(los) nombre(s) de la colección de Qdrant que coinciden con el prefijo `rows_U_X_Y_`. +4. Busca en la(s) colección(es) de Qdrant que coincidan para encontrar los vectores más cercanos. +5. Obtiene los puntos coincidentes con cargas útiles que contienen `index_name` y `index_value`. +6. Consulta Cassandra: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. Devolver filas coincidentes + +#### Opcional: Filtrado por Nombre de Índice + +Las consultas pueden filtrar opcionalmente por `index_name` en Qdrant para buscar solo campos específicos: + +**"Encontrar cualquier campo que coincida con 'Chestnut'"** → buscar todos los vectores en la colección +**"Encontrar street_name que coincida con 'Chestnut'"** → filtrar donde `payload.index_name = 'street_name'` + +#### Arquitectura + +Los incrustados de filas siguen el **patrón de dos etapas** utilizado por GraphRAG (incrustados de grafos, incrustados de documentos): + +**Etapa 1: Cálculo de incrustados** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - Consume `ExtractedObject`, calcula incrustados a través del servicio de incrustados, produce `RowEmbeddings` +**Etapa 2: Almacenamiento de incrustados** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - Consume `RowEmbeddings`, escribe vectores en Qdrant + +El escritor de filas de Cassandra es un consumidor paralelo separado: + +**Escritor de filas de Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - Consume `ExtractedObject`, escribe filas en Cassandra + +Los tres servicios consumen del mismo flujo, manteniéndolos desacoplados. Esto permite: +Escalado independiente de las escrituras de Cassandra frente a la generación de incrustados frente al almacenamiento de vectores +Los servicios de incrustados se pueden desactivar si no son necesarios +Las fallas en un servicio no afectan a los demás +Arquitectura consistente con las canalizaciones de GraphRAG + +#### Ruta de Escritura + +**Etapa 1 (procesador de incrustados de filas):** Al recibir un `ExtractedObject`: + +1. Buscar el esquema para encontrar campos indexados +2. Para cada campo indexado: + Construir la representación de texto del valor del índice + Calcular el incrustado a través del servicio de incrustados +3. Producir un mensaje `RowEmbeddings` que contenga todos los vectores calculados + +**Etapa 2 (escritura de incrustados de filas en Qdrant):** Al recibir un `RowEmbeddings`: + +1. Para cada incrustado en el mensaje: + Determinar la colección de Qdrant a partir de `(user, collection, schema_name, dimension)` + Crear la colección si es necesario (creación perezosa en la primera escritura) + Insertar el punto con el vector y la carga útil + +#### Tipos de Mensajes + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### Integración de Eliminación + +Las colecciones de Qdrant se descubren mediante la comparación de prefijos en el patrón de nombre de la colección: + +**Eliminar `(user, collection)`:** +1. Listar todas las colecciones de Qdrant que coincidan con el prefijo `rows_{user}_{collection}_` +2. Eliminar cada colección que coincida +3. Eliminar particiones de filas de Cassandra (como se documenta anteriormente) +4. Limpiar las entradas de `row_partitions` + +**Eliminar `(user, collection, schema_name)`:** +1. Listar todas las colecciones de Qdrant que coincidan con el prefijo `rows_{user}_{collection}_{schema_name}_` +2. Eliminar cada colección que coincida (maneja múltiples dimensiones) +3. Eliminar particiones de filas de Cassandra +4. Limpiar `row_partitions` + +#### Ubicaciones de los Módulos + +| Etapa | Módulo | Punto de Entrada | +|-------|--------|-------------| +| Etapa 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| Etapa 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### API de Consulta de Incrustaciones de Filas + +La consulta de incrustaciones de filas es una **API separada** del servicio de consulta de filas GraphQL: + +| API | Propósito | Backend | +|-----|---------|---------| +| Consulta de Filas (GraphQL) | Coincidencia exacta en campos indexados | Cassandra | +| Consulta de Incrustaciones de Filas | Coincidencia difusa/semántica | Qdrant | + +Esta separación mantiene la claridad: +El servicio GraphQL se enfoca en consultas exactas y estructuradas +La API de incrustaciones maneja la similitud semántica +Flujo de trabajo del usuario: búsqueda difusa a través de incrustaciones para encontrar candidatos, luego una consulta exacta para obtener los datos completos de la fila + +#### Esquema de Solicitud/Respuesta + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### Procesador de Consultas + +Módulo: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +Punto de entrada: `row-embeddings-query-qdrant` + +El procesador: +1. Recibe `RowEmbeddingsRequest` con vectores de consulta +2. Encuentra la colección Qdrant apropiada mediante la coincidencia de prefijos +3. Busca los vectores más cercanos con un filtro opcional `index_name` +4. Devuelve `RowEmbeddingsResponse` con información del índice correspondiente + +#### Integración con la API Gateway + +La puerta de enlace expone consultas de incrustaciones de filas a través del patrón estándar de solicitud/respuesta: + +| Componente | Ubicación | +|-----------|----------| +| Despachador | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| Registro | Agrega `"row-embeddings"` a `request_response_dispatchers` en `manager.py` | + +Nombre de la interfaz de flujo: `row-embeddings` + +Definición de la interfaz en el plano de flujo: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### Soporte del SDK de Python + +El SDK proporciona métodos para consultas de incrustaciones de filas: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### Utilidad de Línea de Comandos (CLI) + +Comando: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### Patrón de uso típico + +La consulta de incrustaciones de filas se utiliza típicamente como parte de un flujo de búsqueda difusa a exacta: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +Este patrón de dos pasos permite: +Encontrar "CHESTNUT ST" cuando el usuario busca "Chestnut Street" +Recuperar datos de fila completos con todos los campos +Combinar la similitud semántica con el acceso a datos estructurados + +### Ingesta de Datos de Fila + +Se pospone a una fase posterior. Se diseñará junto con otros cambios de ingesta. + +## Impacto en la Implementación + +### Análisis del Estado Actual + +La implementación existente tiene dos componentes principales: + +| Componente | Ubicación | Líneas | Descripción | +|-----------|----------|-------|-------------| +| Servicio de Consulta | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | Monolítico: generación de esquema GraphQL, análisis de filtros, consultas de Cassandra, manejo de solicitudes | +| Escritor | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | Creación de tablas por esquema, índices secundarios, inserción/eliminación | + +**Patrón de Consulta Actual:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**Nuevo Patrón de Consulta:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### Cambios Clave + +1. **La semántica de las consultas se simplifica**: El nuevo esquema solo admite coincidencias exactas en `index_value`. Los filtros GraphQL actuales (`gt`, `lt`, `contains`, etc.) ya sea: + Se convierten en filtrado posterior de los datos devueltos (si es necesario) + Se eliminan en favor de usar la API de embeddings para la coincidencia difusa + +2. **El código GraphQL está fuertemente acoplado**: El código `service.py` actual incluye la generación de tipos de Strawberry, el análisis de filtros y las consultas específicas de Cassandra. Agregar otro backend de almacenamiento de filas duplicaría aproximadamente 400 líneas de código GraphQL. + +### Refactorización Propuesta + +La refactorización tiene dos partes: + +#### 1. Separar el Código GraphQL + +Extraer componentes GraphQL reutilizables en un módulo compartido: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +Esto permite: +Reutilización en diferentes backends de almacenamiento de datos. +Una separación más clara de responsabilidades. +Pruebas más fáciles de la lógica de GraphQL de forma independiente. + +#### 2. Implementar el Nuevo Esquema de Tabla + +Refactorizar el código específico de Cassandra para utilizar la tabla unificada: + +**Escritor** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +Una única tabla `rows` en lugar de tablas por esquema. +Escribir N copias por fila (una por índice). +Registrarse en la tabla `row_partitions`. +Creación de tabla más sencilla (configuración única). + +**Servicio de Consulta** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +Consultar la tabla `rows` unificada. +Utilizar el módulo GraphQL extraído para la generación de esquemas. +Manejo de filtros simplificado (solo coincidencia exacta a nivel de base de datos). + +### Cambios de Nombre de Módulos + +Como parte de la limpieza de nombres de "objeto" a "fila": + +| Actual | Nuevo | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### Nuevos Módulos + +| Módulo | Propósito | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | Utilidades GraphQL compartidas | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | API de consulta de incrustaciones de filas | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | Cálculo de incrustaciones de filas (Etapa 1) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | Almacenamiento de incrustaciones de filas (Etapa 2) | + +## Referencias + +[Especificación Técnica de Datos Estructurados](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.he.md b/docs/tech-specs/structured-data-2.he.md new file mode 100644 index 00000000..a01b6c31 --- /dev/null +++ b/docs/tech-specs/structured-data-2.he.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "מפרט טכני של נתונים מובנים (חלק 2)" +parent: "Hebrew (Beta)" +--- + +# מפרט טכני של נתונים מובנים (חלק 2) + +> **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, כפי שמתואר ב-`structured-data.md`. + +## הצגת בעיות + +### 1. חוסר עקביות בשמות: "אובייקט" לעומת "שורה" + +יישום נוכחי משתמש בטרמינולוגיה של "אובייקט" בכל מקום (לדוגמה, `ExtractedObject`, חילוץ אובייקטים, הטמעות אובייקטים). שם זה כללי מדי וגורם לבלבול: + +"אובייקט" הוא מונח מוגדר מראש בתוכנה (אובייקטים בפייתון, אובייקטים ב-JSON, וכו') +הנתונים המטופלים הם למעשה טבלאיים - שורות בטבלאות עם סכימות מוגדרות +"שורה" מתארת ​​במדויק יותר את מודל הנתונים ומתאימה לטרמינולוגיה של מסדי נתונים + +חוסר עקביות זה מופיע בשמות מודולים, שמות מחלקות, סוגי הודעות ובתעוד. + +### 2. מגבלות שאילתות של אחסון שורות + +ליישום הנוכחי של אחסון שורות יש מגבלות שאילתות משמעותיות: + +**אי התאמה לשפה טבעית**: שאילתות מתקשות עם וריאציות של נתונים מהעולם האמיתי. לדוגמה: +קשה למצוא מסד נתונים של רחובות המכיל `"CHESTNUT ST"` כאשר שואלים על `"Chestnut Street"` +קיצורים, הבדלי רישיות ווריאציות בפורמט שוברים שאילתות התאמה מדויקת +משתמשים מצפים להבנה סמנטית, אך המאגר מספק התאמה מילולית + +**בעיות בהתפתחות סכימה**: שינוי סכימות גורם לבעיות: +נתונים קיימים עשויים שלא להתאים לסכימות מעודכנות +שינויים במבנה הטבלה עלולים לשבור שאילתות ושלמות נתונים +אין מסלול מעבר ברור לעדכוני סכימה + +### 3. הטמעות שורות נדרשות + +בהקשר לבעיה 2, המערכת זקוקה להטמעות וקטוריות עבור נתוני שורה כדי לאפשר: + +חיפוש סמנטי בנתונים מובנים (מציאת "Chestnut Street" כאשר הנתונים מכילים "CHESTNUT ST") +התאמת דמיון לשאילתות מעורפלות +חיפוש היברידי המשלב מסננים מובנים עם דמיון סמנטי +תמיכה טובה יותר בשפה טבעית + +שירות ההטמעה הוגדר אך לא יושם. + +### 4. הטמעה של נתוני שורה לא שלמה + +צינור ההטמעה של נתונים מובנים אינו פעיל במלואו: + +קיימות הנחיות אבחון כדי לסווג פורמטים של קלט (CSV, JSON, וכו') +שירות ההטמעה המשתמש בהנחיות אלה אינו מחובר למערכת +אין מסלול מקצה לקצה לטעינת נתונים מובנים לאחסון השורות + +## מטרות + +**גמישות סכימה**: לאפשר התפתחות סכימה מבלי לשבור נתונים קיימים או לדרוש מעברים +**שמות עקביים**: לתקנן על "שורה" בכל בסיס הקוד +**יכולת שאילתא סמנטית**: לתמוך בהתאמה מעורפלת/סמנטית באמצעות הטמעות שורות +**צינור הטמעה שלם**: לספק מסלול מקצה לקצה לטעינת נתונים מובנים + +## עיצוב טכני + +### סכימת אחסון שורות מאוחדת + +יישום קודם יצר טבלת Cassandra נפרדת עבור כל סכימה. זה גרם לבעיות כאשר הסכימות התפתחו, מכיוון ששינויים במבנה הטבלה דרשו מעברים. + +העיצוב החדש משתמש בטבלה מאוחדת אחת עבור כל נתוני שורה: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### הגדרות עמודות + +| עמודה | סוג | תיאור | +|--------|------|-------------| +| `collection` | `text` | מזהה איסוף/ייבוא נתונים (ממטא-נתונים) | +| `schema_name` | `text` | שם הסכימה אליה השורה הזו מתאימה | +| `index_name` | `text` | שם השדה/ים המאומדד, מחובר באמצעות פסיק עבור אינדקסים מורכבים | +| `index_value` | `frozen>` | ערכי האינדקס כרשימה | +| `data` | `map` | נתוני השורה כזוגות מפתח-ערך | +| `source` | `text` | URI אופציונלי המקשר למידע על מקור בגרף הידע. מחרוזת ריקה או NULL מציינים שאין מקור. | + +#### טיפול באינדקסים + +כל שורה מאוחסנת מספר פעמים - פעם אחת עבור כל שדה מאומדד המוגדר בסכימה. שדות המפתח הראשוניים מטופלים כאינדקס ללא סימון מיוחד, מה שמספק גמישות עתידית. + +**דוגמה לאינדקס של שדה בודד:** +הסכימה מגדירה את `email` כמאומדד +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**דוגמה לאינדקס מורכב:** +הסכימה מגדירה אינדקס מורכב על `region` ו-`status` +`index_name = "region,status"` (שמות השדות ממוינים ומחוברים באמצעות פסיק) +`index_value = ['US', 'active']` (הערכים באותו סדר כמו שמות השדות) + +**דוגמה למפתח ראשי:** +הסכימה מגדירה את `customer_id` כמפתח ראשי +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### תבניות שאילתה + +כל השאילתות עוקבות אחר אותו תבנית, ללא קשר לאיזה אינדקס משתמשים: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### פשרות עיצוביות + +**יתרונות:** +שינויים בסכימה אינם מחייבים שינויים במבנה הטבלה +נתוני השורה אינם גלויים ל-Cassandra - הוספות/הסרות שדות הן שקופות +דפוס שאילתות עקבי לכל שיטות הגישה +אין אינדקסים משניים של Cassandra (שיכולים להיות איטיים בקנה מידה גדול) +סוגי Cassandra מקוריים בכל מקום (`map`, `frozen`) + +**פשרות:** +הגברה בכתיבה: כל הוספת שורה = N הוספות (אחת לכל שדה מועדן) +תקורה של אחסון עקב שכפול נתוני שורה +מידע על סוגים מאוחסן בתצורת הסכימה, המרה בשכבת האפליקציה + +#### מודל עקביות + +העיצוב מקבל מספר פישוטים: + +1. **אין עדכוני שורות**: המערכת היא רק להוספה. זה מבטל חששות לגבי עקביות בעדכון עותקים מרובים של אותה שורה. + +2. **סובלנות לשינויי סכימה**: כאשר הסכימות משתנות (לדוגמה, הוספת/הסרת אינדקסים), שורות קיימות שומרות על האינדוקס המקורי שלהן. שורות ישנות לא יהיו ניתנות לגילוי באמצעות אינדקסים חדשים. משתמשים יכולים למחוק וליצור מחדש סכימה כדי להבטיח עקביות במידת הצורך. + +### מעקב ומחיקת מחיצות + +#### הבעיה + +עם מפתח המחיצה `(collection, schema_name, index_name)`, מחיקה יעילה דורשת ידיעת כל מפתחות המחיצה למחיקה. מחיקה רק לפי `collection` או `collection + schema_name` דורשת ידיעת כל ערכי `index_name` שיש להם נתונים. + +#### טבלת מעקב מחיצות + +טבלת חיפוש משנית עוקבת אחר אילו מחיצות קיימות: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +זה מאפשר גילוי יעיל של מחיצות עבור פעולות מחיקה. + +#### התנהגות של כותב שורות + +כותב השורות שומר מטמון בזיכרון של זוגות `(collection, schema_name)` רשומים. בעת עיבוד שורה: + +1. בדוק אם `(collection, schema_name)` נמצא במטמון +2. אם לא שמור במטמון (השורה הראשונה עבור זוג זה): + חפש את תצורת הסכימה כדי לקבל את כל שמות האינדקסים + הכנס ערכים ל-`row_partitions` עבור כל `(collection, schema_name, index_name)` + הוסף את הזוג למטמון +3. המשך בכתיבת נתוני השורה + +כותב השורות גם עוקב אחר אירועי שינוי בתצורת הסכימה. כאשר סכימה משתנה, רשומות מטמון רלוונטיות נמחקים כך שהשורה הבאה תגרום לרישום מחדש עם שמות האינדקסים המעודכנים. + +גישה זו מבטיחה: +כתיבות לטבלת חיפוש מתרחשות פעם אחת לכל זוג `(collection, schema_name)`, ולא לכל שורה +טבלת החיפוש משקפת את האינדקסים שהיו פעילים בעת כתיבת הנתונים +שינויי סכימה במהלך הייבוא מזוהים כראוי + +#### פעולות מחיקה + +**מחיקת אוסף:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**מחיקת אוסף וסכימה:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### הטמעות שורות + +הטמעות שורות מאפשרות התאמה סמנטית/עמומה על ערכים מוענקים, תוך פתרון בעיית אי ההתאמה בשפה טבעית (לדוגמה, מציאת "CHESTNUT ST" בעת חיפוש עבור "Chestnut Street"). + +#### סקירה כללית של העיצוב + +כל ערך מוענק מוטמע ונשמר במאגר וקטורים (Qdrant). בזמן שאילתה, השאילתה מוטמעת, וקטורים דומים נמצאים, ומטא-הנתונים המשויכים משמשים לאחזור השורות בפועל ב-Cassandra. + +#### מבנה אוסף Qdrant + +אוסף Qdrant אחד לכל טופל `(user, collection, schema_name, dimension)`: + +**שם האוסף:** `rows_{user}_{collection}_{schema_name}_{dimension}` +השמות עוברים סינון (תווים שאינם אלפא-נומריים מוחלפים ב-`_`, אותיות קטנות, קידומות מספריות מקבלות קידומת `r_`) +**ההצדקה:** מאפשר מחיקה נקייה של מופע `(user, collection, schema_name)` על ידי מחיקת אוספי Qdrant תואמים; הסיומת של הממד מאפשרת למודלי הטמעה שונים להתקיים יחד. + +#### מה מוטמע + +הייצוג הטקסטואלי של ערכי אינדקס: + +| סוג אינדקס | דוגמה `index_value` | טקסט להטמעה | +|------------|----------------------|---------------| +| שדה בודד | `['foo@bar.com']` | `"foo@bar.com"` | +| מורכב | `['US', 'active']` | `"US active"` (מחוברים באמצעות רווח) | + +#### מבנה נקודה + +כל נקודה ב-Qdrant מכילה: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| שדה מטען | תיאור | +|---------------|-------------| +| `index_name` | השדות המאופיינים בהטמעה זו | +| `index_value` | הרשימה המקורית של הערכים (לחיפוש בקסנדרה) | +| `text` | הטקסט שהוטמע (לצרכי ניפוי באגים/הצגה) | + +הערה: `user`, `collection` ו-`schema_name` משתמעים משם האוסף של Qdrant. + +#### זרימת שאילתה + +1. משתמש מבקש מידע על "Chestnut Street" בתוך משתמש U, אוסף X, סכימה Y. +2. הטמע את טקסט השאילתה. +3. קבע את שם/שמות האוסף של Qdrant התואמים לפריט `rows_U_X_Y_`. +4. חפש באוספי Qdrant התואמים את הווקטורים הקרובים ביותר. +5. קבל נקודות תואמות עם מטענים המכילים `index_name` ו-`index_value`. +6. שאילתת קסנדרה: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. החזרת שורות תואמות + +#### אופציונלי: סינון לפי שם אינדקס + +שאילתות יכולות, באופן אופציונלי, לסנן לפי `index_name` ב-Qdrant כדי לחפש רק שדות ספציפיים: + +**"מצא כל שדה התואם ל-'Chestnut'"** → חיפוש בכל הווקטורים באוסף +**"מצא את street_name התואם ל-'Chestnut'"** → סינון כאשר `payload.index_name = 'street_name'` + +#### ארכיטקטורה + +הטמעות שורות עוקבות את ה**תבנית בשני שלבים** המשמשת את GraphRAG (graph-embeddings, document-embeddings): + +**שלב 1: חישוב הטמעה** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - צורך `ExtractedObject`, מחשב הטמעות באמצעות שירות ההטמעות, מוציא `RowEmbeddings` +**שלב 2: אחסון הטמעה** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - צורך `RowEmbeddings`, כותב וקטורים ל-Qdrant + +כותב השורות של Cassandra הוא צרכן מקבילי נפרד: + +**כותב שורות Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - צורך `ExtractedObject`, כותב שורות ל-Cassandra + +שלושת השירותים צורכים מאותו זרימה, תוך שמירה על הפרדה ביניהם. זה מאפשר: +התאמה עצמאית של כתיבת Cassandra לעומת יצירת הטמעות לעומת אחסון וקטורים +ניתן להשבית שירותי הטמעות אם אינם נחוצים +כשל בשירות אחד לא משפיע על השירותים האחרים +ארכיטקטורה עקבית עם צינורות GraphRAG + +#### נתיב כתיבה + +**שלב 1 (מעבד הטמעות שורות):** בעת קבלת `ExtractedObject`: + +1. חפש את הסכימה כדי למצוא שדות מודדים +2. עבור כל שדה מודד: + בנה את הייצוג הטקסטואלי של ערך האינדקס + חשב הטמעה באמצעות שירות ההטמעות +3. הפק פלט הודעה `RowEmbeddings` המכילה את כל הווקטורים שחושבו + +**שלב 2 (כתיבת הטמעות שורות ל-Qdrant):** בעת קבלת `RowEmbeddings`: + +1. עבור כל הטמעה בהודעה: + קבע את האוסף של Qdrant מ-`(user, collection, schema_name, dimension)` + צור אוסף אם יש צורך (יצירה עצלה בכתיבה הראשונה) + הוסף נקודה עם וקטור ו-payload + +#### סוגי הודעות + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### אינטגרציה של מחיקה + +אוספי Qdrant מתגלים באמצעות התאמה מקדימה של תבנית שם האוסף: + +**מחיקת `(user, collection)`:** +1. רשום את כל אוספי Qdrant התואמים לקידומת `rows_{user}_{collection}_` +2. מחק כל אוסף תואם +3. מחק מחיצות שורות Cassandra (כפי שמפורט לעיל) +4. נקה רשומות `row_partitions` + +**מחיקת `(user, collection, schema_name)`:** +1. רשום את כל אוספי Qdrant התואמים לקידומת `rows_{user}_{collection}_{schema_name}_` +2. מחק כל אוסף תואם (מטפל בממדים מרובים) +3. מחק מחיצות שורות Cassandra +4. נקה `row_partitions` + +#### מיקומי מודולים + +| שלב | מודול | נקודת כניסה | +|-------|--------|-------------| +| שלב 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| שלב 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### API לשאילתות הטמעות שורות + +שאילתת הטמעות השורות היא **API נפרד** משירות שאילתות השורות GraphQL: + +| API | מטרה | בסיס נתונים | +|-----|---------|---------| +| שאילתת שורות (GraphQL) | התאמה מדויקת בשדות מועדנים | Cassandra | +| שאילתת הטמעות שורות | התאמה מעורפלת/סמנטית | Qdrant | + +הפרדה זו שומרת על הפרדת אחריות: +שירות GraphQL מתמקד בשאילתות מדויקות ומובנות +ממשק הטמעות מטפל בדמיון סמנטי +זרימת עבודה של משתמש: חיפוש מעורפל באמצעות הטמעות כדי למצוא מועמדים, ולאחר מכן שאילתה מדויקת כדי לקבל את נתוני השורה המלאים + +#### סכימת בקשה/תגובה + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### מעבד שאילתות + +מודול: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +נקודת כניסה: `row-embeddings-query-qdrant` + +המעבד: +1. מקבל `RowEmbeddingsRequest` עם וקטורי שאילתה +2. מוצא את אוסף Qdrant המתאים באמצעות התאמה מקדימה +3. מחפש את הווקטורים הקרובים ביותר עם מסנן אופציונלי `index_name` +4. מחזיר `RowEmbeddingsResponse` עם מידע אינדקס תואם + +#### אינטגרציה עם שער API + +השער חושף שאילתות הטבעה של שורות באמצעות תבנית בקשה/תגובה סטנדרטית: + +| רכיב | מיקום | +|-----------|----------| +| מפזר | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| רישום | הוסף `"row-embeddings"` ל-`request_response_dispatchers` ב-`manager.py` | + +שם ממשק זרימה: `row-embeddings` + +הגדרת ממשק בתרשים זרימה: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### תמיכה ב-SDK של Python + +ה-SDK מספק שיטות לשאילתות הטמעות שורות: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### כלי שורת הפקודה + +פקודה: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### דוגמה טיפוסית לשימוש + +שאילתת הטמעות השורות משמשת בדרך כלל כחלק מזרימת חיפוש "מעורפל" לחיפוש מדויק: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +דפוס בן שני שלבים זה מאפשר: +מציאת "CHESTNUT ST" כאשר המשתמש מחפש "Chestnut Street" +שליפת נתוני שורה שלמים עם כל השדות +שילוב של דמיון סמנטי עם גישה לנתונים מובנים + +### קליטת נתוני שורה + +נדחה לשלב מאוחר יותר. יתוכנן יחד עם שינויי קליטה אחרים. + +## השפעה על יישום + +### ניתוח מצב נוכחי + +ליישום הקיים יש שני מרכיבים עיקריים: + +| רכיב | מיקום | שורות | תיאור | +|-----------|----------|-------|-------------| +| שירות שאילתות | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | מונוליטי: יצירת סכימת GraphQL, ניתוח פילטרים, שאילתות Cassandra, טיפול בבקשות | +| כותב | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | יצירת טבלאות לפי סכימה, אינדקסים משניים, הוספה/מחיקה | + +**דפוס שאילתות נוכחי:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**תבנית שאילתה חדשה:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### שינויים מרכזיים + +1. **הפשטת סמנטיקת שאילתות**: הסכימה החדשה תומכת רק בהתאמות מדויקות עבור `index_value`. מסנני ה-GraphQL הנוכחיים (`gt`, `lt`, `contains`, וכו') או: + הופכים לסינון לאחר קבלת הנתונים (אם עדיין נדרש) + מוסרים לטובת שימוש ב-API של הטמעות (embeddings) לביצוע התאמות משוערות + +2. **קוד GraphQL משולב הדוק**: ה-`service.py` הנוכחי כולל יצירת טיפוסים של Strawberry, ניתוח מסננים ושאילתות ספציפיות ל-Cassandra. הוספת בסיס נתונים טבלאי נוסף תכפיל כ-400 שורות של קוד GraphQL. + +### שינוי מבנה מוצע + +השינוי המבני כולל שני חלקים: + +#### 1. הפרדת קוד GraphQL + +חילוץ רכיבי GraphQL שניתן לעשות בהם שימוש חוזר למודול משותף: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +זה מאפשר: +שימוש חוזר בין בסיסי נתונים שונים +הפרדה נקייה יותר של תחומים +בדיקה קלה יותר של לוגיקת GraphQL באופן עצמאי + +#### 2. יישום סכימת טבלה חדשה + +שינוי הקוד הספציפי ל-Cassandra לשימוש בטבלה המאוחדת: + +**כותב** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +טבלה אחת של `rows` במקום טבלאות לכל סכימה +כתיבת N עותקים לשורה (אחד לכל אינדקס) +רישום לטבלה `row_partitions` +יצירת טבלה פשוטה יותר (הגדרה חד-פעמית) + +**שירות שאילתות** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +שאילתא של הטבלה המאוחדת `rows` +שימוש במודול GraphQL חלץ ליצירת סכימה +טיפול פשוט יותר בסינון (התאמה מדויקת בלבד ברמת מסד הנתונים) + +### שינוי שמות מודולים + +כחלק מניקוי השמות מ-"object" ל-"row": + +| נוכחי | חדש | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### מודולים חדשים + +| מודול | מטרה | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | כלי GraphQL משותפים | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | ממשק API לשאילתות הטמעות שורות | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | חישוב הטמעות שורות (שלב 1) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | אחסון הטמעות שורות (שלב 2) | + +## הפניות + +[מפרט טכני של נתונים מובנים](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.hi.md b/docs/tech-specs/structured-data-2.hi.md new file mode 100644 index 00000000..da032aed --- /dev/null +++ b/docs/tech-specs/structured-data-2.hi.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "संरचित डेटा तकनीकी विनिर्देश (भाग 2)" +parent: "Hindi (Beta)" +--- + +# संरचित डेटा तकनीकी विनिर्देश (भाग 2) + +> **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. + +## अवलोकन + +यह विनिर्देश उन मुद्दों और कमियों को संबोधित करता है जिन्हें ट्रस्टग्राफ के संरचित डेटा एकीकरण के प्रारंभिक कार्यान्वयन के दौरान पहचाना गया था, जैसा कि `structured-data.md` में वर्णित है। + +## समस्या विवरण + +### 1. नामकरण में असंगति: "ऑब्जेक्ट" बनाम "पंक्ति" + +वर्तमान कार्यान्वयन में पूरे समय "ऑब्जेक्ट" शब्दावली का उपयोग किया जाता है (उदाहरण के लिए, `ExtractedObject`, ऑब्जेक्ट निष्कर्षण, ऑब्जेक्ट एम्बेडिंग)। यह नामकरण बहुत सामान्य है और भ्रम पैदा करता है: + +"ऑब्जेक्ट" सॉफ्टवेयर में एक अतिव्यापी शब्द है (पायथन ऑब्जेक्ट, JSON ऑब्जेक्ट, आदि)। +संसाधित डेटा अनिवार्य रूप से सारणीबद्ध है - परिभाषित स्कीमा वाली तालिकाओं में पंक्तियाँ। +"पंक्ति" डेटा मॉडल का अधिक सटीक वर्णन है और यह डेटाबेस शब्दावली के साथ मेल खाता है। + +यह असंगति मॉड्यूल नामों, क्लास नामों, संदेश प्रकारों और दस्तावेज़ों में दिखाई देती है। + +### 2. पंक्ति भंडारण क्वेरी सीमाएँ + +वर्तमान पंक्ति भंडारण कार्यान्वयन में महत्वपूर्ण क्वेरी सीमाएँ हैं: + +**प्राकृतिक भाषा बेमेल**: क्वेरी वास्तविक दुनिया के डेटा विविधताओं के साथ संघर्ष करती हैं। उदाहरण के लिए: +`"CHESTNUT ST"` युक्त एक सड़क डेटाबेस को `"Chestnut Street"` के बारे में पूछने पर खोजना मुश्किल है। +संक्षिप्त नाम, केस अंतर और स्वरूपण भिन्नताएं सटीक-मेल क्वेरी को तोड़ देती हैं। +उपयोगकर्ताओं को सिमेंटिक समझ की उम्मीद होती है, लेकिन स्टोर शाब्दिक मिलान प्रदान करता है। + +**स्कीमा विकास मुद्दे**: स्कीमा में परिवर्तन समस्याएं पैदा करते हैं: +मौजूदा डेटा अद्यतन स्कीमा के अनुरूप नहीं हो सकता है। +तालिका संरचना में परिवर्तन क्वेरी और डेटा अखंडता को तोड़ सकते हैं। +स्कीमा अपडेट के लिए कोई स्पष्ट माइग्रेशन पथ नहीं है। + +### 3. पंक्ति एम्बेडिंग की आवश्यकता + +समस्या 2 से संबंधित, सिस्टम को पंक्ति डेटा के लिए वेक्टर एम्बेडिंग की आवश्यकता है ताकि: + +संरचित डेटा में सिमेंटिक खोज (जब डेटा में "CHESTNUT ST" हो तो "Chestnut Street" खोजना)। +धुंधली क्वेरी के लिए समानता मिलान। +संरचित फ़िल्टर को सिमेंटिक समानता के साथ मिलाने वाली हाइब्रिड खोज। +बेहतर प्राकृतिक भाषा क्वेरी समर्थन। + +एम्बेडिंग सेवा को निर्दिष्ट किया गया था लेकिन लागू नहीं किया गया था। + +### 4. पंक्ति डेटा अंतर्ग्रहण अधूरा + +संरचित डेटा अंतर्ग्रहण पाइपलाइन पूरी तरह से कार्यात्मक नहीं है: + +इनपुट प्रारूपों (CSV, JSON, आदि) को वर्गीकृत करने के लिए नैदानिक संकेत मौजूद हैं। +इन संकेतों का उपयोग करने वाली अंतर्ग्रहण सेवा को सिस्टम में प्लंब नहीं किया गया है। +पंक्ति स्टोर में पूर्व-संरचित डेटा लोड करने के लिए कोई एंड-टू-एंड पथ नहीं है। + +## लक्ष्य + +**स्कीमा लचीलापन**: मौजूदा डेटा को तोड़ने या माइग्रेशन की आवश्यकता के बिना स्कीमा विकास को सक्षम करें। +**संगत नामकरण**: पूरे कोडबेस में "पंक्ति" शब्दावली का मानकीकरण करें। +**सिमेंटिक क्वेरी क्षमता**: पंक्ति एम्बेडिंग के माध्यम से धुंधली/सिमेंटिक मिलान का समर्थन करें। +**पूर्ण अंतर्ग्रहण पाइपलाइन**: संरचित डेटा लोड करने के लिए एंड-टू-एंड पथ प्रदान करें। + +## तकनीकी डिजाइन + +### एकीकृत पंक्ति भंडारण स्कीमा + +पिछले कार्यान्वयन में प्रत्येक स्कीमा के लिए एक अलग कैसेंड्रा तालिका बनाई गई थी। इससे तब समस्याएं हुईं जब स्कीमा विकसित हुए, क्योंकि तालिका संरचना में परिवर्तन के लिए माइग्रेशन की आवश्यकता होती थी। + +नए डिज़ाइन में सभी पंक्ति डेटा के लिए एक एकल, एकीकृत तालिका का उपयोग किया जाता है: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### कॉलम परिभाषाएँ + +| कॉलम | प्रकार | विवरण | +|--------|------|-------------| +| `collection` | `text` | डेटा संग्रह/आयात पहचानकर्ता (मेटाडेटा से) | +| `schema_name` | `text` | स्कीमा का नाम जिससे यह पंक्ति मेल खाती है | +| `index_name` | `text` | अनुक्रमित फ़ील्ड का नाम, संयुक्त अल्पविराम के साथ (मिश्रित के लिए) | +| `index_value` | `frozen>` | अनुक्रमित मानों की सूची | +| `data` | `map` | पंक्ति डेटा कुंजी-मान जोड़े के रूप में | +| `source` | `text` | वैकल्पिक यूआरआई जो नॉलेज ग्राफ में मूल जानकारी से लिंक करता है। खाली स्ट्रिंग या NULL इंगित करता है कि कोई स्रोत नहीं है। | + +#### अनुक्रमण प्रबंधन + +प्रत्येक पंक्ति कई बार संग्रहीत की जाती है - स्कीमा में परिभाषित प्रत्येक अनुक्रमित फ़ील्ड के लिए एक बार। प्राथमिक कुंजी फ़ील्ड को किसी विशेष मार्कर के बिना एक अनुक्रमणिका के रूप में माना जाता है, जो भविष्य में लचीलापन प्रदान करता है। + +**सिंगल-फ़ील्ड अनुक्रमणिका का उदाहरण:** +स्कीमा `email` को अनुक्रमित के रूप में परिभाषित करता है +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**मिश्रित अनुक्रमणिका का उदाहरण:** +स्कीमा `region` और `status` पर मिश्रित अनुक्रमणिका को परिभाषित करता है +`index_name = "region,status"` (फ़ील्ड नाम क्रमबद्ध और अल्पविराम से जुड़े हुए) +`index_value = ['US', 'active']` (फ़ील्ड नामों के समान क्रम में मान) + +**प्राथमिक कुंजी का उदाहरण:** +स्कीमा `customer_id` को प्राथमिक कुंजी के रूप में परिभाषित करता है +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### क्वेरी पैटर्न + +सभी क्वेरी एक ही पैटर्न का पालन करती हैं, चाहे कोई भी अनुक्रमणिका उपयोग की जाए: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### डिज़ाइन में संतुलन + +**लाभ:** +स्कीमा में बदलावों के लिए टेबल संरचना में बदलाव की आवश्यकता नहीं होती है। +पंक्ति डेटा कैसेंड्रा के लिए अस्पष्ट है - फ़ील्ड जोड़ने/हटाने से कोई फर्क नहीं पड़ता। +सभी एक्सेस विधियों के लिए सुसंगत क्वेरी पैटर्न। +कोई कैसेंड्रा सेकेंडरी इंडेक्स नहीं (जो बड़े पैमाने पर धीमे हो सकते हैं)। +पूरी तरह से देशी कैसेंड्रा प्रकार (`map`, `frozen`)। + +**गड़बड़ियाँ:** +राइट एम्प्लीफिकेशन: प्रत्येक पंक्ति डालने = N डालने (प्रत्येक इंडेक्स्ड फ़ील्ड के लिए एक)। +डुप्लिकेट पंक्ति डेटा के कारण स्टोरेज ओवरहेड। +प्रकार की जानकारी स्कीमा कॉन्फ़िगरेशन में संग्रहीत है, एप्लिकेशन लेयर पर रूपांतरण। + +#### संगति मॉडल + +डिज़ाइन कुछ सरलीकरणों को स्वीकार करता है: + +1. **कोई पंक्ति अपडेट नहीं**: सिस्टम केवल अपेंड-ओनली है। यह एक ही पंक्ति की कई प्रतियों को अपडेट करने के बारे में संगति संबंधी चिंताओं को समाप्त करता है। + +2. **स्कीमा परिवर्तन सहिष्णुता**: जब स्कीमा बदलते हैं (उदाहरण के लिए, इंडेक्स जोड़े/हटाए जाते हैं), तो मौजूदा पंक्तियाँ अपनी मूल इंडेक्सिंग को बनाए रखती हैं। पुराने पंक्तियों को नए इंडेक्स के माध्यम से खोजा नहीं जा सकता है। यदि आवश्यक हो, तो उपयोगकर्ता संगति सुनिश्चित करने के लिए एक स्कीमा को हटा और पुनः बना सकते हैं। + +### विभाजन ट्रैकिंग और हटाना + +#### समस्या + +विभाजन कुंजी `(collection, schema_name, index_name)` के साथ, कुशल हटाने के लिए सभी विभाजन कुंजियों को हटाने की आवश्यकता होती है। केवल `collection` या `collection + schema_name` द्वारा हटाना उन सभी `index_name` मानों को जानने की आवश्यकता होती है जिनमें डेटा है। + +#### विभाजन ट्रैकिंग टेबल + +एक सेकेंडरी लुकअप टेबल ट्रैक करती है कि कौन से विभाजन मौजूद हैं: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +यह हटाने के कार्यों के लिए विभाजनों की कुशल खोज को सक्षम बनाता है। + +#### पंक्ति लेखक व्यवहार + +पंक्ति लेखक पंजीकृत `(collection, schema_name)` युग्मों का एक इन-मेमोरी कैश बनाए रखता है। पंक्ति को संसाधित करते समय: + +1. जांचें कि `(collection, schema_name)` कैश में है या नहीं। +2. यदि कैश में नहीं है (इस युग्म के लिए पहली पंक्ति): + सभी इंडेक्स नामों को प्राप्त करने के लिए स्कीमा कॉन्फ़िगरेशन देखें। + प्रत्येक `(collection, schema_name, index_name)` के लिए `row_partitions` में प्रविष्टियाँ डालें। + युग्म को कैश में जोड़ें। +3. पंक्ति डेटा लिखने के साथ आगे बढ़ें। + +पंक्ति लेखक स्कीमा कॉन्फ़िगरेशन परिवर्तन घटनाओं की भी निगरानी करता है। जब कोई स्कीमा बदलता है, तो प्रासंगिक कैश प्रविष्टियाँ साफ़ कर दी जाती हैं ताकि अगली पंक्ति अपडेट किए गए इंडेक्स नामों के साथ पुनः पंजीकरण को ट्रिगर करे। + +इस दृष्टिकोण से यह सुनिश्चित होता है: +लुकअप तालिका लेखन प्रत्येक `(collection, schema_name)` युग्म के लिए एक बार होता है, प्रत्येक पंक्ति के लिए नहीं। +लुकअप तालिका उन इंडेक्स को दर्शाती है जो डेटा लिखे जाने पर सक्रिय थे। +आयात के दौरान होने वाले स्कीमा परिवर्तनों को सही ढंग से पहचाना जाता है। + +#### हटाने के कार्य + +**संग्रह हटाएं:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**संग्रह और स्कीमा हटाएं:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### पंक्ति एम्बेडिंग + +पंक्ति एम्बेडिंग, अनुक्रमित मानों पर अर्थपूर्ण/अस्पष्ट मिलान को सक्षम करते हैं, जिससे प्राकृतिक भाषा में विसंगति की समस्या हल होती है (उदाहरण के लिए, "चेस्टनट स्ट्रीट" के लिए खोज करते समय "चेस्टनट एसटी" खोजना)। + +#### डिज़ाइन अवलोकन + +प्रत्येक अनुक्रमित मान को एम्बेड किया जाता है और एक वेक्टर स्टोर (क्यूड्रेंट) में संग्रहीत किया जाता है। क्वेरी के समय, क्वेरी को एम्बेड किया जाता है, समान वेक्टर पाए जाते हैं, और संबंधित मेटाडेटा का उपयोग कैसेंड्रा में वास्तविक पंक्तियों को देखने के लिए किया जाता है। + +#### क्यूड्रेंट संग्रह संरचना + +प्रत्येक `(user, collection, schema_name, dimension)` टपल के लिए एक क्यूड्रेंट संग्रह: + +**संग्रह नामकरण:** `rows_{user}_{collection}_{schema_name}_{dimension}` +नामों को साफ़ किया जाता है (गैर-अक्षरांकीय वर्णों को `_` से बदला जाता है, लोअरकेस किया जाता है, संख्यात्मक उपसर्गों को `r_` उपसर्ग मिलता है) +**तर्क:** एक `(user, collection, schema_name)` उदाहरण को मिलान वाले क्यूड्रेंट संग्रहों को हटाकर साफ-सुथरे तरीके से हटाने की अनुमति देता है; आयाम प्रत्यय विभिन्न एम्बेडिंग मॉडल को एक साथ मौजूद रहने की अनुमति देता है। + +#### क्या एम्बेड किया जाता है + +अनुक्रमण मानों का पाठ प्रतिनिधित्व: + +| अनुक्रमण प्रकार | उदाहरण `index_value` | एम्बेड करने के लिए पाठ | +|------------|----------------------|---------------| +| एकल-क्षेत्र | `['foo@bar.com']` | `"foo@bar.com"` | +| समग्र | `['US', 'active']` | `"US active"` (स्पेस-जोड़ा हुआ) | + +#### बिंदु संरचना + +प्रत्येक क्यूड्रेंट बिंदु में शामिल हैं: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| पेलोड फ़ील्ड | विवरण | +|---------------|-------------| +| `index_name` | यह एम्बेडिंग किस अनुक्रमित फ़ील्ड(s) का प्रतिनिधित्व करता है | +| `index_value` | मूल्यों की मूल सूची (कैसेंड्रा लुकअप के लिए) | +| `text` | वह पाठ जिसे एम्बेड किया गया था (डीबगिंग/प्रदर्शन के लिए) | + +ध्यान दें: `user`, `collection`, और `schema_name` Qdrant संग्रह नाम से निहित हैं। + +#### क्वेरी प्रवाह + +1. उपयोगकर्ता U, संग्रह X, स्कीमा Y के भीतर "चेस्टनट स्ट्रीट" के लिए क्वेरी करता है। +2. क्वेरी टेक्स्ट को एम्बेड करें। +3. उपसर्ग `rows_U_X_Y_` से मेल खाने वाले Qdrant संग्रह नाम(s) निर्धारित करें। +4. निकटतम वैक्टरों के लिए मिलान करने वाले Qdrant संग्रह(s) की खोज करें। +5. `index_name` और `index_value` युक्त पेलोड वाले मिलान करने वाले बिंदुओं को प्राप्त करें। +6. कैसेंड्रा को क्वेरी करें: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. मिलान किए गए पंक्तियों को वापस करना + +#### वैकल्पिक: इंडेक्स नाम द्वारा फ़िल्टरिंग + +क्वेरी वैकल्पिक रूप से Qdrant में `index_name` द्वारा फ़िल्टर की जा सकती हैं ताकि केवल विशिष्ट फ़ील्ड की खोज की जा सके: + +**"उन सभी फ़ील्ड को खोजें जो 'Chestnut' से मेल खाते हैं"** → संग्रह में सभी वैक्टर की खोज करें +**"उन सड़कों को खोजें जिनका नाम 'Chestnut' से मेल खाता है"** → उन पंक्तियों को फ़िल्टर करें जहाँ `payload.index_name = 'street_name'` + +#### आर्किटेक्चर + +पंक्ति एम्बेडिंग **दो-चरणीय पैटर्न** का पालन करते हैं जिसका उपयोग GraphRAG (ग्राफ-एम्बेडिंग, दस्तावेज़-एम्बेडिंग) द्वारा किया जाता है: + +**चरण 1: एम्बेडिंग गणना** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - `ExtractedObject` का उपयोग करता है, एम्बेडिंग सेवा के माध्यम से एम्बेडिंग की गणना करता है, `RowEmbeddings` आउटपुट करता है +**चरण 2: एम्बेडिंग भंडारण** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - `RowEmbeddings` का उपयोग करता है, वैक्टर को Qdrant में लिखता है + +कैसेंड्रा पंक्ति लेखक एक अलग समानांतर उपभोक्ता है: + +**कैसेंड्रा पंक्ति लेखक** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - `ExtractedObject` का उपयोग करता है, पंक्तियों को कैसेंड्रा में लिखता है + +तीनों सेवाएं एक ही प्रवाह से डेटा लेती हैं, जिससे वे अलग-अलग रहती हैं। यह अनुमति देता है: +कैसेंड्रा लेखन बनाम एम्बेडिंग पीढ़ी बनाम वेक्टर भंडारण का स्वतंत्र स्केलिंग +यदि आवश्यक न हो तो एम्बेडिंग सेवाओं को अक्षम किया जा सकता है +एक सेवा में विफलता अन्य सेवाओं को प्रभावित नहीं करती है +GraphRAG पाइपलाइनों के साथ सुसंगत आर्किटेक्चर + +#### लेखन पथ + +**चरण 1 (पंक्ति-एम्बेडिंग प्रोसेसर):** जब एक `ExtractedObject` प्राप्त होता है: + +1. अनुक्रमित फ़ील्ड खोजने के लिए स्कीमा देखें +2. प्रत्येक अनुक्रमित फ़ील्ड के लिए: + अनुक्रमण मान का पाठ प्रतिनिधित्व बनाएं + एम्बेडिंग सेवा के माध्यम से एम्बेडिंग की गणना करें +3. सभी गणना किए गए वैक्टर युक्त एक `RowEmbeddings` संदेश आउटपुट करें + +**चरण 2 (पंक्ति-एम्बेडिंग-लिखें-Qdrant):** जब एक `RowEmbeddings` प्राप्त होता है: + +1. संदेश में प्रत्येक एम्बेडिंग के लिए: + `(user, collection, schema_name, dimension)` से Qdrant संग्रह निर्धारित करें + यदि आवश्यक हो तो संग्रह बनाएं (पहली बार लिखने पर आलसी निर्माण) + वेक्टर और पेलोड के साथ पॉइंट अपサート करें + +#### संदेश प्रकार + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### विलोपन एकीकरण + +Qdrant संग्रह, संग्रह नाम पैटर्न पर उपसर्ग मिलान द्वारा खोजे जाते हैं: + +**`(user, collection)` हटाएं:** +1. `rows_{user}_{collection}_` उपसर्ग से मेल खाने वाले सभी Qdrant संग्रहों की सूची बनाएं +2. प्रत्येक मेल खाने वाले संग्रह को हटाएं +3. कैसेंड्रा पंक्तियों के विभाजन को हटाएं (जैसा कि ऊपर प्रलेखित है) +4. `row_partitions` प्रविष्टियों को साफ़ करें + +**`(user, collection, schema_name)` हटाएं:** +1. `rows_{user}_{collection}_{schema_name}_` उपसर्ग से मेल खाने वाले सभी Qdrant संग्रहों की सूची बनाएं +2. प्रत्येक मेल खाने वाले संग्रह को हटाएं (यह कई आयामों को संभालता है) +3. कैसेंड्रा पंक्तियों के विभाजन को हटाएं +4. `row_partitions` को साफ़ करें + +#### मॉड्यूल स्थान + +| चरण | मॉड्यूल | प्रवेश बिंदु | +|-------|--------|-------------| +| चरण 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| चरण 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### पंक्ति एम्बेडिंग क्वेरी एपीआई + +पंक्ति एम्बेडिंग क्वेरी, GraphQL पंक्ति क्वेरी सेवा से एक **अलग एपीआई** है: + +| एपीआई | उद्देश्य | बैकएंड | +|-----|---------|---------| +| पंक्ति क्वेरी (GraphQL) | अनुक्रमित फ़ील्ड पर सटीक मिलान | कैसेंड्रा | +| पंक्ति एम्बेडिंग क्वेरी | अस्पष्ट/अर्थ संबंधी मिलान | Qdrant | + +यह अलगाव चिंताओं को साफ रखता है: +GraphQL सेवा सटीक, संरचित प्रश्नों पर केंद्रित है +एम्बेडिंग एपीआई अर्थ संबंधी समानता को संभालता है +उपयोगकर्ता कार्यप्रवाह: उम्मीदवारों को खोजने के लिए एम्बेडिंग के माध्यम से अस्पष्ट खोज, फिर पूर्ण पंक्ति डेटा प्राप्त करने के लिए सटीक क्वेरी + +#### अनुरोध/प्रतिक्रिया स्कीमा + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### क्वेरी प्रोसेसर + +मॉड्यूल: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +प्रवेश बिंदु: `row-embeddings-query-qdrant` + +प्रोसेसर: +1. `RowEmbeddingsRequest` के साथ क्वेरी वेक्टर प्राप्त करता है +2. उपसर्ग मिलान के माध्यम से उपयुक्त Qdrant संग्रह ढूंढता है +3. वैकल्पिक `index_name` फ़िल्टर के साथ निकटतम वेक्टर खोजता है +4. मिलान किए गए इंडेक्स जानकारी के साथ `RowEmbeddingsResponse` लौटाता है + +#### एपीआई गेटवे एकीकरण + +गेटवे मानक अनुरोध/प्रतिक्रिया पैटर्न के माध्यम से पंक्ति एम्बेडिंग प्रश्नों को उजागर करता है: + +| घटक | स्थान | +|-----------|----------| +| डिस्पैचर | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| पंजीकरण | `"row-embeddings"` को `request_response_dispatchers` में `manager.py` में जोड़ें | + +फ्लो इंटरफ़ेस नाम: `row-embeddings` + +फ्लो ब्लूप्रिंट में इंटरफ़ेस परिभाषा: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### पायथन एसडीके समर्थन + +एसडीके पंक्ति एम्बेडिंग प्रश्नों के लिए विधियाँ प्रदान करता है: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### कमांड लाइन यूटिलिटी + +कमांड: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### विशिष्ट उपयोग पैटर्न + +पंक्ति एम्बेडिंग क्वेरी का उपयोग आमतौर पर एक अस्पष्ट-से-सटीक लुकअप प्रवाह के हिस्से के रूप में किया जाता है: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +यह दो-चरणीय पैटर्न निम्नलिखित को सक्षम करता है: +जब उपयोगकर्ता "Chestnut Street" खोजता है तो "CHESTNUT ST" खोजना। +सभी फ़ील्ड के साथ पूरी पंक्ति डेटा प्राप्त करना। +संरचित डेटा एक्सेस के साथ सिमेंटिक समानता को जोड़ना। + +### पंक्ति डेटा का अंतर्ग्रहण + +बाद के चरण में स्थगित। अन्य अंतर्ग्रहण परिवर्तनों के साथ मिलकर डिज़ाइन किया जाएगा। + +## कार्यान्वयन प्रभाव + +### वर्तमान स्थिति विश्लेषण + +मौजूदा कार्यान्वयन में दो मुख्य घटक हैं: + +| घटक | स्थान | लाइनें | विवरण | +|-----------|----------|-------|-------------| +| क्वेरी सेवा | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | एकरूप: GraphQL स्कीमा पीढ़ी, फ़िल्टर पार्सिंग, कैसेंड्रा क्वेरी, अनुरोध हैंडलिंग | +| लेखक | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | प्रति-स्कीमा तालिका निर्माण, द्वितीयक अनुक्रमणिका, सम्मिलित/हटाना | + +**वर्तमान क्वेरी पैटर्न:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**नई क्वेरी पैटर्न:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### मुख्य परिवर्तन + +1. **क्वेरी सिमेंटिक्स को सरल बनाया गया**: नया स्कीमा केवल `index_value` पर सटीक मिलान का समर्थन करता है। वर्तमान GraphQL फ़िल्टर (`gt`, `lt`, `contains`, आदि) या तो: + लौटाए गए डेटा पर पोस्ट-फ़िल्टरिंग बन जाते हैं (यदि अभी भी आवश्यक हैं) + अस्पष्ट मिलान के लिए एम्बेडिंग एपीआई का उपयोग करने के पक्ष में हटा दिए जाते हैं + +2. **GraphQL कोड दृढ़ता से युग्मित है**: वर्तमान `service.py` स्ट्रॉबेरी टाइप जनरेशन, फ़िल्टर पार्सिंग और कैसेंड्रा-विशिष्ट प्रश्नों को बंडल करता है। एक और रो स्टोर बैकएंड जोड़ने से ~400 लाइनों का GraphQL कोड दोहराया जाएगा। + +### प्रस्तावित रिफैक्टर + +रिफैक्टर में दो भाग हैं: + +#### 1. GraphQL कोड को अलग करें + +पुन: प्रयोज्य GraphQL घटकों को एक साझा मॉड्यूल में निकालें: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +यह निम्नलिखित कार्य करता है: +विभिन्न रो स्टोर बैकएंड में पुन: उपयोग +चिंताओं का स्पष्ट अलगाव +GraphQL लॉजिक का स्वतंत्र रूप से परीक्षण करना आसान + +#### 2. नई टेबल स्कीमा को लागू करें + +कैसेंड्रा-विशिष्ट कोड को एकीकृत टेबल का उपयोग करने के लिए रिफैक्टर करें: + +**राइटर** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +प्रति-स्कीमा टेबल के बजाय एक एकल `rows` टेबल +प्रति पंक्ति N प्रतियां लिखें (प्रत्येक इंडेक्स के लिए एक) +`row_partitions` टेबल में पंजीकरण करें +सरल टेबल निर्माण (एक बार सेटअप) + +**क्वेरी सर्विस** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +एकीकृत `rows` टेबल को क्वेरी करें +स्कीमा पीढ़ी के लिए निकाले गए GraphQL मॉड्यूल का उपयोग करें +सरलीकृत फ़िल्टर हैंडलिंग (केवल DB स्तर पर सटीक मिलान) + +### मॉड्यूल का नाम बदलना + +"ऑब्जेक्ट" से "रो" नामकरण को साफ करने के हिस्से के रूप में: + +| वर्तमान | नया | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### नए मॉड्यूल + +| मॉड्यूल | उद्देश्य | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | साझा GraphQL उपयोगिताएँ | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | रो एम्बेडिंग क्वेरी एपीआई | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | रो एम्बेडिंग गणना (स्टेज 1) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | रो एम्बेडिंग भंडारण (स्टेज 2) | + +## संदर्भ + +[स्ट्रक्चर्ड डेटा तकनीकी विनिर्देश](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.md b/docs/tech-specs/structured-data-2.md index 1b70a6c3..807d3326 100644 --- a/docs/tech-specs/structured-data-2.md +++ b/docs/tech-specs/structured-data-2.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Structured Data Technical Specification (Part 2)" +parent: "Tech Specs" +--- + # Structured Data Technical Specification (Part 2) ## Overview diff --git a/docs/tech-specs/structured-data-2.pt.md b/docs/tech-specs/structured-data-2.pt.md new file mode 100644 index 00000000..f14198de --- /dev/null +++ b/docs/tech-specs/structured-data-2.pt.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "Especificação Técnica de Dados Estruturados (Parte 2)" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Dados Estruturados (Parte 2) + +> **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 aborda problemas e lacunas identificadas durante a implementação inicial da integração de dados estruturados do TrustGraph, conforme descrito em `structured-data.md`. + +## Declarações do Problema + +### 1. Inconsistência na Nomenclatura: "Objeto" vs "Linha" + +A implementação atual usa a terminologia "objeto" em todo o código (por exemplo, `ExtractedObject`, extração de objetos, incorporações de objetos). Essa nomenclatura é muito genérica e causa confusão: + +"Objeto" é um termo sobrecarregado em software (objetos Python, objetos JSON, etc.) +Os dados que estão sendo processados são fundamentalmente tabulares - linhas em tabelas com esquemas definidos +"Linha" descreve com mais precisão o modelo de dados e está alinhado com a terminologia de banco de dados + +Essa inconsistência aparece em nomes de módulos, nomes de classes, tipos de mensagens e documentação. + +### 2. Limitações de Consulta do Armazenamento de Linhas + +A implementação atual do armazenamento de linhas tem limitações significativas de consulta: + +**Incompatibilidade com a Linguagem Natural**: As consultas têm dificuldades com variações de dados do mundo real. Por exemplo: +É difícil encontrar uma base de dados de ruas contendo `"CHESTNUT ST"` quando se pergunta sobre `"Chestnut Street"` +Abreviaturas, diferenças de maiúsculas e minúsculas e variações de formatação interrompem as consultas de correspondência exata +Os usuários esperam compreensão semântica, mas o armazenamento fornece correspondência literal + +**Problemas de Evolução do Esquema**: Alterar os esquemas causa problemas: +Os dados existentes podem não estar em conformidade com os esquemas atualizados +Alterações na estrutura da tabela podem quebrar consultas e a integridade dos dados +Não há um caminho de migração claro para atualizações de esquema + +### 3. Incorporações de Linhas Necessárias + +Relacionado ao problema 2, o sistema precisa de incorporações vetoriais para dados de linha para permitir: + +Pesquisa semântica em dados estruturados (encontrando "Chestnut Street" quando os dados contêm "CHESTNUT ST") +Correspondência de similaridade para consultas aproximadas +Pesquisa híbrida combinando filtros estruturados com similaridade semântica +Melhor suporte para consultas em linguagem natural + +O serviço de incorporação foi especificado, mas não implementado. + +### 4. Ingestão de Dados de Linha Incompleta + +O pipeline de ingestão de dados estruturados não está totalmente operacional: + +Existem prompts de diagnóstico para classificar formatos de entrada (CSV, JSON, etc.) +O serviço de ingestão que usa esses prompts não está integrado ao sistema +Não há um caminho de ponta a ponta para carregar dados pré-estruturados no armazenamento de linhas + +## Objetivos + +**Flexibilidade de Esquema**: Permitir a evolução do esquema sem quebrar dados existentes ou exigir migrações +**Nomenclatura Consistente**: Padronizar na terminologia "linha" em todo o código +**Consultabilidade Semântica**: Suportar correspondência aproximada/semântica por meio de incorporações de linhas +**Pipeline de Ingestão Completo**: Fornecer um caminho de ponta a ponta para carregar dados estruturados + +## Design Técnico + +### Esquema de Armazenamento de Linhas Unificado + +A implementação anterior criou uma tabela Cassandra separada para cada esquema. Isso causou problemas quando os esquemas evoluíram, pois as alterações na estrutura da tabela exigiram migrações. + +O novo design usa uma única tabela unificada para todos os dados de linha: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### Definições das Colunas + +| Coluna | Tipo | Descrição | +|--------|------|-------------| +| `collection` | `text` | Identificador de coleta/importação de dados (a partir de metadados) | +| `schema_name` | `text` | Nome do esquema ao qual esta linha está em conformidade | +| `index_name` | `text` | Nome(s) do(s) campo(s) indexado(s), unidos por vírgula para compostos | +| `index_value` | `frozen>` | Valor(es) do índice como uma lista | +| `data` | `map` | Dados da linha como pares chave-valor | +| `source` | `text` | URI opcional que faz referência a informações de procedência no grafo de conhecimento. Uma string vazia ou NULL indica que não há fonte. | + +#### Tratamento de Índices + +Cada linha é armazenada várias vezes - uma vez por campo indexado definido no esquema. Os campos de chave primária são tratados como um índice sem um marcador especial, proporcionando flexibilidade futura. + +**Exemplo de índice de campo único:** +O esquema define `email` como indexado +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**Exemplo de índice composto:** +O esquema define um índice composto em `region` e `status` +`index_name = "region,status"` (nomes dos campos ordenados e unidos por vírgula) +`index_value = ['US', 'active']` (valores na mesma ordem dos nomes dos campos) + +**Exemplo de chave primária:** +O esquema define `customer_id` como chave primária +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### Padrões de Consulta + +Todas as consultas seguem o mesmo padrão, independentemente de qual índice é usado: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### Compensações no Design + +**Vantagens:** +Alterações no esquema não exigem alterações na estrutura da tabela +Os dados das linhas são opacos para o Cassandra - adições/remoções de campos são transparentes +Padrão de consulta consistente para todos os métodos de acesso +Sem índices secundários do Cassandra (que podem ser lentos em grande escala) +Tipos nativos do Cassandra em todo o sistema (`map`, `frozen`) + +**Compensações:** +Amplificação de escrita: cada inserção de linha = N inserções (uma por campo indexado) +Sobrecarga de armazenamento devido à duplicação de dados das linhas +Informações de tipo armazenadas na configuração do esquema, conversão na camada de aplicação + +#### Modelo de Consistência + +O design aceita certas simplificações: + +1. **Sem atualizações de linha**: O sistema é somente de anexação. Isso elimina as preocupações com a consistência ao atualizar várias cópias da mesma linha. + +2. **Tolerância a alterações de esquema**: Quando os esquemas são alterados (por exemplo, índices adicionados/removidos), as linhas existentes mantêm seu índice original. Linhas antigas não serão encontradas por meio de novos índices. Os usuários podem excluir e recriar um esquema para garantir a consistência, se necessário. + +### Rastreamento e Exclusão de Partições + +#### O Problema + +Com a chave de partição `(collection, schema_name, index_name)`, a exclusão eficiente requer o conhecimento de todas as chaves de partição a serem excluídas. Excluir apenas por `collection` ou `collection + schema_name` requer o conhecimento de todos os valores de `index_name` que contêm dados. + +#### Tabela de Rastreamento de Partições + +Uma tabela de consulta secundária rastreia quais partições existem: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +Isso permite a descoberta eficiente de partições para operações de exclusão. + +#### Comportamento do Escritor de Linhas + +O escritor de linhas mantém um cache na memória de pares `(collection, schema_name)` registrados. Ao processar uma linha: + +1. Verifique se `(collection, schema_name)` está no cache. +2. Se não estiver no cache (primeira linha para este par): + Consulte a configuração do esquema para obter todos os nomes de índice. + Insira entradas em `row_partitions` para cada `(collection, schema_name, index_name)`. + Adicione o par ao cache. +3. Continue com a escrita dos dados da linha. + +O escritor de linhas também monitora eventos de alteração da configuração do esquema. Quando um esquema é alterado, as entradas relevantes do cache são limpas para que a próxima linha acione o re-registro com os nomes de índice atualizados. + +Essa abordagem garante: +As escritas na tabela de pesquisa ocorrem apenas uma vez por par `(collection, schema_name)`, e não por linha. +A tabela de pesquisa reflete os índices que estavam ativos quando os dados foram escritos. +As alterações no esquema durante a importação são detectadas corretamente. + +#### Operações de Exclusão + +**Excluir coleção:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**Excluir coleção + esquema:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### Incorporações de Linhas + +As incorporações de linhas permitem a correspondência semântica/aproximada em valores indexados, resolvendo o problema de incompatibilidade de linguagem natural (por exemplo, encontrar "CHESTNUT ST" ao pesquisar por "Chestnut Street"). + +#### Visão Geral do Design + +Cada valor indexado é incorporado e armazenado em um armazenamento vetorial (Qdrant). No momento da consulta, a consulta é incorporada, vetores semelhantes são encontrados e os metadados associados são usados para pesquisar as linhas reais no Cassandra. + +#### Estrutura da Coleção Qdrant + +Uma coleção Qdrant por tupla `(user, collection, schema_name, dimension)`: + +**Nome da coleção:** `rows_{user}_{collection}_{schema_name}_{dimension}` +Os nomes são higienizados (caracteres não alfanuméricos substituídos por `_`, em letras minúsculas, os prefixos numéricos recebem o prefixo `r_`) +**Justificativa:** Permite a exclusão limpa de uma instância `(user, collection, schema_name)`, descartando as coleções Qdrant correspondentes; o sufixo de dimensão permite que diferentes modelos de incorporação coexistam. + +#### O Que é Incorporado + +A representação de texto dos valores do índice: + +| Tipo de Índice | Exemplo `index_value` | Texto a Incorporar | +|------------|----------------------|---------------| +| Campo único | `['foo@bar.com']` | `"foo@bar.com"` | +| Composto | `['US', 'active']` | `"US active"` (juntados por espaço) | + +#### Estrutura do Ponto + +Cada ponto Qdrant contém: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| Campo de Payload | Descrição | +|---------------|-------------| +| `index_name` | Os campos indexados que esta incorporação representa | +| `index_value` | A lista original de valores (para pesquisa no Cassandra) | +| `text` | O texto que foi incorporado (para depuração/exibição) | + +Nota: `user`, `collection` e `schema_name` são implícitos do nome da coleção Qdrant. + +#### Fluxo de Consulta + +1. O usuário consulta por "Chestnut Street" dentro do usuário U, coleção X, esquema Y +2. Incorpore o texto da consulta +3. Determine o(s) nome(s) da coleção Qdrant que correspondem ao prefixo `rows_U_X_Y_` +4. Pesquise na(s) coleção(ões) Qdrant correspondente(s) pelos vetores mais próximos +5. Obtenha os pontos correspondentes com payloads contendo `index_name` e `index_value` +6. Consulte o Cassandra: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. Retornar linhas correspondentes + +#### Opcional: Filtragem por Nome do Índice + +As consultas podem opcionalmente filtrar por `index_name` no Qdrant para pesquisar apenas campos específicos: + +**"Encontrar qualquer campo que corresponda a 'Chestnut'"** → pesquisa todos os vetores na coleção +**"Encontrar street_name que corresponda a 'Chestnut'"** → filtrar onde `payload.index_name = 'street_name'` + +#### Arquitetura + +Os embeddings das linhas seguem o **padrão de duas etapas** usado pelo GraphRAG (embeddings do grafo, embeddings do documento): + +**Etapa 1: Computação de embeddings** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - Consome `ExtractedObject`, calcula embeddings através do serviço de embeddings, gera `RowEmbeddings` +**Etapa 2: Armazenamento de embeddings** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - Consome `RowEmbeddings`, escreve vetores no Qdrant + +O escritor de linhas do Cassandra é um consumidor paralelo separado: + +**Escritor de linhas do Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - Consome `ExtractedObject`, escreve linhas no Cassandra + +Todos os três serviços consomem do mesmo fluxo, mantendo-os desacoplados. Isso permite: +Escalonamento independente das escritas do Cassandra em relação à geração de embeddings em relação ao armazenamento de vetores +Os serviços de embeddings podem ser desativados se não forem necessários +Falhas em um serviço não afetam os outros +Arquitetura consistente com os pipelines do GraphRAG + +#### Caminho de Escrita + +**Etapa 1 (processador de embeddings das linhas):** Ao receber um `ExtractedObject`: + +1. Consultar o esquema para encontrar campos indexados +2. Para cada campo indexado: + Construir a representação de texto do valor do índice + Calcular o embedding através do serviço de embeddings +3. Gerar uma mensagem `RowEmbeddings` contendo todos os vetores calculados + +**Etapa 2 (escritor de embeddings-Qdrant):** Ao receber um `RowEmbeddings`: + +1. Para cada embedding na mensagem: + Determinar a coleção do Qdrant a partir de `(user, collection, schema_name, dimension)` + Criar a coleção, se necessário (criação preguiçosa na primeira escrita) + Inserir/atualizar o ponto com o vetor e o payload + +#### Tipos de Mensagens + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### Integração de Exclusão + +As coleções Qdrant são descobertas por correspondência de prefixo no padrão de nome da coleção: + +**Excluir `(user, collection)`:** +1. Listar todas as coleções Qdrant que correspondem ao prefixo `rows_{user}_{collection}_` +2. Excluir cada coleção correspondente +3. Excluir partições de linhas do Cassandra (como documentado acima) +4. Limpar as entradas `row_partitions` + +**Excluir `(user, collection, schema_name)`:** +1. Listar todas as coleções Qdrant que correspondem ao prefixo `rows_{user}_{collection}_{schema_name}_` +2. Excluir cada coleção correspondente (lida com múltiplas dimensões) +3. Excluir partições de linhas do Cassandra +4. Limpar `row_partitions` + +#### Localizações dos Módulos + +| Estágio | Módulo | Ponto de Entrada | +|-------|--------|-------------| +| Estágio 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| Estágio 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### API de Consulta de Incorporações de Linhas + +A consulta de incorporações de linhas é uma **API separada** do serviço de consulta de linhas GraphQL: + +| API | Propósito | Backend | +|-----|---------|---------| +| Consulta de Linhas (GraphQL) | Correspondência exata em campos indexados | Cassandra | +| Consulta de Incorporações de Linhas | Correspondência aproximada/semântica | Qdrant | + +Essa separação mantém as responsabilidades bem definidas: +O serviço GraphQL se concentra em consultas estruturadas e exatas +A API de incorporações lida com a similaridade semântica +Fluxo de trabalho do usuário: pesquisa aproximada por meio de incorporações para encontrar candidatos e, em seguida, consulta exata para obter os dados completos da linha + +#### Esquema de Solicitação/Resposta + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### Processador de Consultas + +Módulo: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +Ponto de entrada: `row-embeddings-query-qdrant` + +O processador: +1. Recebe `RowEmbeddingsRequest` com vetores de consulta +2. Encontra a coleção Qdrant apropriada por correspondência de prefixo +3. Procura os vetores mais próximos com filtro opcional `index_name` +4. Retorna `RowEmbeddingsResponse` com informações do índice correspondente + +#### Integração com o Gateway de API + +O gateway expõe consultas de incorporações de linhas através do padrão padrão de solicitação/resposta: + +| Componente | Localização | +|-----------|----------| +| Dispatcher | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| Registro | Adicione `"row-embeddings"` a `request_response_dispatchers` em `manager.py` | + +Nome da interface do fluxo: `row-embeddings` + +Definição da interface no blueprint do fluxo: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### Suporte ao SDK Python + +O SDK fornece métodos para consultas de incorporações de linhas: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### Utilitário de Linha de Comando (CLI) + +Comando: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### Padrão de Uso Típico + +A consulta de incorporações de linhas é normalmente usada como parte de um fluxo de pesquisa aproximada para correspondência exata: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +Este padrão de duas etapas permite: +Encontrar "CHESTNUT ST" quando o usuário pesquisa por "Chestnut Street" +Recuperar dados completos da linha com todos os campos +Combinar similaridade semântica com acesso a dados estruturados + +### Ingestão de Dados da Linha + +Será adiada para uma fase posterior. Será projetada juntamente com outras alterações de ingestão. + +## Impacto na Implementação + +### Análise do Estado Atual + +A implementação existente possui dois componentes principais: + +| Componente | Localização | Linhas | Descrição | +|-----------|----------|-------|-------------| +| Serviço de Consulta | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | Monolítico: geração de esquema GraphQL, análise de filtros, consultas Cassandra, tratamento de solicitações | +| Escritor | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | Criação de tabelas por esquema, índices secundários, inserção/exclusão | + +**Padrão de Consulta Atual:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**Novo Padrão de Consulta:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### Mudanças Principais + +1. **A semântica das consultas é simplificada**: O novo esquema suporta apenas correspondências exatas em `index_value`. Os filtros GraphQL atuais (`gt`, `lt`, `contains`, etc.) ou: + Tornam-se pós-filtragem nos dados retornados (se ainda forem necessários) + São removidos em favor do uso da API de embeddings para correspondências aproximadas + +2. **O código GraphQL está fortemente acoplado**: O código `service.py` atual combina a geração de tipos Strawberry, a análise de filtros e as consultas específicas do Cassandra. Adicionar outro backend de armazenamento de linhas duplicaria cerca de 400 linhas de código GraphQL. + +### Refatoração Proposta + +A refatoração tem duas partes: + +#### 1. Separar o Código GraphQL + +Extrair componentes GraphQL reutilizáveis para um módulo compartilhado: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +Isso permite: +Reutilização em diferentes backends de armazenamento de dados. +Separação mais clara de responsabilidades. +Teste mais fácil da lógica GraphQL de forma independente. + +#### 2. Implementar Novo Esquema de Tabela + +Refatorar o código específico do Cassandra para usar a tabela unificada: + +**Escritor** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +Uma única tabela `rows` em vez de tabelas por esquema. +Escrever N cópias por linha (uma por índice). +Registrar na tabela `row_partitions`. +Criação de tabela mais simples (configuração única). + +**Serviço de Consulta** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +Consultar a tabela `rows` unificada. +Usar o módulo GraphQL extraído para geração de esquema. +Tratamento de filtros simplificado (apenas correspondência exata no nível do banco de dados). + +### Renomeação de Módulos + +Como parte da limpeza de nomes de "objeto" para "linha": + +| Atual | Novo | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### Novos Módulos + +| Módulo | Propósito | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | Utilitários GraphQL compartilhados | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | API de consulta de incorporações de linhas | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | Cálculo de incorporações de linhas (Etapa 1) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | Armazenamento de incorporações de linhas (Etapa 2) | + +## Referências + +[Especificação Técnica de Dados Estruturados](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.ru.md b/docs/tech-specs/structured-data-2.ru.md new file mode 100644 index 00000000..877d32db --- /dev/null +++ b/docs/tech-specs/structured-data-2.ru.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "Техническая спецификация структурированных данных (часть 2)" +parent: "Russian (Beta)" +--- + +# Техническая спецификация структурированных данных (часть 2) + +> **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, как описано в `structured-data.md`. + +## Описание проблем + +### 1. Несоответствие в наименованиях: "Объект" против "Строка" + +В текущей реализации используется терминология "объект" во всем коде (например, `ExtractedObject`, извлечение объектов, векторные представления объектов). Это наименование слишком общее и вызывает путаницу: + +Термин "объект" является перегруженным в программном обеспечении (объекты Python, объекты JSON и т.д.) +Данные, которые обрабатываются, по сути являются табличными - строки в таблицах с определенными схемами. +"Строка" более точно описывает модель данных и соответствует терминологии баз данных. + +Это несоответствие проявляется в названиях модулей, названиях классов, типах сообщений и документации. + +### 2. Ограничения запросов к хранилищу строк + +Текущая реализация хранилища строк имеет значительные ограничения по запросам: + +**Несоответствие с естественным языком**: Запросы испытывают трудности с вариациями реальных данных. Например: +Сложно найти базу данных улиц, содержащую `"CHESTNUT ST"`, при запросе информации о `"Chestnut Street"`. +Аббревиатуры, различия в регистре и вариации форматирования нарушают запросы точного соответствия. +Пользователи ожидают семантического понимания, но хранилище обеспечивает только буквальное сопоставление. + +**Проблемы с эволюцией схемы**: Изменение схем вызывает проблемы: +Существующие данные могут не соответствовать обновленным схемам. +Изменения структуры таблицы могут нарушить запросы и целостность данных. +Отсутствует четкий путь миграции для обновлений схемы. + +### 3. Требуются векторные представления строк + +В связи с проблемой 2, системе требуются векторные представления данных строк для обеспечения: + +Семантического поиска по структурированным данным (поиск "Chestnut Street", когда данные содержат "CHESTNUT ST"). +Сопоставления по сходству для нечетких запросов. +Гибридного поиска, сочетающего структурированные фильтры с семантическим сходством. +Лучшей поддержки запросов на естественном языке. + +Сервис создания векторных представлений был определен, но не реализован. + +### 4. Неполная загрузка данных строк + +Конвейер загрузки структурированных данных не полностью функционирует: + +Существуют диагностические подсказки для классификации форматов входных данных (CSV, JSON и т.д.). +Сервис загрузки, использующий эти подсказки, не подключен к системе. +Отсутствует сквозной путь для загрузки предварительно структурированных данных в хранилище строк. + +## Цели + +**Гибкость схемы**: Обеспечить эволюцию схемы без нарушения существующих данных или необходимости миграций. +**Согласованное наименование**: Стандартизировать использование термина "строка" во всем коде. +**Семантическая запросаемость**: Поддержка нечеткого/семантического сопоставления с помощью векторных представлений строк. +**Полный конвейер загрузки**: Предоставить сквозной путь для загрузки структурированных данных. + +## Технический дизайн + +### Унифицированная схема хранения строк + +В предыдущей реализации для каждой схемы создавалась отдельная таблица Cassandra. Это вызывало проблемы при эволюции схем, поскольку изменения структуры таблицы требовали миграций. + +В новой разработке используется единая унифицированная таблица для всех данных строк: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### Описание столбцов + +| Столбец | Тип | Описание | +|--------|------|-------------| +| `collection` | `text` | Идентификатор сбора/импорта данных (из метаданных) | +| `schema_name` | `text` | Название схемы, которой соответствует эта строка | +| `index_name` | `text` | Название индексируемого поля (полей), объединенное запятыми для составных индексов | +| `index_value` | `frozen>` | Значение(я) индекса в виде списка | +| `data` | `map` | Данные строки в виде пар ключ-значение | +| `source` | `text` | Необязательный URI, ссылающийся на информацию об источнике в графе знаний. Пустая строка или NULL указывает на отсутствие источника. | + +#### Обработка индексов + +Каждая строка хранится несколько раз - один раз для каждого индексируемого поля, определенного в схеме. Первичные ключи рассматриваются как индекс без специального маркера, что обеспечивает гибкость в будущем. + +**Пример индекса для одного поля:** +Схема определяет `email` как индексируемое +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**Пример составного индекса:** +Схема определяет составной индекс для `region` и `status` +`index_name = "region,status"` (названия полей отсортированы и объединены запятыми) +`index_value = ['US', 'active']` (значения в том же порядке, что и названия полей) + +**Пример первичного ключа:** +Схема определяет `customer_id` как первичный ключ +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### Шаблоны запросов + +Все запросы следуют одной и той же схеме, независимо от того, какой индекс используется: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### Компромиссы в проектировании + +**Преимущества:** +Изменения схемы не требуют изменений структуры таблицы +Данные строк не видны Cassandra - добавление/удаление полей прозрачно +Единый шаблон запросов для всех методов доступа +Отсутствуют вторичные индексы Cassandra (которые могут быть медленными при больших масштабах) +Использование нативных типов Cassandra (`map`, `frozen`) + +**Компромиссы:** +Увеличение количества операций записи: каждая вставка строки = N вставок (по одной на каждое индексированное поле) +Дополнительные затраты памяти из-за дублирования данных строк +Информация о типах хранится в конфигурации схемы, преобразование происходит на уровне приложения + +#### Модель согласованности + +В проекте приняты определенные упрощения: + +1. **Отсутствие обновлений строк**: Система работает только на добавление данных. Это устраняет проблемы согласованности, связанные с обновлением нескольких копий одной и той же строки. + +2. **Толерантность к изменениям схемы**: При изменении схем (например, при добавлении/удалении индексов) существующие строки сохраняют свою первоначальную индексацию. Старые строки не будут доступны через новые индексы. Пользователи могут удалить и пересоздать схему для обеспечения согласованности, если это необходимо. + +### Отслеживание и удаление разделов + +#### Проблема + +При использовании ключа раздела `(collection, schema_name, index_name)`, для эффективного удаления необходимо знать все ключи разделов, которые нужно удалить. Удаление только по `collection` или `collection + schema_name` требует знания всех значений `index_name`, которые содержат данные. + +#### Таблица отслеживания разделов + +Вторичная таблица поиска отслеживает, какие разделы существуют: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +Это обеспечивает эффективное обнаружение разделов для операций удаления. + +#### Поведение модуля записи строк + +Модуль записи строк поддерживает кэш в памяти, содержащий зарегистрированные пары `(collection, schema_name)`. При обработке строки: + +1. Проверьте, есть ли `(collection, schema_name)` в кэше. +2. Если ⟦CODE_0⟧ не в кэше (первая строка для этой пары): + Найдите конфигурацию схемы, чтобы получить все имена индексов. + Вставьте записи в `row_partitions` для каждого `(collection, schema_name, index_name)`. + Добавьте пару в кэш. +3. Перейдите к записи данных строки. + +Модуль записи строк также отслеживает события изменения конфигурации схемы. При изменении схемы соответствующие записи кэша очищаются, чтобы следующая строка вызвала повторную регистрацию с обновленными именами индексов. + +Этот подход обеспечивает: +Записи в таблицу поиска происходят только один раз для каждой пары `(collection, schema_name)`, а не для каждой строки. +Таблица поиска отражает индексы, которые были активны во время записи данных. +Изменения схемы во время импорта обрабатываются правильно. + +#### Операции удаления + +**Удаление коллекции:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**Удалить коллекцию и схему:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### Встраивания строк + +Встраивания строк обеспечивают семантическое/приближенное сопоставление проиндексированных значений, решая проблему несовместимости естественного языка (например, поиск "CHESTNUT ST", когда выполняется запрос "Chestnut Street"). + +#### Обзор архитектуры + +Каждое проиндексированное значение преобразуется во встраивание и хранится в векторной базе данных (Qdrant). Во время запроса запрос также преобразуется во встраивание, находятся похожие векторы, и связанная метаинформация используется для поиска фактических строк в Cassandra. + +#### Структура коллекции Qdrant + +Одна коллекция Qdrant для каждой кортежи `(user, collection, schema_name, dimension)`: + +**Именование коллекции:** `rows_{user}_{collection}_{schema_name}_{dimension}` +Имена очищаются (небуквенно-цифровые символы заменяются на `_`, приводятся к нижнему регистру, числовые префиксы получают префикс `r_`) +**Обоснование:** Позволяет чисто удалить экземпляр `(user, collection, schema_name)` путем удаления соответствующих коллекций Qdrant; суффикс измерения позволяет различным моделям встраивания сосуществовать. + +#### Что подвергается встраиванию + +Текстовое представление значений индекса: + +| Тип индекса | Пример `index_value` | Текст для встраивания | +|------------|----------------------|---------------| +| Одиночное поле | `['foo@bar.com']` | `"foo@bar.com"` | +| Композитный | `['US', 'active']` | `"US active"` (объединенные пробелами) | + +#### Структура точки + +Каждая точка Qdrant содержит: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| Поле полезной нагрузки | Описание | +|---------------|-------------| +| `index_name` | Индексированные поля, которые представляет эта вставка. | +| `index_value` | Исходный список значений (для поиска в Cassandra). | +| `text` | Текст, который был вставлен (для отладки/отображения). | + +Обратите внимание: `user`, `collection` и `schema_name` определяются неявно из имени коллекции Qdrant. + +#### Поток запросов + +1. Пользователь запрашивает "Chestnut Street" для пользователя U, коллекции X, схемы Y. +2. Вставьте текст запроса. +3. Определите имя(и) коллекции Qdrant, соответствующие префиксу `rows_U_X_Y_`. +4. Выполните поиск в соответствующих коллекциях Qdrant для поиска ближайших векторов. +5. Получите соответствующие точки с полезными нагрузками, содержащими `index_name` и `index_value`. +6. Запрос к Cassandra: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. Возврат соответствующих строк. + +#### Необязательно: Фильтрация по имени индекса. + +Запросы могут опционально фильтровать данные по `index_name` в Qdrant, чтобы искать только определенные поля: + +**"Найти любое поле, соответствующее 'Chestnut'"** → поиск по всем векторам в коллекции. +**"Найти поле street_name, соответствующее 'Chestnut'"** → фильтрация по `payload.index_name = 'street_name'`. + +#### Архитектура. + +Векторные представления строк следуют **двухступенчатой схеме**, используемой в GraphRAG (graph-embeddings, document-embeddings): + +**Этап 1: Вычисление векторных представлений** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - Использует `ExtractedObject`, вычисляет векторные представления через сервис векторных представлений, выдает `RowEmbeddings`. +**Этап 2: Хранение векторных представлений** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - Использует `RowEmbeddings`, записывает векторы в Qdrant. + +Модуль записи строк в Cassandra является отдельным параллельным компонентом: + +**Модуль записи строк в Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - Использует `ExtractedObject`, записывает строки в Cassandra. + +Все три компонента используют один и тот же поток данных, что обеспечивает их независимость. Это позволяет: +Независимое масштабирование записи в Cassandra по сравнению с генерацией векторных представлений и хранением векторов. +Отключение сервисов генерации векторных представлений, если они не требуются. +Отказы в одном компоненте не влияют на другие. +Согласованная архитектура с конвейерами GraphRAG. + +#### Путь записи. + +**Этап 1 (процессор векторных представлений строк):** При получении `ExtractedObject`: + +1. Получение схемы для поиска индексированных полей. +2. Для каждого индексированного поля: + Создание текстового представления значения индекса. + Вычисление векторного представления через сервис векторных представлений. +3. Вывод сообщения `RowEmbeddings`, содержащего все вычисленные векторы. + +**Этап 2 (запись векторных представлений в Qdrant):** При получении `RowEmbeddings`: + +1. Для каждого векторного представления в сообщении: + Определение коллекции Qdrant из `(user, collection, schema_name, dimension)`. + Создание коллекции, если это необходимо (создание при первой записи). + Добавление точки с вектором и полезной нагрузкой. + +#### Типы сообщений. + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### Интеграция удаления + +Коллекции Qdrant обнаруживаются путем сопоставления префикса с шаблоном имени коллекции: + +**Удаление `(user, collection)`:** +1. Перечислить все коллекции Qdrant, соответствующие префиксу `rows_{user}_{collection}_` +2. Удалить каждую соответствующую коллекцию +3. Удалить разделы строк Cassandra (как описано выше) +4. Очистить записи `row_partitions` + +**Удаление `(user, collection, schema_name)`:** +1. Перечислить все коллекции Qdrant, соответствующие префиксу `rows_{user}_{collection}_{schema_name}_` +2. Удалить каждую соответствующую коллекцию (обрабатывает несколько измерений) +3. Удалить разделы строк Cassandra +4. Очистить `row_partitions` + +#### Расположение модулей + +| Этап | Модуль | Точка входа | +|-------|--------|-------------| +| Этап 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| Этап 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### API запросов для векторных представлений строк + +API запросов для векторных представлений строк является **отдельным API** от сервиса запросов строк GraphQL: + +| API | Назначение | Бэкенд | +|-----|---------|---------| +| Запрос строк (GraphQL) | Точное сопоставление с индексированными полями | Cassandra | +| Запрос векторных представлений строк | Нечеткое/семантическое сопоставление | Qdrant | + +Это разделение позволяет четко разделить функциональность: +Сервис GraphQL фокусируется на точных, структурированных запросах +API векторных представлений обрабатывает семантическую схожесть +Рабочий процесс пользователя: нечеткий поиск с помощью векторных представлений для поиска кандидатов, затем точный запрос для получения полных данных строки + +#### Схема запроса/ответа + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### Обработчик запросов + +Модуль: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +Точка входа: `row-embeddings-query-qdrant` + +Обработчик: +1. Получает `RowEmbeddingsRequest` с векторами запросов +2. Находит соответствующую коллекцию Qdrant путем сопоставления префикса +3. Ищет ближайшие векторы с необязательным фильтром `index_name` +4. Возвращает `RowEmbeddingsResponse` с информацией об индексе, соответствующем запросу + +#### Интеграция с API-шлюзом + +Шлюз предоставляет запросы на получение векторных представлений строк через стандартный шаблон запроса/ответа: + +| Компонент | Местоположение | +|-----------|----------| +| Диспетчер | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| Регистрация | Добавьте `"row-embeddings"` в `request_response_dispatchers` в `manager.py` | + +Имя интерфейса потока: `row-embeddings` + +Определение интерфейса в шаблоне потока: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### Поддержка Python SDK + +SDK предоставляет методы для запросов векторных представлений строк: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### Утилита командной строки + +Команда: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### Типичная схема использования + +Запрос векторных представлений строк обычно используется как часть процесса поиска приблизительного соответствия для точного поиска: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +Эта двухэтапная схема позволяет: +Находить "CHESTNUT ST", когда пользователь ищет "Chestnut Street" +Получать полные данные строки со всеми полями +Объединять семантическую схожесть с доступом к структурированным данным + +### Импорт данных строк + +Отложено до последующей фазы. Будет разработано вместе с другими изменениями импорта. + +## Влияние на реализацию + +### Анализ текущего состояния + +Существующая реализация имеет два основных компонента: + +| Компонент | Местоположение | Строк | Описание | +|-----------|----------|-------|-------------| +| Сервис запросов | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | Монолит: генерация схемы GraphQL, разбор фильтров, запросы Cassandra, обработка запросов | +| Записывающий модуль | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | Создание таблиц для каждой схемы, вторичные индексы, вставка/удаление | + +**Текущая схема запросов:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**Новая схема запроса:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### Ключевые изменения + +1. **Упрощение семантики запросов**: Новая схема поддерживает только точное соответствие для `index_value`. Текущие фильтры GraphQL (`gt`, `lt`, `contains` и т.д.) либо: + Становятся постобработкой возвращаемых данных (если это все еще необходимо) + Удаляются в пользу использования API для работы с эмбеддингами для нечеткого сопоставления. + +2. **Код GraphQL тесно связан**: Текущие сборки `service.py` включают генерацию типов Strawberry, разбор фильтров и запросы, специфичные для Cassandra. Добавление еще одного бэкенда для хранения данных потребует дублирования примерно 400 строк кода GraphQL. + +### Предлагаемая реструктуризация + +Реструктуризация состоит из двух частей: + +#### 1. Выделение кода GraphQL + +Извлеките многократно используемые компоненты GraphQL в общий модуль: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +Это позволяет: +Повторное использование в различных системах хранения данных. +Более четкое разделение ответственности. +Более простое тестирование логики GraphQL независимо. + +#### 2. Реализация новой схемы таблицы + +Переработайте код, специфичный для Cassandra, для использования унифицированной таблицы: + +**Записывающий модуль** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +Одна `rows` таблица вместо таблиц для каждой схемы. +Запись N копий на строку (по одной для каждого индекса). +Регистрация в `row_partitions` таблице. +Более простое создание таблицы (единоразовая настройка). + +**Сервис запросов** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +Запрос унифицированной `rows` таблицы. +Использование извлеченного модуля GraphQL для генерации схемы. +Упрощенная обработка фильтров (только точное соответствие на уровне базы данных). + +### Переименование модулей + +В рамках очистки наименований "object" → "row": + +| Текущее | Новое | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### Новые модули + +| Модуль | Назначение | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | Общие утилиты GraphQL | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | API запросов для векторных представлений строк | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | Вычисление векторных представлений строк (Этап 1) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | Хранение векторных представлений строк (Этап 2) | + +## Ссылки + +[Техническая спецификация структурированных данных](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.sw.md b/docs/tech-specs/structured-data-2.sw.md new file mode 100644 index 00000000..347b84c9 --- /dev/null +++ b/docs/tech-specs/structured-data-2.sw.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "Vipimo vya Kawaida vya Takwimu Zilizopangwa (Sehemu ya 2)" +parent: "Swahili (Beta)" +--- + +# Vipimo vya Kawaida vya Takwimu Zilizopangwa (Sehemu ya 2) + +> **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 + +Maelezo haya yanaeleza masuala na pengo ambazo zimetambuliwa wakati wa utekelezaji wa awali wa ujumuishaji wa takwimu zilizopangwa wa TrustGraph, kama ilivyoelezwa katika `structured-data.md`. + +## Matatizo + +### 1. Utangamano Usio sawa wa Majina: "Kitu" dhidi ya "Rata" + +Utaratibu wa sasa hutumia neno "kitembele" katika kila sehemu (k.m., `ExtractedObject`, utoaji wa kitu, uwekaji wa kitu). Neno hili ni la jumla sana na husababisha mchanganyiko: + +"Kitembele" ni neno linalotumika kwa matumizi mengi katika programu (vitu vya Python, vitu vya JSON, n.k.) +Data inayoshughulikiwa ni ya aina ya meza - ratiba katika meza zilizo na muundo uliotofautishwa +"Rata" inaelezea vizuri zaidi mfumo wa data na inaendana na neno la hifadhi ya data + +Utangamano huu huonekana katika majina ya moduli, majina ya madarasa, aina za ujumbe, na nyaraka. + +### 2. Mipaka ya Ufuatiliaji wa Rata + +Utaratibu wa sasa wa hifadhi ya rata una mipaka muhimu ya ufuatiliaji: + +**Utangamano wa Lugha Asilia:** Ufuatiliaji unashindana na tofauti za ulimwengu halisi. Kwa mfano: +Ni vigumu kupata hifadhi ya barabara inayokuwa na `"CHESTNUT ST"` wakati unatafuta `"Chestnut Street"` +Marekebisho, tofauti za herufi, na tofauti za umbizo hufutilia ufuatiliaji wa usawizi +Watumiaji wanatarajia uelewa wa maana, lakini hifadhi hutoa mechi ya moja kwa moja + +**Masuala ya Mabadiliko ya Muundo:** Mabadiliko ya muundo husababisha matatizo: +Data iliyopo inaweza kutosana na muundo uliosasishwa +Mabadiliko ya muundo wa meza yanaweza kuvunja ufuatiliaji na uadilifu wa data +Hakuna njia wazi ya kusonga muundo kwa mabadiliko ya muundo + +### 3. Uwekaji wa Rata Unahitajika + +Kuhusiana na tatizo la 2, mfumo unahitaji uwekaji wa vector kwa data ya rata ili kuwezesha: + +Ufuatiliaji wa maana katika data iliyopangwa (kupata "Chestnut Street" wakati data ina "CHESTNUT ST") +Mechi ya ufanano kwa ufuatiliaji wa uwazi +Ufuatiliaji wa mchanganyiko unaounganisha vichujio vilivyopangwa na ufanano wa maana +Usaidizi bora wa lugha asilia ya ufuatiliaji + +Huduma ya uwekaji ilikuwa imeelezwa lakini haijatekelezwa. + +### 4. Uongezaji wa Data ya Rata hajakamilika + +Mnyororo wa data ya takwimu zilizopangwa haujafanya kazi kikamilifu: + +Mawazo ya uchunguzi yanapatikana ili kuainisha muundo wa pembejeo (CSV, JSON, n.k.) +Huduma ya uongezaji ambayo hutumia mawazo haya haijunganishwa kwenye mfumo +Hakuna njia kamili ya kupakia data iliyopangwa tayari kwenye hifadhi ya rata + +## Lengo + +**Unyumbufu wa Muundo:** Kuwezesha mabadiliko ya muundo bila kuvunja data iliyopo au kuhitaji uhamisho +**Utangamano wa Majina:** Kuweka "rata" kama neno la kawaida katika kila sehemu ya programu +**Ufuatiliaji wa Maana:** Kusaidia mechi ya maana/uwazi kupitia uwekaji wa rata +**Mnyororo Kamili wa Uongezaji:** Kutoa njia kamili ya kupakia data iliyopangwa + +## Muundo wa Kiufundi + +### Muundo Uliounganishwa wa Hifadhi ya Rata + +Utaratibu wa awali uliunda meza tofauti ya Cassandra kwa kila muundo. Hii ilisababisha matatizo wakati muundo ulibadilika, kwa sababu mabadiliko ya muundo wa meza yalihitaji uhamisho. + +Muundo mpya hutumia meza moja iliyounganishwa kwa data yote ya rata: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### Ufafanuzi wa Safu + +| Safu | Aina | Maelezo | +|--------|------|-------------| +| `collection` | `text` | Kitambulisho cha ukusanyaji/kuingiza data (kutoka kwa metadata) | +| `schema_name` | `text` | Jina la mpango ambao safu hii inafuata | +| `index_name` | `text` | Majina ya sehemu zilizopangiliwa, yameunganishwa kwa mkato kwa sehemu mbalimbali | +| `index_value` | `frozen>` | Maadili ya kifunguo kama orodha | +| `data` | `map` | Data ya safu kama jozi za ufunguo-thamani | +| `source` | `text` | URI ya hiari inayounganisha na maelezo ya asili katika mfumo wa maarifa. Mnyororo tupu au NULL inaonyesha kuwa hakuna chanzo. | + +#### Usimamizi wa Faharasa + +Kila safu huhifadhiwa mara nyingi - mara moja kwa kila sehemu iliyopangiliwa iliyobainishwa katika mpango. Sehemu kuu za ufunguo zinatibiwa kama faharasa bila alama maalum, ambayo hutoa uwezekano wa kubadilika katika siku zijazo. + +**Mfano wa faharasa ya sehemu moja:** +Mpango unafafanua `email` kuwa iliyopangiliwa +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**Mfano wa faharasa mchanganyiko:** +Mpango unafafanua faharasa mchanganyiko kwenye `region` na `status` +`index_name = "region,status"` (majina ya sehemu yamepangwa na yameunganishwa kwa mkato) +`index_value = ['US', 'active']` (maadili katika utaratibu sawa na majina ya sehemu) + +**Mfano wa ufunguo mkuu:** +Mpango unafafanua `customer_id` kuwa ufunguo mkuu +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### Mfano wa Maswali + +Maswali yote yanafuata muundo sawa bila kujali faharasa gani inayotumika: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### Mizunguko ya Ubunifu + +**Faida:** +Mabadiliko ya schema hayahitaji mabadiliko ya muundo wa jedwali +Data ya mstari ni ya siri kwa Cassandra - ongezeko/ondoano la nafasi ni wazi +Mfumo thabiti wa swali kwa njia zote za upatikanaji +Hakuna fahirisi za sekondari za Cassandra (ambazo zinaweza kuwa polepole kwa kiwango kikubwa) +Aina za asili za Cassandra katika kila sehemu (`map`, `frozen`) + +**Utofauti:** +Kuongezeka kwa uandishi: kila kuingizwa kwa mstari = ongezeko la N (moja kwa kila nafasi iliyofichwa) +Gharama ya kuhifadhi kutokana na data ya mstari iliyorudiwa +Habari ya aina huhifadhiwa katika usanidi wa schema, ubadilishaji katika safu ya programu + +#### Mfumo wa Ulinganisho + +Ubunifu huu unapokea uboreshaji fulani: + +1. **Hakuna sasisho za mstari**: Mfumo huu ni wa kuongeza tu. Hii inazuia wasiwasi wa ulinganisho kuhusu kusasisha nakala nyingi za mstari mmoja. + +2. **Uvumilivu wa mabadiliko ya schema**: Wakati schemas hubadilika (k.m., fahirisi zinaongezwa/kuondolewa), mistari iliyopo inaendelea kuwa na uwekaji wa fahirisi wake wa awali. Mistari ya zamani haitaweza kupatikana kupitia fahirisi mpya. Watumiaji wanaweza kufuta na kuunda tena schema ili kuhakikisha ulinganisho ikiwa ni lazima. + +### Ufuatiliaji na Ufutilishaji wa Sehemu + +#### Tatizo + +Kwa ufunguo wa sehemu `(collection, schema_name, index_name)`, ufutaji bora unahitaji kujua ufunguo wote wa sehemu ili kufutwa. Ufutilishaji kwa `collection` au `collection + schema_name` pekee unahitaji kujua maadili yote ya `index_name` ambayo yana data. + +#### Jedwali la Ufuatiliaji wa Sehemu + +Jedwali la ziada la utafutaji linafuatilia sehemu zipi zilizo. + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +Hii inaruhusu ugunduzi bora wa sehemu za kufutwa. + +#### Tabia ya Kifaa cha Kuandika Mistari + +Kifaa cha kuandika mistari kinahifadhi kumbukumbu ya jozi zilizosajiliwa za `(collection, schema_name)`. Wakati wa kuchakata mstari: + +1. Angalia ikiwa `(collection, schema_name)` iko kwenye kumbukumbu +2. Ikiwa haijahifadhiwa (mstari wa kwanza kwa jozi hii): + Tafuta usanidi wa schema ili kupata majina yote ya index + Ingiza vipengele katika `row_partitions` kwa kila `(collection, schema_name, index_name)` + Ongeza jozi kwenye kumbukumbu +3. Endelea na kuandika data ya mstari + +Kifaa cha kuandika mistari pia kinachunguza mabadiliko ya usanidi wa schema. Wakati schema inabadilika, vipengele muhimu vya kumbukumbu vinafutwa ili mstari unaofuata usisababishwe tena usajili na majina mapya ya index. + +Mbinu hii inahakikisha: +Uandikaji wa jedwali la utafutaji hutokea mara moja kwa kila jozi ya `(collection, schema_name)`, sio kwa kila mstari +Jedwali la utafutaji linaonyesha indexes ambazo zilikuwa zinafanya kazi wakati data ilipoandikwa +Mabadiliko ya schema wakati wa uingizaji yanaonekana kwa usahihi + +#### Operesheni za Ufute + +**Futa mkusanyiko:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**Futa mkusanyiko na schema:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### Uelekezaji wa Data + +Uelekezaji wa data unawezesha utambuzi wa maana/ufanano kwenye maadili yaliyohifadhiwa, na kutatua tatizo la kutofautiana kwa lugha (k.m., kutafuta "CHESTNUT ST" wakati unatafuta "Chestnut Street"). + +#### Muhtasari wa Ubunifu + +Kila jambo lililohifadhiwa limeelekezwa na kuhifadhiwa katika hifadhi ya vekta (Qdrant). Wakati wa utafutaji, swali linaelekezwa, vekta sawa zinafanywa, na metadata inayohusiana hutumiwa kutafuta mistari halisi katika Cassandra. + +#### Muundo wa Mkusanyiko wa Qdrant + +Mkusanyiko mmoja wa Qdrant kwa kila jozi ya `(user, collection, schema_name, dimension)`: + +**Jina la mkusanyiko:** `rows_{user}_{collection}_{schema_name}_{dimension}` +Majina husafishwa (herufi ambazo sio alfabeti hubadilishwa na `_`, yamebadilishwa kuwa herufi ndogo, prefixes za namba hupata prefix ya `r_`) +**Sababu:** Inaruhusu kufutwa kwa jozi ya `(user, collection, schema_name)` kwa kufuta makusanyiko yanayolingana ya Qdrant; kiambishi cha kipimo huruhusu modeli tofauti za uelekezaji kuwepo. + +#### Kile Kinachoelekezwa + +Uwazi wa maandishi wa maadili ya index: + +| Aina ya Index | Mfano wa `index_value` | Maandishi ya Kuelekeza | +|------------|----------------------|---------------| +| Uwanja mmoja | `['foo@bar.com']` | `"foo@bar.com"` | +| Mchanganyiko | `['US', 'active']` | `"US active"` (imeunganishwa na nafasi) | + +#### Muundo wa Pointi + +Kila pointi ya Qdrant ina: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| Uwanja wa Data | Maelezo | +|---------------|-------------| +| `index_name` | Uwanja(s) ulio(o) ambao embedding hii inawakilisha | +| `index_value` | Orodha ya awali ya maadili (kwa utafutaji wa Cassandra) | +| `text` | Nakala iliyoingizwa (kwa ajili ya utatuzi/kuonyesha) | + +Kumbuka: `user`, `collection`, na `schema_name` zinaonyeshwa moja kwa moja kutoka kwa jina la mkusanyiko wa Qdrant. + +#### Mtiririko wa Utafiti + +1. Mtumiaji anatafuta "Chestnut Street" ndani ya mtumiaji U, mkusanyiko X, schema Y +2. Ingiza nakala ya utafutaji +3. Tambua jina(s) la mkusanyiko wa Qdrant linalolingana na kielelezo `rows_U_X_Y_` +4. Tafuta mkusanyiko(s) unaolingana wa Qdrant kwa vectori za karibu +5. Pata pointi zinazolingana zilizo na data zinazozingatia `index_name` na `index_value` +6. Tafuta Cassandra: + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. Kurudisha mistari iliyolingana. + +#### Hiari: Kuchuja kwa Jina la Index + +Maswali yanaweza hiari kuchuja kwa `index_name` katika Qdrant ili kutafuta tu sehemu maalum: + +**"Tafuta sehemu yoyote inayolingana na 'Chestnut'"** → tafuta vectori zote katika mkusanyiko. +**"Tafuta 'street_name' inayolingana na 'Chestnut'"** → chuja ambapo `payload.index_name = 'street_name'`. + +#### Muundo + +Uwekaji wa mistari unafuata **muundo wa hatua mbili** unaotumika na GraphRAG (uwekaji wa grafu, uwekaji wa hati): + +**Hatua ya 1: Hesabu ya uwekaji** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - Hutumia `ExtractedObject`, huhesabu uwekaji kupitia huduma ya uwekaji, hutoka `RowEmbeddings`. +**Hatua ya 2: Uhifadhi wa uwekaji** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - Hutumia `RowEmbeddings`, huandika vectori kwenye Qdrant. + +Mwandishi wa mistari wa Cassandra ni mtumiaji wa ziada unaoendeshwa kwa njia fiche: + +**Mwandishi wa mistari wa Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - Hutumia `ExtractedObject`, huandika mistari kwenye Cassandra. + +Huduma zote tatu hutumia kutoka kwa mtiririko mmoja, na hivyo kuzifanya kuwa huru. Hii inaruhusu: +Uongezaji wa kasi wa kujitegemea wa uandishi wa Cassandra dhidi ya utengenezaji wa uwekaji dhidi ya uhifadhi wa vectori. +Huduma za uwekaji zinaweza kuzimwa ikiwa hazihitajiki. +Hitilafu katika huduma moja hazisababishi athari kwa huduma zingine. +Muundo thabiti na mabomba ya GraphRAG. + +#### Njia ya Kuandika + +**Hatua ya 1 (mchakato wa uwekaji wa mistari):** Unapopokea `ExtractedObject`: + +1. Tafuta schema ili kupata sehemu zilizoidishwa. +2. Kwa kila sehemu iliyoidishwa: + Jenga uwakilishi wa maandishi wa thamani ya index. + Hesabu uwekaji kupitia huduma ya uwekaji. +3. Toa ujumbe wa `RowEmbeddings` unao na vectori zote zilizohitajiwa. + +**Hatua ya 2 (uandishi wa uwekaji wa mistari-qdrant):** Unapopokea `RowEmbeddings`: + +1. Kwa kila uwekaji katika ujumbe: + Tambua mkusanyiko wa Qdrant kutoka `(user, collection, schema_name, dimension)`. + Unda mkusanyiko ikiwa unahitajika (utengenezaji wa polepole katika uandishi wa kwanza). + Ongeza pointi na vector na mzigo. + +#### Aina za Ujumbe + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### Jumuisho la Ufuteaji + +Makusanyo ya Qdrant hugunduliwa kwa kutumia utangamano wa jina la makusanyo: + +**Futa `(user, collection)`:** +1. Orodha makusanyo yote ya Qdrant yanayolingana na utangamano `rows_{user}_{collection}_` +2. Futa kila makusanyo yanayolingana +3. Futa sehemu za mistari ya Cassandra (kama ilivyoelezwa hapo juu) +4. Safisha maingizo ya `row_partitions` + +**Futa `(user, collection, schema_name)`:** +1. Orodha makusanyo yote ya Qdrant yanayolingana na utangamano `rows_{user}_{collection}_{schema_name}_` +2. Futa kila makusanyo yanayolingana (inashughulikia vipimo vingi) +3. Futa sehemu za mistari ya Cassandra +4. Safisha `row_partitions` + +#### Maeneo ya Moduli + +| Hatua | Moduli | Kituo cha Kuanzia | +|-------|--------|-------------| +| Hatua 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| Hatua 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### API ya Uchunguzi wa Uelekezo + +Uchunguzi wa uelekezo ni **API tofauti** kutoka kwa huduma ya uchunguzi wa mstari wa GraphQL: + +| API | Madhumuni | Nyuma | +|-----|---------|---------| +| Uchunguzi wa Mstari (GraphQL) | Utangamano kamili kwenye sehemu zilizofichwa | Cassandra | +| Uchunguzi wa Uelekezo | Utangamano wa dhana/maneno | Qdrant | + +Tofauti hii huweka masuala tofauti: +Huduma ya GraphQL inazingatia maswali kamili na yaliyo na muundo +API ya uelekezo inashughulikia ufanano wa dhana +Mchakato wa mtumiaji: utafutaji wa dhana kupitia uelekezo ili kupata wagombea, kisha uchunguzi kamili ili kupata data kamili ya mstari + +#### Mfumo wa Ombi/Jibu + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### Mchakato wa Uchunguzi + +Moduli: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +Kuanzia: `row-embeddings-query-qdrant` + +Mchakato: +1. Hupokea `RowEmbeddingsRequest` pamoja na vektor za swali +2. Hutafuta mkusanyiko unaofaa wa Qdrant kwa kutumia utangamano wa nenosiri +3. Hutafuta vektor za karibu pamoja na kipengele cha `index_name` cha hiari +4. Hurudisha `RowEmbeddingsResponse` pamoja na maelezo ya fahirisi yanayolingana + +#### Uunganisho wa Milango ya API + +Lango huonyesha maswali ya uelekezo wa mstari kupitia muundo wa kawaida wa ombi/jibu: + +| Sehemu | Mahali | +|-----------|----------| +| Msambazaji | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| Usajili | Ongeza `"row-embeddings"` kwenye `request_response_dispatchers` katika `manager.py` | + +Jina la kiungo cha mtiririko: `row-embeddings` + +Ufafanuzi wa kiungo katika mpango wa mtiririko: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### Usaidizi wa SDK ya Python + +SDK hutoa njia za kuuliza kuhusu uwekaji wa data katika mistari: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### Utumizi wa Kamba ya Amri + +Amri: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### Mfano wa Matumizi ya Kawaida + +Uchunguzi wa pembejeo za mstari kwa kawaida hutumika kama sehemu ya mtiririko wa utafutaji wa "vunjifu" hadi "sahihi": + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +Mfumo huu wa hatua mbili huruhusu: +Kugundua "CHESTNUT ST" wakati mtumiaji anatafuta "Chestnut Street" +Kuchukua data kamili ya mstari pamoja na sehemu zote +Kuchanganya utambulisho wa maana na ufikiaji wa data iliyopangwa + +### Uingizaji wa Data ya Mstari + +Itarefushwa hadi hatua ya baadaye. Itaundwa pamoja na mabadiliko mengine ya uingizaji. + +## Athari ya Utendaji + +### Uchambuzi wa Hali ya Sasa + +Utendaji uliopo una vipengele viwili mikuu: + +| Kipengele | Mahali | Mistari | Maelezo | +|-----------|----------|-------|-------------| +| Huduma ya Utafutaji | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | Moja kwa moja: Uundaji wa schema ya GraphQL, uchanganuzi wa vichujio, maswali ya Cassandra, usimamizi wa ombi | +| Mwandishi | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | Uundaji wa jedwali kwa kila schema, fahirisi za sekondari, kuingiza/kufuta | + +**Mfumo wa Sasa wa Utafutaji:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**Muundo Mpya wa Ulizaji:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### Mabadiliko Muhimu + +1. **Uboreshaji wa maana ya maswali**: Mfumo mpya unaunga mkono tu mechi kamili kwenye `index_value`. Vifiltrishi vya GraphQL ya sasa (`gt`, `lt`, `contains`, n.k.) ama: + Yanakuwa uchujaji wa ziada kwenye data iliyorudishwa (ikiwa bado inahitajika) + Yanondolewa ili kutumia API ya embeddings kwa mechi zisizo sahihi + +2. **Msimbo wa GraphQL umeunganishwa sana**: Mfumo wa sasa wa `service.py` unajumuisha utengenezaji wa aina za Strawberry, uchanganuzi wa vifiltrishi, na maswali maalum ya Cassandra. Kuongeza mfumo mwingine wa kuhifadhi data ingeongeza mistari ~400 ya msimbo wa GraphQL. + +### Pendekezo la Urekebishaji + +Urekebishaji una sehemu mbili: + +#### 1. Tenganisha Msimbo wa GraphQL + +Toa vipengele vya GraphQL ambavyo vinaweza kutumika tena katika moduli iliyoshirikiwa: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +Hii inawezesha: +Matumizi upya katika mifumo tofauti ya kuhifadhi data. +Tofauti wazi zaidi ya majukumu. +Uchunguzi rahisi zaidi wa mantiki ya GraphQL kwa kujitegemea. + +#### 2. Tengeneza Mpango Mpya wa Jedwali + +Badilisha msimbo maalum wa Cassandra ili kutumia jedwali lililo na mpango mmoja: + +**Mwandishi** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +Jedwali moja la `rows` badala ya jedwali kila mpango. +Andika nakala N kwa kila mstari (moja kwa kila fahirisi). +Jisajili kwenye jedwali la `row_partitions`. +Uundaji rahisi zaidi wa jedwali (usanidi wa mara moja). + +**Huduma ya Utafiti** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +Tafuta kwenye jedwali lililo na mpango mmoja la `rows`. +Tumia moduli iliyochimbwa ya GraphQL kwa uundaji wa mpango. +Usimamizi ulioboreshwa wa vichujio (mechi kamili tu kwenye kiwango cha hifadhidata). + +### Mabadiliko ya Majina ya Moduli + +Kama sehemu ya usafi wa majina kutoka "object" hadi "row": + +| Sasa | Mpya | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### Moduli Mpya + +| Moduli | Lengo | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | Utumizi wa pamoja wa GraphQL. | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | API ya utafiti wa uingishaji wa mstari. | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | Hesabu ya uingishaji wa mstari (Hatua ya 1). | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | Uhifadhi wa uingishaji wa mstari (Hatua ya 2). | + +## Marejeleo + +[Maelezo ya Kiufundi ya Data Iliyopangwa](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.tr.md b/docs/tech-specs/structured-data-2.tr.md new file mode 100644 index 00000000..eb71f8a2 --- /dev/null +++ b/docs/tech-specs/structured-data-2.tr.md @@ -0,0 +1,621 @@ +--- +layout: default +title: "Yapılandırılmış Veri Teknik Özellikleri (Bölüm 2)" +parent: "Turkish (Beta)" +--- + +# Yapılandırılmış Veri Teknik Özellikleri (Bölüm 2) + +> **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'ın yapılandırılmış veri entegrasyonunun ilk uygulamasının ilk aşamalarında tespit edilen sorunları ve eksiklikleri ele almaktadır, bu da `structured-data.md`'da açıklanmıştır. + +## Sorun Tanımları + +### 1. İsimlendirme Tutarsızlığı: "Nesne" vs "Satır" + +Mevcut uygulama, "nesne" terimini tüm alanlarda kullanmaktadır (örneğin, `ExtractedObject`, nesne çıkarma, nesne gömme). Bu isimlendirme çok genel olup kafa karışıklığına neden olmaktadır: + +"Nesne" terimi, yazılımda (Python nesneleri, JSON nesneleri vb.) aşırı kullanılan bir terimdir. +İşlenen veri temelde tablolardır; tanımlı şemalara sahip satırlar. +"Satır", veri modelini daha doğru bir şekilde tanımlar ve veritabanı terminolojisiyle uyumludur. + +Bu tutarsızlık, modül adlarında, sınıf adlarında, mesaj türlerinde ve belgelerde görülmektedir. + +### 2. Satır Depolama Sorgu Sınırlamaları + +Mevcut satır depolama uygulamasının önemli sorgu sınırlamaları bulunmaktadır: + +**Doğal Dil Uyumsuzluğu**: Sorgular, gerçek dünya verilerindeki değişikliklerle başa çıkmakta zorlanmaktadır. Örneğin: +`"CHESTNUT ST"` içeren bir sokak veritabanını sorgulamak, `"Chestnut Street"` hakkında bilgi almak için zordur. +Kısaltmalar, büyük/küçük harf farklılıkları ve biçimlendirme değişiklikleri, tam eşleşme sorgularını bozmaktadır. +Kullanıcılar semantik bir anlayış beklemekte, ancak depolama literal eşleşme sağlamaktadır. + +**Şema Evrimi Sorunları**: Şemaların değiştirilmesi sorunlara neden olmaktadır: +Mevcut veriler, güncellenmiş şemalara uygun olmayabilir. +Tablo yapısındaki değişiklikler, sorguları ve veri bütünlüğünü bozabilir. +Şema güncellemeleri için net bir geçiş yolu bulunmamaktadır. + +### 3. Satır Gömme Gerekliliği + +2. soruna bağlı olarak, sistemin satır verileri için vektör gömmelere ihtiyacı vardır, bu da şunları sağlamak için gereklidir: + +Yapılandırılmış veriler arasında semantik arama (örneğin, "Chestnut Street" verisinin "CHESTNUT ST" olarak bulunduğu durumlarda) +Bulanık sorgular için benzerlik eşleştirme +Yapılandırılmış filtreleri semantik benzerlikle birleştiren hibrit arama +Daha iyi doğal dil sorgu desteği + +Gömme hizmeti belirtilmiş, ancak uygulanmamıştır. + +### 4. Satır Veri Alımı Eksikliği + +Yapılandırılmış veri alım hattı henüz tam olarak çalışır durumda değildir: + +Giriş formatlarını (CSV, JSON vb.) sınıflandırmak için tanısal istemler bulunmaktadır. +Bu istemleri kullanan alım hizmeti, sisteme entegre edilmemiştir. +Önceden yapılandırılmış verileri satır deposuna yüklemek için uçtan uca bir yol bulunmamaktadır. + +## Hedefler + +**Şema Esnekliği**: Mevcut verileri bozmadan veya geçişler gerektirmeden şema evrimini etkinleştirin. +**Tutarlı İsimlendirme**: Kod tabanında "satır" terimini standartlaştırın. +**Semantik Sorgulanabilirlik**: Satır gömmeleri aracılığıyla bulanık/semantik eşleştirmeyi destekleyin. +**Tam Alım Hattı**: Yapılandırılmış verileri yüklemek için uçtan uca bir yol sağlayın. + +## Teknik Tasarım + +### Birleşik Satır Depolama Şeması + +Önceki uygulamada, her şema için ayrı bir Cassandra tablosu oluşturulmuştur. Bu, şema evrimleri sırasında tablo yapısındaki değişikliklerin geçişler gerektirmesine neden olmuştur. + +Yeni tasarım, tüm satır verileri için tek birleşik bir tablo kullanmaktadır: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### Sütun Tanımları + +| Sütun | Tür | Açıklama | +|--------|------|-------------| +| `collection` | `text` | Veri toplama/içe aktarma tanımlayıcısı (metaveriden) | +| `schema_name` | `text` | Bu satırın uyduğu şema adı | +| `index_name` | `text` | Birleştirilmiş virgülle indekslenen alan(lar) adı | +| `index_value` | `frozen>` | Liste olarak indeks değerleri | +| `data` | `map` | Satır verisi, anahtar-değer çiftleri olarak | +| `source` | `text` | Bilgi grafiğindeki kaynak bilgisine bağlanan isteğe bağlı URI. Boş bir dize veya NULL, kaynak olmadığını gösterir. | + +#### İndeks Yönetimi + +Her satır, şemada tanımlanan her indeks için bir kez olmak üzere birden çok kez saklanır. Birincil anahtar alanları, özel bir işaretçi olmadan bir indeks olarak kabul edilir ve bu, gelecekteki esnekliği sağlar. + +**Tek alanlı indeks örneği:** +Şema, `email`'ı indeks olarak tanımlar +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**Bileşik indeks örneği:** +Şema, `region` ve `status` üzerinde bileşik bir indeks tanımlar +`index_name = "region,status"` (alan adları sıralanır ve virgülle birleştirilir) +`index_value = ['US', 'active']` (değerler, alan adları sırasıyla aynı sırada) + +**Birincil anahtar örneği:** +Şema, `customer_id`'ı birincil anahtar olarak tanımlar +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### Sorgu Desenleri + +Tüm sorgular, kullanılan indeksten bağımsız olarak aynı deseni izler: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### Tasarım Uzlaşmaları + +**Avantajları:** +Şema değişiklikleri, tablo yapısı değişiklikleri gerektirmez. +Satır verileri Cassandra için şeffaftır; alan ekleme/çıkarma işlemleri şeffaftır. +Tüm erişim yöntemleri için tutarlı sorgu kalıbı. +Cassandra'nın ikincil indeksleri (ki bunlar ölçekte yavaş olabilir). +Tüm yerel Cassandra türleri (`map`, `frozen`). + +**Uzlaşmalar:** +Yazma çoğaltması: her satır eklemesi = N eklemesi (dizinlenmiş alan başına bir tane). +Tekrarlanan satır verilerinden kaynaklanan depolama ek yükü. +Tür bilgisi şema yapılandırmasında saklanır, dönüşüm uygulama katmanında yapılır. + +#### Tutarlılık Modeli + +Bu tasarım, belirli basitleştirmeleri kabul eder: + +1. **Satır güncellemeleri yok:** Sistem yalnızca eklemelerle çalışır. Bu, aynı satırın birden çok kopyasının güncellenmesiyle ilgili tutarlılık sorunlarını ortadan kaldırır. + +2. **Şema değişikliği toleransı:** Şemalar değiştiğinde (örneğin, indeksler eklendi/çıkarıldı), mevcut satırlar orijinal dizinlemelerini korur. Eski satırlar, gerektiğinde kullanıcılar tutarlılığı sağlamak için bir şemayı silebilir ve yeniden oluşturabilir, ancak yeni indeksler aracılığıyla bulunamaz. + +### Bölüm Takibi ve Silme + +#### Sorun + +Bölüm anahtarı `(collection, schema_name, index_name)` ile, verimli silme, silinecek tüm bölüm anahtarlarını bilmeyi gerektirir. Yalnızca `collection` veya `collection + schema_name` ile silmek, veriye sahip olan tüm `index_name` değerlerini bilmeyi gerektirir. + +#### Bölüm Takip Tablosu + +Birincil olmayan bir arama tablosu, hangi bölümlerin mevcut olduğunu izler: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +Bu, silme işlemleri için bölümlerin verimli bir şekilde bulunmasını sağlar. + +#### Satır Yazıcı Davranışı + +Satır yazıcı, kaydedilen `(collection, schema_name)` çiftlerinin bellek içi bir önbelleğini tutar. Bir satırı işlerken: + +1. `(collection, schema_name)`'ın önbellekte olup olmadığını kontrol edin. +2. Önbellekte yoksa (bu çift için ilk satır): + Tüm indeks adlarını almak için şema yapılandırmasını arayın. + Her `(collection, schema_name, index_name)` için `row_partitions`'a girişler ekleyin. + Çifti önbelleğe ekleyin. +3. Satır verilerini yazmaya devam edin. + +Satır yazıcı ayrıca şema yapılandırma değişiklik olaylarını da izler. Bir şema değiştiğinde, ilgili önbellek girişleri temizlenir, böylece sonraki satır, güncellenmiş indeks adlarıyla yeniden kayda alınmasını sağlar. + +Bu yaklaşım şunları sağlar: +Arama tablosu yazmaları, satır başına değil, her `(collection, schema_name)` çifti için bir kez gerçekleşir. +Arama tablosu, verilerin yazıldığı sırada aktif olan indeksleri yansıtır. +İçe aktarma sırasında yapılan şema değişiklikleri doğru şekilde algılanır. + +#### Silme İşlemleri + +**Koleksiyonu sil:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**Koleksiyonu ve şemayı sil:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### Satır Gömme İşlemleri + +Satır gömme işlemleri, indeksli değerlerde semantik/bulanık eşleşme sağlayarak, doğal dil uyumsuzluğu sorununu çözer (örneğin, "Chestnut Street" için arama yaparken "CHESTNUT ST" bulmak). + +#### Tasarım Genel Bakışı + +Her indeksli değer gömülür ve bir vektör deposunda (Qdrant) saklanır. Sorgu zamanında, sorgu gömülür, benzer vektörler bulunur ve ilişkili meta veriler, Cassandra'daki gerçek satırları bulmak için kullanılır. + +#### Qdrant Koleksiyonu Yapısı + +Her `(user, collection, schema_name, dimension)` tuple'ı için bir Qdrant koleksiyonu: + +**Koleksiyon adı:** `rows_{user}_{collection}_{schema_name}_{dimension}` +İsimler temizlenir (alfanumerik olmayan karakterler `_` ile değiştirilir, küçük harfe dönüştürülür, sayısal önekler `r_` öneki alır) +**Gerekçe:** Bir `(user, collection, schema_name)` örneğini, eşleşen Qdrant koleksiyonlarını silerek temiz bir şekilde silmeyi sağlar; boyut soneki, farklı gömme modellerinin birlikte var olmasına olanak tanır. + +#### Nelerin Gömüldüğü + +İndeks değerlerinin metin gösterimi: + +| İndeks Tipi | Örnek `index_value` | Gömülecek Metin | +|------------|----------------------|---------------| +| Tek Alan | `['foo@bar.com']` | `"foo@bar.com"` | +| Birleşik | `['US', 'active']` | `"US active"` (boşluklarla birleştirilmiş) | + +#### Nokta Yapısı + +Her Qdrant noktası şunları içerir: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| Yük Verisi Alanı | Açıklama | +|---------------|-------------| +| `index_name` | Bu gömme işleminin temsil ettiği indeksli alan(lar). | +| `index_value` | Cassandra araması için orijinal değer listesi. | +| `text` | Gömülen metin (hata ayıklama/görüntüleme için). | + +Not: `user`, `collection` ve `schema_name`, Qdrant koleksiyon adı aracılığıyla örtülüdür. | + +#### Sorgu Akışı | + +1. Kullanıcı, kullanıcı U, koleksiyon X ve şema Y içinde "Chestnut Street" için sorgu yapar. | +2. Sorgu metnini gömün. | +3. Önekle eşleşen Qdrant koleksiyon adı(larını) belirleyin: `rows_U_X_Y_`. | +4. En yakın vektörler için eşleşen Qdrant koleksiyonları içinde arama yapın. | +5. `index_name` ve `index_value` içeren yük verilerine sahip eşleşen noktaları alın. | +6. Cassandra'ya sorgu yapın: | + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. Eşleşen satırları döndür. + +#### İsteğe Bağlı: İndeks Adı ile Filtreleme + +Sorgular, Qdrant'ta yalnızca belirli alanları aramak için isteğe bağlı olarak `index_name` ile filtrelenebilir: + +**" 'Chestnut' ile eşleşen herhangi bir alanı bul"** → koleksiyondaki tüm vektörleri arayın. +**" 'Chestnut' ile eşleşen 'street_name' alanını bul"** → `payload.index_name = 'street_name'` alanını filtreleyin. + +#### Mimari + +Satır gömüleri, GraphRAG tarafından kullanılan **iki aşamalı yapılandırmaya** sahiptir (grafik-gömüleri, belge-gömüleri): + +**1. Aşama: Gömü hesaplama** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - `ExtractedObject`'i tüketir, gömü hizmeti aracılığıyla gömüleri hesaplar, `RowEmbeddings` çıktısını üretir. +**2. Aşama: Gömü depolama** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - `RowEmbeddings`'i tüketir, vektörleri Qdrant'a yazar. + +Cassandra satır yazarı, ayrı bir paralel tüketici işlemidir: + +**Cassandra satır yazarı** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - `ExtractedObject`'i tüketir, satırları Cassandra'ya yazar. + +Tüm üç hizmet de aynı akıştan tüketir, böylece bunlar birbirinden ayrılır. Bu, şunları sağlar: +Cassandra yazma işlemlerinin, gömü oluşturma işlemlerine ve vektör depolama işlemlerine göre bağımsız olarak ölçeklenebilmesi. +Gerekli değilse gömü hizmetleri devre dışı bırakılabilir. +Bir hizmetteki hatalar diğerlerini etkilemez. +GraphRAG işlem hatları ile tutarlı bir mimari. + +#### Yazma Yolu + +**1. Aşama (satır-gömü işlemcisi):** Bir `ExtractedObject` aldığında: + +1. İndeksli alanları bulmak için şemayı arayın. +2. Her indeksli alan için: + İndeks değerinin metin gösterimini oluşturun. + Gömü hizmeti aracılığıyla gömüyü hesaplayın. +3. Tüm hesaplanan vektörleri içeren bir `RowEmbeddings` mesajı çıktısını verin. + +**2. Aşama (satır-gömü-yaz-qdrant):** Bir `RowEmbeddings` aldığında: + +1. Mesajdaki her gömü için: + `(user, collection, schema_name, dimension)`'dan Qdrant koleksiyonunu belirleyin. + Gerekirse koleksiyonu oluşturun (ilk yazmada tembel oluşturma). + Vektör ve yük ile noktayı ekleyin/güncelleyin. + +#### Mesaj Türleri + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### Silme Entegrasyonu + +Qdrant koleksiyonları, koleksiyon adı kalıbına göre önek eşleştirmesiyle bulunur: + +**`(user, collection)`'ı Silin:** +1. Önek `rows_{user}_{collection}_` ile eşleşen tüm Qdrant koleksiyonlarını listeleyin +2. Her eşleşen koleksiyonu silin +3. Cassandra satır bölümlerini silin (yukarıda belirtildiği gibi) +4. `row_partitions` girişlerini temizleyin + +**`(user, collection, schema_name)`'ı Silin:** +1. Önek `rows_{user}_{collection}_{schema_name}_` ile eşleşen tüm Qdrant koleksiyonlarını listeleyin +2. Her eşleşen koleksiyonu silin (çoklu boyutları işler) +3. Cassandra satır bölümlerini silin +4. `row_partitions`'ı temizleyin + +#### Modül Konumları + +| Aşama | Modül | Giriş Noktası | +|-------|--------|-------------| +| Aşama 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| Aşama 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### Satır Gömme Sorgu API'si + +Satır gömme sorgusu, GraphQL satır sorgu hizmetinden **ayrı bir API'dir**: + +| API | Amaç | Arka Uç | +|-----|---------|---------| +| Satır Sorgusu (GraphQL) | İndekslenmiş alanlarda tam eşleşme | Cassandra | +| Satır Gömme Sorgusu | Bulanık/anlamsal eşleşme | Qdrant | + +Bu ayrım, işlevleri net tutar: +GraphQL hizmeti, tam ve yapılandırılmış sorgulara odaklanır +Gömme API'si, anlamsal benzerliği işler +Kullanıcı iş akışı: adayları bulmak için gömmeler aracılığıyla bulanık arama, ardından tam satır verilerini almak için tam sorgu + +#### İstek/Yanıt Şeması + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### Sorgu İşleyici + +Modül: `trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +Giriş noktası: `row-embeddings-query-qdrant` + +İşleyici: +1. `RowEmbeddingsRequest` ile sorgu vektörlerini alır. +2. Önek eşleştirmesiyle uygun Qdrant koleksiyonunu bulur. +3. İsteğe bağlı `index_name` filtresiyle en yakın vektörleri arar. +4. Eşleşen indeks bilgileriyle `RowEmbeddingsResponse` döndürür. + +#### API Ağ Geçidi Entegrasyonu + +Ağ geçidi, standart istek/yanıt kalıbı aracılığıyla satır gömme sorgularını sunar: + +| Bileşen | Konum | +|-----------|----------| +| Yönlendirici | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| Kayıt | `"row-embeddings"`'ı `request_response_dispatchers`'e `manager.py` içinde ekleyin | + +Akış arayüz adı: `row-embeddings` + +Akış şablonundaki arayüz tanımı: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### Python SDK Desteği + +SDK, satır gömme sorguları için yöntemler sağlar: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### CLI Yardımcı Programı + +Komut: `tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### Tipik Kullanım Şekli + +Satır gömme sorgusu genellikle bulanık aramadan kesin aramaya geçiş akışının bir parçası olarak kullanılır: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +Bu iki aşamalı yapı şu olanakları sağlar: +Kullanıcı "Chestnut Street" araması yaptığında "CHESTNUT ST" ifadesinin bulunması +Tüm alanlarıyla birlikte eksiksiz satır verilerinin alınması +Anlamsal benzerliği yapılandırılmış veri erişimiyle birleştirme + +### Satır Veri Alımı + +Daha sonraki bir aşamaya ertelenmiştir. Diğer veri alım değişiklikleriyle birlikte tasarlanacaktır. + +## Uygulama Etkisi + +### Mevcut Durum Analizi + +Mevcut uygulama iki ana bileşenden oluşmaktadır: + +| Bileşen | Konum | Satır Sayısı | Açıklama | +|-----------|----------|-------|-------------| +| Sorgu Servisi | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | Tek bir blok: GraphQL şema oluşturma, filtre ayrıştırma, Cassandra sorguları, istek işleme | +| Yazıcı | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | Şema başına tablo oluşturma, ikincil indeksler, ekleme/silme | + +**Mevcut Sorgu Modeli:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**Yeni Sorgu Deseni:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### Önemli Değişiklikler + +1. **Sorgu anlamları basitleştirildi**: Yeni şema, yalnızca `index_value` üzerindeki tam eşleşmeleri desteklemektedir. Mevcut GraphQL filtreleri (`gt`, `lt`, `contains`, vb.): + Gerekliyse, döndürülen veriler üzerinde arka filtreleme olarak kullanılır. + Bulanık eşleştirme için gömülü API'nin kullanılması lehine kaldırılır. + +2. **GraphQL kodu sıkı bir şekilde birleştirilmiş durumda**: Mevcut `service.py`, Strawberry türü oluşturma, filtre ayrıştırma ve Cassandra'ya özgü sorguları bir araya getirmektedir. Başka bir satır depolama arka ucunun eklenmesi, yaklaşık 400 satır GraphQL kodunun çoğaltılmasına neden olacaktır. + +### Önerilen Yeniden Düzenleme + +Yeniden düzenleme iki bölümden oluşmaktadır: + +#### 1. GraphQL Kodunu Ayırmak + +Yeniden kullanılabilir GraphQL bileşenlerini, paylaşılan bir modüle çıkarın: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +Bu, şunları sağlar: +Farklı satır depolama arka uçlarında yeniden kullanılabilirlik +Daha temiz bir sorumluluk ayrımı +GraphQL mantığının bağımsız olarak daha kolay test edilebilmesi + +#### 2. Yeni Tablo Şemasını Uygulayın + +Cassandra'ya özgü kodu, birleşik tabloyu kullanacak şekilde yeniden düzenleyin: + +**Yazıcı** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +Her şema için ayrı tablolar yerine tek bir `rows` tablosu +Her satır için N kopyası yazın (her indeks için bir tane) +`row_partitions` tablosuna kaydolun +Daha basit tablo oluşturma (tek seferlik kurulum) + +**Sorgu Hizmeti** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +Birleşik `rows` tablosunu sorgulayın +Şema oluşturma için çıkarılan GraphQL modülünü kullanın +Basitleştirilmiş filtre işleme (yalnızca veritabanı düzeyinde tam eşleşme) + +### Modül Yeniden Adlandırmaları + +"nesne" → "satır" adlandırma temizliği kapsamında: + +| Mevcut | Yeni | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### Yeni Modüller + +| Modül | Amaç | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | Paylaşılan GraphQL yardımcı programları | +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | Satır gömme sorgu API'si | +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | Satır gömme hesaplama (1. Aşama) | +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | Satır gömme depolama (2. Aşama) | + +## Referanslar + +[Yapılandırılmış Veri Teknik Özellikleri](structured-data.md) diff --git a/docs/tech-specs/structured-data-2.zh-cn.md b/docs/tech-specs/structured-data-2.zh-cn.md new file mode 100644 index 00000000..eea930c0 --- /dev/null +++ b/docs/tech-specs/structured-data-2.zh-cn.md @@ -0,0 +1,621 @@ +--- +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 结构化数据集成初始实施过程中发现的问题和差距,如 `structured-data.md` 中所述。 + +## 问题陈述 + +### 1. 命名不一致:"对象" 与 "行" + +当前实现方案在整个代码中使用 "对象" 术语 (例如,`ExtractedObject`,对象提取,对象嵌入)。 这种命名方式过于通用,容易造成混淆: + +"对象" 在软件中是一个 overloaded 的术语 (Python 对象,JSON 对象等)。 +正在处理的数据本质上是表格数据,即具有定义模式的表格中的行。 +"行" 更准确地描述了数据模型,并且与数据库术语一致。 + +这种不一致性出现在模块名称、类名称、消息类型和文档中。 + +### 2. 行存储查询限制 + +当前的行存储实现方案存在重大的查询限制: + +**自然语言匹配问题**: 查询难以处理真实世界数据的变化。 例如: +很难在包含 `"CHESTNUT ST"` 的街道数据库中找到关于 `"Chestnut Street"` 的信息。 +缩写、大小写差异和格式变化会破坏精确匹配查询。 +用户期望语义理解,但存储系统只提供字面匹配。 + +**模式演化问题**: 更改模式会导致问题: +现有数据可能不符合更新后的模式。 +表结构的变化可能会破坏查询和数据完整性。 +没有明确的模式更新迁移路径。 + +### 3. 需要行嵌入 + +与问题 2 相关,系统需要行数据的向量嵌入,以便: + +在结构化数据上进行语义搜索 (找到 "Chestnut Street" 时,数据包含 "CHESTNUT ST")。 +模糊查询的相似性匹配。 +结合结构化过滤器和语义相似性的混合搜索。 +更好的自然语言查询支持。 + +嵌入服务已指定,但尚未实施。 + +### 4. 行数据摄取不完整 + +结构化数据摄取管道尚未完全投入使用: + +存在诊断提示,用于对输入格式进行分类 (CSV,JSON 等)。 +使用这些提示的摄取服务尚未集成到系统中。 +没有将预结构化数据加载到行存储的端到端路径。 + +## 目标 + +**模式灵活性**: 允许模式演化,而不会破坏现有数据或需要迁移。 +**命名一致性**: 在整个代码库中采用 "行" 术语。 +**语义可查询性**: 通过行嵌入支持模糊/语义匹配。 +**完整的摄取管道**: 提供将结构化数据加载到存储的端到端路径。 + +## 技术设计 + +### 统一的行存储模式 + +之前的实现方案为每个模式创建了一个单独的 Cassandra 表。 这在模式演化时会导致问题,因为表结构的变化需要迁移。 + +新的设计使用一个统一的表来存储所有行数据: + +```sql +CREATE TABLE rows ( + collection text, + schema_name text, + index_name text, + index_value frozen>, + data map, + source text, + PRIMARY KEY ((collection, schema_name, index_name), index_value) +) +``` + +#### 列定义 + +| 列 | 类型 | 描述 | +|--------|------|-------------| +| `collection` | `text` | 数据收集/导入标识符(来自元数据)| +| `schema_name` | `text` | 此行所遵循的模式名称 | +| `index_name` | `text` | 索引字段名称,以逗号分隔的字符串表示复合索引 | +| `index_value` | `frozen>` | 索引值列表 | +| `data` | `map` | 行数据,以键值对形式存储 | +| `source` | `text` | 可选的 URI,链接到知识图谱中的来源信息。空字符串或 NULL 表示没有来源。| + +#### 索引处理 + +每行数据会被存储多次,对于模式中定义的每个索引字段,都会存储一次。主键字段被视为索引,没有特殊的标记,以提供未来的灵活性。 + +**单字段索引示例:** +模式定义 `email` 为索引 +`index_name = "email"` +`index_value = ['foo@bar.com']` + +**复合索引示例:** +模式定义在 `region` 和 `status` 上创建复合索引 +`index_name = "region,status"` (字段名称按排序方式连接) +`index_value = ['US', 'active']` (值与字段名称的顺序相同) + +**主键示例:** +模式定义 `customer_id` 为主键 +`index_name = "customer_id"` +`index_value = ['CUST001']` + +#### 查询模式 + +无论使用哪个索引,所有查询都遵循相同的模式: + +```sql +SELECT * FROM rows +WHERE collection = 'import_2024' + AND schema_name = 'customers' + AND index_name = 'email' + AND index_value = ['foo@bar.com'] +``` + +#### 设计权衡 + +**优点:** +模式更改不需要更改表结构 +行数据对 Cassandra 隐藏 - 字段的添加/删除是透明的 +所有访问方法都具有一致的查询模式 +不需要 Cassandra 的二级索引(这在大型环境中可能会很慢) +整个过程中都使用 Cassandra 的原生类型(`map`,`frozen`) + +**权衡:** +写入放大:每个行插入 = N 次插入(每个索引字段一次) +重复行数据带来的存储开销 +类型信息存储在模式配置中,应用程序层进行转换 + +#### 一致性模型 + +该设计接受某些简化: + +1. **没有行更新**:系统是只追加的。这消除了关于更新同一行的多个副本的一致性问题。 + +2. **模式更改容错性**:当模式发生更改(例如,添加/删除索引)时,现有行保留其原始索引。旧行将无法通过新索引发现。如果需要,用户可以删除并重新创建模式以确保一致性。 + +### 分区跟踪和删除 + +#### 问题 + +借助分区键 `(collection, schema_name, index_name)`,高效删除需要知道所有要删除的分区键。仅通过 `collection` 或 `collection + schema_name` 删除需要知道所有具有数据的 `index_name` 值。 + +#### 分区跟踪表 + +一个辅助查找表跟踪哪些分区存在: + +```sql +CREATE TABLE row_partitions ( + collection text, + schema_name text, + index_name text, + PRIMARY KEY ((collection), schema_name, index_name) +) +``` + +这使得能够高效地发现用于删除操作的分区。 + +#### 行写入器行为 + +行写入器维护一个已注册的 `(collection, schema_name)` 对的内存缓存。 在处理一行时: + +1. 检查 `(collection, schema_name)` 是否在缓存中 +2. 如果未缓存(对于此对的第一个行): + 查找模式配置以获取所有索引名称 + 将条目插入到 `row_partitions` 中,对于每个 `(collection, schema_name, index_name)` + 将该对添加到缓存中 +3. 继续写入行数据 + +行写入器还监视模式配置更改事件。 当模式发生更改时,相关的缓存条目将被清除,以便下一行触发使用更新的索引名称重新注册。 + +这种方法确保: +查找表写入仅针对每个 `(collection, schema_name)` 对发生一次,而不是针对每行。 +查找表反映了数据写入时活动的索引。 +导入过程中发生的模式更改可以正确处理。 + +#### 删除操作 + +**删除集合:** +```sql +-- 1. Discover all partitions +SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table +DELETE FROM row_partitions WHERE collection = 'X'; +``` + +**删除集合 + 模式:** +```sql +-- 1. Discover partitions for this schema +SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; + +-- 2. Delete each partition from rows table +DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...'; +-- (repeat for each discovered partition) + +-- 3. Clean up the lookup table entries +DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y'; +``` + +### 行嵌入 + +行嵌入允许对索引值进行语义/模糊匹配,从而解决自然语言不匹配的问题(例如,在搜索“Chestnut Street”时找到“CHESTNUT ST”)。 + +#### 设计概述 + +每个索引值都会被嵌入,并存储在向量存储中(Qdrant)。在查询时,查询内容也会被嵌入,找到相似的向量,然后使用相关的元数据来查找 Cassandra 中的实际行。 + +#### Qdrant 集合结构 + +每个 `(user, collection, schema_name, dimension)` 元组对应一个 Qdrant 集合: + +**集合命名:** `rows_{user}_{collection}_{schema_name}_{dimension}` +名称会被清理(非字母数字字符替换为 `_`,转换为小写,数字前缀添加 `r_` 前缀) +**理由:** 允许通过删除匹配的 Qdrant 集合来干净地删除一个 `(user, collection, schema_name)` 实例;维度后缀允许不同的嵌入模型共存。 + +#### 哪些内容会被嵌入 + +索引值的文本表示: + +| 索引类型 | 示例 `index_value` | 要嵌入的文本 | +|------------|----------------------|---------------| +| 单字段 | `['foo@bar.com']` | `"foo@bar.com"` | +| 组合 | `['US', 'active']` | `"US active"` (空格连接) | + +#### 点结构 + +每个 Qdrant 点包含: + +```json +{ + "id": "", + "vector": [0.1, 0.2, ...], + "payload": { + "index_name": "street_name", + "index_value": ["CHESTNUT ST"], + "text": "CHESTNUT ST" + } +} +``` + +| Payload Field | Description | +|---------------|-------------| +| `index_name` | 此嵌入所代表的索引字段。| +| `index_value` | 原始值列表(用于 Cassandra 查找)。| +| `text` | 嵌入的文本(用于调试/显示)。| + +注意:`user`、`collection` 和 `schema_name` 可以从 Qdrant 集合名称中推断出来。| + +#### 查询流程 + +1. 用户查询用户 U、集合 X、模式 Y 中的“Chestnut Street”。| +2. 嵌入查询文本。| +3. 确定与前缀 `rows_U_X_Y_` 匹配的 Qdrant 集合名称。| +4. 在匹配的 Qdrant 集合中搜索最接近的向量。| +5. 获取包含 `index_name` 和 `index_value` 的有效负载的匹配点。| +6. 查询 Cassandra:| + ```sql + SELECT * FROM rows + WHERE collection = 'X' + AND schema_name = 'Y' + AND index_name = '' + AND index_value = + ``` +7. 返回匹配的行 + +#### 可选:按索引名称过滤 + +查询可以选择性地按 `index_name` 进行过滤,以便在 Qdrant 中仅搜索特定字段: + +**"查找所有匹配 'Chestnut' 的字段"** → 搜索集合中的所有向量 +**"查找 'Chestnut' 匹配的 street_name"** → 过滤 `payload.index_name = 'street_name'` + +#### 架构 + +行嵌入遵循 GraphRAG 使用的 **两阶段模式**(图嵌入、文档嵌入): + +**第一阶段:嵌入计算** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - 消耗 `ExtractedObject`,通过嵌入服务计算嵌入,输出 `RowEmbeddings` +**第二阶段:嵌入存储** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - 消耗 `RowEmbeddings`,将向量写入 Qdrant + +Cassandra 行写入器是一个独立的并行消费者: + +**Cassandra 行写入器** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - 消耗 `ExtractedObject`,将行写入 Cassandra + +所有三个服务都从同一个流中读取,从而使它们彼此解耦。 这允许: +独立地扩展 Cassandra 写入与嵌入生成与向量存储 +如果不需要,可以禁用嵌入服务 +一个服务中的故障不会影响其他服务 +与 GraphRAG 管道保持一致的架构 + +#### 写入路径 + +**第一阶段(行嵌入处理器):** 接收到 `ExtractedObject` 时: + +1. 查找模式以找到索引字段 +2. 对于每个索引字段: + 构建索引值的文本表示 + 通过嵌入服务计算嵌入 +3. 输出一个包含所有计算向量的 `RowEmbeddings` 消息 + +**第二阶段(行嵌入-写入-Qdrant):** 接收到 `RowEmbeddings` 时: + +1. 对于消息中的每个嵌入: + 从 `(user, collection, schema_name, dimension)` 确定 Qdrant 集合 + 如果需要,创建集合(首次写入时延迟创建) + 使用向量和有效载荷进行更新 + +#### 消息类型 + +```python +@dataclass +class RowIndexEmbedding: + index_name: str # The indexed field name(s) + index_value: list[str] # The field value(s) + text: str # Text that was embedded + vectors: list[list[float]] # Computed embedding vectors + +@dataclass +class RowEmbeddings: + metadata: Metadata + schema_name: str + embeddings: list[RowIndexEmbedding] +``` + +#### 删除集成 + +Qdrant 集合通过在集合名称模式上进行前缀匹配来发现: + +**删除 `(user, collection)`:** +1. 列出所有与前缀 `rows_{user}_{collection}_` 匹配的 Qdrant 集合 +2. 删除每个匹配的集合 +3. 删除 Cassandra 行分区(如上文所述) +4. 清理 `row_partitions` 条目 + +**删除 `(user, collection, schema_name)`:** +1. 列出所有与前缀 `rows_{user}_{collection}_{schema_name}_` 匹配的 Qdrant 集合 +2. 删除每个匹配的集合(处理多个维度) +3. 删除 Cassandra 行分区 +4. 清理 `row_partitions` + +#### 模块位置 + +| 阶段 | 模块 | 入口点 | +|-------|--------|-------------| +| 阶段 1 | `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | `row-embeddings` | +| 阶段 2 | `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | `row-embeddings-write-qdrant` | + +### 行嵌入查询 API + +行嵌入查询是与 GraphQL 行查询服务**不同的 API**: + +| API | 目的 | 后端 | +|-----|---------|---------| +| 行查询 (GraphQL) | 对索引字段进行精确匹配 | Cassandra | +| 行嵌入查询 | 模糊/语义匹配 | Qdrant | + +这种分离保持了关注点的清晰: +GraphQL 服务专注于精确、结构化的查询 +嵌入 API 处理语义相似性 +用户工作流程:通过嵌入进行模糊搜索以查找候选对象,然后进行精确查询以获取完整的行数据 + +#### 请求/响应模式 + +```python +@dataclass +class RowEmbeddingsRequest: + vectors: list[list[float]] # Query vectors (pre-computed embeddings) + user: str = "" + collection: str = "" + schema_name: str = "" + index_name: str = "" # Optional: filter to specific index + limit: int = 10 # Max results per vector + +@dataclass +class RowIndexMatch: + index_name: str = "" # The matched index field(s) + index_value: list[str] = [] # The matched value(s) + text: str = "" # Original text that was embedded + score: float = 0.0 # Similarity score + +@dataclass +class RowEmbeddingsResponse: + error: Error | None = None + matches: list[RowIndexMatch] = [] +``` + +#### 查询处理器 + +模块:`trustgraph-flow/trustgraph/query/row_embeddings/qdrant` + +入口点:`row-embeddings-query-qdrant` + +处理器: +1. 接收带有查询向量的 `RowEmbeddingsRequest` +2. 通过前缀匹配找到合适的 Qdrant 集合 +3. 搜索最近的向量,并可选择使用 `index_name` 过滤器 +4. 返回包含匹配索引信息的 `RowEmbeddingsResponse` + +#### API 网关集成 + +网关通过标准的请求/响应模式公开行嵌入查询: + +| 组件 | 位置 | +|-----------|----------| +| 调度器 | `trustgraph-flow/trustgraph/gateway/dispatch/row_embeddings_query.py` | +| 注册 | 将 `"row-embeddings"` 添加到 `request_response_dispatchers` 中,位于 `manager.py` | + +流程接口名称:`row-embeddings` + +流程蓝图中的接口定义: +```json +{ + "interfaces": { + "row-embeddings": { + "request": "non-persistent://tg/request/row-embeddings:{id}", + "response": "non-persistent://tg/response/row-embeddings:{id}" + } + } +} +``` + +#### Python SDK 支持 + +SDK 提供了用于行嵌入查询的方法: + +```python +# Flow-scoped query (preferred) +api = Api(url) +flow = api.flow().id("default") + +# Query with text (SDK computes embeddings) +matches = flow.row_embeddings_query( + text="Chestnut Street", + collection="my_collection", + schema_name="addresses", + index_name="street_name", # Optional filter + limit=10 +) + +# Query with pre-computed vectors +matches = flow.row_embeddings_query( + vectors=[[0.1, 0.2, ...]], + collection="my_collection", + schema_name="addresses" +) + +# Each match contains: +for match in matches: + print(match.index_name) # e.g., "street_name" + print(match.index_value) # e.g., ["CHESTNUT ST"] + print(match.text) # e.g., "CHESTNUT ST" + print(match.score) # e.g., 0.95 +``` + +#### 命令行工具 + +命令:`tg-invoke-row-embeddings` + +```bash +# Query by text (computes embedding automatically) +tg-invoke-row-embeddings \ + --text "Chestnut Street" \ + --collection my_collection \ + --schema addresses \ + --index street_name \ + --limit 10 + +# Query by vector file +tg-invoke-row-embeddings \ + --vectors vectors.json \ + --collection my_collection \ + --schema addresses + +# Output formats +tg-invoke-row-embeddings --text "..." --format json +tg-invoke-row-embeddings --text "..." --format table +``` + +#### 典型用法示例 + +行嵌入查询通常用作模糊到精确查找流程的一部分: + +```python +# Step 1: Fuzzy search via embeddings +matches = flow.row_embeddings_query( + text="chestnut street", + collection="geo", + schema_name="streets" +) + +# Step 2: Exact lookup via GraphQL for full row data +for match in matches: + query = f''' + query {{ + streets(where: {{ {match.index_name}: {{ eq: "{match.index_value[0]}" }} }}) {{ + street_name + city + zip_code + }} + }} + ''' + rows = flow.rows_query(query, collection="geo") +``` + +这种两步模式可以实现: +当用户搜索 "Chestnut Street" 时,找到 "CHESTNUT ST" +检索包含所有字段的完整行数据 +结合语义相似性和结构化数据访问 + +### 行数据导入 + +暂定于后续阶段。将与其他导入更改一起设计。 + +## 实施影响 + +### 当前状态分析 + +现有的实现包含两个主要组件: + +| 组件 | 位置 | 行数 | 描述 | +|-----------|----------|-------|-------------| +| 查询服务 | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | 整体式:GraphQL 模式生成、过滤器解析、Cassandra 查询、请求处理 | +| 写入器 | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | 每个模式的表创建、二级索引、插入/删除 | + +**当前的查询模式:** +```sql +SELECT * FROM {keyspace}.o_{schema_name} +WHERE collection = 'X' AND email = 'foo@bar.com' +ALLOW FILTERING +``` + +**新的查询模式:** +```sql +SELECT * FROM {keyspace}.rows +WHERE collection = 'X' AND schema_name = 'customers' + AND index_name = 'email' AND index_value = ['foo@bar.com'] +``` + +### 关键变更 + +1. **查询语义简化:** 新的模式仅支持对 `index_value` 的精确匹配。当前的 GraphQL 过滤器(`gt`、`lt`、`contains` 等)要么: + 变为对返回数据的后过滤(如果仍然需要) + 被移除,转而使用嵌入 API 进行模糊匹配 + +2. **GraphQL 代码紧密耦合:** 当前的 `service.py` 包含了 Strawberry 类型生成、过滤器解析以及 Cassandra 相关的查询。添加另一个行存储后端会重复大约 400 行的 GraphQL 代码。 + +### 提出的重构 + +重构分为两部分: + +#### 1. 提取 GraphQL 代码 + +将可重用的 GraphQL 组件提取到共享模块中: + +``` +trustgraph-flow/trustgraph/query/graphql/ +├── __init__.py +├── types.py # Filter types (IntFilter, StringFilter, FloatFilter) +├── schema.py # Dynamic schema generation from RowSchema +└── filters.py # Filter parsing utilities +``` + +这实现了: +在不同的行存储后端中实现重用 +更清晰的分层 +更容易独立地测试 GraphQL 逻辑 + +#### 2. 实现新的表模式 + +重构特定于 Cassandra 的代码,以使用统一的表: + +**写入器 (Writer)** (`trustgraph-flow/trustgraph/storage/rows/cassandra/`): +使用单个 `rows` 表,而不是每个模式的表 +写入 N 个副本到每行(每个索引一个) +注册到 `row_partitions` 表 +更简单的表创建(一次性设置) + +**查询服务 (Query Service)** (`trustgraph-flow/trustgraph/query/rows/cassandra/`): +查询统一的 `rows` 表 +使用提取的 GraphQL 模块进行模式生成 +简化的过滤处理(仅在数据库级别进行精确匹配) + +### 模块重命名 + +作为“object”→“row”命名清理的一部分: + +| 当前 (Current) | 新 (New) | +|---------|-----| +| `storage/objects/cassandra/` | `storage/rows/cassandra/` | +| `query/objects/cassandra/` | `query/rows/cassandra/` | +| `embeddings/object_embeddings/` | `embeddings/row_embeddings/` | + +### 新模块 + +| 模块 (Module) | 目的 (Purpose) | +|--------|---------| +| `trustgraph-flow/trustgraph/query/graphql/` | 共享 GraphQL 工具 +| `trustgraph-flow/trustgraph/query/row_embeddings/qdrant/` | 行嵌入查询 API +| `trustgraph-flow/trustgraph/embeddings/row_embeddings/` | 行嵌入计算(第一阶段) +| `trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/` | 行嵌入存储(第二阶段) + +## 引用 + +[结构化数据技术规范](structured-data.md) diff --git a/docs/tech-specs/structured-data-descriptor.ar.md b/docs/tech-specs/structured-data-descriptor.ar.md new file mode 100644 index 00000000..639177b7 --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.ar.md @@ -0,0 +1,567 @@ +--- +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. + +## نظرة عامة + +محدد البيانات المنظمة هو لغة تكوين تعتمد على JSON تصف كيفية تحليل وتحويل واستيراد البيانات المنظمة إلى TrustGraph. يوفر نهجًا تصريحيًا لاستيعاب البيانات، مما يدعم تنسيقات إدخال متعددة وقنوات تحويل معقدة دون الحاجة إلى تعليمات برمجية مخصصة. + +## المفاهيم الأساسية + +### 1. تعريف التنسيق +يصف نوع ملف الإدخال وخيارات التحليل. يحدد أي محلل لاستخدامه وكيفية تفسير البيانات المصدر. + +### 2. تعيينات الحقول +يربط مسارات المصدر بحقول الهدف مع التحويلات. يحدد كيفية تدفق البيانات من مصادر الإدخال إلى حقول مخطط الإخراج. + +### 3. سلسلة التحويل +سلسلة من تحويلات البيانات التي يمكن تطبيقها على قيم الحقول، بما في ذلك: +تنظيف البيانات (التقليم، التسوية) +تحويل التنسيق (تحليل التاريخ، تحويل النوع) +العمليات الحسابية (العمليات الحسابية، معالجة السلاسل) +عمليات البحث (جداول مرجعية، استبدالات) + +### 4. قواعد التحقق من الصحة +عمليات فحص جودة البيانات المطبقة لضمان سلامة البيانات: +التحقق من النوع +عمليات التحقق من النطاق +مطابقة الأنماط (regex) +التحقق من صحة الحقول المطلوبة +منطق التحقق المخصص + +### 5. الإعدادات العامة +التكوين الذي ينطبق على عملية الاستيراد بأكملها: +جداول البحث لإثراء البيانات +المتغيرات والثوابت العامة +مواصفات تنسيق الإخراج +سياسات معالجة الأخطاء + +## استراتيجية التنفيذ + +يتبع تطبيق المستورد هذا المسار: + +1. **تحليل التكوين** - تحميل والتحقق من صحة الوصف JSON +2. **تهيئة المحلل** - تحميل المحلل المناسب (CSV، XML، JSON، إلخ) بناءً على `format.type` +3. **تطبيق المعالجة المسبقة** - تنفيذ المرشحات والتحويلات العامة +4. **معالجة السجلات** - لكل سجل إدخال: + استخراج البيانات باستخدام مسارات المصدر (JSONPath، XPath، أسماء الأعمدة) + تطبيق التحويلات الخاصة بالحقل بالتسلسل + التحقق من صحة النتائج مقابل القواعد المحددة + تطبيق القيم الافتراضية للبيانات المفقودة +5. **تطبيق المعالجة اللاحقة** - تنفيذ إزالة التكرار، التجميع، إلخ. +6. **إنشاء الإخراج** - إنتاج البيانات بالتنسيق المستهدف المحدد + +## دعم تعبيرات المسار + +تستخدم تنسيقات الإدخال المختلفة لغات تعبيرات المسار المناسبة: + +**CSV**: أسماء الأعمدة أو الفهارس (`"column_name"` أو `"[2]"`) +**JSON**: بناء جملة JSONPath (`"$.user.profile.email"`) +**XML**: تعبيرات XPath (`"//product[@id='123']/price"`) +**العرض الثابت**: أسماء الحقول من تعريفات الحقول + +## المزايا + +**قاعدة تعليمات برمجية واحدة** - يقوم مستورد واحد بمعالجة تنسيقات إدخال متعددة +**سهل الاستخدام** - يمكن للمستخدمين غير التقنيين إنشاء تكوينات +**قابلة لإعادة الاستخدام** - يمكن مشاركة التكوينات وتنسيق الإصدارات +**مرنة** - تحويلات معقدة بدون ترميز مخصص +**قوية** - تحقق مدمج ومعالجة شاملة للأخطاء +**قابلة للصيانة** - يوفر النهج التصريحي تقليل تعقيد التنفيذ + +## مواصفات اللغة + +يستخدم محدد البيانات المنظمة تنسيق تكوين JSON مع البنية العامة التالية: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### تعريف التنسيق + +يصف تنسيق البيانات المدخلة وخيارات التحليل: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +### خيارات تنسيق CSV +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### خيارات تنسيق JSON +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### خيارات تنسيق XML +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### الإعدادات العامة + +تحديد الجداول المرجعية والمتغيرات والتكوين العام: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### تعيينات الحقول + +حدد كيفية تعيين البيانات المصدر إلى الحقول المستهدفة مع التحويلات: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### أنواع التحويل + +الوظائف المتاحة للتحويل: + +#### تحويلات السلاسل النصية +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### تحويلات الأنواع +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### العمليات على البيانات +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### قواعد التحقق + +عمليات فحص جودة البيانات مع معالجة أخطاء قابلة للتكوين: + +#### عمليات التحقق الأساسية +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### التحقق من الصحة المخصصة +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### المعالجة الأولية والمعالجة اللاحقة + +العمليات العامة المطبقة قبل/بعد تعيين الحقول: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### إعدادات الإخراج + +حدد كيفية إخراج البيانات المعالجة: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## مثال كامل + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## موجه نموذج اللغة الكبير لإنشاء الوصف + +يمكن استخدام الموجه التالي لجعل نموذج لغة كبير يحلل بيانات عينة وينشئ تكوينًا للوصف: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### مثال للاستخدام + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +CustomerID، الاسم، البريد الإلكتروني، العمر، البلد، الحالة، تاريخ الانضمام، إجمالي المشتريات +1001، "Smith, John"، john.smith@email.com، 35، الولايات المتحدة الأمريكية، 1، 2023-01-15، 5420.50 +1002، "doe, jane"، JANE.DOE@GMAIL.COM، 28، كندا، 1، 2023-03-22، 3200.00 +1003، "Bob Johnson"، bob@، 62، المملكة المتحدة، 0، 2022-11-01، 0 +1004، "Alice Chen"، alice.chen@company.org، 41، الولايات المتحدة الأمريكية، 1، 2023-06-10، 8900.25 +1005، ، invalid-email، 25، XX، 1، 2024-01-01، 100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### طلب لتحليل البيانات الحالية بدون عينة + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.es.md b/docs/tech-specs/structured-data-descriptor.es.md new file mode 100644 index 00000000..b45cae60 --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.es.md @@ -0,0 +1,567 @@ +--- +layout: default +title: "Especificación del Descriptor de Datos Estructurados" +parent: "Spanish (Beta)" +--- + +# Especificación del Descriptor de Datos Estructurados + +> **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 + +El Descriptor de Datos Estructurados es un lenguaje de configuración basado en JSON que describe cómo analizar, transformar e importar datos estructurados en TrustGraph. Proporciona un enfoque declarativo para la ingesta de datos, admitiendo múltiples formatos de entrada y complejas canalizaciones de transformación sin requerir código personalizado. + +## Conceptos Clave + +### 1. Definición de Formato +Describe el tipo de archivo de entrada y las opciones de análisis. Determina qué analizador utilizar y cómo interpretar los datos de origen. + +### 2. Mapeo de Campos +Mapea las rutas de origen a los campos de destino con transformaciones. Define cómo fluyen los datos desde las fuentes de entrada a los campos del esquema de salida. + +### 3. Canalización de Transformación +Cadena de transformaciones de datos que se pueden aplicar a los valores de los campos, incluyendo: +Limpieza de datos (recorte, normalización) +Conversión de formato (análisis de fechas, conversión de tipos) +Cálculos (aritméticos, manipulación de cadenas) +Consultas (tablas de referencia, sustituciones) + +### 4. Reglas de Validación +Comprobaciones de calidad de datos aplicadas para garantizar la integridad de los datos: +Validación de tipo +Comprobaciones de rango +Coincidencia de patrones (expresiones regulares) +Validación de campos obligatorios +Lógica de validación personalizada + +### 5. Configuración Global +Configuración que se aplica a todo el proceso de importación: +Tablas de consulta para la enriquecimiento de datos +Variables y constantes globales +Especificaciones de formato de salida +Políticas de manejo de errores + +## Estrategia de Implementación + +La implementación del importador sigue esta canalización: + +1. **Análisis de Configuración** - Carga y valida el descriptor JSON +2. **Inicialización del Analizador** - Carga el analizador apropiado (CSV, XML, JSON, etc.) basado en `format.type` +3. **Aplicación de Preprocesamiento** - Ejecuta filtros y transformaciones globales +4. **Procesamiento de Registros** - Para cada registro de entrada: + Extrae datos utilizando rutas de origen (JSONPath, XPath, nombres de columna) + Aplica transformaciones a nivel de campo en secuencia + Valida los resultados contra las reglas definidas + Aplica valores predeterminados para datos faltantes +5. **Aplicación de Postprocesamiento** - Ejecuta desduplicación, agregación, etc. +6. **Generación de Salida** - Produce datos en el formato de destino especificado + +## Soporte de Expresiones de Ruta + +Diferentes formatos de entrada utilizan lenguajes de expresiones de ruta apropiados: + +**CSV**: Nombres de columna o índices (`"column_name"` o `"[2]"`) +**JSON**: Sintaxis JSONPath (`"$.user.profile.email"`) +**XML**: Expresiones XPath (`"//product[@id='123']/price"`) +**Ancho Fijo**: Nombres de campo de las definiciones de campo + +## Beneficios + +**Base de Código Única** - Un único importador maneja múltiples formatos de entrada +**Fácil de Usar** - Usuarios no técnicos pueden crear configuraciones +**Reutilizable** - Las configuraciones se pueden compartir y versionar +**Flexible** - Transformaciones complejas sin codificación personalizada +**Robusto** - Validación integrada y manejo de errores integral +**Mantenible** - El enfoque declarativo reduce la complejidad de la implementación + +## Especificación del Lenguaje + +El Descriptor de Datos Estructurados utiliza un formato de configuración JSON con la siguiente estructura de nivel superior: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### Definición del formato + +Describe el formato de los datos de entrada y las opciones de análisis: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### Opciones de formato CSV +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### Opciones de formato JSON +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### Opciones de formato XML +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### Configuración Global + +Defina tablas de búsqueda, variables y configuración global: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### Mapeo de campos + +Defina cómo los datos de origen se mapean a los campos de destino con transformaciones: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### Tipos de Transformación + +Funciones de transformación disponibles: + +#### Transformaciones de Cadenas de Texto +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### Conversiones de tipo +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### Operaciones de datos +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### Reglas de validación + +Comprobaciones de calidad de datos con manejo de errores configurable: + +#### Validaciones básicas +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### Validaciones Personalizadas +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### Preprocesamiento y Postprocesamiento + +Operaciones globales aplicadas antes/después del mapeo de campos: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### Configuración de salida + +Defina cómo se deben mostrar los datos procesados: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## Ejemplo Completo + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## Indicación para el LLM para la Generación de Descriptores + +La siguiente indicación se puede utilizar para que un LLM analice datos de muestra y genere una configuración de descriptor: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### Ejemplo de uso (Prompt) + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +CustomerID,Nombre,Email,Edad,País,Estado,Fecha de Inscripción,Total de Compras +1001,"Smith, John",john.smith@email.com,35,US,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,CA,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,UK,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,US,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### Solicitud para Analizar Datos Existentes Sin Muestra + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.he.md b/docs/tech-specs/structured-data-descriptor.he.md new file mode 100644 index 00000000..d80f13f7 --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.he.md @@ -0,0 +1,567 @@ +--- +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. + +## סקירה כללית + +תיאור הנתונים המובנים הוא שפת תצורה מבוססת JSON המתארת כיצד לנתח, להמיר ולייבא נתונים מובנים ל-TrustGraph. הוא מספק גישה הצהרתית לייבוא נתונים, תוך תמיכה בפורמטים מרובים של קלט וצינורות המרה מורכבים מבלי לדרוש קוד מותאם אישית. + +## מושגים מרכזיים + +### 1. הגדרת פורמט +מתאר את סוג הקובץ הנכנס ואפשרויות הניתוח. קובע איזה מנתח להשתמש וכיצד לפרש את הנתונים המקור. + +### 2. מיפוי שדות +ממפה נתיבים מקור לשדות יעד עם המרות. מגדיר כיצד הנתונים זורמים ממקורות קלט לשדות סכימה בפלט. + +### 3. צינור המרה +שרשרת של המרות נתונים שניתן להחיל על ערכי שדות, כולל: +ניקוי נתונים (חיתוך, נרמול) +המרת פורמט (ניתוח תאריכים, המרת טיפוסים) +חישובים (חשבון, מניפולציה של מחרוזות) +חיפושים (טבלאות הפניה, החלפות) + +### 4. כללי אימות +בדיקות איכות נתונים המיושמות כדי להבטיח את שלמות הנתונים: +אימות טיפוס +בדיקות טווח +התאמת תבניות (ביטויים רגולריים) +אימות שדות חובה +לוגיקה מותאמת אישית לאימות + +### 5. הגדרות גלובליות +תצורה החלה על כל תהליך הייבוא: +טבלאות חיפוש להעשרת נתונים +משתנים וקבועים גלובליים +מפרטי פורמט פלט +מדיניות טיפול בשגיאות + +## אסטרטגיית יישום + +יישום המייבא עוקב אחר הצינור הבא: + +1. **ניתוח תצורה** - טעינה ואימות של תיאור JSON +2. **אתחול מנתח** - טעינת מנתח מתאים (CSV, XML, JSON, וכו') בהתבסס על `format.type` +3. **החלת עיבוד מקדים** - ביצוע פילטרים והמרות גלובליים +4. **עיבוד רשומות** - עבור כל רשומה נכנסת: + חילוץ נתונים באמצעות נתיבי מקור (JSONPath, XPath, שמות עמודות) + החלת המרות ברמת השדה בסדר + אימות תוצאות בהתאם לכללים מוגדרים + החלת ערכי ברירת מחדל עבור נתונים חסרים +5. **החלת עיבוד לאחר** - ביצוע הסרה כפילות, אגרגציה, וכו'. +6. **יצירת פלט** - יצירת נתונים בפורמט יעד מוגדר + +## תמיכה בביטוי נתיב + +פורמטים שונים של קלט משתמשים בשפות ביטוי נתיב מתאימות: + +**CSV**: שמות עמודות או אינדקסים (`"column_name"` או `"[2]"`) +**JSON**: תחביר JSONPath (`"$.user.profile.email"`) +**XML**: ביטויי XPath (`"//product[@id='123']/price"`) +**רוחב קבוע**: שמות שדות מהגדרות שדות + +## יתרונות + +**בסיס קוד יחיד** - מייבא אחד מטפל בפורמטים מרובים של קלט +**ידידותי למשתמש** - משתמשים לא טכניים יכולים ליצור תצורות +**ניתן לשימוש חוזר** - ניתן לשתף תצורות ולגרסן +**גמיש** - המרות מורכבות ללא קידוד מותאם אישית +**יציב** - אימות מובנה וטיפול מקיף בשגיאות +**ניתן לתחזוקה** - גישה הצהרתית מפחיתה את מורכבות היישום + +## מפרט שפה + +תיאור הנתונים המובנים משתמש בפורמט תצורה JSON עם המבנה הבסיסי הבא ברמה העליונה: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### הגדרת פורמט + +מתאר את פורמט הנתונים הקלט ואפשרויות הניתוח: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### אפשרויות פורמט CSV +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### אפשרויות פורמט JSON +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### אפשרויות פורמט XML +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### הגדרות גלובליות + +הגדירו טבלאות חיפוש, משתנים ותצורות גלובליות: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### מיפוי שדות + +הגדירו כיצד נתוני המקור ממופים לשדות היעד עם טרנספורמציות: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### סוגי טרנספורמציה + +פונקציות טרנספורמציה זמינות: + +#### טרנספורמציות מחרוזות +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### המרות טיפוסים +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### פעולות נתונים +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### כללי אימות + +בדיקות איכות נתונים עם טיפול בשגיאות הניתן להגדרה: + +#### אימותים בסיסיים +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### אימותים מותאמים אישית +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### עיבוד מקדים ועיבוד סופי + +פעולות גלובליות המיושמות לפני/אחרי מיפוי שדות: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### הגדרות פלט + +הגדירו כיצד יש להוציא את הנתונים שעברו עיבוד: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## דוגמה מלאה + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## הנחיה עבור מודל שפה גדול (LLM) ליצירת תיאור + +ניתן להשתמש בהנחיה הבאה כדי לגרום למודל שפה גדול לנתח נתוני דוגמה וליצור תצורת תיאור: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### הנחיה לדוגמה לשימוש + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +CustomerID,שם לקוח,כתובת דוא"ל,גיל,מדינה,סטטוס,תאריך הצטרפות,סך רכישות +1001,"Smith, John",john.smith@email.com,35,US,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,CA,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,UK,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,US,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### הנחיה לניתוח נתונים קיימים ללא דוגמה + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.hi.md b/docs/tech-specs/structured-data-descriptor.hi.md new file mode 100644 index 00000000..12a92189 --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.hi.md @@ -0,0 +1,567 @@ +--- +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. + +## अवलोकन + +संरचित डेटा विवरण एक JSON-आधारित कॉन्फ़िगरेशन भाषा है जो यह बताती है कि संरचित डेटा को कैसे पार्स, रूपांतरित और ट्रस्टग्राफ में आयात किया जाए। यह डेटा इनग्रेसन के लिए एक घोषणात्मक दृष्टिकोण प्रदान करता है, जो कई इनपुट प्रारूपों और जटिल परिवर्तन पाइपलाइनों का समर्थन करता है, बिना कस्टम कोड की आवश्यकता के। + +## मुख्य अवधारणाएँ + +### 1. प्रारूप परिभाषा +इनपुट फ़ाइल प्रकार और पार्सिंग विकल्पों का वर्णन करता है। यह निर्धारित करता है कि किस पार्सर का उपयोग करना है और स्रोत डेटा की व्याख्या कैसे करनी है। + +### 2. फ़ील्ड मैपिंग +स्रोत पथों को लक्ष्य फ़ील्ड में रूपांतरणों के साथ मैप करता है। यह परिभाषित करता है कि डेटा इनपुट स्रोतों से आउटपुट स्कीमा फ़ील्ड में कैसे प्रवाहित होता है। + +### 3. परिवर्तन पाइपलाइन +डेटा रूपांतरणों की श्रृंखला जो फ़ील्ड मानों पर लागू की जा सकती है, जिसमें शामिल हैं: +डेटा सफाई (ट्रिम, सामान्यीकरण) +प्रारूप रूपांतरण (तारीख पार्सिंग, प्रकार कास्टिंग) +गणनाएँ (अंकगणित, स्ट्रिंग हेरफेर) +लुकअप (संदर्भ तालिकाएँ, प्रतिस्थापन) + +### 4. सत्यापन नियम +डेटा गुणवत्ता जांच जो डेटा अखंडता सुनिश्चित करने के लिए लागू की जाती हैं: +प्रकार सत्यापन +सीमा जांच +पैटर्न मिलान (रेगेक्स) +आवश्यक फ़ील्ड सत्यापन +कस्टम सत्यापन तर्क + +### 5. वैश्विक सेटिंग्स +कॉन्फ़िगरेशन जो संपूर्ण आयात प्रक्रिया पर लागू होता है: +डेटा संवर्धन के लिए लुकअप तालिकाएँ +वैश्विक चर और स्थिरांक +आउटपुट प्रारूप विनिर्देश +त्रुटि हैंडलिंग नीतियां + +## कार्यान्वयन रणनीति + +इम्पोर्टर कार्यान्वयन निम्नलिखित पाइपलाइन का पालन करता है: + +1. **कॉन्फ़िगरेशन पार्स करें** - JSON विवरण लोड करें और मान्य करें +2. **पार्सर आरंभ करें** - उपयुक्त पार्सर लोड करें (CSV, XML, JSON, आदि) `format.type` के आधार पर +3. **पूर्व-प्रसंस्करण लागू करें** - वैश्विक फ़िल्टर और रूपांतरण निष्पादित करें +4. **रिकॉर्ड संसाधित करें** - प्रत्येक इनपुट रिकॉर्ड के लिए: + स्रोत पथों (JSONPath, XPath, कॉलम नाम) का उपयोग करके डेटा निकालें + अनुक्रम में फ़ील्ड-स्तरीय रूपांतरण लागू करें + परिभाषित नियमों के विरुद्ध परिणामों को मान्य करें + लापता डेटा के लिए डिफ़ॉल्ट मान लागू करें +5. **पोस्ट-प्रोसेसिंग लागू करें** - डुप्लिकेट हटाना, एकत्रीकरण, आदि निष्पादित करें। +6. **आउटपुट उत्पन्न करें** - निर्दिष्ट लक्ष्य प्रारूप में डेटा उत्पन्न करें + +## पथ अभिव्यक्ति समर्थन + +विभिन्न इनपुट प्रारूप उपयुक्त पथ अभिव्यक्ति भाषाओं का उपयोग करते हैं: + +**CSV**: कॉलम नाम या इंडेक्स (`"column_name"` या `"[2]"`) +**JSON**: JSONPath सिंटैक्स (`"$.user.profile.email"`) +**XML**: XPath एक्सप्रेशन (`"//product[@id='123']/price"`) +**फिक्स्ड-विड्थ**: फ़ील्ड परिभाषाओं से फ़ील्ड नाम + +## लाभ + +**सिंगल कोडबेस** - एक इम्पोर्टर कई इनपुट प्रारूपों को संभालता है +**उपयोगकर्ता के अनुकूल** - गैर-तकनीकी उपयोगकर्ता कॉन्फ़िगरेशन बना सकते हैं +**पुन: प्रयोज्य** - कॉन्फ़िगरेशन साझा और संस्करणित किए जा सकते हैं +**लचीला** - कस्टम कोडिंग के बिना जटिल रूपांतरण +**मजबूत** - अंतर्निहित सत्यापन और व्यापक त्रुटि हैंडलिंग +**रखरखाव योग्य** - घोषणात्मक दृष्टिकोण कार्यान्वयन जटिलता को कम करता है + +## भाषा विनिर्देश + +संरचित डेटा विवरण एक JSON कॉन्फ़िगरेशन प्रारूप का उपयोग करता है जिसमें निम्नलिखित शीर्ष-स्तरीय संरचना है: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### प्रारूप परिभाषा + +इनपुट डेटा प्रारूप और पार्सिंग विकल्पों का वर्णन करता है: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### सीएसवी प्रारूप विकल्प +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### जेएसओएन प्रारूप विकल्प +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### XML प्रारूप विकल्प +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### वैश्विक सेटिंग्स + +लुकअप टेबल, वेरिएबल और वैश्विक कॉन्फ़िगरेशन को परिभाषित करें: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### फ़ील्ड मैपिंग + +परिभाषित करें कि स्रोत डेटा लक्ष्य फ़ील्ड में कैसे मैप होता है, जिसमें रूपांतरण शामिल हैं: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### रूपांतरण प्रकार + +उपलब्ध रूपांतरण फ़ंक्शन: + +#### स्ट्रिंग रूपांतरण +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### प्रकार रूपांतरण +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### डेटा संचालन +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### सत्यापन नियम + +कॉन्फ़िगर करने योग्य त्रुटि प्रबंधन के साथ डेटा गुणवत्ता जांच: + +#### बुनियादी सत्यापन +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### कस्टम सत्यापन +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### पूर्व-प्रसंस्करण और उत्तर-प्रसंस्करण + +फ़ील्ड मैपिंग से पहले/बाद लागू किए गए वैश्विक ऑपरेशन: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### आउटपुट कॉन्फ़िगरेशन + +परिभाषित करें कि संसाधित डेटा को कैसे आउटपुट किया जाना चाहिए: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## पूर्ण उदाहरण + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## एलएलएम प्रॉम्प्ट (LLM Prompt) का उपयोग करके विवरण (डेस्क्रिप्टर) निर्माण + +निम्नलिखित प्रॉम्प्ट का उपयोग करके, एक एलएलएम (LLM) नमूना डेटा का विश्लेषण कर सकता है और एक विवरण कॉन्फ़िगरेशन उत्पन्न कर सकता है: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### उदाहरण उपयोग संकेत + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +ग्राहक आईडी, नाम, ईमेल, आयु, देश, स्थिति, शामिल होने की तिथि, कुल खरीदारी +1001, "स्मिथ, जॉन", john.smith@email.com, 35, यूएस, 1, 2023-01-15, 5420.50 +1002, "डो, जेन", JANE.DOE@GMAIL.COM, 28, कनाडा, 1, 2023-03-22, 3200.00 +1003, "बॉब जॉनसन", bob@, 62, यूके, 0, 2022-11-01, 0 +1004, "एलिस चेन", "alice.chen@company.org", 41, यूएस, 1, 2023-06-10, 8900.25 +1005, , invalid-email, 25, XX, 1, 2024-01-01, 100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### मौजूदा डेटा का विश्लेषण करने के लिए संकेत (प्रॉम्प्ट) बिना नमूने के + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.md b/docs/tech-specs/structured-data-descriptor.md index e3a797ae..216f29c8 100644 --- a/docs/tech-specs/structured-data-descriptor.md +++ b/docs/tech-specs/structured-data-descriptor.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Structured Data Descriptor Specification" +parent: "Tech Specs" +--- + # Structured Data Descriptor Specification ## Overview @@ -556,4 +562,4 @@ Please generate a Structured Data Descriptor configuration that will: 5. Output in TrustGraph ExtractedObject format Focus on making the configuration robust and reusable. -``` \ No newline at end of file +``` diff --git a/docs/tech-specs/structured-data-descriptor.pt.md b/docs/tech-specs/structured-data-descriptor.pt.md new file mode 100644 index 00000000..227fe58d --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.pt.md @@ -0,0 +1,567 @@ +--- +layout: default +title: "Especificação do Descritor de Dados Estruturados" +parent: "Portuguese (Beta)" +--- + +# Especificação do Descritor de Dados Estruturados + +> **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 + +O Descritor de Dados Estruturados é uma linguagem de configuração baseada em JSON que descreve como analisar, transformar e importar dados estruturados para o TrustGraph. Ele fornece uma abordagem declarativa para a ingestão de dados, suportando vários formatos de entrada e pipelines de transformação complexos sem a necessidade de código personalizado. + +## Conceitos Principais + +### 1. Definição de Formato +Descreve o tipo de arquivo de entrada e as opções de análise. Determina qual analisador usar e como interpretar os dados de origem. + +### 2. Mapeamentos de Campos +Mapeia caminhos de origem para campos de destino com transformações. Define como os dados fluem das fontes de entrada para os campos do esquema de saída. + +### 3. Pipeline de Transformação +Cadeia de transformações de dados que podem ser aplicadas aos valores dos campos, incluindo: +Limpeza de dados (remover espaços em branco, normalização) +Conversão de formato (análise de data, conversão de tipo) +Cálculos (aritméticos, manipulação de strings) +Consultas (tabelas de referência, substituições) + +### 4. Regras de Validação +Verificações de qualidade de dados aplicadas para garantir a integridade dos dados: +Validação de tipo +Verificações de intervalo +Correspondência de padrões (regex) +Validação de campos obrigatórios +Lógica de validação personalizada + +### 5. Configurações Globais +Configuração que se aplica a todo o processo de importação: +Tabelas de consulta para enriquecimento de dados +Variáveis e constantes globais +Especificações de formato de saída +Políticas de tratamento de erros + +## Estratégia de Implementação + +A implementação do importador segue este pipeline: + +1. **Analisar Configuração** - Carregar e validar o descritor JSON +2. **Inicializar Analisador** - Carregar o analisador apropriado (CSV, XML, JSON, etc.) com base em `format.type` +3. **Aplicar Pré-processamento** - Executar filtros e transformações globais +4. **Processar Registros** - Para cada registro de entrada: + Extrair dados usando caminhos de origem (JSONPath, XPath, nomes de coluna) + Aplicar transformações de nível de campo em sequência + Validar os resultados em relação às regras definidas + Aplicar valores padrão para dados ausentes +5. **Aplicar Pós-processamento** - Executar desduplicação, agregação, etc. +6. **Gerar Saída** - Produzir dados no formato de destino especificado + +## Suporte a Expressões de Caminho + +Diferentes formatos de entrada usam linguagens de expressão de caminho apropriadas: + +**CSV**: Nomes de coluna ou índices (`"column_name"` ou `"[2]"`) +**JSON**: Sintaxe JSONPath (`"$.user.profile.email"`) +**XML**: Expressões XPath (`"//product[@id='123']/price"`) +**Largura Fixa**: Nomes de campo das definições de campo + +## Benefícios + +**Base de Código Única** - Um único importador lida com vários formatos de entrada +**Fácil de Usar** - Usuários não técnicos podem criar configurações +**Reutilizável** - As configurações podem ser compartilhadas e versionadas +**Flexível** - Transformações complexas sem codificação personalizada +**Robusto** - Validação integrada e tratamento de erros abrangente +**Manutenível** - A abordagem declarativa reduz a complexidade da implementação + +## Especificação da Linguagem + +O Descritor de Dados Estruturados usa um formato de configuração JSON com a seguinte estrutura de nível superior: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### Definição do Formato + +Descreve o formato dos dados de entrada e as opções de análise: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### Opções de Formato CSV +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### Opções de Formato JSON +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### Opções de Formato XML +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### Configurações Globais + +Defina tabelas de consulta, variáveis e configuração global: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### Mapeamentos de Campos + +Defina como os dados de origem são mapeados para os campos de destino, com transformações: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### Tipos de Transformação + +Funções de transformação disponíveis: + +#### Transformações de String +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### Conversões de Tipo +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### Operações com Dados +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### Regras de Validação + +Verificações de qualidade de dados com tratamento de erros configurável: + +#### Validações Básicas +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### Validações Personalizadas +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### Pré-processamento e pós-processamento + +Operações globais aplicadas antes/depois do mapeamento de campos: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### Configuração de Saída + +Defina como os dados processados devem ser enviados: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## Exemplo Completo + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## Prompt de LLM para Geração de Descritores + +O seguinte prompt pode ser usado para que um LLM analise dados de amostra e gere uma configuração de descritores: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### Exemplo de Uso (Prompt) + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +CustomerID,Nome,Email,Idade,País,Status,Data de Adesão,Total de Compras +1001,"Smith, John",john.smith@email.com,35,US,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,CA,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,UK,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,US,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### Solicitação para Análise de Dados Existentes Sem Amostra + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.ru.md b/docs/tech-specs/structured-data-descriptor.ru.md new file mode 100644 index 00000000..b27ee59b --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.ru.md @@ -0,0 +1,567 @@ +--- +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. + +## Обзор + +Дескриптор структурированных данных - это язык конфигурации на основе JSON, который описывает, как анализировать, преобразовывать и импортировать структурированные данные в TrustGraph. Он предоставляет декларативный подход к импорту данных, поддерживающий различные форматы входных данных и сложные конвейеры преобразований без необходимости написания пользовательского кода. + +## Основные понятия + +### 1. Определение формата +Описывает тип входного файла и параметры анализа. Определяет, какой анализатор использовать и как интерпретировать исходные данные. + +### 2. Отображения полей +Отображает пути источника на целевые поля с преобразованиями. Определяет, как данные передаются из исходных источников в поля выходной схемы. + +### 3. Конвейер преобразований +Цепочка преобразований данных, которые могут быть применены к значениям полей, включая: +Очистка данных (удаление лишних пробелов, нормализация) +Преобразование формата (разбор дат, приведение типов) +Вычисления (арифметические операции, манипуляции со строками) +Поиск (таблицы ссылок, замены) + +### 4. Правила проверки +Проверки качества данных, применяемые для обеспечения целостности данных: +Проверка типов +Проверки диапазонов +Сопоставление с образцом (регулярные выражения) +Проверка обязательных полей +Пользовательская логика проверки + +### 5. Глобальные настройки +Конфигурация, применяемая ко всему процессу импорта: +Таблицы поиска для обогащения данных +Глобальные переменные и константы +Спецификации формата вывода +Политики обработки ошибок + +## Стратегия реализации + +Реализация импортера следует следующей схеме: + +1. **Анализ конфигурации** - Загрузка и проверка JSON-дескриптора +2. **Инициализация анализатора** - Загрузка соответствующего анализатора (CSV, XML, JSON и т.д.) на основе `format.type` +3. **Применение предварительной обработки** - Выполнение глобальных фильтров и преобразований +4. **Обработка записей** - Для каждой входной записи: + Извлечение данных с использованием путей источника (JSONPath, XPath, имена столбцов) + Применение преобразований на уровне поля в последовательности + Проверка результатов на соответствие определенным правилам + Применение значений по умолчанию для отсутствующих данных +5. **Применение постобработки** - Выполнение дедупликации, агрегации и т.д. +6. **Генерация вывода** - Создание данных в указанном целевом формате + +## Поддержка выражений путей + +Различные форматы входных данных используют соответствующие языки выражений путей: + +**CSV**: Имена столбцов или индексы (`"column_name"` или `"[2]"`) +**JSON**: Синтаксис JSONPath (`"$.user.profile.email"`) +**XML**: Выражения XPath (`"//product[@id='123']/price"`) +**Fixed-width**: Имена полей из определений полей + +## Преимущества + +**Единая кодовая база** - Один импортер обрабатывает несколько форматов входных данных +**Удобство использования** - Пользователи, не являющиеся специалистами, могут создавать конфигурации +**Повторное использование** - Конфигурации можно обмениваться и версионировать +**Гибкость** - Сложные преобразования без пользовательского кода +**Надежность** - Встроенная проверка и комплексная обработка ошибок +**Поддерживаемость** - Декларативный подход снижает сложность реализации + +## Спецификация языка + +Дескриптор структурированных данных использует формат конфигурации JSON со следующей структурой верхнего уровня: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### Определение формата + +Описывает формат входных данных и параметры разбора: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### Варианты формата CSV +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### Варианты формата JSON +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### Варианты формата XML +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### Глобальные настройки + +Определите таблицы поиска, переменные и глобальную конфигурацию: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### Отображение полей + +Определите, как исходные данные сопоставляются с целевыми полями с использованием преобразований: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### Типы преобразований + +Доступные функции преобразования: + +#### Преобразования строк +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### Преобразования типов +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### Операции с данными +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### Правила проверки + +Проверки качества данных с настраиваемой обработкой ошибок: + +#### Базовые проверки +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### Пользовательские проверки +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### Предварительная обработка и постобработка + +Глобальные операции, применяемые до/после сопоставления полей: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### Настройка вывода + +Определите, как обработанные данные должны быть выведены: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## Полный пример + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## Подсказка для LLM для генерации описаний + +Следующую подсказку можно использовать, чтобы LLM проанализировал примеры данных и сгенерировал конфигурацию описания: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### Пример использования запроса + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +CustomerID,Имя,Электронная почта,Возраст,Страна,Статус,Дата присоединения,Общая сумма покупок +1001,"Smith, John",john.smith@email.com,35,US,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,CA,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,UK,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,US,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### Запрос на анализ существующих данных без использования образцов + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.sw.md b/docs/tech-specs/structured-data-descriptor.sw.md new file mode 100644 index 00000000..b70dd4e6 --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.sw.md @@ -0,0 +1,567 @@ +--- +layout: default +title: "Maelezo ya Muundo wa Data" +parent: "Swahili (Beta)" +--- + +# Maelezo ya Muundo wa Data + +> **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 + +Maelezo ya Muundo wa Data ni lugha ya usanidi iliyo msingi ya JSON ambayo inaeleza jinsi ya kuchanganua, kubadilisha, na kuingiza data iliyo na muundo katika TrustGraph. Inatoa njia ya matangazo ya jinsi ya kuingiza data, ikisaidia aina tofauti za pembejeo na mnyororo mgumu wa mabadiliko bila kuhitaji nambari maalum. + +## Dhana Muhimu + +### 1. Ufafanuzi wa Aina +Inaeleza aina ya faili ya pembejeo na chaguzi za kuchanganua. Inaamua kichanganuzi gani cha kutumia na jinsi ya kutafsiri data ya chanzo. + +### 2. Ramani za Uwanja +Inaunganisha njia za chanzo na uwanja wa lengo pamoja na mabadiliko. Inaeleza jinsi data inavyosonga kutoka kwa vyanzo vya pembejeo hadi kwenye uwanja wa schema ya pato. + +### 3. Mnyororo wa Mabadiliko +Mnyororo wa mabadiliko ya data ambayo yanaweza kutumika kwenye thamani za uwanja, pamoja na: +Usafishaji wa data (kukata, kusawazisha) +Ubadilishaji wa aina (uchanganuzi wa tarehe, ubadilishaji wa aina) +Hesabu (hesabu, urekebishaji wa maandishi) +Utafiti (meza za rejea, mbadala) + +### 4. Kanuni za Uthibitisho +Vipimo vya ubora wa data ambavyo hutumika kuhakikisha uadilifu wa data: +Uthibitisho wa aina +Vipimo vya anuwai +Ulinganishi wa muundo (regex) +Uthibitisho wa uwanja unaohitajika +Mantiki ya uthibitisho maalum + +### 5. Mpangilio wa Jumla +Mpangilio ambao hutumika katika mchakato wote wa uingizaji: +Meza za utafiti kwa uboreshaji wa data +Vigezo na mara kwa mara vya kimataifa +Maelezo ya muundo wa pato +Sera za kushughulikia makosa + +## Mkakati wa Utendaji + +Utendaji wa programu ya uingizaji unafuata mnyororo huu: + +1. **Changanua Mpangilio** - Pakia na thibitisha maelezo ya JSON +2. **Anzisha Kichanganuzi** - Pakia kichanganuzi kinachofaa (CSV, XML, JSON, n.k.) kulingana na `format.type` +3. **Tumia Uchujaji wa Awali** - Fanya vichujio na mabadiliko ya kimataifa +4. **Chakata Rekodi** - Kwa kila rekodi ya pembejeo: + Toa data ukitumia njia za chanzo (JSONPath, XPath, majina ya safu) + Tumia mabadiliko ya kiwanja kwa mlolongo + Thibitisha matokeo dhidi ya sheria zilizoelezwa + Tumia maadili chaguu kwa data inayokosekana +5. **Tumia Uchakataji wa Baada** - Fanya uondoaji mara mbili, ukusanyaji, n.k. +6. **Toa Pato** - Toa data katika muundo wa lengo uliotakikana + +## Usaidizi wa Maneno ya Njia + +Aina tofauti za pembejeo hutumia lugha zinazofaa za maneno ya njia: + +**CSV**: Majina ya safu au fahirisi (`"column_name"` au `"[2]"`) +**JSON**: Lugha ya JSONPath (`"$.user.profile.email"`) +**XML**: Maneno ya XPath (`"//product[@id='123']/price"`) +**Upana-uliofanyika**: Majina ya uwanja kutoka maelezo ya uwanja + +## Faida + +**Nambari Moja** - Programu moja ya uingizaji inashughulikia aina tofauti za pembejeo +**Inafaa kwa Mtumiaji** - Watumiaji ambao hawana ujuzi wa kiufundi wanaweza kuunda mipangilio +**Inaweza Kurejeshwa** - Mipangilio inaweza kushirikiwa na kutolewa toleo +**Inafaa** - Mabadiliko magumu bila nambari maalum +**Imara** - Uthibitisho uliounganishwa na utunzaji wa kina wa makosa +**Inaweza Kudumishwa** - Njia ya matangazo hupunguza utata wa utekelezaji + +## Maelezo ya Lugha + +Maelezo ya Muundo wa Data hutumia muundo wa usanidi wa JSON na muundo wa juu unaofuata: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### Ufafanuzi wa Muundo + +Huainisha muundo wa data ya pembejeo na chaguo za uchakataji: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### Chaguo za Muundo wa CSV +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### Chaguo za Muundo wa JSON +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### Chaguo za Muundo wa XML +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### Mipangilio ya Ulimwengu + +Fafanua jedwali za utafutaji, vigezo, na usanidi wa jumla: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### Ramani za Vyanzo vya Habari + +Eleza jinsi data kutoka chanzo inavyolingana na vyanzo vya habari vya lengo, pamoja na mabadiliko: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### Aina za Ubadilishaji + +Kazi zinazopatikana za kubadilisha: + +#### Ubadilishaji wa Mfumo wa Herufi +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### Tafsiri za Aina +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### Operesheni za Data +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### Kanuni za Uthibitisho + +Uchunguzi wa ubora wa data pamoja na udhibiti wa makosa unaoweza kusanidiwa: + +### Uthibitisho Msingi +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### Uthibitisho Maalum +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### Maandalizi na Urekebishaji + +Operesheni za jumla zinazotumiwa kabla na baada ya uhamishaji wa data: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### Usanidi wa Matokeo + +Eleza jinsi data iliyochakatwa inapaswa kuonyeshwa: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## Mfano Kamili + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## Maagizo ya LLM kwa Ajili ya Uundaji wa Maelezo + +Maagizo yafuatayo yanaweza kutumika ili LLM iweze kuchanganua data ya mfano na kuunda usanidi wa maelezo: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### Mfano wa Matumizi + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +Kitambulisho cha Mteja,Jina,Barua pepe,Umri,Nchi,Hali,Tarehe ya Kujiunga,Ununuzi Jumla +1001,"Smith, John",john.smith@email.com,35,US,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,CA,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,UK,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,US,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### Ombi la Kuchanganua Data Zilizopo Bila Sampuli + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.tr.md b/docs/tech-specs/structured-data-descriptor.tr.md new file mode 100644 index 00000000..d438ac9c --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.tr.md @@ -0,0 +1,567 @@ +--- +layout: default +title: "Yapılandırılmış Veri Tanımlayıcı Özellikleri" +parent: "Turkish (Beta)" +--- + +# Yapılandırılmış Veri Tanımlayıcı Ö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ış + +Yapılandırılmış Veri Tanımlayıcı, JSON tabanlı bir yapılandırma dilidir ve TrustGraph'a yapılandırılmış verilerin nasıl ayrıştırıldığı, dönüştürüldüğü ve içe aktarıldığını tanımlar. Veri içe aktarma için deklaratif bir yaklaşım sunar, çoklu giriş formatlarını ve özel kod gerektirmeden karmaşık dönüşüm süreçlerini destekler. + +## Temel Kavramlar + +### 1. Format Tanımı +Giriş dosya türünü ve ayrıştırma seçeneklerini tanımlar. Hangi ayrıştırıcının kullanılacağını ve kaynak verilerin nasıl yorumlanacağını belirler. + +### 2. Alan Eşlemeleri +Kaynak yollarını hedef alanlarla dönüşümlerle eşler. Verilerin kaynaklardan çıktı şema alanlarına nasıl aktığını tanımlar. + +### 3. Dönüşüm Süreci +Alan değerlerine uygulanabilecek veri dönüşüm zinciri. Şunları içerir: +Veri temizleme (boşlukları kaldırma, normalleştirme) +Biçim dönüştürme (tarih ayrıştırma, tür dönüştürme) +Hesaplamalar (aritmetik işlemler, dize manipülasyonu) +Arama tabloları (referans tabloları, eşleştirmeler) + +### 4. Doğrulama Kuralları +Veri bütünlüğünü sağlamak için uygulanan veri kalitesi kontrolleri: +Tür doğrulama +Aralık kontrolleri +Desen eşleştirme (regex) +Gerekli alan doğrulama +Özel doğrulama mantığı + +### 5. Genel Ayarlar +Tüm içe aktarma sürecine uygulanan yapılandırma: +Veri zenginleştirme için arama tabloları +Küresel değişkenler ve sabitler +Çıktı biçimi özellikleri +Hata işleme politikaları + +## Uygulama Stratejisi + +İçe aktarıcı uygulaması aşağıdaki süreci izler: + +1. **Yapılandırmayı Ayrıştır** - JSON tanımlayıcısını yükleyin ve doğrulayın +2. **Ayrıştırıcıyı Başlat** - `format.type`'a göre uygun ayrıştırıcıyı yükleyin (CSV, XML, JSON, vb.) +3. **Ön İşleme Uygula** - Küresel filtreleri ve dönüşümleri çalıştırın +4. **Kayıtları İşle** - Her giriş kaydı için: + Kaynak yollarını (JSONPath, XPath, sütun adları) kullanarak verileri çıkarın + Alan düzeyindeki dönüşümleri sırayla uygulayın + Sonuçları tanımlı kurallara göre doğrulayın + Eksik veriler için varsayılan değerleri uygulayın +5. **Son İşleme Uygula** - Tekilleştirme, birleştirme, vb. işlemlerini gerçekleştirin +6. **Çıktıyı Oluştur** - Verileri belirtilen hedef biçimde oluşturun + +## Yol İfadesi Desteği + +Farklı giriş formatları, uygun yol ifadesi dillerini kullanır: + +**CSV**: Sütun adları veya indeksler (`"column_name"` veya `"[2]"`) +**JSON**: JSONPath sözdizimi (`"$.user.profile.email"`) +**XML**: XPath ifadeleri (`"//product[@id='123']/price"`) +**Sabit genişlik**: Alan tanımlarından alan adları + +## Avantajlar + +**Tek Kod Tabanı** - Tek bir içe aktarıcı, çoklu giriş formatlarını işler +**Kullanıcı Dostu** - Teknik olmayan kullanıcılar, yapılandırmalar oluşturabilir +**Yeniden Kullanılabilir** - Yapılandırmalar paylaşılabilir ve sürüm kontrolüne tabi tutulabilir +**Esnek** - Özel kodlama olmadan karmaşık dönüşümler +**Sağlam** - Yerleşik doğrulama ve kapsamlı hata işleme +**Bakımı Kolay** - Deklaratif yaklaşım, uygulama karmaşıklığını azaltır + +## Dil Özellikleri + +Yapılandırılmış Veri Tanımlayıcı, aşağıdaki üst düzey yapıya sahip bir JSON yapılandırma biçimi kullanır: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### Biçim Tanımı + +Giriş verisi biçimini ve ayrıştırma seçeneklerini açıklar: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### CSV Format Seçenekleri +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### JSON Formatı Seçenekleri +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### XML Formatı Seçenekleri +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### Küresel Ayarlar + +Arama tablolarını, değişkenleri ve genel yapılandırmayı tanımlayın: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### Alan Eşlemeleri + +Dönüşümlerle birlikte kaynak verilerinin hedef alanlara nasıl eşlendiğini tanımlayın: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### Dönüşüm Türleri + +Kullanılabilir dönüşüm fonksiyonları: + +#### String Dönüşümleri +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### Tür Dönüşümleri +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### Veri İşlemleri +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### Doğrulama Kuralları + +Yapılandırılabilir hata yönetimi ile veri kalitesi kontrolleri: + +#### Temel Doğrulamalar +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### Özel Doğrulamalar +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### Ön İşleme ve Son İşleme + +Alan eşlemesi öncesinde/sonrasında uygulanan genel işlemler: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### Çıktı Yapılandırması + +İşlenmiş verilerin nasıl çıktı olarak verilmesi gerektiğini tanımlayın: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## Tam Bir Örnek + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## Açıklayıcı Oluşturma İçin LLM İstem + +Aşağıdaki istem, bir LLM'nin örnek verileri analiz etmesi ve bir açıklayıcı yapılandırma oluşturması için kullanılabilir: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### Örnek Kullanım İsteği + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +MüşteriID,Ad,E-posta,Yaş,Ülke,Durum,KayıtTarihi,ToplamSatınAlımlar +1001,"Smith, John",john.smith@email.com,35,US,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,CA,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,UK,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,US,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### Mevcut Verileri Örnek Olmadan Analiz Etme İsteği + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-descriptor.zh-cn.md b/docs/tech-specs/structured-data-descriptor.zh-cn.md new file mode 100644 index 00000000..77ce2fa5 --- /dev/null +++ b/docs/tech-specs/structured-data-descriptor.zh-cn.md @@ -0,0 +1,567 @@ +--- +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. + +## 概述 + +结构化数据描述符是一种基于 JSON 的配置语言,用于描述如何解析、转换和导入结构化数据到 TrustGraph 中。它提供了一种声明式的数据导入方法,支持多种输入格式和复杂的转换流程,而无需自定义代码。 + +## 核心概念 + +### 1. 格式定义 +描述输入文件类型和解析选项。确定要使用的解析器以及如何解释源数据。 + +### 2. 字段映射 +将源路径映射到目标字段,并进行转换。定义数据如何从输入源流向输出模式字段。 + +### 3. 转换流程 +一系列应用于字段值的转换,包括: +数据清洗(修剪、标准化) +格式转换(日期解析、类型转换) +计算(算术运算、字符串操作) +查找(引用表、替换) + +### 4. 验证规则 +应用于确保数据完整性的数据质量检查: +类型验证 +范围检查 +模式匹配(正则表达式) +必填字段验证 +自定义验证逻辑 + +### 5. 全局设置 +适用于整个导入过程的配置: +用于数据增强的查找表 +全局变量和常量 +输出格式规范 +错误处理策略 + +## 实施策略 + +导入器的实现遵循以下流程: + +1. **解析配置** - 加载和验证 JSON 描述符 +2. **初始化解析器** - 根据 `format.type` 加载适当的解析器(CSV、XML、JSON 等) +3. **应用预处理** - 执行全局过滤器和转换 +4. **处理记录** - 对于每个输入记录: + 使用源路径(JSONPath、XPath、列名)提取数据 + 按照顺序应用字段级别的转换 + 根据定义的规则验证结果 + 为缺失数据应用默认值 +5. **应用后处理** - 执行去重、聚合等操作 +6. **生成输出** - 以指定的目标格式生成数据 + +## 路径表达式支持 + +不同的输入格式使用适当的路径表达式语言: + +**CSV**: 列名或索引(`"column_name"` 或 `"[2]"`) +**JSON**: JSONPath 语法(`"$.user.profile.email"`) +**XML**: XPath 表达式(`"//product[@id='123']/price"`) +**定宽**: 来自字段定义的字段名 + +## 优点 + +**单一代码库** - 一个导入器处理多种输入格式 +**用户友好** - 非技术用户可以创建配置 +**可重用** - 可以共享和版本控制配置 +**灵活** - 无需自定义代码即可进行复杂的转换 +**健壮** - 内置验证和全面的错误处理 +**可维护** - 声明式方法减少了实施复杂性 + +## 语言规范 + +结构化数据描述符使用基于 JSON 的配置格式,其顶级结构如下: + +```json +{ + "version": "1.0", + "metadata": { + "name": "Configuration Name", + "description": "Description of what this config does", + "author": "Author Name", + "created": "2024-01-01T00:00:00Z" + }, + "format": { ... }, + "globals": { ... }, + "preprocessing": [ ... ], + "mappings": [ ... ], + "postprocessing": [ ... ], + "output": { ... } +} +``` + +### 格式定义 + +描述输入数据格式和解析选项: + +```json +{ + "format": { + "type": "csv|json|xml|fixed-width|excel|parquet", + "encoding": "utf-8", + "options": { + // Format-specific options + } + } +} +``` + +#### CSV 格式选项 +```json +{ + "format": { + "type": "csv", + "options": { + "delimiter": ",", + "quote_char": "\"", + "escape_char": "\\", + "skip_rows": 1, + "has_header": true, + "null_values": ["", "NULL", "null", "N/A"] + } + } +} +``` + +#### JSON 格式选项 +```json +{ + "format": { + "type": "json", + "options": { + "root_path": "$.data", + "array_mode": "records|single", + "flatten": false + } + } +} +``` + +#### XML 格式选项 +```json +{ + "format": { + "type": "xml", + "options": { + "root_element": "//records/record", + "namespaces": { + "ns": "http://example.com/namespace" + } + } + } +} +``` + +### 全局设置 + +定义查找表、变量和全局配置: + +```json +{ + "globals": { + "variables": { + "current_date": "2024-01-01", + "batch_id": "BATCH_001", + "default_confidence": 0.8 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "UK": "United Kingdom", + "CA": "Canada" + }, + "status_mapping": { + "1": "active", + "0": "inactive" + } + }, + "constants": { + "source_system": "legacy_crm", + "import_type": "full" + } + } +} +``` + +### 字段映射 + +定义如何将源数据映射到目标字段,并进行转换: + +```json +{ + "mappings": [ + { + "target_field": "person_name", + "source": "$.name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"}, + {"type": "required"} + ], + "validation": [ + {"type": "min_length", "value": 2}, + {"type": "max_length", "value": 100}, + {"type": "pattern", "value": "^[A-Za-z\\s]+$"} + ] + }, + { + "target_field": "age", + "source": "$.age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 150} + ] + }, + { + "target_field": "country", + "source": "$.country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ] +} +``` + +### 转换类型 + +可用的转换函数: + +#### 字符串转换 +```json +{"type": "trim"}, +{"type": "upper"}, +{"type": "lower"}, +{"type": "title_case"}, +{"type": "replace", "pattern": "old", "replacement": "new"}, +{"type": "regex_replace", "pattern": "\\d+", "replacement": "XXX"}, +{"type": "substring", "start": 0, "end": 10}, +{"type": "pad_left", "length": 10, "char": "0"} +``` + +#### 类型转换 +```json +{"type": "to_string"}, +{"type": "to_int"}, +{"type": "to_float"}, +{"type": "to_bool"}, +{"type": "to_date", "format": "YYYY-MM-DD"}, +{"type": "parse_json"} +``` + +#### 数据操作 +```json +{"type": "default", "value": "default_value"}, +{"type": "lookup", "table": "table_name"}, +{"type": "concat", "values": ["field1", " - ", "field2"]}, +{"type": "calculate", "expression": "${field1} + ${field2}"}, +{"type": "conditional", "condition": "${age} > 18", "true_value": "adult", "false_value": "minor"} +``` + +### 验证规则 + +数据质量检查,具有可配置的错误处理: + +#### 基础验证 +```json +{"type": "required"}, +{"type": "not_null"}, +{"type": "min_length", "value": 5}, +{"type": "max_length", "value": 100}, +{"type": "range", "min": 0, "max": 1000}, +{"type": "pattern", "value": "^[A-Z]{2,3}$"}, +{"type": "in_list", "values": ["active", "inactive", "pending"]} +``` + +#### 自定义验证 +```json +{ + "type": "custom", + "expression": "${age} >= 18 && ${country} == 'US'", + "message": "Must be 18+ and in US" +}, +{ + "type": "cross_field", + "fields": ["start_date", "end_date"], + "expression": "${start_date} < ${end_date}", + "message": "Start date must be before end date" +} +``` + +### 预处理和后处理 + +在字段映射之前/之后应用的全局操作: + +```json +{ + "preprocessing": [ + { + "type": "filter", + "condition": "${status} != 'deleted'" + }, + { + "type": "sort", + "field": "created_date", + "order": "asc" + } + ], + "postprocessing": [ + { + "type": "deduplicate", + "key_fields": ["email", "phone"] + }, + { + "type": "aggregate", + "group_by": ["country"], + "functions": { + "total_count": {"type": "count"}, + "avg_age": {"type": "avg", "field": "age"} + } + } + ] +} +``` + +### 输出配置 + +定义如何输出处理后的数据: + +```json +{ + "output": { + "format": "trustgraph-objects", + "schema_name": "person", + "options": { + "batch_size": 1000, + "confidence": 0.9, + "source_span_field": "raw_text", + "metadata": { + "source": "crm_import", + "version": "1.0" + } + }, + "error_handling": { + "on_validation_error": "skip|fail|log", + "on_transform_error": "skip|fail|default", + "max_errors": 100, + "error_output": "errors.json" + } + } +} +``` + +## 完整示例 + +```json +{ + "version": "1.0", + "metadata": { + "name": "Customer Import from CRM CSV", + "description": "Imports customer data from legacy CRM system", + "author": "Data Team", + "created": "2024-01-01T00:00:00Z" + }, + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true, + "skip_rows": 1 + } + }, + "globals": { + "variables": { + "import_date": "2024-01-01", + "default_confidence": 0.85 + }, + "lookup_tables": { + "country_codes": { + "US": "United States", + "CA": "Canada", + "UK": "United Kingdom" + } + } + }, + "preprocessing": [ + { + "type": "filter", + "condition": "${status} == 'active'" + } + ], + "mappings": [ + { + "target_field": "full_name", + "source": "customer_name", + "transforms": [ + {"type": "trim"}, + {"type": "title_case"} + ], + "validation": [ + {"type": "required"}, + {"type": "min_length", "value": 2} + ] + }, + { + "target_field": "email", + "source": "email_address", + "transforms": [ + {"type": "trim"}, + {"type": "lower"} + ], + "validation": [ + {"type": "pattern", "value": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"} + ] + }, + { + "target_field": "age", + "source": "age", + "transforms": [ + {"type": "to_int"}, + {"type": "default", "value": 0} + ], + "validation": [ + {"type": "range", "min": 0, "max": 120} + ] + }, + { + "target_field": "country", + "source": "country_code", + "transforms": [ + {"type": "lookup", "table": "country_codes"}, + {"type": "default", "value": "Unknown"} + ] + } + ], + "output": { + "format": "trustgraph-objects", + "schema_name": "customer", + "options": { + "confidence": "${default_confidence}", + "batch_size": 500 + }, + "error_handling": { + "on_validation_error": "log", + "max_errors": 50 + } + } +} +``` + +## 用于描述符生成的 LLM 提示 + +以下提示可用于让 LLM 分析样本数据并生成描述符配置: + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +The descriptor should follow this specification: +- version: "1.0" +- metadata: Configuration name, description, author, and creation date +- format: Input format type and parsing options +- globals: Variables, lookup tables, and constants +- preprocessing: Filters and transformations applied before mapping +- mappings: Field-by-field mapping from source to target with transformations and validations +- postprocessing: Operations like deduplication or aggregation +- output: Target format and error handling configuration + +ANALYZE THE DATA: +1. Identify the format (CSV, JSON, XML, etc.) +2. Detect delimiters, encodings, and structure +3. Find data types for each field +4. Identify patterns and constraints +5. Look for fields that need cleaning or transformation +6. Find relationships between fields +7. Identify lookup opportunities (codes that map to values) +8. Detect required vs optional fields + +CREATE THE DESCRIPTOR: +For each field in the sample data: +- Map it to an appropriate target field name +- Add necessary transformations (trim, case conversion, type casting) +- Include appropriate validations (required, patterns, ranges) +- Set defaults for missing values + +Include preprocessing if needed: +- Filters to exclude invalid records +- Sorting requirements + +Include postprocessing if beneficial: +- Deduplication on key fields +- Aggregation for summary data + +Configure output for TrustGraph: +- format: "trustgraph-objects" +- schema_name: Based on the data entity type +- Appropriate error handling + +DATA SAMPLE: +[Insert data sample here] + +ADDITIONAL CONTEXT (optional): +- Target schema name: [if known] +- Business rules: [any specific requirements] +- Data quality issues to address: [known problems] + +Generate a complete, valid Structured Data Descriptor configuration that will properly import this data into TrustGraph. Include comments explaining key decisions. +``` + +### 示例用法提示 + +``` +I need you to analyze the provided data sample and create a Structured Data Descriptor configuration in JSON format. + +[Standard instructions from above...] + +DATA SAMPLE: +```csv +客户ID,姓名,电子邮件,年龄,国家,状态,加入日期,总购买额 +1001,"Smith, John",john.smith@email.com,35,美国,1,2023-01-15,5420.50 +1002,"doe, jane",JANE.DOE@GMAIL.COM,28,加拿大,1,2023-03-22,3200.00 +1003,"Bob Johnson",bob@,62,英国,0,2022-11-01,0 +1004,"Alice Chen","alice.chen@company.org",41,美国,1,2023-06-10,8900.25 +1005,,invalid-email,25,XX,1,2024-01-01,100 +``` + +ADDITIONAL CONTEXT: +- Target schema name: customer +- Business rules: Email should be valid and lowercase, names should be title case +- Data quality issues: Some emails are invalid, some names are missing, country codes need mapping +``` + +### 用于分析现有数据而无需样本的提示 + +``` +I need you to help me create a Structured Data Descriptor configuration for importing [data type] data. + +The source data has these characteristics: +- Format: [CSV/JSON/XML/etc] +- Fields: [list the fields] +- Data quality issues: [describe any known issues] +- Volume: [approximate number of records] + +Requirements: +- [List any specific transformation needs] +- [List any validation requirements] +- [List any business rules] + +Please generate a Structured Data Descriptor configuration that will: +1. Parse the input format correctly +2. Clean and standardize the data +3. Validate according to the requirements +4. Handle errors gracefully +5. Output in TrustGraph ExtractedObject format + +Focus on making the configuration robust and reusable. +``` diff --git a/docs/tech-specs/structured-data-schemas.ar.md b/docs/tech-specs/structured-data-schemas.ar.md new file mode 100644 index 00000000..cc2931f1 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.ar.md @@ -0,0 +1,139 @@ +--- +layout: default +title: "مخطط بيانات البنية: تغييرات مخطط Pulsar" +parent: "Arabic (Beta)" +--- + +# مخطط بيانات البنية: تغييرات مخطط Pulsar + +> **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. + +## نظرة عامة + +استنادًا إلى مواصفات `STRUCTURED_DATA.md`، تقترح هذه الوثيقة الإضافات والتعديلات اللازمة على مخطط Pulsar لدعم قدرات البيانات المنظمة في TrustGraph. + +## تغييرات مخطط مطلوبة + +### 1. تحسينات مخطط أساسية + +#### تعريف الحقل المحسّن +تحتاج الفئة الحالية `Field` في `core/primitives.py` إلى خصائص إضافية: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # حقول جديدة: + required = Boolean() # ما إذا كان الحقل مطلوبًا + enum_values = Array(String()) # للحقول من نوع Enum + indexed = Boolean() # ما إذا كان يجب فهرسة الحقل +``` + +### 2. مخططات معرفة جديدة + +#### 2.1 إرسال بيانات منظمة +ملف جديد: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # مرجع إلى المخطط في التكوين + data = Bytes() # البيانات الخام للإدخال + options = Map(String()) # خيارات محددة بالتنسيق +``` + +### 3. مخططات الخدمات الجديدة + +#### 3.1 خدمة استعلام NLP إلى منظمة +ملف جديد: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # تلميحات سياق اختيارية لتوليد الاستعلام + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # استعلام GraphQL المُنشأ + variables = Map(String()) # متغيرات GraphQL إذا كانت موجودة + detected_schemas = Array(String()) # المخططات التي يستهدفها الاستعلام + confidence = Double() +``` + +#### 3.2 خدمة استعلام منظمة +ملف جديد: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # استعلام GraphQL + variables = Map(String()) # متغيرات GraphQL + operation_name = String() # اسم العملية الاختياري للمستندات متعددة العمليات + +class StructuredQueryResponse(Record): + error = Error() + data = String() # بيانات استجابة GraphQL المُشفرة بتنسيق JSON + errors = Array(String()) # أخطاء GraphQL إذا كانت موجودة +``` + +#### 2.2 مخرجات استخراج الكائنات +ملف جديد: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # أي مخطط ينتمي إليه هذا الكائن + values = Map(String()) # اسم الحقل -> القيمة + confidence = Double() + source_span = String() # نطاق النص الذي تم فيه العثور على الكائن +``` + +### 4. مخططات معرفة محسّنة + +#### 4.1 تحسين تضمين الكائنات +قم بتحديث `knowledge/embeddings.py` لدعم تضمين الكائنات المنظمة بشكل أفضل: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # قيمة المفتاح الأساسي + field_embeddings = Map(Array(Double())) # تضمينات الحقول +``` + +## نقاط التكامل + +### تكامل التدفق + +سيتم استخدام المخططات في وحدات تدفق جديدة: +- `trustgraph-flow/trustgraph/decoding/structured` - يستخدم StructuredDataSubmission +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - يستخدم مخططات استعلام NLP +- `trustgraph-flow/trustgraph/query/objects/cassandra` - يستخدم مخططات استعلام منظمة +- `trustgraph-flow/trustgraph/extract/object/row/` - يستهلك Chunk، وينتج ExtractedObject +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - يستخدم مخطط Rows +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - يستخدم مخططات تضمين الكائنات + +## ملاحظات التنفيذ + +1. **إصدار المخطط**: ضع في اعتبارك إضافة حقل `version` إلى RowSchema لدعم الترحيل المستقبلي +2. **نظام الأنواع**: يجب أن يدعم `Field.type` جميع أنواع بيانات Cassandra الأصلية +3. **عمليات المجموعة**: يجب أن يدعم معظم الخدمات العمليات الفردية والمجمعة +4. **معالجة الأخطاء**: يجب أن يكون للإبلاغ عن الأخطاء باستمرار عبر جميع الخدمات الجديدة +5. **التوافق مع الإصدارات السابقة**: تظل المخططات الحالية دون تغيير باستثناء التحسينات الطفيفة للملفات diff --git a/docs/tech-specs/structured-data-schemas.es.md b/docs/tech-specs/structured-data-schemas.es.md new file mode 100644 index 00000000..821517aa --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.es.md @@ -0,0 +1,145 @@ +--- +layout: default +title: "Cambios en el Esquema de Datos Estructurados en Pulsar" +parent: "Spanish (Beta)" +--- + +# Cambios en el Esquema de Datos Estructurados en Pulsar + +> **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. + +## Visión general + +Basado en la especificación `STRUCTURED_DATA.md`, este documento propone las adiciones y modificaciones necesarias en el esquema de Pulsar para soportar las capacidades de datos estructurados en TrustGraph. + +## Cambios de Esquema Requeridos + +### 1. Mejoras en el Esquema Central + +#### Definición de Campo Mejorada +La clase `Field` existente en `core/primitives.py` necesita propiedades adicionales: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # CAMPOS NUEVOS: + required = Boolean() # Indica si el campo es obligatorio + enum_values = Array(String()) # Para campos de tipo enum + indexed = Boolean() # Indica si el campo debe ser indexado +``` + +### 2. Nuevos Esquemas de Conocimiento + +#### 2.1 Envío de Datos Estructurados +Nuevo archivo: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # Referencia al esquema en la configuración + data = Bytes() # Datos brutos para ingerir + options = Map(String()) # Opciones específicas del formato +``` + +#### 2.2 Nuevo Servicio de Consulta Estructurada +Nuevo archivo: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # Contexto opcional para la generación de consulta + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # Consulta GraphQL generada + variables = Map(String()) # Variables de GraphQL si existen + detected_schemas = Array(String()) # Esquemas a los que apunta la consulta + confidence = Double() +``` + +#### 2.2 Servicio de Consulta Estructurada +Nuevo archivo: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # Consulta GraphQL + variables = Map(String()) # Variables de GraphQL + operation_name = String() # Nombre opcional de operación para documentos con múltiples operaciones + +class StructuredQueryResponse(Record): + error = Error() + data = String() # Datos de respuesta GraphQL codificados en JSON + errors = Array(String()) # Errores GraphQL si existen +``` + +#### 2.2 Salida de Extracción de Objetos +Nuevo archivo: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # Esquema al que pertenece este objeto + values = Map(String()) # Nombre del campo -> valor + confidence = Double() + source_span = String() # Rango de texto donde se encontró el objeto +``` + +### 4. Esquemas de Conocimiento Mejorados + +#### 4.1 Mejora en la Incorporación de Objetos +Actualiza `knowledge/embeddings.py` para soportar una mejor incorporación de objetos estructurados: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # Valor clave primaria + field_embeddings = Map(Array(Double())) # Incorporaciones por campo +``` + +## Puntos de Integración + +### Integración de Flujo + +Los esquemas se utilizarán en nuevos módulos de flujo: +- `trustgraph-flow/trustgraph/decoding/structured` - Utiliza StructuredDataSubmission +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - Utiliza esquemas de consulta NLP +- `trustgraph-flow/trustgraph/query/objects/cassandra` - Utiliza esquemas de consulta estructurada +- `trustgraph-flow/trustgraph/extract/object/row/` - Consumo de Chunk, produce ExtractedObject +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - Utiliza Esquema de Filas +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - Utiliza esquemas de incorporación de objetos + +## Notas de Implementación + +1. **Versionado del Esquema**: Considerar añadir un campo `version` al Esquema de Fila para soporte de migración futuro. +2. **Sistema de Tipos**: El `Field.type` debería soportar todos los tipos nativos de Cassandra. +3. **Operaciones en Lotes**: La mayoría de los servicios deben soportar tanto operaciones individuales como en lote. +4. **Manejo de Errores**: Reporte de errores consistente en todos los nuevos servicios. +5. **Compatibilidad hacia atrás**: Los esquemas existentes permanecen sin cambios, excepto por las pequeñas mejoras en los Campos. + +## Próximos Pasos + +1. Implementar los archivos de esquema en la nueva estructura. +2. Actualizar los servicios existentes para reconocer los nuevos tipos de esquema. +3. Implementar los módulos de flujo que utilicen estos esquemas. +4. Añadir puntos finales gateway/rev-gateway para los nuevos servicios. +5. Crear pruebas unitarias para la validación del esquema. diff --git a/docs/tech-specs/structured-data-schemas.he.md b/docs/tech-specs/structured-data-schemas.he.md new file mode 100644 index 00000000..b58dae70 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.he.md @@ -0,0 +1,147 @@ +--- +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. + +## סקירה כללית + +בהתבסס על מפרט ה-STRUCTURED_DATA.md, המסמך מציע את התוספות והשינויים הנדרשים בסכימת פולסר כדי לתמוך ביכולות נתונים מובנות ב-TrustGraph. + +## שינויים בסכימה נדרשים + +### 1. שיפורים בסכימה הליבה + +#### הגדרת שדה משופרת +המחלקה `Field` הקיימת בקובץ `core/primitives.py` זקוקה לתכונות נוספות: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # שדות חדשים: + required = Boolean() # האם השדה נדרש + enum_values = Array(String()) # עבור סוגי שדות enum + indexed = Boolean() # האם השדה צריך להיות מצביע +``` + +### 2. סכימות ידע חדשות + +#### 2.1 שליחת נתונים מובנים +קובץ חדש: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # הפניה לסכימה בקונפיגורציה + data = Bytes() # נתונים גולמיים לשליחה + options = Map(String()) # אפשרויות ספציפיות לפורמט +``` + +#### 3. סכימות שירות חדשות + +#### 3.1 שירות שאילתות NLP לנתונים מובנים +קובץ חדש: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # הקשר אופציונלי לשליפת שאילתה + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # שאילתת GraphQL שנוצרה + variables = Map(String()) # משתני GraphQL אם יש + detected_schemas = Array(String()) # אילו סכימות השאילתה מכוונות + confidence = Double() +``` + +#### 3.2 שירות שאילתות מובנות +קובץ חדש: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # שאילתת GraphQL + variables = Map(String()) # משתני GraphQL + operation_name = String() # שם פעולה אופציונלי למסמכים מרובי פעולות + +class StructuredQueryResponse(Record): + error = Error() + data = String() # נתוני התגובה של GraphQL מקודדים ב-JSON + errors = Array(String()) # שגיאות GraphQL אם יש +``` + +#### 2.2 פלט חילוץ אובייקטים +קובץ חדש: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # לאיזו סכימה השם הזה שייך + values = Map(String()) # שם שדה -> ערך + confidence = Double() + source_span = String() # טקסט השדה בו נמצא האובייקט +``` + +### 4. סכימות ידע משופרות + +#### 4.1 שיפור אמצעי הטבע +עדכן את `knowledge/embeddings.py` כדי לתמוך טוב יותר באמצעי הטבע מובנים: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # ערך מפתח ראשי + field_embeddings = Map(Array(Double())) # אמצעי הטבע לכל שדה +``` + +## נקודות אינטגרציה + +### אינטגרציה של זרימה + +הסכימות ישמשו על ידי מודולי זרימה חדשים: +- `trustgraph-flow/trustgraph/decoding/structured` - משתמש ב-StructuredDataSubmission +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - משתמש בסכימות שאילתות NLP +- `trustgraph-flow/trustgraph/query/objects/cassandra` - משתמש בסכימות שאילתות מובנות +- `trustgraph-flow/trustgraph/extract/object/row/` - צורך Chunk, מייצר ExtractedObject +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - משתמש בסכימה Rows +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - משתמש בסכימות אמצעי הטבע + +## הערות על יישום + +1. **גרסת סכימה**: כדאי להוסיף שדה `version` ל-RowSchema לתמיכה בעדכונים עתידיים. +2. **מערכת סוגים**: ה-`Field.type` צריך לתמוך בכל סוגי הנתונים המקוריים של Cassandra. +3. **פעולות אצווה**: רוב השירותים צריכים לתמוך הן בפעולות בודדות והן בפעולות אצווה. +4. **טיפול בשגיאות**: דיווח אחיד על שגיאות בכל השירותים החדשים. +5. **תאימות לאחור**: הסכימות הקיימות נשארות ללא שינוי, מלבד שיפורים קטנים בשדות. + +## שלבים הבאים + +1. יישום קבצי הסכימה במבנה החדש. +2. עדכון שירותים קיימים כדי לזהות סוגי סכימה חדשים. +3. יישום מודולי זרימה המשתמשים בסכימות אלה. +4. הוספת סיומות גשר/rev-גשר לשירותים החדשים. +5. יצירת בדיקות יחידה עבור אימות סכימה. diff --git a/docs/tech-specs/structured-data-schemas.hi.md b/docs/tech-specs/structured-data-schemas.hi.md new file mode 100644 index 00000000..ab1499a6 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.hi.md @@ -0,0 +1,147 @@ +--- +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. + +## अवलोकन + +`STRUCTURED_DATA.md` विनिर्देश के आधार पर, यह दस्तावेज़ आवश्यक पल्सर स्कीमा परिवर्धन और संशोधन प्रस्तावित करता है ताकि ट्रस्टग्राफ में संरचित डेटा क्षमताओं का समर्थन किया जा सके। + +## आवश्यक स्कीमा परिवर्तन + +### 1. कोर स्कीमा संवर्द्धन + +#### उन्नत फ़ील्ड परिभाषा +`core/primitives.py` में मौजूदा `Field` वर्ग में अतिरिक्त गुण होने चाहिए: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # नए फ़ील्ड: + required = Boolean() # क्या फ़ील्ड अनिवार्य है + enum_values = Array(String()) # एनम प्रकार के फ़ील्ड के लिए + indexed = Boolean() # क्या फ़ील्ड को अनुक्रमित किया जाना चाहिए +``` + +### 2. नई ज्ञान स्कीमा + +#### 2.1 संरचित डेटा सबमिशन +नई फ़ाइल: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # कॉन्फ़िगरेशन में स्कीमा का संदर्भ + data = Bytes() # संसाधित करने के लिए कच्चा डेटा + options = Map(String()) # प्रारूप-विशिष्ट विकल्प +``` + +### 3. नई सेवा स्कीमा + +#### 3.1 एनएलपी से संरचित क्वेरी सेवा +नई फ़ाइल: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # क्वेरी पीढ़ी के लिए वैकल्पिक संदर्भ + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # उत्पन्न ग्राफ़क्यूएल क्वेरी + variables = Map(String()) # यदि कोई हो तो ग्राफ़क्यूएल चर + detected_schemas = Array(String()) # कौन सी स्कीमा क्वेरी को लक्षित करती हैं + confidence = Double() +``` + +#### 3.2 संरचित क्वेरी सेवा +नई फ़ाइल: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # ग्राफ़क्यूएल क्वेरी + variables = Map(String()) # ग्राफ़क्यूएल चर + operation_name = String() # मल्टी-ऑपरेशन दस्तावेजों के लिए वैकल्पिक ऑपरेशन नाम + +class StructuredQueryResponse(Record): + error = Error() + data = String() # JSON-एन्कोडेड ग्राफ़क्यूएल प्रतिक्रिया डेटा + errors = Array(String()) # यदि कोई हो तो ग्राफ़क्यूएल त्रुटियां +``` + +#### 2.2 ऑब्जेक्ट निष्कर्षण आउटपुट +नई फ़ाइल: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # यह ऑब्जेक्ट किस स्कीमा से संबंधित है + values = Map(String()) # फ़ील्ड नाम -> मान + confidence = Double() + source_span = String() # पाठ का वह भाग जहां ऑब्जेक्ट पाया गया था +``` + +### 4. उन्नत ज्ञान स्कीमा + +#### 4.1 ऑब्जेक्ट एम्बेडिंग संवर्द्धन +संरचित ऑब्जेक्ट एम्बेडिंग को बेहतर ढंग से समर्थन करने के लिए `knowledge/embeddings.py` को अपडेट करें: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # प्राथमिक कुंजी मान + field_embeddings = Map(Array(Double())) # प्रति-फ़ील्ड एम्बेडिंग +``` + +## एकीकरण बिंदु + +### फ्लो एकीकरण + +इन स्कीमा का उपयोग नए फ्लो मॉड्यूल द्वारा किया जाएगा: +- `trustgraph-flow/trustgraph/decoding/structured` - `StructuredDataSubmission` का उपयोग करता है +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - एनएलपी क्वेरी स्कीमा का उपयोग करता है +- `trustgraph-flow/trustgraph/query/objects/cassandra` - संरचित क्वेरी स्कीमा का उपयोग करता है +- `trustgraph-flow/trustgraph/extract/object/row/` - `Chunk` का उपभोग करता है, `ExtractedObject` उत्पन्न करता है +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - `Rows` स्कीमा का उपयोग करता है +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - ऑब्जेक्ट एम्बेडिंग स्कीमा का उपयोग करता है + +## कार्यान्वयन नोट्स + +1. **स्कीमा संस्करण:** भविष्य के माइग्रेशन समर्थन के लिए `RowSchema` में एक `version` फ़ील्ड जोड़ने पर विचार करें। +2. **प्रकार प्रणाली:** `Field.type` को सभी कैसेंड्रा मूल प्रकारों का समर्थन करना चाहिए। +3. **बैच ऑपरेशन:** अधिकांश सेवाओं को एकल और बैच दोनों ऑपरेशन का समर्थन करना चाहिए। +4. **त्रुटि प्रबंधन:** सभी नई सेवाओं में सुसंगत त्रुटि रिपोर्टिंग। +5. **पिछड़ा संगतता:** मौजूदा स्कीमा अपरिवर्तित रहते हैं, केवल छोटे फ़ील्ड संवर्द्धन को छोड़कर। + +## अगले कदम + +1. नई संरचना में स्कीमा फ़ाइलें लागू करें। +2. मौजूदा सेवाओं को नए स्कीमा प्रकारों को पहचानने के लिए अपडेट करें। +3. इन स्कीमा का उपयोग करने वाले फ्लो मॉड्यूल लागू करें। +4. नई सेवाओं के लिए गेटवे/रिवर्स-गेटवे एंडपॉइंट बनाएं। +5. स्कीमा सत्यापन के लिए यूनिट परीक्षण बनाएं। diff --git a/docs/tech-specs/structured-data-schemas.md b/docs/tech-specs/structured-data-schemas.md index 1e758e10..2a31d5cc 100644 --- a/docs/tech-specs/structured-data-schemas.md +++ b/docs/tech-specs/structured-data-schemas.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Structured Data Pulsar Schema Changes" +parent: "Tech Specs" +--- + # Structured Data Pulsar Schema Changes ## Overview diff --git a/docs/tech-specs/structured-data-schemas.pt.md b/docs/tech-specs/structured-data-schemas.pt.md new file mode 100644 index 00000000..e5f8dba3 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.pt.md @@ -0,0 +1,147 @@ +--- +layout: default +title: "Alterações no Esquema Pulsar para Dados Estruturados" +parent: "Portuguese (Beta)" +--- + +# Alterações no Esquema Pulsar para Dados Estruturados + +> **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 + +Com base na especificação STRUCTURED_DATA.md, este documento propõe as adições e modificações necessárias no esquema Pulsar para suportar as capacidades de dados estruturados no TrustGraph. + +## Alterações Necessárias no Esquema + +### 1. Melhorias no Esquema Principal + +#### Definição de Campo Aprimorada +A classe `Field` existente em `core/primitives.py` precisa de propriedades adicionais: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # NEW FIELDS: + required = Boolean() # Whether field is required + enum_values = Array(String()) # For enum type fields + indexed = Boolean() # Whether field should be indexed +``` + +### 2. Novos Esquemas de Conhecimento + +#### 2.1 Submissão de Dados Estruturados +Novo arquivo: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # Reference to schema in config + data = Bytes() # Raw data to ingest + options = Map(String()) # Format-specific options +``` + +### 3. Novos Esquemas de Serviço + +#### 3.1 Serviço de Consulta Estruturada a partir de Processamento de Linguagem Natural +Novo arquivo: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # Optional context for query generation + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # Generated GraphQL query + variables = Map(String()) # GraphQL variables if any + detected_schemas = Array(String()) # Which schemas the query targets + confidence = Double() +``` + +#### 3.2 Serviço de Consulta Estruturada +Novo arquivo: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # GraphQL query + variables = Map(String()) # GraphQL variables + operation_name = String() # Optional operation name for multi-operation documents + +class StructuredQueryResponse(Record): + error = Error() + data = String() # JSON-encoded GraphQL response data + errors = Array(String()) # GraphQL errors if any +``` + +#### 2.2 Saída da Extração de Objetos +Novo arquivo: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # Which schema this object belongs to + values = Map(String()) # Field name -> value + confidence = Double() + source_span = String() # Text span where object was found +``` + +### 4. Esquemas de Conhecimento Aprimorados + +#### 4.1 Aprimoramento de Incorporações de Objetos +Atualizar `knowledge/embeddings.py` para oferecer melhor suporte a incorporações de objetos estruturadas: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # Primary key value + field_embeddings = Map(Array(Double())) # Per-field embeddings +``` + +## Pontos de Integração + +### Integração de Fluxo + +Os esquemas serão usados por novos módulos de fluxo: +`trustgraph-flow/trustgraph/decoding/structured` - Usa StructuredDataSubmission +`trustgraph-flow/trustgraph/query/nlp_query/cassandra` - Usa esquemas de consulta NLP +`trustgraph-flow/trustgraph/query/objects/cassandra` - Usa esquemas de consulta estruturados +`trustgraph-flow/trustgraph/extract/object/row/` - Consome Chunk, produz ExtractedObject +`trustgraph-flow/trustgraph/storage/objects/cassandra` - Usa o esquema Rows +`trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - Usa esquemas de incorporação de objetos + +## Notas de Implementação + +1. **Versionamento de Esquemas**: Considere adicionar um campo `version` em RowSchema para suporte futuro de migração. +2. **Sistema de Tipos**: O `Field.type` deve suportar todos os tipos nativos do Cassandra. +3. **Operações em Lote**: A maioria dos serviços deve suportar operações individuais e em lote. +4. **Tratamento de Erros**: Relatório de erros consistente em todos os novos serviços. +5. **Compatibilidade com Versões Anteriores**: Os esquemas existentes permanecem inalterados, exceto por pequenos aprimoramentos de campos. + +## Próximos Passos + +1. Implementar os arquivos de esquema na nova estrutura. +2. Atualizar os serviços existentes para reconhecer os novos tipos de esquema. +3. Implementar módulos de fluxo que usem esses esquemas. +4. Adicionar endpoints de gateway/rev-gateway para novos serviços. +5. Criar testes unitários para validação de esquema. diff --git a/docs/tech-specs/structured-data-schemas.ru.md b/docs/tech-specs/structured-data-schemas.ru.md new file mode 100644 index 00000000..9f238339 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.ru.md @@ -0,0 +1,147 @@ +--- +layout: default +title: "Структурированные данные Pulsar: Изменения схемы" +parent: "Russian (Beta)" +--- + +# Структурированные данные Pulsar: Изменения схемы + +> **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. + +## Обзор + +На основе спецификации `STRUCTURED_DATA.md`, этот документ предлагает необходимые дополнения и изменения схемы Pulsar для поддержки возможностей работы со структурированными данными в TrustGraph. + +## Необходимые изменения схемы + +### 1. Улучшения основной схемы + +#### Улучшенное определение поля +Сущность `Field` в файле `core/primitives.py` требует дополнительных свойств: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # НОВЫЕ ПОЛЯ: + required = Boolean() # Требуется ли поле + enum_values = Array(String()) # Для полей типа enum + indexed = Boolean() # Нужно ли индексировать поле +``` + +### 2. Новые схемы знаний + +#### 2.1 Отправка структурированных данных +Новый файл: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # Ссылка на схему в конфигурации + data = Bytes() # Сырые данные для обработки + options = Map(String()) # Опции, специфичные для формата +``` + +#### 2.2 Структурированный запрос + +#### 3.1 Преобразование NLP в структурированный запрос +Новый файл: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # Дополнительный контекст для генерации запроса + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # Сгенерированный GraphQL запрос + variables = Map(String()) # Переменные GraphQL, если есть + detected_schemas = Array(String()) # Какие схемы затрагивает запрос + confidence = Double() +``` + +#### 3.2 Структурированный запрос +Новый файл: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # GraphQL запрос + variables = Map(String()) # Переменные GraphQL + operation_name = String() # Дополнительное имя операции для документов с несколькими операциями + +class StructuredQueryResponse(Record): + error = Error() + data = String() # JSON-кодированный формат данных GraphQL + errors = Array(String()) # Ошибки GraphQL, если есть +``` + +#### 2.2 Вывод извлечения объектов +Новый файл: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # Какая схема принадлежит этому объекту + values = Map(String()) # Имя поля -> значение + confidence = Double() + source_span = String() # Текстовый фрагмент, где был найден объект +``` + +### 4. Улучшенные схемы знаний + +#### 4.1 Улучшение встраивания объектов +Обновите `knowledge/embeddings.py` для лучшей поддержки встраивания структурированных объектов: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # Основной ключ + field_embeddings = Map(Array(Double())) # Встраивание для каждого поля +``` + +## Точки интеграции + +### Интеграция потоков + +Схемы будут использоваться в новых модулях потоков: +- `trustgraph-flow/trustgraph/decoding/structured` - Использует StructuredDataSubmission +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - Использует схемы запросов NLP +- `trustgraph-flow/trustgraph/query/objects/cassandra` - Использует схемы структурированных запросов +- `trustgraph-flow/trustgraph/extract/object/row/` - Потребляет Chunk, производит ExtractedObject +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - Использует схему Rows +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - Использует схемы встраивания объектов + +## Примечания по реализации + +1. **Версионирование схемы**: Рассмотрите возможность добавления поля `version` к схеме RowSchema для поддержки будущих миграций. +2. **Система типов**: `Field.type` должна поддерживать все родные типы Cassandra. +3. **Операции пакета**: Большинство сервисов должны поддерживать как одиночные, так и пакетные операции. +4. **Обработка ошибок**: Необходимо обеспечить единообразное сообщение об ошибках во всех новых сервисах. +5. **Совместимость с существующими схемами**: Существующие схемы остаются неизменными, за исключением незначительных улучшений поля. + +## Следующие шаги + +1. Реализуйте файлы схем в новой структуре. +2. Обновите существующие сервисы для распознавания новых типов схем. +3. Реализуйте модули потоков, использующие эти схемы. +4. Добавьте конечные точки gateway/rev-gateway для новых сервисов. +5. Создайте модульные тесты для проверки схемы. diff --git a/docs/tech-specs/structured-data-schemas.sw.md b/docs/tech-specs/structured-data-schemas.sw.md new file mode 100644 index 00000000..18c6a1be --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.sw.md @@ -0,0 +1,130 @@ +--- +layout: default +title: "Mfano wa Data, Mbadala ya Pulsar" +parent: "Swahili (Beta)" +--- + +# Mfano wa Data, Mbadala ya Pulsar + +> **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. + +## Maelezo + +Kulingana na toleo la `STRUCTURED_DATA.md`, hati hii inatoa mabadiliko muhimu ya mfano wa Pulsar na mabadiliko, ili kupendeza uwezo wa data iliyoundwa katika TrustGraph. + +## Mabadiliko muhimu ya mfano + +### 1. Uboreshaji wa mfano +#### Maelezo ya shamba +Sasa, kwenye `Field` class katika `core/primitives.py`, lazima ipate mali zaidi: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # MAELEZO MPYA: + required = Boolean() # Mara kama shamba ni muhimu + enum_values = Array(String()) # Kwa miundo ya shamba + indexed = Boolean() # Mara kama shamba linahitajika +``` + +### 2. Mfano mpya wa Maarifa + +#### 2.1 Utumaji Data Iliyoundwa +Faili mpya: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # Mara kama mfano katika faili + data = Bytes() # Data iliyoundwa + options = Map(String()) # Chaguzi maalum kwa format +``` + +### 3. Mfano mpya wa Huduma + +#### 3.1 Huduma ya NLP hadi Sarani ya Data +Faili mpya: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # Mara kama mawasiliano kwa utengenezaji wa sarani + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # Sarani GraphQL iliyoundwa + variables = Map(String()) # Chaguzi GraphQL + detected_schemas = Array(String()) # Miundo ambazo sarani huangalia + confidence = Double() +``` + +#### 3.2 Sarani ya Data +Faili mpya: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # Sarani GraphQL + variables = Map(String()) # Chaguzi GraphQL + operation_name = String() # Mara kama jina la operesheni kwa hati za mfululizo + +class StructuredQueryResponse(Record): + error = Error() + data = String() # Data iliyoundwa kwa JSON + errors = Array(String()) # Mara kama ada GraphQL +``` + +#### 2.2 Pato la Uteuzi wa Madhara +Faili mpya: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # Mara kama mfano + values = Map(String()) # Jina la shamba -> thamani + confidence = Double() + source_span = String() # Mara kama kitanzi +``` + +### 4. Mfano wa Maarifa + +#### 4.1 Uboreshaji wa Embedings +Badilisha `knowledge/embeddings.py` ili kusaidia uhifadhi wa madhara iliyoundwa: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # Thamani muhimu + field_embeddings = Map(Array(Double())) # Embedings kwa kila shamba +``` + +## Vitu vya Uunganishi + +### Uunganishi wa Mzunguko + +Mifano itatumika na moduli mpya za mzunguko: +- `trustgraph-flow/trustgraph/decoding/structured` - Inatumia StructuredDataSubmission +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - Inatumia mifano za sarani +- `trustgraph-flow/trustgraph/query/objects/cassandra` - Inatumia mifano za sarani +- `trustgraph-flow/trustgraph/extract/object/row/` - Inatumia Chunk, inatoa ExtractedObject +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - Inatumia mfano wa Rows +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - Inatumia mifano za embedings diff --git a/docs/tech-specs/structured-data-schemas.tr.md b/docs/tech-specs/structured-data-schemas.tr.md new file mode 100644 index 00000000..02670993 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.tr.md @@ -0,0 +1,147 @@ +--- +layout: default +title: "Yapılandırılmış Veri Pulsar Şema Değişiklikleri" +parent: "Turkish (Beta)" +--- + +# Yapılandırılmış Veri Pulsar Şema Değişiklikleri + +> **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ış + +STRUCTURED_DATA.md spesifikasyonuna dayanarak, bu belge, TrustGraph'ta yapılandırılmış veri yeteneklerini desteklemek için gerekli olan Pulsar şema eklemelerini ve değişikliklerini önermektedir. + +## Gerekli Şema Değişiklikleri + +### 1. Temel Şema Geliştirmeleri + +#### Gelişmiş Alan Tanımı +`core/primitives.py` içindeki mevcut `Field` sınıfı, ek özelliklere ihtiyaç duymaktadır: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # NEW FIELDS: + required = Boolean() # Whether field is required + enum_values = Array(String()) # For enum type fields + indexed = Boolean() # Whether field should be indexed +``` + +### 2. Yeni Bilgi Şemaları + +#### 2.1 Yapılandırılmış Veri Gönderimi +Yeni dosya: `knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # Reference to schema in config + data = Bytes() # Raw data to ingest + options = Map(String()) # Format-specific options +``` + +### 3. Yeni Hizmet Şemaları + +#### 3.1 Doğal Dil İşleme'den Yapılandırılmış Sorgu Hizmeti +Yeni dosya: `services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # Optional context for query generation + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # Generated GraphQL query + variables = Map(String()) # GraphQL variables if any + detected_schemas = Array(String()) # Which schemas the query targets + confidence = Double() +``` + +#### 3.2 Yapılandırılmış Sorgu Hizmeti +Yeni dosya: `services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # GraphQL query + variables = Map(String()) # GraphQL variables + operation_name = String() # Optional operation name for multi-operation documents + +class StructuredQueryResponse(Record): + error = Error() + data = String() # JSON-encoded GraphQL response data + errors = Array(String()) # GraphQL errors if any +``` + +#### 2.2 Nesne Çıkarımı Çıktısı +Yeni dosya: `knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # Which schema this object belongs to + values = Map(String()) # Field name -> value + confidence = Double() + source_span = String() # Text span where object was found +``` + +### 4. Gelişmiş Bilgi Şemaları + +#### 4.1 Nesne Gömme İyileştirmeleri +`knowledge/embeddings.py`'ı, yapılandırılmış nesne gömmelerini daha iyi destekleyecek şekilde güncelleyin: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # Primary key value + field_embeddings = Map(Array(Double())) # Per-field embeddings +``` + +## Entegrasyon Noktaları + +### Akış Entegrasyonu + +Bu şemalar, yeni akış modülleri tarafından kullanılacaktır: +`trustgraph-flow/trustgraph/decoding/structured` - StructuredDataSubmission'ı kullanır +`trustgraph-flow/trustgraph/query/nlp_query/cassandra` - NLP sorgu şemalarını kullanır +`trustgraph-flow/trustgraph/query/objects/cassandra` - Yapılandırılmış sorgu şemalarını kullanır +`trustgraph-flow/trustgraph/extract/object/row/` - Chunk'ı tüketir, ExtractedObject üretir +`trustgraph-flow/trustgraph/storage/objects/cassandra` - Rows şemasını kullanır +`trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - Nesne gömme şemalarını kullanır + +## Uygulama Notları + +1. **Şema Sürümleme**: Gelecekteki geçiş desteği için RowSchema'ya bir `version` alanı eklemeyi düşünün. +2. **Tip Sistemi**: `Field.type`, tüm Cassandra yerel türlerini desteklemelidir. +3. **Toplu İşlemler**: Çoğu hizmet, hem tekil hem de toplu işlemleri desteklemelidir. +4. **Hata Yönetimi**: Tüm yeni hizmetlerde tutarlı hata raporlama. +5. **Geriye Uyumluluk**: Mevcut şemalar, küçük alan geliştirmeleri dışında değişmeden kalacaktır. + +## Sonraki Adımlar + +1. Şema dosyalarını yeni yapıya göre uygulayın. +2. Mevcut hizmetleri, yeni şema türlerini tanıyacak şekilde güncelleyin. +3. Bu şemaları kullanan akış modüllerini uygulayın. +4. Yeni hizmetler için ağ geçidi/geri ağ geçidi uç noktaları ekleyin. +5. Şema doğrulaması için birim testleri oluşturun. diff --git a/docs/tech-specs/structured-data-schemas.zh-cn.md b/docs/tech-specs/structured-data-schemas.zh-cn.md new file mode 100644 index 00000000..c351d5a1 --- /dev/null +++ b/docs/tech-specs/structured-data-schemas.zh-cn.md @@ -0,0 +1,147 @@ +--- +layout: default +title: "结构化数据 Pulsar 模式更改" +parent: "Chinese (Beta)" +--- + +# 结构化数据 Pulsar 模式更改 + +> **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. + +## 概述 + +根据 `STRUCTURED_DATA.md` 规范,本文件提出必要的 Pulsar 模式添加和修改,以支持 TrustGraph 中的结构化数据功能。 + +## 必需的模式更改 + +### 1. 核心模式增强 + +#### 增强的字段定义 +现有的 `Field` 类在 `core/primitives.py` 中需要额外的属性: + +```python +class Field(Record): + name = String() + type = String() # int, string, long, bool, float, double, timestamp + size = Integer() + primary = Boolean() + description = String() + # 新字段: + required = Boolean() # 字段是否必需 + enum_values = Array(String()) # 针对枚举类型的字段 + indexed = Boolean() # 字段是否应进行索引 +``` + +### 2. 新的知识模式 + +#### 2.1 结构化数据提交 +新的文件:`knowledge/structured.py` + +```python +from pulsar.schema import Record, String, Bytes, Map +from ..core.metadata import Metadata + +class StructuredDataSubmission(Record): + metadata = Metadata() + format = String() # "json", "csv", "xml" + schema_name = String() # 引用配置中的模式 + data = Bytes() # 原始数据,用于导入 + options = Map(String()) # 格式特定的选项 +``` + +#### 2.2 结构化查询模式 + +#### 3.1 NLP 到结构化查询服务 +新的文件:`services/nlp_query.py` + +```python +from pulsar.schema import Record, String, Array, Map, Integer, Double +from ..core.primitives import Error + +class NLPToStructuredQueryRequest(Record): + natural_language_query = String() + max_results = Integer() + context_hints = Map(String()) # 针对查询生成的可选上下文 + +class NLPToStructuredQueryResponse(Record): + error = Error() + graphql_query = String() # 生成的 GraphQL 查询 + variables = Map(String()) # 如果有的话,GraphQL 变量 + detected_schemas = Array(String()) # 查询的目标模式 + confidence = Double() +``` + +#### 3.2 结构化查询服务 +新的文件:`services/structured_query.py` + +```python +from pulsar.schema import Record, String, Map, Array +from ..core.primitives import Error + +class StructuredQueryRequest(Record): + query = String() # GraphQL 查询 + variables = Map(String()) # GraphQL 变量 + operation_name = String() # 针对多操作文档的可选操作名称 + +class StructuredQueryResponse(Record): + error = Error() + data = String() # JSON 编码的 GraphQL 响应数据 + errors = Array(String()) # 如果有的话,GraphQL 错误 +``` + +#### 2.2 对象提取输出 +新的文件:`knowledge/object.py` + +```python +from pulsar.schema import Record, String, Map, Double +from ..core.metadata import Metadata + +class ExtractedObject(Record): + metadata = Metadata() + schema_name = String() # 此对象属于哪个模式 + values = Map(String()) # 字段名称 -> 值 + confidence = Double() + source_span = String() # 对象所在的文本范围 +``` + +### 4. 增强的知识模式 + +#### 4.1 对象嵌入增强 +更新 `knowledge/embeddings.py` 以更好地支持结构化对象嵌入: + +```python +class StructuredObjectEmbedding(Record): + metadata = Metadata() + vectors = Array(Array(Double())) + schema_name = String() + object_id = String() # 主键值 + field_embeddings = Map(Array(Double())) # 针对每个字段的嵌入 +``` + +## 集成点 + +### 流集成 + +这些模式将由新的流模块使用: +- `trustgraph-flow/trustgraph/decoding/structured` - 使用 StructuredDataSubmission +- `trustgraph-flow/trustgraph/query/nlp_query/cassandra` - 使用 NLP 查询模式 +- `trustgraph-flow/trustgraph/query/objects/cassandra` - 使用结构化查询模式 +- `trustgraph-flow/trustgraph/extract/object/row/` - 消耗 Chunk,产生 ExtractedObject +- `trustgraph-flow/trustgraph/storage/objects/cassandra` - 使用 Rows 模式 +- `trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant` - 使用对象嵌入模式 + +## 实现说明 + +1. **模式版本控制**: 考虑为 RowSchema 添加 `version` 字段,以便进行未来迁移支持 +2. **类型系统**: `Field.type` 应该支持所有 Cassandra 原生类型 +3. **批量操作**: 大多数服务都应该支持单个和批量操作 +4. **错误处理**: 所有新服务的错误报告应保持一致 +5. **向后兼容性**: 现有的模式不受影响,只有字段进行了轻微增强 + +## 接下来要做的事 + +1. 在新的结构中实现模式文件 +2. 更新现有服务以识别新的模式类型 +3. 实现使用这些模式的流模块 +4. 为新的服务添加网关/反向网关端点 +5. 创建模式验证的单元测试 diff --git a/docs/tech-specs/structured-data.ar.md b/docs/tech-specs/structured-data.ar.md new file mode 100644 index 00000000..4ffe60f9 --- /dev/null +++ b/docs/tech-specs/structured-data.ar.md @@ -0,0 +1,260 @@ +--- +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. +**تكامل سلس**: تمكين التوافق السلس بين تمثيل المعرفة القائم على الرسم البياني في TrustGraph وتنسيقات البيانات المهيكلة التقليدية. +**استخراج مرن**: دعم الاستخراج التلقائي للبيانات المهيكلة من مصادر غير مهيكلة متنوعة (المستندات، والنصوص، وما إلى ذلك). +**تنوع الاستعلام**: السماح للمستخدمين بالاستعلام عن البيانات باستخدام كل من اللغة الطبيعية ولغات الاستعلام المهيكلة. +**اتساق البيانات**: الحفاظ على سلامة البيانات واتساقها عبر تمثيلات البيانات المختلفة. +**تحسين الأداء**: ضمان تخزين واسترجاع فعال للبيانات المهيكلة على نطاق واسع. +**مرونة المخطط**: دعم كل من مناهج "المخطط عند الكتابة" و "المخطط عند القراءة" لاستيعاب مصادر البيانات المتنوعة. +**التوافق مع الإصدارات السابقة**: الحفاظ على وظائف TrustGraph الحالية مع إضافة إمكانات البيانات المهيكلة. + +## الخلفية + +تتفوق TrustGraph حاليًا في معالجة البيانات غير المهيكلة وإنشاء الرسوم البيانية المعرفية من مصادر متنوعة. ومع ذلك، تتضمن العديد من حالات الاستخدام في المؤسسات بيانات مهيكلة بشكل متأصل - سجلات العملاء، وسجلات المعاملات، وقواعد بيانات المخزون، ومجموعات بيانات جدولية أخرى. غالبًا ما تحتاج هذه مجموعات البيانات المهيكلة إلى تحليلها جنبًا إلى جنب مع المحتوى غير المهيكل لتقديم رؤى شاملة. + +القيود الحالية تشمل: +لا يوجد دعم أصلي لاستيعاب تنسيقات البيانات المهيكلة مسبقًا (CSV، ومصفوفات JSON، وتصديرات قواعد البيانات). +عدم القدرة على الحفاظ على الهيكل المتأصل عند استخراج البيانات الجدولية من المستندات. +عدم وجود آليات استعلام فعالة لأنماط البيانات المهيكلة. +عدم وجود جسر بين استعلامات تشبه SQL واستعلامات الرسم البياني في TrustGraph. + +تعالج هذه المواصفات هذه الفجوات من خلال تقديم طبقة بيانات مهيكلة تكمل إمكانات TrustGraph الحالية. من خلال دعم البيانات المهيكلة أصلاً، يمكن لـ TrustGraph: +أن تكون منصة موحدة لتحليل كل من البيانات المهيكلة وغير المهيكلة. +تمكين الاستعلامات الهجينة التي تمتد عبر علاقات الرسم البياني والبيانات الجدولية. +توفير واجهات مألوفة للمستخدمين الذين اعتادوا العمل مع البيانات المهيكلة. +إطلاق حالات استخدام جديدة في تكامل البيانات وذكاء الأعمال. + +## التصميم الفني + +### البنية + +يتطلب تكامل البيانات المهيكلة المكونات الفنية التالية: + +1. **خدمة NLP-to-Structured-Query** + تحويل الأسئلة باللغة الطبيعية إلى استعلامات مهيكلة. + يدعم أهداف لغة استعلام متعددة (في البداية بناء الجملة المشابه لـ SQL). + يتكامل مع إمكانات NLP الحالية في TrustGraph. + + الوحدة: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **دعم مخطط التكوين** ✅ **[مكتمل]** + نظام تكوين موسع لتخزين مخططات البيانات المهيكلة. + دعم لتعريف هياكل الجداول وأنواع الحقول والعلاقات. + إمكانيات إصدار وترحيل المخططات. + +3. **وحدة استخراج الكائنات** ✅ **[مكتمل]** + تكامل محسن لتدفق استخراج المعرفة. + تحديد واستخراج كائنات مهيكلة من مصادر غير مهيكلة. + الحفاظ على الأصل ودرجات الثقة. + يسجل معالج تكوين (مثال: trustgraph-flow/trustgraph/prompt/template/service.py) لتلقي بيانات التكوين وفك تشفير معلومات المخطط. + يتلقى الكائنات ويفك تشفيرها إلى كائنات ExtractedObject للتسليم على قائمة الانتظار Pulsar. + ملاحظة: يوجد رمز موجود في `trustgraph-flow/trustgraph/extract/object/row/`. كان هذا محاولة سابقة وسيتطلب إعادة هيكلة كبيرة لأنه لا يتوافق مع واجهات برمجة التطبيقات الحالية. استخدمه إذا كان مفيدًا، وابدأ من البداية إذا لم يكن كذلك. + يتطلب واجهة سطر أوامر: `kg-extract-objects` + + الوحدة: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **وحدة كاتب المتجر المهيكل** ✅ **[مكتمل]** + يتلقى الكائنات بتنسيق ExtractedObject من قوائم انتظار Pulsar. + التنفيذ الأولي يستهدف Apache Cassandra كمتجر البيانات المهيكل. + يتعامل مع إنشاء الجداول الديناميكي بناءً على المخططات التي تمت مواجهتها. + يدير تعيين المخطط إلى جدول Cassandra وتحويل البيانات. + يوفر عمليات كتابة مجمعة وتدفق لتحسين الأداء. + لا توجد مخرجات Pulsar - هذه خدمة نهائية في تدفق البيانات. + + **معالجة المخططات**: + يراقب رسائل ExtractedObject الواردة للإشارة إلى المخططات. + عندما يتم مواجهة مخطط جديد لأول مرة، يقوم تلقائيًا بإنشاء جدول Cassandra المقابل. + يحتفظ بخزنة للمخططات المعروفة لتجنب محاولات إنشاء جداول متكررة. + يجب أن تأخذ في الاعتبار ما إذا كان سيتم تلقي تعريفات المخططات مباشرة أو الاعتماد على أسماء المخططات في رسائل ExtractedObject. + + **ربط جدول Cassandra**: + يتم تسمية مساحة المفاتيح (Keyspace) بناءً على الحقل `user` من بيانات التعريف (Metadata) الخاصة بـ ExtractedObject. + يتم تسمية الجدول بناءً على الحقل `schema_name` الخاص بـ ExtractedObject. + تصبح المجموعة (Collection) من بيانات التعريف جزءًا من مفتاح التقسيم (partition key) لضمان: + توزيع البيانات بشكل طبيعي عبر عقد Cassandra. + استعلامات فعالة داخل مجموعة معينة. + عزل منطقي بين عمليات استيراد البيانات/المصادر المختلفة. + هيكل المفتاح الأساسي: `PRIMARY KEY ((collection, ), )`. + تكون المجموعة دائمًا المكون الأول من مفتاح التقسيم. + تتبع حقول المفتاح الأساسي المعرفة في المخطط (schema) كجزء من مفتاح التقسيم المركب. + يتطلب هذا تحديد المجموعة في الاستعلامات، مما يضمن أداءً متوقعًا. + يتم تعيين تعريفات الحقول إلى أعمدة Cassandra مع تحويلات الأنواع: + `string` → `text`. + `integer` → `int` أو `bigint` بناءً على تلميح الحجم. + `float` → `float` أو `double` بناءً على احتياجات الدقة. + `boolean` → `boolean`. + `timestamp` → `timestamp`. + `enum` → `text` مع التحقق من الصحة على مستوى التطبيق. + تقوم الحقول المفهرسة بإنشاء فهارس ثانوية لـ Cassandra (باستثناء الحقول الموجودة بالفعل في المفتاح الأساسي). + يتم فرض الحقول المطلوبة على مستوى التطبيق (لا تدعم Cassandra NOT NULL). + + **تخزين الكائنات (Object Storage)**: + يستخرج القيم من خريطة ExtractedObject.values. + يقوم بتحويل النوع والتحقق من الصحة قبل الإدراج. + يتعامل مع الحقول الاختيارية المفقودة بأمان. + يحتفظ ببيانات وصفية حول أصل الكائن (مستند المصدر، درجات الثقة). + يدعم عمليات الكتابة المتطابقة (idempotent writes) للتعامل مع سيناريوهات إعادة إرسال الرسائل. + + **ملاحظات التنفيذ**: + الكود الحالي الموجود في `trustgraph-flow/trustgraph/storage/objects/cassandra/` قديم ولا يتوافق مع واجهات برمجة التطبيقات (APIs) الحالية. + يجب الرجوع إلى `trustgraph-flow/trustgraph/storage/triples/cassandra` كمثال على معالج تخزين يعمل. + يجب تقييم الكود الحالي بحثًا عن أي مكونات قابلة لإعادة الاستخدام قبل اتخاذ قرار بإعادة هيكلة أو إعادة كتابة. + + الوحدة: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **خدمة الاستعلامات المهيكلة** ✅ **[مكتمل]** + تقبل استعلامات مهيكلة بتنسيقات محددة. + تنفذ الاستعلامات على المستودع المهيكل. + تُرجع الكائنات التي تتطابق مع معايير الاستعلام. + تدعم التقسيم والترشيح للنتائج. + + الوحدة: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **تكامل أدوات الوكيل (Agent Tool Integration)** + فئة أداة جديدة لأطر عمل الوكيل. + تمكن الوكلاء من الاستعلام عن مستودعات البيانات المهيكلة. + توفر واجهات استعلام باللغة الطبيعية والمهيكلة. + تتكامل مع عمليات اتخاذ القرار الحالية للوكلاء. + +7. **خدمة استيعاب البيانات المهيكلة** + تقبل بيانات مهيكلة بتنسيقات متعددة (JSON، CSV، XML). + تقوم بتحليل والتحقق من صحة البيانات الواردة مقابل المخططات المحددة. + تحول البيانات إلى تدفقات كائنات مُنظمة. + تُصدر الكائنات إلى قوائم انتظار الرسائل المناسبة للمعالجة. + تدعم عمليات التحميل المجمعة والاستيعاب المتدفق. + + الوحدة: trustgraph-flow/trustgraph/decoding/structured + +8. **خدمة تضمين الكائنات (Object Embedding Service)** + تولد تضمينات متجهة للكائنات المهيكلة. + تمكن البحث الدلالي عبر البيانات المهيكلة. + تدعم البحث الهجين الذي يجمع بين الاستعلامات المهيكلة والتشابه الدلالي. + تتكامل مع مخازن المتجهات الحالية. + + الوحدة: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### نماذج البيانات + +#### آلية تخزين المخططات + +يتم تخزين المخططات في نظام تكوين TrustGraph باستخدام الهيكل التالي: + +**النوع (Type)**: `schema` (قيمة ثابتة لجميع مخططات البيانات المهيكلة). +**المفتاح (Key)**: الاسم/المعرف الفريد للمخطط (مثل `customer_records`، `transaction_log`). +**القيمة (Value)**: تعريف مخطط JSON يحتوي على الهيكل. + +مثال على إدخال التكوين: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +هذا النهج يسمح بما يلي: +تعريف مخطط ديناميكي دون تغييرات في التعليمات البرمجية +تحديثات سهلة للمخططات وإصداراتها +تكامل متسق مع إدارة التكوين الحالية لـ TrustGraph +دعم مخططات متعددة داخل عملية نشر واحدة + +### واجهات برمجة التطبيقات (APIs) + +واجهات برمجة تطبيقات جديدة: + مخططات Pulsar للأنواع المذكورة أعلاه + واجهات Pulsar في التدفقات الجديدة + هناك حاجة إلى وسيلة لتحديد أنواع المخططات في التدفقات حتى تعرف التدفقات + أنواع المخططات التي يجب تحميلها + تمت إضافة واجهات برمجة تطبيقات إلى البوابة والبوابة العكسية + +واجهات برمجة تطبيقات معدلة: +نقاط نهاية استخراج المعرفة - إضافة خيار إخراج كائن منظم +نقاط نهاية الوكيل - إضافة دعم لأدوات البيانات المنظمة + +### تفاصيل التنفيذ + +باتباع الاتفاقيات الحالية - هذه مجرد وحدات معالجة جديدة. +كل شيء موجود في حزم trustgraph-flow باستثناء عناصر المخطط +الموجودة في trustgraph-base. + +هناك حاجة إلى بعض الأعمال لواجهة المستخدم في Workbench لتمكين عرض / تجربة هذه +الإمكانية. + +## اعتبارات الأمان + +لا توجد اعتبارات إضافية. + +## اعتبارات الأداء + +بعض الأسئلة حول استخدام استعلامات وفهارس Cassandra بحيث لا تبطئ الاستعلامات. + +## استراتيجية الاختبار + +استخدم استراتيجية الاختبار الحالية، سيتم إنشاء اختبارات الوحدة والاتفاقية والتكامل. + +## خطة الترحيل + +لا يوجد. + +## الجدول الزمني + + +لم يتم تحديده. + +## أسئلة مفتوحة + +هل يمكن جعل هذا يعمل مع أنواع تخزين أخرى؟ نحن نهدف إلى استخدام + واجهات تجعل الوحدات التي تعمل مع تخزين واحد قابلة للتطبيق على + تخزين آخر. + +## المراجع + +غير متوفر. diff --git a/docs/tech-specs/structured-data.es.md b/docs/tech-specs/structured-data.es.md new file mode 100644 index 00000000..3aec2f32 --- /dev/null +++ b/docs/tech-specs/structured-data.es.md @@ -0,0 +1,260 @@ +--- +layout: default +title: "Especificación Técnica de Datos Estructurados" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica de Datos Estructurados + +> **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 la integración de TrustGraph con flujos de datos estructurados, lo que permite que el sistema trabaje con datos que se pueden representar como filas en tablas u objetos en almacenes de objetos. La integración admite cuatro casos de uso principales: + +1. **Extracción de Datos No Estructurados a Estructurados**: Leer fuentes de datos no estructurados, identificar y extraer estructuras de objetos y almacenarlas en un formato tabular. +2. **Ingesta de Datos Estructurados**: Cargar datos que ya están en formatos estructurados directamente en el almacén estructurado junto con los datos extraídos. +3. **Consultas en Lenguaje Natural**: Convertir preguntas en lenguaje natural en consultas estructuradas para extraer datos coincidentes del almacén. +4. **Consultas Estructuradas Directas**: Ejecutar consultas estructuradas directamente contra el almacén de datos para una recuperación de datos precisa. + +## Objetivos + +**Acceso Unificado a Datos**: Proporcionar una única interfaz para acceder tanto a datos estructurados como no estructurados dentro de TrustGraph. +**Integración Fluida**: Permitir una interoperabilidad fluida entre la representación de conocimiento basada en gráficos de TrustGraph y los formatos de datos estructurados tradicionales. +**Extracción Flexible**: Admitir la extracción automática de datos estructurados de diversas fuentes no estructuradas (documentos, texto, etc.). +**Versatilidad de Consulta**: Permitir a los usuarios consultar datos utilizando tanto lenguaje natural como lenguajes de consulta estructurados. +**Consistencia de Datos**: Mantener la integridad y la consistencia de los datos en diferentes representaciones de datos. +**Optimización del Rendimiento**: Garantizar el almacenamiento y la recuperación eficientes de datos estructurados a escala. +**Flexibilidad del Esquema**: Admitir enfoques de esquema-en-escritura y esquema-en-lectura para adaptarse a diversas fuentes de datos. +**Compatibilidad con Versiones Anteriores**: Preservar la funcionalidad existente de TrustGraph al agregar capacidades de datos estructurados. + +## Antecedentes + +Actualmente, TrustGraph destaca en el procesamiento de datos no estructurados y en la creación de gráficos de conocimiento a partir de diversas fuentes. Sin embargo, muchos casos de uso empresariales implican datos que son inherentemente estructurados: registros de clientes, registros de transacciones, bases de datos de inventario y otros conjuntos de datos tabulares. Estos conjuntos de datos estructurados a menudo deben analizarse junto con contenido no estructurado para proporcionar información integral. + +Las limitaciones actuales incluyen: +No hay soporte nativo para la ingesta de formatos de datos preestructurados (CSV, matrices JSON, exportaciones de bases de datos). +Incapacidad para preservar la estructura inherente al extraer datos tabulares de documentos. +Falta de mecanismos de consulta eficientes para patrones de datos estructurados. +Falta de un puente entre las consultas tipo SQL y las consultas de gráficos de TrustGraph. + +Esta especificación aborda estas deficiencias mediante la introducción de una capa de datos estructurados que complementa las capacidades existentes de TrustGraph. Al admitir datos estructurados de forma nativa, TrustGraph puede: +Servir como una plataforma unificada para el análisis tanto de datos estructurados como no estructurados. +Permitir consultas híbridas que abarquen tanto las relaciones de gráficos como los datos tabulares. +Proporcionar interfaces familiares para los usuarios acostumbrados a trabajar con datos estructurados. +Desbloquear nuevos casos de uso en la integración de datos y la inteligencia empresarial. + +## Diseño Técnico + +### Arquitectura + +La integración de datos estructurados requiere los siguientes componentes técnicos: + +1. **Servicio de Conversión de Lenguaje Natural a Consulta Estructurada** + Convierte preguntas en lenguaje natural en consultas estructuradas. + Admite múltiples objetivos de lenguaje de consulta (inicialmente sintaxis tipo SQL). + Se integra con las capacidades existentes de NLP de TrustGraph. + + Módulo: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **Soporte de Esquema de Configuración** ✅ **[COMPLETO]** + Sistema de configuración extendido para almacenar esquemas de datos estructurados. + Soporte para definir estructuras de tablas, tipos de campos y relaciones. + Capacidades de versionado y migración de esquemas. + +3. **Módulo de Extracción de Objetos** ✅ **[COMPLETO]** + Integración mejorada del flujo de extracción de conocimiento. + Identifica y extrae objetos estructurados de fuentes no estructuradas. + Mantiene el origen y las puntuaciones de confianza. + Registra un controlador de configuración (ejemplo: trustgraph-flow/trustgraph/prompt/template/service.py) para recibir datos de configuración y decodificar información del esquema. + Recibe objetos y los decodifica en objetos ExtractedObject para su entrega en la cola de Pulsar. + NOTA: Existe código en `trustgraph-flow/trustgraph/extract/object/row/`. Este fue un intento anterior y deberá refactorizarse por completo, ya que no se ajusta a las API actuales. Úselo si es útil, comience desde cero si no. + Requiere una interfaz de línea de comandos: `kg-extract-objects` + + Módulo: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **Módulo de Escritura de Almacén Estructurado** ✅ **[COMPLETO]** + Recibe objetos en formato ExtractedObject de las colas de Pulsar. + Implementación inicial dirigida a Apache Cassandra como el almacén de datos estructurados. + Maneja la creación dinámica de tablas basada en los esquemas encontrados. + Administra el mapeo de esquemas a tablas de Cassandra y la transformación de datos. + Proporciona operaciones de escritura por lotes y en streaming para la optimización del rendimiento. + No hay salidas de Pulsar: este es un servicio terminal en el flujo de datos. + + **Manejo de Esquemas**: + Supervisa los mensajes ExtractedObject entrantes en busca de referencias de esquema. + Cuando se encuentra un nuevo esquema por primera vez, crea automáticamente la tabla correspondiente en Cassandra. + Mantiene una caché de esquemas conocidos para evitar intentos redundantes de creación de tablas. + Se debe considerar si se reciben definiciones de esquema directamente o si se confía en los nombres de esquema en los mensajes ExtractedObject. + + **Mapeo de Tablas de Cassandra**: + El espacio de claves tiene el nombre derivado del campo `user` del campo de metadatos de ExtractedObject. + La tabla tiene el nombre derivado del campo `schema_name` de ExtractedObject. + La colección del metadato se convierte en parte de la clave de partición para garantizar: + Distribución de datos natural en los nodos de Cassandra. + Consultas eficientes dentro de una colección específica. + Aislamiento lógico entre diferentes importaciones de datos/fuentes. + Estructura de la clave primaria: `PRIMARY KEY ((collection, ), )` + La colección siempre es el primer componente de la clave de partición. + Los campos de la clave primaria definidos en el esquema siguen como parte de la clave de partición compuesta. + Esto requiere que las consultas especifiquen la colección, lo que garantiza un rendimiento predecible. + Las definiciones de campos se mapean a columnas de Cassandra con conversiones de tipo: + `string` → `text` + `integer` → `int` o `bigint` según la sugerencia de tamaño. + `float` → `float` o `double` según las necesidades de precisión. + `boolean` → `boolean` + `timestamp` → `timestamp` + `enum` → `text` con validación a nivel de aplicación. + Los campos indexados crean índices secundarios de Cassandra (excluyendo los campos que ya están en la clave primaria). + Los campos obligatorios se imponen a nivel de aplicación (Cassandra no admite NOT NULL). + + **Almacenamiento de Objetos**: + Extrae valores del mapa ExtractedObject.values. + Realiza la conversión de tipo y la validación antes de la inserción. + Maneja los campos opcionales faltantes de forma elegante. + Mantiene metadatos sobre el origen del objeto (documento de origen, puntajes de confianza). + Admite escrituras idempotentes para manejar escenarios de retransmisión de mensajes. + + **Notas de Implementación**: + El código existente en `trustgraph-flow/trustgraph/storage/objects/cassandra/` está obsoleto y no cumple con las API actuales. + Debe referenciar `trustgraph-flow/trustgraph/storage/triples/cassandra` como un ejemplo de un procesador de almacenamiento que funciona. + Es necesario evaluar el código existente para identificar cualquier componente reutilizable antes de decidir refactorizar o reescribir. + + Módulo: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **Servicio de Consulta Estructurada** ✅ **[COMPLETO]** + Acepta consultas estructuradas en formatos definidos. + Ejecuta consultas contra el almacén estructurado. + Devuelve objetos que coinciden con los criterios de la consulta. + Admite paginación y filtrado de resultados. + + Módulo: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **Integración de Herramientas de Agente** + Nueva clase de herramienta para marcos de agentes. + Permite que los agentes consulten almacenes de datos estructurados. + Proporciona interfaces de consulta de lenguaje natural y estructuradas. + Se integra con los procesos de toma de decisiones existentes de los agentes. + +7. **Servicio de Ingestión de Datos Estructurados** + Acepta datos estructurados en múltiples formatos (JSON, CSV, XML). + Analiza y valida los datos entrantes según los esquemas definidos. + Convierte los datos en flujos de objetos normalizados. + Emite objetos a colas de mensajes apropiadas para su procesamiento. + Admite cargas masivas e ingestión en streaming. + + Módulo: trustgraph-flow/trustgraph/decoding/structured + +8. **Servicio de Incrustación de Objetos** + Genera incrustaciones vectoriales para objetos estructurados. + Permite la búsqueda semántica en datos estructurados. + Admite la búsqueda híbrida que combina consultas estructuradas con similitud semántica. + Se integra con almacenes de vectores existentes. + + Módulo: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### Modelos de Datos + +#### Mecanismo de Almacenamiento de Esquemas + +Los esquemas se almacenan en el sistema de configuración de TrustGraph utilizando la siguiente estructura: + +**Tipo**: `schema` (valor fijo para todos los esquemas de datos estructurados) +**Clave**: El nombre/identificador único del esquema (por ejemplo, `customer_records`, `transaction_log`) +**Valor**: Definición de esquema JSON que contiene la estructura + +Ejemplo de entrada de configuración: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +Este enfoque permite: +Definición dinámica del esquema sin cambios en el código +Actualizaciones y versiones de esquema fáciles +Integración consistente con la gestión de configuración de TrustGraph existente +Soporte para múltiples esquemas dentro de un único despliegue + +### APIs + +Nuevas APIs: + Esquemas de Pulsar para los tipos anteriores + Interfaces de Pulsar en nuevos flujos + Se necesita un medio para especificar los tipos de esquema en los flujos para que los flujos sepan qué + tipos de esquema cargar + APIs añadidas a la puerta de enlace y a la puerta de enlace de revisión + +APIs modificadas: +Puntos finales de extracción de conocimiento: añadir opción de salida de objeto estructurado +Puntos finales de agentes: añadir soporte para herramientas de datos estructurados + +### Detalles de implementación + +Siguiendo las convenciones existentes: estos son simplemente nuevos módulos de procesamiento. +Todo está en los paquetes de trustgraph-flow, excepto los elementos del esquema +en trustgraph-base. + +Se necesita algo de trabajo de interfaz de usuario en el Workbench para poder demostrar / probar +esta funcionalidad. + +## Consideraciones de seguridad + +No hay consideraciones adicionales. + +## Consideraciones de rendimiento + +Algunas preguntas sobre el uso de consultas e índices de Cassandra para que las consultas +no ralenticen el sistema. + +## Estrategia de pruebas + +Utilizar la estrategia de pruebas existente, se crearán pruebas unitarias, de contrato e de integración. + +## Plan de migración + +Ninguno. + +## Cronograma + +No especificado. + +## Preguntas abiertas + +¿Se puede hacer que esto funcione con otros tipos de almacenamiento? Nuestro objetivo es utilizar + interfaces que hagan que los módulos que funcionan con un almacenamiento sean aplicables a + otros almacenamientos. + +## Referencias + +n/a. diff --git a/docs/tech-specs/structured-data.he.md b/docs/tech-specs/structured-data.he.md new file mode 100644 index 00000000..9e86bf43 --- /dev/null +++ b/docs/tech-specs/structured-data.he.md @@ -0,0 +1,260 @@ +--- +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. +**שילוב חלק**: אפשור תאימות הדוקה בין ייצוג הידע מבוסס הגרף של TrustGraph לבין פורמטים מובנים מסורתיים. +**חילוץ גמיש**: תמיכה בחילוץ אוטומטי של נתונים מובנים ממקורות לא מובנים שונים (מסמכים, טקסט וכו'). +**גמישות שאילתא**: לאפשר למשתמשים לשאול נתונים באמצעות שפה טבעית ושפות שאילתא מובנות. +**עקביות נתונים**: שמירה על שלמות ועקביות הנתונים בייצוגי נתונים שונים. +**אופטימיזציה של ביצועים**: הבטחת אחסון ושליפה יעילים של נתונים מובנים בקנה מידה גדול. +**גמישות סכימה**: תמיכה בגישות "סכימה בכתיבה" ו"סכימה בקריאה" כדי להתאים למקורות נתונים מגוונים. +**תאימות לאחור**: שמירה על פונקציונליות קיימת של TrustGraph תוך הוספת יכולות נתונים מובנים. + +## רקע + +TrustGraph מצטיינת כיום בעיבוד נתונים לא מובנים ובבניית גרפי ידע ממקורות מגוונים. עם זאת, תרחישי שימוש רבים בארגונים כוללים נתונים המובנים מטבעם - רשומות לקוחות, יומני עסקאות, מסדי נתונים של מלאי וערכות נתונים טבלאיים אחרים. ערכות נתונים מובנות אלו לעתים קרובות צריכות להיות מנותחות יחד עם תוכן לא מובנה כדי לספק תובנות מקיפות. + +מגבלות נוכחיות כוללות: +חוסר תמיכה מובנית בטעינת פורמטים מובנים מראש (CSV, מערכי JSON, יצוא מסדי נתונים). +חוסר יכולת לשמור על המבנה הטבעי בעת חילוץ נתונים טבלאיים ממסמכים. +היעדר מנגנוני שאילתא יעילים עבור דפוסי נתונים מובנים. +חוסר גשר בין שאילתות בסגנון SQL לשאילתות גרפיות של TrustGraph. + +מפרט זה מתייחס לפערים אלה על ידי הצגת שכבת נתונים מובנים המשלימה את היכולות הקיימות של TrustGraph. על ידי תמיכה בנתונים מובנים באופן טבעי, TrustGraph יכולה: +לשמש כפלטפורמה מאוחדת לניתוח נתונים מובנים ולא מובנים. +לאפשר שאילתות היברידיות החוצות קשרי גרף ונתונים טבלאיים. +לספק ממשקים מוכרים למשתמשים המורגלים לעבודה עם נתונים מובנים. +לפתוח תרחישי שימוש חדשים בשילוב נתונים ובינה עסקית. + +## עיצוב טכני + +### ארכיטקטורה + +השילוב של נתונים מובנים דורש את הרכיבים הטכניים הבאים: + +1. **שירות NLP ל-Structured-Query** + ממיר שאלות בשפה טבעית לשאילתות מובנות. + תומך במספר יעדי שפת שאילתא (בשלב הראשוני תחביר בסגנון SQL). + משתלב עם יכולות NLP קיימות של TrustGraph. + + מודול: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **תמיכה בסכימה לתצורה** ✅ **[הושלם]** + מערכת תצורה מורחבת לאחסון סכימות נתונים מובנים. + תמיכה בהגדרת מבני טבלאות, סוגי שדות ויחסים. + יכולות גרסאות סכימה ומיגרציה. + +3. **מודול חילוץ אובייקטים** ✅ **[הושלם]** + שילוב משופר של זרימת חילוץ ידע. + מזהה ומחלץ אובייקטים מובנים ממקורות לא מובנים. + שומר על מוצא וציוני אמון. + רושם מטפל תצורה (לדוגמה: trustgraph-flow/trustgraph/prompt/template/service.py) כדי לקבל נתוני תצורה ולפענח מידע סכימה. + מקבל אובייקטים ומפענח אותם לאובייקטים של ExtractedObject לצורך העברה בתורת ההודעות Pulsar. + הערה: קיים קוד ב-`trustgraph-flow/trustgraph/extract/object/row/`. זו הייתה ניסיון קודם וצריך לשכתב אותו באופן משמעותי מכיוון שהוא אינו תואם ל-APIs הנוכחיים. השתמש בו אם זה שימושי, התחל מאפס אם לא. + דורש ממשק שורת פקודה: `kg-extract-objects` + + מודול: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **מודול כתיבת אחסון מובנה** ✅ **[הושלם]** + מקבל אובייקטים בפורמט ExtractedObject מתורי Pulsar. + יישום ראשוני המכוון ל-Apache Cassandra כאחסון נתונים מובנים. + מטפל ביצירת טבלאות דינמית על סמך סכימות המתגלות. + מנהל מיפוי סכימה לטבלאות Cassandra והמרת נתונים. + מספק פעולות כתיבה באצווה ובסטרימינג לשיפור ביצועים. + אין פלטים של Pulsar - זוהי שירות סופי בזרימת הנתונים. + + **טיפול בסכימה**: + מנטר הודעות ExtractedObject נכנסות עבור הפניות סכימה. + כאשר מתגלה סכימה חדשה בפעם הראשונה, יוצרת טבלה באופן אוטומטי. + תומך בגישות "סכימה בקריאה" ו"סכימה בכתיבה" כדי להתאים למקורות נתונים מגוונים. + +פלט חוזה (יש לעקוב בדיוק אחר הפורמט הבא). + **מיפוי טבלאות Cassandra**: + מרחב הנתונים (Keyspace) נקרא על שם השדה `user` מתוך מטא-הנתונים של ExtractedObject. + הטבלה נקראת על שם השדה `schema_name` מתוך ExtractedObject. + אוסף מתוך מטא-הנתונים הופך לחלק ממפתח המחיצה (partition key) כדי להבטיח: + התפלגות נתונים טבעית על פני צמתים של Cassandra. + שאילתות יעילות בתוך אוסף ספציפי. + בידוד לוגי בין יבוא נתונים/מקורות שונים. + מבנה מפתח ראשי: `PRIMARY KEY ((collection, ), )`. + האוסף הוא תמיד הרכיב הראשון של מפתח המחיצה. + שדות מפתח ראשי המוגדרים בסכימה מופיעים כחלק ממפתח המחיצה המורכב. + זה דורש ששאילתות יציינו את האוסף, מה שמבטיח ביצועים צפויים. + הגדרות שדות ממופות לעמודות של Cassandra עם המרות סוג: + `string` → `text`. + `integer` → `int` או `bigint` בהתאם לרמז לגודל. + `float` → `float` או `double` בהתאם לדרישות דיוק. + `boolean` → `boolean`. + `timestamp` → `timestamp`. + `enum` → `text` עם אימות ברמת היישום. + שדות עם אינדקס יוצרים אינדקסים משניים של Cassandra (למעט שדות שכבר נמצאים במפתח הראשי). + שדות חובה מיושמים ברמת היישום (Cassandra אינה תומכת ב-NOT NULL). + + **אחסון אובייקטים**: + מחלץ ערכים ממפת ExtractedObject.values. + מבצע המרת סוג ואימות לפני הכנסה. + מטפל בשדות אופציונליים חסרים בצורה חלקה. + שומר על מטא-נתונים לגבי מקור האובייקט (מסמך מקור, ציוני אמון). + תומך בכתיבות אידמפוטנטיות כדי לטפל בתרחישי שידור חוזר של הודעות. + + **הערות יישום**: + קוד קיים ב-`trustgraph-flow/trustgraph/storage/objects/cassandra/` מיושן ואינו תואם ל-APIs הנוכחיים. + יש להתייחס ל-`trustgraph-flow/trustgraph/storage/triples/cassandra` כדוגמה למעבד אחסון תקין. + יש להעריך את הקוד הקיים כדי לזהות רכיבים שניתן לעשות בהם שימוש חוזר לפני שמחליטים לבצע שינוי מבני או כתיבה מחדש. + + מודול: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **שירות שאילתות מובנה** ✅ **[הושלם]** + מקבל שאילתות מובנות בפורמטים מוגדרים. + מבצע שאילתות על הנתונים המובנים. + מחזיר אובייקטים התואמים לקריטריוני השאילתה. + תומך בדפדוף וסינון תוצאות. + + מודול: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **אינטגרציה עם כלי סוכן**: + מחלקת כלי חדשה עבור מסגרות סוכן. + מאפשר לסוכנים לשאול נתונים מובנים. + מספק ממשקי שפה טבעית ושאילתות מובנות. + משתלב עם תהליכי קבלת החלטות קיימים של סוכנים. + +7. **שירות הכנסת נתונים מובנים**: + מקבל נתונים מובנים בפורמטים מרובים (JSON, CSV, XML). + מנתח ומאמת נתונים נכנסים בהתאם לסכימות מוגדרות. + ממיר נתונים לזרמי אובייקטים מנורמלים. + פולט אובייקטים לתורי הודעות מתאימים לעיבוד. + תומך בהעלאות אצווה ובהכנסה רציפה. + + מודול: trustgraph-flow/trustgraph/decoding/structured + +8. **שירות הטמעת אובייקטים**: + מייצר הטמעות וקטוריות עבור אובייקטים מובנים. + מאפשר חיפוש סמנטי על פני נתונים מובנים. + תומך בחיפוש היברידי המשלב שאילתות מובנות עם דמיון סמנטי. + משתלב עם מאגרי וקטורים קיימים. + + מודול: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### מודלים של נתונים + +#### מנגנון אחסון סכימות + +סכימות מאוחסנות במערכת התצורה של TrustGraph באמצעות המבנה הבא: + +**סוג**: `schema` (ערך קבוע עבור כל סכימות הנתונים המובנים). +**מפתח**: השם/מזהה הייחודי של הסכימה (לדוגמה, `customer_records`, `transaction_log`). +**ערך**: הגדרת סכימת JSON המכילה את המבנה. + +רשומה לדוגמה בתצורה: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +גישה זו מאפשרת: +הגדרה דינמית של סכימה ללא שינויים בקוד +עדכונים וגרסאות קלים של הסכימה +אינטגרציה עקבית עם ניהול התצורה הקיים של TrustGraph +תמיכה במספר סכימות בתוך פריסה אחת + +### ממשקי API + +ממשקי API חדשים: + סכימות Pulsar עבור הסוגים שלעיל + ממשקי Pulsar בזרמים חדשים + נדרש אמצעי לציין סוגי סכימה בזרמים כך שהזרמים ידעו אילו + סוגי סכימה לטעון + ממשקי API נוספו לשער ולשער ההיפוך + +ממשקי API ששונו: +נקודות קצה לחילוץ ידע - הוספת אפשרות פלט של אובייקט מובנה +נקודות קצה של סוכנים - הוספת תמיכה בכלי נתונים מובנים + +### פרטי יישום + +בהתאם לקונבנציות קיימות - אלו מודולים חדשים לעיבוד בלבד. +הכל נמצא בחבילות trustgraph-flow למעט פריטי סכימה +ב-trustgraph-base. + +נדרשת עבודה כלשהי בממשק המשתמש ב-Workbench כדי שניתן יהיה להדגים / לבצע פיילוט +ליכולת זו. + +## שיקולי אבטחה + +אין שיקולים נוספים. + +## שיקולי ביצועים + +ישנן שאלות בנוגע לשימוש בשאילתות ואינדקסים של Cassandra כך ששאלות +לא יאטו את העבודה. + +## אסטרטגיית בדיקה + +יש להשתמש באסטרטגיית בדיקה קיימת, ייבנו בדיקות יחידה, חוזה ואינטגרציה. + +## תוכנית מעבר + +אין. + +## ציר זמן + +לא צוין. + +## שאלות פתוחות + +האם ניתן לגרום לזה לעבוד עם סוגי אחסון אחרים? אנו שואפים להשתמש + בממשקים אשר הופכים מודולים שעובדים עם אחסון אחד ליישומיים + לאחסון אחר. + +## הפניות + +n/a. diff --git a/docs/tech-specs/structured-data.hi.md b/docs/tech-specs/structured-data.hi.md new file mode 100644 index 00000000..cac826b7 --- /dev/null +++ b/docs/tech-specs/structured-data.hi.md @@ -0,0 +1,258 @@ +--- +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. **प्रत्यक्ष संरचित प्रश्न**: सटीक डेटा पुनर्प्राप्ति के लिए डेटा स्टोर के खिलाफ सीधे संरचित प्रश्नों को निष्पादित करें। + +## लक्ष्य + +**एकीकृत डेटा एक्सेस**: ट्रस्टग्राफ के भीतर संरचित और असंरचित दोनों डेटा तक पहुंचने के लिए एक एकल इंटरफ़ेस प्रदान करें। +**निर्बाध एकीकरण**: ट्रस्टग्राफ के ग्राफ-आधारित ज्ञान प्रतिनिधित्व और पारंपरिक संरचित डेटा प्रारूपों के बीच सुचारू अंतर-संचालन को सक्षम करें। +**लचीला निष्कर्षण**: विभिन्न असंरचित स्रोतों (दस्तावेज़, पाठ, आदि) से संरचित डेटा के स्वचालित निष्कर्षण का समर्थन करें। +**प्रश्न बहुमुखी प्रतिभा**: उपयोगकर्ताओं को प्राकृतिक भाषा और संरचित प्रश्न भाषाओं दोनों का उपयोग करके डेटा क्वेरी करने की अनुमति दें। +**डेटा स्थिरता**: विभिन्न डेटा प्रतिनिधित्व में डेटा अखंडता और स्थिरता बनाए रखें। +**प्रदर्शन अनुकूलन**: पैमाने पर संरचित डेटा के कुशल भंडारण और पुनर्प्राप्ति सुनिश्चित करें। +**स्कीमा लचीलापन**: विभिन्न डेटा स्रोतों को समायोजित करने के लिए स्कीमा-ऑन-राइट और स्कीमा-ऑन-रीड दोनों दृष्टिकोणों का समर्थन करें। +**पिछड़ा संगतता**: संरचित डेटा क्षमताओं को जोड़ते समय मौजूदा ट्रस्टग्राफ कार्यक्षमता को संरक्षित करें। + +## पृष्ठभूमि + +ट्रस्टग्राफ वर्तमान में असंरचित डेटा को संसाधित करने और विभिन्न स्रोतों से ज्ञान ग्राफ बनाने में उत्कृष्ट है। हालाँकि, कई उद्यम उपयोग मामलों में डेटा शामिल होता है जो स्वाभाविक रूप से संरचित होता है - ग्राहक रिकॉर्ड, लेनदेन लॉग, इन्वेंट्री डेटाबेस और अन्य सारणीबद्ध डेटासेट। इन संरचित डेटासेट का अक्सर व्यापक अंतर्दृष्टि प्रदान करने के लिए असंरचित सामग्री के साथ विश्लेषण करने की आवश्यकता होती है। + +वर्तमान सीमाएँ शामिल हैं: +पूर्व-संरचित डेटा प्रारूपों (CSV, JSON सरणियों, डेटाबेस निर्यात) को अंतर्ग्रहण करने के लिए कोई देशी समर्थन नहीं। +दस्तावेज़ों से सारणीबद्ध डेटा निकालते समय अंतर्निहित संरचना को संरक्षित करने में असमर्थता। +संरचित डेटा पैटर्न के लिए कुशल प्रश्न तंत्र की कमी। +SQL-जैसे प्रश्नों और ट्रस्टग्राफ के ग्राफ प्रश्नों के बीच कोई पुल नहीं। + +यह विनिर्देश इन कमियों को एक संरचित डेटा परत पेश करके संबोधित करता है जो ट्रस्टग्राफ की मौजूदा क्षमताओं को पूरक करता है। संरचित डेटा का मूल रूप से समर्थन करके, ट्रस्टग्राफ: +संरचित और असंरचित दोनों डेटा विश्लेषण के लिए एक एकीकृत मंच के रूप में कार्य कर सकता है। +ग्राफ संबंधों और सारणीबद्ध डेटा दोनों को कवर करने वाले हाइब्रिड प्रश्नों को सक्षम कर सकता है। +संरचित डेटा के साथ काम करने के लिए अभ्यस्त उपयोगकर्ताओं के लिए परिचित इंटरफेस प्रदान कर सकता है। +डेटा एकीकरण और व्यावसायिक बुद्धिमत्ता में नए उपयोग मामलों को अनलॉक कर सकता है। + +## तकनीकी डिजाइन + +### वास्तुकला + +संरचित डेटा एकीकरण के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है: + +1. **एनएलपी-टू-स्ट्रक्चर्ड-क्वेरी सेवा** + प्राकृतिक भाषा के प्रश्नों को संरचित प्रश्नों में परिवर्तित करता है। + कई प्रश्न भाषा लक्ष्यों का समर्थन करता है (प्रारंभ में SQL-जैसे सिंटैक्स)। + मौजूदा ट्रस्टग्राफ एनएलपी क्षमताओं के साथ एकीकृत होता है। + + मॉड्यूल: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **कॉन्फ़िगरेशन स्कीमा समर्थन** ✅ **[पूर्ण]** + संरचित डेटा स्कीमा को संग्रहीत करने के लिए विस्तारित कॉन्फ़िगरेशन सिस्टम। + तालिका संरचनाओं, फ़ील्ड प्रकारों और संबंधों को परिभाषित करने का समर्थन। + स्कीमा संस्करण और माइग्रेशन क्षमताएं। + +3. **ऑब्जेक्ट निष्कर्षण मॉड्यूल** ✅ **[पूर्ण]** + बेहतर ज्ञान निष्कर्षण प्रवाह एकीकरण। + असंरचित स्रोतों से संरचित ऑब्जेक्ट की पहचान और निष्कर्षण। + उत्पत्ति और आत्मविश्वास स्कोर बनाए रखता है। + एक कॉन्फ़िग हैंडलर (उदाहरण: trustgraph-flow/trustgraph/prompt/template/service.py) को कॉन्फ़िग डेटा प्राप्त करने और स्कीमा जानकारी को डिकोड करने के लिए पंजीकृत करता है। + ऑब्जेक्ट प्राप्त करता है और उन्हें पल्सर कतार पर डिलीवरी के लिए एक्सट्रैक्टेडऑब्जेक्ट ऑब्जेक्ट में डिकोड करता है। + ध्यान दें: `trustgraph-flow/trustgraph/extract/object/row/` पर मौजूदा कोड है। यह एक पिछला प्रयास था और इसे वर्तमान एपीआई के अनुरूप नहीं होने के कारण प्रमुख रूप से फिर से तैयार करने की आवश्यकता होगी। यदि यह उपयोगी है तो इसका उपयोग करें, यदि नहीं तो इसे खरोंच से शुरू करें। + एक कमांड-लाइन इंटरफ़ेस की आवश्यकता है: `kg-extract-objects` + + मॉड्यूल: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **संरचित स्टोर लेखक मॉड्यूल** ✅ **[पूर्ण]** + पल्सर कतारों से एक्सट्रैक्टेडऑब्जेक्ट प्रारूप में ऑब्जेक्ट प्राप्त करता है। + Apache Cassandra को संरचित डेटा स्टोर के रूप में लक्षित करने वाला प्रारंभिक कार्यान्वयन। + सामना किए गए स्कीमा के आधार पर गतिशील तालिका निर्माण को संभालता है। + स्कीमा-से-कैसेंड्रा तालिका मैपिंग और डेटा परिवर्तन का प्रबंधन करता है। + प्रदर्शन अनुकूलन के लिए बैच और स्ट्रीमिंग लेखन संचालन प्रदान करता है। + कोई पल्सर आउटपुट नहीं - यह डेटा प्रवाह में एक टर्मिनल सेवा है। + + **स्कीमा हैंडलिंग**: + स्कीमा संदर्भों के लिए आने वाले एक्सट्रैक्टेडऑब्जेक्ट संदेशों की निगरानी करता है। + पहली बार जब एक नया स्कीमा सामना किया जाता है, तो स्वचालित रूप से संबंधित कैसेंड्रा तालिका बनाता है। + ज्ञात स्कीमा के एक कैश को बनाए रखता है ताकि अनावश्यक तालिका निर्माण प्रयासों से बचा जा सके। + इस पर विचार करना चाहिए कि स्कीमा परिभाषाएँ सीधे प्राप्त की जानी चाहिए या एक्सट्रैक्टेडऑब्जेक्ट संदेशों में स्कीमा नामों पर भरोसा किया जाना चाहिए। + + **कैसेंड्रा टेबल मैपिंग**: + कीस्पेस का नाम एक्सट्रैक्टेडऑब्जेक्ट के मेटाडेटा से `user` फ़ील्ड से लिया गया है। + टेबल का नाम एक्सट्रैक्टेडऑब्जेक्ट से `schema_name` फ़ील्ड से लिया गया है। + मेटाडेटा से कलेक्शन को पार्टीशन कुंजी का हिस्सा बनाया जाता है ताकि: + कैसेंड्रा नोड्स में डेटा का प्राकृतिक वितरण सुनिश्चित हो सके। + एक विशिष्ट कलेक्शन के भीतर कुशल क्वेरीज़ संभव हों। + विभिन्न डेटा आयात/स्रोत के बीच तार्किक अलगाव सुनिश्चित हो सके। + प्राइमरी की संरचना: `PRIMARY KEY ((collection, ), )` + कलेक्शन हमेशा पार्टीशन कुंजी का पहला घटक होता है। + स्कीमा-परिभाषित प्राइमरी की फ़ील्ड, समग्र पार्टीशन कुंजी का हिस्सा होते हैं। + इसके लिए क्वेरीज़ में कलेक्शन को निर्दिष्ट करने की आवश्यकता होती है, जिससे प्रदर्शन पूर्वानुमेय रहता है। + फ़ील्ड परिभाषाएँ कैसेंड्रा कॉलम में टाइप रूपांतरण के साथ मैप होती हैं: + `string` → `text` + `integer` → `int` या `bigint`, आकार के संकेत के आधार पर। + `float` → `float` या `double`, परिशुद्धता की आवश्यकताओं के आधार पर। + `boolean` → `boolean` + `timestamp` → `timestamp` + `enum` → `text`, एप्लिकेशन-स्तरीय सत्यापन के साथ। + अनुक्रमित फ़ील्ड कैसेंड्रा सेकेंडरी इंडेक्स बनाते हैं (प्राइमरी कुंजी में पहले से मौजूद फ़ील्ड को छोड़कर)। + आवश्यक फ़ील्ड एप्लिकेशन स्तर पर लागू किए जाते हैं (कैसेंड्रा NOT NULL का समर्थन नहीं करता है)। + + **ऑब्जेक्ट स्टोरेज**: + एक्सट्रैक्टेडऑब्जेक्ट.वैल्यूज़ मैप से मान निकाले जाते हैं। + सम्मिलन से पहले टाइप रूपांतरण और सत्यापन किया जाता है। + गुम वैकल्पिक फ़ील्ड को कुशलतापूर्वक संभाला जाता है। + ऑब्जेक्ट की उत्पत्ति के बारे में मेटाडेटा बनाए रखा जाता है (स्रोत दस्तावेज़, आत्मविश्वास स्कोर)। + संदेश पुनरावृत्ति परिदृश्यों को संभालने के लिए आइडेंपोटेंट राइट का समर्थन करता है। + + **कार्यान्वयन नोट्स**: + `trustgraph-flow/trustgraph/storage/objects/cassandra/` पर मौजूद मौजूदा कोड पुराना है और वर्तमान एपीआई के अनुरूप नहीं है। + `trustgraph-flow/trustgraph/storage/triples/cassandra` को एक कार्यशील स्टोरेज प्रोसेसर के उदाहरण के रूप में संदर्भित किया जाना चाहिए। + पुन: उपयोग करने योग्य घटकों के लिए मौजूदा कोड का मूल्यांकन किया जाना चाहिए, फिर रिफैक्टर या फिर से लिखने का निर्णय लिया जाना चाहिए। + + मॉड्यूल: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **स्ट्रक्चर्ड क्वेरी सर्विस** ✅ **[पूर्ण]** + परिभाषित प्रारूपों में संरचित क्वेरी स्वीकार करता है। + संरचित स्टोर के खिलाफ क्वेरी निष्पादित करता है। + क्वेरी मानदंडों से मेल खाने वाले ऑब्जेक्ट लौटाता है। + पेजिंग और परिणाम फ़िल्टरिंग का समर्थन करता है। + + मॉड्यूल: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **एजेंट टूल इंटीग्रेशन**: + एजेंट फ्रेमवर्क के लिए एक नया टूल क्लास। + एजेंटों को संरचित डेटा स्टोर से क्वेरी करने में सक्षम बनाता है। + प्राकृतिक भाषा और संरचित क्वेरी इंटरफेस प्रदान करता है। + मौजूदा एजेंट निर्णय लेने की प्रक्रियाओं के साथ एकीकृत होता है। + +7. **स्ट्रक्चर्ड डेटा इंजेक्शन सर्विस**: + कई प्रारूपों (JSON, CSV, XML) में संरचित डेटा स्वीकार करता है। + परिभाषित स्कीमा के खिलाफ आने वाले डेटा को पार्स और सत्यापित करता है। + डेटा को सामान्यीकृत ऑब्जेक्ट स्ट्रीम में परिवर्तित करता है। + प्रसंस्करण के लिए उपयुक्त संदेश कतारों में ऑब्जेक्ट उत्सर्जित करता है। + बल्क अपलोड और स्ट्रीमिंग इंजेक्शन का समर्थन करता है। + + मॉड्यूल: trustgraph-flow/trustgraph/decoding/structured + +8. **ऑब्जेक्ट एम्बेडिंग सर्विस**: + संरचित ऑब्जेक्ट के लिए वेक्टर एम्बेडिंग उत्पन्न करता है। + संरचित डेटा में सिमेंटिक खोज को सक्षम करता है। + संरचित क्वेरी के साथ सिमेंटिक समानता को मिलाकर हाइब्रिड खोज का समर्थन करता है। + मौजूदा वेक्टर स्टोर के साथ एकीकृत होता है। + + मॉड्यूल: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### डेटा मॉडल: + +#### स्कीमा स्टोरेज मैकेनिज्म: + +स्कीमा को ट्रस्टग्राफ की कॉन्फ़िगरेशन प्रणाली में निम्नलिखित संरचना का उपयोग करके संग्रहीत किया जाता है: + +**टाइप**: `schema` (सभी संरचित डेटा स्कीमा के लिए एक निश्चित मान)। +**की**: स्कीमा का अद्वितीय नाम/पहचानकर्ता (जैसे, `customer_records`, `transaction_log`)। +**वैल्यू**: संरचना वाली JSON स्कीमा परिभाषा। + +उदाहरण कॉन्फ़िगरेशन प्रविष्टि: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +यह दृष्टिकोण निम्नलिखित कार्य करने की अनुमति देता है: +कोड में बदलाव किए बिना गतिशील स्कीमा परिभाषा +आसान स्कीमा अपडेट और संस्करण +मौजूदा ट्रस्टग्राफ कॉन्फ़िगरेशन प्रबंधन के साथ सुसंगत एकीकरण +एक ही परिनियोजन में एकाधिक स्कीमा के लिए समर्थन + +### एपीआई + +नए एपीआई: + ऊपर दिए गए प्रकारों के लिए पल्सर स्कीमा + नए फ्लो में पल्सर इंटरफेस + फ्लो को यह जानने के लिए कि कौन से + स्कीमा प्रकार लोड करने हैं, फ्लो में स्कीमा प्रकारों को निर्दिष्ट करने का एक तरीका आवश्यक है। + गेटवे और रिव-गेटवे में जोड़े गए एपीआई + +संशोधित एपीआई: +नॉलेज एक्सट्रैक्शन एंडपॉइंट - संरचित ऑब्जेक्ट आउटपुट विकल्प जोड़ें +एजेंट एंडपॉइंट - संरचित डेटा टूल समर्थन जोड़ें + +### कार्यान्वयन विवरण + +मौजूदा सम्मेलनों का पालन करें - ये केवल नए प्रोसेसिंग मॉड्यूल हैं। +सब कुछ ट्रस्टग्राफ-फ्लो पैकेजों में है, सिवाय ट्रस्टग्राफ-बेस में स्कीमा आइटम के। + + +इस क्षमता का प्रदर्शन/पायलट करने के लिए वर्कबेंच में कुछ यूआई कार्य की आवश्यकता है। + + +## सुरक्षा संबंधी विचार + +कोई अतिरिक्त विचार नहीं। + +## प्रदर्शन संबंधी विचार + +कैसेंड्रा प्रश्नों और इंडेक्स का उपयोग करने के बारे में कुछ प्रश्न हैं ताकि प्रश्न धीमे न हों। + +## परीक्षण रणनीति + +मौजूदा परीक्षण रणनीति का उपयोग करें, यूनिट, कॉन्ट्रैक्ट और एकीकरण परीक्षण बनाए जाएंगे। + +## माइग्रेशन योजना + +कोई नहीं। + +## समयरेखा + +निर्दिष्ट नहीं है। + +## खुले प्रश्न + + +क्या इसे अन्य स्टोर प्रकारों के साथ काम करने के लिए बनाया जा सकता है? हम इंटरफेस का उपयोग करने का लक्ष्य रख रहे हैं जो एक स्टोर के साथ काम करने वाले मॉड्यूल को अन्य स्टोर पर लागू करने योग्य बनाते हैं। + + ## संदर्भ + +लागू नहीं। diff --git a/docs/tech-specs/structured-data.md b/docs/tech-specs/structured-data.md index 0c9142ab..82369d6d 100644 --- a/docs/tech-specs/structured-data.md +++ b/docs/tech-specs/structured-data.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Structured Data Technical Specification" +parent: "Tech Specs" +--- + # Structured Data Technical Specification ## Overview @@ -250,4 +256,3 @@ Not specified. ## References n/a. - diff --git a/docs/tech-specs/structured-data.pt.md b/docs/tech-specs/structured-data.pt.md new file mode 100644 index 00000000..4ee94f34 --- /dev/null +++ b/docs/tech-specs/structured-data.pt.md @@ -0,0 +1,260 @@ +--- +layout: default +title: "Especificação Técnica de Dados Estruturados" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica de Dados Estruturados + +> **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 a integração do TrustGraph com fluxos de dados estruturados, permitindo que o sistema trabalhe com dados que podem ser representados como linhas em tabelas ou objetos em armazenamentos de objetos. A integração suporta quatro casos de uso primários: + +1. **Extração de Não Estruturado para Estruturado**: Ler fontes de dados não estruturados, identificar e extrair estruturas de objetos e armazená-las em um formato tabular. +2. **Ingestão de Dados Estruturados**: Carregar dados que já estão em formatos estruturados diretamente no armazenamento estruturado, juntamente com os dados extraídos. +3. **Consulta em Linguagem Natural**: Converter perguntas em linguagem natural em consultas estruturadas para extrair dados correspondentes do armazenamento. +4. **Consulta Estruturada Direta**: Executar consultas estruturadas diretamente contra o armazenamento de dados para recuperação precisa de dados. + +## Objetivos + +**Acesso Unificado a Dados**: Fornecer uma única interface para acessar dados estruturados e não estruturados dentro do TrustGraph. +**Integração Perfeita**: Permitir interoperabilidade perfeita entre a representação de conhecimento baseada em grafo do TrustGraph e formatos de dados estruturados tradicionais. +**Extração Flexível**: Suportar a extração automática de dados estruturados de várias fontes não estruturadas (documentos, texto, etc.). +**Versatilidade de Consulta**: Permitir que os usuários consultem dados usando linguagem natural e linguagens de consulta estruturadas. +**Consistência de Dados**: Manter a integridade e a consistência dos dados em diferentes representações de dados. +**Otimização de Desempenho**: Garantir o armazenamento e a recuperação eficientes de dados estruturados em grande escala. +**Flexibilidade de Esquema**: Suportar abordagens de esquema-na-escrita e esquema-na-leitura para acomodar diversas fontes de dados. +**Compatibilidade com Versões Anteriores**: Preservar a funcionalidade existente do TrustGraph, adicionando recursos de dados estruturados. + +## Contexto + +Atualmente, o TrustGraph se destaca no processamento de dados não estruturados e na construção de grafos de conhecimento a partir de diversas fontes. No entanto, muitos casos de uso empresariais envolvem dados que são inerentemente estruturados - registros de clientes, logs de transações, bancos de dados de inventário e outros conjuntos de dados tabulares. Esses conjuntos de dados estruturados geralmente precisam ser analisados ​​juntamente com conteúdo não estruturado para fornecer insights abrangentes. + +As limitações atuais incluem: +Ausência de suporte nativo para ingestão de formatos de dados pré-estruturados (CSV, arrays JSON, exportações de banco de dados). +Impossibilidade de preservar a estrutura inerente ao extrair dados tabulares de documentos. +Falta de mecanismos de consulta eficientes para padrões de dados estruturados. +Falta de uma ponte entre consultas semelhantes a SQL e as consultas de grafo do TrustGraph. + +Esta especificação aborda essas lacunas, introduzindo uma camada de dados estruturados que complementa as capacidades existentes do TrustGraph. Ao suportar dados estruturados nativamente, o TrustGraph pode: +Servir como uma plataforma unificada para análise de dados estruturados e não estruturados. +Permitir consultas híbridas que abrangem relacionamentos de grafo e dados tabulares. +Fornecer interfaces familiares para usuários acostumados a trabalhar com dados estruturados. +Desbloquear novos casos de uso em integração de dados e inteligência de negócios. + +## Design Técnico + +### Arquitetura + +A integração de dados estruturados requer os seguintes componentes técnicos: + +1. **Serviço de Conversão de Linguagem Natural para Consulta Estruturada** + Converte perguntas em linguagem natural em consultas estruturadas. + Suporta vários alvos de linguagem de consulta (inicialmente sintaxe semelhante a SQL). + Integra-se com as capacidades existentes de NLP do TrustGraph. + + Módulo: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **Suporte para Esquema de Configuração** ✅ **[COMPLETO]** + Sistema de configuração estendido para armazenar esquemas de dados estruturados. + Suporte para definir estruturas de tabela, tipos de campo e relacionamentos. + Versionamento de esquema e capacidades de migração. + +3. **Módulo de Extração de Objetos** ✅ **[COMPLETO]** + Integração aprimorada do fluxo de extração de conhecimento. + Identifica e extrai objetos estruturados de fontes não estruturadas. + Mantém a rastreabilidade e as pontuações de confiança. + Registra um manipulador de configuração (exemplo: trustgraph-flow/trustgraph/prompt/template/service.py) para receber dados de configuração e decodificar informações de esquema. + Recebe objetos e os decodifica em objetos ExtractedObject para entrega na fila Pulsar. + OBS: Existe código existente em `trustgraph-flow/trustgraph/extract/object/row/`. Esta foi uma tentativa anterior e precisará ser refatorada significativamente, pois não está em conformidade com as APIs atuais. Use-o se for útil, comece do zero se não for. + Requer uma interface de linha de comando: `kg-extract-objects` + + Módulo: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **Módulo de Escrita de Armazenamento Estruturado** ✅ **[COMPLETO]** + Recebe objetos no formato ExtractedObject de filas Pulsar. + Implementação inicial direcionada ao Apache Cassandra como o armazenamento de dados estruturados. + Lida com a criação dinâmica de tabelas com base nos esquemas encontrados. + Gerencia o mapeamento de esquema para tabela Cassandra e a transformação de dados. + Fornece operações de gravação em lote e em streaming para otimização de desempenho. + Sem saídas Pulsar - este é um serviço terminal no fluxo de dados. + + **Manipulação de Esquema**: + Monitora mensagens ExtractedObject recebidas para referências de esquema. + Quando um novo esquema é encontrado pela primeira vez, cria automaticamente a tabela Cassandra correspondente. + Mantém um cache de esquemas conhecidos para evitar tentativas redundantes de criação de tabela. + Deve considerar se deve receber definições de esquema diretamente ou confiar em nomes de esquema em mensagens ExtractedObject. + + **Mapeamento de Tabela Cassandra**: + O keyspace é nomeado a partir do campo `user` do Metadata do ExtractedObject. + A tabela é nomeada a partir do campo `schema_name` do ExtractedObject. + A coleção do Metadata se torna parte da chave de partição para garantir: + Distribuição natural dos dados em todos os nós do Cassandra. + Consultas eficientes dentro de uma coleção específica. + Isolamento lógico entre diferentes importações/fontes de dados. + Estrutura da chave primária: `PRIMARY KEY ((collection, ), )`. + A coleção é sempre o primeiro componente da chave de partição. + Os campos da chave primária definidos no esquema seguem como parte da chave de partição composta. + Isso requer que as consultas especifiquem a coleção, garantindo um desempenho previsível. + As definições de campos são mapeadas para colunas do Cassandra com conversões de tipo: + `string` → `text`. + `integer` → `int` ou `bigint` com base na dica de tamanho. + `float` → `float` ou `double` com base nas necessidades de precisão. + `boolean` → `boolean`. + `timestamp` → `timestamp`. + `enum` → `text` com validação no nível da aplicação. + Campos indexados criam índices secundários do Cassandra (excluindo campos já na chave primária). + Campos obrigatórios são aplicados no nível da aplicação (o Cassandra não suporta NOT NULL). + + **Armazenamento de Objetos**: + Extrai valores do mapa ExtractedObject.values. + Realiza conversão de tipo e validação antes da inserção. + Lida com campos opcionais ausentes de forma elegante. + Mantém metadados sobre a origem do objeto (documento de origem, pontuações de confiança). + Suporta escritas idempotentes para lidar com cenários de repetição de mensagens. + + **Observações de Implementação**: + O código existente em `trustgraph-flow/trustgraph/storage/objects/cassandra/` está desatualizado e não está em conformidade com as APIs atuais. + Deve referenciar `trustgraph-flow/trustgraph/storage/triples/cassandra` como um exemplo de um processador de armazenamento funcional. + É necessário avaliar o código existente para identificar quaisquer componentes reutilizáveis antes de decidir refatorar ou reescrever. + + Módulo: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **Serviço de Consulta Estruturada** ✅ **[COMPLETO]** + Aceita consultas estruturadas em formatos definidos. + Executa consultas no armazenamento estruturado. + Retorna objetos que correspondem aos critérios da consulta. + Suporta paginação e filtragem de resultados. + + Módulo: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **Integração com Ferramenta de Agente** + Nova classe de ferramenta para frameworks de agente. + Permite que agentes consultem armazenamentos de dados estruturados. + Fornece interfaces de consulta em linguagem natural e estruturada. + Integra-se com os processos de tomada de decisão existentes dos agentes. + +7. **Serviço de Ingestão de Dados Estruturados** + Aceita dados estruturados em vários formatos (JSON, CSV, XML). + Analisa e valida os dados recebidos de acordo com os esquemas definidos. + Converte os dados em fluxos de objetos normalizados. + Emite objetos para as filas de mensagens apropriadas para processamento. + Suporta uploads em lote e ingestão em streaming. + + Módulo: trustgraph-flow/trustgraph/decoding/structured + +8. **Serviço de Incorporação de Objetos** + Gera incorporações vetoriais para objetos estruturados. + Permite a pesquisa semântica em dados estruturados. + Suporta pesquisa híbrida combinando consultas estruturadas com similaridade semântica. + Integra-se com armazenamentos de vetores existentes. + + Módulo: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### Modelos de Dados + +#### Mecanismo de Armazenamento de Esquemas + +Os esquemas são armazenados no sistema de configuração do TrustGraph usando a seguinte estrutura: + +**Type**: `schema` (valor fixo para todos os esquemas de dados estruturados) +**Key**: O nome/identificador exclusivo do esquema (por exemplo, `customer_records`, `transaction_log`) +**Value**: Definição de esquema JSON contendo a estrutura + +Exemplo de entrada de configuração: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +Esta abordagem permite: +Definição dinâmica de esquema sem alterações de código +Atualizações e versionamento de esquema fáceis +Integração consistente com o gerenciamento de configuração existente do TrustGraph +Suporte para vários esquemas dentro de um único ambiente de implantação + +### APIs + +Novas APIs: + Esquemas Pulsar para os tipos acima + Interfaces Pulsar em novos fluxos + É necessário um meio de especificar os tipos de esquema nos fluxos para que os fluxos saibam quais + tipos de esquema carregar + APIs adicionadas ao gateway e rev-gateway + +APIs modificadas: +Pontos de extremidade de extração de conhecimento - Adicionar opção de saída de objeto estruturado +Pontos de extremidade do agente - Adicionar suporte para ferramentas de dados estruturados + +### Detalhes da Implementação + +Seguindo as convenções existentes - estes são apenas novos módulos de processamento. +Tudo está nos pacotes trustgraph-flow, exceto os itens de esquema +em trustgraph-base. + +É necessário algum trabalho de interface do usuário no Workbench para poder demonstrar / testar +essa funcionalidade. + +## Considerações de Segurança + +Nenhuma consideração adicional. + +## Considerações de Desempenho + +Algumas perguntas sobre o uso de consultas e índices do Cassandra para que as consultas +não diminuam a velocidade. + +## Estratégia de Teste + +Use a estratégia de teste existente, serão criados testes unitários, de contrato e de integração. + +## Plano de Migração + +Nenhum. + +## Cronograma + +Não especificado. + +## Perguntas Abertas + +Isso pode ser adaptado para funcionar com outros tipos de armazenamento? Estamos buscando usar + interfaces que tornem os módulos que funcionam com um armazenamento aplicáveis a + outros armazenamentos. + +## Referências + +n/a. diff --git a/docs/tech-specs/structured-data.ru.md b/docs/tech-specs/structured-data.ru.md new file mode 100644 index 00000000..b686dc3a --- /dev/null +++ b/docs/tech-specs/structured-data.ru.md @@ -0,0 +1,260 @@ +--- +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. +**Бесшовная интеграция**: Обеспечение плавного взаимодействия между графовым представлением знаний TrustGraph и традиционными форматами структурированных данных. +**Гибкое извлечение**: Поддержка автоматического извлечения структурированных данных из различных неструктурированных источников (документов, текста и т.д.). +**Универсальность запросов**: Предоставление пользователям возможности выполнять запросы к данным как на естественном языке, так и с использованием структурированных языков запросов. +**Согласованность данных**: Поддержание целостности и согласованности данных в различных представлениях. +**Оптимизация производительности**: Обеспечение эффективного хранения и извлечения структурированных данных в масштабе. +**Гибкость схемы**: Поддержка как подходов "схема при записи", так и "схема при чтении" для адаптации к различным источникам данных. +**Обратная совместимость**: Сохранение существующей функциональности TrustGraph при добавлении возможностей работы со структурированными данными. + +## Предыстория + +В настоящее время TrustGraph отлично справляется с обработкой неструктурированных данных и построением графов знаний из различных источников. Однако, многие корпоративные сценарии использования включают данные, которые изначально являются структурированными - записи о клиентах, журналы транзакций, базы данных инвентаризации и другие табличные наборы данных. Эти структурированные наборы данных часто необходимо анализировать вместе с неструктурированным контентом для получения всесторонних сведений. + +Текущие ограничения включают: +Отсутствие встроенной поддержки импорта данных в предварительно структурированных форматах (CSV, массивы JSON, экспорты баз данных). +Невозможность сохранения исходной структуры при извлечении табличных данных из документов. +Отсутствие эффективных механизмов запросов для структурированных данных. +Отсутствие моста между запросами, похожими на SQL, и графовыми запросами TrustGraph. + +Эта спецификация решает эти проблемы, вводя слой структурированных данных, который дополняет существующие возможности TrustGraph. Поддерживая структурированные данные нативно, TrustGraph может: +Служить унифицированной платформой для анализа как структурированных, так и неструктурированных данных. +Обеспечивать гибридные запросы, охватывающие как графовые отношения, так и табличные данные. +Предоставлять знакомые интерфейсы для пользователей, привыкших работать со структурированными данными. +Открывать новые сценарии использования в интеграции данных и бизнес-аналитике. + +## Технический дизайн + +### Архитектура + +Интеграция структурированных данных требует следующих технических компонентов: + +1. **Сервис преобразования естественного языка в структурированные запросы** + Преобразует вопросы, заданные на естественном языке, в структурированные запросы. + Поддерживает несколько целевых языков запросов (изначально синтаксис, похожий на SQL). + Интегрируется с существующими возможностями NLP TrustGraph. + + Модуль: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **Поддержка схемы конфигурации** ✅ **[ПОЛНО]** + Расширенная система конфигурации для хранения схем структурированных данных. + Поддержка определения структуры таблиц, типов полей и взаимосвязей. + Возможности версионирования и миграции схем. + +3. **Модуль извлечения объектов** ✅ **[ПОЛНО]** + Улучшенная интеграция потока извлечения знаний. + Определяет и извлекает структурированные объекты из неструктурированных источников. + Сохраняет информацию о происхождении и коэффициенты уверенности. + Регистрирует обработчик конфигурации (например: trustgraph-flow/trustgraph/prompt/template/service.py) для получения данных конфигурации и декодирования информации о схеме. + Получает объекты и декодирует их в объекты ExtractedObject для передачи в очередь Pulsar. + ВАЖНО: Существует существующий код по адресу `trustgraph-flow/trustgraph/extract/object/row/`. Это была предыдущая попытка, и его потребуется серьезно переработать, поскольку он не соответствует текущим API. Используйте его, если это полезно, начните с нуля, если нет. + Требуется интерфейс командной строки: `kg-extract-objects` + + Модуль: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **Модуль записи структурированных данных** ✅ **[ПОЛНО]** + Получает объекты в формате ExtractedObject из очередей Pulsar. + Первоначальная реализация, ориентированная на Apache Cassandra в качестве хранилища структурированных данных. + Обрабатывает динамическое создание таблиц на основе обнаруженных схем. + Управляет сопоставлением схем и таблиц Cassandra и преобразованием данных. + Предоставляет операции пакетной и потоковой записи для оптимизации производительности. + Не имеет выходных данных Pulsar - это терминальный сервис в потоке данных. + + **Обработка схем**: + Отслеживает входящие сообщения ExtractedObject на наличие ссылок на схемы. + При первом обнаружении новой схемы автоматически создает соответствующую таблицу Cassandra. + Поддерживает кэш известных схем, чтобы избежать повторных попыток создания таблиц. + Следует рассмотреть, следует ли получать определения схем напрямую или полагаться на имена схем в сообщениях ExtractedObject. + + **Сопоставление таблиц Cassandra**: + Имя пространства ключей (keyspace) берется из поля `user` из метаданных объекта ExtractedObject. + Имя таблицы берется из поля `schema_name` объекта ExtractedObject. + Коллекция из метаданных становится частью ключа секции (partition key) для обеспечения: + Естественного распределения данных между узлами Cassandra. + Эффективных запросов внутри определенной коллекции. + Логической изоляции между различными импортами данных/источниками. + Структура первичного ключа: `PRIMARY KEY ((collection, ), )`. + Коллекция всегда является первым компонентом ключа секции. + Поля, определенные в схеме, следуют за первичным ключом в виде составного ключа секции. + Это требует, чтобы запросы указывали коллекцию, что обеспечивает предсказуемую производительность. + Определение полей сопоставляется с столбцами Cassandra с преобразованием типов: + `string` → `text`. + `integer` → `int` или `bigint` в зависимости от размера. + `float` → `float` или `double` в зависимости от требуемой точности. + `boolean` → `boolean`. + `timestamp` → `timestamp`. + `enum` → `text` с проверкой на уровне приложения. + Индексированные поля создают вторичные индексы Cassandra (за исключением полей, которые уже находятся в первичном ключе). + Обязательные поля проверяются на уровне приложения (Cassandra не поддерживает NOT NULL). + + **Хранилище объектов**: + Извлекает значения из карты ExtractedObject.values. + Выполняет преобразование типов и проверку перед вставкой. + Обрабатывает отсутствующие необязательные поля корректно. + Поддерживает метаданные об источнике объекта (исходный документ, показатели достоверности). + Поддерживает идемпотентные записи для обработки сценариев повторной отправки сообщений. + + **Примечания к реализации**: + Существующий код, расположенный по адресу `trustgraph-flow/trustgraph/storage/objects/cassandra/`, устарел и не соответствует текущим API. + Следует использовать `trustgraph-flow/trustgraph/storage/triples/cassandra` в качестве примера работающего процессора хранилища. + Необходимо оценить существующий код на предмет наличия компонентов, которые можно повторно использовать, прежде чем принимать решение о рефакторинге или переписывании. + + Модуль: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **Сервис структурированных запросов** ✅ **[ЗАВЕРШЕНО]** + Принимает структурированные запросы в определенных форматах. + Выполняет запросы к структурированному хранилищу. + Возвращает объекты, соответствующие критериям запроса. + Поддерживает постраничную выдачу и фильтрацию результатов. + + Модуль: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **Интеграция с инструментами агентов**: + Новый класс инструмента для фреймворков агентов. + Позволяет агентам выполнять запросы к структурированным хранилищам данных. + Предоставляет интерфейсы структурированных запросов и запросов на естественном языке. + Интегрируется с существующими процессами принятия решений агентами. + +7. **Сервис приема структурированных данных**: + Принимает структурированные данные в нескольких форматах (JSON, CSV, XML). + Разбирает и проверяет входящие данные в соответствии с определенными схемами. + Преобразует данные в нормализованные потоки объектов. + Отправляет объекты в соответствующие очереди сообщений для обработки. + Поддерживает массовую загрузку и потоковую передачу данных. + + Модуль: trustgraph-flow/trustgraph/decoding/structured + +8. **Сервис встраивания объектов**: + Генерирует векторные представления для структурированных объектов. + Обеспечивает семантический поиск по структурированным данным. + Поддерживает гибридный поиск, сочетающий структурированные запросы с семантической схожестью. + Интегрируется с существующими векторными хранилищами. + + Модуль: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### Модели данных + +#### Механизм хранения схем + +Схемы хранятся в системе конфигурации TrustGraph со следующей структурой: + +**Тип**: `schema` (фиксированное значение для всех схем структурированных данных). +**Ключ**: Уникальное имя/идентификатор схемы (например, `customer_records`, `transaction_log`). +**Значение**: Определение схемы JSON, содержащее структуру. + +Пример записи конфигурации: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +Этот подход позволяет: +Динамическое определение схемы без внесения изменений в код +Простое обновление и версионирование схемы +Последовательная интеграция с существующим управлением конфигурацией TrustGraph +Поддержка нескольких схем в рамках одного развертывания + +### API + +Новые API: + Схемы Pulsar для вышеперечисленных типов + Интерфейсы Pulsar в новых потоках + Необходим способ указания типов схем в потоках, чтобы потоки знали, какие + типы схем загружать + API добавлены в шлюз и обратный шлюз + +Измененные API: +Конечные точки извлечения знаний - Добавлена опция структурированного объектного вывода +Конечные точки агентов - Добавлена поддержка инструментов для структурированных данных + +### Детали реализации + +В соответствии с существующими соглашениями - это просто новые модули обработки. +Все находится в пакетах trustgraph-flow, за исключением элементов схемы, +находящихся в trustgraph-base. + +Требуется некоторая работа в пользовательском интерфейсе Workbench, чтобы +продемонстрировать / протестировать эту +возможность. + +## Вопросы безопасности + +Нет дополнительных соображений. + +## Вопросы производительности + +Некоторые вопросы, касающиеся использования запросов и индексов Cassandra, чтобы +запросы не замедлялись. + +## Стратегия тестирования + +Используйте существующую стратегию тестирования, будут созданы модульные, +контрактные и интеграционные тесты. + +## План миграции + +Отсутствует. + +## Сроки + +Не указаны. + +## Открытые вопросы + + Можно ли сделать так, чтобы это работало с другими типами хранилищ? Мы стремимся +использовать интерфейсы, которые делают модули, работающие с одним хранилищем, +применимыми к другим хранилищам. + +## Ссылки diff --git a/docs/tech-specs/structured-data.sw.md b/docs/tech-specs/structured-data.sw.md new file mode 100644 index 00000000..82ba79a7 --- /dev/null +++ b/docs/tech-specs/structured-data.sw.md @@ -0,0 +1,260 @@ +--- +layout: default +title: "Vipimo vya Teknisia vya Data Iliyoainishwa" +parent: "Swahili (Beta)" +--- + +# Vipimo vya Teknisia vya Data Iliyoainishwa + +> **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 jinsi TrustGraph inavyounganishwa na mtiririko wa data iliyoainishwa, na kuwezesha mfumo kufanya kazi na data ambayo inaweza kuwakilishwa kama mistari katika meza au vitu katika maduka ya vitu. Uunganisho huu unaunga mkono matumizi manne makuu: + +1. **Utoaji kutoka kwa Data Isiyoainishwa hadi Imeinishwa**: Soma vyanzo vya data visivyoainishwa, tambua na uondoe muundo wa vitu, na uihifadhi katika umbizo wa meza. +2. **Uingizaji wa Data Imeinishwa**: Pakia data ambayo tayari iko katika umbizo iliyoainishwa moja kwa moja katika duka la data iliyoainishwa pamoja na data iliyoondolewa. +3. **Uulizaje kwa Lugha Asilia**: Badilisha maswali ya lugha asilia katika maswali iliyoainishwa ili kuchuja data inayolingana kutoka kwa duka. +4. **Uulizaje wa Moja kwa Moja wa Imeinishwa**: Fanya maswali iliyoainishwa moja kwa moja dhidi ya duka la data ili kupata data kwa usahihi. + +## Lengo + +**Ufikiaji Umoja wa Data**: Toa kiungo kimoja cha kufikia data zote, iliyoainishwa na isiyoainishwa, ndani ya TrustGraph. +**Uunganisho Kamili**: Uwezesha utendaji wa pamoja kati ya uwakilishi wa maarifa wa TrustGraph unaotegemea chati na umbizo wa jadi wa data iliyoainishwa. +**Utoaji Wenye Ugumu**: Unga uondoleaji wa moja kwa moja wa data iliyoainishwa kutoka kwa vyanzo mbalimbali visivyoainishwa (nyaraka, maandishi, n.k.). +**Uwezekano wa Uulizaje**: Ruhusu watumiaji kuuliza data kwa kutumia lugha ya asilia na lugha za uulizaje iliyoainishwa. +**Ulinganifu wa Data**: Dumishe uadilifu na ulinganifu wa data katika uwakilishi tofauti wa data. +**Uboreshaji wa Utendaji**: Hakikisha uhifadhi na upekuzi wa ufanisi wa data iliyoainishwa kwa kiwango kikubwa. +**Uwezekano wa Mfumo**: Unga mifumo ya "andika-mfumo" na "soma-mfumo" ili kukidhi vyanzo tofauti vya data. +**Ulinganifu na Mifumo ya Zamani**: Dumishe utendaji wa sasa wa TrustGraph huku uongezwa uwezekano wa data iliyoainishwa. + +## Asili + +Hivi sasa, TrustGraph inafaa katika kuchakata data isiyoainishwa na kuunda chati za maarifa kutoka kwa vyanzo tofauti. Hata hivyo, matumizi mengi ya kampuni yanahusisha data ambayo ina muundo - rekodi za wateja, magogo ya miamala, hifadhi za bidhaa, na mengineyo ya seti za data za meza. Data hii iliyoainishwa mara nyingi inahitaji kuchanganuliwa pamoja na maudhui isiyoainishwa ili kutoa ufahamu kamili. + +Mapungufu ya sasa ni pamoja na: +Hakuna msaada wa asili kwa kuingiza umbizo la awali la data (CSV, safu za JSON, mauzo ya hifadhi ya data). +Uwezekano wa kutohifadhi muundo halisi wakati wa kuondoa data ya meza kutoka kwa nyaraka. +Ukosefu wa mitambo ya uulizaje ya ufanisi kwa muundo wa data iliyoainishwa. +Upungufu wa daraja kati ya maswali kama ya SQL na maswali ya chati ya TrustGraph. + +Maelekezo haya yanaashiria pengo hizi kwa kuleta safu ya data iliyoainishwa ambayo inakamilisha uwezekano wa sasa wa TrustGraph. Kwa kusaidia data iliyoainishwa kwa asili, TrustGraph inaweza: +Kutoa jukwaa la umoja kwa uchanganuzi wa data iliyoainishwa na isiyoainishwa. +Kuwezesha maswali ya mchanganyiko ambayo yanaenea katika uhusiano wa chati na data ya meza. +Kutoa kiungo cha kawaida kwa watumiaji ambao wamezoea kufanya kazi na data iliyoainishwa. +Kufungua matumizi mapya katika ujumuishaji wa data na ujasusi wa biashara. + +## Muundo wa Kiufundi + +### Usanifu + +Uunganisho wa data iliyoainishwa unahitaji vipengele vifuatavyo vya kiufundi: + +1. **Huduma ya NLP-kwa-Uulizaje-Imeinishwa** + Inabadilisha maswali ya lugha asilia katika maswali iliyoainishwa. + Inasaidia malengo mengi ya lugha ya uulizaje (hasa, usanifu kama wa SQL). + Inaunganishwa na uwezekano wa sasa wa NLP ya TrustGraph. + + Moduli: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **Usaidizi wa Mfumo wa Mpangilio** ✅ **[IMEKAMILIKA]** + Mfumo ulioongezwa wa mpangilio ili kuhifadhi umbizo wa data iliyoainishwa. + Usaidizi wa kufafanua muundo wa meza, aina za sehemu, na uhusiano. + Utoleaji wa toleo na uwezekano wa uhamishaji wa mfumo. + +3. **Moduli ya Utoaji wa Vitu** ✅ **[IMEKAMILIKA]** + Uunganisho uliorekebishwa wa mtiririko wa uondoleaji wa maarifa. + Inatambua na kuondoa vitu vilivyoainishwa kutoka kwa vyanzo visivyoainishwa. + Inahifadhi asili na alama za uaminifu. + Inasajili kiungo cha usanidi (mfano: trustgraph-flow/trustgraph/prompt/template/service.py) ili kupokea data ya usanidi na kuondoa maelezo ya mfumo. + Inapokea vitu na kuyaondoa kuwa vitu vya ExtractedObject ili kuwasilisha kwenye folyo ya Pulsar. + NOTE: Kuna msimbo uliopo kwenye `trustgraph-flow/trustgraph/extract/object/row/`. Hii ilikuwa jaribio la awali na itahitaji marekebisho makubwa kwani haikubaliana na API za sasa. Tumia ikiwa ni muhimu, anza kutoka mwanzo ikiwa sio. + Inahitaji kiungo cha mstari wa amri: `kg-extract-objects` + + Moduli: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **Moduli ya Kuandika ya Duka la Imeinishwa** ✅ **[IMEKAMILIKA]** + Inapokea vitu katika umbizo wa ExtractedObject kutoka kwa folyo za Pulsar. + Utumiaji wa awali unalenga Apache Cassandra kama duka la data iliyoainishwa. + Inashughulikia uundaji wa meza ya moja kwa moja kulingana na umbizo uliokutana. + Inadhibiti ramani ya mfumo-kwa-meza ya Cassandra na ubadilishaji wa data. + Inatoa operesheni za kuandika za kundi na za mtiririko kwa uboreshaji wa utendaji. + Hakuna matokeo ya Pulsar - hii ni huduma ya mwisho katika mtiririko wa data. + + **Ushughulikiaji wa Mfumo**: + Inafuatilia meseji zinazoingia za ExtractedObject kwa marejeleo ya mfumo. + + + Inapaswa kuzingatia kama itapokea maelezo ya muundo moja kwa moja au itategemea majina ya muundo katika ujumbe wa ExtractedObject. + + **Ramapishi ya Jedwali la Cassandra**: + Jina la keyspace linatokana na sehemu `user` kutoka Metadata ya ExtractedObject + Jina la jedwali linatokana na sehemu `schema_name` kutoka ExtractedObject + Mkusanyiko kutoka Metadata unakuwa sehemu ya ufunguo wa partition ili kuhakikisha: + Usambazaji wa data kwa njia ya asili katika nodi za Cassandra + Maswali (queries) bora ndani ya mkusanyiko maalum + Utengano wa mantiki kati ya uingizaji wa data tofauti/vyanzo + Muundo wa ufunguo mkuu: `PRIMARY KEY ((collection, ), )` + Mkusanyiko huwa sehemu ya kwanza ya ufunguo wa partition + Sehemu za ufunguo mkuu zilizobainishwa katika schema zinafuata kama sehemu ya ufunguo wa partition iliyounganishwa + Hii inahitaji maswali (queries) yataonyesha mkusanyiko, kuhakikisha utendaji unaoweza kutabirika + Ufafanuzi wa sehemu unahusishwa na safu za Cassandra na mabadiliko ya aina: + `string` → `text` + `integer` → `int` au `bigint` kulingana na ukubwa + `float` → `float` au `double` kulingana na mahitaji ya usahihi + `boolean` → `boolean` + `timestamp` → `timestamp` + `enum` → `text` na uthibitishaji wa kiwango cha programu + Sehemu zilizo na fahirisi huunda fahirisi za sekondari za Cassandra (isipokuwa sehemu zilizopo katika ufunguo mkuu) + Sehemu zinazohitajika zinafanywa katika kiwango cha programu (Cassandra haitumii NOT NULL) + + **Hifadhi ya Data (Object Storage)**: + Inatoa maadili kutoka ramani ya ExtractedObject.values + Inafanya mabadiliko ya aina na uthibitishaji kabla ya kuingizwa + Inashughulikia sehemu za hiari ambazo hazipo kwa utulivu + Inahifadhi metadata kuhusu asili ya data (hati ya chanzo, alama za uaminifu) + Inasaidia uandikaji ambao unaweza kufanywa tena ili kushughulikia hali za kucheza tena ujumbe + + **Maelezo ya Utendaji**: + Msimbo uliopo katika `trustgraph-flow/trustgraph/storage/objects/cassandra/` ni wa zamani na haukidhi vipimo vya sasa vya API + Inapaswa kurejelea `trustgraph-flow/trustgraph/storage/triples/cassandra` kama mfano wa mchakato wa hifadhi unaofanya kazi + Inahitaji tathmini ya msimbo uliopo ili kuona ikiwa kuna sehemu ambazo zinaweza kutumika tena kabla ya kuamua kufanya marekebisho au kuandika upya + + Moduli: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **Huduma ya Maswali (Structured Query Service)** ✅ **[IMEKAMILIKA]** + Inakubali maswali ya muundo katika muundo uliotolewa + Inatekeleza maswali dhidi ya hifadhi ya muundo + Inarudisha data inayolingana na vigezo vya swali + Inasaidia upangishaji na uchujaji wa matokeo + + Moduli: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **Uunganisho wa Zana za Wakala (Agent Tool Integration)** + Darasa jipya la zana kwa mifumo ya wakala + Inaruhusu wakala kuuliza hifadhi za data zilizopangwa + Inatoa interfaces ya lugha ya asili na maswali ya muundo + Inajumuishwa na michakato iliyopo ya wakala ya kufanya maamuzi + +7. **Huduma ya Uingizaji wa Data Iliyopangwa (Structured Data Ingestion Service)** + Inakubali data iliyopangwa katika muundo mbalimbali (JSON, CSV, XML) + Inachanganua na kuthibitisha data inayokuja dhidi ya schemas zilizobainishwa + Inabadilisha data kuwa mitirisho ya data iliyopangwa + Inatoa data kwa folyo za ujumbe zinazofaa kwa usindikaji + Inasaidia upakiaji wa wingi na uingizaji wa mtiririko + + Moduli: trustgraph-flow/trustgraph/decoding/structured + +8. **Huduma ya Uwekaji wa Data (Object Embedding Service)** + Inazalisha uwekaji wa vector kwa data iliyopangwa + Inaruhusu utafutaji wa semantic katika data iliyopangwa + Inasaidia utafutaji wa mchanganyiko unaounganisha maswali ya muundo na ufanano wa semantic + Inajumuishwa na hifadhi za vector zilizopo + + Moduli: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### Mifano ya Data + +#### Utaratibu wa Uhifadhi wa Schema + +Schemas zinawekwa katika mfumo wa usanidi wa TrustGraph kwa kutumia muundo ufuatao: + +**Aina**: `schema` (thamani iliyobainishwa kwa schemas zote za data iliyopangwa) +**Ufunguo**: Jina/kitambulisho cha kipekee cha schema (k.m., `customer_records`, `transaction_log`) +**Thamani**: Ufafanuzi wa schema ya JSON unao na muundo + +Ingizo la usanidi wa mfano: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +Mbinu hii inaruhusu: +Ufafanuzi wa muundo (schema) unaobadilika bila mabadiliko ya programu +Marekebisho na matoleo ya muundo (schema) rahisi +Uunganishaji thabiti na usimamizi wa usanidi wa TrustGraph uliopo +Usaidizi wa muundo (schemas) nyingi ndani ya matumizi moja + +### API + +API mpya: + Muundo (schemas) za Pulsar kwa aina zilizo hapo juu + Vifaa vya Pulsar katika mtiririko mpya + Inahitajika njia ya kutaja aina za muundo (schema) katika mitiririko ili mitiririko iweze kujua + aina gani za muundo (schema) kupakua + API zimeongezwa kwenye lango na lango la marekebisho + +API zilizobadilishwa: +Vifaa vya utoaji wa maarifa - Ongeza chaguo la pato la kitu kilicho na muundo +Vifaa vya wakala - Ongeza usaidizi wa zana za data iliyo na muundo + +### Maelezo ya Utendaji + +Kufuata mbinu zilizopo - haya ni moduli mpya tu za usindikaji. +Kila kitu kiko katika vifurushi vya trustgraph-flow isipokuwa vipengele vya muundo (schema) +katika trustgraph-base. + +Inahitajika kazi ya UI katika Workbench ili kuweza kuonyesha / majaribio ya +uwezo huu. + +## Masuala ya Usalama + +Hakuna masuala ya ziada. + +## Masuala ya Utendaji + +Maswali kadhaa kuhusu matumizi ya maswali na fahirisi za Cassandra ili maswali +yasichanganye. + +## Mkakati wa Majaribio + +Tumia mkakati wa majaribio uliopo, tutaunda majaribio ya kitengo, mkataba na ujumuishaji. + +## Mpango wa Uhamisho + +Hakuna. + +## Muda + +Haikubainishwa. + +## Maswali Yaliyofunguliwa + +Je, hii inaweza kufanywa ili kufanya kazi na aina zingine za hifadhi? Tunalenga kutumia + vifaa ambavyo hufanya moduli zinazofanya kazi na hifadhi moja kuwa zinapatikana kwa + hifadhi zingine. + +## Marejeleo + +n/a. diff --git a/docs/tech-specs/structured-data.tr.md b/docs/tech-specs/structured-data.tr.md new file mode 100644 index 00000000..3f8f48fc --- /dev/null +++ b/docs/tech-specs/structured-data.tr.md @@ -0,0 +1,260 @@ +--- +layout: default +title: "Yapılandırılmış Veri Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Yapılandırılmış Veri 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'ın yapılandırılmış veri akışlarıyla entegrasyonunu tanımlar ve sistemin, satırlar halinde tablolarda veya nesne depolarında temsil edilebilen verilerle çalışmasını sağlar. Bu entegrasyon, dört birincil kullanım senaryosunu destekler: + +1. **Yapısızdan Yapılandırılmışa Çıkarma**: Yapısız veri kaynaklarını okuyun, nesne yapılarını belirleyin ve çıkarın ve bunları tablo formatında saklayın. +2. **Yapılandırılmış Veri Alma**: Zaten yapılandırılmış formatlarda olan verileri, çıkarılan verilerle birlikte yapılandırılmış depoya doğrudan yükleyin. +3. **Doğal Dil Sorgulama**: Doğal dil sorularını, depodan eşleşen verileri çıkarmak için yapılandırılmış sorgulara dönüştürün. +4. **Doğrudan Yapılandırılmış Sorgulama**: Hassas veri alımı için yapılandırılmış sorguları doğrudan veri deposuna çalıştırın. + +## Hedefler + +**Birleşik Veri Erişimi**: TrustGraph içinde hem yapılandırılmış hem de yapılandırılmamış verilere erişmek için tek bir arayüz sağlayın. +**Sorunsuz Entegrasyon**: TrustGraph'ın grafik tabanlı bilgi gösterimi ile geleneksel yapılandırılmış veri formatları arasındaki sorunsuz uyumluluğu sağlayın. +**Esnek Çıkarma**: Çeşitli yapılandırılmamış kaynaklardan (belgeler, metin vb.) yapılandırılmış verilerin otomatik olarak çıkarılmasını destekleyin. +**Sorgu Çeşitliliği**: Kullanıcıların verilere hem doğal dil hem de yapılandırılmış sorgu dilleriyle sorgu yapmasına izin verin. +**Veri Tutarlılığı**: Farklı veri gösterimleri arasında veri bütünlüğünü ve tutarlılığını koruyun. +**Performans Optimizasyonu**: Ölçekte yapılandırılmış verilerin verimli bir şekilde depolanmasını ve alınmasını sağlayın. +**Şema Esnekliği**: Çeşitli veri kaynaklarına uyum sağlamak için hem şema-yazma hem de şema-okuma yaklaşımlarını destekleyin. +**Geriye Dönük Uyumluluk**: Yapılandırılmış veri yetenekleri eklerken mevcut TrustGraph işlevselliğini koruyun. + +## Arka Plan + +TrustGraph şu anda yapılandırılmamış verileri işleme ve çeşitli kaynaklardan bilgi grafikleri oluşturma konusunda mükemmeldir. Ancak, birçok kurumsal kullanım senaryosu, müşteri kayıtları, işlem günlükleri, envanter veritabanları ve diğer tablo veri kümeleri gibi doğası gereği yapılandırılmış verileri içerir. Bu yapılandırılmış veri kümeleri genellikle kapsamlı bilgiler sağlamak için yapılandırılmamış içerikle birlikte analiz edilmelidir. + +Mevcut sınırlamalar şunlardır: +Önceden yapılandırılmış veri formatlarını (CSV, JSON dizileri, veritabanı dışa aktarmaları) alma konusunda yerel destek yoktur. +Belgelerden tablo verilerini çıkarırken, yerleşik yapıyı koruyamama. +Yapılandırılmış veri kalıpları için verimli sorgulama mekanizmalarının olmaması. +SQL benzeri sorgular ile TrustGraph'ın grafik sorguları arasındaki köprünün olmaması. + +Bu özellik, TrustGraph'ın mevcut yeteneklerini tamamlayan bir yapılandırılmış veri katmanı tanıtarak bu boşlukları giderir. Yapılandırılmış verilere yerel olarak destek sağlayarak, TrustGraph şunları yapabilir: +Hem yapılandırılmış hem de yapılandırılmamış veri analizleri için birleşik bir platform görevi görmek. +Hem grafik ilişkilerini hem de tablo verilerini kapsayan hibrit sorguları etkinleştirmek. +Yapılandırılmış verilerle çalışmaya alışkın kullanıcılar için tanıdık arayüzler sağlamak. +Veri entegrasyonu ve iş zekası alanlarında yeni kullanım senaryolarını açmak. + +## Teknik Tasarım + +### Mimari + +Yapılandırılmış veri entegrasyonu, aşağıdaki teknik bileşenleri gerektirir: + +1. **NLP'den Yapılandırılmış Sorgu Hizmetine** + Doğal dil sorularını yapılandırılmış sorgulara dönüştürür. + Birden çok sorgu dili hedefi (başlangıçta SQL benzeri sözdizimi) destekler. + Mevcut TrustGraph NLP yetenekleriyle entegre olur. + + Modül: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **Yapılandırma Şema Desteği** ✅ **[TAMAMLANDI]** + Yapılandırılmış veri şemalarını depolamak için genişletilmiş yapılandırma sistemi. + Tablo yapılarını, alan türlerini ve ilişkileri tanımlama desteği. + Şema sürümleme ve geçiş yetenekleri. + +3. **Nesne Çıkarma Modülü** ✅ **[TAMAMLANDI]** + Gelişmiş bilgi çıkarıcı akışı entegrasyonu. + Yapısız kaynaklardan yapılandırılmış nesneleri tanımlar ve çıkarır. + Kaynak ve güven puanlarını korur. + Yapılandırma verilerini almak ve şema bilgilerini çözmek için bir yapılandırma işleyici (örneğin: trustgraph-flow/trustgraph/prompt/template/service.py) kaydeder. + Nesneleri alır ve bunları Pulsar kuyruğuna teslim etmek üzere ExtractedObject nesnelerine dönüştürür. + NOT: `trustgraph-flow/trustgraph/extract/object/row/` adresinde mevcut kod bulunmaktadır. Bu, önceki bir girişimdir ve mevcut API'lere uymadığından büyük ölçüde yeniden düzenlenmesi gerekecektir. Kullanışlıysa kullanın, değilse sıfırdan başlayın. + Bir komut satırı arayüzü gerektirir: `kg-extract-objects` + + Modül: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **Yapılandırılmış Depo Yazma Modülü** ✅ **[TAMAMLANDI]** + ExtractedObject formatında nesneleri Pulsar kuyruklarından alır. + İlk uygulama, yapılandırılmış veri deposu olarak Apache Cassandra'yı hedef alır. + Karşılaşılan şemalara göre dinamik olarak tablo oluşturmayı yönetir. + Şema-Cassandra tablo eşlemesini ve veri dönüşümünü yönetir. + Performans optimizasyonu için toplu ve akışlı yazma işlemleri sağlar. + Pulsar çıktıları yok - bu, veri akışında bir terminal hizmetidir. + + **Şema İşleme**: + Yeni bir şema ilk kez karşılaşıldığında, otomatik olarak ilgili Cassandra tablosunu oluşturur. + Tekrarlayan tablo oluşturma girişimlerinden kaçınmak için bilinen şemaların bir önbelleğini korur. + Şema tanımlarını doğrudan alıp almamak veya ExtractedObject mesajlarındaki şema adlarına güvenip güvenmemek konusunda dikkat edilmesi gereken bir durum. + + + **Cassandra Tablo Eşlemesi**: + Anahtar alanı, ExtractedObject'in Meta Verilerinden gelen `user` alanından alınır. + Tablo, ExtractedObject'in `schema_name` alanından alınır. + Meta Verilerden gelen Koleksiyon, Cassandra düğümleri arasında doğal veri dağılımını sağlamak için bölüm anahtarının bir parçası haline gelir: + Cassandra düğümleri arasında verilerin doğal bir şekilde dağıtılmasını sağlar. + Belirli bir koleksiyon içindeki sorguların verimli bir şekilde çalışmasını sağlar. + Farklı veri aktarımları/kaynakları arasında mantıksal bir izolasyon sağlar. + Birincil anahtar yapısı: `PRIMARY KEY ((collection, ), )` + Koleksiyon, her zaman bölüm anahtarının ilk bileşenidir. + Şema tanımlı birincil anahtar alanları, birleşik bölüm anahtarının bir parçası olarak gelir. + Bu, sorguların koleksiyonu belirtmesini gerektirir ve öngörülebilir bir performans sağlar. + Alan tanımları, Cassandra sütunlarına tür dönüşümleriyle eşlenir: + `string` → `text` + `integer` → `int` veya `bigint` (boyut ipucuna bağlı olarak) + `float` → `float` veya `double` (doğruluk gereksinimlerine bağlı olarak) + `boolean` → `boolean` + `timestamp` → `timestamp` + `enum` → `text` (uygulama seviyesinde doğrulama ile) + İndeksli alanlar, Cassandra ikincil indekslerini oluşturur (birincil anahtarda zaten bulunan alanlar hariç). + Gerekli alanlar, uygulama seviyesinde zorunlu kılınır (Cassandra NOT NULL'ı desteklemez). + + **Nesne Depolama**: + ExtractedObject.values haritasından değerleri çıkarır. + Eklemeden önce tür dönüşümü ve doğrulama yapar. + Eksik isteğe bağlı alanları zarif bir şekilde işler. + Nesne kökeni hakkında meta verileri korur (kaynak belge, güvenilirlik puanları). + Mesaj tekrar senaryolarını işlemek için idempotent yazma işlemlerini destekler. + + **Uygulama Notları**: + `trustgraph-flow/trustgraph/storage/objects/cassandra/` adresindeki mevcut kod güncel değildir ve mevcut API'lere uygun değildir. + Çalışan bir depolama işlemcisinin örneği olarak `trustgraph-flow/trustgraph/storage/triples/cassandra`'a başvurulmalıdır. + Yeniden düzenleme veya yeniden yazma kararı vermeden önce, yeniden kullanılabilir bileşenler için mevcut kodun değerlendirilmesi gerekir. + + Modül: trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **Yapılandırılmış Sorgu Hizmeti** ✅ **[TAMAMLANDI]** + Tanımlanmış formatlarda yapılandırılmış sorguları kabul eder. + Yapılandırılmış depoya karşı sorguları yürütür. + Sorgu kriterlerine uyan nesneleri döndürür. + Sayfalama ve sonuç filtrelemeyi destekler. + + Modül: trustgraph-flow/trustgraph/query/objects/cassandra + +6. **Ajan Aracı Entegrasyonu** + Ajan çerçeveleri için yeni bir araç sınıfı. + Ajanların yapılandırılmış veri depolarını sorgulamasına olanak tanır. + Doğal dil ve yapılandırılmış sorgu arayüzleri sağlar. + Mevcut ajan karar verme süreçleriyle entegre olur. + +7. **Yapılandırılmış Veri Alma Hizmeti** + Yapılandırılmış verileri çeşitli formatlarda (JSON, CSV, XML) kabul eder. + Gelen verileri tanımlanmış şemalara göre ayrıştırır ve doğrular. + Verileri normalleştirilmiş nesne akışlarına dönüştürür. + Nesneleri işleme için uygun mesaj kuyruklarına gönderir. + Toplu yüklemeleri ve akışlı almayı destekler. + + Modül: trustgraph-flow/trustgraph/decoding/structured + +8. **Nesne Gömme Hizmeti** + Yapılandırılmış nesneler için vektör gömmeleri oluşturur. + Yapılandırılmış veriler arasında semantik aramayı sağlar. + Yapılandırılmış sorguları semantik benzerlikle birleştiren hibrit aramayı destekler. + Mevcut vektör depolarıyla entegre olur. + + Modül: trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### Veri Modelleri + +#### Şema Depolama Mekanizması + +Şemalar, aşağıdaki yapı kullanılarak TrustGraph'ın yapılandırma sisteminde saklanır: + +**Türü**: `schema` (tüm yapılandırılmış veri şemaları için sabit değer) +**Anahtar**: Şemanın benzersiz adı/tanımlayıcısı (örneğin, `customer_records`, `transaction_log`) +**Değer**: Yapıyı içeren JSON şema tanımı + +Örnek yapılandırma girişi: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +Bu yaklaşım şunları sağlar: +Kod değişiklikleri olmadan dinamik şema tanımı +Kolay şema güncellemeleri ve sürüm yönetimi +Mevcut TrustGraph yapılandırma yönetimi ile tutarlı entegrasyon +Tek bir dağıtım içinde birden fazla şema desteği + +### API'ler + +Yeni API'ler: + Yukarıdaki türler için Pulsar şemaları + Yeni akışlarda Pulsar arayüzleri + Akışların hangi şema türlerini yükleyeceğini bilmesi için, şema türlerini akışlarda belirtmenin bir yolu gereklidir + Ağ geçidi ve ters ağ geçidine eklenen API'ler + + +Değiştirilen API'ler: +Bilgi çıkarma uç noktaları - Yapılandırılmış nesne çıktısı seçeneği ekleyin +Ajan uç noktaları - Yapılandırılmış veri aracı desteği ekleyin + +### Uygulama Detayları + +Mevcut kurallara uygun olarak, bunlar sadece yeni işleme modülleridir. +Her şey trustgraph-flow paketlerinde yer almaktadır, şema öğeleri ise trustgraph-base'de bulunmaktadır. + + +Bu özelliği tanıtmak/denemek için Workbench'te bazı kullanıcı arayüzü (UI) çalışmaları yapılması gerekmektedir. + + +## Güvenlik Hususları + +Ek hususlar bulunmamaktadır. + +## Performans Hususları + +Sorguların yavaşlamasını önlemek için Cassandra sorgularının ve indekslerinin kullanımına ilişkin bazı sorular bulunmaktadır. + + +## Test Stratejisi + +Mevcut test stratejisi kullanılacak, birim, sözleşme ve entegrasyon testleri oluşturulacaktır. + +## Geçiş Planı + +Yok. + +## Zaman Çizelgesi + +Belirtilmemiştir. + +## Açık Sorular + +Bu, diğer depolama türleriyle de çalışacak şekilde yapılabilir mi? Tek bir depolamayla çalışan modüllerin, diğer depolamalara da uygulanabilmesi için arayüzler kullanmayı hedefliyoruz. + + +## Referanslar + + +n/a. diff --git a/docs/tech-specs/structured-data.zh-cn.md b/docs/tech-specs/structured-data.zh-cn.md new file mode 100644 index 00000000..7bab2cbc --- /dev/null +++ b/docs/tech-specs/structured-data.zh-cn.md @@ -0,0 +1,260 @@ +--- +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. **非结构化到结构化提取**: 读取非结构化数据源,识别和提取对象结构,并将它们存储在表格格式中。 +2. **结构化数据导入**: 将已经采用结构化格式的数据直接导入到结构化存储中,与提取的数据一起存储。 +3. **自然语言查询**: 将自然语言问题转换为结构化查询,以从存储中提取匹配的数据。 +4. **直接结构化查询**: 直接对数据存储执行结构化查询,以进行精确的数据检索。 + +## 目标 + +**统一数据访问**: 提供一个用于访问 TrustGraph 中结构化和非结构化数据的单一接口。 +**无缝集成**: 实现 TrustGraph 的基于图的知识表示与传统结构化数据格式之间的平滑互操作性。 +**灵活提取**: 支持从各种非结构化源(文档、文本等)自动提取结构化数据。 +**查询灵活性**: 允许用户使用自然语言和结构化查询语言查询数据。 +**数据一致性**: 维护不同数据表示形式之间的数据完整性和一致性。 +**性能优化**: 确保在大规模下高效地存储和检索结构化数据。 +**模式灵活性**: 支持“写时模式”和“读时模式”两种方法,以适应各种数据源。 +**向后兼容性**: 在添加结构化数据功能的同时,保留现有的 TrustGraph 功能。 + +## 背景 + +TrustGraph 目前擅长处理非结构化数据并从各种来源构建知识图。然而,许多企业用例涉及本质上是结构化的数据,例如客户记录、事务日志、库存数据库和其他表格数据集。这些结构化数据集通常需要与非结构化内容一起进行分析,以提供全面的见解。 + +当前的局限性包括: +不支持导入预结构化数据格式(CSV、JSON 数组、数据库导出)。 +无法在从文档中提取表格数据时保留其固有的结构。 +缺乏用于结构化数据模式的有效查询机制。 +SQL 样式的查询与 TrustGraph 的图查询之间的桥梁缺失。 + +本规范通过引入补充 TrustGraph 现有功能的结构化数据层来解决这些差距。通过原生支持结构化数据,TrustGraph 可以: +作为结构化和非结构化数据分析的统一平台。 +实现跨图关系和表格数据的混合查询。 +为习惯于处理结构化数据的用户提供熟悉的接口。 +释放数据集成和商业智能中的新用例。 + +## 技术设计 + +### 架构 + +结构化数据集成需要以下技术组件: + +1. **NLP-to-Structured-Query 服务** + 将自然语言问题转换为结构化查询。 + 支持多种查询语言目标(最初为 SQL 样式的语法)。 + 与现有的 TrustGraph NLP 功能集成。 + + 模块: trustgraph-flow/trustgraph/query/nlp_query/cassandra + +2. **配置模式支持** ✅ **[完成]** + 扩展配置系统以存储结构化数据模式。 + 支持定义表结构、字段类型和关系。 + 模式版本控制和迁移功能。 + +3. **对象提取模块** ✅ **[完成]** + 增强的知识提取流程集成。 + 从非结构化源识别和提取结构化对象。 + 维护溯源信息和置信度分数。 + 注册一个配置处理程序(例如:trustgraph-flow/trustgraph/prompt/template/service.py),以接收配置数据并解码模式信息。 + 接收对象并将其解码为 ExtractedObject 对象,并通过 Pulsar 队列进行传递。 + 注意:存在于 `trustgraph-flow/trustgraph/extract/object/row/` 的现有代码。这是一个之前的尝试,需要进行重大重构,因为它不符合当前的 API。如果有用,可以使用它,否则从头开始。 + 需要一个命令行界面:`kg-extract-objects` + + 模块: trustgraph-flow/trustgraph/extract/kg/objects/ + +4. **结构化存储写入模块** ✅ **[完成]** + 从 Pulsar 队列接收 ExtractedObject 格式的对象。 + 初始实现针对 Apache Cassandra 作为结构化数据存储。 + 处理基于遇到的模式动态创建表。 + 管理模式到 Cassandra 表的映射以及数据转换。 + 提供批量和流式写入操作以进行性能优化。 + 没有 Pulsar 输出 - 这是一个数据流中的终端服务。 + + **模式处理**: + 监控传入的 ExtractedObject 消息以查找模式引用。 + 首次遇到新模式时,自动创建相应的 Cassandra 表。 + 维护已知模式的缓存,以避免重复的表创建尝试。 + 应该考虑是直接接收模式定义,还是依赖于 ExtractedObject 消息中的模式名称。 + + **Cassandra 表映射**: + 键空间(Keyspace)的名称源自 ExtractedObject 的 Metadata 中的 `user` 字段。 + 表的名称源自 ExtractedObject 中的 `schema_name` 字段。 + Metadata 中的集合(Collection)成为分区键的一部分,以确保: + Cassandra 节点之间的数据自然分布。 + 特定集合内的查询效率。 + 不同数据导入/来源之间的逻辑隔离。 + 主键结构:`PRIMARY KEY ((collection, ), )` + 集合始终是分区键的第一部分。 + 遵循定义的模式的主键字段作为组合分区键的一部分。 + 这要求查询指定集合,以确保可预测的性能。 + 字段定义映射到 Cassandra 列,并进行类型转换: + `string` → `text` + `integer` → `int` 或 `bigint`,具体取决于大小提示。 + `float` → `float` 或 `double`,具体取决于精度需求。 + `boolean` → `boolean` + `timestamp` → `timestamp` + `enum` → `text`,并进行应用程序级别的验证。 + 索引字段创建 Cassandra 的二级索引(不包括主键中的字段)。 + 必需字段在应用程序级别强制执行(Cassandra 不支持 NOT NULL)。 + + **对象存储**: + 从 ExtractedObject.values 映射中提取值。 + 在插入之前执行类型转换和验证。 + 优雅地处理缺失的可选字段。 + 维护有关对象来源的元数据(源文档、置信度分数)。 + 支持幂等写入,以处理消息重放场景。 + + **实现说明**: + 位于 `trustgraph-flow/trustgraph/storage/objects/cassandra/` 的现有代码已过时,不符合当前的 API。 + 应该参考 `trustgraph-flow/trustgraph/storage/triples/cassandra` 作为工作存储处理器的示例。 + 在决定重构或重写之前,需要评估现有代码以查找任何可重用组件。 + + 模块:trustgraph-flow/trustgraph/storage/objects/cassandra + +5. **结构化查询服务** ✅ **[完成]** + 接受定义格式的结构化查询。 + 对结构化存储执行查询。 + 返回与查询条件匹配的对象。 + 支持分页和结果过滤。 + + 模块:trustgraph-flow/trustgraph/query/objects/cassandra + +6. **代理工具集成** + 用于代理框架的新工具类。 + 使代理能够查询结构化数据存储。 + 提供自然语言和结构化查询接口。 + 与现有的代理决策过程集成。 + +7. **结构化数据摄取服务** + 接受多种格式(JSON、CSV、XML)的结构化数据。 + 根据定义的模式解析和验证传入数据。 + 将数据转换为规范化的对象流。 + 将对象发送到适当的消息队列进行处理。 + 支持批量上传和流式摄取。 + + 模块:trustgraph-flow/trustgraph/decoding/structured + +8. **对象嵌入服务** + 为结构化对象生成向量嵌入。 + 启用结构化数据的语义搜索。 + 支持结合结构化查询和语义相似性的混合搜索。 + 与现有的向量存储集成。 + + 模块:trustgraph-flow/trustgraph/embeddings/object_embeddings/qdrant + +### 数据模型 + +#### 模式存储机制 + +模式存储在 TrustGraph 的配置系统中使用以下结构: + +**类型**: `schema`(所有结构化数据模式的固定值) +**键**: 模式的唯一名称/标识符(例如,`customer_records`、`transaction_log`) +**值**: 包含结构的 JSON 模式定义 + +示例配置条目: +``` +Type: schema +Key: customer_records +Value: { + "name": "customer_records", + "description": "Customer information table", + "fields": [ + { + "name": "customer_id", + "type": "string", + "primary_key": true + }, + { + "name": "name", + "type": "string", + "required": true + }, + { + "name": "email", + "type": "string", + "required": true + }, + { + "name": "registration_date", + "type": "timestamp" + }, + { + "name": "status", + "type": "string", + "enum": ["active", "inactive", "suspended"] + } + ], + "indexes": ["email", "registration_date"] +} +``` + +此方法允许: +动态模式定义,无需代码更改 +轻松的模式更新和版本控制 +与现有 TrustGraph 配置管理的一致集成 +支持在单个部署中使用的多个模式 + +### API + +新增 API: + 用于上述类型的 Pulsar 模式 + 新流程中的 Pulsar 接口 + 需要一种方法来指定模式类型,以便流程知道要加载哪些 + 模式类型 + 向网关和反向网关添加了 API + +修改后的 API: +知识提取端点 - 添加结构化对象输出选项 +代理端点 - 添加结构化数据工具支持 + +### 实施细节 + +遵循现有约定 - 这些只是新的处理模块。 +除了 trustgraph-base 中的模式项之外,所有内容都位于 trustgraph-flow 包中。 + + +需要在 Workbench 中进行一些 UI 工作,以便演示/试用此 +功能。 + +## 安全注意事项 + +没有额外的注意事项。 + +## 性能注意事项 + +关于使用 Cassandra 查询和索引的一些问题,以确保查询 +不会降低速度。 + +## 测试策略 + +使用现有的测试策略,将构建单元测试、契约测试和集成测试。 + +## 迁移计划 + +无。 + +## 时间线 + +未指定。 + +## 开放问题 + +是否可以使其与其它存储类型一起工作? 我们的目标是使用 + 接口,使适用于一种存储的模块也适用于 + 其他存储。 + +## 参考文献 + +n/a。 diff --git a/docs/tech-specs/structured-diag-service.ar.md b/docs/tech-specs/structured-diag-service.ar.md new file mode 100644 index 00000000..bcd819cb --- /dev/null +++ b/docs/tech-specs/structured-diag-service.ar.md @@ -0,0 +1,281 @@ +--- +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. تستخرج الخدمة الوظائف من أداة سطر الأوامر `tg-load-structured-data` الحالية وتعرضها كخدمة طلب/استجابة، مما يتيح الوصول البرمجي إلى قدرات اكتشاف أنواع البيانات وإنشاء الوصف. + +تدعم الخدمة ثلاث عمليات رئيسية: + +1. **اكتشاف نوع البيانات**: تحليل عينة بيانات لتحديد تنسيقها (CSV أو JSON أو XML) +2. **إنشاء الوصف**: إنشاء وصف بيانات مهيكلة لـ TrustGraph لعينة بيانات معينة ونوع +3. **التشخيص المدمج**: إجراء كل من اكتشاف النوع وإنشاء الوصف بالتسلسل + +## الأهداف + +**تجزئة تحليل البيانات**: استخراج منطق تشخيص البيانات من واجهة سطر الأوامر إلى مكونات خدمة قابلة لإعادة الاستخدام +**تمكين الوصول البرمجي**: توفير وصول قائم على واجهة برمجة التطبيقات (API) إلى قدرات تحليل البيانات +**دعم تنسيقات بيانات متعددة**: التعامل مع تنسيقات بيانات CSV و JSON و XML بشكل متسق +**إنشاء أوصاف دقيقة**: إنتاج أوصاف بيانات مهيكلة تعكس بدقة بيانات المصدر إلى مخططات TrustGraph +**الحفاظ على التوافق مع الإصدارات السابقة**: التأكد من أن وظائف واجهة سطر الأوامر الحالية تظل تعمل +**تمكين تجميع الخدمات**: السماح للخدمات الأخرى بالاستفادة من قدرات تشخيص البيانات +**تحسين إمكانية الاختبار**: فصل منطق الأعمال عن واجهة سطر الأوامر لتحسين الاختبار +**دعم التحليل المتدفق**: تمكين تحليل عينات البيانات دون تحميل الملفات بأكملها + +## الخلفية + +حاليًا، يوفر الأمر `tg-load-structured-data` وظائف شاملة لتحليل البيانات المهيكلة وإنشاء الأوصاف. ومع ذلك، فإن هذه الوظائف مرتبطة ارتباطًا وثيقًا بواجهة سطر الأوامر، مما يحد من إمكانية إعادة استخدامها. + +تشمل القيود الحالية: +منطق تشخيص البيانات مضمن في كود واجهة سطر الأوامر +لا يوجد وصول برمجي إلى اكتشاف النوع وإنشاء الوصف +من الصعب دمج قدرات التشخيص في خدمات أخرى +قدرة محدودة على تجميع سير عمل تحليل البيانات + +تعالج هذه المواصفات هذه الفجوات من خلال إنشاء خدمة مخصصة لتشخيص البيانات المهيكلة. من خلال تعريض هذه القدرات كخدمة، يمكن لـ TrustGraph: +تمكين خدمات أخرى من تحليل البيانات برمجيًا +دعم مسارات معالجة بيانات أكثر تعقيدًا +تسهيل التكامل مع الأنظمة الخارجية +تحسين قابلية الصيانة من خلال الفصل بين المهام + +## التصميم الفني + +### البنية + +تتطلب خدمة تشخيص البيانات المهيكلة المكونات الفنية التالية: + +1. **معالج خدمة التشخيص** + يتعامل مع طلبات التشخيص الواردة + يقوم بتنسيق اكتشاف النوع وإنشاء الوصف + يُرجع استجابات مهيكلة مع نتائج التشخيص + + الوحدة: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **كاشف نوع البيانات** + يستخدم الكشف الخوارزمي لتحديد تنسيق البيانات (CSV أو JSON أو XML) + يحلل هيكل البيانات والفواصل وأنماط بناء الجملة + يُرجع التنسيق المكتشف ودرجات الثقة + + الوحدة: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **مولد الوصف** + يستخدم خدمة المطالبة لإنشاء الأوصاف + يستدعي المطالبات الخاصة بالتنسيق (diagnose-csv أو diagnose-json أو diagnose-xml) + يربط حقول البيانات بحقول مخطط TrustGraph من خلال استجابات المطالبة + + الوحدة: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### نماذج البيانات + +#### StructuredDataDiagnosisRequest + +رسالة طلب لعمليات تشخيص البيانات المهيكلة: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### استجابة تشخيص البيانات المنظمة + +رسالة استجابة تحتوي على نتائج التشخيص: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### هيكل الوصف + +يتبع الوصف الناتج تنسيق الوصف المنظم للبيانات الموجود: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### واجهة الخدمة + +ستعرض الخدمة العمليات التالية من خلال نمط الطلب/الاستجابة: + +1. **عملية اكتشاف النوع** + المدخلات: عينة بيانات + المعالجة: تحليل هيكل البيانات باستخدام الكشف الخوارزمي + المخرجات: النوع المكتشف مع درجة الثقة + +2. **عملية توليد الوصف** + المدخلات: عينة بيانات، والنوع، واسم المخطط المستهدف + المعالجة: + استدعاء خدمة المطالبة بمعرف المطالبة الخاص بالتنسيق (diagnose-csv أو diagnose-json أو diagnose-xml) + تمرير عينة البيانات والمخططات المتاحة إلى المطالبة + استقبال الوصف الذي تم إنشاؤه من استجابة المطالبة + المخرجات: وصف البيانات المنظمة + +3. **عملية التشخيص المجمعة** + المدخلات: عينة بيانات، واسم المخطط (اختياري) + المعالجة: + استخدام الكشف الخوارزمي لتحديد التنسيق أولاً + تحديد معرف المطالبة الخاص بالتنسيق المناسب بناءً على النوع المكتشف + استدعاء خدمة المطالبة لإنشاء الوصف + المخرجات: كل من النوع المكتشف والوصف + +### تفاصيل التنفيذ + +ستتبع الخدمة اتفاقيات خدمة TrustGraph: + +1. **تسجيل الخدمة** + التسجيل كنوع خدمة `structured-diag` + استخدام مواضيع الطلب/الاستجابة القياسية + تنفيذ الفئة الأساسية FlowProcessor + تسجيل PromptClientSpec لتفاعل خدمة المطالبة + +2. **إدارة التكوين** + الوصول إلى تكوينات المخططات عبر خدمة التكوين + تخزين المخططات مؤقتًا لتحسين الأداء + التعامل مع تحديثات التكوين ديناميكيًا + +3. **تكامل المطالبة** + استخدام البنية التحتية الحالية لخدمة المطالبة + استدعاء خدمة المطالبة بمعرفات المطالبة الخاصة بالتنسيق: + `diagnose-csv`: لتحليل بيانات CSV + `diagnose-json`: لتحليل بيانات JSON + `diagnose-xml`: لتحليل بيانات XML + يتم تكوين المطالبات في تكوين المطالبة، وليس ترميزها بشكل ثابت في الخدمة + تمرير المخططات وعينات البيانات كمتغيرات للمطالبة + تحليل استجابات المطالبة لاستخراج الأوصاف + +4. **معالجة الأخطاء** + التحقق من صحة عينات البيانات المدخلة + توفير رسائل خطأ وصفية + التعامل مع البيانات التالفة بأمان + التعامل مع فشل خدمة المطالبة + +5. **أخذ العينات من البيانات** + معالجة أحجام العينات القابلة للتكوين + التعامل مع السجلات غير المكتملة بشكل مناسب + الحفاظ على اتساق أخذ العينات + +### تكامل واجهة برمجة التطبيقات (API) + +ستتكامل الخدمة مع واجهات برمجة تطبيقات TrustGraph الحالية: + +المكونات المعدلة: +`tg-load-structured-data` CLI - تم إعادة هيكلتها لاستخدام الخدمة الجديدة لعمليات التشخيص +Flow API - تم توسيعه لدعم طلبات تشخيص البيانات المنظمة + +نقاط نهاية الخدمة الجديدة: +`/api/v1/flow/{flow}/diagnose/structured-data` - نقطة نهاية WebSocket لطلبات التشخيص +`/api/v1/diagnose/structured-data` - نقطة نهاية REST للتشخيص المتزامن + +### تدفق الرسائل + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## اعتبارات الأمان + +التحقق من صحة الإدخال لمنع هجمات الحقن. +حدود الحجم على عينات البيانات لمنع هجمات الحرمان من الخدمة (DoS). +تنقية الواصفات التي تم إنشاؤها. +التحكم في الوصول من خلال مصادقة TrustGraph الحالية. + +## اعتبارات الأداء + +تخزين تعريفات المخططات مؤقتًا لتقليل عدد استدعاءات خدمة التكوين. +تحديد حدود لحجم العينات للحفاظ على أداء سريع الاستجابة. +استخدام المعالجة المتدفقة لعلاجات البيانات الكبيرة. +تطبيق آليات المهلة للتحليلات التي تستغرق وقتًا طويلاً. + +## استراتيجية الاختبار + +1. **اختبارات الوحدة** + اكتشاف النوع لـتنسيقات البيانات المختلفة. + دقة توليد الواصفات. + سيناريوهات معالجة الأخطاء. + +2. **اختبارات التكامل** + تدفق طلب/استجابة الخدمة. + استرجاع المخططات وتخزينها مؤقتًا. + تكامل واجهة سطر الأوامر (CLI). + +3. **اختبارات الأداء** + معالجة العينات الكبيرة. + معالجة الطلبات المتزامنة. + استخدام الذاكرة تحت الحمل. + +## خطة الترحيل + +1. **المرحلة الأولى**: تنفيذ الخدمة مع الوظائف الأساسية. +2. **المرحلة الثانية**: إعادة هيكلة واجهة سطر الأوامر (CLI) لاستخدام الخدمة (مع الحفاظ على التوافق مع الإصدارات السابقة). +3. **المرحلة الثالثة**: إضافة نقاط نهاية واجهة برمجة التطبيقات (REST API). +4. **المرحلة الرابعة**: إيقاف وظائف واجهة سطر الأوامر (CLI) المضمنة (مع إشعار مسبق). + +## الجدول الزمني + +الأسبوع 1-2: تنفيذ الخدمة الأساسية واكتشاف النوع. +الأسبوع 3-4: إضافة توليد الواصفات والتكامل. +الأسبوع 5: الاختبار والتوثيق. +الأسبوع 6: إعادة هيكلة واجهة سطر الأوامر (CLI) والترحيل. + +## أسئلة مفتوحة + +هل يجب أن تدعم الخدمة تنسيقات بيانات إضافية (مثل Parquet، Avro)؟ +ما هو الحد الأقصى لحجم العينة للتحليل؟ +هل يجب تخزين نتائج التشخيص مؤقتًا للطلبات المتكررة؟ +كيف يجب أن تتعامل الخدمة مع السيناريوهات متعددة المخططات؟ +هل يجب أن تكون معرفات المطالبات معلمات قابلة للتكوين للخدمة؟ + +## المراجع + +[مواصفات واصف البيانات المنظمة](structured-data-descriptor.md) +[توثيق تحميل البيانات المنظمة](structured-data.md) +`tg-load-structured-data` التنفيذ: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.es.md b/docs/tech-specs/structured-diag-service.es.md new file mode 100644 index 00000000..1cb49164 --- /dev/null +++ b/docs/tech-specs/structured-diag-service.es.md @@ -0,0 +1,281 @@ +--- +layout: default +title: "Especificación Técnica del Servicio de Diagnóstico de Datos Estructurados" +parent: "Spanish (Beta)" +--- + +# Especificación Técnica del Servicio de Diagnóstico de Datos Estructurados + +> **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 un nuevo servicio invocable para diagnosticar y analizar datos estructurados dentro de TrustGraph. El servicio extrae la funcionalidad de la herramienta de línea de comandos `tg-load-structured-data` existente y la expone como un servicio de solicitud/respuesta, lo que permite el acceso programático a las capacidades de detección de tipos de datos y generación de descriptores. + +El servicio admite tres operaciones principales: + +1. **Detección de Tipo de Datos**: Analiza una muestra de datos para determinar su formato (CSV, JSON o XML). +2. **Generación de Descriptores**: Genera un descriptor de datos estructurados de TrustGraph para una muestra de datos y tipo dados. +3. **Diagnóstico Combinado**: Realiza la detección de tipo y la generación de descriptores en secuencia. + +## Objetivos + +**Modularización del Análisis de Datos**: Extrae la lógica de diagnóstico de datos de la CLI en componentes de servicio reutilizables. +**Habilitar el Acceso Programático**: Proporciona acceso basado en API a las capacidades de análisis de datos. +**Admitir Múltiples Formatos de Datos**: Maneja los formatos de datos CSV, JSON y XML de manera consistente. +**Generar Descriptores Precisos**: Produce descriptores de datos estructurados que mapean con precisión los datos de origen a los esquemas de TrustGraph. +**Mantener la Compatibilidad Inversa**: Garantiza que la funcionalidad existente de la CLI continúe funcionando. +**Habilitar la Composición de Servicios**: Permite que otros servicios aprovechen las capacidades de diagnóstico de datos. +**Mejorar la Capacidad de Pruebas**: Separa la lógica de negocio de la interfaz de la CLI para una mejor prueba. +**Admitir el Análisis por Flujo**: Permite el análisis de muestras de datos sin cargar archivos completos. + +## Antecedentes + +Actualmente, el comando `tg-load-structured-data` proporciona una funcionalidad completa para analizar datos estructurados y generar descriptores. Sin embargo, esta funcionalidad está estrechamente acoplada a la interfaz de la CLI, lo que limita su reutilización. + +Las limitaciones actuales incluyen: +Lógica de diagnóstico de datos incrustada en el código de la CLI. +Sin acceso programático a la detección de tipos y la generación de descriptores. +Difícil de integrar las capacidades de diagnóstico en otros servicios. +Capacidad limitada para componer flujos de trabajo de análisis de datos. + +Esta especificación aborda estas deficiencias mediante la creación de un servicio dedicado para el diagnóstico de datos estructurados. Al exponer estas capacidades como un servicio, TrustGraph puede: +Permitir que otros servicios analicen datos de forma programática. +Admitir canalizaciones de procesamiento de datos más complejas. +Facilitar la integración con sistemas externos. +Mejorar la mantenibilidad mediante la separación de responsabilidades. + +## Diseño Técnico + +### Arquitectura + +El servicio de diagnóstico de datos estructurados requiere los siguientes componentes técnicos: + +1. **Procesador del Servicio de Diagnóstico** + Maneja las solicitudes de diagnóstico entrantes. + Orquesta la detección de tipos y la generación de descriptores. + Devuelve respuestas estructuradas con los resultados del diagnóstico. + + Módulo: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **Detector de Tipo de Datos** + Utiliza la detección algorítmica para identificar el formato de datos (CSV, JSON, XML). + Analiza la estructura de datos, los delimitadores y los patrones de sintaxis. + Devuelve el formato detectado y las puntuaciones de confianza. + + Módulo: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **Generador de Descriptores** + Utiliza el servicio de prompts para generar descriptores. + Invoca prompts específicos del formato (diagnose-csv, diagnose-json, diagnose-xml). + Mapea los campos de datos a los campos del esquema de TrustGraph a través de las respuestas del prompt. + + Módulo: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### Modelos de Datos + +#### StructuredDataDiagnosisRequest + +Mensaje de solicitud para operaciones de diagnóstico de datos estructurados: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### RespuestaDiagnósticoDatosEstructurados + +Mensaje de respuesta que contiene los resultados del diagnóstico: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### Estructura del descriptor + +El descriptor generado sigue el formato de descriptor de datos estructurados existente: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### Interfaz de Servicio + +El servicio expondrá las siguientes operaciones a través del patrón de solicitud/respuesta: + +1. **Operación de Detección de Tipo** + Entrada: Muestra de datos + Procesamiento: Analizar la estructura de datos utilizando la detección algorítmica + Salida: Tipo detectado con una puntuación de confianza + +2. **Operación de Generación de Descriptores** + Entrada: Muestra de datos, tipo, nombre del esquema de destino + Procesamiento: + Llamar al servicio de solicitud con el ID de solicitud específico del formato (diagnóstico-csv, diagnóstico-json o diagnóstico-xml) + Pasar la muestra de datos y los esquemas disponibles a la solicitud + Recibir el descriptor generado de la respuesta de la solicitud + Salida: Descriptor de datos estructurados + +3. **Operación de Diagnóstico Combinado** + Entrada: Muestra de datos, nombre de esquema opcional + Procesamiento: + Utilizar la detección algorítmica para identificar el formato primero + Seleccionar la solicitud específica del formato basada en el tipo detectado + Llamar al servicio de solicitud para generar el descriptor + Salida: Tanto el tipo detectado como el descriptor + +### Detalles de Implementación + +El servicio seguirá las convenciones del servicio TrustGraph: + +1. **Registro de Servicio** + Registrarse como tipo de servicio `structured-diag` + Utilizar temas estándar de solicitud/respuesta + Implementar la clase base FlowProcessor + Registrar PromptClientSpec para la interacción con el servicio de solicitud + +2. **Gestión de la Configuración** + Acceder a las configuraciones del esquema a través del servicio de configuración + Almacenar en caché los esquemas para mejorar el rendimiento + Manejar las actualizaciones de configuración de forma dinámica + +3. **Integración de Solicitudes** + Utilizar la infraestructura existente del servicio de solicitud + Llamar al servicio de solicitud con los ID de solicitud específicos del formato: + `diagnose-csv`: Para el análisis de datos CSV + `diagnose-json`: Para el análisis de datos JSON + `diagnose-xml`: Para el análisis de datos XML + Las solicitudes están configuradas en la configuración de la solicitud, no codificadas de forma rígida en el servicio + Pasar los esquemas y las muestras de datos como variables de la solicitud + Analizar las respuestas de la solicitud para extraer los descriptores + +4. **Manejo de Errores** + Validar las muestras de datos de entrada + Proporcionar mensajes de error descriptivos + Manejar los datos incorrectos de forma elegante + Manejar las fallas del servicio de solicitud + +5. **Muestreo de Datos** + Procesar tamaños de muestra configurables + Manejar los registros incompletos de forma adecuada + Mantener la coherencia del muestreo + +### Integración de la API + +El servicio se integrará con las API existentes de TrustGraph: + +Componentes Modificados: +`tg-load-structured-data` CLI: Refactorizado para utilizar el nuevo servicio para las operaciones de diagnóstico +Flow API: Extendido para admitir solicitudes de diagnóstico de datos estructurados + +Nuevos Puntos Finales del Servicio: +`/api/v1/flow/{flow}/diagnose/structured-data`: Punto final de WebSocket para solicitudes de diagnóstico +`/api/v1/diagnose/structured-data`: Punto final REST para el diagnóstico sincrónico + +### Flujo de Mensajes + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## Consideraciones de seguridad + +Validación de entrada para prevenir ataques de inyección +Límites de tamaño en muestras de datos para prevenir DoS +Sanitización de descriptores generados +Control de acceso a través de la autenticación TrustGraph existente + +## Consideraciones de rendimiento + +Almacenar en caché las definiciones de esquema para reducir las llamadas al servicio de configuración +Limitar los tamaños de muestra para mantener un rendimiento receptivo +Utilizar procesamiento en streaming para grandes muestras de datos +Implementar mecanismos de tiempo de espera para análisis de larga duración + +## Estrategia de pruebas + +1. **Pruebas unitarias** + Detección de tipo para varios formatos de datos + Precisión de la generación de descriptores + Escenarios de manejo de errores + +2. **Pruebas de integración** + Flujo de solicitud/respuesta del servicio + Recuperación y almacenamiento en caché del esquema + Integración de la CLI + +3. **Pruebas de rendimiento** + Procesamiento de grandes muestras + Manejo de solicitudes concurrentes + Uso de memoria bajo carga + +## Plan de migración + +1. **Fase 1**: Implementar el servicio con la funcionalidad principal +2. **Fase 2**: Refactorizar la CLI para que utilice el servicio (mantener la compatibilidad con versiones anteriores) +3. **Fase 3**: Agregar puntos finales de la API REST +4. **Fase 4**: Descartar la lógica integrada de la CLI (con un período de aviso) + +## Cronograma + +Semana 1-2: Implementar el servicio principal y la detección de tipo +Semana 3-4: Agregar la generación de descriptores y la integración +Semana 5: Pruebas y documentación +Semana 6: Refactorización de la CLI y migración + +## Preguntas abiertas + +¿Debería el servicio admitir formatos de datos adicionales (por ejemplo, Parquet, Avro)? +¿Cuál debería ser el tamaño máximo de la muestra para el análisis? +¿Deben almacenarse en caché los resultados del diagnóstico para solicitudes repetidas? +¿Cómo debe manejar el servicio los escenarios de esquemas múltiples? +¿Deben los ID de las indicaciones ser parámetros configurables para el servicio? + +## Referencias + +[Especificación del descriptor de datos estructurados](structured-data-descriptor.md) +[Documentación de carga de datos estructurados](structured-data.md) +`tg-load-structured-data` implementación: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.he.md b/docs/tech-specs/structured-diag-service.he.md new file mode 100644 index 00000000..8f4f9fff --- /dev/null +++ b/docs/tech-specs/structured-diag-service.he.md @@ -0,0 +1,281 @@ +--- +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. השירות שואב פונקציונליות מכלי שורת הפקודה הקיים `tg-load-structured-data` ומציג אותו כשירות בקשה/תגובה, ומאפשר גישה תכנותית ליכולות זיהוי סוג נתונים ויצירת תיאורים. + +השירות תומך בשלוש פעולות עיקריות: + +1. **זיהוי סוג נתונים**: ניתוח דוגמת נתונים כדי לקבוע את הפורמט שלה (CSV, JSON או XML) +2. **יצירת תיאור**: יצירת תיאור נתונים מובנים עבור דוגמת נתונים מסוימת וסוג +3. **אבחון משולב**: ביצוע גם זיהוי סוג וגם יצירת תיאור ברצף + +## מטרות + +**מודולריזציה של ניתוח נתונים**: העברת לוגיקת אבחון נתונים משורת הפקודה לרכיבי שירות הניתנים לשימוש חוזר +**אפשרות לגישה תכנותית**: מתן גישה מבוססת API ליכולות ניתוח נתונים +**תמיכה במספר פורמטים של נתונים**: טיפול בפורמטי נתונים של CSV, JSON ו-XML באופן עקבי +**יצירת תיאורים מדויקים**: יצירת תיאורי נתונים מובנים המתאימים בצורה מדויקת לנתוני המקור לתוך סכימות TrustGraph +**שמירה על תאימות לאחור**: הבטחה שפונקציונליות קיימת של שורת הפקודה תמשיך לעבוד +**אפשרות לחיבור שירותים**: לאפשר לשירותים אחרים לנצל יכולות אבחון נתונים +**שיפור יכולת בדיקה**: הפרדת לוגיקה עסקית מממשק שורת הפקודה לצורך בדיקות טובות יותר +**תמיכה בניתוח סטרימינג**: אפשרות לניתוח דוגמאות נתונים מבלי לטעון קבצים שלמים + +## רקע + +כיום, הפקודה `tg-load-structured-data` מספקת פונקציונליות מקיפה לניתוח נתונים מובנים ויצירת תיאורים. עם זאת, פונקציונליות זו קשורה הדוקות לממשק שורת הפקודה, מה שמגביל את יכולת השימוש החוזר בה. + +מגבלות נוכחיות כוללות: +לוגיקת אבחון נתונים מוטמעת בקוד שורת הפקודה +אין גישה תכנותית לזיהוי סוג ויצירת תיאורים +קשה לשלב יכולות אבחון בשירותים אחרים +יכולת מוגבלת ליצור זרימות עבודה לניתוח נתונים + +מפרט זה מתייחס לפערים אלה על ידי יצירת שירות ייעודי לאבחון נתונים מובנים. על ידי חשיפת יכולות אלה כשירות, TrustGraph יכולה: +לאפשר לשירותים אחרים לנתח נתונים באופן תכנותי +לתמוך בצינורות עיבוד נתונים מורכבים יותר +להקל על שילוב עם מערכות חיצוניות +לשפר את תחזוקת המערכת באמצעות הפרדת אחריות + +## עיצוב טכני + +### ארכיטקטורה + +שירות האבחון של נתונים מובנים דורש את הרכיבים הטכניים הבאים: + +1. **מעבד שירות אבחון** + מטפל בבקשות אבחון נכנסות + מתאם זיהוי סוג ויצירת תיאורים + מחזיר תגובות מובנות עם תוצאות אבחון + + מודול: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **מגַלֶּה סוג נתונים** + משתמש בגילוי אלגוריתמי כדי לזהות פורמט נתונים (CSV, JSON, XML) + מנתח מבנה נתונים, מפרידים ותבניות תחביר + מחזיר פורמט מזוהה וציוני אמון + + מודול: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **יוצר תיאורים** + משתמש בשירות פרומפטים כדי ליצור תיאורים + מפעיל פרומפטים ספציפיים לפורמט (diagnose-csv, diagnose-json, diagnose-xml) + ממפה שדות נתונים לשדות סכימת TrustGraph באמצעות תגובות פרומפטים + + מודול: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### מודלים של נתונים + +#### StructuredDataDiagnosisRequest + +הודעת בקשה לפעולות אבחון נתונים מובנים: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### תגובת אבחון נתונים מובנים + +הודעת תגובה המכילה תוצאות אבחון: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### מבנה תיאור + +התיאור שנוצר עוקב אחר פורמט התיאור המובנה הקיים: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### ממשק שירות + +השירות יחשוף את הפעולות הבאות באמצעות תבנית בקשה/תגובה: + +1. **פעולת זיהוי סוג** + קלט: דוגמת נתונים + עיבוד: ניתוח מבנה הנתונים באמצעות זיהוי אלגוריתמי + פלט: סוג מזוהה עם ציון אמון + +2. **פעולת יצירת תיאור** + קלט: דוגמת נתונים, סוג, שם סכימה יעד + עיבוד: + הפעלת שירות הפרומפט עם מזהה הפרומפט הספציפי לפורמט (diagnose-csv, diagnose-json או diagnose-xml) + העברת דוגמת הנתונים והסכימות הזמינות לפרומפט + קבלת התיאור שנוצר מתגובת הפרומפט + פלט: תיאור נתונים מובנים + +3. **פעולת אבחון משולבת** + קלט: דוגמת נתונים, שם סכימה אופציונלי + עיבוד: + שימוש בזיהוי אלגוריתמי לזיהוי הפורמט תחילה + בחירת פרומפט ספציפי לפורמט בהתאם לסוג המזוהה + הפעלת שירות הפרומפט ליצירת תיאור + פלט: גם הסוג המזוהה וגם התיאור + +### פרטי יישום + +השירות יפעל בהתאם לקונבנציות של שירות TrustGraph: + +1. **רישום שירות** + רישום כסוג שירות `structured-diag` + שימוש בנושאים סטנדרטיים של בקשה/תגובה + יישום מחלקת FlowProcessor בסיסית + רישום PromptClientSpec עבור אינטראקציה עם שירות הפרומפט + +2. **ניהול תצורה** + גישה לתצורות סכימה באמצעות שירות התצורה + שמירת סכימות במטמון לביצועים + טיפול בעדכוני תצורה באופן דינמי + +3. **שילוב פרומפט** + שימוש בתשתית קיימת של שירות הפרומפט + הפעלת שירות הפרומפט עם מזהי פרומפט ספציפיים לפורמט: + `diagnose-csv`: לניתוח נתוני CSV + `diagnose-json`: לניתוח נתוני JSON + `diagnose-xml`: לניתוח נתוני XML + הפרומפטים מוגדרים בתצורת הפרומפט, ולא מקודדים קשות בשירות + העברת סכימות ודוגמאות נתונים כמשתני פרומפט + ניתוח תגובות פרומפט לחילוץ תיאורים + +4. **טיפול בשגיאות** + אימות דוגמאות נתונים + מתן הודעות שגיאה תיאוריות + טיפול מסודר בנתונים פגומים + טיפול בכשלים בשירות הפרומפט + +5. **דגימת נתונים** + עיבוד גדלי דגימה הניתנים לתצורה + טיפול מתאים ברשומות חסרות + שמירה על עקביות דגימה + +### שילוב API + +השירות ישולב עם ממשקי TrustGraph קיימים: + +רכיבים שעברו שינוי: +`tg-load-structured-data` CLI - שופץ לשימוש בשירות החדש לפעולות אבחון +Flow API - הורחב לתמיכה בבקשות אבחון נתונים מובנים + +נקודות שירות חדשות: +`/api/v1/flow/{flow}/diagnose/structured-data` - נקודת קצה WebSocket לבקשות אבחון +`/api/v1/diagnose/structured-data` - נקודת קצה REST לאבחון סינכרוני + +### זרימת הודעות + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## שיקולי אבטחה + +אימות קלט למניעת התקפות הזרקה +מגבלות גודל על דוגמאות נתונים למניעת התקפות מניעת שירות (DoS) +ניקוי של מזהים שנוצרו +בקרת גישה באמצעות אימות TrustGraph הקיים + +## שיקולי ביצועים + +שמירת הגדרות סכימה במטמון להפחתת קריאות לשירות התצורה +הגבלת גודל הדוגמאות לשמירה על ביצועים מהירים +שימוש בעיבוד סטרימינג עבור דוגמאות נתונים גדולות +הטמעת מנגנוני זמן קצוב עבור ניתוחים ארוכים + +## אסטרטגיית בדיקות + +1. **בדיקות יחידה** + זיהוי סוג עבור פורמטי נתונים שונים + דיוק יצירת מזהים + תרחישי טיפול בשגיאות + +2. **בדיקות אינטגרציה** + זרימת בקשות/תגובות של שירות + שליפה ושמירה במטמון של סכימות + אינטגרציה עם שורת הפקודה (CLI) + +3. **בדיקות ביצועים** + עיבוד של דוגמאות גדולות + טיפול בבקשות מקבילות + שימוש בזיכרון בתנאי עומס + +## תוכנית מעבר + +1. **שלב 1**: הטמעת שירות עם פונקציונליות בסיסית +2. **שלב 2**: שינוי שורת הפקודה (CLI) לשימוש בשירות (שמירה על תאימות לאחור) +3. **שלב 3**: הוספת נקודות קצה של ממשק API REST +4. **שלב 4**: הפסקת השימוש בלוגיקה מוטמעת של שורת הפקודה (עם תקופת התראה) + +## ציר זמן + +שבוע 1-2: הטמעת שירות וזיהוי סוג בסיסי +שבוע 3-4: הוספת יצירת מזהים ואינטגרציה +שבוע 5: בדיקות ותיעוד +שבוע 6: שינוי שורת הפקודה (CLI) ומעבר + +## שאלות פתוחות + +האם השירות צריך לתמוך בפורמטי נתונים נוספים (לדוגמה, Parquet, Avro)? +מהו גודל הדוגמה המקסימלי לניתוח? +האם תוצאות האבחון צריכות להיות שמורות במטמון עבור בקשות חוזרות? +כיצד השירות צריך להתמודד עם תרחישים של סכימות מרובות? +האם מזהי הבקשות צריכים להיות פרמטרים הניתנים להגדרה עבור השירות? + +## הפניות + +[מפרט מזהה נתונים מובנים](structured-data-descriptor.md) +[תיעוד טעינת נתונים מובנים](structured-data.md) +`tg-load-structured-data` יישום: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.hi.md b/docs/tech-specs/structured-diag-service.hi.md new file mode 100644 index 00000000..3689648c --- /dev/null +++ b/docs/tech-specs/structured-diag-service.hi.md @@ -0,0 +1,281 @@ +--- +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. + +## अवलोकन + +यह स्पेसिफिकेशन ट्रस्टग्राफ के भीतर संरचित डेटा का निदान और विश्लेषण करने के लिए एक नए इनवोकेबल सर्विस का वर्णन करता है। यह सर्विस मौजूदा `tg-load-structured-data` कमांड-लाइन टूल से कार्यक्षमता निकालती है और इसे एक अनुरोध/प्रतिक्रिया सेवा के रूप में प्रस्तुत करती है, जिससे डेटा प्रकार का पता लगाने और विवरण पीढ़ी क्षमताओं तक प्रोग्रामेटिक पहुंच सक्षम होती है। + +यह सेवा तीन प्राथमिक कार्यों का समर्थन करती है: + +1. **डेटा टाइप डिटेक्शन**: यह निर्धारित करने के लिए कि इसका प्रारूप क्या है (CSV, JSON, या XML), एक डेटा नमूने का विश्लेषण करें। +2. **डिस्क्रिप्टर जेनरेशन**: दिए गए डेटा नमूने और प्रकार के लिए एक ट्रस्टग्राफ संरचित डेटा विवरण उत्पन्न करें। +3. **संयुक्त निदान**: अनुक्रम में डेटा प्रकार का पता लगाने और विवरण पीढ़ी दोनों करें। + +## लक्ष्य + +**डेटा विश्लेषण का मॉड्यूलरकरण**: CLI से डेटा निदान तर्क को पुन: प्रयोज्य सेवा घटकों में निकालें। +**प्रोग्रामेटिक एक्सेस सक्षम करें**: डेटा विश्लेषण क्षमताओं तक API-आधारित पहुंच प्रदान करें। +**एकाधिक डेटा प्रारूपों का समर्थन करें**: CSV, JSON और XML डेटा प्रारूपों को लगातार संभालें। +**सटीक विवरण उत्पन्न करें**: संरचित डेटा विवरण उत्पन्न करें जो स्रोत डेटा को ट्रस्टग्राफ स्कीमा से सटीक रूप से मैप करते हैं। +**पिछला संगतता बनाए रखें**: सुनिश्चित करें कि मौजूदा CLI कार्यक्षमता जारी रहती है। +**सेवा रचना को सक्षम करें**: अन्य सेवाओं को डेटा निदान क्षमताओं का लाभ उठाने दें। +**परीक्षण क्षमता में सुधार करें**: बेहतर परीक्षण के लिए CLI इंटरफ़ेस से व्यावसायिक तर्क को अलग करें। +**स्ट्रीमिंग विश्लेषण का समर्थन करें**: संपूर्ण फ़ाइलों को लोड किए बिना डेटा नमूनों का विश्लेषण सक्षम करें। + +## पृष्ठभूमि + +वर्तमान में, `tg-load-structured-data` कमांड संरचित डेटा का विश्लेषण करने और विवरण उत्पन्न करने के लिए व्यापक कार्यक्षमता प्रदान करता है। हालाँकि, यह कार्यक्षमता CLI इंटरफ़ेस से दृढ़ता से जुड़ी हुई है, जो इसकी पुन: प्रयोज्यता को सीमित करती है। + +वर्तमान सीमाएँ शामिल हैं: +CLI कोड में एम्बेडेड डेटा निदान तर्क। +डेटा प्रकार का पता लगाने और विवरण पीढ़ी तक कोई प्रोग्रामेटिक पहुंच नहीं। +अन्य सेवाओं में निदान क्षमताओं को एकीकृत करना मुश्किल है। +डेटा विश्लेषण वर्कफ़्लो को संयोजित करने की सीमित क्षमता। + +यह स्पेसिफिकेशन इन कमियों को एक समर्पित संरचित डेटा निदान सेवा बनाकर संबोधित करता है। इन क्षमताओं को एक सेवा के रूप में उजागर करके, ट्रस्टग्राफ: +अन्य सेवाओं को डेटा का प्रोग्रामेटिक रूप से विश्लेषण करने में सक्षम बनाता है। +अधिक जटिल डेटा प्रसंस्करण पाइपलाइन का समर्थन करता है। +बाहरी प्रणालियों के साथ एकीकरण को सुविधाजनक बनाता है। +चिंताओं के अलगाव के माध्यम से रखरखाव में सुधार करता है। + +## तकनीकी डिजाइन + +### आर्किटेक्चर + +संरचित डेटा निदान सेवा के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है: + +1. **डायग्नोस्टिक सर्विस प्रोसेसर** + आने वाले निदान अनुरोधों को संभालता है। + डेटा प्रकार का पता लगाने और विवरण पीढ़ी का समन्वय करता है। + निदान परिणामों के साथ संरचित प्रतिक्रियाएँ लौटाता है। + + मॉड्यूल: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **डेटा टाइप डिटेक्टर** + डेटा प्रारूप (CSV, JSON, XML) की पहचान करने के लिए एल्गोरिथम का उपयोग करता है। + पता लगाए गए प्रारूप और आत्मविश्वास स्कोर लौटाता है। + पता लगाए गए प्रारूप और आत्मविश्वास स्कोर वापस करता है। + + मॉड्यूल: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **डिस्क्रिप्टर जेनरेटर** + विवरण उत्पन्न करने के लिए प्रॉम्प्ट सेवा का उपयोग करता है। + प्रारूप-विशिष्ट प्रॉम्प्ट (diagnose-csv, diagnose-json, diagnose-xml) को लागू करता है। + डेटा फ़ील्ड को प्रॉम्प्ट प्रतिक्रियाओं के माध्यम से ट्रस्टग्राफ स्कीमा फ़ील्ड में मैप करता है। + + मॉड्यूल: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### डेटा मॉडल + +#### StructuredDataDiagnosisRequest + +संरचित डेटा निदान कार्यों के लिए अनुरोध संदेश: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### संरचित डेटा निदान प्रतिक्रिया + +निदान परिणामों को शामिल करने वाला प्रतिक्रिया संदेश: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### विवरण संरचना + +उत्पन्न विवरण मौजूदा संरचित डेटा विवरण प्रारूप का पालन करता है: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### सेवा इंटरफ़ेस + +यह सेवा अनुरोध/प्रतिक्रिया पैटर्न के माध्यम से निम्नलिखित कार्यों को प्रदान करेगी: + +1. **टाइप डिटेक्शन ऑपरेशन** + इनपुट: डेटा नमूना + प्रसंस्करण: एल्गोरिथम डिटेक्शन का उपयोग करके डेटा संरचना का विश्लेषण करें + आउटपुट: पता लगाए गए प्रकार के साथ आत्मविश्वास स्कोर + +2. **डिस्क्रिप्टर जनरेशन ऑपरेशन** + इनपुट: डेटा नमूना, प्रकार, लक्षित स्कीमा नाम + प्रसंस्करण: + प्रारूप-विशिष्ट प्रॉम्प्ट आईडी (diagnose-csv, diagnose-json, या diagnose-xml) के साथ प्रॉम्प्ट सेवा को कॉल करें + डेटा नमूना और उपलब्ध स्कीमा को प्रॉम्प्ट में पास करें + प्रॉम्प्ट प्रतिक्रिया से उत्पन्न डिस्क्रिप्टर प्राप्त करें + आउटपुट: संरचित डेटा डिस्क्रिप्टर + +3. **संयुक्त निदान ऑपरेशन** + इनपुट: डेटा नमूना, वैकल्पिक स्कीमा नाम + प्रसंस्करण: + पहले एल्गोरिथम डिटेक्शन का उपयोग करके प्रारूप की पहचान करें + पता लगाए गए प्रकार के आधार पर उपयुक्त प्रारूप-विशिष्ट प्रॉम्प्ट का चयन करें + डिस्क्रिप्टर उत्पन्न करने के लिए प्रॉम्प्ट सेवा को कॉल करें + आउटपुट: पता लगाए गए प्रकार और डिस्क्रिप्टर दोनों + +### कार्यान्वयन विवरण + +यह सेवा TrustGraph सेवा सम्मेलनों का पालन करेगी: + +1. **सेवा पंजीकरण** + `structured-diag` सेवा प्रकार के रूप में पंजीकृत करें + मानक अनुरोध/प्रतिक्रिया विषयों का उपयोग करें + FlowProcessor बेस क्लास को लागू करें + प्रॉम्प्ट सेवा के साथ इंटरैक्शन के लिए PromptClientSpec को पंजीकृत करें + +2. **कॉन्फ़िगरेशन प्रबंधन** + कॉन्फ़िग सेवा के माध्यम से स्कीमा कॉन्फ़िगरेशन तक पहुंचें + प्रदर्शन के लिए स्कीमा को कैश करें + गतिशील रूप से कॉन्फ़िगरेशन अपडेट को संभालें + +3. **प्रॉम्प्ट एकीकरण** + मौजूदा प्रॉम्प्ट सेवा बुनियादी ढांचे का उपयोग करें + प्रारूप-विशिष्ट प्रॉम्प्ट आईडी के साथ प्रॉम्प्ट सेवा को कॉल करें: + `diagnose-csv`: CSV डेटा विश्लेषण के लिए + `diagnose-json`: JSON डेटा विश्लेषण के लिए + `diagnose-xml`: XML डेटा विश्लेषण के लिए + प्रॉम्प्ट सेवा में कॉन्फ़िगर किए गए हैं, सेवा में हार्ड-कोडेड नहीं हैं + स्कीमा और डेटा नमूने को प्रॉम्प्ट चर के रूप में पास करें + डिस्क्रिप्टर निकालने के लिए प्रॉम्प्ट प्रतिक्रियाओं को पार्स करें + +4. **त्रुटि प्रबंधन** + इनपुट डेटा नमूनों को मान्य करें + वर्णनात्मक त्रुटि संदेश प्रदान करें + खराब डेटा को शालीनता से संभालें + प्रॉम्प्ट सेवा विफलताओं को संभालें + +5. **डेटा नमूनाकरण** + कॉन्फ़िगर करने योग्य नमूना आकारों को संसाधित करें + अधूरी रिकॉर्ड को उचित रूप से संभालें + नमूनाकरण स्थिरता बनाए रखें + +### एपीआई एकीकरण + +यह सेवा मौजूदा TrustGraph एपीआई के साथ एकीकृत होगी: + +संशोधित घटक: +`tg-load-structured-data` CLI - निदान कार्यों के लिए नई सेवा का उपयोग करने के लिए रिफैक्टर किया गया +फ्लो एपीआई - संरचित डेटा निदान अनुरोधों का समर्थन करने के लिए विस्तारित + +नए सेवा एंडपॉइंट: +`/api/v1/flow/{flow}/diagnose/structured-data` - निदान अनुरोधों के लिए वेबसॉकेट एंडपॉइंट +`/api/v1/diagnose/structured-data` - सिंक्रोनस निदान के लिए REST एंडपॉइंट + +### संदेश प्रवाह + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## सुरक्षा संबंधी विचार + +इंजेक्शन हमलों को रोकने के लिए इनपुट सत्यापन +DoS को रोकने के लिए डेटा नमूनों पर आकार सीमाएं +उत्पन्न विवरणों का सैनिटाइजेशन +मौजूदा ट्रस्टग्राफ प्रमाणीकरण के माध्यम से एक्सेस नियंत्रण + +## प्रदर्शन संबंधी विचार + +कॉन्फ़िगरेशन सेवा कॉल को कम करने के लिए स्कीमा परिभाषाओं को कैश करें +उत्तरदायी प्रदर्शन बनाए रखने के लिए नमूना आकारों को सीमित करें +बड़े डेटा नमूनों के लिए स्ट्रीमिंग प्रोसेसिंग का उपयोग करें +लंबे समय तक चलने वाले विश्लेषणों के लिए टाइमआउट तंत्र लागू करें + +## परीक्षण रणनीति + +1. **इकाई परीक्षण** + विभिन्न डेटा प्रारूपों के लिए प्रकार का पता लगाना + विवरण पीढ़ी की सटीकता + त्रुटि हैंडलिंग परिदृश्य + +2. **एकीकरण परीक्षण** + सेवा अनुरोध/प्रतिक्रिया प्रवाह + स्कीमा पुनर्प्राप्ति और कैशिंग + CLI एकीकरण + +3. **प्रदर्शन परीक्षण** + बड़े नमूने प्रसंस्करण + समवर्ती अनुरोध हैंडलिंग + लोड के तहत मेमोरी उपयोग + +## माइग्रेशन योजना + +1. **चरण 1**: मुख्य कार्यक्षमता के साथ सेवा लागू करें +2. **चरण 2**: CLI को सेवा का उपयोग करने के लिए रिफैक्टर करें (पिछड़ी संगतता बनाए रखें) +3. **चरण 3**: REST API एंडपॉइंट जोड़ें +4. **चरण 4**: एम्बेडेड CLI लॉजिक को अप्रचलित करें (सूचना अवधि के साथ) + +## समयरेखा + +सप्ताह 1-2: मुख्य सेवा और प्रकार का पता लगाना लागू करें +सप्ताह 3-4: विवरण पीढ़ी और एकीकरण जोड़ें +सप्ताह 5: परीक्षण और दस्तावेज़ीकरण +सप्ताह 6: CLI रिफैक्टरिंग और माइग्रेशन + +## खुले प्रश्न + +क्या सेवा को अतिरिक्त डेटा प्रारूपों (जैसे, Parquet, Avro) का समर्थन करना चाहिए? +विश्लेषण के लिए अधिकतम नमूना आकार क्या होना चाहिए? +क्या निदान परिणाम बार-बार अनुरोधों के लिए कैश किए जाने चाहिए? +सेवा को मल्टी-स्कीमा परिदृश्यों को कैसे संभालना चाहिए? +क्या प्रॉम्प्ट आईडी सेवा के लिए कॉन्फ़िगर करने योग्य पैरामीटर होने चाहिए? + +## संदर्भ + +[स्ट्रक्चर्ड डेटा डिस्क्रिप्टर विनिर्देश](structured-data-descriptor.md) +[स्ट्रक्चर्ड डेटा लोडिंग दस्तावेज़](structured-data.md) +`tg-load-structured-data` कार्यान्वयन: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.md b/docs/tech-specs/structured-diag-service.md index 1eab9df2..dcc84e82 100644 --- a/docs/tech-specs/structured-diag-service.md +++ b/docs/tech-specs/structured-diag-service.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Structured Data Diagnostic Service Technical Specification" +parent: "Tech Specs" +--- + # Structured Data Diagnostic Service Technical Specification ## Overview @@ -270,4 +276,4 @@ Client ← Gateway ← Structured Diag Service (response) - [Structured Data Descriptor Specification](structured-data-descriptor.md) - [Structured Data Loading Documentation](structured-data.md) -- `tg-load-structured-data` implementation: `trustgraph-cli/trustgraph/cli/load_structured_data.py` \ No newline at end of file +- `tg-load-structured-data` implementation: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.pt.md b/docs/tech-specs/structured-diag-service.pt.md new file mode 100644 index 00000000..a331002e --- /dev/null +++ b/docs/tech-specs/structured-diag-service.pt.md @@ -0,0 +1,281 @@ +--- +layout: default +title: "Especificação Técnica do Serviço de Diagnóstico de Dados Estruturados" +parent: "Portuguese (Beta)" +--- + +# Especificação Técnica do Serviço de Diagnóstico de Dados Estruturados + +> **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 um novo serviço invocável para diagnosticar e analisar dados estruturados dentro do TrustGraph. O serviço extrai a funcionalidade da ferramenta de linha de comando existente `tg-load-structured-data` e a expõe como um serviço de solicitação/resposta, permitindo o acesso programático às capacidades de detecção de tipo de dados e geração de descritores. + +O serviço suporta três operações principais: + +1. **Detecção de Tipo de Dados**: Analisa uma amostra de dados para determinar seu formato (CSV, JSON ou XML) +2. **Geração de Descritor**: Gera um descritor de dados estruturados do TrustGraph para uma determinada amostra de dados e tipo +3. **Diagnóstico Combinado**: Realiza a detecção de tipo e a geração de descritor em sequência + +## Objetivos + +**Modularização da Análise de Dados**: Extrai a lógica de diagnóstico de dados da CLI para componentes de serviço reutilizáveis +**Habilitar Acesso Programático**: Fornecer acesso baseado em API às capacidades de análise de dados +**Suportar Múltiplos Formatos de Dados**: Lidar com formatos de dados CSV, JSON e XML de forma consistente +**Gerar Descritores Precisos**: Produzir descritores de dados estruturados que mapeiem com precisão os dados de origem para os esquemas do TrustGraph +**Manter a Compatibilidade com Versões Anteriores**: Garantir que a funcionalidade existente da CLI continue a funcionar +**Habilitar a Composição de Serviços**: Permitir que outros serviços aproveitem as capacidades de diagnóstico de dados +**Melhorar a Testabilidade**: Separar a lógica de negócios da interface da CLI para melhor teste +**Suportar a Análise em Streaming**: Permitir a análise de amostras de dados sem carregar arquivos inteiros + +## Contexto + +Atualmente, o comando `tg-load-structured-data` fornece funcionalidade abrangente para analisar dados estruturados e gerar descritores. No entanto, essa funcionalidade está fortemente acoplada à interface da CLI, limitando sua reutilização. + +As limitações atuais incluem: +Lógica de diagnóstico de dados incorporada no código da CLI +Sem acesso programático à detecção de tipo e à geração de descritores +Difícil integrar as capacidades de diagnóstico em outros serviços +Capacidade limitada de compor fluxos de trabalho de análise de dados + +Esta especificação aborda essas lacunas, criando um serviço dedicado para o diagnóstico de dados estruturados. Ao expor essas capacidades como um serviço, o TrustGraph pode: +Permitir que outros serviços analisem dados programaticamente +Suportar pipelines de processamento de dados mais complexos +Facilitar a integração com sistemas externos +Melhorar a manutenção por meio da separação de responsabilidades + +## Design Técnico + +### Arquitetura + +O serviço de diagnóstico de dados estruturados requer os seguintes componentes técnicos: + +1. **Processador do Serviço de Diagnóstico** + Lida com solicitações de diagnóstico recebidas + Orquestra a detecção de tipo e a geração de descritores + Retorna respostas estruturadas com os resultados do diagnóstico + + Módulo: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **Detector de Tipo de Dados** + Usa a detecção algorítmica para identificar o formato de dados (CSV, JSON, XML) + Analisa a estrutura de dados, delimitadores e padrões de sintaxe + Retorna o formato detectado e as pontuações de confiança + + Módulo: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **Gerador de Descritores** + Usa o serviço de prompt para gerar descritores + Invoca prompts específicos do formato (diagnosticar-csv, diagnosticar-json, diagnosticar-xml) + Mapeia campos de dados para campos de esquema do TrustGraph por meio de respostas de prompt + + Módulo: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### Modelos de Dados + +#### StructuredDataDiagnosisRequest + +Mensagem de solicitação para operações de diagnóstico de dados estruturados: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### StructuredDataDiagnosisResponse + +Mensagem de resposta contendo os resultados do diagnóstico: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### Estrutura do Descritor + +O descritor gerado segue o formato existente de descritor de dados estruturados: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### Interface de Serviço + +O serviço exporá as seguintes operações através do padrão de solicitação/resposta: + +1. **Operação de Detecção de Tipo** + Entrada: Amostra de dados + Processamento: Analisar a estrutura de dados usando detecção algorítmica + Saída: Tipo detectado com pontuação de confiança + +2. **Operação de Geração de Descritor** + Entrada: Amostra de dados, tipo, nome do esquema de destino + Processamento: + Chamar o serviço de prompt com o ID de prompt específico do formato (diagnosticar-csv, diagnosticar-json ou diagnosticar-xml) + Passar a amostra de dados e os esquemas disponíveis para o prompt + Receber o descritor gerado da resposta do prompt + Saída: Descritor de dados estruturados + +3. **Operação de Diagnóstico Combinado** + Entrada: Amostra de dados, nome de esquema opcional + Processamento: + Usar a detecção algorítmica para identificar o formato primeiro + Selecionar o prompt específico do formato apropriado com base no tipo detectado + Chamar o serviço de prompt para gerar o descritor + Saída: Tanto o tipo detectado quanto o descritor + +### Detalhes da Implementação + +O serviço seguirá as convenções do serviço TrustGraph: + +1. **Registro de Serviço** + Registrar como tipo de serviço `structured-diag` + Usar tópicos padrão de solicitação/resposta + Implementar a classe base FlowProcessor + Registrar PromptClientSpec para a interação com o serviço de prompt + +2. **Gerenciamento de Configuração** + Acessar as configurações do esquema através do serviço de configuração + Armazenar em cache os esquemas para desempenho + Lidar com atualizações de configuração dinamicamente + +3. **Integração de Prompt** + Usar a infraestrutura existente do serviço de prompt + Chamar o serviço de prompt com IDs de prompt específicos do formato: + `diagnose-csv`: Para análise de dados CSV + `diagnose-json`: Para análise de dados JSON + `diagnose-xml`: Para análise de dados XML + Os prompts são configurados na configuração do prompt, e não codificados no serviço + Passar esquemas e amostras de dados como variáveis de prompt + Analisar as respostas do prompt para extrair os descritores + +4. **Tratamento de Erros** + Validar as amostras de dados de entrada + Fornecer mensagens de erro descritivas + Lidar com dados malformados de forma elegante + Lidar com falhas no serviço de prompt + +5. **Amostragem de Dados** + Processar tamanhos de amostra configuráveis + Lidar com registros incompletos de forma apropriada + Manter a consistência da amostragem + +### Integração de API + +O serviço será integrado com as APIs TrustGraph existentes: + +Componentes Modificados: +`tg-load-structured-data` CLI - Refatorado para usar o novo serviço para operações de diagnóstico +Flow API - Estendido para suportar solicitações de diagnóstico de dados estruturados + +Novos Pontos de Extremidade do Serviço: +`/api/v1/flow/{flow}/diagnose/structured-data` - Endpoint WebSocket para solicitações de diagnóstico +`/api/v1/diagnose/structured-data` - Endpoint REST para diagnóstico síncrono + +### Fluxo de Mensagens + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## Considerações de Segurança + +Validação de entrada para prevenir ataques de injeção +Limites de tamanho em amostras de dados para prevenir ataques de negação de serviço (DoS) +Sanitização de descritores gerados +Controle de acesso através da autenticação TrustGraph existente + +## Considerações de Desempenho + +Cache de definições de esquema para reduzir o número de chamadas ao serviço de configuração +Limitar o tamanho das amostras para manter um desempenho responsivo +Usar processamento em fluxo para grandes amostras de dados +Implementar mecanismos de timeout para análises de longa duração + +## Estratégia de Testes + +1. **Testes Unitários** + Detecção de tipo para vários formatos de dados + Precisão da geração de descritores + Cenários de tratamento de erros + +2. **Testes de Integração** + Fluxo de solicitação/resposta do serviço + Recuperação e cache de esquema + Integração com a interface de linha de comando (CLI) + +3. **Testes de Desempenho** + Processamento de grandes amostras + Tratamento de solicitações concorrentes + Uso de memória sob carga + +## Plano de Migração + +1. **Fase 1**: Implementar o serviço com a funcionalidade principal +2. **Fase 2**: Refatorar a CLI para usar o serviço (manter a compatibilidade com versões anteriores) +3. **Fase 3**: Adicionar endpoints de API REST +4. **Fase 4**: Descontinuar a lógica da CLI incorporada (com aviso prévio) + +## Cronograma + +Semana 1-2: Implementar o serviço principal e a detecção de tipo +Semana 3-4: Adicionar geração de descritores e integração +Semana 5: Testes e documentação +Semana 6: Refatoração da CLI e migração + +## Perguntas Abertas + +O serviço deve suportar formatos de dados adicionais (por exemplo, Parquet, Avro)? +Qual deve ser o tamanho máximo da amostra para análise? +Os resultados do diagnóstico devem ser armazenados em cache para solicitações repetidas? +Como o serviço deve lidar com cenários de vários esquemas? +Os IDs de prompt devem ser parâmetros configuráveis para o serviço? + +## Referências + +[Especificação do Descritor de Dados Estruturados](structured-data-descriptor.md) +[Documentação de Carregamento de Dados Estruturados](structured-data.md) +`tg-load-structured-data` implementação: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.ru.md b/docs/tech-specs/structured-diag-service.ru.md new file mode 100644 index 00000000..4f239876 --- /dev/null +++ b/docs/tech-specs/structured-diag-service.ru.md @@ -0,0 +1,281 @@ +--- +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. Сервис извлекает функциональность из существующего инструмента командной строки `tg-load-structured-data` и предоставляет ее в виде сервиса запросов/ответов, обеспечивая программный доступ к возможностям определения типа данных и генерации описаний. + +Сервис поддерживает три основные операции: + +1. **Определение типа данных**: Анализ образца данных для определения его формата (CSV, JSON или XML). +2. **Генерация описания**: Генерация структурированного описания данных TrustGraph для заданного образца данных и типа. +3. **Комплексная диагностика**: Выполнение как определения типа данных, так и генерации описания последовательно. + +## Цели + +**Модулизация анализа данных**: Извлечение логики диагностики данных из интерфейса командной строки в многократно используемые компоненты сервиса. +**Обеспечение программного доступа**: Предоставление API для доступа к возможностям анализа данных. +**Поддержка нескольких форматов данных**: Обработка форматов данных CSV, JSON и XML согласованным образом. +**Генерация точных описаний**: Создание структурированных описаний данных, которые точно сопоставляют исходные данные со схемами TrustGraph. +**Сохранение обратной совместимости**: Обеспечение продолжения работы существующей функциональности интерфейса командной строки. +**Обеспечение возможности объединения сервисов**: Предоставление другим сервисам возможности использования возможностей диагностики данных. +**Улучшение тестируемости**: Разделение бизнес-логики от интерфейса командной строки для улучшения тестирования. +**Поддержка потоковой обработки**: Обеспечение возможности анализа образцов данных без загрузки целых файлов. + +## Обзор + +В настоящее время команда `tg-load-structured-data` предоставляет комплексную функциональность для анализа структурированных данных и генерации описаний. Однако эта функциональность тесно связана с интерфейсом командной строки, что ограничивает ее повторное использование. + +Существующие ограничения включают: +Логика диагностики данных, встроенная в код интерфейса командной строки. +Отсутствие программного доступа к определению типа данных и генерации описаний. +Сложность интеграции возможностей диагностики в другие сервисы. +Ограниченная возможность создания рабочих процессов анализа данных. + +Эта спецификация решает эти проблемы, создавая специальный сервис для диагностики структурированных данных. Предоставляя эти возможности в виде сервиса, TrustGraph может: +Обеспечить возможность другим сервисам программного анализа данных. +Поддерживать более сложные конвейеры обработки данных. +Облегчить интеграцию с внешними системами. +Улучшить поддерживаемость за счет разделения ответственности. + +## Технический дизайн + +### Архитектура + +Сервису диагностики структурированных данных требуются следующие технические компоненты: + +1. **Процессор сервиса диагностики** + Обрабатывает входящие запросы на диагностику. + Координирует определение типа данных и генерацию описаний. + Возвращает структурированные ответы с результатами диагностики. + + Модуль: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **Детектор типа данных** + Использует алгоритмическое определение для идентификации формата данных (CSV, JSON, XML). + Анализирует структуру данных, разделители и шаблоны синтаксиса. + Возвращает определенный формат и коэффициенты достоверности. + + Модуль: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **Генератор описаний** + Использует сервис запросов для генерации описаний. + Вызывает специфичные для формата запросы (diagnose-csv, diagnose-json, diagnose-xml). + Отображает поля данных на поля схемы TrustGraph с помощью ответов запросов. + + Модуль: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### Модели данных + +#### StructuredDataDiagnosisRequest + +Сообщение запроса для операций диагностики структурированных данных: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### StructuredDataDiagnosisResponse + +Сообщение ответа, содержащее результаты диагностики: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### Структура дескриптора + +Сгенерированный дескриптор соответствует существующему формату структурированного дескриптора данных: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### Интерфейс сервиса + +Сервис будет предоставлять следующие операции с использованием шаблона запрос/ответ: + +1. **Операция определения типа** + Входные данные: Образец данных + Обработка: Анализ структуры данных с использованием алгоритмического определения + Выходные данные: Определенный тип с уровнем достоверности + +2. **Операция генерации дескриптора** + Входные данные: Образец данных, тип, имя целевой схемы + Обработка: + Вызов сервиса запросов с идентификатором запроса, специфичным для формата (diagnose-csv, diagnose-json или diagnose-xml) + Передача образца данных и доступных схем в запрос + Получение сгенерированного дескриптора из ответа запроса + Выходные данные: Структурированный дескриптор данных + +3. **Комплексная операция диагностики** + Входные данные: Образец данных, необязательное имя схемы + Обработка: + Использование алгоритмического определения для определения формата + Выбор соответствующего запроса, специфичного для формата, на основе определенного типа + Вызов сервиса запросов для генерации дескриптора + Выходные данные: Определенный тип и дескриптор + +### Детали реализации + +Сервис будет соответствовать соглашениям сервиса TrustGraph: + +1. **Регистрация сервиса** + Регистрация как сервис типа `structured-diag` + Использование стандартных тем запросов/ответов + Реализация базового класса FlowProcessor + Регистрация PromptClientSpec для взаимодействия с сервисом запросов + +2. **Управление конфигурацией** + Доступ к конфигурациям схем через сервис конфигурации + Кэширование схем для повышения производительности + Динамическая обработка обновлений конфигурации + +3. **Интеграция с сервисом запросов** + Использование существующей инфраструктуры сервиса запросов + Вызов сервиса запросов с идентификаторами запросов, специфичными для формата: + `diagnose-csv`: Для анализа данных CSV + `diagnose-json`: Для анализа данных JSON + `diagnose-xml`: Для анализа данных XML + Запросы настроены в конфигурации запросов, а не жестко закодированы в сервисе + Передача схем и образцов данных в качестве переменных запроса + Разбор ответов запросов для извлечения дескрипторов + +4. **Обработка ошибок** + Проверка входных образцов данных + Предоставление описательных сообщений об ошибках + Обработка некорректных данных + Обработка сбоев сервиса запросов + +5. **Выборка данных** + Обработка настраиваемых размеров выборки + Правильная обработка неполных записей + Поддержание согласованности выборки + +### Интеграция с API + +Сервис будет интегрирован с существующими API TrustGraph: + +Измененные компоненты: +`tg-load-structured-data` CLI - Переработан для использования нового сервиса для операций диагностики +Flow API - Расширен для поддержки запросов структурированной диагностики + +Новые конечные точки сервиса: +`/api/v1/flow/{flow}/diagnose/structured-data` - WebSocket конечная точка для запросов диагностики +`/api/v1/diagnose/structured-data` - REST конечная точка для синхронной диагностики + +### Поток сообщений + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## Соображения безопасности + +Проверка входных данных для предотвращения атак внедрения +Ограничения на размер образцов данных для предотвращения DoS-атак +Очистка сгенерированных описаний +Контроль доступа через существующую аутентификацию TrustGraph + +## Соображения производительности + +Кэширование определений схемы для уменьшения количества обращений к сервису конфигурации +Ограничение размеров образцов для поддержания отзывчивой производительности +Использование потоковой обработки для больших образцов данных +Реализация механизмов тайм-аута для длительных анализов + +## Стратегия тестирования + +1. **Модульные тесты** + Обнаружение типа для различных форматов данных + Точность генерации описаний + Сценарии обработки ошибок + +2. **Интеграционные тесты** + Поток запросов/ответов сервиса + Получение и кэширование схемы + Интеграция с CLI + +3. **Тесты производительности** + Обработка больших образцов + Обработка одновременных запросов + Использование памяти при высокой нагрузке + +## План миграции + +1. **Этап 1**: Реализация сервиса с основной функциональностью +2. **Этап 2**: Рефакторинг CLI для использования сервиса (с сохранением обратной совместимости) +3. **Этап 3**: Добавление REST API +4. **Этап 4**: Отказ от встроенной логики CLI (с предварительным уведомлением) + +## График + +Неделя 1-2: Реализация основного сервиса и обнаружения типа +Неделя 3-4: Добавление генерации описаний и интеграции +Неделя 5: Тестирование и документация +Неделя 6: Рефакторинг CLI и миграция + +## Открытые вопросы + +Должен ли сервис поддерживать дополнительные форматы данных (например, Parquet, Avro)? +Каков должен быть максимальный размер образца для анализа? +Следует ли кэшировать результаты диагностики для повторяющихся запросов? +Как сервис должен обрабатывать сценарии с несколькими схемами? +Должны ли идентификаторы запросов быть настраиваемыми параметрами для сервиса? + +## Ссылки + +[Спецификация структурированного описания данных](structured-data-descriptor.md) +[Документация по загрузке структурированных данных](structured-data.md) +`tg-load-structured-data` реализация: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.sw.md b/docs/tech-specs/structured-diag-service.sw.md new file mode 100644 index 00000000..ab7e3858 --- /dev/null +++ b/docs/tech-specs/structured-diag-service.sw.md @@ -0,0 +1,281 @@ +--- +layout: default +title: "Vigezo vya Kisaikolojia kwa Huduma ya Utambuzi wa Data Imebuniwa" +parent: "Swahili (Beta)" +--- + +# Vigezo vya Kisaikolojia kwa Huduma ya Utambuzi wa Data Imebuniwa + +> **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 + +Vigezo hivi vinaelezea huduma mpya inayoweza kutumika kwa utambuzi na uchambuzi wa data iliyobuniwa ndani ya TrustGraph. Huduma hii hutoa utendakazi kutoka kwa zana ya `tg-load-structured-data` iliyopo ya mstari wa amri na kuifanya kuwa huduma ya ombi/jibu, na hivyo kuwezesha ufikiaji wa programu kwa uwezo wa utambuzi wa aina ya data na uundaji wa maelezo. + +Huduma hii inasaidia operesheni tatu kuu: + +1. **Utambuzi wa Aina ya Data**: Changanua sampuli ya data ili kubaini muundo wake (CSV, JSON, au XML) +2. **Uundaji wa Maelezo**: Unda maelezo ya TrustGraph ya data iliyobuniwa kwa sampuli fulani ya data na aina +3. **Utambuzi Mchanganyiko**: Fanya utambuzi wa aina na uundaji wa maelezo kwa pamoja + +## Lengo + +**Kugawa Uchunguzi wa Data**: Toa mantiki ya utambuzi wa data kutoka kwa CLI hadi vipengele vya huduma vinavyoweza kutumika tena +**Kuwezesha Ufikiaji wa Programu**: Toa ufikiaji wa API kwa uwezo wa uchambuzi wa data +**Kusaidia Muundo Mbalimbali wa Data**: Shirikisha muundo wa data wa CSV, JSON, na XML kwa uthabiti +**Kuzalisha Maelezo Sahihi**: Toa maelezo ya data iliyobuniwa ambayo yanaelea data ya chanzo kwa schemas za TrustGraph +**Kuhifadhi Utangamano wa Zamani**: Hakikisha utendakazi wa sasa wa CLI unaendelea kufanya kazi +**Kuwezesha Uundaji wa Huduma**: Ruhusu huduma zingine kutumia uwezo wa utambuzi wa data +**Kuboresha Uwezekano wa Kujaribu**: Tenganisha mantiki ya biashara kutoka kwa kiolesura cha CLI kwa ajili ya majaribio bora +**Kusaidia Uchanganuzi wa Msururu**: Wezesha uchanganuzi wa sampuli za data bila kulaini faili nzima + +## Asili + +Kwa sasa, amri ya `tg-load-structured-data` hutoa utendakazi kamili kwa uchambuzi wa data iliyobuniwa na uundaji wa maelezo. Hata hivyo, utendakazi huu umeunganishwa sana na kiolesura cha CLI, na hivyo kupunguza uwezekano wake wa kutumika tena. + +Mapungufu ya sasa ni pamoja na: +Mantiki ya utambuzi wa data iliyo ndani ya nambari ya CLI +Hakuna ufikiaji wa programu kwa utambuzi wa aina na uundaji wa maelezo +Ni vigumu kuunganisha uwezo wa utambuzi katika huduma zingine +Uwezo mdogo wa kuunda mchakato wa uchambuzi wa data + +Vigezo hivi vinashughulikia pengo hizi kwa kuunda huduma maalum ya utambuzi wa data iliyobuniwa. Kwa kuonyesha uwezo huu kama huduma, TrustGraph inaweza: +Kuwezesha huduma zingine kuchambua data kwa programu +Kusaidia mnyororo wa uchakataji wa data unaozidi +Kurahisisha ushirikiano na mifumo ya nje +Kuboresha uendelevu kupitia kutenganisha masuala + +## Muundo wa Kiufundi + +### Usanifu + +Huduma ya utambuzi wa data iliyobuniwa inahitaji vipengele vifuatavyo vya kiufundi: + +1. **Mchakato wa Huduma ya Utambuzi** + Hushughulikia ombi la utambuzi linalokuja + Huendesha utambuzi wa aina na uundaji wa maelezo + Hurudisha majibu yaliyobuniwa na matokeo ya utambuzi + + Moduli: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **Kigunduzi cha Aina ya Data** + Hutumia utambuzi wa algorithm ili kutambua muundo wa data (CSV, JSON, XML) + Inachanganua muundo wa data, vichakavu, na mifumo ya sintaksia + Hurudisha muundo uliogunduliwa na alama za uaminifu + + Moduli: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **Mundua wa Maelezo** + Hutumia huduma ya ombi ili kuzalisha maelezo + Huita ombi maalum ya muundo (diagnose-csv, diagnose-json, diagnose-xml) + Inoelekeza nafasi za data kwa nafasi za schema za TrustGraph kupitia majibu ya ombi + + Moduli: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### Mifano ya Data + +#### StructuredDataDiagnosisRequest + +Ujumbe wa ombi kwa operesheni za utambuzi wa data iliyobuniwa: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### Jibu la Uchambuzi wa Data Iliyopangwa + +Ujumbe wa jibu unaoonyesha matokeo ya uchambuzi: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### Muundo wa Kisajili + +Kisajili kinachozalishwa kinafuata muundo wa sasa wa kisajili cha data iliyopangwa: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### Kiolesho cha Muunganisho + +Huduma itatoa huduma zifuatazo kupitia mfumo wa ombi/jibu: + +1. **Operesheni ya Udagilizaji wa Aina** + Ingizo: Sampuli ya data + Uchakataji: Angalia muundo wa data kwa kutumia ugani wa uchunguzi + Patoto: Aina iliyogunduliwa pamoja na alama ya uaminifu + +2. **Operesheni ya Uundaji wa Kisajili** + Ingizo: Sampuli ya data, aina, jina la mpango (schema) unaolengwa + Uchakataji: + Piga huduma ya ombi kwa kitambulisho cha ombi maalum kwa aina (diagnose-csv, diagnose-json, au diagnose-xml) + Pasa sampuli ya data na mipango inayopatikana kwa ombi + Pokea kisajili kilichoundwa kutoka kwa jibu la ombi + Patoto: Kisajili cha data iliyopangwa + +3. **Operesheni ya Uchambuzi Mchanganyiko** + Ingizo: Sampuli ya data, jina la mpango (schema) la hiari + Uchakataji: + Tumia ugani wa uchunguzi ili kubaini aina kwanza + Chagua ombi maalum kwa aina kulingana na aina iliyogunduliwa + Piga huduma ya ombi ili kuunda kisajili + Patoto: Aina iliyogunduliwa na kisajili + +### Maelezo ya Utendaji + +Huduma itafuata miongozo ya huduma ya TrustGraph: + +1. **Usajili wa Huduma** + Sajili kama aina ya `structured-diag` + Tumia mada za kipekee za ombi/jibu + Lenga darasa la msingi la FlowProcessor + Sajili PromptClientSpec kwa mwingiliano wa huduma ya ombi + +2. **Usimamizi wa Usanidi** + Pata usanidi wa mpango kupitia huduma ya usanidi + Hifadhi mipango kwa utendaji + Shirikisha mabadiliko ya usanidi kwa utaratibu + +3. **Uunganisho wa Ombi** + Tumia miundombinu iliyopo ya huduma ya ombi + Piga huduma ya ombi kwa kitambulisho cha ombi maalum kwa aina: + `diagnose-csv`: Kwa uchambuzi wa data ya CSV + `diagnose-json`: Kwa uchambuzi wa data ya JSON + `diagnose-xml`: Kwa uchambuzi wa data ya XML + Ombi zimepangwa katika usanidi wa ombi, sio zilizopangwa katika huduma + Pasa mipango na sampuli za data kama vigezo vya ombi + Changanua majibu ya ombi ili kuchimbua visajili + +4. **Usimamizi wa Hitilafu** + Thibitisha sampuli za ingizo + Toa ujumbe wa kosa unaoeleweka + Shirikisha data iliyo na kasoro kwa utaratibu + Shirikisha hitilafu za huduma ya ombi + +5. **Uchukuzi wa Sampuli** + Chakata saizi za sampuli zinazoweza kusanidiwa + Shirikisha rekodi zisizo kamili kwa utaratibu + Dumishe utaratibu wa uchukuzi + +### Uunganisho wa API + +Huduma itounganisha na API za TrustGraph zilizopo: + +Vipengele Vilivyobadilishwa: +`tg-load-structured-data` CLI - Imepangwa upya ili kutumia huduma mpya kwa operesheni za uchambuzi +Flow API - Imepanuliwa ili kusaidia ombi za uchambuzi wa data iliyopangwa + +Ncha Mpya za Huduma: +`/api/v1/flow/{flow}/diagnose/structured-data` - Ncha ya WebSocket kwa ombi za uchambuzi +`/api/v1/diagnose/structured-data` - Ncha ya REST kwa uchambuzi wa synchronous + +### Mtiririko wa Ujumbe + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## Masuala ya Usalama + +Uthibitishaji wa pembejeo ili kuzuia mashambulizi ya kuingiza data +Mipaka ya ukubwa ya sampuli za data ili kuzuia mashambulizi ya aina ya "Denial of Service" (DoS) +Usafishaji wa maelezo yaliyoundwa +Udhibiti wa ufikiaji kupitia uthibitishaji wa TrustGraph uliopo + +## Masuala ya Utendaji + +Hifadhi maelezo ya muundo ili kupunguza idadi ya ombi kwa huduma ya usanidi +Punguza ukubwa wa sampuli ili kudumisha utendaji wa haraka +Tumia usindikaji wa mtiririko kwa sampuli kubwa za data +Lenga mitambo ya muda kwa uchambuzi unaochukua muda mrefu + +## Mkakati wa Majaribio + +1. **Majaribio ya Kitengo** + Utambuzi wa aina kwa muundo tofauti wa data + Usahihi wa uundaji wa maelezo + Hali za kushughulikia makosa + +2. **Majaribio ya Uunganisho** + Mtiririko wa ombi/jibu wa huduma + Kupata na kuhifadhi muundo + Uunganisho wa CLI + +3. **Majaribio ya Utendaji** + Usindikaji wa sampuli kubwa + Kushughulikia ombi kwa wakati mmoja + Matumizi ya kumbukumbu chini ya mzigo + +## Mpango wa Uhamisho + +1. **Awamu ya 1**: Tekeleza huduma na utendaji wa msingi +2. **Awamu ya 2**: Badilisha CLI ili itumie huduma (dumishe utangamano wa zamani) +3. **Awamu ya 3**: Ongeza vidokezo vya API ya REST +4. **Awamu ya 4**: Ondoa mantiki iliyojumuishwa ya CLI (na kipindi cha taarifa) + +## Ratiba + +Wiki ya 1-2: Tekeleza huduma ya msingi na utambuzi wa aina +Wiki ya 3-4: Ongeza uundaji wa maelezo na uunganisho +Wiki ya 5: Majaribio na maandishi +Wiki ya 6: Ubadilishaji wa CLI na uhamishaji + +## Maswali ya Wazi + +Je, huduma inapaswa kusaidia muundo wa ziada wa data (e.g., Parquet, Avro)? +Je, ukubwa wa juu wa sampuli kwa uchambuzi unapaswa kuwa gani? +Je, matokeo ya uchunguzi yanapaswa kuhifadhiwa kwa ombi zinazorudia? +Huduma inapaswa kushughulikia hali ya muundo mwingi vipi? +Je, kitambulisho cha ombi (prompt IDs) vinaweza kupangwa kama vigezo vya huduma? + +## Marejeleo + +[Maelezo ya Muundo wa Data](structured-data-descriptor.md) +[Maandishi ya Kupakua Data Imeundwa](structured-data.md) +`tg-load-structured-data` utekelezaji: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.tr.md b/docs/tech-specs/structured-diag-service.tr.md new file mode 100644 index 00000000..306ae75b --- /dev/null +++ b/docs/tech-specs/structured-diag-service.tr.md @@ -0,0 +1,281 @@ +--- +layout: default +title: "Yapılandırılmış Veri Tanı Hizmeti Teknik Özellikleri" +parent: "Turkish (Beta)" +--- + +# Yapılandırılmış Veri Tanı Hizmeti 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çinde yapılandırılmış verileri teşhis etmek ve analiz etmek için yeni bir kullanılabilir hizmeti tanımlar. Bu hizmet, mevcut `tg-load-structured-data` komut satırı aracından işlevleri ayırır ve bunları istek/yanıt hizmeti olarak sunar, böylece veri türü algılama ve tanımlayıcı oluşturma yeteneklerine programlı erişim sağlar. + +Bu hizmet, üç birincil işlemi destekler: + +1. **Veri Türü Algılama**: Bir veri örneğinin biçimini (CSV, JSON veya XML) belirlemek için analiz gerçekleştirin. +2. **Tanımlayıcı Oluşturma**: Verilen bir veri örneği ve tür için bir TrustGraph yapılandırılmış veri tanımlayıcısı oluşturun. +3. **Birleşik Tanı**: Hem tür algılama hem de tanımlayıcı oluşturmayı sırayla gerçekleştirin. + +## Hedefler + +**Veri Analizini Modülerleştirme**: Veri teşhis mantığını CLI'dan yeniden kullanılabilir hizmet bileşenlerine ayırma. +**Programlı Erişimi Sağlama**: Veri analiz yeteneklerine API tabanlı erişim sağlama. +**Çoklu Veri Biçimlerini Destekleme**: CSV, JSON ve XML veri biçimlerini tutarlı bir şekilde işleme. +**Doğru Tanımlayıcılar Oluşturma**: Kaynak verileri TrustGraph şemalarına doğru bir şekilde eşleyen yapılandırılmış veri tanımlayıcıları oluşturma. +**Geriye Dönük Uyumluluğu Koruma**: Mevcut CLI işlevselliğinin çalışmaya devam etmesini sağlama. +**Hizmet Birleştirme İmkanı Sağlama**: Diğer hizmetlerin veri teşhis yeteneklerinden yararlanmasına olanak sağlama. +**Test Edilebilirliği Artırma**: İş mantığını CLI arayüzünden ayırarak daha iyi test imkanı sağlama. +**Akış Analizini Destekleme**: Tüm dosyaları yüklemeden veri örneklerinin analizini yapma imkanı sağlama. + +## Arka Plan + +Şu anda, `tg-load-structured-data` komutu, yapılandırılmış verileri analiz etmek ve tanımlayıcılar oluşturmak için kapsamlı işlevsellik sağlar. Ancak, bu işlevsellik CLI arayüzüne sıkı bir şekilde bağlıdır ve yeniden kullanılabilirliğini sınırlar. + +Mevcut sınırlamalar şunlardır: +Veri teşhis mantığının CLI kodunda yer alması. +Tür algılama ve tanımlayıcı oluşturma için programlı erişimin olmaması. +Teşhis yeteneklerinin diğer hizmetlere entegre edilmesinin zor olması. +Veri analiz iş akışlarının birleştirme yeteneğinin sınırlı olması. + +Bu özellik, yapılandırılmış veri teşhisi için özel bir hizmet oluşturarak bu boşlukları giderir. Bu yetenekleri bir hizmet olarak sunarak, TrustGraph şunları yapabilir: +Diğer hizmetlerin verileri programlı olarak analiz etmesine olanak sağlama. +Daha karmaşık veri işleme süreçlerini destekleme. +Harici sistemlerle entegrasyonu kolaylaştırma. +Endişelerin ayrılması yoluyla bakım kolaylığını artırma. + +## Teknik Tasarım + +### Mimari + +Yapılandırılmış veri teşhis hizmeti, aşağıdaki teknik bileşenleri gerektirir: + +1. **Teşhis Hizmeti İşlemcisi** + Gelen teşhis isteklerini işler. + Tür algılama ve tanımlayıcı oluşturmayı koordine eder. + Teşhis sonuçlarıyla yapılandırılmış yanıtlar döndürür. + + Modül: `trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **Veri Türü Algılayıcı** + Algoritmik algılama kullanarak veri biçimini (CSV, JSON, XML) belirler. + Veri yapısını, ayırıcıları ve sözdizimi kalıplarını analiz eder. + Algılanan biçimi ve güvenilirlik puanlarını döndürür. + + Modül: `trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **Tanımlayıcı Oluşturucu** + Tanımlayıcılar oluşturmak için bir istem hizmetini kullanır. + Biçime özgü istemleri (diagnose-csv, diagnose-json, diagnose-xml) çağırır. + Veri alanlarını, istem yanıtları aracılığıyla TrustGraph şema alanlarına eşler. + + Modül: `trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### Veri Modelleri + +#### StructuredDataDiagnosisRequest + +Yapılandırılmış veri teşhis işlemleri için istek mesajı: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### YapılandırılmışVeriTeşhisYanıtı + +Teşhis sonuçlarını içeren yanıt mesajı: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### Açıklayıcı Yapı + +Oluşturulan açıklayıcı, mevcut yapılandırılmış veri açıklayıcı biçimini izler: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### Hizmet Arayüzü + +Hizmet, istek/yanıt kalıbı aracılığıyla aşağıdaki işlemleri sunacaktır: + +1. **Tip Algılama İşlemi** + Giriş: Veri örneği + İşlem: Algoritmik algılama kullanarak veri yapısını analiz etme + Çıkış: Belirlenen tip ve güvenilirlik skoru + +2. **Açıklayıcı Oluşturma İşlemi** + Giriş: Veri örneği, tip, hedef şema adı + İşlem: + Biçime özgü bir istem kimliği (diagnose-csv, diagnose-json veya diagnose-xml) ile istem hizmetini çağırın. + Veri örneğini ve mevcut şemaları isteme iletin. + İstem yanıtından oluşturulan açıklayıcıyı alın. + Çıkış: Yapılandırılmış veri açıklayıcısı + +3. **Birleşik Tanılama İşlemi** + Giriş: Veri örneği, isteğe bağlı şema adı + İşlem: + Önce algoritmik algılama kullanarak biçimi belirleyin. + Belirlenen tipe göre uygun biçime özgü istemi seçin. + Açıklayıcı oluşturmak için istem hizmetini çağırın. + Çıkış: Hem belirlenen tip hem de açıklayıcı + +### Uygulama Detayları + +Hizmet, TrustGraph hizmeti geleneklerini takip edecektir: + +1. **Hizmet Kaydı** + `structured-diag` hizmet türü olarak kaydedin + Standart istek/yanıt konularını kullanın + FlowProcessor temel sınıfını uygulayın + İstem hizmeti etkileşimi için PromptClientSpec'i kaydedin + +2. **Yapılandırma Yönetimi** + Şema yapılandırmalarına yapılandırma hizmeti aracılığıyla erişin + Performans için şemaları önbelleğe alın + Yapılandırma güncellemelerini dinamik olarak işleyin + +3. **İstem Entegrasyonu** + Mevcut istem hizmeti altyapısını kullanın + Biçime özgü istem kimlikleriyle istem hizmetini çağırın: + `diagnose-csv`: CSV verisi analizi için + `diagnose-json`: JSON verisi analizi için + `diagnose-xml`: XML verisi analizi için + İstemler, hizmette sabit kodlanmış olan istem yapılandırmasında yapılandırılmıştır. + Şemaları ve veri örneklerini istem değişkenleri olarak iletin + Açıklayıcıları çıkarmak için istem yanıtlarını ayrıştırın + +4. **Hata Yönetimi** + Giriş veri örneklerini doğrulayın + Açıklayıcı hata mesajları sağlayın + Hatalı verileri zarif bir şekilde işleyin + İstem hizmeti hatalarını işleyin + +5. **Veri Örneklemesi** + Yapılandırılabilir örnek boyutlarını işleyin + Eksik kayıtları uygun şekilde işleyin + Örnekleme tutarlılığını koruyun + +### API Entegrasyonu + +Hizmet, mevcut TrustGraph API'leriyle entegre olacaktır: + +Değiştirilen Bileşenler: +`tg-load-structured-data` CLI - Tanılama işlemleri için yeni hizmeti kullanmak üzere yeniden düzenlendi +Flow API - Yapılandırılmış veri tanılama isteklerini desteklemek üzere genişletildi + +Yeni Hizmet Uç Noktaları: +`/api/v1/flow/{flow}/diagnose/structured-data` - Tanılama istekleri için WebSocket uç noktası +`/api/v1/diagnose/structured-data` - Senkron tanılama için REST uç noktası + +### Mesaj Akışı + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## Güvenlik Hususları + +Enjeksiyon saldırılarını önlemek için girdi doğrulama +DoS saldırılarını önlemek için veri örnekleri üzerindeki boyut sınırlamaları +Oluşturulan tanımlayıcıların temizlenmesi +Mevcut TrustGraph kimlik doğrulama aracılığıyla erişim kontrolü + +## Performans Hususları + +Yapılandırma hizmeti çağrılarını azaltmak için şema tanımlarını önbelleğe alın +Duyarlı performansı korumak için örnek boyutlarını sınırlayın +Büyük veri örnekleri için akış işleme kullanın +Uzun süren analizler için zaman aşımı mekanizmaları uygulayın + +## Test Stratejisi + +1. **Birim Testleri** + Çeşitli veri formatları için tür tespiti + Tanımlayıcı oluşturma doğruluğu + Hata işleme senaryoları + +2. **Entegrasyon Testleri** + Hizmet istek/yanıt akışı + Şema alma ve önbelleğe alma + CLI entegrasyonu + +3. **Performans Testleri** + Büyük örnek işleme + Eşzamanlı istek işleme + Yük altında bellek kullanımı + +## Geçiş Planı + +1. **1. Aşama**: Temel işlevselliğe sahip hizmeti uygulayın +2. **2. Aşama**: CLI'ı hizmeti kullanacak şekilde yeniden düzenleyin (geriye dönük uyumluluğu koruyun) +3. **3. Aşama**: REST API uç noktaları ekleyin +4. **4. Aşama**: Gömülü CLI mantığını kullanımdan kaldırın (bildirim süresiyle) + +## Zaman Çizelgesi + +1-2. Hafta: Temel hizmeti ve tür tespitini uygulayın +3-4. Hafta: Tanımlayıcı oluşturmayı ve entegrasyonu ekleyin +5. Hafta: Test ve dokümantasyon +6. Hafta: CLI yeniden düzenlemesi ve geçiş + +## Açık Sorular + +Hizmet, ek veri formatlarını (örneğin, Parquet, Avro) desteklemeli mi? +Analiz için maksimum örnek boyutu ne olmalıdır? +Teşhis sonuçları, tekrarlanan istekler için önbelleğe alınmalı mı? +Hizmet, çoklu şema senaryolarını nasıl işlemelidir? +İstek kimlikleri, hizmet için yapılandırılabilir parametreler olmalı mı? + +## Referanslar + +[Yapılandırılmış Veri Tanımlayıcı Özellikleri](structured-data-descriptor.md) +[Yapılandırılmış Veri Yükleme Dokümantasyonu](structured-data.md) +`tg-load-structured-data` uygulaması: `trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/structured-diag-service.zh-cn.md b/docs/tech-specs/structured-diag-service.zh-cn.md new file mode 100644 index 00000000..66a1d6d3 --- /dev/null +++ b/docs/tech-specs/structured-diag-service.zh-cn.md @@ -0,0 +1,281 @@ +--- +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 中的结构化数据。该服务从现有的 `tg-load-structured-data` 命令行工具中提取功能,并将其暴露为请求/响应服务,从而实现对数据类型检测和描述符生成功能的编程访问。 + +该服务支持三种主要操作: + +1. **数据类型检测**: 分析数据样本以确定其格式(CSV、JSON 或 XML) +2. **描述符生成**: 为给定的数据样本和类型生成 TrustGraph 结构化数据描述符 +3. **综合诊断**: 依次执行数据类型检测和描述符生成 + +## 目标 + +**模块化数据分析**: 将数据诊断逻辑从 CLI 提取到可重用的服务组件中 +**启用编程访问**: 提供基于 API 的访问数据分析能力 +**支持多种数据格式**: 始终如一地处理 CSV、JSON 和 XML 数据格式 +**生成准确的描述符**: 生成准确映射源数据到 TrustGraph 模式的结构化数据描述符 +**保持向后兼容性**: 确保现有的 CLI 功能继续正常工作 +**启用服务组合**: 允许其他服务利用数据诊断能力 +**提高可测试性**: 将业务逻辑与 CLI 接口分离,以获得更好的测试效果 +**支持流式分析**: 允许分析数据样本,而无需加载整个文件 + +## 背景 + +目前,`tg-load-structured-data` 命令提供了用于分析结构化数据和生成描述符的全面功能。但是,此功能与 CLI 接口紧密耦合,限制了其可重用性。 + +当前的限制包括: +数据诊断逻辑嵌入在 CLI 代码中 +没有对数据类型检测和描述符生成的编程访问 +难以将诊断能力集成到其他服务中 +难以组合数据分析工作流程 + +本规范通过创建一个专用的结构化数据诊断服务来解决这些差距。通过将这些功能暴露为服务,TrustGraph 可以: +允许其他服务以编程方式分析数据 +支持更复杂的数据处理管道 +促进与外部系统的集成 +通过分离关注点来提高可维护性 + +## 技术设计 + +### 架构 + +结构化数据诊断服务需要以下技术组件: + +1. **诊断服务处理器** + 处理传入的诊断请求 + 协调数据类型检测和描述符生成 + 返回包含诊断结果的结构化响应 + + 模块:`trustgraph-flow/trustgraph/diagnosis/structured_data/service.py` + +2. **数据类型检测器** + 使用算法检测来识别数据格式(CSV、JSON、XML) + 分析数据结构、分隔符和语法模式 + 返回检测到的格式和置信度分数 + + 模块:`trustgraph-flow/trustgraph/diagnosis/structured_data/type_detector.py` + +3. **描述符生成器** + 使用提示服务生成描述符 + 调用特定于格式的提示(diagnose-csv、diagnose-json、diagnose-xml) + 通过提示响应将数据字段映射到 TrustGraph 模式字段 + + 模块:`trustgraph-flow/trustgraph/diagnosis/structured_data/descriptor_generator.py` + +### 数据模型 + +#### StructuredDataDiagnosisRequest + +结构化数据诊断操作的请求消息: + +```python +class StructuredDataDiagnosisRequest: + operation: str # "detect-type", "generate-descriptor", or "diagnose" + sample: str # Data sample to analyze (text content) + type: Optional[str] # Data type (csv, json, xml) - required for generate-descriptor + schema_name: Optional[str] # Target schema name for descriptor generation + options: Dict[str, Any] # Additional options (e.g., delimiter for CSV) +``` + +#### 结构化数据诊断响应 + +包含诊断结果的响应消息: + +```python +class StructuredDataDiagnosisResponse: + operation: str # The operation that was performed + detected_type: Optional[str] # Detected data type (for detect-type/diagnose) + confidence: Optional[float] # Confidence score for type detection + descriptor: Optional[Dict] # Generated descriptor (for generate-descriptor/diagnose) + error: Optional[str] # Error message if operation failed + metadata: Dict[str, Any] # Additional metadata (e.g., field count, sample records) +``` + +#### 描述符结构 + +生成的描述符遵循现有的结构化数据描述符格式: + +```json +{ + "format": { + "type": "csv", + "encoding": "utf-8", + "options": { + "delimiter": ",", + "has_header": true + } + }, + "mappings": [ + { + "source_field": "customer_id", + "target_field": "id", + "transforms": [ + {"type": "trim"} + ] + } + ], + "output": { + "schema_name": "customer", + "options": { + "batch_size": 1000, + "confidence": 0.9 + } + } +} +``` + +### 服务接口 + +该服务将通过请求/响应模式提供以下操作: + +1. **类型检测操作** + 输入:数据样本 + 处理:使用算法检测分析数据结构 + 输出:检测到的类型及其置信度分数 + +2. **描述符生成操作** + 输入:数据样本、类型、目标模式名称 + 处理: + 使用特定格式的提示 ID(diagnose-csv、diagnose-json 或 diagnose-xml)调用提示服务 + 将数据样本和可用模式传递给提示 + 从提示响应接收生成的描述符 + 输出:结构化数据描述符 + +3. **综合诊断操作** + 输入:数据样本、可选模式名称 + 处理: + 首先使用算法检测识别格式 + 根据检测到的类型选择适当的特定格式的提示 + 调用提示服务以生成描述符 + 输出:检测到的类型和描述符 + +### 实现细节 + +该服务将遵循 TrustGraph 服务约定: + +1. **服务注册** + 注册为 `structured-diag` 服务类型 + 使用标准的请求/响应主题 + 实现 FlowProcessor 基础类 + 注册 PromptClientSpec 以进行提示服务交互 + +2. **配置管理** + 通过配置服务访问模式配置 + 缓存模式以提高性能 + 动态处理配置更新 + +3. **提示集成** + 使用现有的提示服务基础设施 + 使用特定格式的提示 ID调用提示服务: + `diagnose-csv`:用于 CSV 数据分析 + `diagnose-json`:用于 JSON 数据分析 + `diagnose-xml`:用于 XML 数据分析 + 提示配置在提示配置中,而不是硬编码在服务中 + 将模式和数据样本作为提示变量传递 + 解析提示响应以提取描述符 + +4. **错误处理** + 验证输入数据样本 + 提供描述性的错误消息 + 优雅地处理格式错误的数据 + 处理提示服务故障 + +5. **数据采样** + 处理可配置的样本大小 + 适当处理不完整的记录 + 保持采样的一致性 + +### API 集成 + +该服务将与现有的 TrustGraph API 集成: + +修改的组件: +`tg-load-structured-data` CLI - 重新设计为使用新的服务进行诊断操作 +Flow API - 扩展以支持结构化数据诊断请求 + +新的服务端点: +`/api/v1/flow/{flow}/diagnose/structured-data` - 用于诊断请求的 WebSocket 端点 +`/api/v1/diagnose/structured-data` - 用于同步诊断的 REST 端点 + +### 消息流 + +``` +Client → Gateway → Structured Diag Service → Config Service (for schemas) + ↓ + Type Detector (algorithmic) + ↓ + Prompt Service (diagnose-csv/json/xml) + ↓ + Descriptor Generator (parses prompt response) + ↓ +Client ← Gateway ← Structured Diag Service (response) +``` + +## 安全注意事项 + +输入验证,以防止注入攻击 +对数据样本的大小设置限制,以防止拒绝服务 (DoS) 攻击 +清理生成的描述符 +通过现有的 TrustGraph 身份验证进行访问控制 + +## 性能注意事项 + +缓存模式定义,以减少对配置服务的调用 +限制样本大小,以保持响应性能 +对大型数据样本使用流式处理 +实施超时机制,用于长时间运行的分析 + +## 测试策略 + +1. **单元测试** + 对各种数据格式进行类型检测 + 描述符生成准确性 + 错误处理场景 + +2. **集成测试** + 服务请求/响应流程 + 模式检索和缓存 + CLI 集成 + +3. **性能测试** + 处理大型样本 + 并发请求处理 + 在负载下的内存使用情况 + +## 迁移计划 + +1. **第一阶段**: 实施具有核心功能的服务 +2. **第二阶段**: 重构 CLI 以使用服务(保持向后兼容性) +3. **第三阶段**: 添加 REST API 端点 +4. **第四阶段**: 弃用嵌入式 CLI 逻辑(提前通知) + +## 时间表 + +第 1-2 周:实施核心服务和类型检测 +第 3-4 周:添加描述符生成和集成 +第 5 周:测试和文档 +第 6 周:CLI 重构和迁移 + +## 开放问题 + +该服务是否应支持其他数据格式(例如,Parquet、Avro)? +分析的最大样本大小应为多少? +诊断结果是否应针对重复请求进行缓存? +该服务应如何处理多模式场景? +提示 ID 是否应为服务的可配置参数? + +## 参考文献 + +[结构化数据描述符规范](structured-data-descriptor.md) +[结构化数据加载文档](structured-data.md) +`tg-load-structured-data` 实现:`trustgraph-cli/trustgraph/cli/load_structured_data.py` diff --git a/docs/tech-specs/tool-group.ar.md b/docs/tech-specs/tool-group.ar.md new file mode 100644 index 00000000..b07a928a --- /dev/null +++ b/docs/tech-specs/tool-group.ar.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "مجموعة أدوات TrustGraph" +parent: "Arabic (Beta)" +--- + +# مجموعة أدوات TrustGraph + +> **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. +## المواصفات الفنية v1.0 + +### ملخص تنفيذي + +تحدد هذه المواصفات نظام تجميع الأدوات لوكلاء TrustGraph، مما يسمح بالتحكم الدقيق في الأدوات المتاحة لطلبات معينة. يقدم النظام تصفية الأدوات المستندة إلى المجموعات من خلال التكوين وتحديد مستوى الطلب، مما يتيح حدودًا أمنية أفضل وإدارة الموارد وتقسيمًا وظيفيًا لقدرات الوكيل. + +### 1. نظرة عامة + +#### 1.1 بيان المشكلة + +حاليًا، يتمتع وكلاء TrustGraph بإمكانية الوصول إلى جميع الأدوات المكونة بغض النظر عن سياق الطلب أو متطلبات الأمان. وهذا يخلق عدة تحديات: + +**مخاطر أمنية**: الأدوات الحساسة (مثل تعديل البيانات) متاحة حتى للاستعلامات للقراءة فقط. +**إهدار الموارد**: يتم تحميل الأدوات المعقدة حتى عندما لا تتطلب الاستعلامات البسيطة ذلك. +**ارتباك وظيفي**: قد تختار الوكلاء أدوات غير مناسبة عندما تكون هناك بدائل أبسط. +**العزل متعدد المستأجرين**: تحتاج مجموعات المستخدمين المختلفة إلى الوصول إلى مجموعات أدوات مختلفة. + +#### 1.2 نظرة عامة على الحل + +يقدم نظام تجميع الأدوات ما يلي: + +1. **تصنيف المجموعات**: يتم وضع علامة على الأدوات باستخدام عضوية المجموعة أثناء التكوين. +2. **التصفية على مستوى الطلب**: يحدد AgentRequest مجموعات الأدوات المسموح بها. +3. **التنفيذ في وقت التشغيل**: لا تملك الوكلاء سوى الأدوات التي تتطابق مع المجموعات المطلوبة. +4. **تجميع مرن**: يمكن أن تنتمي الأدوات إلى مجموعات متعددة للسيناريوهات المعقدة. + +### 2. تغييرات المخطط + +#### 2.1 تحسين مخطط تكوين الأداة + +يتم تحسين تكوين الأداة الحالي بإضافة حقل `group`: + +**قبل:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**بعد:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**تحديد حقل المجموعة:** +`group`: Array(String) - قائمة المجموعات التي تنتمي إليها هذه الأداة. +**اختياري**: الأدوات التي لا تحتوي على حقل المجموعة تنتمي إلى المجموعة الافتراضية. +**العضوية المتعددة**: يمكن للأدوات أن تنتمي إلى مجموعات متعددة. +**حساسية حالة الأحرف**: أسماء المجموعات هي مطابقات دقيقة للسلاسل النصية. + +#### 2.1.2 تحسين انتقال حالة الأداة + +يمكن للأدوات تحديد انتقالات الحالة وحالة التوفر بناءً على الحالة بشكل اختياري: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**تحديد حقل الحالة:** +`state`: String - **اختياري** - الحالة التي يتم الانتقال إليها بعد تنفيذ الأداة بنجاح +`available_in_states`: Array(String) - **اختياري** - الحالات التي تتوفر فيها هذه الأداة +**السلوك الافتراضي**: الأدوات التي لا تحتوي على `available_in_states` متاحة في جميع الحالات +**انتقال الحالة**: يحدث فقط بعد تنفيذ الأداة بنجاح + +#### 2.2 تحسين مخطط AgentRequest + +مخطط `AgentRequest` في `trustgraph-base/trustgraph/schema/services/agent.py` تم تحسينه: + +**AgentRequest الحالي:** +`question`: String - استعلام المستخدم +`plan`: String - خطة التنفيذ (يمكن إزالتها) +`state`: String - حالة الوكيل +`history`: Array(AgentStep) - سجل التنفيذ + +**AgentRequest المحسن:** +`question`: String - استعلام المستخدم +`state`: String - حالة تنفيذ الوكيل (تستخدم الآن بنشاط لتصفية الأدوات) +`history`: Array(AgentStep) - سجل التنفيذ +`group`: Array(String) - **جديد** - مجموعات الأدوات المسموح بها لهذا الطلب + +**تغييرات المخطط:** +**تمت إزالة**: حقل `plan` لم يعد مطلوبًا ويمكن إزالته (كان مخصصًا في الأصل لتحديد الأدوات) +**تمت إضافة**: حقل `group` لتحديد مجموعة الأدوات +**تم التحسين**: يتحكم حقل `state` الآن في توفر الأدوات أثناء التنفيذ + +**سلوكيات الحقول:** + +**حقل المجموعة:** +**اختياري**: إذا لم يتم تحديده، فسيتم تعيينه افتراضيًا إلى ["default"] +**التقاطع**: تتوفر فقط الأدوات التي تتطابق مع مجموعة واحدة على الأقل من المجموعات المحددة +**مصفوفة فارغة**: لا تتوفر أي أدوات (يمكن للوكيل استخدام الاستدلال الداخلي فقط) +**رمز بدل (Wildcard)**: تمنح المجموعة الخاصة "*" إمكانية الوصول إلى جميع الأدوات + +**حقل الحالة:** +**اختياري**: إذا لم يتم تحديده، فسيتم تعيينه افتراضيًا إلى "undefined" +**التصفية بناءً على الحالة**: الأدوات المتاحة فقط في الحالة الحالية هي المؤهلة +**الحالة الافتراضية**: تسمح حالة "undefined" بجميع الأدوات (مع مراعاة تصفية المجموعة) +**انتقالات الحالة**: يمكن للأدوات تغيير الحالة بعد التنفيذ الناجح + +### 3. أمثلة على المجموعات المخصصة + +يمكن للمؤسسات تحديد مجموعات خاصة بالمجال: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. تفاصيل التنفيذ + +#### 4.1 تحميل الأدوات وتصفيتها + +**مرحلة التهيئة:** +1. يتم تحميل جميع الأدوات من ملف التهيئة مع تحديد مجموعاتها. +2. يتم تعيين الأدوات التي لا تحتوي على مجموعات محددة إلى المجموعة "الافتراضية". +3. يتم التحقق من عضوية المجموعة وتخزينها في سجل الأدوات. + +**مرحلة معالجة الطلبات:** +1. يصل طلب الوكيل (AgentRequest) مع تحديد المجموعة الاختياري. +2. يقوم الوكيل بتصفية الأدوات المتاحة بناءً على تقاطع المجموعات. +3. يتم تمرير الأدوات المتطابقة فقط إلى سياق تنفيذ الوكيل. +4. يعمل الوكيل مع مجموعة الأدوات المفلترة طوال دورة حياة الطلب. + +#### 4.2 منطق تصفية الأدوات + +**التصفية المجمعة للمجموعة والحالة:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**منطق الانتقال بين الحالات:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 نقاط تكامل الوكيل + +**الوكيل ReAct:** +يتم تصفية الأدوات في agent_manager.py أثناء إنشاء سجل الأدوات. +يتم تصفية قائمة الأدوات المتاحة بناءً على المجموعة والحالة قبل إنشاء الخطة. +تحديثات انتقالات الحالة تحدّث حقل AgentRequest.state بعد تنفيذ الأداة بنجاح. +تستخدم التكرار التالي الحالة المحدثة لتصفية الأدوات. + +**الوكيل القائم على الثقة:** +يتم تصفية الأدوات في planner.py أثناء إنشاء الخطة. +التحقق من صحة ExecutionStep يضمن استخدام الأدوات المؤهلة فقط بناءً على المجموعة والحالة. +وحدة التحكم في التدفق تفرض توفر الأدوات في وقت التشغيل. +تتم إدارة انتقالات الحالة بواسطة وحدة التحكم في التدفق بين الخطوات. + +### 5. أمثلة التكوين + +#### 5.1 تكوين الأداة مع المجموعات والحالات + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 أمثلة للطلبات مع سير العمل الخاص بالحالة. + +**طلب البحث الأولي:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*الأدوات المتاحة: knowledge-query، text-completion* +*بعد استخدام knowledge-query: الحالة → "analysis"* + +**مرحلة التحليل:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*الأدوات المتاحة: تحليل معقد، تحديث الرسم البياني، إعادة تعيين سير العمل* +*بعد التحليل المعقد: الحالة → "النتائج"* + +**مرحلة النتائج:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*الأدوات المتاحة: reset-workflow فقط* +*بعد reset-workflow: الحالة → "غير محددة"* + +**مثال سير العمل - التدفق الكامل:** +1. **البداية (غير محددة):** استخدم knowledge-query للانتقال إلى الحالة "تحليل". +2. **حالة التحليل:** استخدم complex-analysis للانتقال إلى الحالة "النتائج". +3. **حالة النتائج:** استخدم reset-workflow للعودة إلى الحالة "غير محددة". +4. **العودة إلى البداية:** تتوفر جميع الأدوات الأولية مرة أخرى. + +### 6. اعتبارات الأمان + +#### 6.1 تكامل التحكم في الوصول + +**التصفية على مستوى البوابة:** +يمكن للبوابة فرض قيود على المجموعات بناءً على أذونات المستخدم. +منع رفع الامتيازات من خلال التلاعب بالطلبات. +يتضمن سجل التدقيق المجموعات المطلوبة والمجموعات الممنوحة. + +**مثال لمنطق البوابة:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 التدقيق والمراقبة + +**مسار تدقيق مُحسّن:** +تسجيل مجموعات الأدوات المطلوبة والحالة الأولية لكل طلب. +تتبع عمليات انتقال الحالة واستخدام الأدوات حسب عضوية المجموعة. +مراقبة محاولات الوصول غير المصرح بها إلى المجموعة والانتقالات غير الصالحة للحالة. +إرسال تنبيهات عند وجود أنماط استخدام غير عادية للمجموعة أو سير عمل حالة مشبوه. + +### 7. استراتيجية الترحيل + +#### 7.1 التوافق مع الإصدارات السابقة + +**المرحلة الأولى: تغييرات إضافية** +إضافة حقل `group` اختياري إلى تكوينات الأدوات. +إضافة حقل `group` اختياري إلى مخطط AgentRequest. +السلوك الافتراضي: تنتمي جميع الأدوات الحالية إلى المجموعة "الافتراضية". +تستخدم الطلبات الحالية التي لا تحتوي على حقل المجموعة المجموعة "الافتراضية". + +**الحفاظ على السلوك الحالي:** +تستمر الأدوات التي لا تحتوي على تكوين مجموعة في العمل (المجموعة الافتراضية). +الأدوات التي لا تحتوي على تكوين حالة متاحة في جميع الحالات. +يمكن للطلبات التي لا تحدد المجموعة الوصول إلى جميع الأدوات (المجموعة الافتراضية). +تستخدم الطلبات التي لا تحدد الحالة حالة "غير محددة" (جميع الأدوات متاحة). +لا توجد تغييرات تؤثر على عمليات النشر الحالية. + +### 8. المراقبة وقابلية الملاحظة + +#### 8.1 مقاييس جديدة + +**استخدام مجموعة الأدوات:** +`agent_tool_group_requests_total` - عد الطلبات حسب المجموعة. +`agent_tool_group_availability` - مقياس للأدوات المتاحة لكل مجموعة. +`agent_filtered_tools_count` - رسم بياني لعدد الأدوات بعد تصفية المجموعة والحالة. + +**مقاييس سير عمل الحالة:** +`agent_state_transitions_total` - عد عمليات انتقال الحالة لكل أداة. +`agent_workflow_duration_seconds` - رسم بياني للوقت المستغرق في كل حالة. +`agent_state_availability` - مقياس للأدوات المتاحة لكل حالة. + +**مقاييس الأمان:** +`agent_group_access_denied_total` - عد الوصول غير المصرح به إلى المجموعة. +`agent_invalid_state_transition_total` - عد عمليات انتقال الحالة غير الصالحة. +`agent_privilege_escalation_attempts_total` - عد الطلبات المشبوهة. + +#### 8.2 تحسينات التسجيل + +**تسجيل الطلبات:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. استراتيجية الاختبار + +#### 9.1 اختبارات الوحدة + +**منطق تصفية الأدوات:** +حسابات تقاطع مجموعات الاختبار. +منطق التصفية المستند إلى الحالة. +التحقق من التعيين الافتراضي للمجموعة والحالة. +اختبار سلوك المجموعة باستخدام أحرف البدل. +التحقق من معالجة المجموعات الفارغة. +اختبار سيناريوهات التصفية المجمعة للمجموعة والحالة. + +**التحقق من التكوين:** +اختبار تحميل الأدوات مع تكوينات مختلفة للمجموعة والحالة. +التحقق من صحة المخطط للمواصفات غير الصالحة للمجموعة والحالة. +اختبار التوافق مع الإصدارات السابقة مع التكوينات الحالية. +التحقق من تعريفات دورات الانتقال بين الحالات. + +#### 9.2 اختبارات التكامل + +**سلوك الوكيل:** +التحقق من أن الوكلاء يرون فقط الأدوات التي تم تصفيتها حسب المجموعة والحالة. +اختبار تنفيذ الطلبات مع مجموعات مختلفة. +اختبار الانتقالات بين الحالات أثناء تنفيذ الوكيل. +التحقق من معالجة الأخطاء عندما لا تتوفر أي أدوات. +اختبار تقدم سير العمل عبر حالات متعددة. + +**اختبار الأمان:** +اختبار منع تصعيد الامتيازات. +التحقق من دقة سجل التدقيق. +اختبار تكامل البوابة مع أذونات المستخدم. + +#### 9.3 سيناريوهات شاملة + +**الاستخدام متعدد المستأجر مع سير عمل الحالة:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**تطور حالة سير العمل:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. الاعتبارات المتعلقة بالأداء + +#### 10.1 تأثير تحميل الأدوات + +**تحميل التكوين:** +يتم تحميل بيانات التعريف الخاصة بالمجموعة والحالة مرة واحدة عند بدء التشغيل. +الحد الأدنى من الحمل على الذاكرة لكل أداة (حقول إضافية). +لا يوجد تأثير على وقت تهيئة الأداة. + +**معالجة الطلبات:** +يتم تطبيق تصفية المجموعة + الحالة المجمعة مرة واحدة لكل طلب. +تعقيد O(n) حيث n = عدد الأدوات المكونة. +تضيف عمليات انتقال الحالة حملًا ضئيلًا (تعيين سلسلة). +تأثير ضئيل لعدد الأدوات النموذجي (< 100). + +#### 10.2 استراتيجيات التحسين + +**مجموعات الأدوات المحسوبة مسبقًا:** +تخزين مجموعات الأدوات حسب مجموعة + مجموعة حالة. +تجنب التصفية المتكررة لأنماط المجموعة / الحالة الشائعة. +مقايضة بين الذاكرة والحساب للتوليفات المستخدمة بشكل متكرر. + +**التحميل الكسول:** +قم بتحميل تطبيقات الأدوات فقط عند الحاجة. +تقليل وقت بدء التشغيل لنشر الأدوات العديدة. +تسجيل الأدوات الديناميكي بناءً على متطلبات المجموعة. + +### 11. التحسينات المستقبلية + +#### 11.1 التعيين الديناميكي للمجموعة + +**التجميع الواعي بالسياق:** +تعيين الأدوات إلى المجموعات بناءً على سياق الطلب. +توفر المجموعة بناءً على الوقت (ساعات العمل فقط). +قيود المجموعة بناءً على الحمل (الأدوات باهظة الثمن أثناء الاستخدام المنخفض). + +#### 11.2 التسلسلات الهرمية للمجموعات + +**هيكل المجموعة المتداخل:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 توصيات بالأدوات + +**اقتراحات قائمة على المجموعات:** +اقتراح مجموعات الأدوات المثلى لأنواع الطلبات. +التعلم من أنماط الاستخدام لتحسين التوصيات. +توفير مجموعات احتياطية عندما تكون الأدوات المفضلة غير متاحة. + +### 12. أسئلة مفتوحة + +1. **التحقق من صحة المجموعة**: هل يجب أن تتسبب أسماء المجموعات غير الصالحة في الطلبات في حدوث أخطاء فادحة أم تحذيرات؟ + +2. **اكتشاف المجموعة**: هل يجب أن يوفر النظام واجهة برمجة تطبيقات (API) لسرد المجموعات المتاحة وأدواتها؟ + +3. **المجموعات الديناميكية**: هل يجب أن تكون المجموعات قابلة للتكوين في وقت التشغيل أم فقط عند بدء التشغيل؟ + +4. **وراثة المجموعة**: هل يجب أن ترث الأدوات مجموعات من فئاتها الأصلية أو تطبيقاتها؟ + +5. **مراقبة الأداء**: ما هي المقاييس الإضافية المطلوبة لتتبع استخدام الأدوات القائمة على المجموعات بشكل فعال؟ + +### 13. الخلاصة + +يوفر نظام مجموعات الأدوات ما يلي: + +**الأمان**: تحكم دقيق في الوصول إلى قدرات الوكيل. +**الأداء**: تقليل الحمل الزائد لاختيار الأدوات وتحميلها. +**المرونة**: تصنيف متعدد الأبعاد للأدوات. +**التوافق**: تكامل سلس مع بنيات الوكيل الحالية. + +يمكّن هذا النظام عمليات نشر TrustGraph من إدارة الوصول إلى الأدوات بشكل أفضل، وتحسين الحدود الأمنية، وتحسين استخدام الموارد مع الحفاظ على التوافق الكامل مع التكوينات والطلبات الحالية. diff --git a/docs/tech-specs/tool-group.es.md b/docs/tech-specs/tool-group.es.md new file mode 100644 index 00000000..6d18b2cc --- /dev/null +++ b/docs/tech-specs/tool-group.es.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "Grupo de Herramientas TrustGraph" +parent: "Spanish (Beta)" +--- + +# Grupo de Herramientas TrustGraph + +> **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. +## Especificación Técnica v1.0 + +### Resumen Ejecutivo + +Esta especificación define un sistema de agrupación de herramientas para agentes de TrustGraph que permite un control preciso sobre qué herramientas están disponibles para solicitudes específicas. El sistema introduce un filtrado de herramientas basado en grupos a través de la configuración y la especificación a nivel de solicitud, lo que permite mejores límites de seguridad, gestión de recursos y partición funcional de las capacidades de los agentes. + +### 1. Descripción General + +#### 1.1 Declaración del Problema + +Actualmente, los agentes de TrustGraph tienen acceso a todas las herramientas configuradas, independientemente del contexto de la solicitud o los requisitos de seguridad. Esto crea varios desafíos: + +**Riesgo de Seguridad**: Herramientas sensibles (por ejemplo, modificación de datos) están disponibles incluso para consultas de solo lectura. +**Desperdicio de Recursos**: Se cargan herramientas complejas incluso cuando las consultas simples no las requieren. +**Confusión Funcional**: Los agentes pueden seleccionar herramientas inapropiadas cuando existen alternativas más simples. +**Aislamiento Multi-inquilino**: Diferentes grupos de usuarios necesitan acceso a diferentes conjuntos de herramientas. + +#### 1.2 Descripción General de la Solución + +El sistema de agrupación de herramientas introduce: + +1. **Clasificación por Grupos**: Las herramientas se etiquetan con membresías de grupos durante la configuración. +2. **Filtrado a Nivel de Solicitud**: AgentRequest especifica qué grupos de herramientas están permitidos. +3. **Aplicación en Tiempo de Ejecución**: Los agentes solo tienen acceso a las herramientas que coinciden con los grupos solicitados. +4. **Agrupación Flexible**: Las herramientas pueden pertenecer a múltiples grupos para escenarios complejos. + +### 2. Cambios en el Esquema + +#### 2.1 Mejora del Esquema de Configuración de Herramientas + +La configuración de herramientas existente se mejora con un campo `group`: + +**Antes:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**Después:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**Especificación del campo de grupo:** +`group`: Array(String) - Lista de grupos a los que pertenece esta herramienta. +**Opcional**: Las herramientas sin campo de grupo pertenecen al grupo "predeterminado". +**Múltiple pertenencia**: Las herramientas pueden pertenecer a múltiples grupos. +**Sensible a mayúsculas y minúsculas**: Los nombres de los grupos deben coincidir exactamente con la cadena. + +#### 2.1.2 Mejora de la transición de estado de la herramienta + +Las herramientas pueden especificar opcionalmente transiciones de estado y disponibilidad basada en el estado: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**Especificación del campo de estado:** +`state`: String - **Opcional** - Estado al que se debe pasar después de la ejecución exitosa de la herramienta. +`available_in_states`: Array(String) - **Opcional** - Estados en los que esta herramienta está disponible. +**Comportamiento predeterminado**: Las herramientas sin `available_in_states` están disponibles en todos los estados. +**Transición de estado**: Solo ocurre después de la ejecución exitosa de la herramienta. + +#### 2.2 Mejora del esquema AgentRequest + +El esquema `AgentRequest` en `trustgraph-base/trustgraph/schema/services/agent.py` se ha mejorado: + +**AgentRequest actual:** +`question`: String - Consulta del usuario. +`plan`: String - Plan de ejecución (se puede eliminar). +`state`: String - Estado del agente. +`history`: Array(AgentStep) - Historial de ejecución. + +**AgentRequest mejorado:** +`question`: String - Consulta del usuario. +`state`: String - Estado de ejecución del agente (ahora se utiliza activamente para el filtrado de herramientas). +`history`: Array(AgentStep) - Historial de ejecución. +`group`: Array(String) - **NUEVO** - Grupos de herramientas permitidos para esta solicitud. + +**Cambios en el esquema:** +**Eliminado**: El campo `plan` ya no es necesario y se puede eliminar (originalmente estaba destinado a la especificación de herramientas). +**Añadido**: El campo `group` para la especificación de grupos de herramientas. +**Mejorado**: El campo `state` ahora controla la disponibilidad de herramientas durante la ejecución. + +**Comportamientos de los campos:** + +**Grupo de campos:** +**Opcional**: Si no se especifica, el valor predeterminado es ["default"]. +**Intersección**: Solo las herramientas que coinciden con al menos un grupo especificado están disponibles. +**Arreglo vacío**: No hay herramientas disponibles (el agente solo puede usar el razonamiento interno). +**Comodín**: El grupo especial "*" otorga acceso a todas las herramientas. + +**Campo de estado:** +**Opcional**: Si no se especifica, el valor predeterminado es "undefined". +**Filtrado basado en el estado**: Solo las herramientas disponibles en el estado actual son elegibles. +**Estado predeterminado**: El estado "undefined" permite todas las herramientas (sujeto al filtrado de grupos). +**Transiciones de estado**: Las herramientas pueden cambiar de estado después de una ejecución exitosa. + +### 3. Ejemplos de grupos personalizados + +Las organizaciones pueden definir grupos específicos del dominio: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. Detalles de implementación + +#### 4.1 Carga y filtrado de herramientas + +**Fase de configuración:** +1. Todas las herramientas se cargan desde la configuración con sus asignaciones de grupo. +2. Las herramientas sin grupos explícitos se asignan al grupo "predeterminado". +3. La pertenencia al grupo se valida y se almacena en el registro de herramientas. + +**Fase de procesamiento de solicitudes:** +1. La solicitud del agente llega con una especificación de grupo opcional. +2. El agente filtra las herramientas disponibles según la intersección de grupos. +3. Solo las herramientas que coinciden se pasan al contexto de ejecución del agente. +4. El agente opera con el conjunto de herramientas filtrado durante todo el ciclo de vida de la solicitud. + +#### 4.2 Lógica de filtrado de herramientas + +**Filtrado combinado de grupos y estado:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**Lógica de transición de estado:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 Puntos de Integración del Agente + +**Agente ReAct:** +El filtrado de herramientas se produce en agent_manager.py durante la creación del registro de herramientas. +La lista de herramientas disponibles se filtra tanto por grupo como por estado antes de la generación del plan. +Las transiciones de estado actualizan el campo AgentRequest.state después de la ejecución exitosa de la herramienta. +La siguiente iteración utiliza el estado actualizado para el filtrado de herramientas. + +**Agente Basado en la Confianza:** +El filtrado de herramientas se produce en planner.py durante la generación del plan. +La validación de ExecutionStep asegura que solo se utilicen las herramientas elegibles por grupo y estado. +El controlador de flujo hace cumplir la disponibilidad de las herramientas en tiempo de ejecución. +Las transiciones de estado son gestionadas por el Controlador de Flujo entre los pasos. + +### 5. Ejemplos de Configuración + +#### 5.1 Configuración de Herramientas con Grupos y Estados + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 Ejemplos de solicitudes con flujos de trabajo de estado + +**Solicitud de investigación inicial:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*Herramientas disponibles: knowledge-query, text-completion* +*Después de knowledge-query: estado → "análisis"* + +**Fase de análisis:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*Herramientas disponibles: análisis complejo, actualización de gráficos, restablecimiento del flujo de trabajo* +*Después del análisis complejo: estado → "resultados"* + +**Fase de resultados:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*Herramientas disponibles: reset-workflow solamente* +*Después de reset-workflow: estado → "indefinido"* + +**Ejemplo de flujo de trabajo: flujo completo:** +1. **Inicio (indefinido):** Use knowledge-query → transiciones a "análisis" +2. **Estado de análisis:** Use complex-analysis → transiciones a "resultados" +3. **Estado de resultados:** Use reset-workflow → transiciones de vuelta a "indefinido" +4. **De vuelta al inicio:** Todas las herramientas iniciales están disponibles nuevamente + +### 6. Consideraciones de seguridad + +#### 6.1 Integración de control de acceso + +**Filtrado a nivel de puerta de enlace:** +La puerta de enlace puede hacer cumplir las restricciones de grupo basadas en los permisos del usuario +Prevenir la elevación de privilegios a través de la manipulación de solicitudes +El registro de auditoría incluye los grupos de herramientas solicitados y concedidos + +**Ejemplo de lógica de la puerta de enlace:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 Auditoría y Monitoreo + +**Registro de Auditoría Mejorado:** +Registrar los grupos de herramientas solicitados y el estado inicial por solicitud. +Registrar las transiciones de estado y el uso de herramientas por pertenencia a un grupo. +Monitorear los intentos de acceso no autorizados a grupos y las transiciones de estado inválidas. +Generar alertas sobre patrones de uso de grupos inusuales o flujos de trabajo de estado sospechosos. + +### 7. Estrategia de Migración + +#### 7.1 Compatibilidad con Versiones Anteriores + +**Fase 1: Cambios Aditivos** +Agregar un campo opcional `group` a las configuraciones de las herramientas. +Agregar un campo opcional `group` al esquema de AgentRequest. +Comportamiento predeterminado: Todas las herramientas existentes pertenecen al grupo "predeterminado". +Las solicitudes existentes sin el campo de grupo utilizan el grupo "predeterminado". + +**Comportamiento Existente Preservado:** +Las herramientas sin configuración de grupo siguen funcionando (grupo predeterminado). +Las herramientas sin configuración de estado están disponibles en todos los estados. +Las solicitudes sin especificación de grupo acceden a todas las herramientas (grupo predeterminado). +Las solicitudes sin especificación de estado utilizan el estado "indefinido" (todas las herramientas disponibles). +No hay cambios que rompan la compatibilidad con las implementaciones existentes. + +### 8. Monitoreo y Observabilidad + +#### 8.1 Nuevas Métricas + +**Uso de Grupos de Herramientas:** +`agent_tool_group_requests_total` - Contador de solicitudes por grupo. +`agent_tool_group_availability` - Indicador de herramientas disponibles por grupo. +`agent_filtered_tools_count` - Histograma del número de herramientas después del filtrado por grupo + estado. + +**Métricas de Flujo de Trabajo de Estado:** +`agent_state_transitions_total` - Contador de transiciones de estado por herramienta. +`agent_workflow_duration_seconds` - Histograma del tiempo empleado en cada estado. +`agent_state_availability` - Indicador de herramientas disponibles por estado. + +**Métricas de Seguridad:** +`agent_group_access_denied_total` - Contador de accesos no autorizados a grupos. +`agent_invalid_state_transition_total` - Contador de transiciones de estado inválidas. +`agent_privilege_escalation_attempts_total` - Contador de solicitudes sospechosas. + +#### 8.2 Mejoras en el Registro + +**Registro de Solicitudes:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. Estrategia de Pruebas + +#### 9.1 Pruebas Unitarias + +**Lógica de Filtrado de Herramientas:** +Cálculos de intersección de grupos de pruebas +Lógica de filtrado basada en el estado de la prueba +Verificar la asignación predeterminada de grupos y estados +Probar el comportamiento de los comodines en los grupos +Validar el manejo de grupos vacíos +Probar escenarios de filtrado combinados de grupos y estados + +**Validación de la Configuración:** +Probar la carga de herramientas con varias configuraciones de grupos y estados +Verificar la validación del esquema para especificaciones inválidas de grupos y estados +Probar la compatibilidad con versiones anteriores con las configuraciones existentes +Validar las definiciones y ciclos de transición de estados + +#### 9.2 Pruebas de Integración + +**Comportamiento del Agente:** +Verificar que los agentes solo vean las herramientas filtradas por grupo y estado +Probar la ejecución de solicitudes con varias combinaciones de grupos +Probar las transiciones de estado durante la ejecución del agente +Validar el manejo de errores cuando no hay herramientas disponibles +Probar el progreso del flujo de trabajo a través de múltiples estados + +**Pruebas de Seguridad:** +Probar la prevención de la escalada de privilegios +Verificar la precisión del registro de auditoría +Probar la integración de la puerta de enlace con los permisos de usuario + +#### 9.3 Escenarios de Extremo a Extremo + +**Uso Multi-inquilino con Flujos de Trabajo de Estado:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**Progresión del estado del flujo de trabajo:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. Consideraciones de rendimiento + +#### 10.1 Impacto de la carga de herramientas + +**Carga de configuración:** +Los metadatos del grupo y el estado se cargan una vez al inicio. +Sobrecarga de memoria mínima por herramienta (campos adicionales). +No hay impacto en el tiempo de inicialización de la herramienta. + +**Procesamiento de solicitudes:** +El filtrado combinado de grupo+estado se realiza una vez por solicitud. +Complejidad O(n), donde n = número de herramientas configuradas. +Las transiciones de estado agregan una sobrecarga mínima (asignación de cadenas). +Impacto insignificante para un número típico de herramientas (< 100). + +#### 10.2 Estrategias de optimización + +**Conjuntos de herramientas precalculados:** +Almacenar en caché los conjuntos de herramientas por combinación de grupo+estado. +Evitar el filtrado repetido para patrones comunes de grupo/estado. +Intercambio entre memoria y computación para combinaciones de uso frecuente. + +**Carga diferida:** +Cargar las implementaciones de las herramientas solo cuando sea necesario. +Reducir el tiempo de inicio para implementaciones con muchas herramientas. +Registro dinámico de herramientas basado en los requisitos del grupo. + +### 11. Mejoras futuras + +#### 11.1 Asignación dinámica de grupos + +**Agrupación con conocimiento del contexto:** +Asignar herramientas a grupos según el contexto de la solicitud. +Disponibilidad del grupo basada en el tiempo (solo durante el horario de atención). +Restricciones de grupo basadas en la carga (herramientas costosas durante el bajo uso). + +#### 11.2 Jerarquías de grupos + +**Estructura de grupo anidada:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 Recomendaciones de herramientas + +**Sugerencias basadas en grupos:** +Sugerir grupos de herramientas óptimos para tipos de solicitud. +Aprender de los patrones de uso para mejorar las recomendaciones. +Proporcionar grupos de respaldo cuando las herramientas preferidas no están disponibles. + +### 12. Preguntas abiertas + +1. **Validación de grupos**: ¿Deben los nombres de grupo no válidos en las solicitudes causar errores graves o advertencias? + +2. **Descubrimiento de grupos**: ¿Debería el sistema proporcionar una API para listar los grupos disponibles y sus herramientas? + +3. **Grupos dinámicos**: ¿Deben los grupos ser configurables en tiempo de ejecución o solo al inicio? + +4. **Herencia de grupos**: ¿Deben las herramientas heredar grupos de sus categorías o implementaciones principales? + +5. **Monitoreo del rendimiento**: ¿Qué métricas adicionales son necesarias para realizar un seguimiento eficaz del uso de herramientas basado en grupos? + +### 13. Conclusión + +El sistema de grupos de herramientas proporciona: + +**Seguridad**: Control de acceso granular sobre las capacidades del agente. +**Rendimiento**: Reducción de la sobrecarga de carga y selección de herramientas. +**Flexibilidad**: Clasificación de herramientas multidimensional. +**Compatibilidad**: Integración perfecta con arquitecturas de agentes existentes. + +Este sistema permite que las implementaciones de TrustGraph gestionen mejor el acceso a las herramientas, mejoren los límites de seguridad y optimicen el uso de recursos, al tiempo que mantiene la compatibilidad con versiones anteriores con las configuraciones y solicitudes existentes. diff --git a/docs/tech-specs/tool-group.he.md b/docs/tech-specs/tool-group.he.md new file mode 100644 index 00000000..dd0206f8 --- /dev/null +++ b/docs/tech-specs/tool-group.he.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "קבוצת כלים עבור TrustGraph" +parent: "Hebrew (Beta)" +--- + +# קבוצת כלים עבור TrustGraph + +> **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.0 + +### תקציר מנהלים + +מפרט זה מגדיר מערכת לקבוצות כלים עבור סוכני TrustGraph, המאפשרת שליטה מדויקת על אילו כלים זמינים עבור בקשות ספציפיות. המערכת מציגה סינון כלים מבוסס קבוצות באמצעות תצורה ומפרט ברמת הבקשה, ומאפשרת גבולות אבטחה טובים יותר, ניהול משאבים וחלוקת פונקציונליות של יכולות הסוכנים. + +### 1. סקירה כללית + +#### 1.1 הצגת הבעיה + +כיום, לסוכני TrustGraph יש גישה לכל הכלים המוגדרים, ללא קשר להקשר הבקשה או לדרישות האבטחה. זה יוצר מספר אתגרים: + +**סיכון אבטחה**: כלים רגישים (לדוגמה, שינוי נתונים) זמינים גם עבור שאילתות לקריאה בלבד. +**בזבוז משאבים**: כלים מורכבים נטענים גם כאשר שאילתות פשוטות אינן דורשים אותם. +**בלבול פונקציונלי**: סוכנים עשויים לבחור כלים לא מתאימים כאשר קיימות חלופות פשוטות יותר. +**בידוד מרובה דיירים**: קבוצות משתמשים שונות צריכות גישה לקבוצות כלים שונות. + +#### 1.2 סקירה כללית של הפתרון + +מערכת קבוצות הכלים מציגה: + +1. **סיווג קבוצות**: כלים מסומנים עם שייכות לקבוצות במהלך התצורה. +2. **סינון ברמת הבקשה**: בקשת סוכן מציינת אילו קבוצות כלים מותרות. +3. **אכיפה בזמן ריצה**: לסוכנים יש גישה רק לכלים התואמים לקבוצות המבוקשות. +4. **קיבוץ גמיש**: כלים יכולים להיות שייכים למספר קבוצות עבור תרחישים מורכבים. + +### 2. שינויים בסכימה + +#### 2.1 שיפור סכימת תצורת הכלים + +תצורת הכלים הקיימת משופרת עם שדה `group`: + +**לפני:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**אחרי:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**מפרט שדה קבוצה:** +`group`: Array(String) - רשימה של קבוצות שאליהן הכלי הזה שייך +**אופציונלי**: כלים ללא שדה קבוצה שייכים לקבוצה "ברירת מחדל" +**חברות מרובות**: כלים יכולים להיות שייכים למספר קבוצות +**רגישות לאותיות**: שמות הקבוצות חייבים להיות התאמה מדויקת של מחרוזות + +#### 2.1.2 שיפור מעבר מצבים של כלי + +כלים יכולים לציין אופציונלית מעברי מצבים וזמינות מבוססת מצב: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**מפרט שדה מצב:** +`state`: מחרוזת - **אופציונלי** - המצב שאליו יש לעבור לאחר ביצוע מוצלח של הכלי +`available_in_states`: מערך(מחרוזת) - **אופציונלי** - מצבים שבהם הכלי זמין +**התנהגות ברירת מחדל**: כלים ללא `available_in_states` זמינים בכל המצבים +**מעבר מצב**: מתרחש רק לאחר ביצוע מוצלח של הכלי + +#### 2.2 שיפור סכימת AgentRequest + +הסכימה `AgentRequest` ב-`trustgraph-base/trustgraph/schema/services/agent.py` משופרת: + +**AgentRequest נוכחי:** +`question`: מחרוזת - שאילתת משתמש +`plan`: מחרוזת - תוכנית ביצוע (ניתן להסיר) +`state`: מחרוזת - מצב סוכן +`history`: מערך(AgentStep) - היסטוריית ביצוע + +**AgentRequest משופר:** +`question`: מחרוזת - שאילתת משתמש +`state`: מחרוזת - מצב ביצוע סוכן (כעת בשימוש פעיל לסינון כלים) +`history`: מערך(AgentStep) - היסטוריית ביצוע +`group`: מערך(מחרוזת) - **חדש** - קבוצות כלים מותרות עבור בקשה זו + +**שינויים בסכימה:** +**הוסר**: השדה `plan` אינו נחוץ יותר וניתן להסירו (היה מיועד במקור למפרט כלים) +**נוסף**: השדה `group` למפרט קבוצות כלים +**שופר**: השדה `state` שולט כעת בזמינות הכלים במהלך הביצוע + +**התנהגויות של שדות:** + +**קבוצת שדות:** +**אופציונלי**: אם לא צוין, ברירת המחדל היא ["default"] +**חיתוך**: זמינים רק כלים התואמים לפחות לקבוצה אחת שצוינה +**מערך ריק**: אין כלים זמינים (הסוכן יכול להשתמש רק בנימוקים פנימיים) +**תו גלובלי**: קבוצה מיוחדת "*" מעניקה גישה לכל הכלים + +**שדה מצב:** +**אופציונלי**: אם לא צוין, ברירת המחדל היא "לא מוגדר" +**סינון מבוסס מצב**: זכאים רק כלים הזמינים במצב הנוכחי +**מצב ברירת מחדל**: מצב "לא מוגדר" מאפשר לכל הכלים (בהתאם לסינון קבוצות) +**מעברי מצב**: כלים יכולים לשנות מצב לאחר ביצוע מוצלח + +### 3. דוגמאות לקבוצות מותאמות אישית + +ארגונים יכולים להגדיר קבוצות ספציפיות לתחום: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. פרטי יישום + +#### 4.1 טעינת כלים וסינון + +**שלב התצורה:** +1. כל הכלים נטענים מקובץ התצורה עם ההקצאות שלהם לקבוצות. +2. כלים שאין להם קבוצות מוגדרות מוקצים לקבוצה "ברירת מחדל". +3. חברות בקבוצות מאומתות ונשמרות במאגר הכלים. + +**שלב עיבוד בקשות:** +1. בקשת סוכן מגיעה עם ציון קבוצה אופציונלי. +2. הסוכן מסנן את הכלים הזמינים בהתבסס על חיתוך קבוצות. +3. רק כלים תואמים מועברים להקשר הביצוע של הסוכן. +4. הסוכן פועל עם סט הכלים המסונן לאורך כל מחזור החיים של הבקשה. + +#### 4.2 לוגיקת סינון כלים + +**סינון משולב של קבוצות ומצבים:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**לוגיקת מעבר מצבים:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 נקודות אינטגרציה של סוכן + +**סוכן ReAct:** +סינון כלים מתבצע ב-agent_manager.py במהלך יצירת רישום הכלים +רשימת הכלים הזמינים מסוננת לפי קבוצה ומצב לפני יצירת תוכנית +מעברי מצבים מעדכנים את השדה AgentRequest.state לאחר ביצוע מוצלח של כלי +האיטרציה הבאה משתמשת במצב המעודכן לסינון כלים + +**סוכן מבוסס ביטחון:** +סינון כלים מתבצע ב-planner.py במהלך יצירת תוכנית +אימות ExecutionStep מבטיח שרק כלים מתאימים לקבוצה ולמצב משמשים +בקר הזרימה (Flow controller) מאכף את זמינות הכלים בזמן ריצה +מעברי מצבים מנוהלים על ידי בקר הזרימה בין שלבים + +### 5. דוגמאות תצורה + +#### 5.1 תצורת כלים עם קבוצות ומצבים + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 דוגמאות לבקשות עם תהליכי עבודה מוגדרים מראש + +**בקשה ראשונית למחקר:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*כלים זמינים: שאילתת ידע, השלמת טקסט* +*לאחר שאילתת ידע: מצב → "ניתוח"* + +**שלב הניתוח:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*כלים זמינים: complex-analysis, graph-update, reset-workflow* +*לאחר complex-analysis: מצב → "תוצאות"* + +**שלב התוצאות:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*כלים זמינים: reset-workflow בלבד* +*לאחר הפעלת reset-workflow: מצב → "לא מוגדר"* + +**דוגמה לזרימת עבודה - זרימה מלאה:** +1. **התחלה (לא מוגדר):** השתמש ב-knowledge-query → מעבר למצב "ניתוח" +2. **מצב ניתוח:** השתמש ב-complex-analysis → מעבר למצב "תוצאות" +3. **מצב תוצאות:** השתמש ב-reset-workflow → חזרה למצב "לא מוגדר" +4. **חזרה להתחלה:** כל הכלים הזמינים זמינים שוב + +### 6. שיקולי אבטחה + +#### 6.1 שילוב בקרת גישה + +**סינון ברמת השער (Gateway):** +השער יכול לאכוף הגבלות קבוצתיות בהתבסס על הרשאות משתמש +מניעת העלאת הרשאות באמצעות מניפולציה של בקשות +רישום ביקורת כולל קבוצות כלים מבוקשות ומוענקות + +**לוגיקה לדוגמה של השער:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 ביקורת וניטור + +**רשומות ביקורת משופרות:** +רישום קבוצות כלים מבוקשות ומצב התחלתי עבור כל בקשה +מעקב אחר מעברי מצבים ושימוש בכלים לפי חברות בקבוצה +ניטור ניסיונות גישה לא מורשים לקבוצות ושינויי מצב לא חוקיים +התראה על דפוסי שימוש חריגים בקבוצות או זרימות עבודה חשודות במצב + +### 7. אסטרטגיית מעבר + +#### 7.1 תאימות לאחור + +**שלב 1: שינויים מצטברים** +הוספת שדה אופציונלי `group` לתצורות כלים +הוספת שדה אופציונלי `group` לתבנית AgentRequest +התנהגות ברירת מחדל: כל הכלים הקיימים שייכים לקבוצה "ברירת מחדל" +בקשות קיימות ללא שדה קבוצה משתמשות בקבוצה "ברירת מחדל" + +**התנהגות קיימת נשמרת:** +כלים ללא תצורת קבוצה ממשיכים לעבוד (קבוצת ברירת מחדל) +כלים ללא תצורת מצב זמינים בכל המצבים +בקשות ללא ציון קבוצה ניגשות לכל הכלים (קבוצת ברירת מחדל) +בקשות ללא ציון מצב משתמשות במצב "לא מוגדר" (כל הכלים זמינים) +אין שינויים משמעותיים לפריסות קיימות + +### 8. ניטור וניתוח + +#### 8.1 מדדים חדשים + +**שימוש בקבוצות כלים:** +`agent_tool_group_requests_total` - מונה של בקשות לפי קבוצה +`agent_tool_group_availability` - מדד של כלים זמינים לכל קבוצה +`agent_filtered_tools_count` - היסטוגרמה של מספר כלים לאחר סינון לפי קבוצה + מצב + +**מדדי זרימת עבודה של מצבים:** +`agent_state_transitions_total` - מונה של מעברי מצבים לפי כלי +`agent_workflow_duration_seconds` - היסטוגרמה של זמן שהייה בכל מצב +`agent_state_availability` - מדד של כלים זמינים לכל מצב + +**מדדי אבטחה:** +`agent_group_access_denied_total` - מונה של גישה לא מורשית לקבוצה +`agent_invalid_state_transition_total` - מונה של מעברי מצב לא חוקיים +`agent_privilege_escalation_attempts_total` - מונה של בקשות חשודות + +#### 8.2 שיפורים ברישום + +**רישום בקשות:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. אסטרטגיית בדיקות + +#### 9.1 בדיקות יחידה + +**לוגיקת סינון כלים:** +חישובים של חיתוך קבוצות בדיקה +לוגיקת סינון מבוססת מצבים +אימות הקצאה ברירת מחדל של קבוצות ומצבים +בדיקת התנהגות של קבוצות עם תווים מיוחדים (wildcard) +אימות טיפול בקבוצות ריקות +בדיקת תרחישים משולבים של סינון קבוצות + מצבים + +**אימות תצורה:** +בדיקת טעינת כלים עם תצורות שונות של קבוצות ומצבים +אימות של תקינות הסכימה עבור מפרטי קבוצות ומצבים לא חוקיים +בדיקת תאימות לאחור עם תצורות קיימות +אימות של הגדרות מעברים בין מצבים ומחזורים + +#### 9.2 בדיקות אינטגרציה + +**התנהגות של סוכן (Agent):** +אימות שהסוכן רואה רק כלים שעברו סינון לפי קבוצה + מצב +בדיקת ביצוע בקשות עם שילובים שונים של קבוצות +בדיקת מעברים בין מצבים במהלך ביצוע הסוכן +אימות של טיפול בשגיאות כאשר אין כלים זמינים +בדיקת התקדמות של זרימת עבודה דרך מצבים שונים + +**בדיקות אבטחה:** +בדיקת מניעת העלאת הרשאות +אימות של דיוק רישום ביקורת (audit trail) +בדיקת שילוב של שער (gateway) עם הרשאות משתמש + +#### 9.3 תרחישים מקצה לקצה + +**שימוש מרובה דיירים (Multi-tenant) עם זרימות עבודה מבוססות מצבים:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**התקדמות מצב העבודה:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. שיקולי ביצועים + +#### 10.1 השפעת טעינת כלים + +**טעינת תצורה:** +מטא-נתונים של קבוצה ומצב נטענים פעם אחת בעת ההפעלה +תקורה מינימלית של זיכרון לכל כלי (שדות נוספים) +אין השפעה על זמן אתחול הכלי + +**עיבוד בקשות:** +סינון משולב של קבוצה+מצב מתבצע פעם אחת לכל בקשה +מורכבות O(n) כאשר n = מספר הכלים המוגדרים +מעברים של מצבים מוסיפים תקורה מינימלית (הקצאת מחרוזות) +השפעה זניחה עבור מספר טיפוסי של כלים (< 100) + +#### 10.2 אסטרטגיות אופטימיזציה + +**סטים של כלים מחושבים מראש:** +שמירת סטים של כלים לפי שילוב של קבוצה+מצב +הימנעות מסינון חוזר עבור דפוסי קבוצה/מצב נפוצים +פשרה בין זיכרון לחישוב עבור שילובים בשימוש תכוף + +**טעינה עצלה:** +טעינת יישומי כלים רק כאשר נדרש +הפחתת זמן אתחול עבור פריסות עם מספר רב של כלים +רישום דינמי של כלים בהתאם לדרישות הקבוצה + +### 11. שיפורים עתידיים + +#### 11.1 הקצאת קבוצות דינמית + +**קיבוץ מודע להקשר:** +הקצאת כלים לקבוצות בהתבסס על הקשר הבקשה +זמינות קבוצה מבוססת זמן (שעות עסקים בלבד) +הגבלות קבוצה מבוססות עומס (כלים יקרים בזמן שימוש נמוך) + +#### 11.2 היררכיות קבוצות + +**מבנה קבוצות מקונן:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 המלצות כלים + +**הצעות מבוססות קבוצות:** +הצעת קבוצות כלים אופטימליות עבור סוגי בקשות +למידה מדפוסי שימוש לשיפור ההמלצות +מתן קבוצות חלופיות כאשר הכלים המועדפים אינם זמינים + +### 12. שאלות פתוחות + +1. **אימות קבוצות**: האם שמות קבוצות לא חוקיים בבקשות צריכים לגרום לכישלונות קשים או אזהרות? + +2. **גילוי קבוצות**: האם המערכת צריכה לספק API לרשימת קבוצות זמינות והכלים שלהן? + +3. **קבוצות דינמיות**: האם הקבוצות צריכות להיות ניתנות להגדרה בזמן ריצה או רק בזמן ההתחלה? + +4. **ירושה של קבוצות**: האם כלים צריכים לרשת קבוצות מהקטגוריות או המימושים הראשיים שלהם? + +5. **ניטור ביצועים**: אילו מדדים נוספים נחוצים למעקב יעיל אחר שימוש בכלים מבוססי קבוצות? + +### 13. סיכום + +מערכת קבוצות הכלים מספקת: + +**אבטחה**: בקרת גישה מפורטת על יכולות הסוכן +**ביצועים**: הפחתת עומס טעינה ובחירת כלים +**גמישות**: סיווג רב-ממדי של כלים +**תאימות**: שילוב חלק עם ארכיטקטורות סוכן קיימות + +מערכת זו מאפשרת לפריסות TrustGraph לנהל טוב יותר את גישת הכלים, לשפר את גבולות האבטחה ולייעל את השימוש במשאבים תוך שמירה על תאימות מלאה לאחור עם תצורות ובקשות קיימות. diff --git a/docs/tech-specs/tool-group.hi.md b/docs/tech-specs/tool-group.hi.md new file mode 100644 index 00000000..674433d2 --- /dev/null +++ b/docs/tech-specs/tool-group.hi.md @@ -0,0 +1,499 @@ +--- +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. +## तकनीकी विनिर्देश v1.0 + +### कार्यकारी सारांश + +यह विनिर्देश ट्रस्टग्राफ एजेंटों के लिए एक टूल ग्रुपिंग सिस्टम को परिभाषित करता है जो विशिष्ट अनुरोधों के लिए कौन से टूल उपलब्ध हैं, इस पर बारीक नियंत्रण की अनुमति देता है। यह सिस्टम कॉन्फ़िगरेशन और अनुरोध-स्तरीय विनिर्देश के माध्यम से समूह-आधारित टूल फ़िल्टरिंग पेश करता है, जो एजेंट क्षमताओं के बेहतर सुरक्षा सीमाओं, संसाधन प्रबंधन और कार्यात्मक विभाजन को सक्षम करता है। + +### 1. अवलोकन + +#### 1.1 समस्या विवरण + +वर्तमान में, ट्रस्टग्राफ एजेंटों के पास अनुरोध संदर्भ या सुरक्षा आवश्यकताओं की परवाह किए बिना, सभी कॉन्फ़िगर किए गए टूल तक पहुंच होती है। इससे कई चुनौतियाँ उत्पन्न होती हैं: + +**सुरक्षा जोखिम**: संवेदनशील टूल (जैसे, डेटा संशोधन) रीड-ओनली प्रश्नों के लिए भी उपलब्ध हैं +**संसाधन बर्बादी**: जटिल टूल लोड किए जाते हैं, भले ही सरल प्रश्नों के लिए उनकी आवश्यकता न हो +**कार्यात्मक भ्रम**: एजेंट उपयुक्त टूल का चयन कर सकते हैं जब सरल विकल्प मौजूद हों +**मल्टी-टेनेन्ट अलगाव**: विभिन्न उपयोगकर्ता समूहों को अलग-अलग टूल सेट तक पहुंचने की आवश्यकता होती है + +#### 1.2 समाधान अवलोकन + +टूल ग्रुप सिस्टम निम्नलिखित पेश करता है: + +1. **समूह वर्गीकरण**: टूल को कॉन्फ़िगरेशन के दौरान समूह सदस्यता के साथ टैग किया जाता है +2. **अनुरोध-स्तरीय फ़िल्टरिंग**: AgentRequest निर्दिष्ट करता है कि कौन से टूल समूह अनुमत हैं +3. **रनटाइम प्रवर्तन**: एजेंटों के पास केवल अनुरोधित समूहों से मेल खाने वाले टूल तक पहुंच होती है +4. **लचीला समूहीकरण**: जटिल परिदृश्यों के लिए टूल कई समूहों से संबंधित हो सकते हैं + +### 2. स्कीमा परिवर्तन + +#### 2.1 टूल कॉन्फ़िगरेशन स्कीमा संवर्धन + +मौजूदा टूल कॉन्फ़िगरेशन को एक `group` फ़ील्ड के साथ बढ़ाया गया है: + +**पहले:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**इसके बाद:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**समूह क्षेत्र विनिर्देश:** +`group`: Array(String) - यह सूची उन समूहों की है जिनसे यह उपकरण संबंधित है। +**वैकल्पिक**: जिन उपकरणों में समूह क्षेत्र नहीं है, वे "डिफ़ॉल्ट" समूह से संबंधित होते हैं। +**बहु-सदस्यता**: उपकरण कई समूहों से संबंधित हो सकते हैं। +**केस-संवेदी**: समूह नाम सटीक स्ट्रिंग मिलान होते हैं। + +#### 2.1.2 उपकरण स्थिति परिवर्तन संवर्धन + +उपकरण वैकल्पिक रूप से स्थिति परिवर्तनों और स्थिति-आधारित उपलब्धता को निर्दिष्ट कर सकते हैं: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**राज्य क्षेत्र विनिर्देश:** +`state`: स्ट्रिंग - **वैकल्पिक** - सफल टूल निष्पादन के बाद जाने वाला राज्य +`available_in_states`: Array(String) - **वैकल्पिक** - उन राज्यों में जहां यह टूल उपलब्ध है +**डिफ़ॉल्ट व्यवहार:** `available_in_states` के बिना टूल सभी राज्यों में उपलब्ध होते हैं +**राज्य परिवर्तन:** केवल सफल टूल निष्पादन के बाद होता है + +#### 2.2 AgentRequest स्कीमा में सुधार + +`trustgraph-base/trustgraph/schema/services/agent.py` में `AgentRequest` स्कीमा में सुधार किया गया है: + +**वर्तमान AgentRequest:** +`question`: स्ट्रिंग - उपयोगकर्ता प्रश्न +`plan`: स्ट्रिंग - निष्पादन योजना (हटाया जा सकता है) +`state`: स्ट्रिंग - एजेंट राज्य +`history`: Array(AgentStep) - निष्पादन इतिहास + +**सुधारे गए AgentRequest:** +`question`: स्ट्रिंग - उपयोगकर्ता प्रश्न +`state`: स्ट्रिंग - एजेंट निष्पादन स्थिति (अब सक्रिय रूप से टूल फ़िल्टरिंग के लिए उपयोग किया जाता है) +`history`: Array(AgentStep) - निष्पादन इतिहास +`group`: Array(String) - **नया** - इस अनुरोध के लिए अनुमत टूल समूह + +**स्कीमा परिवर्तन:** +**हटाया गया:** `plan` फ़ील्ड अब आवश्यक नहीं है और इसे हटाया जा सकता है (मूल रूप से टूल विनिर्देश के लिए अभिप्रेत था) +**जोड़ा गया:** टूल समूह विनिर्देश के लिए `group` फ़ील्ड +**सुधारा गया:** `state` फ़ील्ड अब निष्पादन के दौरान टूल उपलब्धता को नियंत्रित करता है + +**फ़ील्ड व्यवहार:** + +**समूह फ़ील्ड:** +**वैकल्पिक:** यदि निर्दिष्ट नहीं है, तो डिफ़ॉल्ट रूप से ["default"] होता है +**प्रतिच्छेदन:** केवल वे टूल जो कम से कम एक निर्दिष्ट समूह से मेल खाते हैं, वे उपलब्ध हैं +**खाली सरणी:** कोई टूल उपलब्ध नहीं है (एजेंट केवल आंतरिक तर्क का उपयोग कर सकता है) +**वाइल्डकार्ड:** विशेष समूह "*" सभी टूल तक पहुंच प्रदान करता है + +**राज्य फ़ील्ड:** +**वैकल्पिक:** यदि निर्दिष्ट नहीं है, तो डिफ़ॉल्ट रूप से "अपरिभाषित" होता है +**राज्य-आधारित फ़िल्टरिंग:** केवल वर्तमान राज्य में उपलब्ध टूल ही पात्र हैं +**डिफ़ॉल्ट राज्य:** "अपरिभाषित" राज्य सभी टूल की अनुमति देता है (समूह फ़िल्टरिंग के अधीन) +**राज्य परिवर्तन:** सफल निष्पादन के बाद टूल अपनी स्थिति बदल सकते हैं + +### 3. कस्टम समूह उदाहरण + +संगठन डोमेन-विशिष्ट समूह परिभाषित कर सकते हैं: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. कार्यान्वयन विवरण + +#### 4.1 टूल लोडिंग और फ़िल्टरिंग + +**कॉन्फ़िगरेशन चरण:** +1. सभी टूल अपने समूह असाइनमेंट के साथ कॉन्फ़िगरेशन से लोड किए जाते हैं। +2. स्पष्ट समूहों के बिना टूल को "डिफ़ॉल्ट" समूह में असाइन किया जाता है। +3. समूह सदस्यता को मान्य किया जाता है और टूल रजिस्ट्री में संग्रहीत किया जाता है। + +**अनुरोध प्रसंस्करण चरण:** +1. एजेंट अनुरोध वैकल्पिक समूह विनिर्देश के साथ आता है। +2. एजेंट उपलब्ध टूल को समूह प्रतिच्छेदन के आधार पर फ़िल्टर करता है। +3. केवल मिलान करने वाले टूल को एजेंट निष्पादन संदर्भ में पास किया जाता है। +4. एजेंट अनुरोध जीवनचक्र के दौरान फ़िल्टर किए गए टूल सेट के साथ काम करता है। + +#### 4.2 टूल फ़िल्टरिंग लॉजिक + +**संयुक्त समूह और स्थिति फ़िल्टरिंग:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**राज्य परिवर्तन तर्क:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 एजेंट एकीकरण बिंदु + +**ReAct एजेंट:** +टूल फ़िल्टरिंग एजेंट_मैनेजर.py में टूल रजिस्ट्री निर्माण के दौरान होती है। +उपलब्ध टूल की सूची को योजना निर्माण से पहले समूह और स्थिति दोनों द्वारा फ़िल्टर किया जाता है। +स्थिति परिवर्तन सफल टूल निष्पादन के बाद AgentRequest.state फ़ील्ड को अपडेट करते हैं। +अगले पुनरावृत्ति में टूल फ़िल्टरिंग के लिए अपडेट की गई स्थिति का उपयोग किया जाता है। + +**विश्वास-आधारित एजेंट:** +टूल फ़िल्टरिंग योजना निर्माण के दौरान प्लानर.py में होती है। +ExecutionStep सत्यापन यह सुनिश्चित करता है कि केवल समूह+स्थिति के लिए योग्य टूल का उपयोग किया जाए। +फ्लो कंट्रोलर रनटाइम पर टूल की उपलब्धता को लागू करता है। +चरणों के बीच फ्लो कंट्रोलर द्वारा स्थिति परिवर्तन प्रबंधित किए जाते हैं। + +### 5. कॉन्फ़िगरेशन उदाहरण + +#### 5.1 समूहों और स्थितियों के साथ टूल कॉन्फ़िगरेशन + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 अनुरोध के उदाहरण राज्य वर्कफ़्लो के साथ + +**प्रारंभिक अनुसंधान अनुरोध:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*उपलब्ध उपकरण: ज्ञान-पूछताछ, पाठ-पूर्णता* +*ज्ञान-पूछताछ के बाद: अवस्था → "विश्लेषण"* + +**विश्लेषण चरण:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*उपलब्ध उपकरण: जटिल-विश्लेषण, ग्राफ-अपडेट, रीसेट-वर्कफ़्लो* +*जटिल-विश्लेषण के बाद: अवस्था → "परिणाम"* + +**परिणाम चरण:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*उपलब्ध उपकरण: केवल reset-workflow* +*reset-workflow के बाद: स्थिति → "अपरिभाषित"* + +**वर्कफ़्लो उदाहरण - पूर्ण प्रवाह:** +1. **शुरुआत (अपरिभाषित):** ज्ञान-पूछताछ का उपयोग करें → "विश्लेषण" में संक्रमण +2. **विश्लेषण अवस्था:** जटिल-विश्लेषण का उपयोग करें → "परिणाम" में संक्रमण +3. **परिणाम अवस्था:** reset-workflow का उपयोग करें → "अपरिभाषित" में वापस संक्रमण +4. **शुरुआत में वापस:** सभी प्रारंभिक उपकरण फिर से उपलब्ध + +### 6. सुरक्षा संबंधी विचार + +#### 6.1 एक्सेस नियंत्रण एकीकरण + +**गेटवे-स्तरीय फ़िल्टरिंग:** +गेटवे उपयोगकर्ता अनुमतियों के आधार पर समूह प्रतिबंधों को लागू कर सकता है +अनुरोध हेरफेर के माध्यम से विशेषाधिकारों को बढ़ाने से रोकें +ऑडिट ट्रेल में अनुरोधित और अनुमत टूल समूह शामिल हैं + +**उदाहरण गेटवे तर्क:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 ऑडिट और निगरानी + +**बेहतर ऑडिट ट्रेल:** +प्रत्येक अनुरोध के लिए अनुरोधित टूल समूहों और प्रारंभिक स्थिति को लॉग करें। +समूह सदस्यता द्वारा स्थिति परिवर्तन और टूल उपयोग को ट्रैक करें। +अनधिकृत समूह एक्सेस प्रयासों और अमान्य स्थिति परिवर्तनों की निगरानी करें। +असामान्य समूह उपयोग पैटर्न या संदिग्ध स्थिति वर्कफ़्लो पर अलर्ट जारी करें। + +### 7. माइग्रेशन रणनीति + +#### 7.1 पिछड़ा संगतता + +**चरण 1: अतिरिक्त परिवर्तन** +टूल कॉन्फ़िगरेशन में वैकल्पिक `group` फ़ील्ड जोड़ें। +AgentRequest स्कीमा में वैकल्पिक `group` फ़ील्ड जोड़ें। +डिफ़ॉल्ट व्यवहार: सभी मौजूदा टूल "डिफ़ॉल्ट" समूह से संबंधित हैं। +समूह फ़ील्ड के बिना मौजूदा अनुरोध "डिफ़ॉल्ट" समूह का उपयोग करते हैं। + +**मौजूदा व्यवहार संरक्षित:** +समूह कॉन्फ़िगरेशन के बिना टूल काम करना जारी रखते हैं (डिफ़ॉल्ट समूह)। +स्थिति कॉन्फ़िगरेशन के बिना टूल सभी स्थितियों में उपलब्ध हैं। +समूह विनिर्देश के बिना अनुरोध सभी टूल तक पहुंचते हैं (डिफ़ॉल्ट समूह)। +स्थिति विनिर्देश के बिना अनुरोध "अपरिभाषित" स्थिति का उपयोग करते हैं (सभी टूल उपलब्ध हैं)। +मौजूदा परिनियोजन में कोई ब्रेकिंग परिवर्तन नहीं। + +### 8. निगरानी और अवलोकन + +#### 8.1 नए मेट्रिक्स + +**टूल समूह उपयोग:** +`agent_tool_group_requests_total` - समूह द्वारा अनुरोधों की संख्या। +`agent_tool_group_availability` - प्रति समूह उपलब्ध टूल का गेज। +`agent_filtered_tools_count` - समूह+स्थिति फ़िल्टरिंग के बाद टूल गणना का हिस्टोग्राम। + +**स्थिति वर्कफ़्लो मेट्रिक्स:** +`agent_state_transitions_total` - टूल द्वारा स्थिति परिवर्तनों की संख्या। +`agent_workflow_duration_seconds` - प्रत्येक स्थिति में बिताए गए समय का हिस्टोग्राम। +`agent_state_availability` - प्रति स्थिति उपलब्ध टूल का गेज। + +**सुरक्षा मेट्रिक्स:** +`agent_group_access_denied_total` - अनधिकृत समूह एक्सेस की संख्या। +`agent_invalid_state_transition_total` - अमान्य स्थिति परिवर्तनों की संख्या। +`agent_privilege_escalation_attempts_total` - संदिग्ध अनुरोधों की संख्या। + +#### 8.2 लॉगिंग सुधार + +**अनुरोध लॉगिंग:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. परीक्षण रणनीति + +#### 9.1 यूनिट परीक्षण + +**उपकरण फ़िल्टरिंग लॉजिक:** +परीक्षण समूह इंटरसेक्शन गणनाएँ +परीक्षण राज्य-आधारित फ़िल्टरिंग लॉजिक +डिफ़ॉल्ट समूह और राज्य असाइनमेंट की जाँच करें +वाइल्डकार्ड समूह व्यवहार का परीक्षण करें +खाली समूह हैंडलिंग को मान्य करें +संयुक्त समूह+राज्य फ़िल्टरिंग परिदृश्यों का परीक्षण करें + +**कॉन्फ़िगरेशन सत्यापन:** +विभिन्न समूह और राज्य कॉन्फ़िगरेशन के साथ उपकरण लोडिंग का परीक्षण करें +अमान्य समूह और राज्य विनिर्देशों के लिए स्कीमा सत्यापन की जाँच करें +मौजूदा कॉन्फ़िगरेशन के साथ पिछड़े अनुकूलता का परीक्षण करें +राज्य संक्रमण परिभाषाओं और चक्रों को मान्य करें + +#### 9.2 एकीकरण परीक्षण + +**एजेंट व्यवहार:** +सत्यापित करें कि एजेंट केवल समूह+राज्य फ़िल्टर किए गए उपकरणों को ही देखते हैं +विभिन्न समूह संयोजनों के साथ अनुरोध निष्पादन का परीक्षण करें +एजेंट निष्पादन के दौरान राज्य संक्रमणों का परीक्षण करें +जब कोई उपकरण उपलब्ध न हो तो त्रुटि हैंडलिंग को मान्य करें +कई राज्यों के माध्यम से वर्कफ़्लो प्रगति का परीक्षण करें + +**सुरक्षा परीक्षण:** +विशेषाधिकार वृद्धि रोकथाम का परीक्षण करें +ऑडिट ट्रेल की सटीकता को सत्यापित करें +उपयोगकर्ता अनुमतियों के साथ गेटवे एकीकरण का परीक्षण करें + +#### 9.3 एंड-टू-एंड परिदृश्य + +**राज्य वर्कफ़्लो के साथ मल्टी-टेनांट उपयोग:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**कार्यप्रवाह स्थिति प्रगति:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. प्रदर्शन संबंधी विचार + +#### 10.1 टूल लोडिंग का प्रभाव + +**कॉन्फ़िगरेशन लोडिंग:** +समूह और स्थिति मेटाडेटा स्टार्टअप पर एक बार लोड होता है +प्रति टूल न्यूनतम मेमोरी ओवरहेड (अतिरिक्त फ़ील्ड) +टूल इनिशियलाइज़ेशन समय पर कोई प्रभाव नहीं + +**अनुरोध प्रसंस्करण:** +समूह+स्थिति फ़िल्टरिंग एक बार प्रति अनुरोध होती है +O(n) जटिलता, जहाँ n = कॉन्फ़िगर किए गए टूल की संख्या +राज्य परिवर्तन न्यूनतम ओवरहेड जोड़ते हैं (स्ट्रिंग असाइनमेंट) +विशिष्ट टूल गणना के लिए नगण्य प्रभाव (< 100) + +#### 10.2 अनुकूलन रणनीतियाँ + +**पूर्व-गणना किए गए टूल सेट:** +समूह+स्थिति संयोजन द्वारा टूल सेट को कैश करें +सामान्य समूह/स्थिति पैटर्न के लिए बार-बार फ़िल्टरिंग से बचें +बार-बार उपयोग किए जाने वाले संयोजनों के लिए मेमोरी बनाम गणना का समझौता + +**लेज़ी लोडिंग:** +केवल आवश्यकता पड़ने पर टूल कार्यान्वयन लोड करें +कई टूल वाले डिप्लॉयमेंट के लिए स्टार्टअप समय कम करें +समूह आवश्यकताओं के आधार पर गतिशील टूल पंजीकरण + +### 11. भविष्य के सुधार + +#### 11.1 गतिशील समूह असाइनमेंट + +**संदर्भ-जागरूक समूहीकरण:** +अनुरोध संदर्भ के आधार पर टूल को समूहों में असाइन करें +समय-आधारित समूह उपलब्धता (केवल व्यावसायिक घंटों के दौरान) +लोड-आधारित समूह प्रतिबंध (कम उपयोग के दौरान महंगे टूल) + +#### 11.2 समूह पदानुक्रम + +**नेस्टेड समूह संरचना:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 उपकरण अनुशंसाएँ + +**समूह-आधारित सुझाव:** +अनुरोध प्रकारों के लिए इष्टतम उपकरण समूहों का सुझाव दें +अनुशंसाओं को बेहतर बनाने के लिए उपयोग पैटर्न से सीखें +जब पसंदीदा उपकरण उपलब्ध न हों तो वैकल्पिक समूहों का प्रावधान करें + +### 12. खुले प्रश्न + +1. **समूह सत्यापन**: क्या अनुरोधों में अमान्य समूह नामों के कारण हार्ड विफलताएँ या चेतावनियाँ आनी चाहिए? + +2. **समूह खोज**: क्या सिस्टम उपलब्ध समूहों और उनके उपकरणों की सूची प्रदान करने के लिए एक एपीआई प्रदान करना चाहिए? + +3. **गतिशील समूह**: क्या समूहों को रनटाइम पर या केवल स्टार्टअप पर ही कॉन्फ़िगर किया जाना चाहिए? + +4. **समूह विरासत**: क्या उपकरणों को अपने मूल श्रेणियों या कार्यान्वयन से समूहों को विरासत में मिलना चाहिए? + +5. **प्रदर्शन निगरानी**: समूह-आधारित उपकरण उपयोग को प्रभावी ढंग से ट्रैक करने के लिए किन अतिरिक्त मेट्रिक्स की आवश्यकता है? + +### 13. निष्कर्ष + +उपकरण समूह प्रणाली निम्नलिखित प्रदान करती है: + +**सुरक्षा**: एजेंट क्षमताओं पर बारीक पहुंच नियंत्रण +**प्रदर्शन**: उपकरण लोडिंग और चयन ओवरहेड में कमी +**लचीलापन**: बहु-आयामी उपकरण वर्गीकरण +**संगतता**: मौजूदा एजेंट आर्किटेक्चर के साथ निर्बाध एकीकरण + +यह प्रणाली ट्रस्टग्राफ परिनियोजन को उपकरण पहुंच को बेहतर ढंग से प्रबंधित करने, सुरक्षा सीमाओं में सुधार करने और मौजूदा कॉन्फ़िगरेशन और अनुरोधों के साथ पूर्ण पिछड़े संगतता बनाए रखते हुए संसाधन उपयोग को अनुकूलित करने में सक्षम बनाती है। diff --git a/docs/tech-specs/tool-group.md b/docs/tech-specs/tool-group.md index e4816de5..7900dac5 100644 --- a/docs/tech-specs/tool-group.md +++ b/docs/tech-specs/tool-group.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "TrustGraph Tool Group System" +parent: "Tech Specs" +--- + # TrustGraph Tool Group System ## Technical Specification v1.0 diff --git a/docs/tech-specs/tool-group.pt.md b/docs/tech-specs/tool-group.pt.md new file mode 100644 index 00000000..36781347 --- /dev/null +++ b/docs/tech-specs/tool-group.pt.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "TrustGraph Tool Group System" +parent: "Portuguese (Beta)" +--- + +# TrustGraph Tool Group System + +> **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. +## Especificação Técnica v1.0 + +### Resumo Executivo + +Esta especificação define um sistema de agrupamento de ferramentas para agentes TrustGraph que permite um controle preciso sobre quais ferramentas estão disponíveis para solicitações específicas. O sistema introduz filtragem de ferramentas baseada em grupos por meio de configuração e especificação no nível da solicitação, permitindo melhores limites de segurança, gerenciamento de recursos e particionamento funcional das capacidades do agente. + +### 1. Visão Geral + +#### 1.1 Declaração do Problema + +Atualmente, os agentes TrustGraph têm acesso a todas as ferramentas configuradas, independentemente do contexto da solicitação ou dos requisitos de segurança. Isso cria vários desafios: + +**Risco de Segurança**: Ferramentas sensíveis (por exemplo, modificação de dados) estão disponíveis mesmo para consultas somente leitura. +**Desperdício de Recursos**: Ferramentas complexas são carregadas mesmo quando consultas simples não as exigem. +**Confusão Funcional**: Os agentes podem selecionar ferramentas inadequadas quando alternativas mais simples existem. +**Isolamento Multi-inquilino**: Diferentes grupos de usuários precisam de acesso a conjuntos de ferramentas diferentes. + +#### 1.2 Visão Geral da Solução + +O sistema de agrupamento de ferramentas introduz: + +1. **Classificação por Grupo**: As ferramentas são marcadas com associações de grupo durante a configuração. +2. **Filtragem no Nível da Solicitação**: AgentRequest especifica quais grupos de ferramentas são permitidos. +3. **Aplicação em Tempo de Execução**: Os agentes têm acesso apenas a ferramentas que correspondem aos grupos solicitados. +4. **Agrupamento Flexível**: As ferramentas podem pertencer a vários grupos para cenários complexos. + +### 2. Alterações no Esquema + +#### 2.1 Aprimoramento do Esquema de Configuração da Ferramenta + +A configuração existente da ferramenta é aprimorada com um campo `group`: + +**Antes:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**Depois:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**Especificação do Campo do Grupo:** +`group`: Array(String) - Lista de grupos aos quais esta ferramenta pertence +**Opcional**: Ferramentas sem campo de grupo pertencem ao grupo "padrão" +**Múltipla associação**: As ferramentas podem pertencer a vários grupos +**Sensível a maiúsculas e minúsculas**: Os nomes dos grupos são correspondências exatas de strings + +#### 2.1.2 Melhoria da Transição de Estado da Ferramenta + +As ferramentas podem, opcionalmente, especificar transições de estado e disponibilidade baseada no estado: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**Especificação do Campo de Estado:** +`state`: String - **Opcional** - Estado para o qual transitar após a execução bem-sucedida da ferramenta +`available_in_states`: Array(String) - **Opcional** - Estados nos quais esta ferramenta está disponível +**Comportamento padrão**: Ferramentas sem `available_in_states` estão disponíveis em todos os estados +**Transição de estado**: Ocorre apenas após a execução bem-sucedida da ferramenta + +#### 2.2 Melhoria do Esquema AgentRequest + +O esquema `AgentRequest` em `trustgraph-base/trustgraph/schema/services/agent.py` é aprimorado: + +**AgentRequest Atual:** +`question`: String - Consulta do usuário +`plan`: String - Plano de execução (pode ser removido) +`state`: String - Estado do agente +`history`: Array(AgentStep) - Histórico de execução + +**AgentRequest Aprimorado:** +`question`: String - Consulta do usuário +`state`: String - Estado de execução do agente (agora usado ativamente para filtragem de ferramentas) +`history`: Array(AgentStep) - Histórico de execução +`group`: Array(String) - **NOVO** - Grupos de ferramentas permitidos para este pedido + +**Alterações no Esquema:** +**Removido**: O campo `plan` não é mais necessário e pode ser removido (originalmente destinado à especificação de ferramentas) +**Adicionado**: O campo `group` para especificação de grupos de ferramentas +**Aprimorado**: O campo `state` agora controla a disponibilidade de ferramentas durante a execução + +**Comportamentos dos Campos:** + +**Grupo de Campo:** +**Opcional**: Se não especificado, o padrão é ["default"] +**Interseção**: Apenas as ferramentas que correspondem a pelo menos um grupo especificado estão disponíveis +**Array vazio**: Nenhuma ferramenta disponível (o agente só pode usar o raciocínio interno) +**Curinga**: O grupo especial "*" concede acesso a todas as ferramentas + +**Campo de Estado:** +**Opcional**: Se não especificado, o padrão é "undefined" +**Filtragem baseada em estado**: Apenas as ferramentas disponíveis no estado atual são elegíveis +**Estado padrão**: O estado "undefined" permite todas as ferramentas (sujeito à filtragem de grupos) +**Transições de estado**: As ferramentas podem alterar o estado após a execução bem-sucedida + +### 3. Exemplos de Grupos Personalizados + +As organizações podem definir grupos específicos do domínio: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. Detalhes de Implementação + +#### 4.1 Carregamento e Filtragem de Ferramentas + +**Fase de Configuração:** +1. Todas as ferramentas são carregadas da configuração com suas atribuições de grupo. +2. Ferramentas sem grupos explícitos são atribuídas ao grupo "padrão". +3. A associação a grupos é validada e armazenada no registro de ferramentas. + +**Fase de Processamento de Solicitações:** +1. Uma solicitação do agente chega com uma especificação de grupo opcional. +2. O agente filtra as ferramentas disponíveis com base na interseção de grupos. +3. Apenas as ferramentas correspondentes são passadas para o contexto de execução do agente. +4. O agente opera com o conjunto de ferramentas filtrado durante todo o ciclo de vida da solicitação. + +#### 4.2 Lógica de Filtragem de Ferramentas + +**Filtragem Combinada de Grupo e Estado:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**Lógica de Transição de Estado:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 Pontos de Integração do Agente + +**Agente ReAct:** +O filtro de ferramentas ocorre em agent_manager.py durante a criação do registro de ferramentas. +A lista de ferramentas disponíveis é filtrada por grupo e estado antes da geração do plano. +As transições de estado atualizam o campo AgentRequest.state após a execução bem-sucedida da ferramenta. +A próxima iteração usa o estado atualizado para o filtro de ferramentas. + +**Agente Baseado em Confiança:** +O filtro de ferramentas ocorre em planner.py durante a geração do plano. +A validação de ExecutionStep garante que apenas as ferramentas elegíveis por grupo e estado sejam usadas. +O controlador de fluxo impõe a disponibilidade da ferramenta em tempo de execução. +As transições de estado são gerenciadas pelo Controlador de Fluxo entre os passos. + +### 5. Exemplos de Configuração + +#### 5.1 Configuração de Ferramentas com Grupos e Estados + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 Exemplos de Solicitações com Fluxos de Trabalho de Estado + +**Solicitação de Pesquisa Inicial:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*Ferramentas disponíveis: knowledge-query, text-completion* +*Após knowledge-query: estado → "análise"* + +**Fase de Análise:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*Ferramentas disponíveis: complex-analysis, graph-update, reset-workflow* +*Após complex-analysis: estado → "results"* + +**Fase de Resultados:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*Ferramentas disponíveis: apenas reset-workflow* +*Após reset-workflow: estado → "indefinido"* + +**Exemplo de Fluxo de Trabalho - Fluxo Completo:** +1. **Início (indefinido)**: Use knowledge-query → transições para "análise" +2. **Estado de análise**: Use complex-analysis → transições para "resultados" +3. **Estado de resultados**: Use reset-workflow → transições de volta para "indefinido" +4. **Retorno ao início**: Todas as ferramentas iniciais estão disponíveis novamente + +### 6. Considerações de Segurança + +#### 6.1 Integração de Controle de Acesso + +**Filtragem no Nível do Gateway:** +O gateway pode impor restrições de grupo com base nas permissões do usuário +Previne a elevação de privilégios através da manipulação de solicitações +O registro de auditoria inclui os grupos de ferramentas solicitados e concedidos + +**Exemplo de Lógica do Gateway:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 Auditoria e Monitoramento + +**Rastreamento de Auditoria Aprimorado:** +Registrar os grupos de ferramentas solicitados e o estado inicial por solicitação +Rastrear as transições de estado e o uso de ferramentas por associação a grupos +Monitorar tentativas de acesso não autorizado a grupos e transições de estado inválidas +Alertar sobre padrões de uso de grupos incomuns ou fluxos de trabalho de estado suspeitos + +### 7. Estratégia de Migração + +#### 7.1 Compatibilidade com Versões Anteriores + +**Fase 1: Alterações Aditivas** +Adicionar campo opcional `group` às configurações de ferramentas +Adicionar campo opcional `group` ao esquema AgentRequest +Comportamento padrão: Todas as ferramentas existentes pertencem ao grupo "default" +Solicitações existentes sem o campo de grupo usam o grupo "default" + +**Comportamento Existente Preservado:** +Ferramentas sem configuração de grupo continuam a funcionar (grupo default) +Ferramentas sem configuração de estado estão disponíveis em todos os estados +Solicitações sem especificação de grupo acessam todas as ferramentas (grupo default) +Solicitações sem especificação de estado usam o estado "undefined" (todas as ferramentas disponíveis) +Nenhuma alteração disruptiva para implantações existentes + +### 8. Monitoramento e Observabilidade + +#### 8.1 Novas Métricas + +**Uso de Grupos de Ferramentas:** +`agent_tool_group_requests_total` - Contador de solicitações por grupo +`agent_tool_group_availability` - Indicador do número de ferramentas disponíveis por grupo +`agent_filtered_tools_count` - Histograma do número de ferramentas após a filtragem por grupo + estado + +**Métricas de Fluxo de Trabalho de Estado:** +`agent_state_transitions_total` - Contador de transições de estado por ferramenta +`agent_workflow_duration_seconds` - Histograma do tempo gasto em cada estado +`agent_state_availability` - Indicador do número de ferramentas disponíveis por estado + +**Métricas de Segurança:** +`agent_group_access_denied_total` - Contador de acessos a grupos não autorizados +`agent_invalid_state_transition_total` - Contador de transições de estado inválidas +`agent_privilege_escalation_attempts_total` - Contador de solicitações suspeitas + +#### 8.2 Melhorias de Registro (Logging) + +**Registro de Solicitações:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. Estratégia de Testes + +#### 9.1 Testes Unitários + +**Lógica de Filtragem de Ferramentas:** +Cálculos de interseção de grupos de teste +Lógica de filtragem baseada em estado +Verificar a atribuição padrão de grupo e estado +Testar o comportamento de grupos curinga +Validar o tratamento de grupos vazios +Testar cenários de filtragem combinada de grupo+estado + +**Validação de Configuração:** +Testar o carregamento de ferramentas com várias configurações de grupo e estado +Verificar a validação de esquema para especificações inválidas de grupo e estado +Testar a compatibilidade com versões anteriores com as configurações existentes +Validar as definições e ciclos de transição de estado + +#### 9.2 Testes de Integração + +**Comportamento do Agente:** +Verificar se os agentes veem apenas as ferramentas filtradas por grupo+estado +Testar a execução de solicitações com várias combinações de grupos +Testar as transições de estado durante a execução do agente +Validar o tratamento de erros quando nenhuma ferramenta está disponível +Testar a progressão do fluxo de trabalho por meio de vários estados + +**Testes de Segurança:** +Testar a prevenção de escalada de privilégios +Verificar a precisão do registro de auditoria +Testar a integração do gateway com as permissões do usuário + +#### 9.3 Cenários de Ponta a Ponta + +**Uso Multi-tenant com Fluxos de Trabalho de Estado:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**Progressão do Estado do Fluxo de Trabalho:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. Considerações de Desempenho + +#### 10.1 Impacto do Carregamento de Ferramentas + +**Carregamento de Configuração:** +Metadados de grupo e estado carregados uma vez na inicialização +Sobrecarga de memória mínima por ferramenta (campos adicionais) +Sem impacto no tempo de inicialização da ferramenta + +**Processamento de Requisições:** +Filtragem combinada de grupo+estado ocorre uma vez por requisição +Complexidade O(n) onde n = número de ferramentas configuradas +Transições de estado adicionam uma sobrecarga mínima (atribuição de string) +Impacto insignificante para um número típico de ferramentas (< 100) + +#### 10.2 Estratégias de Otimização + +**Conjuntos de Ferramentas Pré-calculados:** +Armazene em cache os conjuntos de ferramentas por combinação de grupo+estado +Evite filtragem repetida para padrões comuns de grupo/estado +Troca entre memória e computação para combinações frequentemente usadas + +**Carregamento Preguiçoso (Lazy Loading):** +Carregue as implementações das ferramentas somente quando necessário +Reduza o tempo de inicialização para implantações com muitas ferramentas +Registro dinâmico de ferramentas com base nos requisitos do grupo + +### 11. Melhorias Futuras + +#### 11.1 Atribuição Dinâmica de Grupos + +**Agrupamento Contextual:** +Atribua ferramentas a grupos com base no contexto da requisição +Disponibilidade do grupo baseada no tempo (apenas horário comercial) +Restrições de grupo baseadas na carga (ferramentas caras durante baixo uso) + +#### 11.2 Hierarquias de Grupos + +**Estrutura de Grupo Aninhada:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 Recomendações de Ferramentas + +**Sugestões Baseadas em Grupos:** +Sugerir grupos de ferramentas ideais para tipos de requisições +Aprender com padrões de uso para melhorar as recomendações +Fornecer grupos de fallback quando as ferramentas preferidas não estiverem disponíveis + +### 12. Perguntas Abertas + +1. **Validação de Grupos**: Nomes de grupos inválidos em requisições devem causar falhas graves ou avisos? + +2. **Descoberta de Grupos**: O sistema deve fornecer uma API para listar os grupos disponíveis e suas ferramentas? + +3. **Grupos Dinâmicos**: Os grupos devem ser configuráveis em tempo de execução ou apenas na inicialização? + +4. **Herança de Grupos**: As ferramentas devem herdar grupos de suas categorias ou implementações pai? + +5. **Monitoramento de Desempenho**: Quais métricas adicionais são necessárias para rastrear o uso de ferramentas com base em grupos de forma eficaz? + +### 13. Conclusão + +O sistema de grupos de ferramentas fornece: + +**Segurança**: Controle de acesso granular sobre as capacidades do agente +**Desempenho**: Redução da sobrecarga de carregamento e seleção de ferramentas +**Flexibilidade**: Classificação de ferramentas multidimensional +**Compatibilidade**: Integração perfeita com arquiteturas de agentes existentes + +Este sistema permite que as implementações do TrustGraph gerenciem melhor o acesso às ferramentas, aprimorem as fronteiras de segurança e otimizem o uso de recursos, mantendo total compatibilidade com versões anteriores de configurações e requisições. diff --git a/docs/tech-specs/tool-group.ru.md b/docs/tech-specs/tool-group.ru.md new file mode 100644 index 00000000..35881379 --- /dev/null +++ b/docs/tech-specs/tool-group.ru.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "TrustGraph Tool Group System" +parent: "Russian (Beta)" +--- + +# TrustGraph Tool Group System + +> **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. +## Техническая спецификация v1.0 + +### Краткое описание + +Эта спецификация определяет систему группировки инструментов для агентов TrustGraph, которая позволяет осуществлять детальный контроль над тем, какие инструменты доступны для конкретных запросов. Система вводит фильтрацию инструментов на основе групп с помощью конфигурации и указания на уровне запроса, что обеспечивает более строгие границы безопасности, управление ресурсами и функциональное разделение возможностей агентов. + +### 1. Обзор + +#### 1.1 Описание проблемы + +В настоящее время агенты TrustGraph имеют доступ ко всем настроенным инструментам, независимо от контекста запроса или требований безопасности. Это создает несколько проблем: + +**Риск безопасности**: Чувствительные инструменты (например, изменение данных) доступны даже для запросов только для чтения. +**Неэффективное использование ресурсов**: Сложные инструменты загружаются даже тогда, когда простые запросы не требуют их. +**Функциональная путаница**: Агенты могут выбирать неподходящие инструменты, когда существуют более простые альтернативы. +**Изоляция для многопользовательских сред**: Различным группам пользователей требуется доступ к разным наборам инструментов. + +#### 1.2 Обзор решения + +Система группировки инструментов включает в себя: + +1. **Классификация по группам**: Инструменты помечаются принадлежностью к группам во время конфигурации. +2. **Фильтрация на уровне запроса**: AgentRequest указывает, какие группы инструментов разрешены. +3. **Принудительное исполнение во время выполнения**: Агенты имеют доступ только к инструментам, соответствующим запрошенным группам. +4. **Гибкая группировка**: Инструменты могут принадлежать к нескольким группам для сложных сценариев. + +### 2. Изменения схемы + +#### 2.1 Расширение схемы конфигурации инструмента + +Существующая схема конфигурации инструмента расширена с помощью поля `group`: + +**До:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**После:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**Спецификация поля группы:** +`group`: Array(String) - Список групп, к которым принадлежит этот инструмент. +**Необязательно**: Инструменты без поля группы принадлежат к группе "по умолчанию". +**Множественная принадлежность**: Инструменты могут принадлежать к нескольким группам. +**Чувствительность к регистру**: Имена групп должны точно соответствовать строке. + +#### 2.1.2 Улучшение переходов состояния инструмента + +Инструменты могут опционально указывать переходы состояний и доступность, зависящую от состояния: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**Спецификация состояния:** +`state`: String - **Необязательно** - Состояние, в которое система переходит после успешного выполнения инструмента. +`available_in_states`: Array(String) - **Необязательно** - Состояния, в которых этот инструмент доступен. +**Поведение по умолчанию**: Инструменты без `available_in_states` доступны во всех состояниях. +**Переход состояния**: Происходит только после успешного выполнения инструмента. + +#### 2.2 Улучшение схемы AgentRequest + +Схема `AgentRequest` в `trustgraph-base/trustgraph/schema/services/agent.py` улучшена: + +**Текущий AgentRequest:** +`question`: String - Пользовательский запрос. +`plan`: String - План выполнения (может быть удален). +`state`: String - Состояние агента. +`history`: Array(AgentStep) - История выполнения. + +**Улучшенный AgentRequest:** +`question`: String - Пользовательский запрос. +`state`: String - Состояние выполнения агента (теперь активно используется для фильтрации инструментов). +`history`: Array(AgentStep) - История выполнения. +`group`: Array(String) - **НОВОЕ** - Группы инструментов, разрешенные для этого запроса. + +**Изменения в схеме:** +**Удалено**: Поле `plan` больше не требуется и может быть удалено (изначально предназначалось для указания инструментов). +**Добавлено**: Поле `group` для указания групп инструментов. +**Улучшено**: Поле `state` теперь контролирует доступность инструментов во время выполнения. + +**Поведение полей:** + +**Группа (Group):** +**Необязательно**: Если не указано, по умолчанию используется ["default"]. +**Пересечение**: Доступны только инструменты, соответствующие хотя бы одной указанной группе. +**Пустой массив**: Ни один инструмент не доступен (агент может использовать только внутренние рассуждения). +**Подстановочный знак**: Специальная группа "*" предоставляет доступ ко всем инструментам. + +**Состояние (State):** +**Необязательно**: Если не указано, по умолчанию используется "undefined". +**Фильтрация по состоянию**: Доступны только инструменты, доступные в текущем состоянии. +**Состояние по умолчанию**: Состояние "undefined" позволяет использовать все инструменты (с учетом фильтрации по группам). +**Переходы состояний**: Состояние инструментов может меняться после успешного выполнения. + +### 3. Примеры пользовательских групп + +Организации могут определять группы, специфичные для домена: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. Детали реализации + +#### 4.1 Загрузка и фильтрация инструментов + +**Фаза конфигурации:** +1. Все инструменты загружаются из конфигурации вместе с их групповыми назначениями. +2. Инструменты, не имеющие явных групповых назначений, назначаются в группу "default". +3. Групповая принадлежность проверяется и сохраняется в реестре инструментов. + +**Фаза обработки запросов:** +1. Запрос AgentRequest поступает с опциональной спецификацией группы. +2. Agent фильтрует доступные инструменты на основе пересечения групп. +3. Только соответствующие инструменты передаются в контекст выполнения агента. +4. Agent работает с отфильтрованным набором инструментов на протяжении всего жизненного цикла запроса. + +#### 4.2 Логика фильтрации инструментов + +**Комбинированная фильтрация по группам и состоянию:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**Логика переходов состояний:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 Точки интеграции агента + +**Агент ReAct:** +Фильтрация инструментов происходит в файле agent_manager.py во время создания регистрации инструментов. +Список доступных инструментов фильтруется как по группе, так и по состоянию перед генерацией плана. +Изменения состояния обновляют поле AgentRequest.state после успешного выполнения инструмента. +Следующая итерация использует обновленное состояние для фильтрации инструментов. + +**Агент, основанный на оценке уверенности:** +Фильтрация инструментов происходит в файле planner.py во время генерации плана. +Проверка ExecutionStep гарантирует, что используются только инструменты, соответствующие группе и состоянию. +Контроллер потока обеспечивает доступность инструментов во время выполнения. +Изменения состояния управляются контроллером потока между шагами. + +### 5. Примеры конфигурации + +#### 5.1 Конфигурация инструментов с группами и состояниями + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 Примеры запросов с рабочими процессами, зависящими от состояния. + +**Первоначальный запрос на исследование:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*Доступные инструменты: knowledge-query, text-completion* +*После knowledge-query: состояние → "analysis"* + +**Фаза анализа:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*Доступные инструменты: complex-analysis, graph-update, reset-workflow* +*После complex-analysis: состояние → "results"* + +**Фаза результатов:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*Доступные инструменты: только reset-workflow* +*После выполнения reset-workflow: состояние → "undefined"* + +**Пример рабочего процесса - Полный цикл:** +1. **Начало (undefined):** Используйте knowledge-query → переходы в состояние "analysis" +2. **Состояние анализа:** Используйте complex-analysis → переходы в состояние "results" +3. **Состояние результатов:** Используйте reset-workflow → возврат в состояние "undefined" +4. **Возврат к началу:** Все начальные инструменты снова доступны + +### 6. Вопросы безопасности + +#### 6.1 Интеграция с контролем доступа + +**Фильтрация на уровне шлюза:** +Шлюз может применять ограничения для групп на основе прав доступа пользователя +Предотвращение повышения привилегий путем манипулирования запросами +Журнал аудита включает запрошенные и предоставленные группы инструментов + +**Пример логики шлюза:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 Аудит и мониторинг + +**Расширенный журнал аудита:** +Регистрировать запрошенные группы инструментов и начальное состояние для каждого запроса. +Отслеживать переходы состояний и использование инструментов по принадлежности к группе. +Мониторить попытки несанкционированного доступа к группам и недопустимые переходы состояний. +Оповещать об необычных шаблонах использования групп или подозрительных рабочих процессах состояний. + +### 7. Стратегия миграции + +#### 7.1 Обратная совместимость + +**Этап 1: Аддитивные изменения** +Добавить необязательное поле `group` в конфигурации инструментов. +Добавить необязательное поле `group` в схему AgentRequest. +Поведение по умолчанию: Все существующие инструменты принадлежат к группе "default". +Существующие запросы без поля группы используют группу "default". + +**Сохранение существующего поведения:** +Инструменты без конфигурации группы продолжают работать (группа "default"). +Инструменты без конфигурации состояния доступны во всех состояниях. +Запросы без указания группы получают доступ ко всем инструментам (группа "default"). +Запросы без указания состояния используют состояние "не определено" (доступны все инструменты). +Отсутствуют изменения, нарушающие работу существующих развертываний. + +### 8. Мониторинг и наблюдаемость + +#### 8.1 Новые метрики + +**Использование групп инструментов:** +`agent_tool_group_requests_total` - Счетчик запросов по группе. +`agent_tool_group_availability` - Показатель количества доступных инструментов для каждой группы. +`agent_filtered_tools_count` - Гистограмма количества инструментов после фильтрации по группе и состоянию. + +**Метрики рабочих процессов состояний:** +`agent_state_transitions_total` - Счетчик переходов состояний по инструменту. +`agent_workflow_duration_seconds` - Гистограмма времени, проведенного в каждом состоянии. +`agent_state_availability` - Показатель количества доступных инструментов для каждого состояния. + +**Метрики безопасности:** +`agent_group_access_denied_total` - Счетчик несанкционированного доступа к группам. +`agent_invalid_state_transition_total` - Счетчик недопустимых переходов состояний. +`agent_privilege_escalation_attempts_total` - Счетчик подозрительных запросов. + +#### 8.2 Улучшения ведения журнала + +**Ведение журнала запросов:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. Стратегия тестирования + +#### 9.1 Юнит-тесты + +**Логика фильтрации инструментов:** +Расчет пересечений тестовых групп +Логика фильтрации на основе состояния теста +Проверка назначения групп и состояний по умолчанию +Тестирование поведения групп с подстановочными знаками +Проверка обработки пустых групп +Тестирование сценариев комбинированной фильтрации групп и состояний + +**Проверка конфигурации:** +Тестирование загрузки инструментов с различными конфигурациями групп и состояний +Проверка валидации схемы для неверных спецификаций групп и состояний +Тестирование обратной совместимости с существующими конфигурациями +Проверка определений и циклов переходов состояний + +#### 9.2 Интеграционные тесты + +**Поведение агента:** +Проверка того, что агенты видят только инструменты, отфильтрованные по группам и состояниям +Тестирование выполнения запросов с различными комбинациями групп +Тестирование переходов состояний во время выполнения агентом +Проверка обработки ошибок, когда ни один инструмент недоступен +Тестирование прогресса рабочего процесса через несколько состояний + +**Тестирование безопасности:** +Тестирование предотвращения повышения привилегий +Проверка точности журнала аудита +Тестирование интеграции шлюза с разрешениями пользователей + +#### 9.3 Сценарии сквозного тестирования + +**Многопользовательское использование с рабочими процессами состояний:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**Прогрессия состояний рабочего процесса:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. Соображения производительности + +#### 10.1 Влияние загрузки инструментов + +**Загрузка конфигурации:** +Метаданные группы и состояния загружаются один раз при запуске +Минимальные накладные расходы памяти на каждый инструмент (дополнительные поля) +Отсутствие влияния на время инициализации инструмента + +**Обработка запросов:** +Объединенная фильтрация группы+состояния выполняется один раз для каждого запроса +Сложность O(n), где n = количество настроенных инструментов +Переходы состояний добавляют минимальные накладные расходы (назначение строки) +Незначительное влияние для типичного количества инструментов (< 100) + +#### 10.2 Стратегии оптимизации + +**Предварительно вычисленные наборы инструментов:** +Кэширование наборов инструментов по комбинации группа+состояние +Избежание повторной фильтрации для распространенных шаблонов группы/состояния +Компромисс между памятью и вычислениями для часто используемых комбинаций + +**Отложенная загрузка:** +Загрузка реализаций инструментов только при необходимости +Уменьшение времени запуска для развертываний с большим количеством инструментов +Динамическая регистрация инструментов на основе требований группы + +### 11. Будущие улучшения + +#### 11.1 Динамическое назначение групп + +**Группировка, учитывающая контекст:** +Назначение инструментов группам на основе контекста запроса +Доступность групп во времени (только в рабочее время) +Ограничения групп на основе нагрузки (дорогие инструменты при низком использовании) + +#### 11.2 Иерархии групп + +**Вложенная структура групп:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 Рекомендации по инструментам + +**Предложения, основанные на группах:** +Предлагать оптимальные группы инструментов для типов запросов. +Учиться на основе моделей использования для улучшения рекомендаций. +Предоставлять резервные группы, когда предпочитаемые инструменты недоступны. + +### 12. Открытые вопросы + +1. **Проверка групп**: Должны ли недопустимые имена групп в запросах вызывать критические ошибки или предупреждения? + +2. **Обнаружение групп**: Должна ли система предоставлять API для перечисления доступных групп и их инструментов? + +3. **Динамические группы**: Должны ли группы быть настраиваемыми во время выполнения или только при запуске? + +4. **Наследование групп**: Должны ли инструменты наследовать группы от своих родительских категорий или реализаций? + +5. **Мониторинг производительности**: Какие дополнительные метрики необходимы для эффективного отслеживания использования инструментов на основе групп? + +### 13. Заключение + +Система групп инструментов обеспечивает: + +**Безопасность**: Гранулярный контроль доступа к возможностям агента. +**Производительность**: Снижение накладных расходов на загрузку и выбор инструментов. +**Гибкость**: Многомерная классификация инструментов. +**Совместимость**: Бесшовная интеграция с существующими архитектурами агентов. + +Эта система позволяет развертываниям TrustGraph лучше управлять доступом к инструментам, улучшать границы безопасности и оптимизировать использование ресурсов, сохраняя полную обратную совместимость с существующими конфигурациями и запросами. diff --git a/docs/tech-specs/tool-group.sw.md b/docs/tech-specs/tool-group.sw.md new file mode 100644 index 00000000..24571538 --- /dev/null +++ b/docs/tech-specs/tool-group.sw.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "Mfumo wa Kikundi cha Zana za TrustGraph" +parent: "Swahili (Beta)" +--- + +# Mfumo wa Kikundi cha Zana za TrustGraph + +> **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. +## Maelezo ya Kiufundi v1.0 + +### Muhtasari + +Maelezo haya yanafafanua mfumo wa kuunganisha zana kwa wakala wa TrustGraph ambao huruhusu udhibiti wa kina kuhusu zana zipi zinazopatikana kwa ombi fulani. Mfumo huu huleta uchujaji wa zana unaotegemea kikundi kupitia usanidi na maelezo ya ombi, na hivyo kuwezesha mipaka bora ya usalama, usimamizi wa rasilimali, na ugawaji wa kazi wa uwezo wa wakala. + +### 1. Muhtasari + +#### 1.1 Tatizo + +Kwa sasa, wakala wa TrustGraph wana uwezo wa kutumia zana zote zilizosanidiwa, bila kujali muktadha wa ombi au mahitaji ya usalama. Hii huleta changamoto kadhaa: + +**Hatari ya Usalama**: Zana nyeti (k.m., uhariri wa data) zinapatikana hata kwa maswali ya kusoma tu. +**Uharibifu wa Rasilimali**: Zana ngumu huzingirwa hata wakati maswali rahisi hayahitaji. +**Uchanganyifu wa Kazi**: Wakala wanaweza kuchagua zana zisizofaa wakati mbadala rahisi zipo. +**Tenganisho la Wafanyabiashara Wengi**: Makundi tofauti ya watumiaji yanahitaji ufikiaji wa seti tofauti za zana. + +#### 1.2 Muhtasari wa Suluhisho + +Mfumo wa kikundi cha zana huleta: + +1. **Uainishaji wa Kikundi**: Zana huwekwa alama na uanachama wa kikundi wakati wa usanidi. +2. **Uchujaji wa Kwenye Ombi**: Ombi la Wakala (AgentRequest) linaonyesha ambayo makundi ya zana yanaruhusiwa. +3. **Utendaji wa Wakati Halisi**: Wakala wana uwezo wa kutumia zana zinazolingana na makundi yaliyoomba. +4. **Uunganishaji Wenye Ugumu**: Zana zinaweza kuwa katika makundi mengi kwa hali ngumu. + +### 2. Mabadiliko ya Muundo + +#### 2.1 Ongezeko la Muundo wa Usanidi wa Zana + +Usanidi wa zana uliopo umeongezwa na sehemu `group`: + +**Kabla:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**Baada ya:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**Maelezo ya Kundi:** +`group`: Array(String) - Orodha ya vikundi ambavyo zana hii inahusishwa nayo. +**Hiari:** Zana ambazo hazina uwanja wa kundi huenda katika kundi "linaloepuka". +**Uanachama wa mengi:** Zana zinaweza kuhusishwa na vikundi vingi. +**Huwezi kubadilishwa (Case-sensitive):** Majina ya vikundi ni mechi kamili ya herufi. + +#### 2.1.2 Kuboresha Mabadiliko ya Hali ya Zana + +Zana zinaweza, kwa hiari, kutaja mabadiliko ya hali na upatikanaji unaotegemea hali: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**Maelezo ya Kikoa:** +`state`: String - **Hiari** - Hali ya kuhamia baada ya utekelezaji wa zana. +`available_in_states`: Array(String) - **Hiari** - Hali ambazo zana hii inapatikana. +**Tabia ya kawaida**: Zana ambazo hazina `available_in_states` zinapatikana katika hali zote. +**Mabadiliko ya hali**: Hutokea tu baada ya utekelezaji wa zana. + +#### 2.2 Uboreshaji wa Mfumo wa AgentRequest + +Mfumo wa `AgentRequest` katika `trustgraph-base/trustgraph/schema/services/agent.py` umeboreshwa: + +**AgentRequest ya Sasa:** +`question`: String - Uliza wa mtumiaji. +`plan`: String - Mpango wa utekelezaji (unaweza kuondolewa). +`state`: String - Hali ya wakala. +`history`: Array(AgentStep) - Historia ya utekelezaji. + +**AgentRequest Iliyoboreshwa:** +`question`: String - Uliza wa mtumiaji. +`state`: String - Hali ya utekelezaji wa wakala (sasa inatumika kikamilifu kwa kuchuja zana). +`history`: Array(AgentStep) - Historia ya utekelezaji. +`group`: Array(String) - **MPYA** - Vikundi vya zana ambavyo vinaruhusiwa kwa ombi hili. + +**Mabadiliko ya Mfumo:** +**Imeondolewa**: Uwanja wa `plan` hauhitajiki tena na unaweza kuondolewa (hapo awali ulikuwa umekusudiwa kwa vipimo vya zana). +**Imeongezwa**: Uwanja wa `group` kwa vipimo vya kikundi cha zana. +**Imeboreshwa**: Uwanja wa `state` sasa unadhibiti upatikanaji wa zana wakati wa utekelezaji. + +**Tabia za Uwanja:** + +**Kikundi cha Uwanja:** +**Hiari**: Ikiwa haijaainishwa, huanguka kwenye ["default"]. +**Uunganishaji**: Zana zinazofanana na angalau kikundi kilichoainishwa ndizo zinazopatikana. +**Safisha ya tupu**: Hakuna zana zinazopatikana (wakala anaweza kutumia tu utafakari wa ndani). +**Kikundi cha "Wildcard"**: Kikundi maalum "*" kinatoa ufikiaji kwa zana zote. + +**Uwanja wa Hali:** +**Hiari**: Ikiwa haijaainishwa, huanguka kwenye "haijulikani". +**Uchujaji wa msingi wa hali**: Zana zinazopatikana katika hali ya sasa ndizo zinazoweza kutumika. +**Hali ya kawaida**: Hali ya "haijulikani" inaruhusu zana zote (kulingana na uchujaji wa kikundi). +**Mabadiliko ya hali**: Zana zinaweza kubadilisha hali baada ya utekelezaji wa mafanikio. + +### 3. Mifano ya Kikundi Maalum + +Mashirika yanaweza kuainisha vikundi maalum ya kikoa: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. Maelezo ya Utendaji + +#### 4.1 Kupakia na Kuchuja Vifaa + +**Awamu ya Usanidi:** +1. Vifaa vyote hupakuliwa kutoka usanidi pamoja na uamlisho wao wa kundi. +2. Vifaa visivyokuwa na uamlisho wa kundi wanakabidhiwa kwenye kundi la "default". +3. Uanachama wa kundi huthibitishwa na kuhifadhiwa kwenye rejista ya vifaa. + +**Awamu ya Usimamizi wa Ombi:** +1. Ombi la Wakala (AgentRequest) linafika pamoja na maelezo ya kundi (group) ambayo ni ya hiari. +2. Wakala huchuja vifaa vinavyopatikana kulingana na msalaba wa makundi. +3. Vifaa vinavyolingana pekee hupitishwa kwa muktadha wa utekelezaji wa wakala. +4. Wakala hutumia seti ya vifaa vilivyochujwa katika mchakato wote wa ombi. + +#### 4.2 Mantiki ya Kuchuja Vifaa + +**Kuchuja kwa Pamoja kwa Kundi na Hali:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**Mantiki ya Mabadiliko ya Hali:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 Maeneo ya Uunganisho wa Mwakala + +**Mwakala wa ReAct:** +Uchujaji wa zana hufanyika katika `agent_manager.py` wakati wa uundaji wa usajili wa zana. +Orodha ya zana zinazopatikana huchujwa na kikundi na hali kabla ya utayarishaji wa mpango. +Mabadiliko ya hali husasisha sehemu `AgentRequest.state` baada ya utekelezaji wa zana kwa mafanikio. +Iteration inayofuata hutumia hali iliyosasishwa kwa uchujaji wa zana. + +**Mwakala Kulingana na Umoja wa Maoni:** +Uchujaji wa zana hufanyika katika `planner.py` wakati wa utayarishaji wa mpango. +Uthibitisho wa `ExecutionStep` huhakikisha kuwa zana zinazofaa tu za kikundi na hali hutumiwa. +Kidhibiti cha mtiririko huweka upatikanaji wa zana wakati wa utendakazi. +Mabadiliko ya hali yanadhibitiwa na Kidhibiti cha Mtiririko kati ya hatua. + +### 5. Mifano ya Usanidi + +#### 5.1 Usanidi wa Zana na Vikundi na Hali + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 Mifano ya Maombi na Mchakato wa Kazi wa Jimbo + +**Maombi ya Uchunguzi wa Mwanzo:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*Vifaa vinavyopatikana: knowledge-query, text-completion* +*Baada ya knowledge-query: hali → "uchambuzi"* + +**Awamu ya Uchambuzi:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*Vifaa vinavyopatikana: uchambuzi-wa-mazingo, sasisho-la-picha, upya-mchakato* +*Baada ya uchambuzi-wa-mazingo: hali → "matokeo"* + +**Awamu ya Matokeo:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*Vifaa vinavyopatikana: reset-workflow pekee* +*Baada ya reset-workflow: hali → "haijulikani"* + +**Mfano wa Mchakato - Mchakato Kamili:** +1. **Anza (haijulikani)**: Tumia utafutaji wa maarifa → mabadiliko hadi "uchambuzi" +2. **Hali ya uchambuzi**: Tumia uchambuzi tata → mabadiliko hadi "matokeo" +3. **Hali ya matokeo**: Tumia reset-workflow → mabadiliko kurudi "haijulikani" +4. **Kurudi kwenye mwanzo**: Vifaa vyote vya awali vinapatikana tena + +### 6. Masuala ya Usalama + +#### 6.1 Uunganisho wa Udhibiti wa Ufikiaji + +**Uchujaji wa Kawaida ya Mawasiliano:** +Kawaida ya mawasiliano inaweza kutekeleza vizuizi vya kikundi kulingana na ruhusa za mtumiaji +Kuzuia ongezeko la madaraka kupitia ubadilishaji wa ombi +Rekodi ya ukaguzi inajumuisha vikundi vya vifaa vilivyoomba na vilivyokabidhiwa + +**Mfano wa Mantiki ya Kawaida ya Mawasiliano:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 Ukaguzi na Ufuatiliaji + +**Ukaguzi Ulioboreshwa:** +Kurekodi vikundi vya zana vilivyoomba na hali ya awali kwa kila ombi +Kufuatilia mabadiliko ya hali na matumizi ya zana kwa kila kundi +Kufuatilia majaribio ya kupata vikundi bila ruhusa na mabadiliko ya hali yasiyofaa +Kutoa arifa kuhusu mifumo isiyo ya kawaida ya matumizi ya kundi au mchakato wa hali unaotishiwa + +### 7. Mkakati wa Uhamisho + +#### 7.1 Ulinganifu na Mifumo ya Zamani + +**Awamu ya 1: Mabadiliko ya Ongezeko** +Ongeza sehemu ya `group` ya hiari kwenye usanidi wa zana +Ongeza sehemu ya `group` ya hiari kwenye schema ya AgentRequest +Tabia ya chagu ya: Zana zote zilizopo zinahusishwa na kundi "linalingana" +Maombi yaliyopo bila sehemu ya kundi hutumia kundi "linalingana" + +**Tabia Zilizopo Zinahifadhiwa:** +Zana ambazo hazina usanidi wa kundi zinaendelea kufanya kazi (kundi linalingana) +Zana ambazo hazina usanidi wa hali zinapatikana katika hali zote +Maombi ambayo hayajainisha kundi hupata zana zote (kundi linalingana) +Maombi ambayo hayajainisha hali hutumia hali "isiyojulikana" (zana zote zinapatikana) +Hakuna mabadiliko yanayoweza kusababisha hitilafu katika matumizi yaliyopo + +### 8. Ufuatiliaji na Uonevu + +#### 8.1 Vipimo Vipya + +**Matumizi ya Kundi la Zana:** +`agent_tool_group_requests_total` - Idadi ya maombi kwa kila kundi +`agent_tool_group_availability` - Kiwango cha zana zinazopatikana kwa kila kundi +`agent_filtered_tools_count` - Jadili ya idadi ya zana baada ya kuchujwa kwa kundi na hali + +**Vipimo vya Mchakato wa Hali:** +`agent_state_transitions_total` - Idadi ya mabadiliko ya hali kwa kila zana +`agent_workflow_duration_seconds` - Jadili ya muda uliotumika katika kila hali +`agent_state_availability` - Kiwango cha zana zinazopatikana kwa kila hali + +**Vipimo vya Usalama:** +`agent_group_access_denied_total` - Idadi ya upataji usioidhinishwa wa kundi +`agent_invalid_state_transition_total` - Idadi ya mabadiliko ya hali yasiyofaa +`agent_privilege_escalation_attempts_total` - Idadi ya maombi yanayoshukiwa + +#### 8.2 Uboreshaji wa Kurekodi + +**Kurekodi ya Maombi:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. Mbinu ya Majaribio + +#### 9.1 Majaribio ya Kitengo + +**Mantiki ya Kuchuja Zana:** +Majaribio ya hesabu za makutano ya vikundi +Majaribio ya mantiki ya kuchuja kulingana na hali +Thibitisha utoaji wa kikundi na hali chagu +Majaribio ya tabia ya kikundi cha "wildcard" +Thibitisha usimamizi wa kikundi tupu +Majaribio ya hali ya kuchuja iliyounganisha kikundi+hali + +**Uthibitisho wa Usanidi:** +Majaribio ya kupakia zana pamoja na usanidi mbalimbali wa kikundi na hali +Thibitisha uthibitisho wa schema kwa vipimo visivyo sahihi vya kikundi na hali +Majaribio ya utangamano wa nyuma na usanidi uliopo +Thibitisha ufafanuzi na mizunguko ya mabadiliko ya hali + +#### 9.2 Majaribio ya Uunganisho + +**Tabia ya Wakala:** +Thibitisha kwamba wakala huona tu zana zilizochujwa kwa kikundi+hali +Majaribio ya utekelezaji wa ombi kwa mchanganyiko mbalimbali wa vikundi +Majaribio ya mabadiliko ya hali wakati wa utekelezaji wa wakala +Thibitisha usimamizi wa makosa wakati hakuna zana zinazopatikana +Majaribio ya maendeleo ya mtiririko wa kazi kupitia hali nyingi + +**Majaribio ya Usalama:** +Majaribio ya kuzuia kupanda kwa madaraka +Thibitisha usahihi wa njia ya ukaguzi +Majaribio ya ujumuishaji wa lango pamoja na ruhusa za mtumiaji + +#### 9.3 Hali za Jumla + +**Matumizi ya Mfumo Mwingi Pamoja na Mitiririko ya Kazi ya Hali:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**Maendeleo ya Hatua ya Mchakato:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. Mambo Muhimu ya Utendaji + +#### 10.1 Athari ya Kuanzisha Zana + +**Uteuzi wa Vipimo:** +Meta data ya kikundi na hali huwekwa mara moja wakati wa kuanzishwa +Uwezekano mdogo wa matumizi ya kumbukumbu kwa kila zana (nafasi za ziada) +Hakuna athari kwenye muda wa kuanzisha zana + +**Uchakataji wa Maombi:** +Kuchujwa kwa pamoja kwa kikundi + hali hufanyika mara moja kwa kila ombi +Ufumbuzi wa O(n) ambapo n = idadi ya zana zilizosanidiwa +Mabadiliko ya hali huongeza uwezekano mdogo (utambulisho wa herufi) +Athari ndogo kwa idadi ya kawaida ya zana (< 100) + +#### 10.2 Mikakati ya Ubora + +**Kikundi cha Zana Zilizopangwa Mapema:** +Hifadhi vikundi vya zana kwa kila mchanganyiko wa kikundi + hali +Epuka kuchujwa mara kwa mara kwa mifumo ya kawaida ya kikundi/hali +Usawa kati ya kumbukumbu na hesabu kwa mchanganyiko unaotumika mara kwa mara + +**Kupakua kwa Kila Matumizi:** +Pakua matumizi ya zana tu wakati inahitajika +Punguza muda wa kuanzishwa kwa matumizi ambayo yana zana nyingi +Usajili wa zana kwa njia ya moja kwa moja kulingana na mahitaji ya kikundi + +### 11. Maboresho ya Baadaye + +#### 11.1 Uteuzi wa Kikundi wa Kila Muda + +**Uteuzi wa Kikundi Kulingana na Mazingira:** +Weka zana katika vikundi kulingana na mazingira ya ombi +Upatikanaji wa kikundi kulingana na wakati (sawa za biashara tu) +Marekebisho ya kikundi kulingana na mzigo (zana ghali wakati wa matumizi kidogo) + +#### 11.2 Hierarkia za Kikundi + +**Muundo Ulioingilishwa wa Kikundi:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 Mapendekezo ya Zana + +**Mapendekezo Kulingana na Kikundi:** +Pendekeza vikundi bora vya zana kwa aina za ombi. +Jifunze kutoka kwa mitindo ya matumizi ili kuboresha mapendekezo. +Toa vikundi vya dharura wakati zana zinazopendekezwa hazipatikani. + +### 12. Maswali ya Kufungua + +1. **Uthibitisho wa Kikundi**: Je, majina ya vikundi yasiyo halali katika maombi yanapaswa kusababisha hitilafu kubwa au onyo? + +2. **Udagano wa Kikundi**: Je, mfumo unapaswa kutoa API ili kuorodhesha vikundi vinavyopatikana na zana zao? + +3. **Vikundi vya Njia Moja Moja**: Je, vikundi vinapaswa kupangwa wakati wa utendaji au wakati wa kuanzishwa tu? + +4. **Urithi wa Kikundi**: Je, zana zinapaswa kurithi vikundi kutoka kwa makundi yao ya wazazi au matoleo? + +5. **Ufuatiliaji wa Utendaji**: Ni vipimo vipi vya ziada vinavyohitajika kufuatilia matumizi ya zana kulingana na vikundi kwa ufanisi? + +### 13. Hitimisho + +Mfumo wa vikundi vya zana hutoa: + +**Usalama**: Udhibiti wa kina wa ufikiaji wa uwezo wa wakala. +**Utendaji**: Kupunguza mzigo wa kupakua na kuchagua zana. +**Unyumbufu**: Uainishaji wa zana wa mwelekeo mwingi. +**Ulinganifu**: Ujumuishaji laini na miundo ya wakala iliyopo. + +Mfumo huu huruhusu usakinishaji wa TrustGraph kusimamia ufikiaji wa zana vizuri zaidi, kuboresha mipaka ya usalama, na kuongeza matumizi ya rasilimali huku ikiendelea kuwa na ulinganifu kamili na usanidi na maombi iliyopo. diff --git a/docs/tech-specs/tool-group.tr.md b/docs/tech-specs/tool-group.tr.md new file mode 100644 index 00000000..0a75e10f --- /dev/null +++ b/docs/tech-specs/tool-group.tr.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "TrustGraph Araç Grubu Sistemi" +parent: "Turkish (Beta)" +--- + +# TrustGraph Araç Grubu Sistemi + +> **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. +## Teknik Özellikler v1.0 + +### Yönetici Özeti + +Bu özellik, TrustGraph ajanları için, belirli istekler için hangi araçların kullanılabilir olduğuna ince ayar yapılmasına olanak tanıyan bir araç gruplama sistemi tanımlar. Sistem, yapılandırma ve istek düzeyinde belirtme yoluyla, grup tabanlı araç filtrelemesi sunarak, daha iyi güvenlik sınırları, kaynak yönetimi ve ajan yeteneklerinin işlevsel ayrımı sağlar. + +### 1. Genel Bakış + +#### 1.1 Problem Tanımı + +Şu anda, TrustGraph ajanları, istek bağlamı veya güvenlik gereksinimlerinden bağımsız olarak, yapılandırılmış tüm araçlara erişebilir. Bu, çeşitli zorluklara yol açmaktadır: + +**Güvenlik Riski**: Hassas araçlar (örneğin, veri değişikliği), yalnızca okuma istekleri için bile kullanılabilir. +**Kaynak İsrafı**: Karmaşık araçlar, basit istekler için gerekli olmadığında bile yüklenir. +**İşlevsel Karmaşa**: Ajanlar, daha basit alternatifler varken, uygun olmayan araçları seçebilir. +**Çok Kiracılı İzolasyon**: Farklı kullanıcı gruplarının farklı araç setlerine erişmesi gerekir. + +#### 1.2 Çözümün Genel Bakışı + +Araç grubu sistemi aşağıdaki özellikleri sunar: + +1. **Grup Sınıflandırması**: Araçlar, yapılandırma sırasında grup üyelikleriyle etiketlenir. +2. **İstek Düzeyinde Filtreleme**: AgentRequest, hangi araç gruplarının izinli olduğunu belirtir. +3. **Çalışma Zamanı Uygulaması**: Ajanlar, yalnızca istenen gruplarla eşleşen araçlara erişebilir. +4. **Esnek Gruplandırma**: Araçlar, karmaşık senaryolar için birden fazla gruba ait olabilir. + +### 2. Şema Değişiklikleri + +#### 2.1 Araç Yapılandırma Şeması Geliştirmesi + +Mevcut araç yapılandırması, bir `group` alanı ile geliştirilmiştir: + +**Önce:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**Sonra:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**Grup Alanı Tanımlaması:** +`group`: Array(String) - Bu aracın ait olduğu grupların listesi +**İsteğe Bağlı:** Grup alanı olmayan araçlar, "varsayılan" gruba aittir +**Çoklu Üyelik:** Araçlar, birden fazla gruba ait olabilir +**Büyük/Küçük Harf Duyarlılığı:** Grup adları, tam string eşleşmeleridir + +#### 2.1.2 Araç Durum Geçişi Geliştirmesi + +Araçlar, isteğe bağlı olarak durum geçişlerini ve duruma bağlı kullanılabilirliği belirtebilir: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**Durum Alanı Tanımlaması:** +`state`: String - **İsteğe bağlı** - Başarılı araç çalıştırması sonrasında geçilecek durum +`available_in_states`: Array(String) - **İsteğe bağlı** - Bu aracın mevcut olduğu durumlar +**Varsayılan davranış:** `available_in_states` değeri olmayan araçlar, tüm durumlarda kullanılabilir +**Durum geçişi:** Sadece başarılı araç çalıştırması sonrasında gerçekleşir + +#### 2.2 AgentRequest Şema Geliştirmesi + +`trustgraph-base/trustgraph/schema/services/agent.py` içindeki `AgentRequest` şeması geliştirilmiştir: + +**Mevcut AgentRequest:** +`question`: String - Kullanıcı sorgusu +`plan`: String - Çalıştırma planı (kaldırılabilir) +`state`: String - Ajan durumu +`history`: Array(AgentStep) - Çalıştırma geçmişi + +**Geliştirilmiş AgentRequest:** +`question`: String - Kullanıcı sorgusu +`state`: String - Ajan çalıştırma durumu (artık araç filtreleme için aktif olarak kullanılıyor) +`history`: Array(AgentStep) - Çalıştırma geçmişi +`group`: Array(String) - **YENİ** - Bu istek için izin verilen araç grupları + +**Şema Değişiklikleri:** +**Kaldırıldı:** `plan` alanı artık gerekli değildir ve kaldırılabilir (başlangıçta araç belirtimi için tasarlanmıştı) +**Eklendi:** Araç grubu belirtimi için `group` alanı +**Geliştirildi:** `state` alanı artık çalıştırma sırasında araç kullanılabilirliğini kontrol eder + +**Alan Davranışları:** + +**Grup Alanı:** +**İsteğe bağlı:** Belirtilmezse, varsayılan olarak ["default"] değerini alır +**Kesişim:** Sadece en az bir belirtilen grupla eşleşen araçlar kullanılabilir +**Boş dizi:** Hiçbir araç kullanılamaz (ajan yalnızca dahili akıl yürütmeyi kullanabilir) +**Yıldız işareti:** Özel "*" grubu, tüm araçlara erişim sağlar + +**Durum Alanı:** +**İsteğe bağlı:** Belirtilmezse, varsayılan olarak "undefined" değerini alır +**Durum tabanlı filtreleme:** Yalnızca mevcut durumda bulunan araçlar uygun olabilir +**Varsayılan durum:** "undefined" durumu, tüm araçlara izin verir (grup filtrelemesine tabidir) +**Durum geçişleri:** Araçlar, başarılı çalıştırmadan sonra durumu değiştirebilir + +### 3. Özel Grup Örnekleri + +Kuruluşlar, alanla ilgili özel gruplar tanımlayabilir: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. Uygulama Detayları + +#### 4.1 Araç Yükleme ve Filtreleme + +**Yapılandırma Aşaması:** +1. Tüm araçlar, grup atamalarıyla birlikte yapılandırmadan yüklenir. +2. Açık bir grup atanmamış araçlar, "varsayılan" gruba atanır. +3. Grup üyeliği doğrulanır ve araç kaydında saklanır. + +**İstek İşleme Aşaması:** +1. İsteğe bağlı grup belirtimiyle birlikte AgentRequest gelir. +2. Agent, mevcut araçları grup kesişimi temelinde filtreler. +3. Yalnızca eşleşen araçlar, agent yürütme bağlamına iletilir. +4. Agent, istek yaşam döngüsü boyunca filtrelenmiş araç kümesiyle çalışır. + +#### 4.2 Araç Filtreleme Mantığı + +**Birleştirilmiş Grup ve Durum Filtreleme:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**Durum Geçişi Mantığı:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 Ajan Entegrasyon Noktaları + +**ReAct Ajanı:** +Araç filtrelemesi, araç kaydı oluşturulurken agent_manager.py dosyasında gerçekleşir. +Kullanılabilir araçlar listesi, plan oluşturulmadan önce hem grup hem de duruma göre filtrelenir. +Durum geçişleri, başarılı araç çalıştırması sonrasında AgentRequest.state alanını günceller. +Bir sonraki yineleme, araç filtrelemesi için güncellenmiş durumu kullanır. + +**Güvenilirlik Tabanlı Ajan:** +Araç filtrelemesi, plan oluşturulurken planner.py dosyasında gerçekleşir. +ExecutionStep doğrulama, yalnızca grup+durum uygun araçların kullanıldığından emin olur. +Akış denetleyicisi, çalışma zamanında araç kullanılabilirliğini zorlar. +Durum geçişleri, adımlar arasında Akış Denetleyicisi tarafından yönetilir. + +### 5. Yapılandırma Örnekleri + +#### 5.1 Gruplar ve Durumlarla Araç Yapılandırması + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 Durum İş Akışlarıyla Birlikte İstek Örnekleri + +**Başlangıç Araştırma İsteği:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*Mevcut araçlar: knowledge-query, text-completion* +*knowledge-query işleminden sonra: durum → "analiz"* + +**Analiz Aşaması:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*Mevcut araçlar: karmaşık analiz, grafik güncelleme, iş akışı sıfırlama* +*Karmaşık analizden sonra: durum → "sonuçlar"* + +**Sonuçlar Aşaması:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*Mevcut araçlar: yalnızca reset-workflow* +*reset-workflow'dan sonra: durum → "undefined"* + +**İş Akışı Örneği - Tam Akış:** +1. **Başlangıç (undefined):** knowledge-query kullanın → "analysis" durumuna geçiş yapar. +2. **Analiz durumu:** complex-analysis kullanın → "results" durumuna geçiş yapar. +3. **Sonuç durumu:** reset-workflow kullanın → "undefined" durumuna geri döner. +4. **Başlangıca dönüş:** Tüm başlangıç araçları tekrar kullanılabilir. + +### 6. Güvenlik Hususları + +#### 6.1 Erişim Kontrolü Entegrasyonu + +**Ağ Geçidi Seviyesinde Filtreleme:** +Ağ geçidi, kullanıcı izinlerine göre grup kısıtlamalarını uygulayabilir. +İstek manipülasyonu yoluyla yetki yükseltmesini engelleyin. +Denetim kaydı, istenen ve verilen araç gruplarını içerir. + +**Örnek Ağ Geçidi Mantığı:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 Denetim ve İzleme + +**Gelişmiş Denetim Kayıtları:** +İstenen araç gruplarını ve her istek için başlangıç durumunu kaydet. +Grup üyeliği tarafından durum geçişlerini ve araç kullanımını izle. +Yetkisiz grup erişim girişimlerini ve geçersiz durum geçişlerini izle. +Olağandışı grup kullanım kalıplarını veya şüpheli durum iş akışlarını tespit etme konusunda uyarı ver. + +### 7. Geçiş Stratejisi + +#### 7.1 Geriye Dönük Uyumluluk + +**1. Aşama: Eklemeler** +Araç yapılandırmalarına isteğe bağlı `group` alanı ekle. +AgentRequest şemasına isteğe bağlı `group` alanı ekle. +Varsayılan davranış: Tüm mevcut araçlar "varsayılan" grubuna aittir. +Grup alanı olmayan mevcut istekler "varsayılan" grubunu kullanır. + +**Mevcut Davranış Korunmuştur:** +Grup yapılandırması olmayan araçlar çalışmaya devam eder (varsayılan grup). +Durum yapılandırması olmayan araçlar tüm durumlarda kullanılabilir. +Grup belirtimi olmayan istekler tüm araçlara erişebilir (varsayılan grup). +Durum belirtimi olmayan istekler "belirsiz" durumu kullanır (tüm araçlar kullanılabilir). +Mevcut dağıtımlarda herhangi bir değişiklik yapılmamıştır. + +### 8. İzleme ve Gözlemlenebilirlik + +#### 8.1 Yeni Metrikler + +**Araç Grubu Kullanımı:** +`agent_tool_group_requests_total` - Grup başına istek sayısı. +`agent_tool_group_availability` - Grup başına kullanılabilir araç sayısı. +`agent_filtered_tools_count` - Grup+durum filtrelemesinden sonraki araç sayısı histogramı. + +**Durum İş Akışı Metrikleri:** +`agent_state_transitions_total` - Araç başına durum geçişleri sayısı. +`agent_workflow_duration_seconds` - Her durumda geçirilen süre histogramı. +`agent_state_availability` - Durum başına kullanılabilir araç sayısı. + +**Güvenlik Metrikleri:** +`agent_group_access_denied_total` - Yetkisiz grup erişim sayısı. +`agent_invalid_state_transition_total` - Geçersiz durum geçişleri sayısı. +`agent_privilege_escalation_attempts_total` - Şüpheli istekler sayısı. + +#### 8.2 Kayıt Güncellemeleri + +**İstek Kayıtları:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. Test Stratejisi + +#### 9.1 Birim Testleri + +**Araç Filtreleme Mantığı:** +Test grubu kesişimi hesaplamaları +Test durumu tabanlı filtreleme mantığı +Varsayılan grup ve durum atamasını doğrulayın +Test joker karakterli grup davranışını +Boş grup işleme doğrulamasını +Test birleştirilmiş grup+durum filtreleme senaryolarını + +**Yapılandırma Doğrulama:** +Test farklı grup ve durum yapılandırmalarıyla araç yüklemeyi +Geçersiz grup ve durum tanımları için şema doğrulamasını +Test mevcut yapılandırmalarla geriye dönük uyumluluğu +Durum geçişi tanımlarını ve döngülerini doğrulayın + +#### 9.2 Entegrasyon Testleri + +**Ajan Davranışı:** +Ajanların yalnızca grup+durumla filtrelenmiş araçları gördüğünü doğrulayın +Test farklı grup kombinasyonlarıyla istek yürütmeyi +Ajan yürütülmesi sırasında durum geçişlerini test edin +Kullanılabilir araç olmadığında hata işleme doğrulamasını +Test çoklu durumlar aracılığıyla iş akışı ilerlemesini + +**Güvenlik Testleri:** +Test ayrıcalık yükseltme önlemini +Denetim kaydı doğruluğunu doğrulayın +Kullanıcı izinleriyle ağ geçidi entegrasyonunu test edin + +#### 9.3 Uçtan Uca Senaryolar + +**Durum İş Akışlarıyla Çok Kiracılı Kullanım:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**İş Akışı Durumu İlerlemesi:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. Performans Hususları + +#### 10.1 Araç Yükleme Etkisi + +**Yapılandırma Yükleme:** +Grup ve durum meta verileri, başlatmada yalnızca bir kez yüklenir. +Her araç için minimum bellek yükü (ek alanlar). +Araç başlatma süresi üzerinde herhangi bir etkisi yoktur. + +**İstek İşleme:** +Grup+durum filtrelemesi, her istek için yalnızca bir kez yapılır. +Yapılandırılmış araç sayısına (n) bağlı olarak O(n) karmaşıklığı. +Durum geçişleri, minimum bir yük ekler (dize ataması). +Tipik araç sayıları (< 100) için ihmal edilebilir bir etki. + +#### 10.2 Optimizasyon Stratejileri + +**Önceden Hesaplanan Araç Kümeleri:** +Araç kümelerini grup+durum kombinasyonuna göre önbelleğe alın. +Yaygın grup/durum kalıpları için tekrarlanan filtrelemeyi önleyin. +Sık kullanılan kombinasyonlar için bellek ve hesaplama arasında bir denge. + +**Gecikmeli Yükleme:** +Araç uygulamalarını yalnızca ihtiyaç duyulduğunda yükleyin. +Birçok araca sahip dağıtımların başlatma süresini azaltın. +Grup gereksinimlerine göre dinamik araç kaydı. + +### 11. Gelecekteki Geliştirmeler + +#### 11.1 Dinamik Grup Ataması + +**Bağlam Farkındalığına Sahip Gruplandırma:** +Araçları, istek bağlamına göre gruplara atayın. +Zaman tabanlı grup kullanılabilirliği (sadece iş saatleri). +Yük tabanlı grup kısıtlamaları (düşük kullanımda pahalı araçlar). + +#### 11.2 Grup Hiyerarşileri + +**İç İçe Geçmiş Grup Yapısı:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 Araç Önerileri + +**Grup Tabanlı Öneriler:** +İstek türleri için en uygun araç gruplarını önerin +Önerileri iyileştirmek için kullanım kalıplarından öğrenin +Tercih edilen araçlar kullanılamadığında yedek gruplar sağlayın + +### 12. Açık Sorular + +1. **Grup Doğrulama**: İstehlerdeki geçersiz grup adları, sert hatalara mı yoksa uyarı mesajlarına mı neden olmalıdır? + +2. **Grup Keşfi**: Sistem, mevcut grupları ve araçlarını listelemek için bir API sağlamalı mıdır? + +3. **Dinamik Gruplar**: Gruplar, çalışma zamanında mı yoksa yalnızca başlangıçta mı yapılandırılabilir olmalıdır? + +4. **Grup Mirası**: Araçlar, grup bilgilerini ebeveyn kategorilerinden veya uygulamalarından mı miras almalıdır? + +5. **Performans İzleme**: Grup tabanlı araç kullanımını etkili bir şekilde izlemek için hangi ek metrikler gereklidir? + +### 13. Sonuç + +Araç grubu sistemi şunları sağlar: + +**Güvenlik**: Aracılar üzerindeki yetenekler için ayrıntılı erişim kontrolü +**Performans**: Araç yükleme ve seçim üzerindeki ek yükün azaltılması +**Esneklik**: Çok boyutlu araç sınıflandırması +**Uyumluluk**: Mevcut araç mimarileriyle sorunsuz entegrasyon + +Bu sistem, TrustGraph dağıtımlarının araç erişimini daha iyi yönetmesini, güvenlik sınırlarını iyileştirmesini ve mevcut yapılandırmalar ve isteklerle tam uyumluluğu korurken kaynak kullanımını optimize etmesini sağlar. diff --git a/docs/tech-specs/tool-group.zh-cn.md b/docs/tech-specs/tool-group.zh-cn.md new file mode 100644 index 00000000..8e14b46c --- /dev/null +++ b/docs/tech-specs/tool-group.zh-cn.md @@ -0,0 +1,499 @@ +--- +layout: default +title: "TrustGraph 工具组系统" +parent: "Chinese (Beta)" +--- + +# TrustGraph 工具组系统 + +> **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. +## 技术规范 v1.0 + +### 摘要 + +本规范定义了一个用于 TrustGraph 代理的工具分组系统,该系统允许对哪些工具可用于特定请求进行细粒度控制。该系统通过配置和请求级别的指定,引入基于组的工具过滤,从而实现更好的安全边界、资源管理以及代理功能的划分。 + +### 1. 概述 + +#### 1.1 问题陈述 + +目前,TrustGraph 代理可以访问所有配置的工具,而与请求上下文或安全要求无关。这带来了一些挑战: + +**安全风险**: 即使是只读查询,也可能访问到敏感工具(例如,数据修改)。 +**资源浪费**: 即使简单的查询也不需要,也会加载复杂的工具。 +**功能混淆**: 代理可能会选择不合适的工具,而存在更简单的替代方案。 +**多租户隔离**: 不同的用户组需要访问不同的工具集。 + +#### 1.2 解决方案概述 + +工具分组系统引入了: + +1. **组分类**: 工具在配置时会被标记为所属的组。 +2. **请求级别过滤**: AgentRequest 指定允许使用的工具组。 +3. **运行时强制**: 代理只能访问与请求的组匹配的工具。 +4. **灵活分组**: 工具可以属于多个组,以适应复杂的场景。 + +### 2. 模式变更 + +#### 2.1 工具配置模式增强 + +现有的工具配置通过添加一个 `group` 字段进行增强: + +**之前:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph" +} +``` + +**翻译后:** +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"] +} +``` + +**组字段规范:** +`group`: Array(String) - 此工具所属的组列表 +**可选:** 没有组字段的工具属于 "默认" 组 +**多重隶属:** 工具可以属于多个组 +**区分大小写:** 组名必须是完全匹配的字符串 + +#### 2.1.2 工具状态转换增强 + +工具可以选择性地指定状态转换和基于状态的可用性: + +```json +{ + "name": "knowledge-query", + "type": "knowledge-query", + "description": "Query the knowledge graph", + "group": ["read-only", "knowledge", "basic"], + "state": "analysis", + "available_in_states": ["undefined", "research"] +} +``` + +**状态字段规范:** +`state`: String - **可选** - 成功执行工具后要转换到的状态 +`available_in_states`: Array(String) - **可选** - 此工具可用的状态 +**默认行为:** 没有 `available_in_states` 的工具在所有状态下都可用 +**状态转换:** 仅在成功执行工具后发生 + +#### 2.2 AgentRequest 模式增强 + +`trustgraph-base/trustgraph/schema/services/agent.py` 中的 `AgentRequest` 模式已增强: + +**当前 AgentRequest:** +`question`: String - 用户查询 +`plan`: String - 执行计划(可以删除) +`state`: String - Agent 状态 +`history`: Array(AgentStep) - 执行历史 + +**增强后的 AgentRequest:** +`question`: String - 用户查询 +`state`: String - Agent 执行状态(现在被积极用于工具过滤) +`history`: Array(AgentStep) - 执行历史 +`group`: Array(String) - **新增** - 此请求允许的工具组 + +**模式变更:** +**已移除:** `plan` 字段不再需要,可以删除(最初用于工具规范) +**已添加:** `group` 字段用于工具组规范 +**已增强:** `state` 字段现在控制执行期间的工具可用性 + +**字段行为:** + +**组字段:** +**可选:** 如果未指定,默认为 ["default"] +**交集:** 只有匹配至少一个指定组的工具才可用 +**空数组:** 没有可用工具(agent 只能使用内部推理) +**通配符:** 特殊组 "*" 授予访问所有工具的权限 + +**状态字段:** +**可选:** 如果未指定,默认为 "undefined" +**基于状态的过滤:** 只有在当前状态下可用的工具才有资格 +**默认状态:** "undefined" 状态允许所有工具(受组过滤限制) +**状态转换:** 成功执行后,工具可以更改状态 + +### 3. 自定义组示例 + +组织可以定义特定领域的组: + +```json +{ + "financial-tools": ["stock-query", "portfolio-analysis"], + "medical-tools": ["diagnosis-assist", "drug-interaction"], + "legal-tools": ["contract-analysis", "case-search"] +} +``` + +### 4. 实现细节 + +#### 4.1 工具加载和过滤 + +**配置阶段:** +1. 所有工具从配置文件中加载,并带有其组分配信息。 +2. 没有明确组分配的工具将被分配到 "默认" 组。 +3. 组成员关系将被验证并存储在工具注册表中。 + +**请求处理阶段:** +1. AgentRequest 携带可选的组指定信息。 +2. Agent 根据组的交集过滤可用的工具。 +3. 只有匹配的工具才会被传递到 Agent 执行上下文。 +4. Agent 在整个请求生命周期内都使用过滤后的工具集。 + +#### 4.2 工具过滤逻辑 + +**组合组和状态过滤:** + +``` +For each configured tool: + tool_groups = tool.group || ["default"] + tool_states = tool.available_in_states || ["*"] // Available in all states + +For each request: + requested_groups = request.group || ["default"] + current_state = request.state || "undefined" + +Tool is available if: + // Group filtering + (intersection(tool_groups, requested_groups) is not empty OR "*" in requested_groups) + AND + // State filtering + (current_state in tool_states OR "*" in tool_states) +``` + +**状态转换逻辑:** + +``` +After successful tool execution: + if tool.state is defined: + next_request.state = tool.state + else: + next_request.state = current_request.state // No change +``` + +#### 4.3 代理集成点 + +**ReAct 代理:** +工具过滤在 `agent_manager.py` 中在工具注册创建期间发生。 +可用工具列表在计划生成之前,会根据组和状态进行过滤。 +状态转换会在工具执行成功后更新 `AgentRequest.state` 字段。 +下一次迭代使用更新后的状态进行工具过滤。 + +**基于置信度的代理:** +工具过滤在 `planner.py` 中在计划生成期间发生。 +`ExecutionStep` 验证确保只使用组+状态符合条件的工具。 +流程控制器在运行时强制执行工具可用性。 +状态转换由流程控制器在步骤之间管理。 + +### 5. 配置示例 + +#### 5.1 带有组和状态的工具配置 + +```yaml +tool: + knowledge-query: + type: knowledge-query + name: "Knowledge Graph Query" + description: "Query the knowledge graph for entities and relationships" + group: ["read-only", "knowledge", "basic"] + state: "analysis" + available_in_states: ["undefined", "research"] + + graph-update: + type: graph-update + name: "Graph Update" + description: "Add or modify entities in the knowledge graph" + group: ["write", "knowledge", "admin"] + available_in_states: ["analysis", "modification"] + + text-completion: + type: text-completion + name: "Text Completion" + description: "Generate text using language models" + group: ["read-only", "text", "basic"] + state: "undefined" + # No available_in_states = available in all states + + complex-analysis: + type: mcp-tool + name: "Complex Analysis Tool" + description: "Perform complex data analysis" + group: ["advanced", "compute", "expensive"] + state: "results" + available_in_states: ["analysis"] + mcp_tool_id: "analysis-server" + + reset-workflow: + type: mcp-tool + name: "Reset Workflow" + description: "Reset to initial state" + group: ["admin"] + state: "undefined" + available_in_states: ["analysis", "results"] +``` + +#### 5.2 请求示例与状态工作流 + +**初始研究请求:** +```json +{ + "question": "What entities are connected to Company X?", + "group": ["read-only", "knowledge"], + "state": "undefined" +} +``` +*可用工具:知识查询,文本补全* +*知识查询后:状态 → "分析"* + +**分析阶段:** +```json +{ + "question": "Continue analysis based on previous results", + "group": ["advanced", "compute", "write"], + "state": "analysis" +} +``` +*可用工具:复杂分析、图更新、重置工作流程* +*复杂分析之后:状态 → "结果"* + +**结果阶段:** +```json +{ + "question": "What should I do with these results?", + "group": ["admin"], + "state": "results" +} +``` +*可用的工具:仅限 reset-workflow* +*reset-workflow 之后:状态 → "undefined"* + +**工作流程示例 - 完整流程:** +1. **开始 (undefined)**:使用 knowledge-query → 转换到 "analysis" +2. **分析状态:** 使用 complex-analysis → 转换到 "results" +3. **结果状态:** 使用 reset-workflow → 转换回 "undefined" +4. **返回开始:** 所有初始工具再次可用 + +### 6. 安全注意事项 + +#### 6.1 访问控制集成 + +**网关级别的过滤:** +网关可以根据用户权限强制执行组限制 +防止通过请求修改来提升权限 +审计跟踪包括请求和授予的工具组 + +**示例网关逻辑:** +``` +user_permissions = get_user_permissions(request.user_id) +allowed_groups = user_permissions.tool_groups +requested_groups = request.group + +# Validate request doesn't exceed permissions +if not is_subset(requested_groups, allowed_groups): + reject_request("Insufficient permissions for requested tool groups") +``` + +#### 6.2 审计和监控 + +**增强的审计跟踪:** +记录每个请求所请求的工具组和初始状态 +跟踪按组成员划分的状态转换和工具使用情况 +监控未经授权的组访问尝试和无效的状态转换 +警报不寻常的组使用模式或可疑的状态工作流程 + +### 7. 迁移策略 + +#### 7.1 向后兼容性 + +**第一阶段:增量更改** +向工具配置添加可选的 `group` 字段 +向 AgentRequest 模式添加可选的 `group` 字段 +默认行为:所有现有工具都属于 "默认" 组 +现有请求如果没有组字段,则使用 "默认" 组 + +**保留现有行为:** +没有组配置的工具继续工作(默认组) +没有状态配置的工具在所有状态下都可用 +没有组指定的请求可以访问所有工具(默认组) +没有状态指定的请求使用 "未定义" 状态(所有工具可用) +没有对现有部署进行破坏性更改 + +### 8. 监控和可观察性 + +#### 8.1 新指标 + +**工具组使用情况:** +`agent_tool_group_requests_total` - 按组划分的请求计数器 +`agent_tool_group_availability` - 每个组可用的工具计量 +`agent_filtered_tools_count` - 组+状态过滤后工具计数的直方图 + +**状态工作流程指标:** +`agent_state_transitions_total` - 按工具划分的状态转换计数器 +`agent_workflow_duration_seconds` - 每个状态花费时间的直方图 +`agent_state_availability` - 每个状态可用的工具计量 + +**安全指标:** +`agent_group_access_denied_total` - 未经授权的组访问计数器 +`agent_invalid_state_transition_total` - 无效状态转换计数器 +`agent_privilege_escalation_attempts_total` - 具有可疑请求的计数器 + +#### 8.2 日志增强 + +**请求日志记录:** +```json +{ + "request_id": "req-123", + "requested_groups": ["read-only", "knowledge"], + "initial_state": "undefined", + "state_transitions": [ + {"tool": "knowledge-query", "from": "undefined", "to": "analysis", "timestamp": "2024-01-01T10:00:01Z"} + ], + "available_tools": ["knowledge-query", "text-completion"], + "filtered_by_group": ["graph-update", "admin-tool"], + "filtered_by_state": [], + "execution_time": "1.2s" +} +``` + +### 9. 测试策略 + +#### 9.1 单元测试 + +**工具过滤逻辑:** +测试组的交集计算 +测试基于状态的过滤逻辑 +验证默认组和状态的分配 +测试通配符组的行为 +验证空组的处理 +测试组合的组+状态过滤场景 + +**配置验证:** +测试使用各种组和状态配置加载工具 +验证无效的组和状态规范的模式验证 +测试与现有配置的向后兼容性 +验证状态转换的定义和循环 + +#### 9.2 集成测试 + +**代理行为:** +验证代理只看到组+状态过滤的工具 +测试使用各种组组合的请求执行 +测试代理执行期间的状态转换 +验证在没有可用工具时错误处理 +测试通过多个状态的工作流程进度 + +**安全测试:** +测试特权提升预防 +验证审计跟踪的准确性 +测试网关与用户权限的集成 + +#### 9.3 完整场景 + +**具有状态工作流程的多租户使用:** +``` +Scenario: Different users with different tool access and workflow states +Given: User A has "read-only" permissions, state "undefined" + And: User B has "write" permissions, state "analysis" +When: Both request knowledge operations +Then: User A gets read-only tools available in "undefined" state + And: User B gets write tools available in "analysis" state + And: State transitions are tracked per user session + And: All usage and transitions are properly audited +``` + +**工作流程状态演进:** +``` +Scenario: Complete workflow execution +Given: Request with groups ["knowledge", "compute"] and state "undefined" +When: Agent executes knowledge-query tool (transitions to "analysis") + And: Agent executes complex-analysis tool (transitions to "results") + And: Agent executes reset-workflow tool (transitions to "undefined") +Then: Each step has correctly filtered available tools + And: State transitions are logged with timestamps + And: Final state allows initial workflow to repeat +``` + +### 10. 性能考虑 + +#### 10.1 工具加载的影响 + +**配置加载:** +组和状态元数据在启动时加载一次 +每个工具的内存开销很小(附加字段) +不会影响工具的初始化时间 + +**请求处理:** +组+状态过滤的组合在每个请求中执行一次 +复杂度为 O(n),其中 n = 配置的工具数量 +状态转换会增加微小的开销(字符串赋值) +对于典型的工具数量(< 100),影响可以忽略不计 + +#### 10.2 优化策略 + +**预计算的工具集:** +根据组+状态组合缓存工具集 +避免重复过滤常见的组/状态模式 +内存与计算之间的权衡,适用于经常使用的组合 + +**延迟加载:** +仅在需要时才加载工具实现 +减少具有许多工具的部署的启动时间 +基于组需求的动态工具注册 + +### 11. 未来增强功能 + +#### 11.1 动态组分配 + +**基于上下文的组:** +根据请求上下文将工具分配到组 +基于时间的组可用性(仅在工作时间内) +基于负载的组限制(在低使用情况下限制昂贵的工具) + +#### 11.2 组层级结构 + +**嵌套的组结构:** +```json +{ + "knowledge": { + "read": ["knowledge-query", "entity-search"], + "write": ["graph-update", "entity-create"] + } +} +``` + +#### 11.3 工具推荐 + +**基于组的建议:** +针对请求类型,推荐最佳工具组。 +从使用模式中学习,以改进推荐。 +在首选工具不可用时,提供备用组。 + +### 12. 开放性问题 + +1. **组验证:** 请求中无效的组名是否应导致硬性错误或警告? + +2. **组发现:** 系统是否应提供一个 API 来列出可用的组及其工具? + +3. **动态组:** 组是否应在运行时配置,或者仅在启动时配置? + +4. **组继承:** 工具是否应从其父类别或实现继承组? + +5. **性能监控:** 需要哪些额外的指标来有效跟踪基于组的工具使用情况? + +### 13. 结论 + +工具组系统提供: + +**安全性:** 对代理功能进行细粒度的访问控制。 +**性能:** 减少工具加载和选择开销。 +**灵活性:** 多维工具分类。 +**兼容性:** 与现有代理架构无缝集成。 + +该系统使 TrustGraph 部署能够更好地管理工具访问,提高安全边界,并优化资源利用率,同时与现有的配置和请求完全兼容。 diff --git a/docs/tech-specs/tool-services.ar.md b/docs/tech-specs/tool-services.ar.md new file mode 100644 index 00000000..9fc5eb65 --- /dev/null +++ b/docs/tech-specs/tool-services.ar.md @@ -0,0 +1,479 @@ +--- +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. + +## الحالة + +تم التنفيذ + +## نظرة عامة + +تحدد هذه المواصفات آلية لأدوات وكيل قابلة للتوصيل ديناميكيًا تسمى "خدمات الأدوات". على عكس أنواع الأدوات المضمنة الحالية (`KnowledgeQueryImpl`، `McpToolImpl`، إلخ)، تسمح خدمات الأدوات بإدخال أدوات جديدة عن طريق: + +1. نشر خدمة جديدة تعتمد على Pulsar +2. إضافة وصف تهيئة يخبر الوكيل كيفية استدعائها + +يتيح ذلك إمكانية التوسع دون تعديل إطار عمل الاستجابة الأساسي للوكيل. + +## المصطلحات + +| المصطلح | التعريف | +|------|------------| +| **أداة مضمنة** | أنواع الأدوات الحالية مع تطبيقات مضمنة في `tools.py` | +| **خدمة أداة** | خدمة Pulsar التي يمكن استدعاؤها كأداة وكيل، ويتم تعريفها بواسطة وصف الخدمة | +| **أداة** | نسخة مُكوّنة تشير إلى خدمة أداة، وتُعرض للوكيل/نموذج اللغة الكبير | + +هذا نموذج من مستويين، مماثل لأدوات MCP: +MCP: يحدد خادم MCP واجهة الأداة → إعداد الأداة يشير إليها +خدمات الأدوات: تحدد خدمة الأداة واجهة Pulsar → إعداد الأداة يشير إليها + +## الخلفية: الأدوات الحالية + +### تنفيذ الأداة المضمنة + +يتم تعريف الأدوات حاليًا في `trustgraph-flow/trustgraph/agent/react/tools.py` مع تطبيقات مُصنّفة: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +كل نوع أداة: +لديه خدمة Pulsar مُبرمجة مسبقًا والتي يستدعيها (مثل: `graph-rag-request`) +يعرف بالضبط الطريقة التي يجب استدعاؤها على العميل (مثل: `client.rag()`) +لديه وسائط مُعرّفة من النوع في التنفيذ + +### تسجيل الأدوات (service.py:105-214) + +يتم تحميل الأدوات من ملف التكوين باستخدام حقل `type` والذي يربط بتنفيذ: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## العمارة + +### نموذج ذو طبقتين + +#### الطبقة الأولى: مُعرّف خدمة الأداة + +تحدد خدمة الأداة واجهة خدمة Pulsar. وهي تُعلن عن: +قوائم انتظار Pulsar للطلبات/الاستجابات +معلمات التكوين التي تتطلبها من الأدوات التي تستخدمها + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +خدمة أداة لا تتطلب أي معلمات تهيئة: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### المستوى الثاني: وصف الأداة + +تشير الأداة إلى خدمة الأداة وتوفر: +قيم معلمات التكوين (التي تلبي متطلبات الخدمة) +بيانات وصفية للأداة للوكيل (الاسم، الوصف) +تعريفات الوسائط لنموذج اللغة الكبيرة (LLM) + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +يمكن لأدوات متعددة الإشارة إلى نفس الخدمة بتكوينات مختلفة: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### تنسيق الطلب + +عندما يتم استدعاء أداة، يتضمن الطلب المرسل إلى خدمة الأداة ما يلي: +`user`: من طلب الوكيل (دعم تعدد المستأجرين) +`config`: قيم التكوين المشفرة بتنسيق JSON والمستمدة من وصف الأداة +`arguments`: وسائط مشفرة بتنسيق JSON والمستمدة من نموذج اللغة الكبير (LLM) + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +تتلقى خدمة الأداة هذه البيانات كقاموسات مُحللة في الطريقة `invoke`. + +### تطبيق عام لخدمة الأداة + +تستدعي فئة `ToolServiceImpl` خدمات الأداة بناءً على التكوين: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## قرارات التصميم + +### نموذج التكوين ثنائي الطبقات + +تتبع خدمات الأدوات نموذجًا ثنائي الطبقات مشابهًا لأدوات MCP: + +1. **خدمة الأداة**: تحدد واجهة خدمة Pulsar (الموضوع، ومعلمات التكوين المطلوبة). +2. **الأداة**: تشير إلى خدمة أداة، وتوفر قيم التكوين، وتحدد وسائط LLM. + +يسمح هذا الفصل بما يلي: +يمكن لخدمة أداة واحدة أن تستخدمها أدوات متعددة بتكوينات مختلفة. +تمييز واضح بين واجهة الخدمة وتكوين الأداة. +إمكانية إعادة استخدام تعريفات الخدمة. + +### تعيين الطلبات: تمرير مع الغلاف + +الطلب إلى خدمة الأداة هو غلاف منظم يحتوي على: +`user`: يتم تمريره من طلب الوكيل لخدمة العملاء المتعددة. +قيم التكوين: من وصف الأداة (مثل `collection`). +`arguments`: وسائط LLM، يتم تمريرها كقاموس. + +يقوم مدير الوكيل بتحليل استجابة LLM إلى `act.arguments` كقاموس (`agent_manager.py:117-154`). يتم تضمين هذا القاموس في غلاف الطلب. + +### معالجة المخططات: غير مُعَرَّفة الأنواع + +تستخدم الطلبات والاستجابات قواميس غير مُعَرَّفة الأنواع. لا يوجد تحقق من صحة المخطط على مستوى الوكيل - خدمة الأداة مسؤولة عن التحقق من صحة مدخلاتها. يوفر هذا أقصى قدر من المرونة لتعريف خدمات جديدة. + +### واجهة العميل: مواضيع Pulsar مباشرة + +تستخدم خدمات الأدوات مواضيع Pulsar مباشرة دون الحاجة إلى تكوين التدفق. يحدد وصف خدمة الأداة أسماء قائمة الانتظار الكاملة: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +هذا يسمح باستضافة الخدمات في أي مساحة اسم. + +### معالجة الأخطاء: الاصطلاح القياسي للأخطاء. + +تتبع استجابات خدمات الأدوات الاصطلاح الحالي للمخطط مع حقل `error`: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +هيكل الاستجابة: +النجاح: إذا كانت `error` تساوي `None`، تحتوي الاستجابة على النتيجة. +الخطأ: يتم ملء `error` بـ `type` و `message`. + +هذا يتوافق مع النمط المستخدم في مخططات الخدمة الحالية (مثل: `PromptResponse`، `QueryResponse`، `AgentResponse`). + +### الارتباط بين الطلبات والاستجابات + +يتم ربط الطلبات والاستجابات باستخدام `id` في خصائص رسائل Pulsar: + +يتضمن الطلب `id` في الخصائص: `properties={"id": id}`. +تتضمن الاستجابة (أو الاستجابات) نفس `id`: `properties={"id": id}`. + +هذا يتبع النمط الحالي المستخدم في قاعدة التعليمات البرمجية بأكملها (مثل: `agent_service.py`، `llm_service.py`). + +### دعم التدفق + +يمكن لخدمات الأدوات إرجاع استجابات متدفقة: + +رسائل استجابة متعددة بنفس `id` في الخصائص. +تتضمن كل استجابة حقل `end_of_stream: bool`. +تحتوي الاستجابة النهائية على `end_of_stream: True`. + +هذا يتوافق مع النمط المستخدم في `AgentResponse` وخدمات التدفق الأخرى. + +### معالجة الاستجابة: إرجاع سلسلة نصية + +تتبع جميع الأدوات الموجودة نفس النمط: **استقبال الوسائط كقاموس، وإرجاع الملاحظة كسلسلة نصية**. + +| الأداة | معالجة الاستجابة | +|------|------------------| +| `KnowledgeQueryImpl` | إرجاع `client.rag()` مباشرة (سلسلة نصية) | +| `TextCompletionImpl` | إرجاع `client.question()` مباشرة (سلسلة نصية) | +| `McpToolImpl` | إرجاع سلسلة نصية، أو `json.dumps(output)` إذا لم تكن سلسلة نصية | +| `StructuredQueryImpl` | تنسيق النتيجة إلى سلسلة نصية | +| `PromptImpl` | إرجاع `client.prompt()` مباشرة (سلسلة نصية) | + +تتبع خدمات الأدوات نفس العقد: +تقوم الخدمة بإرجاع استجابة سلسلة نصية (الملاحظة). +إذا لم تكن الاستجابة سلسلة نصية، يتم تحويلها عبر `json.dumps()`. +لا يلزم وجود تكوين استخراج في الوصف. + +هذا يبقي الوصف بسيطًا ويضع المسؤولية على الخدمة لإرجاع استجابة نصية مناسبة للوكيل. + +## دليل التكوين + +لإضافة خدمة أداة جديدة، يلزم وجود عنصرين في التكوين: + +### 1. تكوين خدمة الأداة + +يتم تخزينها تحت مفتاح التكوين `tool-service`. تحدد قوائم انتظار Pulsar والمعلمات التكوين المتاحة. + +| الحقل | مطلوب | الوصف | +|-------|----------|-------------| +| `id` | نعم | معرف فريد لخدمة الأداة | +| `request-queue` | نعم | موضوع Pulsar الكامل للطلبات (مثل: `non-persistent://tg/request/joke`) | +| `response-queue` | نعم | موضوع Pulsar الكامل للاستجابات (مثل: `non-persistent://tg/response/joke`) | +| `config-params` | لا | مصفوفة من معلمات التكوين التي تقبلها الخدمة | + +يمكن لكل معلمة تكوين تحديد: +`name`: اسم المعلمة (مطلوب) +`required`: ما إذا كان يجب توفير المعلمة بواسطة الأدوات (افتراضي: خطأ) + +مثال: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. إعدادات الأداة + +يتم تخزينها تحت مفتاح التكوين `tool`. تحدد أداة يمكن للوكيل استخدامها. + +| الحقل | مطلوب | الوصف | +|-------|----------|-------------| +| `type` | نعم | يجب أن يكون `"tool-service"` | +| `name` | نعم | اسم الأداة المعروضة لنظام LLM | +| `description` | نعم | وصف لما تفعله الأداة (يُعرض لنظام LLM) | +| `service` | نعم | معرف خدمة الأداة التي سيتم استدعاؤها | +| `arguments` | لا | مصفوفة من تعريفات الوسائط لنظام LLM | +| *(معلمات التكوين)* | يختلف | أي معلمات تكوين معرفة بواسطة الخدمة | + +يمكن لكل وسيط تحديد: +`name`: اسم الوسيط (مطلوب) +`type`: نوع البيانات، على سبيل المثال، `"string"` (مطلوب) +`description`: الوصف المعروض لنظام LLM (مطلوب) + +مثال: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### تحميل الإعدادات + +استخدم `tg-put-config-item` لتحميل الإعدادات: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +يجب إعادة تشغيل الوكيل الإداري لاستيعاب التكوينات الجديدة. + +## تفاصيل التنفيذ + +### المخطط + +أنواع الطلبات والاستجابات في `trustgraph-base/trustgraph/schema/services/tool_service.py`: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### الخادم: خدمة DynamicToolService + +الفئة الأساسية في `trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### جانب العميل: ToolServiceImpl + +التنفيذ في `trustgraph-flow/trustgraph/agent/react/tools.py`: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### الملفات + +| الملف | الغرض | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | مخططات الطلبات والاستجابات | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | عميل لاستدعاء الخدمات | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | الفئة الأساسية لتنفيذ الخدمة | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | فئة `ToolServiceImpl` | +| `trustgraph-flow/trustgraph/agent/react/service.py` | تحميل التكوين | + +### مثال: خدمة النكت + +مثال لخدمة في `trustgraph-flow/trustgraph/tool_service/joke/`: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +تكوين خدمة الأداة: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +إعدادات الأداة: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### التوافق مع الإصدارات السابقة + +تظل أنواع الأدوات المدمجة الحالية تعمل دون تغيير. +`tool-service` هو نوع أداة جديد بالإضافة إلى الأنواع الموجودة (`knowledge-query`، `mcp-tool`، إلخ). + +## اعتبارات مستقبلية + +### الخدمات ذات الإعلان الذاتي + +يمكن أن تسمح ترقية مستقبلية للخدمات بنشر أوصافها الخاصة: + +تنشر الخدمات إلى موضوع `tool-descriptors` معروف عند بدء التشغيل. +يشترك الوكيل ويسجل الأدوات ديناميكيًا. +يتيح ذلك إمكانية التوصيل والتشغيل الحقيقية دون تغييرات في التكوين. + +هذا خارج نطاق التنفيذ الأولي. + +## المراجع + +التنفيذ الحالي للأداة: `trustgraph-flow/trustgraph/agent/react/tools.py` +تسجيل الأداة: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +مخططات الوكيل: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.es.md b/docs/tech-specs/tool-services.es.md new file mode 100644 index 00000000..6b2ca666 --- /dev/null +++ b/docs/tech-specs/tool-services.es.md @@ -0,0 +1,479 @@ +--- +layout: default +title: "Servicios de Herramientas: Herramientas de Agente Dinámicamente Conectables" +parent: "Spanish (Beta)" +--- + +# Servicios de Herramientas: Herramientas de Agente Dinámicamente Conectables + +> **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 + +Implementado + +## Resumen + +Esta especificación define un mecanismo para herramientas de agente dinámicamente conectables llamadas "servicios de herramientas". A diferencia de los tipos de herramientas integradas existentes (`KnowledgeQueryImpl`, `McpToolImpl`, etc.), los servicios de herramientas permiten introducir nuevas herramientas mediante: + +1. Desplegar un nuevo servicio basado en Pulsar +2. Agregar un descriptor de configuración que le indique al agente cómo invocarlo + +Esto permite la extensibilidad sin modificar el marco de respuesta del agente principal. + +## Terminología + +| Término | Definición | +|------|------------| +| **Herramienta Integrada** | Tipos de herramientas existentes con implementaciones codificadas en `tools.py` | +| **Servicio de Herramienta** | Un servicio de Pulsar que se puede invocar como una herramienta de agente, definido por un descriptor de servicio | +| **Herramienta** | Una instancia configurada que hace referencia a un servicio de herramienta, expuesta al agente/LLM | + +Este es un modelo de dos niveles, análogo a las herramientas MCP: +MCP: El servidor MCP define la interfaz de la herramienta → La configuración de la herramienta la referencia +Servicios de Herramienta: El servicio de herramienta define la interfaz de Pulsar → La configuración de la herramienta la referencia + +## Antecedentes: Herramientas Existentes + +### Implementación de Herramienta Integrada + +Las herramientas se definen actualmente en `trustgraph-flow/trustgraph/agent/react/tools.py` con implementaciones tipadas: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +Cada tipo de herramienta: +Tiene un servicio Pulsar predefinido al que llama (por ejemplo, `graph-rag-request`) +Conoce el método exacto para llamar al cliente (por ejemplo, `client.rag()`) +Tiene argumentos tipados definidos en la implementación + +### Registro de herramientas (service.py:105-214) + +Las herramientas se cargan desde la configuración con un campo `type` que se mapea a una implementación: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## Arquitectura + +### Modelo de Dos Capas + +#### Capa 1: Descriptor del Servicio de Herramienta + +Un servicio de herramienta define una interfaz de servicio de Pulsar. Declara: +Las colas de Pulsar para solicitud/respuesta +Los parámetros de configuración que requiere de las herramientas que lo utilizan + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +Un servicio de herramienta que no necesita parámetros de configuración: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### Nivel 2: Descriptor de la herramienta + +Una herramienta hace referencia a un servicio de herramienta y proporciona: +Valores de parámetros de configuración (que satisfacen los requisitos del servicio) +Metadatos de la herramienta para el agente (nombre, descripción) +Definiciones de argumentos para el LLM + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +Múltiples herramientas pueden referenciar el mismo servicio con diferentes configuraciones: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### Formato de solicitud + +Cuando se invoca una herramienta, la solicitud al servicio de la herramienta incluye: +`user`: Desde la solicitud del agente (multitenencia) +`config`: Valores de configuración codificados en JSON provenientes de la descripción de la herramienta +`arguments`: Argumentos codificados en JSON provenientes del LLM + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +El servicio de herramientas recibe esto como diccionarios analizados en el método `invoke`. + +### Implementación Genérica del Servicio de Herramientas + +Una clase `ToolServiceImpl` invoca servicios de herramientas basándose en la configuración: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## Decisiones de Diseño + +### Modelo de Configuración de Dos Niveles + +Los servicios de herramientas siguen un modelo de dos niveles similar a las herramientas de MCP: + +1. **Servicio de Herramienta**: Define la interfaz del servicio de Pulsar (tema, parámetros de configuración requeridos) +2. **Herramienta**: Hace referencia a un servicio de herramienta, proporciona valores de configuración, define argumentos de LLM + +Esta separación permite: +Que un servicio de herramienta sea utilizado por múltiples herramientas con diferentes configuraciones +Una distinción clara entre la interfaz del servicio y la configuración de la herramienta +La reutilización de las definiciones de servicio + +### Mapeo de Solicitudes: Transmisión con Sobre + +La solicitud a un servicio de herramienta es un sobre estructurado que contiene: +`user`: Propagado desde la solicitud del agente para la multi-inquilinato +Valores de configuración: Del descriptor de la herramienta (por ejemplo, `collection`) +`arguments`: Argumentos proporcionados por el LLM, transmitidos como un diccionario + +El administrador del agente analiza la respuesta del LLM en `act.arguments` como un diccionario (`agent_manager.py:117-154`). Este diccionario se incluye en el sobre de la solicitud. + +### Manejo de Esquemas: No Tipado + +Las solicitudes y las respuestas utilizan diccionarios no tipados. No hay validación de esquema a nivel del agente; el servicio de herramienta es responsable de validar sus entradas. Esto proporciona la máxima flexibilidad para definir nuevos servicios. + +### Interfaz de Cliente: Temas Directos de Pulsar + +Los servicios de herramientas utilizan temas directos de Pulsar sin requerir configuración de flujo. El descriptor del servicio de herramienta especifica los nombres completos de las colas: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +Esto permite que los servicios se alojen en cualquier espacio de nombres. + +### Manejo de errores: Convención de error estándar + +Las respuestas del servicio de herramientas siguen la convención de esquema existente con un campo `error`: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +Estructura de la respuesta: +Éxito: `error` es `None`, la respuesta contiene el resultado +Error: `error` se completa con `type` y `message` + +Esto coincide con el patrón utilizado en todo el esquema de servicios existente (por ejemplo, `PromptResponse`, `QueryResponse`, `AgentResponse`). + +### Correlación de solicitudes/respuestas + +Las solicitudes y las respuestas se correlacionan mediante un `id` en las propiedades del mensaje de Pulsar: + +La solicitud incluye `id` en las propiedades: `properties={"id": id}` +La(s) respuesta(s) incluyen el mismo `id`: `properties={"id": id}` + +Esto sigue el patrón existente utilizado en todo el código base (por ejemplo, `agent_service.py`, `llm_service.py`). + +### Soporte de transmisión + +Los servicios de herramientas pueden devolver respuestas de transmisión: + +Múltiples mensajes de respuesta con el mismo `id` en las propiedades +Cada respuesta incluye el campo `end_of_stream: bool` +La respuesta final tiene `end_of_stream: True` + +Esto coincide con el patrón utilizado en `AgentResponse` y otros servicios de transmisión. + +### Manejo de la respuesta: retorno de cadena + +Todas las herramientas existentes siguen el mismo patrón: **recibir argumentos como un diccionario, devolver la observación como una cadena**. + +| Herramienta | Manejo de la respuesta | +|------|------------------| +| `KnowledgeQueryImpl` | Devuelve `client.rag()` directamente (cadena) | +| `TextCompletionImpl` | Devuelve `client.question()` directamente (cadena) | +| `McpToolImpl` | Devuelve una cadena, o `json.dumps(output)` si no es una cadena | +| `StructuredQueryImpl` | Formatea el resultado a una cadena | +| `PromptImpl` | Devuelve `client.prompt()` directamente (cadena) | + +Los servicios de herramientas siguen el mismo contrato: +El servicio devuelve una respuesta de cadena (la observación) +Si la respuesta no es una cadena, se convierte mediante `json.dumps()` +No se necesita ninguna configuración de extracción en el descriptor + +Esto mantiene el descriptor simple y delega la responsabilidad de devolver una respuesta de texto adecuada al agente en el servicio. + +## Guía de configuración + +Para agregar un nuevo servicio de herramientas, se requieren dos elementos de configuración: + +### 1. Configuración del servicio de herramientas + +Se almacena bajo la clave de configuración `tool-service`. Define las colas de Pulsar y los parámetros de configuración disponibles. + +| Campo | Requerido | Descripción | +|-------|----------|-------------| +| `id` | Sí | Identificador único para el servicio de herramientas | +| `request-queue` | Sí | Tema de Pulsar completo para las solicitudes (por ejemplo, `non-persistent://tg/request/joke`) | +| `response-queue` | Sí | Tema de Pulsar completo para las respuestas (por ejemplo, `non-persistent://tg/response/joke`) | +| `config-params` | No | Matriz de parámetros de configuración que el servicio acepta | + +Cada parámetro de configuración puede especificar: +`name`: Nombre del parámetro (obligatorio) +`required`: Si el parámetro debe ser proporcionado por las herramientas (por defecto: falso) + +Ejemplo: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. Configuración de la herramienta + +Almacenado bajo la clave de configuración `tool`. Define una herramienta que el agente puede utilizar. + +| Campo | Requerido | Descripción | +|-------|----------|-------------| +| `type` | Sí | Debe ser `"tool-service"` | +| `name` | Sí | Nombre de la herramienta expuesto al LLM | +| `description` | Sí | Descripción de lo que hace la herramienta (mostrada al LLM) | +| `service` | Sí | ID del servicio de herramientas a invocar | +| `arguments` | No | Matriz de definiciones de argumentos para el LLM | +| *(parámetros de configuración)* | Varía | Cualquier parámetro de configuración definido por el servicio | + +Cada argumento puede especificar: +`name`: Nombre del argumento (requerido) +`type`: Tipo de datos, por ejemplo, `"string"` (requerido) +`description`: Descripción mostrada al LLM (requerido) + +Ejemplo: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### Carga de la configuración + +Utilice `tg-put-config-item` para cargar configuraciones: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +El agente-administrador debe reiniciarse para cargar nuevas configuraciones. + +## Detalles de implementación + +### Esquema + +Tipos de solicitud y respuesta en `trustgraph-base/trustgraph/schema/services/tool_service.py`: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### Servidor: Servicio DynamicToolService + +Clase base en `trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### Cliente: ToolServiceImpl + +Implementación en `trustgraph-flow/trustgraph/agent/react/tools.py`: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### Archivos + +| Archivo | Propósito | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | Esquemas de solicitud/respuesta | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | Cliente para invocar servicios | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | Clase base para la implementación de servicios | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | Clase `ToolServiceImpl` | +| `trustgraph-flow/trustgraph/agent/react/service.py` | Carga de configuración | + +### Ejemplo: Servicio de Chistes + +Un ejemplo de servicio en `trustgraph-flow/trustgraph/tool_service/joke/`: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +Configuración del servicio de herramientas: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +Configuración de la herramienta: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### Compatibilidad hacia atrás + +Los tipos de herramientas integradas existentes continúan funcionando sin cambios. +`tool-service` es un nuevo tipo de herramienta, además de los tipos existentes (`knowledge-query`, `mcp-tool`, etc.). + +## Consideraciones futuras + +### Servicios de autoanuncio + +Una mejora futura podría permitir que los servicios publiquen sus propios descriptores: + +Los servicios publican en un tema `tool-descriptors` conocido al inicio. +El agente se suscribe y registra dinámicamente las herramientas. +Permite una verdadera funcionalidad de conexión y uso sin cambios de configuración. + +Esto está fuera del alcance de la implementación inicial. + +## Referencias + +Implementación actual de la herramienta: `trustgraph-flow/trustgraph/agent/react/tools.py` +Registro de herramientas: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +Esquemas del agente: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.he.md b/docs/tech-specs/tool-services.he.md new file mode 100644 index 00000000..1db6f01b --- /dev/null +++ b/docs/tech-specs/tool-services.he.md @@ -0,0 +1,479 @@ +--- +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. + +## סטטוס + +מיושם + +## סקירה כללית + +מפרט זה מגדיר מנגנון לכלים דינמיים הניתנים לחיבור הנקראים "שירותי כלים". בניגוד לסוגי הכלים המובנים הקיימים (`KnowledgeQueryImpl`, `McpToolImpl`, וכו'), שירותי כלים מאפשרים להציג כלים חדשים על ידי: + +1. פריסת שירות חדש המבוסס על Pulsar +2. הוספת תיאור תצורה המציין לסוכן כיצד להפעיל אותו + +זה מאפשר הרחבה מבלי לשנות את מסגרת התגובה הבסיסית של הסוכן. + +## מונחים + +| מונח | הגדרה | +|------|------------| +| **כלי מובנה** | סוגי כלים קיימים עם יישומים מוגדרים מראש ב-`tools.py` | +| **שירות כלי** | שירות Pulsar שניתן להפעיל ככלי סוכן, המוגדר על ידי תיאור שירות | +| **כלי** | מופע מוגדר המתייחס לשירות כלי, החשוף לסוכן/LLM | + +זהו מודל דו-שכבתי, אנלוגי לכלי MCP: +MCP: שרת MCP מגדיר את ממשק הכלי → תצורת הכלי מתייחסת אליו +שירותי כלים: שירות הכלי מגדיר את ממשק Pulsar → תצורת הכלי מתייחסת אליו + +## רקע: כלים קיימים + +### יישום כלי מובנה + +כלי מוגדרים כיום ב-`trustgraph-flow/trustgraph/agent/react/tools.py` עם יישומים מטיפוסים: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +כל סוג כלי: +כולל שירות Pulsar מובנה שהוא קורא אליו (לדוגמה: `graph-rag-request`) +יודע בדיוק את השיטה לקריאה בלקוח (לדוגמה: `client.rag()`) +מכיל ארגומנטים מוגדרים בסביבת היישום + +### רישום כלים (service.py:105-214) + +כלים נטענים מקובץ תצורה עם שדה `type` שממפה ליישום: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## ארכיטקטורה + +### מודל דו-שכבתי + +#### שכבה 1: תיאור שירות כלי + +שירות כלי מגדיר ממשק שירות של פולסר. הוא מכריז על: +תורי הפולסר עבור בקשות/תגובות +פרמטרי תצורה שהוא דורש מכלי המשתמשים בו + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +שירות כלי שאינו דורש פרמטרים של תצורה: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### שכבה 2: תיאור כלי + +כלי מפנה לשירות כלי ומספק: +ערכי פרמטרים של תצורה (העונים על דרישות השירות) +מטא-נתונים של הכלי עבור הסוכן (שם, תיאור) +הגדרות ארגומנטים עבור מודל השפה הגדול (LLM) + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +מספר כלים יכולים להתייחס לאותה שירות עם תצורות שונות: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### פורמט בקשה + +כאשר כלי מופעל, הבקשה לשירות הכלי כוללת: +`user`: מהבקשה של הסוכן (ריבוי דיירים) +`config`: ערכי תצורה מקודדים ב-JSON מהתיאור של הכלי +`arguments`: ארגומנטים מקודדים ב-JSON מהמודל הלשוני הגדול (LLM) + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +השירות של הכלי מקבל זאת כ-dicts שעברו ניתוח בשיטה `invoke`. + +### יישום כללי של שירות הכלי + +מחלקה `ToolServiceImpl` מפעילה שירותי כלי בהתבסס על תצורה: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## החלטות עיצוב + +### מודל תצורה דו-שכבתי + +שירותי כלים פועלים לפי מודל דו-שכבתי הדומה לכלי MCP: + +1. **שירות כלי**: מגדיר את ממשק השירות של Pulsar (נושא, פרמטרי תצורה נדרשים) +2. **כלי**: מפנה לשירות כלי, מספק ערכי תצורה, מגדיר ארגומנטים של LLM + +הפרדה זו מאפשרת: +שירות כלי אחד יכול לשמש מספר כלים עם תצורות שונות +הבחנה ברורה בין ממשק השירות לתצורת הכלי +שימוש חוזר בהגדרות שירות + +### מיפוי בקשות: העברה עם מעטפה + +הבקשה לשירות כלי היא מעטפה מובנית המכילה: +`user`: מועבר מבקשת הסוכן עבור ריבוי דיירים +ערכי תצורה: מתיאור הכלי (לדוגמה, `collection`) +`arguments`: ארגומנטים המסופקים על ידי LLM, מועברים כמילון + +מנהל הסוכן מנתח את התגובה של ה-LLM ל-`act.arguments` כמילון (`agent_manager.py:117-154`). מילון זה כלול במעטפת הבקשה. + +### טיפול בסכימה: לא מסווג + +בקשות ותגובות משתמשות במילונים לא מסווגים. אין אימות סכימה ברמת הסוכן - שירות הכלי אחראי לאימות הקלט שלו. זה מספק גמישות מרבית בהגדרת שירותים חדשים. + +### ממשק לקוח: נושאים ישירים של Pulsar + +שירותי כלים משתמשים בנושאים ישירים של Pulsar מבלי לדרוש תצורת זרימה. תיאור שירות הכלי מציין את שמות התורים המלאים: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +זה מאפשר לארח שירותים בכל מרחב שם. + +### טיפול בשגיאות: מוסכמות שגיאות סטנדרטיות + +תגובות של שירותי כלים עוקבות אחר מוסכמות הסכימה הקיימות עם שדה `error`: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +מבנה תגובה: +הצלחה: `error` הוא `None`, התגובה מכילה תוצאה +שגיאה: `error` מאוכלס עם `type` ו- `message` + +זה תואם לדפוס המשמש בכל סכימות השירות הקיימות (לדוגמה, `PromptResponse`, `QueryResponse`, `AgentResponse`). + +### התאמה בין בקשה לתגובה + +בקשות ותגובות משויכות באמצעות `id` במאפייני הודעות Pulsar: + +בקשה כוללת `id` במאפיינים: `properties={"id": id}` +התגובות כוללות את אותו `id`: `properties={"id": id}` + +זה עוקב אחר הדפוס הקיים המשמש בכל בסיס הקוד (לדוגמה, `agent_service.py`, `llm_service.py`). + +### תמיכה בסטרימינג + +שירותי כלים יכולים להחזיר תגובות בסטרימינג: + +הודעות תגובה מרובות עם אותו `id` במאפיינים +כל תגובה כוללת את השדה `end_of_stream: bool` +התגובה הסופית כוללת את `end_of_stream: True` + +זה תואם לדפוס המשמש ב- `AgentResponse` ובשירותי סטרימינג אחרים. + +### טיפול בתגובה: החזרת מחרוזת + +כל הכלים הקיימים עוקבים אחר אותו דפוס: **קבלת ארגומנטים כמילון, החזרת התצפית כמחרוזת**. + +| כלי | טיפול בתגובה | +|------|------------------| +| `KnowledgeQueryImpl` | מחזיר את `client.rag()` ישירות (מחרוזת) | +| `TextCompletionImpl` | מחזיר את `client.question()` ישירות (מחרוזת) | +| `McpToolImpl` | מחזיר מחרוזת, או `json.dumps(output)` אם אינה מחרוזת | +| `StructuredQueryImpl` | מעצב את התוצאה למחרוזת | +| `PromptImpl` | מחזיר את `client.prompt()` ישירות (מחרוזת) | + +שירותי כלים עוקבים אחר אותו חוזה: +השירות מחזיר תגובת מחרוזת (התצפית) +אם התגובה אינה מחרוזת, היא מומרת באמצעות `json.dumps()` +אין צורך בתצורת חילוץ במגדיר + +זה שומר על המגדיר פשוט ומעביר את האחריות לשירות להחזיר תגובת טקסט מתאימה עבור הסוכן. + +## מדריך תצורה + +כדי להוסיף שירות כלי חדש, נדרשים שני פריטי תצורה: + +### 1. תצורת שירות כלי + +מאוחסן תחת מפתח התצורה `tool-service`. מגדיר את תורי Pulsar ואת פרמטרי התצורה הזמינים. + +| שדה | נדרש | תיאור | +|-------|----------|-------------| +| `id` | כן | מזהה ייחודי עבור שירות הכלי | +| `request-queue` | כן | נושא Pulsar מלא עבור בקשות (לדוגמה, `non-persistent://tg/request/joke`) | +| `response-queue` | כן | נושא Pulsar מלא עבור תגובות (לדוגמה, `non-persistent://tg/response/joke`) | +| `config-params` | לא | מערך של פרמטרי תצורה שהשירות מקבל | + +ניתן לציין כל פרמטר תצורה: +`name`: שם הפרמטר (נדרש) +`required`: האם הפרמטר חייב להיות מסופק על ידי כלים (ברירת מחדל: false) + +דוגמה: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. תצורת כלי + +שמור תחת מפתח התצורה `tool`. מגדיר כלי שהסוכן יכול להשתמש בו. + +| שדה | נדרש | תיאור | +|-------|----------|-------------| +| `type` | כן | חייב להיות `"tool-service"` | +| `name` | כן | שם הכלי החשוף ל-LLM | +| `description` | כן | תיאור של מה הכלי עושה (מוצג ל-LLM) | +| `service` | כן | מזהה של שירות הכלי לביצוע | +| `arguments` | לא | מערך של הגדרות ארגומנטים עבור ה-LLM | +| *(פרמטרי תצורה)* | משתנה | כל פרמטרי תצורה המוגדרים על ידי השירות | + +כל ארגומנט יכול לציין: +`name`: שם הארגומנט (נדרש) +`type`: סוג נתונים, לדוגמה, `"string"` (נדרש) +`description`: תיאור המוצג ל-LLM (נדרש) + +דוגמה: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### טעינת הגדרות + +השתמשו ב-`tg-put-config-item` כדי לטעון הגדרות: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +יש להפעיל מחדש את מנהל הסוכן כדי לקלוט הגדרות חדשות. + +## פרטי יישום + +### סכימה + +סוגי בקשות ותגובות ב-`trustgraph-base/trustgraph/schema/services/tool_service.py`: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### צד שרת: DynamicToolService + +מחלקה בסיסית ב-`trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### צד לקוח: ToolServiceImpl + +יישום ב-`trustgraph-flow/trustgraph/agent/react/tools.py`: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### קבצים + +| קובץ | מטרה | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | סכימות בקשה/תגובה | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | לקוח להפעלת שירותים | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | מחלקה בסיסית ליישום שירות | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | מחלקה `ToolServiceImpl` | +| `trustgraph-flow/trustgraph/agent/react/service.py` | טעינת תצורה | + +### דוגמה: שירות בדיחות + +דוגמה לשירות ב-`trustgraph-flow/trustgraph/tool_service/joke/`: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +תצורת שירות הכלי: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +הגדרות כלי: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### תאימות לאחור + +סוגי כלים מובנים קיימים ממשיכים לעבוד ללא שינוי. +`tool-service` הוא סוג כלי חדש לצד סוגים קיימים (`knowledge-query`, `mcp-tool`, וכו'). + +## שיקולים עתידיים + +### שירותים המצהירים על עצמם + +שיפור עתידי יכול לאפשר לשירותים לפרסם את התיאורים שלהם: + +שירותים מפרסמים לנושא `tool-descriptors` ידוע בעת ההפעלה. +הסוכן נרשם ורושם כלים באופן דינמי. +מאפשר חיבור והפעלה אמיתיים ללא שינויי תצורה. + +זה מחוץ לתחום של המימוש הראשוני. + +## הפניות + +יישום כלי נוכחי: `trustgraph-flow/trustgraph/agent/react/tools.py` +רישום כלים: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +סכימות סוכן: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.hi.md b/docs/tech-specs/tool-services.hi.md new file mode 100644 index 00000000..50559560 --- /dev/null +++ b/docs/tech-specs/tool-services.hi.md @@ -0,0 +1,479 @@ +--- +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. + +## स्थिति + +कार्यान्वित + +## अवलोकन + +यह विनिर्देश "टूल सेवाओं" नामक गतिशील रूप से प्लगेबल एजेंट टूल के लिए एक तंत्र को परिभाषित करता है। मौजूदा अंतर्निहित टूल प्रकारों (`KnowledgeQueryImpl`, `McpToolImpl`, आदि) के विपरीत, टूल सेवाएं नए टूल को इस प्रकार पेश करने की अनुमति देती हैं: + +1. एक नई पल्सर-आधारित सेवा को तैनात करना +2. एक कॉन्फ़िगरेशन विवरण जोड़ना जो एजेंट को बताता है कि इसे कैसे कॉल करना है + +यह मुख्य एजेंट-रिएक्ट फ्रेमवर्क को संशोधित किए बिना विस्तारशीलता को सक्षम बनाता है। + +## शब्दावली + +| शब्द | परिभाषा | +|------|------------| +| **अंतर्निहित टूल** | `tools.py` में हार्डकोडेड कार्यान्वयन वाले मौजूदा टूल प्रकार +| **टूल सेवा** | एक पल्सर सेवा जिसे एजेंट टूल के रूप में कॉल किया जा सकता है, जिसे एक सेवा विवरण द्वारा परिभाषित किया गया है +| **टूल** | एक कॉन्फ़िगर किया गया उदाहरण जो एक टूल सेवा को संदर्भित करता है, जो एजेंट/एलएलएम को उजागर किया जाता है + +यह एक दो-स्तरीय मॉडल है, जो एमसीपी टूल के समान है: +एमसीपी: एमसीपी सर्वर टूल इंटरफ़ेस को परिभाषित करता है → टूल कॉन्फ़िगरेशन इसका संदर्भ देता है +टूल सेवाएं: टूल सेवा पल्सर इंटरफ़ेस को परिभाषित करती है → टूल कॉन्फ़िगरेशन इसका संदर्भ देता है + +## पृष्ठभूमि: मौजूदा टूल + +### अंतर्निहित टूल कार्यान्वयन + +टूल वर्तमान में `trustgraph-flow/trustgraph/agent/react/tools.py` में टाइप किए गए कार्यान्वयन के साथ परिभाषित किए गए हैं: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +प्रत्येक उपकरण प्रकार: +में एक हार्डकोडेड पल्सर सेवा होती है जिसे वह कॉल करता है (उदाहरण के लिए, `graph-rag-request`) +वह क्लाइंट पर कॉल करने के लिए सटीक विधि जानता है (उदाहरण के लिए, `client.rag()`) +इसमें कार्यान्वयन में परिभाषित टाइप किए गए तर्क होते हैं + +### उपकरण पंजीकरण (service.py:105-214) + +उपकरण कॉन्फ़िगरेशन से लोड किए जाते हैं जिसमें एक `type` फ़ील्ड होता है जो एक कार्यान्वयन से मेल खाता है: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## आर्किटेक्चर + +### दो-स्तरीय मॉडल + +#### स्तर 1: टूल सर्विस डिस्क्रिप्टर + +एक टूल सर्विस, पल्सर सर्विस इंटरफेस को परिभाषित करता है। यह निम्नलिखित घोषित करता है: +अनुरोध/प्रतिक्रिया के लिए पल्सर क्यू +उन कॉन्फ़िगरेशन पैरामीटर जिन्हें इसका उपयोग करने वाले टूल से इसकी आवश्यकता होती है + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +एक उपकरण सेवा जिसे किसी भी कॉन्फ़िगरेशन पैरामीटर की आवश्यकता नहीं है: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### स्तर 2: टूल विवरणिका + +एक टूल एक टूल सेवा को संदर्भित करता है और निम्नलिखित प्रदान करता है: +कॉन्फ़िगरेशन पैरामीटर मान (सेवा की आवश्यकताओं को पूरा करते हुए) +एजेंट के लिए टूल मेटाडेटा (नाम, विवरण) +एलएलएम के लिए तर्क परिभाषाएँ + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +कई उपकरण एक ही सेवा को विभिन्न कॉन्फ़िगरेशन के साथ संदर्भित कर सकते हैं: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### अनुरोध प्रारूप + +जब कोई टूल सक्रिय किया जाता है, तो टूल सेवा को भेजा गया अनुरोध में शामिल होता है: +`user`: एजेंट अनुरोध से (मल्टी-टेनेंसी) +`config`: टूल विवरणिका से JSON-एन्कोडेड कॉन्फ़िगरेशन मान +`arguments`: LLM से JSON-एन्कोडेड तर्क + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +टूल सर्विस इन डेटा को पार्स किए गए डिक्शनरी के रूप में `invoke` मेथड में प्राप्त करती है। + +### सामान्य टूल सर्विस कार्यान्वयन + +एक `ToolServiceImpl` क्लास कॉन्फ़िगरेशन के आधार पर टूल सेवाओं को लागू करता है: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## डिज़ाइन निर्णय + +### दो-स्तरीय कॉन्फ़िगरेशन मॉडल + +टूल सेवाएं एमसीपी टूल के समान एक दो-स्तरीय मॉडल का पालन करती हैं: + +1. **टूल सेवा**: पल्सर सेवा इंटरफ़ेस को परिभाषित करती है (विषय, आवश्यक कॉन्फ़िगरेशन पैरामीटर) +2. **टूल**: एक टूल सेवा को संदर्भित करता है, कॉन्फ़िगरेशन मान प्रदान करता है, एलएलएम तर्क को परिभाषित करता है + +यह अलगाव अनुमति देता है: +एक टूल सेवा का उपयोग विभिन्न कॉन्फ़िगरेशन वाले कई टूल द्वारा किया जा सकता है +सेवा इंटरफ़ेस और टूल कॉन्फ़िगरेशन के बीच स्पष्ट अंतर +सेवा परिभाषाओं का पुन: उपयोग + +### अनुरोध मैपिंग: एन्वेलप के साथ पास-थ्रू + +एक टूल सेवा के लिए अनुरोध एक संरचित एन्वेलप होता है जिसमें शामिल हैं: +`user`: मल्टी-टेनेंसी के लिए एजेंट अनुरोध से प्रचारित +कॉन्फ़िगरेशन मान: टूल विवरणिका से (उदाहरण के लिए, `collection`) +`arguments`: एलएलएम-प्रदत्त तर्क, एक डिक्ट के रूप में पास किए जाते हैं + +एजेंट प्रबंधक एलएलएम की प्रतिक्रिया को `act.arguments` के रूप में एक डिक्ट (`agent_manager.py:117-154`) में पार्स करता है। यह डिक्ट अनुरोध एन्वेलप में शामिल है। + +### स्कीमा हैंडलिंग: अनटाइप्ड + +अनुरोध और प्रतिक्रियाएं अनटाइप्ड डिक्ट का उपयोग करती हैं। एजेंट स्तर पर कोई स्कीमा सत्यापन नहीं होता है - टूल सेवा अपने इनपुट को मान्य करने के लिए जिम्मेदार है। यह नई सेवाओं को परिभाषित करने के लिए अधिकतम लचीलापन प्रदान करता है। + +### क्लाइंट इंटरफ़ेस: डायरेक्ट पल्सर टॉपिक + +टूल सेवाएं प्रवाह कॉन्फ़िगरेशन की आवश्यकता के बिना डायरेक्ट पल्सर टॉपिक का उपयोग करती हैं। टूल-सेवा विवरणिका पूर्ण कतार नामों को निर्दिष्ट करती है: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +यह सेवाओं को किसी भी नेमस्पेस में होस्ट करने की अनुमति देता है। + +### त्रुटि प्रबंधन: मानक त्रुटि सम्मेलन + +टूल सेवा प्रतिक्रियाएं मौजूदा स्कीमा सम्मेलन का पालन करती हैं, जिसमें एक `error` फ़ील्ड है: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +प्रतिक्रिया संरचना: +सफलता: `error` का मान `None` है, प्रतिक्रिया में परिणाम शामिल है +त्रुटि: `error` को `type` और `message` के मानों के साथ भरा जाता है + +यह मौजूदा सेवा स्कीमा में उपयोग किए गए पैटर्न से मेल खाता है (उदाहरण के लिए, `PromptResponse`, `QueryResponse`, `AgentResponse`)। + +### अनुरोध/प्रतिक्रिया सहसंबंध + +अनुरोधों और प्रतिक्रियाओं को पल्सर संदेश गुणों में एक `id` का उपयोग करके सहसंबंधित किया जाता है: + +अनुरोध में गुणों में `id` शामिल है: `properties={"id": id}` +प्रतिक्रिया(ओं) में समान `id` शामिल है: `properties={"id": id}` + +यह पूरे कोडबेस में उपयोग किए गए मौजूदा पैटर्न का अनुसरण करता है (उदाहरण के लिए, `agent_service.py`, `llm_service.py`)। + +### स्ट्रीमिंग समर्थन + +टूल सेवाएं स्ट्रीमिंग प्रतिक्रियाएं वापस कर सकती हैं: + +समान `id` वाले कई प्रतिक्रिया संदेश +प्रत्येक प्रतिक्रिया में `end_of_stream: bool` फ़ील्ड शामिल है +अंतिम प्रतिक्रिया में `end_of_stream: True` है + +यह `AgentResponse` और अन्य स्ट्रीमिंग सेवाओं में उपयोग किए गए पैटर्न से मेल खाता है। + +### प्रतिक्रिया हैंडलिंग: स्ट्रिंग रिटर्न + +सभी मौजूदा टूल समान पैटर्न का पालन करते हैं: **तर्कों को एक डिक्ट के रूप में प्राप्त करें, अवलोकन को एक स्ट्रिंग के रूप में वापस करें।** + +| टूल | प्रतिक्रिया हैंडलिंग | +|------|------------------| +| `KnowledgeQueryImpl` | `client.rag()` को सीधे वापस करता है (स्ट्रिंग) | +| `TextCompletionImpl` | `client.question()` को सीधे वापस करता है (स्ट्रिंग) | +| `McpToolImpl` | एक स्ट्रिंग वापस करता है, या यदि स्ट्रिंग नहीं है तो `json.dumps(output)` | +| `StructuredQueryImpl` | परिणाम को स्ट्रिंग में प्रारूपित करता है | +| `PromptImpl` | `client.prompt()` को सीधे वापस करता है (स्ट्रिंग) | + +टूल सेवाएं समान अनुबंध का पालन करती हैं: +सेवा एक स्ट्रिंग प्रतिक्रिया (अवलोकन) वापस करती है +यदि प्रतिक्रिया एक स्ट्रिंग नहीं है, तो इसे `json.dumps()` के माध्यम से परिवर्तित किया जाता है +वर्णनकर्ता में किसी निष्कर्षण कॉन्फ़िगरेशन की आवश्यकता नहीं है + +यह वर्णनकर्ता को सरल रखता है और सेवा पर एजेंट के लिए एक उपयुक्त पाठ प्रतिक्रिया वापस करने की जिम्मेदारी डालता है। + +## कॉन्फ़िगरेशन गाइड + +एक नई टूल सेवा जोड़ने के लिए, दो कॉन्फ़िगरेशन आइटम की आवश्यकता होती है: + +### 1. टूल सेवा कॉन्फ़िगरेशन + +`tool-service` कॉन्फ़िगरेशन कुंजी के अंतर्गत संग्रहीत। पल्सर कतारों और उपलब्ध कॉन्फ़िगरेशन मापदंडों को परिभाषित करता है। + +| फ़ील्ड | आवश्यक | विवरण | +|-------|----------|-------------| +| `id` | हाँ | टूल सेवा के लिए अद्वितीय पहचानकर्ता | +| `request-queue` | हाँ | अनुरोधों के लिए पूर्ण पल्सर विषय (उदाहरण के लिए, `non-persistent://tg/request/joke`) | +| `response-queue` | हाँ | प्रतिक्रियाओं के लिए पूर्ण पल्सर विषय (उदाहरण के लिए, `non-persistent://tg/response/joke`) | +| `config-params` | नहीं | सेवा द्वारा स्वीकार किए जाने वाले कॉन्फ़िगरेशन मापदंडों की सरणी | + +प्रत्येक कॉन्फ़िगरेशन पैरामीटर में निम्नलिखित निर्दिष्ट किया जा सकता है: +`name`: पैरामीटर नाम (आवश्यक) +`required`: क्या पैरामीटर को टूल द्वारा प्रदान किया जाना चाहिए (डिफ़ॉल्ट: झूठा) + +उदाहरण: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. टूल कॉन्फ़िगरेशन + +`tool` कुंजी के अंतर्गत संग्रहीत। यह एक ऐसा टूल परिभाषित करता है जिसका उपयोग एजेंट कर सकता है। + +| फ़ील्ड | आवश्यक | विवरण | +|-------|----------|-------------| +| `type` | हाँ | यह `"tool-service"` होना चाहिए | +| `name` | हाँ | एलएलएम को प्रदर्शित होने वाला टूल नाम | +| `description` | हाँ | टूल क्या करता है इसका विवरण (एलएलएम को दिखाया जाता है) | +| `service` | हाँ | टूल-सर्विस का आईडी जिसे कॉल किया जाना है | +| `arguments` | नहीं | एलएलएम के लिए तर्क परिभाषाओं का सरणी | +| *(कॉन्फ़िगरेशन पैरामीटर)* | भिन्न | सेवा द्वारा परिभाषित कोई भी कॉन्फ़िगरेशन पैरामीटर | + +प्रत्येक तर्क में निम्नलिखित निर्दिष्ट किया जा सकता है: +`name`: तर्क का नाम (आवश्यक) +`type`: डेटा प्रकार, उदाहरण के लिए, `"string"` (आवश्यक) +`description`: एलएलएम को दिखाया जाने वाला विवरण (आवश्यक) + +उदाहरण: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### कॉन्फ़िगरेशन लोड करना + +कॉन्फ़िगरेशन लोड करने के लिए `tg-put-config-item` का उपयोग करें: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +एजेंट-मैनेजर को नए कॉन्फ़िगरेशन को लागू करने के लिए पुनरारंभ किया जाना चाहिए। + +## कार्यान्वयन विवरण + +### स्कीमा + +`trustgraph-base/trustgraph/schema/services/tool_service.py` में अनुरोध और प्रतिक्रिया प्रकार: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### सर्वर-साइड: डायनामिकटूलसर्विस + +`trustgraph-base/trustgraph/base/dynamic_tool_service.py` में बेस क्लास: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### क्लाइंट-साइड: ToolServiceImpl + +`trustgraph-flow/trustgraph/agent/react/tools.py` में कार्यान्वयन: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### फ़ाइलें + +| फ़ाइल | उद्देश्य | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | अनुरोध/प्रतिक्रिया स्कीमा | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | सेवाओं को आमंत्रित करने के लिए क्लाइंट | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | सेवा कार्यान्वयन के लिए आधार वर्ग | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | `ToolServiceImpl` वर्ग | +| `trustgraph-flow/trustgraph/agent/react/service.py` | कॉन्फ़िगरेशन लोडिंग | + +### उदाहरण: जोक सर्विस + +`trustgraph-flow/trustgraph/tool_service/joke/` में एक उदाहरण सेवा: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +टूल सर्विस कॉन्फ़िगरेशन: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +टूल कॉन्फ़िगरेशन: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### पिछली अनुकूलता (पिछड़ी संगतता) + +मौजूदा अंतर्निहित टूल प्रकार बिना किसी बदलाव के काम करना जारी रखते हैं। +`tool-service` एक नया टूल प्रकार है जो मौजूदा प्रकारों (`knowledge-query`, `mcp-tool`, आदि) के साथ है। + +## भविष्य के विचार + +### स्व-घोषणा करने वाली सेवाएं + +एक भविष्य का सुधार सेवाओं को अपने स्वयं के विवरण प्रकाशित करने की अनुमति दे सकता है: + +सेवाएं स्टार्टअप पर एक ज्ञात `tool-descriptors` विषय पर प्रकाशित करती हैं। +एजेंट सदस्यता लेता है और गतिशील रूप से टूल पंजीकृत करता है। +यह वास्तविक प्लग-एंड-प्ले को कॉन्फ़िगरेशन परिवर्तनों के बिना सक्षम बनाता है। + +यह प्रारंभिक कार्यान्वयन के दायरे से बाहर है। + +## संदर्भ + +वर्तमान टूल कार्यान्वयन: `trustgraph-flow/trustgraph/agent/react/tools.py` +टूल पंजीकरण: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +एजेंट स्कीमा: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.md b/docs/tech-specs/tool-services.md index 6edf7551..3fa026f9 100644 --- a/docs/tech-specs/tool-services.md +++ b/docs/tech-specs/tool-services.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Tool Services: Dynamically Pluggable Agent Tools" +parent: "Tech Specs" +--- + # Tool Services: Dynamically Pluggable Agent Tools ## Status diff --git a/docs/tech-specs/tool-services.pt.md b/docs/tech-specs/tool-services.pt.md new file mode 100644 index 00000000..c2ea3072 --- /dev/null +++ b/docs/tech-specs/tool-services.pt.md @@ -0,0 +1,479 @@ +--- +layout: default +title: "Serviços de Ferramentas: Ferramentas de Agente Dinamicamente Plugáveis" +parent: "Portuguese (Beta)" +--- + +# Serviços de Ferramentas: Ferramentas de Agente Dinamicamente Plugáveis + +> **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 + +Implementado + +## Visão Geral + +Esta especificação define um mecanismo para ferramentas de agente dinamicamente plugáveis, chamadas "serviços de ferramentas". Ao contrário dos tipos de ferramentas integradas existentes (`KnowledgeQueryImpl`, `McpToolImpl`, etc.), os serviços de ferramentas permitem que novas ferramentas sejam introduzidas por: + +1. Implantando um novo serviço baseado em Pulsar +2. Adicionando um descritor de configuração que informa ao agente como invocá-lo + +Isso permite a extensibilidade sem modificar o framework de resposta do agente principal. + +## Terminologia + +| Termo | Definição | +|------|------------| +| **Ferramenta Integrada** | Tipos de ferramentas existentes com implementações codificadas em `tools.py` | +| **Serviço de Ferramenta** | Um serviço Pulsar que pode ser invocado como uma ferramenta de agente, definido por um descritor de serviço | +| **Ferramenta** | Uma instância configurada que referencia um serviço de ferramenta, exposta ao agente/LLM | + +Este é um modelo de duas camadas, análogo às ferramentas MCP: +MCP: O servidor MCP define a interface da ferramenta → A configuração da ferramenta a referencia +Serviços de Ferramenta: O serviço de ferramenta define a interface Pulsar → A configuração da ferramenta a referencia + +## Contexto: Ferramentas Existentes + +### Implementação de Ferramenta Integrada + +As ferramentas são atualmente definidas em `trustgraph-flow/trustgraph/agent/react/tools.py` com implementações tipadas: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +Cada tipo de ferramenta: +Possui um serviço Pulsar pré-definido que ele chama (por exemplo, `graph-rag-request`) +Conhece o método exato a ser chamado no cliente (por exemplo, `client.rag()`) +Possui argumentos tipados definidos na implementação + +### Registro de Ferramentas (service.py:105-214) + +As ferramentas são carregadas da configuração com um campo `type` que mapeia para uma implementação: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## Arquitetura + +### Modelo de Duas Camadas + +#### Camada 1: Descritor do Serviço de Ferramenta + +Um serviço de ferramenta define uma interface de serviço Pulsar. Ele declara: +As filas Pulsar para solicitação/resposta +Os parâmetros de configuração que ele requer das ferramentas que o utilizam + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +Um serviço de ferramenta que não requer parâmetros de configuração: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### Nível 2: Descritor de Ferramenta + +Uma ferramenta referencia um serviço de ferramenta e fornece: +Valores de parâmetros de configuração (que satisfazem os requisitos do serviço) +Metadados da ferramenta para o agente (nome, descrição) +Definições de argumentos para o LLM + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +Múltiplas ferramentas podem referenciar o mesmo serviço com diferentes configurações: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### Formato da Requisição + +Quando uma ferramenta é invocada, a requisição ao serviço da ferramenta inclui: +`user`: Do pedido do agente (multi-tenência) +`config`: Valores de configuração codificados em JSON, provenientes da descrição da ferramenta +`arguments`: Argumentos codificados em JSON, provenientes do LLM + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +O serviço de ferramenta recebe estes como dicionários analisados no método `invoke`. + +### Implementação Genérica do Serviço de Ferramenta + +Uma classe `ToolServiceImpl` invoca serviços de ferramenta com base na configuração: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## Decisões de Design + +### Modelo de Configuração de Duas Camadas + +Os serviços de ferramentas seguem um modelo de duas camadas semelhante às ferramentas MCP: + +1. **Serviço de Ferramenta**: Define a interface do serviço Pulsar (tópico, parâmetros de configuração necessários) +2. **Ferramenta**: Referencia um serviço de ferramenta, fornece valores de configuração, define argumentos do LLM + +Essa separação permite: +Que um único serviço de ferramenta seja usado por várias ferramentas com diferentes configurações +Uma distinção clara entre a interface do serviço e a configuração da ferramenta +A reutilização das definições de serviço + +### Mapeamento de Solicitações: Transmissão com Envelope + +A solicitação a um serviço de ferramenta é um envelope estruturado contendo: +`user`: Propagado do pedido do agente para multi-inquilinato +Valores de configuração: Do descritor da ferramenta (por exemplo, `collection`) +`arguments`: Argumentos fornecidos pelo LLM, transmitidos como um dicionário + +O gerenciador de agente analisa a resposta do LLM em `act.arguments` como um dicionário (`agent_manager.py:117-154`). Este dicionário é incluído no envelope da solicitação. + +### Tratamento de Esquemas: Não Tipados + +As solicitações e respostas usam dicionários não tipados. Não há validação de esquema no nível do agente - o serviço de ferramenta é responsável por validar suas entradas. Isso fornece o máximo de flexibilidade para definir novos serviços. + +### Interface do Cliente: Tópicos Pulsar Diretos + +Os serviços de ferramentas usam tópicos Pulsar diretos, sem a necessidade de configuração de fluxo. O descritor do serviço de ferramenta especifica os nomes completos das filas: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +Isso permite que os serviços sejam hospedados em qualquer namespace. + +### Tratamento de Erros: Convenção de Erro Padrão + +As respostas do serviço de ferramenta seguem a convenção de esquema existente com um campo `error`: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +Estrutura da resposta: +Sucesso: `error` é `None`, a resposta contém o resultado +Erro: `error` é preenchido com `type` e `message` + +Isso corresponde ao padrão usado em todo o serviço existente (por exemplo, `PromptResponse`, `QueryResponse`, `AgentResponse`). + +### Correlação de Requisições/Respostas + +As requisições e respostas são correlacionadas usando um `id` nas propriedades da mensagem Pulsar: + +A requisição inclui `id` nas propriedades: `properties={"id": id}` +A(s) resposta(s) incluem o mesmo `id`: `properties={"id": id}` + +Isso segue o padrão existente usado em todo o código-fonte (por exemplo, `agent_service.py`, `llm_service.py`). + +### Suporte a Streaming + +Os serviços de ferramenta podem retornar respostas em streaming: + +Múltiplas mensagens de resposta com o mesmo `id` nas propriedades +Cada resposta inclui o campo `end_of_stream: bool` +A resposta final tem `end_of_stream: True` + +Isso corresponde ao padrão usado em `AgentResponse` e outros serviços de streaming. + +### Tratamento da Resposta: Retorno de String + +Todas as ferramentas existentes seguem o mesmo padrão: **receber argumentos como um dicionário, retornar a observação como uma string**. + +| Ferramenta | Tratamento da Resposta | +|------|------------------| +| `KnowledgeQueryImpl` | Retorna `client.rag()` diretamente (string) | +| `TextCompletionImpl` | Retorna `client.question()` diretamente (string) | +| `McpToolImpl` | Retorna uma string, ou `json.dumps(output)` se não for uma string | +| `StructuredQueryImpl` | Formata o resultado para uma string | +| `PromptImpl` | Retorna `client.prompt()` diretamente (string) | + +Os serviços de ferramenta seguem o mesmo contrato: +O serviço retorna uma resposta em string (a observação) +Se a resposta não for uma string, ela é convertida via `json.dumps()` +Nenhuma configuração de extração é necessária no descritor + +Isso mantém o descritor simples e coloca a responsabilidade de retornar uma resposta de texto apropriada para o agente no serviço. + +## Guia de Configuração + +Para adicionar um novo serviço de ferramenta, são necessários dois itens de configuração: + +### 1. Configuração do Serviço de Ferramenta + +Armazenado sob a chave de configuração `tool-service`. Define as filas Pulsar e os parâmetros de configuração disponíveis. + +| Campo | Obrigatório | Descrição | +|-------|----------|-------------| +| `id` | Sim | Identificador único para o serviço de ferramenta | +| `request-queue` | Sim | Tópico Pulsar completo para requisições (por exemplo, `non-persistent://tg/request/joke`) | +| `response-queue` | Sim | Tópico Pulsar completo para respostas (por exemplo, `non-persistent://tg/response/joke`) | +| `config-params` | Não | Array de parâmetros de configuração que o serviço aceita | + +Cada parâmetro de configuração pode especificar: +`name`: Nome do parâmetro (obrigatório) +`required`: Se o parâmetro deve ser fornecido pelas ferramentas (padrão: falso) + +Exemplo: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. Configuração da Ferramenta + +Armazenado sob a chave de configuração `tool`. Define uma ferramenta que o agente pode usar. + +| Campo | Obrigatório | Descrição | +|-------|----------|-------------| +| `type` | Sim | Deve ser `"tool-service"` | +| `name` | Sim | Nome da ferramenta exposto para o LLM | +| `description` | Sim | Descrição do que a ferramenta faz (mostrada para o LLM) | +| `service` | Sim | ID do serviço de ferramenta a ser invocado | +| `arguments` | Não | Array de definições de argumentos para o LLM | +| *(parâmetros de configuração)* | Varia | Quaisquer parâmetros de configuração definidos pelo serviço | + +Cada argumento pode especificar: +`name`: Nome do argumento (obrigatório) +`type`: Tipo de dados, por exemplo, `"string"` (obrigatório) +`description`: Descrição mostrada para o LLM (obrigatório) + +Exemplo: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### Carregando a Configuração + +Use `tg-put-config-item` para carregar as configurações: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +O agente-gerenciador deve ser reiniciado para aplicar novas configurações. + +## Detalhes da Implementação + +### Esquema + +Tipos de requisição e resposta em `trustgraph-base/trustgraph/schema/services/tool_service.py`: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### Servidor: DynamicToolService + +Classe base em `trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### Cliente: ToolServiceImpl + +Implementação em `trustgraph-flow/trustgraph/agent/react/tools.py`: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### Arquivos + +| Arquivo | Propósito | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | Esquemas de requisição/resposta | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | Cliente para invocar serviços | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | Classe base para implementação de serviço | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | Classe `ToolServiceImpl` | +| `trustgraph-flow/trustgraph/agent/react/service.py` | Carregamento de configuração | + +### Exemplo: Serviço de Piadas + +Um exemplo de serviço em `trustgraph-flow/trustgraph/tool_service/joke/`: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +Configuração do serviço de ferramenta: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +Configuração da ferramenta: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### Compatibilidade com versões anteriores + +Os tipos de ferramentas integradas existentes continuam a funcionar sem alterações. +`tool-service` é um novo tipo de ferramenta, juntamente com os tipos existentes (`knowledge-query`, `mcp-tool`, etc.). + +## Considerações futuras + +### Serviços de autoanúncio + +Uma melhoria futura poderia permitir que os serviços publicassem seus próprios descritores: + +Os serviços publicam em um tópico `tool-descriptors` conhecido na inicialização. +O agente se inscreve e registra dinamicamente as ferramentas. +Permite um verdadeiro sistema de plug-and-play sem alterações de configuração. + +Isso está fora do escopo da implementação inicial. + +## Referências + +Implementação atual da ferramenta: `trustgraph-flow/trustgraph/agent/react/tools.py` +Registro de ferramentas: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +Esquemas do agente: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.ru.md b/docs/tech-specs/tool-services.ru.md new file mode 100644 index 00000000..d87195a3 --- /dev/null +++ b/docs/tech-specs/tool-services.ru.md @@ -0,0 +1,479 @@ +--- +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. + +## Статус + +Реализовано + +## Обзор + +Эта спецификация определяет механизм динамически подключаемых инструментов для агентов, называемых "сервисами инструментов". В отличие от существующих встроенных типов инструментов (`KnowledgeQueryImpl`, `McpToolImpl` и т.д.), сервисы инструментов позволяют добавлять новые инструменты путем: + +1. Развертывания нового сервиса на базе Pulsar +2. Добавления описания конфигурации, которое сообщает агенту, как его вызывать + +Это обеспечивает расширяемость без изменения основной структуры агента. + +## Терминология + +| Термин | Определение | +|------|------------| +| **Встроенный инструмент** | Существующие типы инструментов с жестко закодированными реализациями в `tools.py` | +| **Сервис инструмента** | Сервис Pulsar, который может быть вызван как инструмент для агента, определенный описанием сервиса | +| **Инструмент** | Настроенный экземпляр, который ссылается на сервис инструмента и предоставляется агенту/LLM | + +Это двухзвенная модель, аналогичная инструментам MCP: +MCP: MCP-сервер определяет интерфейс инструмента → Конфигурация инструмента ссылается на него +Сервисы инструментов: Сервис инструмента определяет интерфейс Pulsar → Конфигурация инструмента ссылается на него + +## Обзор: Существующие инструменты + +### Реализация встроенного инструмента + +Инструменты в настоящее время определены в `trustgraph-flow/trustgraph/agent/react/tools.py` с типизированными реализациями: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +Каждый тип инструмента: +Имеет жестко заданный сервис Pulsar, к которому он обращается (например, `graph-rag-request`) +Знает точный метод, который нужно вызвать у клиента (например, `client.rag()`) +Имеет типизированные аргументы, определенные в реализации + +### Регистрация инструментов (service.py:105-214) + +Инструменты загружаются из конфигурации с помощью поля `type`, которое сопоставляется с реализацией: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## Архитектура + +### Двухуровневая модель + +#### Уровень 1: Описание сервиса инструмента + +Сервис инструмента определяет интерфейс сервиса Pulsar. Он объявляет: +Очереди Pulsar для запросов/ответов +Параметры конфигурации, которые он требует от инструментов, использующих его + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +Сервис, который не требует параметров конфигурации: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### Уровень 2: Описание инструмента + +Инструмент ссылается на сервис инструмента и предоставляет: +Значения параметров конфигурации (соответствующие требованиям сервиса) +Метаданные инструмента для агента (название, описание) +Определения аргументов для LLM + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +Несколько инструментов могут ссылаться на один и тот же сервис с разными конфигурациями: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### Формат запроса + +Когда вызывается инструмент, запрос к службе инструмента включает в себя: +`user`: Из запроса агента (многопользовательский режим) +`config`: Значения конфигурации, закодированные в формате JSON, из описания инструмента +`arguments`: Аргументы, закодированные в формате JSON, из LLM + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +Сервис инструментов получает это в виде разобранных словарей в методе `invoke`. + +### Общая реализация сервиса инструментов + +Класс `ToolServiceImpl` вызывает сервисы инструментов на основе конфигурации: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## Принятые решения по проектированию + +### Модель конфигурации с двумя уровнями + +Сервисы инструментов следуют двухслойной модели, аналогичной инструментам MCP: + +1. **Сервис инструмента**: Определяет интерфейс сервиса Pulsar (тема, необходимые параметры конфигурации). +2. **Инструмент**: Ссылается на сервис инструмента, предоставляет значения конфигурации, определяет аргументы LLM. + +Это разделение позволяет: +Использовать один сервис инструмента несколькими инструментами с разными конфигурациями. +Четко различать интерфейс сервиса и конфигурацию инструмента. +Повторное использование определений сервисов. + +### Отображение запросов: Прямая передача с оболочкой + +Запрос к сервису инструмента представляет собой структурированную оболочку, содержащую: +`user`: Передается из запроса агента для поддержки многопользовательской среды. +Значения конфигурации: Из описателя инструмента (например, `collection`). +`arguments`: Аргументы, предоставленные LLM, передаются в виде словаря. + +Менеджер агента анализирует ответ LLM в `act.arguments` в виде словаря (`agent_manager.py:117-154`). Этот словарь включается в оболочку запроса. + +### Обработка схем: Без типов + +Запросы и ответы используют нетипизированные словари. Отсутствует проверка схемы на уровне агента - сервис инструмента отвечает за проверку своих входных данных. Это обеспечивает максимальную гибкость при определении новых сервисов. + +### Клиентский интерфейс: Прямые темы Pulsar + +Сервисы инструментов используют прямые темы Pulsar без необходимости настройки потоков. Описатель сервиса инструмента указывает полные имена очередей: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +Это позволяет размещать сервисы в любом пространстве имен. + +### Обработка ошибок: Стандартная конвенция для ошибок + +Ответы сервисов инструментов соответствуют существующей схеме с полем `error`: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +Структура ответа: +Успех: `error` имеет значение `None`, ответ содержит результат +Ошибка: `error` заполняется значениями `type` и `message` + +Это соответствует шаблону, используемому во всех существующих схемах сервисов (например, `PromptResponse`, `QueryResponse`, `AgentResponse`). + +### Корреляция запросов и ответов + +Корреляция запросов и ответов осуществляется с использованием `id` в свойствах сообщения Pulsar: + +Запрос включает `id` в свойствах: `properties={"id": id}` +Ответы включают тот же `id`: `properties={"id": id}` + +Это соответствует существующему шаблону, используемому во всей кодовой базе (например, `agent_service.py`, `llm_service.py`). + +### Поддержка потоковой передачи + +Сервисы инструментов могут возвращать потоковые ответы: + +Несколько сообщений ответа с тем же `id` в свойствах +Каждый ответ включает поле `end_of_stream: bool` +Заключительный ответ имеет `end_of_stream: True` + +Это соответствует шаблону, используемому в `AgentResponse` и других сервисах потоковой передачи. + +### Обработка ответов: Возврат строки + +Все существующие инструменты следуют одному и тому же шаблону: **получение аргументов в виде словаря, возврат наблюдения в виде строки**. + +| Инструмент | Обработка ответов | +|------|------------------| +| `KnowledgeQueryImpl` | Возвращает `client.rag()` напрямую (строка) | +| `TextCompletionImpl` | Возвращает `client.question()` напрямую (строка) | +| `McpToolImpl` | Возвращает строку, или `json.dumps(output)`, если это не строка | +| `StructuredQueryImpl` | Форматирует результат в строку | +| `PromptImpl` | Возвращает `client.prompt()` напрямую (строка) | + +Сервисы инструментов следуют тому же контракту: +Сервис возвращает строковый ответ (наблюдение) +Если ответ не является строкой, он преобразуется с помощью `json.dumps()` +Не требуется конфигурация извлечения в дескрипторе + +Это упрощает дескриптор и возлагает ответственность на сервис по возврату соответствующего текстового ответа для агента. + +## Руководство по настройке + +Для добавления нового сервиса инструмента требуются два элемента конфигурации: + +### 1. Конфигурация сервиса инструмента + +Хранится под ключом конфигурации `tool-service`. Определяет очереди Pulsar и доступные параметры конфигурации. + +| Поле | Обязательно | Описание | +|-------|----------|-------------| +| `id` | Да | Уникальный идентификатор для сервиса инструмента | +| `request-queue` | Да | Полная тема Pulsar для запросов (например, `non-persistent://tg/request/joke`) | +| `response-queue` | Да | Полная тема Pulsar для ответов (например, `non-persistent://tg/response/joke`) | +| `config-params` | Нет | Массив параметров конфигурации, которые принимает сервис | + +Каждый параметр конфигурации может указывать: +`name`: Имя параметра (обязательно) +`required`: Должен ли параметр предоставляться инструментами (по умолчанию: false) + +Пример: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. Конфигурация инструмента + +Хранится под ключом конфигурации `tool`. Определяет инструмент, которым может пользоваться агент. + +| Поле | Обязательно | Описание | +|-------|----------|-------------| +| `type` | Да | Должно быть `"tool-service"` | +| `name` | Да | Название инструмента, доступное для LLM | +| `description` | Да | Описание того, что делает инструмент (отображается для LLM) | +| `service` | Да | ID сервиса инструмента, который необходимо вызвать | +| `arguments` | Нет | Массив определений аргументов для LLM | +| *(параметры конфигурации)* | Зависит | Любые параметры конфигурации, определенные сервисом | + +Каждый аргумент может содержать: +`name`: Имя аргумента (обязательно) +`type`: Тип данных, например, `"string"` (обязательно) +`description`: Описание, отображаемое для LLM (обязательно) + +Пример: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### Загрузка конфигурации + +Используйте `tg-put-config-item` для загрузки конфигураций: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +Агент-менеджер должен быть перезапущен для применения новых конфигураций. + +## Детали реализации + +### Схема + +Типы запросов и ответов в `trustgraph-base/trustgraph/schema/services/tool_service.py`: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### Серверная часть: DynamicToolService + +Базовый класс в `trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### Клиентская часть: ToolServiceImpl + +Реализация в `trustgraph-flow/trustgraph/agent/react/tools.py`: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### Файлы + +| Файл | Назначение | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | Схемы запросов/ответов | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | Клиент для вызова сервисов | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | Базовый класс для реализации сервиса | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | Класс `ToolServiceImpl` | +| `trustgraph-flow/trustgraph/agent/react/service.py` | Загрузка конфигурации | + +### Пример: Сервис шуток + +Пример сервиса на `trustgraph-flow/trustgraph/tool_service/joke/`: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +Конфигурация сервиса инструментов: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +Конфигурация инструмента: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### Обратная совместимость + +Существующие встроенные типы инструментов продолжают работать без изменений. +`tool-service` - это новый тип инструмента, который существует наряду с существующими типами (`knowledge-query`, `mcp-tool` и т.д.). + +## Будущие соображения + +### Сервисы с автоматическим оповещением + +В будущем можно будет реализовать функцию, позволяющую сервисам публиковать свои собственные описания: + +Сервисы публикуют информацию при запуске в определенной теме `tool-descriptors`. +Агент подписывается и динамически регистрирует инструменты. +Это обеспечивает возможность подключения и использования без изменения конфигурации. + +Это выходит за рамки первоначальной реализации. + +## Ссылки + +Текущая реализация инструментов: `trustgraph-flow/trustgraph/agent/react/tools.py` +Регистрация инструментов: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +Схемы агента: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.sw.md b/docs/tech-specs/tool-services.sw.md new file mode 100644 index 00000000..bbe79956 --- /dev/null +++ b/docs/tech-specs/tool-services.sw.md @@ -0,0 +1,479 @@ +--- +layout: default +title: "Huduma za Zana: Zana za Wakala Zinazoweza Kuunganishwa Kwenye Mfumo" +parent: "Swahili (Beta)" +--- + +# Huduma za Zana: Zana za Wakala Zinazoweza Kuunganishwa Kwenye Mfumo + +> **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 + +Imetekelezwa + +## Muhtasari + +Maelezo haya yanafafanua mfumo wa zana za wakala ambazo zinaweza kuunganishwa kwenye mfumo, zinazojulikana kama "huduma za zana". Tofauti na aina za zana zilizojumuishwa awali (`KnowledgeQueryImpl`, `McpToolImpl`, n.k.), huduma za zana huruhusu zana mpya kuletwa kwa: + +1. Kuanzisha huduma mpya iliyojengwa kwenye Pulsar +2. Kuongeza maelezo ya usanidi ambayo huambia wakala jinsi ya kuiita + +Hii inaruhusu uboreshaji bila kubadilisha mfumo msingi wa wakala. + +## Dhana + +| Neno | Ufafanuzi | +|------|------------| +| **Zana Iliyojumuishwa** | Aina za zana zilizopo zilizo na matumizi yaliyopangwa mapema katika `tools.py` | +| **Huduma ya Zana** | Huduma ya Pulsar ambayo inaweza kuita kama zana ya wakala, iliyoainishwa na maelezo ya huduma | +| **Zana** | Toleo lililosanidiwa ambalo linarejelea huduma ya zana, lililowezeshwa kwa wakala/LLM | + +Hii ni mfumo wa tabaka mbili, sawa na zana za MCP: +MCP: Seva ya MCP inaainisha kiolesura cha zana → Usanidi wa zana huirejelea +Huduma za Zana: Huduma ya zana inaainisha kiolesura cha Pulsar → Usanidi wa zana huirejelea + +## Asili: Zana Zilizopo + +### Utendaji wa Zana Iliyojumuishwa + +Zana kwa sasa zinafafanuliwa katika `trustgraph-flow/trustgraph/agent/react/tools.py` na matumizi yaliyopangwa: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +Kila aina ya zana: +Ina huduma ya Pulsar iliyopangwa tayari ambayo inaitumia (k.m., `graph-rag-request`) +Inajua njia sahihi ya kuita kwenye mteja (k.m., `client.rag()`) +Ina vigezo vilivyopangwa ambavyo vimefafuliwa katika utekelezaji + +### Usajili wa Zana (service.py:105-214) + +Zana huzamilishwa kutoka kwa usanidi na sehemu ya `type` ambayo inaelekeza kwenye utekelezaji: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## Usanifu + +### Mfumo wa Tabaka Mbili + +#### Tabaka la 1: Kisajili cha Huduma ya Zana + +Huduma ya zana inaelezea kiolesura cha huduma ya Pulsar. Inaangazia: +Mizinga ya Pulsar kwa ombi/jibu +Vigezo vya usanidi ambavyo vinahitajika na zana zinazotumia huduma hiyo + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +Huduma ya zana ambayo haihitaji vigezo vya usanidi: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### Kategoria ya 2: Kisajili cha Zana + +Zana inarejelea huduma ya zana na hutoa: +Maelezo ya vigezo ya usanidi (yakinayo na mahitaji ya huduma) +Meta-data ya zana kwa wakala (jina, maelezo) +Ufafanuzi wa hoja kwa mfumo wa lugha (LLM) + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +Zana nyingi zinaweza kurejelea huduma moja kwa usanidi tofauti: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### Muundo wa Ombi + +Wakati zana inaitwa, ombi kwa huduma ya zana linajumuisha: +`user`: Kutoka ombi la wakala (utumiaji wa pamoja) +`config`: Maelezo ya usanidi yaliyokandwa katika umbizo la JSON kutoka kwa maelezo ya zana +`arguments`: Majadilisho yaliyokandwa katika umbizo la JSON kutoka kwa mfumo wa lugha kubwa (LLM) + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +Huduma ya zana hupokea haya kama dictionaries yaliyochanganishwa katika njia ya `invoke`. + +### Utendakazi wa Huduma ya Zana ya Jumla + +Darasa la `ToolServiceImpl` huita huduma za zana kulingana na usanidi: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## Maamuzi ya Ubunifu + +### Mfumo wa Uwekaji wa Tabaka Mbili + +Huduma za zana zinafuata mfumo wa tabaka mbili, sawa na zana za MCP: + +1. **Huduma ya Zana**: Inaelezea kiolesura cha huduma ya Pulsar (mada, vigezo muhimu vya usanidi) +2. **Zana**: Inarejelea huduma ya zana, hutoa maadili ya usanidi, inaelezea hoja za LLM + +Tofauti hii inaruhusu: +Huduma moja ya zana kutumika na zana nyingi zenye usanidi tofauti +Tofauti wazi kati ya kiolesura cha huduma na usanidi wa zana +Ujuzi wa matumizi wa maelezo ya huduma + +### Ramani ya Ombi: Kupitisha na Kifurushi + +Ombi kwa huduma ya zana ni kifurushi kilicho na muundo, kinachojumuisha: +`user`: Inasambazwa kutoka ombi la wakala kwa ajili ya utumiaji wa pamoja +Maadili ya usanidi: Kutoka kwa maelezo ya zana (k.m., `collection`) +`arguments`: Hoja zilizotolewa na LLM, zinazopitishwa kama kamusi + +Kidhibiti cha wakala huchanganua jibu la LLM kuwa `act.arguments` kama kamusi (`agent_manager.py:117-154`). Kamusi hii inajumuishwa katika kifurushi cha ombi. + +### Usimamizi wa Mpango: Bila Aina + +Maombi na majibu hutumia kamusi zisizo na aina. Hakuna uthibitishaji wa mpango katika ngazi ya wakala - huduma ya zana inawajibika kwa uthibitishaji wa pembejeo zake. Hii hutoa uwezo mkubwa wa kufafanua huduma mpya. + +### Kiolesura cha Mteja: Mada za Moja kwa Moja za Pulsar + +Huduma za zana hutumia mada za moja kwa moja za Pulsar bila kuhitaji usanidi wa mtiririko. Maelezo ya huduma-ya-zana yanaelezea majina kamili ya folyo: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +Hii inaruhusu huduma kuwa zimepakwa kwenye nafasi yoyote. + +### Usimamizi wa Makosa: Mfumo wa Makosa wa Kawaida + +Majibu ya huduma ya zana yanafuata mfumo wa sasa wa muundo na sehemu ya `error`: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +Muundo wa majibu: +Mafanikio: `error` ni `None`, majibu yana matokeo +Kosa: `error` imejaa na `type` na `message` + +Hii inafanana na muundo uliotumika katika huduma zingine (e.g., `PromptResponse`, `QueryResponse`, `AgentResponse`). + +### Uhusiano wa Ombi/Jibu + +Maombi na majibu yanahusishwa kwa kutumia `id` katika vipengele vya ujumbe wa Pulsar: + +Ombi linajumuisha `id` katika vipengele: `properties={"id": id}` +Majibu (mengi) yanajumuisha `id` sawa: `properties={"id": id}` + +Hii inafuata muundo uliopo katika codebase (e.g., `agent_service.py`, `llm_service.py`). + +### Usaidizi wa Uhamaji (Streaming) + +Huduma za zana zinaweza kurejesha majibu ya uhamaji: + +Ujumbe mwingi wa majibu wenye `id` sawa katika vipengele +Kila jibu linajumuisha `end_of_stream: bool` +Jibu la mwisho lina `end_of_stream: True` + +Hii inafanana na muundo uliotumika katika `AgentResponse` na huduma zingine za uhamaji. + +### Usimamizi wa Majibu: Kurudisha Kamba (String) + +Zana zote zilizopo zinafuata muundo huo: **kupokea hoja kama orodha, kurejesha matokeo kama kamba**. + +| Zana | Usimamizi wa Majibu | +|------|------------------| +| `KnowledgeQueryImpl` | Inarejea `client.rag()` moja kwa moja (kamba) | +| `TextCompletionImpl` | Inarejea `client.question()` moja kwa moja (kamba) | +| `McpToolImpl` | Inarejea kamba, au `json.dumps(output)` ikiwa si kamba | +| `StructuredQueryImpl` | Inaweka matokeo katika kamba | +| `PromptImpl` | Inarejea `client.prompt()` moja kwa moja (kamba) | + +Huduma za zana zinafuata mkataba huo: +Huduma inarejea jibu la kamba (matokeo) +Ikiwa jibu si kamba, linabadilishwa kupitia `json.dumps()` +Hakuna usanidi wa uondoaji unaohitajika katika maelezo + +Hii huweka maelezo kuwa rahisi na kuweka jukumu kwa huduma kurejesha jibu la maandishi linalofaa kwa wakala. + +## Mwongozo wa Usanidi + +Ili kuongeza huduma mpya ya zana, vipengele viwili vya usanidi vinahitajika: + +### 1. Usanidi wa Huduma ya Zana + +Inahifadhiwa chini ya ufunguo wa usanidi `tool-service`. Inaelezea folyo za Pulsar na vigezo vinavyopatikana vya usanidi. + +| Uwanja | Inahitajika | Maelezo | +|-------|----------|-------------| +| `id` | Ndiyo | Kitambulisho cha kipekee kwa huduma ya zana | +| `request-queue` | Ndiyo | Mada kamili ya Pulsar kwa maombi (e.g., `non-persistent://tg/request/joke`) | +| `response-queue` | Ndiyo | Mada kamili ya Pulsar kwa majibu (e.g., `non-persistent://tg/response/joke`) | +| `config-params` | Hapana | Safu ya vigezo vya usanidi ambavyo huduma inakubali | + +Kila kiparamu cha usanidi kinaweza kuainisha: +`name`: Jina la kiparamu (inahitajika) +`required`: Ikiwa kiparamu lazima kipewe na zana (cha kawaida: bandia) + +Mfano: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. Usanidi wa Zana + +Hifadhiwa chini ya ufunguo wa `tool`. Inaelezea zana ambayo wakala anaweza kutumia. + +| Sehemu | Inahitajika | Maelezo | +|-------|----------|-------------| +| `type` | Ndiyo | Lazima iwe `"tool-service"` | +| `name` | Ndiyo | Jina la zana linaloonyeshwa kwa LLM | +| `description` | Ndiyo | Maelezo ya kile ambacho zana inafanya (yanaonyeshwa kwa LLM) | +| `service` | Ndiyo | Kitambulisho cha huduma ya zana inayotumiwa | +| `arguments` | Hapana | Safu ya maelezo ya hoja kwa ajili ya LLM | +| *(vigezo vya usanidi)* | Hubadilika | Vigezo vyovyote vya usanidi vilivyobainishwa na huduma | + +Kila hoja inaweza kubainisha: +`name`: Jina la hoja (inahitajika) +`type`: Aina ya data, kwa mfano, `"string"` (inahitajika) +`description`: Maelezo yanayoonyeshwa kwa LLM (inahitajika) + +Mfano: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### Upakiaji wa Mipangilio + +Tumia `tg-put-config-item` ili kupakia mipangilio: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +Wakala-mtawala lazima uanzishwe tena ili kuchukua usanidi mpya. + +## Maelezo ya Utendaji + +### Mpango + +Aina za ombi na majibu katika `trustgraph-base/trustgraph/schema/services/tool_service.py`: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### Upande wa Server: Huduma ya DynamicToolService + +Darasa la msingi katika `trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### Upande wa Mteja: Huduma ya ToolServiceImpl + +Utendaji katika `trustgraph-flow/trustgraph/agent/react/tools.py`: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### Faili + +| Faili | Madhumuni | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | Mifumo ya ombi/jibu | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | Mteja wa kutumia huduma | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | Darasa la msingi kwa utekelezaji wa huduma | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | Darasa la `ToolServiceImpl` | +| `trustgraph-flow/trustgraph/agent/react/service.py` | Kupakia usanidi | + +### Mifano: Huduma ya Utani + +Mfano wa huduma katika `trustgraph-flow/trustgraph/tool_service/joke/`: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +Usanidi wa huduma za zana: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +Usanidi wa zana: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### Ulinganishi na Matoleo ya Zamani + +Aina za zana zilizopo zilizojumuishwa zinaendelea kufanya kazi bila kubadilishwa. +`tool-service` ni aina mpya ya zana pamoja na aina zilizopo (`knowledge-query`, `mcp-tool`, n.k.). + +## Mambo ya Kuzingatia Baadaye + +### Huduma Zinajitangaza Zenyewe + +Uboreshaji wa siku zijazo unaweza kuruhusu huduma kuchapisha maelezo yao wenyewe: + +Huduma huchapisha kwenye mada iliyojulikana ya `tool-descriptors` wakati wa kuanza. +Wakala husajili na kusajili zana kwa njia ya moja kwa moja. +Inaruhusu uunganishaji halisi wa "plug-and-play" bila mabadiliko ya usanidi. + +Hii ni nje ya upeo wa utekelezaji wa awali. + +## Marejeleo + +Utaratibu wa sasa wa zana: `trustgraph-flow/trustgraph/agent/react/tools.py` +Usajili wa zana: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +Schemas za wakala: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.tr.md b/docs/tech-specs/tool-services.tr.md new file mode 100644 index 00000000..3842c61c --- /dev/null +++ b/docs/tech-specs/tool-services.tr.md @@ -0,0 +1,479 @@ +--- +layout: default +title: "Araç Hizmetleri: Dinamik Olarak Eklenebilen Ajan Araçları" +parent: "Turkish (Beta)" +--- + +# Araç Hizmetleri: Dinamik Olarak Eklenebilen Ajan Araçları + +> **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 + +Uygulandı + +## Genel Bakış + +Bu özellik, "araç hizmetleri" olarak adlandırılan, dinamik olarak eklenebilen ajan araçları için bir mekanizma tanımlar. Mevcut, yerleşik araç türlerinin (`KnowledgeQueryImpl`, `McpToolImpl`, vb.) aksine, araç hizmetleri, aşağıdaki yöntemlerle yeni araçların eklenmesine olanak tanır: + +1. Yeni bir Pulsar tabanlı hizmetin dağıtılması +2. Ajanın hizmeti nasıl çağıracağını belirten bir yapılandırma açıklamasının eklenmesi + +Bu, çekirdek ajan-yanıt çerçevesini değiştirmeden genişletilebilirlik sağlar. + +## Terminoloji + +| Terim | Tanım | +|------|------------| +| **Yerleşik Araç** | `tools.py` içinde sabit kodlanmış uygulamalara sahip mevcut araç türleri | +| **Araç Hizmeti** | Bir hizmet açıklamasıyla tanımlanan ve bir ajan aracı olarak çağrılabilecek bir Pulsar hizmeti | +| **Araç** | Bir hizmet aracını referans alan ve ajana/LLM'ye sunulan yapılandırılmış bir örnek | + +Bu, MCP araçlarına benzer iki katmanlı bir modeldir: +MCP: MCP sunucusu araç arayüzünü tanımlar → Araç yapılandırması buna başvurur +Araç Hizmetleri: Araç hizmeti Pulsar arayüzünü tanımlar → Araç yapılandırması buna başvurur + +## Arka Plan: Mevcut Araçlar + +### Yerleşik Araç Uygulaması + +Araçlar şu anda `trustgraph-flow/trustgraph/agent/react/tools.py` içinde, türlenmiş uygulamalarla tanımlanmıştır: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +Her araç türü: +Çağırdığı sabit kodlu bir Pulsar servisine sahiptir (örneğin, `graph-rag-request`) +İstemci üzerinde çağrılacak kesin yöntemi bilir (örneğin, `client.rag()`) +Uygulamada tanımlanmış türlü argümanlara sahiptir + +### Araç Kaydı (service.py:105-214) + +Araçlar, bir uygulamaya eşleyen `type` alanıyla yapılandırmadan yüklenir: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## Mimari + +### İki Katmanlı Model + +#### 1. Katman: Araç Hizmeti Tanımlayıcısı + +Bir araç hizmeti, bir Pulsar hizmeti arayüzünü tanımlar. Aşağıdakileri belirtir: +İstek/yanıt için kullanılan Pulsar kuyrukları +Onu kullanan araçlardan gerektirdiği yapılandırma parametreleri + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +Herhangi bir yapılandırma parametresine ihtiyaç duymayan bir araç hizmeti: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### 2. Seviye: Araç Açıklaması + +Bir araç, bir araç hizmetine başvurur ve şunları sağlar: +Yapılandırma parametre değerleri (hizmetin gereksinimlerini karşılar) +Aracının ajana yönelik meta verileri (ad, açıklama) +LLM için argüman tanımları + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +Birden fazla aracın, farklı yapılandırmalarla aynı hizmete başvurabileceğini unutmayın: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### İstek Formatı + +Bir araç çağrıldığında, araca yapılan istek, aşağıdaki bilgileri içerir: +`user`: Aracının isteğinden (çoklu kiracılık) +`config`: Araç açıklamasından alınan, JSON formatında kodlanmış yapılandırma değerleri +`arguments`: LLM'den alınan, JSON formatında kodlanmış argümanlar + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +Araç hizmeti, bunları `invoke` yönteminde ayrıştırılmış sözlükler olarak alır. + +### Genel Araç Hizmeti Uygulaması + +Bir `ToolServiceImpl` sınıfı, yapılandırmaya göre araç hizmetlerini çağırır: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## Tasarım Kararları + +### İki Katmanlı Konfigürasyon Modeli + +Araç hizmetleri, MCP araçlarına benzer bir iki katmanlı model izler: + +1. **Araç Hizmeti**: Pulsar hizmet arayüzünü (konu, gerekli yapılandırma parametreleri) tanımlar. +2. **Araç**: Bir araç hizmetine başvurur, yapılandırma değerlerini sağlar, LLM argümanlarını tanımlar. + +Bu ayrım şunları sağlar: +Farklı yapılandırmalara sahip birden fazla aracın aynı araç hizmetini kullanabilmesi +Hizmet arayüzü ve araç yapılandırması arasındaki net ayrım +Hizmet tanımlarının yeniden kullanılabilirliği + +### İstek Eşleme: Zarf ile Doğrudan İletim + +Bir araç hizmetine yapılan istek, şunları içeren yapılandırılmış bir zarf içerir: +`user`: Çoklu kiracılık için aracıdan gelen istekten aktarılır. +Yapılandırma değerleri: Araç açıklamasından (örneğin, `collection`). +`arguments`: LLM tarafından sağlanan argümanlar, bir sözlük olarak iletilir. + +Aracı yöneticisi, LLM'nin yanıtını `act.arguments` olarak bir sözlükte (`agent_manager.py:117-154`) ayrıştırır. Bu sözlük, istek zarfında bulunur. + +### Şema İşleme: Türsüz + +İstekler ve yanıtlar, tür tanımlaması olmayan sözlükler kullanır. Aracılar seviyesinde herhangi bir şema doğrulaması yapılmaz; araç hizmeti, girişlerini doğrulamaktan sorumludur. Bu, yeni hizmetler tanımlamak için maksimum esneklik sağlar. + +### İstemci Arayüzü: Doğrudan Pulsar Konuları + +Araç hizmetleri, akış yapılandırması gerektirmeden doğrudan Pulsar konularını kullanır. Araç hizmeti tanımında, tam kuyruk adları belirtilir: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +Bu, hizmetlerin herhangi bir ad alanında barındırılmasını sağlar. + +### Hata Yönetimi: Standart Hata Kuralı + +Ara hizmet yanıtları, `error` alanı ile mevcut şema kuralını takip eder: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +Yanıt yapısı: +Başarı: `error`, `None` ise, yanıt sonuç içerir. +Hata: `error`, `type` ve `message` ile doldurulur. + +Bu, mevcut hizmet şemalarında kullanılan kalıpla eşleşir (örneğin, `PromptResponse`, `QueryResponse`, `AgentResponse`). + +### İstek/Yanıt İlişkilendirmesi + +İstekler ve yanıtlar, Pulsar mesaj özelliklerindeki bir `id` kullanılarak ilişkilendirilir: + +İstek, özelliklerde `id` içerir: `properties={"id": id}` +Yanıt(lar), aynı `id`'ı içerir: `properties={"id": id}` + +Bu, kod tabanında kullanılan mevcut kalıpla uyumludur (örneğin, `agent_service.py`, `llm_service.py`). + +### Akış Desteği + +Araç hizmetleri, akış yanıtları döndürebilir: + +Aynı `id`'a sahip çoklu yanıt mesajı +Her yanıt, `end_of_stream: bool` alanını içerir +Son yanıt, `end_of_stream: True`'a sahiptir + +Bu, `AgentResponse` ve diğer akış hizmetlerinde kullanılan kalıpla eşleşir. + +### Yanıt İşleme: String Dönüşü + +Tüm mevcut araçlar aynı kalıbı izler: **argümanları bir sözlük olarak alın, gözlemi bir dize olarak döndürün**. + +| Araç | Yanıt İşleme | +|------|------------------| +| `KnowledgeQueryImpl` | `client.rag()`'i doğrudan döndürür (dize) | +| `TextCompletionImpl` | `client.question()`'i doğrudan döndürür (dize) | +| `McpToolImpl` | Bir dize döndürür veya dize değilse `json.dumps(output)` döndürür | +| `StructuredQueryImpl` | Sonucu bir dizeye dönüştürür | +| `PromptImpl` | `client.prompt()`'i doğrudan döndürür (dize) | + +Araç hizmetleri aynı sözleşmeyi izler: +Hizmet, bir dize yanıtı (gözlem) döndürür +Yanıt bir dize değilse, `json.dumps()` aracılığıyla dönüştürülür +Tanımlayıcıda herhangi bir çıkarma yapılandırması gerekmez + +Bu, tanımlayıcıyı basit tutar ve aracın uygun bir metin yanıtı döndürme sorumluluğunu hizmete bırakır. + +## Yapılandırma Kılavuzu + +Yeni bir araç hizmeti eklemek için, iki yapılandırma öğesi gereklidir: + +### 1. Araç Hizmeti Yapılandırması + +`tool-service` yapılandırma anahtarı altında saklanır. Pulsar kuyruklarını ve mevcut yapılandırma parametrelerini tanımlar. + +| Alan | Gerekli | Açıklama | +|-------|----------|-------------| +| `id` | Evet | Araç hizmeti için benzersiz tanımlayıcı | +| `request-queue` | Evet | İstekler için tam Pulsar konusu (örneğin, `non-persistent://tg/request/joke`) | +| `response-queue` | Evet | Yanıtlar için tam Pulsar konusu (örneğin, `non-persistent://tg/response/joke`) | +| `config-params` | Hayır | Hizmetin kabul ettiği yapılandırma parametrelerinin dizisi | + +Her yapılandırma parametresi şunları belirtebilir: +`name`: Parametre adı (gerekli) +`required`: Parametrenin araçlar tarafından sağlanması gerekip gerekmediği (varsayılan: false) + +Örnek: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. Araç Yapılandırması + +`tool` anahtarının altında saklanır. Aracının kullanabileceği bir aracı tanımlar. + +| Alan | Gerekli | Açıklama | +|-------|----------|-------------| +| `type` | Evet | `"tool-service"` olmalıdır | +| `name` | Evet | LLM'ye sunulan araç adı | +| `description` | Evet | Aracın ne yaptığına dair açıklama (LLM'ye gösterilir) | +| `service` | Evet | Çağrılacak araç hizmetinin kimliği | +| `arguments` | Hayır | LLM için argüman tanımları dizisi | +| *(yapılandırma parametreleri)* | Değişken | Hizmet tarafından tanımlanan herhangi bir yapılandırma parametresi | + +Her argüman aşağıdaki gibi bir şeye sahip olabilir: +`name`: Argüman adı (gerekli) +`type`: Veri türü, örneğin `"string"` (gerekli) +`description`: LLM'ye gösterilen açıklama (gerekli) + +Örnek: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### Yapılandırmayı Yükleme + +Yapılandırmaları yüklemek için `tg-put-config-item`'ı kullanın: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +Aracının ve yöneticinin, yeni yapılandırmaları alabilmesi için yeniden başlatılması gerekir. + +## Uygulama Detayları + +### Şema + +`trustgraph-base/trustgraph/schema/services/tool_service.py` içindeki istek ve yanıt türleri: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### Sunucu Tarafı: DynamicToolService + +`trustgraph-base/trustgraph/base/dynamic_tool_service.py` içindeki temel sınıf: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### İstemci Tarafı: ToolServiceImpl + +`trustgraph-flow/trustgraph/agent/react/tools.py` içindeki uygulama: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### Dosyalar + +| Dosya | Amaç | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | İstek/yanıt şemaları | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | Hizmetleri çağırmak için istemci | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | Hizmet uygulamasının temel sınıfı | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | `ToolServiceImpl` sınıfı | +| `trustgraph-flow/trustgraph/agent/react/service.py` | Yapılandırma yükleme | + +### Örnek: Şaka Hizmeti + +`trustgraph-flow/trustgraph/tool_service/joke/`'da bir örnek hizmet: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +Araç hizmeti yapılandırması: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +Araç yapılandırması: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### Geriye Dönük Uyumluluk + +Mevcut, yerleşik araç türleri, herhangi bir değişiklik olmadan çalışmaya devam etmektedir. +`tool-service`, mevcut türlerin (`knowledge-query`, `mcp-tool`, vb.) yanı sıra yeni bir araç türüdür. + +## Gelecek Planları + +### Kendini Tanımlayan Hizmetler + +Gelecekteki bir geliştirmede, hizmetlerin kendi tanımlarını yayınlamasına izin verilebilir: + +Hizmetler, başlatıldığında, bilinen bir `tool-descriptors` konusuna yayın yapar. +Aracılar abone olur ve araçları dinamik olarak kaydeder. +Yapılandırma değişiklikleri olmadan gerçek bir tak ve çalıştır imkanı sağlar. + +Bu, ilk uygulamada kapsam dışındadır. + +## Referanslar + +Mevcut araç uygulaması: `trustgraph-flow/trustgraph/agent/react/tools.py` +Araç kaydı: `trustgraph-flow/trustgraph/agent/react/service.py:105-214` +Aracı şemaları: `trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/tool-services.zh-cn.md b/docs/tech-specs/tool-services.zh-cn.md new file mode 100644 index 00000000..478a5465 --- /dev/null +++ b/docs/tech-specs/tool-services.zh-cn.md @@ -0,0 +1,479 @@ +--- +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. + +## 状态 + +已实现 + +## 概述 + +本规范定义了一种称为“工具服务”的动态可插拔代理工具的机制。 与现有的内置工具类型(`KnowledgeQueryImpl`,`McpToolImpl`等)不同,工具服务允许通过以下方式引入新的工具: + +1. 部署一个新的基于Pulsar的服务 +2. 添加一个配置描述符,该描述符告诉代理如何调用它 + +这实现了可扩展性,而无需修改核心代理响应框架。 + +## 术语 + +| 术语 | 定义 | +|------|------------| +| **内置工具** | 具有硬编码实现的现有工具类型,位于`tools.py` | +| **工具服务** | 可以作为代理工具调用的Pulsar服务,由服务描述符定义 | +| **工具** | 引用工具服务的已配置实例,暴露给代理/LLM | + +这是一个两层模型,类似于MCP工具: +MCP:MCP服务器定义工具接口 → 工具配置引用它 +工具服务:工具服务定义Pulsar接口 → 工具配置引用它 + +## 背景:现有工具 + +### 内置工具实现 + +当前,工具在`trustgraph-flow/trustgraph/agent/react/tools.py`中定义,并具有类型化的实现: + +```python +class KnowledgeQueryImpl: + async def invoke(self, question): + client = self.context("graph-rag-request") + return await client.rag(question, self.collection) +``` + +每种工具类型: +具有一个硬编码的 Pulsar 服务,它会调用该服务(例如:`graph-rag-request`) +知道要调用的客户端上的确切方法(例如:`client.rag()`) +在实现中定义了类型化的参数 + +### 工具注册 (service.py:105-214) + +工具从配置文件中加载,其中有一个 `type` 字段,它映射到实现: + +```python +if impl_id == "knowledge-query": + impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection")) +elif impl_id == "text-completion": + impl = TextCompletionImpl +# ... etc +``` + +## 架构 + +### 两层模型 + +#### 第一层:工具服务描述器 + +一个工具服务定义了 Pulsar 服务接口。它声明: +用于请求/响应的 Pulsar 队列 +它需要的来自使用它的工具的配置参数 + +```json +{ + "id": "custom-rag", + "request-queue": "non-persistent://tg/request/custom-rag", + "response-queue": "non-persistent://tg/response/custom-rag", + "config-params": [ + {"name": "collection", "required": true} + ] +} +``` + +一种不需要任何配置参数的工具服务: + +```json +{ + "id": "calculator", + "request-queue": "non-persistent://tg/request/calc", + "response-queue": "non-persistent://tg/response/calc", + "config-params": [] +} +``` + +#### 第二层:工具描述 + +一个工具引用一个工具服务,并提供: +配置参数值(满足服务的要求) +代理的工具元数据(名称、描述) +LLM 的参数定义 + +```json +{ + "type": "tool-service", + "name": "query-customers", + "description": "Query the customer knowledge base", + "service": "custom-rag", + "collection": "customers", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about customers" + } + ] +} +``` + +多个工具可以使用不同的配置来引用相同的服务: + +```json +{ + "type": "tool-service", + "name": "query-products", + "description": "Query the product knowledge base", + "service": "custom-rag", + "collection": "products", + "arguments": [ + { + "name": "question", + "type": "string", + "description": "The question to ask about products" + } + ] +} +``` + +### 请求格式 + +当一个工具被调用时,发送给工具服务的请求包括: +`user`: 来自代理的请求(多租户) +`config`: 来自工具描述的 JSON 编码的配置值 +`arguments`: 来自 LLM 的 JSON 编码的参数 + +```json +{ + "user": "alice", + "config": "{\"collection\": \"customers\"}", + "arguments": "{\"question\": \"What are the top customer complaints?\"}" +} +``` + +工具服务接收这些数据,并将其解析为字典,在 `invoke` 方法中进行处理。 + +### 通用工具服务实现 + +一个 `ToolServiceImpl` 类根据配置调用工具服务: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + self.request_queue = request_queue + self.response_queue = response_queue + self.config_values = config_values # e.g., {"collection": "customers"} + # ... + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, self.config_values, arguments) + if isinstance(response, str): + return response + else: + return json.dumps(response) +``` + +## 设计决策 + +### 双层配置模型 + +工具服务遵循类似于 MCP 工具的双层模型: + +1. **工具服务 (Tool Service)**:定义 Pulsar 服务接口(主题、所需的配置参数)。 +2. **工具 (Tool)**:引用工具服务,提供配置值,定义 LLM 参数。 + +这种分离方式允许: +一个工具服务可以被多个具有不同配置的工具使用。 +清晰区分服务接口和工具配置。 +重用服务定义。 + +### 请求映射:带外壳的透传 + +发送到工具服务的请求是一个结构化的外壳,包含: +`user`:从代理请求中传播,用于多租户。 +配置值:来自工具描述符(例如,`collection`)。 +`arguments`:LLM 提供的参数,作为字典传递。 + +代理管理器将 LLM 的响应解析为 `act.arguments`(作为字典,`agent_manager.py:117-154`)。此字典包含在请求外壳中。 + +### 模式处理:无类型 + +请求和响应使用无类型的字典。代理级别不进行任何模式验证 - 工具服务负责验证其输入。这提供了定义新服务的最大灵活性。 + +### 客户端接口:直接 Pulsar 主题 + +工具服务使用直接的 Pulsar 主题,无需配置流。工具服务描述符指定完整的队列名称: + +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [...] +} +``` + +这允许服务在任何命名空间中被托管。 + +### 错误处理:标准错误约定 + +工具服务响应遵循现有的模式约定,包含一个 `error` 字段: + +```python +@dataclass +class Error: + type: str = "" + message: str = "" +``` + +响应结构: +成功: `error` 为 `None`,响应包含结果 +错误: `error` 被填充为 `type` 和 `message` + +这符合现有服务模式(例如:`PromptResponse`,`QueryResponse`,`AgentResponse`)。 + +### 请求/响应关联 + +请求和响应使用 `id` 在 Pulsar 消息属性中进行关联: + +请求包含 `id` 在属性中:`properties={"id": id}` +响应包含相同的 `id`:`properties={"id": id}` + +这遵循代码库中使用的现有模式(例如:`agent_service.py`,`llm_service.py`)。 + +### 流式支持 + +工具服务可以返回流式响应: + +具有相同 `id` 在属性中的多个响应消息 +每个响应包含 `end_of_stream: bool` 字段 +最终响应具有 `end_of_stream: True` + +这符合 `AgentResponse` 和其他流式服务中使用的模式。 + +### 响应处理:字符串返回 + +所有现有工具都遵循相同的模式:**接收参数作为字典,将观察结果作为字符串返回**。 + +| 工具 | 响应处理 | +|------|------------------| +| `KnowledgeQueryImpl` | 直接返回 `client.rag()` (字符串) | +| `TextCompletionImpl` | 直接返回 `client.question()` (字符串) | +| `McpToolImpl` | 返回字符串,或如果不是字符串则返回 `json.dumps(output)` | +| `StructuredQueryImpl` | 将结果格式化为字符串 | +| `PromptImpl` | 直接返回 `client.prompt()` (字符串) | + +工具服务遵循相同的约定: +服务返回一个字符串响应(观察结果) +如果响应不是字符串,则通过 `json.dumps()` 进行转换 +描述符中不需要提取配置 + +这使描述符保持简单,并将责任放在服务上,使其为代理返回适当的文本响应。 + +## 配置指南 + +要添加一个新的工具服务,需要两个配置项: + +### 1. 工具服务配置 + +存储在 `tool-service` 配置键下。定义了 Pulsar 队列和可用的配置参数。 + +| 字段 | 必需 | 描述 | +|-------|----------|-------------| +| `id` | 是 | 工具服务的唯一标识符 | +| `request-queue` | 是 | 用于请求的完整 Pulsar 主题(例如:`non-persistent://tg/request/joke`) | +| `response-queue` | 是 | 用于响应的完整 Pulsar 主题(例如:`non-persistent://tg/response/joke`) | +| `config-params` | 否 | 服务接受的配置参数数组 | + +每个配置参数可以指定: +`name`: 参数名称 (必需) +`required`: 是否需要工具提供该参数 (默认: 否) + +示例: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [ + {"name": "style", "required": false} + ] +} +``` + +### 2. 工具配置 + +存储在 `tool` 配置键下。定义了代理可以使用的工具。 + +| 字段 | 必需 | 描述 | +|-------|----------|-------------| +| `type` | 是 | 必须是 `"tool-service"` | +| `name` | 是 | 暴露给 LLM 的工具名称 | +| `description` | 是 | 描述工具的功能(显示给 LLM)| +| `service` | 是 | 调用工具服务的 ID | +| `arguments` | 否 | LLM 的参数定义数组 | +| *(配置参数)* | 变化 | 服务定义的任何配置参数 | + +每个参数可以指定: +`name`:参数名称(必需) +`type`:数据类型,例如 `"string"`(必需) +`description`:显示给 LLM 的描述(必需) + +示例: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + { + "name": "topic", + "type": "string", + "description": "The topic for the joke (e.g., programming, animals, food)" + } + ] +} +``` + +### 加载配置 + +使用 `tg-put-config-item` 加载配置: + +```bash +# Load tool-service config +tg-put-config-item tool-service/joke-service < joke-service.json + +# Load tool config +tg-put-config-item tool/tell-joke < tell-joke.json +``` + +必须重启代理服务器才能加载新的配置。 + +## 实现细节 + +### 模式 + +`trustgraph-base/trustgraph/schema/services/tool_service.py` 中的请求和响应类型: + +```python +@dataclass +class ToolServiceRequest: + user: str = "" # User context for multi-tenancy + config: str = "" # JSON-encoded config values from tool descriptor + arguments: str = "" # JSON-encoded arguments from LLM + +@dataclass +class ToolServiceResponse: + error: Error | None = None + response: str = "" # String response (the observation) + end_of_stream: bool = False +``` + +### 服务器端:DynamicToolService + +基类位于 `trustgraph-base/trustgraph/base/dynamic_tool_service.py`: + +```python +class DynamicToolService(AsyncProcessor): + """Base class for implementing tool services.""" + + def __init__(self, **params): + topic = params.get("topic", default_topic) + # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic} + # Sets up Consumer and Producer + + async def invoke(self, user, config, arguments): + """Override this method to implement the tool's logic.""" + raise NotImplementedError() +``` + +### 客户端:ToolServiceImpl + +在 `trustgraph-flow/trustgraph/agent/react/tools.py` 中的实现: + +```python +class ToolServiceImpl: + def __init__(self, context, request_queue, response_queue, config_values, arguments, processor): + # Uses the provided queue paths directly + # Creates ToolServiceClient on first use + + async def invoke(self, **arguments): + client = await self._get_or_create_client() + response = await client.call(user, config_values, arguments) + return response if isinstance(response, str) else json.dumps(response) +``` + +### 文件 + +| 文件 | 目的 | +|------|---------| +| `trustgraph-base/trustgraph/schema/services/tool_service.py` | 请求/响应模式 | +| `trustgraph-base/trustgraph/base/tool_service_client.py` | 调用服务的客户端 | +| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | 服务实现的基类 | +| `trustgraph-flow/trustgraph/agent/react/tools.py` | `ToolServiceImpl` 类 | +| `trustgraph-flow/trustgraph/agent/react/service.py` | 配置加载 | + +### 示例:笑话服务 + +一个用 `trustgraph-flow/trustgraph/tool_service/joke/` 编写的示例服务: + +```python +class Processor(DynamicToolService): + async def invoke(self, user, config, arguments): + style = config.get("style", "pun") + topic = arguments.get("topic", "") + joke = pick_joke(topic, style) + return f"Hey {user}! Here's a {style} for you:\n\n{joke}" +``` + +工具服务配置: +```json +{ + "id": "joke-service", + "request-queue": "non-persistent://tg/request/joke", + "response-queue": "non-persistent://tg/response/joke", + "config-params": [{"name": "style", "required": false}] +} +``` + +工具配置: +```json +{ + "type": "tool-service", + "name": "tell-joke", + "description": "Tell a joke on a given topic", + "service": "joke-service", + "style": "pun", + "arguments": [ + {"name": "topic", "type": "string", "description": "The topic for the joke"} + ] +} +``` + +### 向后兼容性 + +现有的内置工具类型继续以不变的方式工作。 +`tool-service` 是一种新的工具类型,与现有类型(`knowledge-query`、`mcp-tool`等)并存。 + +## 未来考虑事项 + +### 自定义服务 + +未来的增强功能可能允许服务发布自己的描述: + +服务在启动时发布到已知的 `tool-descriptors` 主题。 +代理订阅并动态注册工具。 +实现了真正的即插即用,无需配置更改。 + +这超出了初始实现的范围。 + +## 参考文献 + +当前工具实现:`trustgraph-flow/trustgraph/agent/react/tools.py` +工具注册:`trustgraph-flow/trustgraph/agent/react/service.py:105-214` +代理模式:`trustgraph-base/trustgraph/schema/services/agent.py` diff --git a/docs/tech-specs/universal-decoder.ar.md b/docs/tech-specs/universal-decoder.ar.md new file mode 100644 index 00000000..37e0419a --- /dev/null +++ b/docs/tech-specs/universal-decoder.ar.md @@ -0,0 +1,419 @@ +--- +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. + +## العنوان + +جهاز فك ترميز المستندات الشامل يعمل بواسطة `unstructured` — استيراد أي تنسيق مستند شائع +من خلال خدمة واحدة مع تتبع كامل وتكامل مع أمين المكتبة، وتسجيل مواقع المصدر كبيانات وصفية لـ "رسم بياني للمعرفة" من أجل التتبع التام. + +## المشكلة + +يحتوي "TrustGraph" حاليًا على جهاز فك ترميز خاص بملفات PDF. دعم تنسيقات إضافية (DOCX, XLSX, HTML, Markdown، نص عادي، PPTX، إلخ) يتطلب +إما كتابة جهاز فك ترميز جديد لكل تنسيق أو اعتماد مكتبة استخراج عالمية. لكل تنسيق هيكل مختلف — بعضها يعتمد على الصفحات، وبعضها لا — ويجب أن يسجل سلسلة التتبع أين أصل كل جزء من النص المستخرج في المستند الأصلي. + +## الحل المقترح + +### المكتبة: `unstructured` + +استخدم `unstructured.partition.auto.partition()` التي تكتشف تلقائيًا التنسيق من نوع MIME أو امتداد الملف وتستخرج العناصر المنظمة (العنوان، النص السردي، الجدول، عنصر القائمة، إلخ). تحمل كل عنصر بيانات وصفية بما في ذلك: + +- `page_number` (للتنسيقات القائمة على الصفحات مثل PDF، PPTX) +- `element_id` (فريد لكل عنصر) +- `coordinates` (مربع إحاطة لملفات PDF) +- `text` (محتوى النص المستخرج) +- `category` (نوع العنصر: العنوان، النص السردي، الجدول، إلخ.) + +### أنواع العناصر + +تستخرج `unstructured` أنواع العناصر من المستندات. كل عنصر لديه فئة و بيانات وصفية مرتبطة: + +**عناصر النص:** +- `Title` — عناوين الأقسام +- `NarrativeText` — فقرات النص +- `ListItem` — عناصر القوائم المرقمة/المسردة +- `Header`, `Footer` — رؤوس/تذييلات الصفحات +- `FigureCaption` — تسميات للرسومات/الصور +- `Formula` — تعبيرات رياضية +- `Address`, `EmailAddress` — معلومات الاتصال +- `CodeSnippet` — كتل التعليمات البرمجية (من markdown) + +**الجداول:** +- `Table` — بيانات جدولية منظمة. توفر `unstructured` كلاً من + `element.text` (نص عادي) و `element.metadata.text_as_html` + (علامة HTML `` حتى يتمكن نموذج اللغة الكبيرة من التمييز بين الجداول والنص السردي. + +على سبيل المثال، صفحة تحتوي على عنوان وفقرة وجدول تنتج: + +``` +نظرة عامة مالية + +ارتفعت الإيرادات بنسبة 15٪ على أساس سنوي مدفوعة باعتماد المؤسسات. + + + + + +
الربعالإيراداتالنمو
Q1$12M12%
Q2$14M17%
+``` + +هذا يحافظ على هيكل الجدول من خلال التقطيع وإلى مسار الاستخراج، حيث يمكن لنموذج اللغة الكبيرة استخراج العلاقات مباشرة من الخلايا المنظمة بدلاً من تخمين محاذاة الأعمدة من المسافات. + +### معالجة الصور + +تتم استخراج الصور وتخزينها في أمين المكتبة كأوراق فرعية مع `document_type="image"` ومعرف `urn:image:{uuid}`. إنها تحصل على ثلاثيات تتبع من النوع `tg:Image`، مرتبطة بصفحتها/قسمها الأصلية عبر `prov:wasDerivedFrom`. يتم تسجيل البيانات الوصفية للصورة (الإحداثيات والأبعاد و `element_id`) في التتبع. + +**من المهم للغاية، لا يتم إخراج الصور كإخراج `TextDocument`.** يتم تخزينها فقط — ولا يتم إرسالها إلى وحدة تقسيم (chunker) أو أي مسار لمعالجة النصوص. هذا مقصود: + +1. لا يوجد مسار لمعالجة الصور بعد (دمج نموذج الرؤية هو عمل مستقبلي) +2. إرسال بيانات صورة base64 أو أجزاء من OCR إلى مسار استخراج النص سينتج عنه ثلاثيات KG (رسم بياني للمعرفة) غير صحيحة. + +كما يتم استبعاد الصور من النص المجمع للصفحة/القسم — أي عناصر `Image` يتم تخطيها بصمت عند ربط عناصر النص لصفحة/قسم. يسجل سلسلة التتبع أن الصور موجودة وأين ظهرت في المستند، بحيث يمكن لنموذج معالجة صور مستقبلي التقاطها دون إعادة استيراد المستند. + +#### عمل مستقبلي + +- توجيه الكيانات `tg:Image` إلى نموذج رؤية للوصف أو تفسير المخططات أو استخراج بيانات الرسم البياني. +- تخزين أوصاف الصور كمستندات نصية فرعية يتم إدخالها في مسار التقطيع/الاستخراج القياسي. +- ربط المعرفة المستخرجة بالصور المصدر عبر التتبع. + +### استراتيجيات الأقسام + +بالنسبة للتنسيقات القائمة على الصفحات (PDF، PPTX، XLSX)، يتم تجميع العناصر دائمًا حسب الصفحة/الشريحة/الورقة أولاً. بالنسبة للتنسيقات غير القائمة على الصفحات (DOCX، HTML، Markdown، إلخ)، يحتاج جهاز فك الترميز إلى استراتيجية لتقسيم المستند إلى أقسام. هذا قابل للتكوين في وقت التشغيل عبر `--section-strategy`. + +تعتبر كل استراتيجية وظيفة تجميع على قائمة `unstructured` للعناصر. الإخراج هو قائمة بمجموعات العناصر؛ يظل بقية المسار (تجميع النص وتخزين أمين المكتبة والتتبع وإصدار `TextDocument`) متطابقًا بغض النظر عن الاستراتيجية. + +#### `whole-document` (افتراضي) + +إخراج المستند بأكمله كقسم واحد. اسمح لوحدة تقسيم المستند (chunker) بمعالجة جميع عمليات التقسيم. + +- أبسط نهج، خط أساس جيد +- قد ينتج عنه `TextDocument` كبير جدًا للملفات الكبيرة، ولكن وحدة التقسيم تتعامل مع ذلك +- الأفضل عندما تريد أقصى قدر من السياق لكل قسم + +#### `heading` + +التقسيم عند عناصر العناوين (`Title`). كل قسم هو عنوان وجميع المحتويات حتى العنوان التالي من نفس المستوى أو أعلى. تخلق العناوين المتداخلة أقسامًا متداخلة. + +- ينتج وحدات متماسكة من الناحية الموضوعية +- يعمل بشكل جيد مع المستندات المنظمة (التقارير والكتيبات والمواصفات) +- يوفر لـ LLM الاستخراج سياق العنوان جنبًا إلى جنب مع المحتوى +- يرجع إلى `whole-document` إذا لم يتم العثور على أي عناوين + +#### `element-type` + +التقسيم عند حدوث تغيير كبير في نوع العنصر — على وجه التحديد، ابدأ قسمًا جديدًا في الانتقالات بين النص السردي والجداول. تظل العناصر المتتالية من نفس الفئة العامة (نص، نص، نص أو جدول، جدول) مجمعة. + +- يحافظ على الجداول كأقسام منفصلة +- جيد للمستندات ذات المحتوى المختلط (التقارير مع الجداول البيانية) +- يتم إعطاء الجداول اهتمام استخراج مخصص + +#### `count` + +تجميع عدد ثابت من العناصر لكل قسم. قابلة للتكوين عبر `--section-element-count` (افتراضي: 20). + +- بسيط وقابل للتنبؤ +- لا يحترم هيكل المستند +- مفيد كحل احتياطي أو للتجريب + +#### `size` + +تجميع العناصر حتى يتم الوصول إلى حد الأحرف، ثم ابدأ قسمًا جديدًا. يحترم حدود العناصر — لا يقسم في منتصف العنصر. قابلة للتكوين عبر `--section-max-size` (افتراضي: 4000 حرف). + +- ينتج أقسامًا ذات أحجام تقريبًا موحدة +- يحترم حدود العناصر (على عكس وحدة التقسيم السفلية) +- حل وسط جيد بين التحكم في الهيكل والحجم +- إذا تجاوز عنصر واحد الحد، فإنه يصبح قسمه الخاص + +#### تفاعل مع التنسيق القائم على الصفحة + +بالنسبة للتنسيقات القائمة على الصفحات، يكون تجميع الصفحة هو الأولوية دائمًا. يمكن أن تنطبق استراتيجيات القسم بشكل اختياري *داخل* صفحة إذا كانت كبيرة جدًا (على سبيل المثال، صفحة PDF تحتوي على جدول ضخم)، ويتم التحكم في ذلك بواسطة +`--section-within-pages` (افتراضي: false). عندما يكون `false`، تكون كل صفحة دائمًا قسمًا واحدًا بغض النظر عن الحجم. + +### اكتشاف التنسيق + +يحتاج جهاز فك الترميز إلى معرفة نوع MIME الخاص بالمستند لتمريره إلى `partition()` الخاصة بـ `unstructured`. هناك مساران: + +- **مسار أمين المكتبة** (`document_id` مضبوط): استرداد بيانات وصفية المستند من أمين المكتبة أولاً — وهذا يعطينا `kind` (نوع MIME) + الذي تم تسجيله في وقت الرفع. ثم استرداد محتوى المستند. + مكالمتان لأمين المكتبة، ولكن استرداد البيانات الوصفية خفيف الوزن. +- **المسار المضمن** (التوافق مع الإصدارات السابقة، `data` مضبوط): لا توجد بيانات وصفية + متاحة على الرسالة. استخدم `python-magic` لاكتشاف التنسيق + من بايت المحتوى كحل احتياطي. + +لا توجد تغييرات ضرورية في مخطط `Document` — يقوم أمين المكتبة بالفعل بتخزين نوع MIME. + +### الهندسة المعمارية + +خدمة `universal-decoder` واحدة تقوم بما يلي: + +1. تتلقى رسالة `Document` (مضمنة أو عبر مرجع أمين المكتبة) +2. إذا كان مسار أمين المكتبة: استرداد بيانات وصفية المستند (الحصول على نوع MIME)، ثم + استرداد المحتوى. إذا كان المسار المضمن: اكتشاف التنسيق من بايت المحتوى. +3. تستدعي `partition()` لاستخراج العناصر +4. تجميع العناصر: حسب الصفحة للتنسيقات القائمة على الصفحات، حسب استراتيجية القسم المحددة للتنسيقات غير القائمة على الصفحات +5. لكل صفحة/قسم: + - توليد معرف `urn:page:{uuid}` أو `urn:section:{uuid}` + - تجميع نص الصفحة: النص العادي، والجداول كـ HTML، + الصور يتم تخطيها + - حساب إزاحة الأحرف لكل عنصر داخل نص الصفحة + - حفظ في أمين المكتبة كوثيقة فرعية + - حساب ثلاثيات تتبع مع بيانات وصفية موضعية + - إرسال `TextDocument` إلى وحدة تقسيم (chunker) +6. لكل عنصر صورة: + - توليد معرف `urn:image:{uuid}` + - حفظ بيانات الصورة في أمين المكتبة كوثيقة فرعية + - حساب ثلاثيات تتبع (مخزنة فقط، ولا يتم إرسالها إلى وحدة تقسيم) + +### معالجة التنسيقات + +| التنسيق | نوع MIME | قائم على الصفحات | ملاحظات | +|---|---|---|---| +| PDF | application/pdf | نعم | تجميع حسب الصفحة | +| DOCX | application/vnd.openxmlformats... | لا | يستخدم استراتيجية القسم | +| PPTX | application/vnd.openxmlformats... | نعم | تجميع حسب الشريحة | +| XLSX/XLS | application/vnd.openxmlformats... | نعم | تجميع حسب ورقة العمل | +| HTML | text/html | لا | يستخدم استراتيجية القسم | +| Markdown | text/markdown | لا | يستخدم استراتيجية القسم | +| Plain | text/plain | لا | يستخدم استراتيجية القسم | +| CSV | text/csv | لا | يستخدم استراتيجية القسم | +| RST | text/x-rst | لا | يستخدم استراتيجية القسم | +| RTF | application/rtf | لا | يستخدم استراتيجية القسم | +| ODT | application/vnd.oasis... | لا | يستخدم استراتيجية القسم | +| TSV | text/tab-separated-values | لا | يستخدم استراتيجية القسم | + +### بيانات التتبع + +تسجل كل صفحة/قسم كيان بيانات وصفية موضعية على شكل ثلاثيات تتبع في الرسم البياني المصدر (`GRAPH_SOURCE`)، مما يتيح التتبع التام من ثلاثيات KG (رسم بياني للمعرفة) إلى مواضع المستند المصدر. + +#### الحقول الحالية (موجودة بالفعل في `provenance/triples.py`) + +- `page_number` — رقم الصفحة/الورقة/الشريحة (مرقم 1، فقط للتنسيقات القائمة على الصفحات) +- `char_offset` — إزاحة الحرف لهذه الصفحة/القسم داخل نص المستند بالكامل +- `char_length` — طول الحرف لنص هذه الصفحة/القسم + +#### حقول جديدة (قم بتوسيع `provenance/triples.py`) + +- `mime_type` — تنسيق المستند الأصلي (على سبيل المثال، `application/pdf`) +- `element_types` — قائمة `unstructured` لفئات العناصر الموجودة في هذه الصفحة/القسم (على سبيل المثال، "العنوان،النص السردي،الجدول") +- `table_count` — عدد الجداول في هذه الصفحة/القسم +- `image_count` — عدد الصور في هذه الصفحة/القسم + +يتطلب هذا بناء جملة جديد لأسماء النطاقات: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +مخطط URN للصورة: `urn:image:{uuid}` + +(`TG_MIME_TYPE` موجود بالفعل.) + +#### نوع الكيان الجديد + +بالنسبة للتنسيقات غير القائمة على الصفحات (DOCX، HTML، Markdown، إلخ) حيث يقوم جهاز فك الترميز بإخراج المستند بأكمله كقسم واحد بدلاً من التقسيم حسب الصفحة، يحصل الكيان على نوع جديد: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +هذا يميز الأقسام عن الصفحات عند الاستعلام عن التتبع: + +| الكيان | النوع | متى يتم استخدامه | +|---|---|---| +| Document | `tg:Document` | الملف الذي تم رفعه أصلاً | +| Page | `tg:Page` | تنسيقات قائمة على الصفحات (PDF، PPTX، XLSX) | +| Section | `tg:Section` | تنسيقات غير قائمة على الصفحات (DOCX، HTML، MD، إلخ) | +| Image | `tg:Image` | صور مضمنة (مخزنة، وغير معالجة) | +| Chunk | `tg:Chunk` | إخراج وحدة تقسيم المستند | +| Subgraph | `tg:Subgraph` | إخراج KG | + +يتم تعيين النوع بواسطة جهاز فك الترميز بناءً على ما إذا كان يقوم بتجميع حسب الصفحة أم أنه يصدر قسمًا كاملاً للمستند. تكتسب `provenance/triples.py` معلمة اختيارية `section` — عندما تكون `true`، يتم تصنيف الكيان على أنه `tg:Section` بدلاً من `tg:Page`. + +#### سلسلة التتبع الكاملة + +``` +ثلاثية KG + → subgraph (تتبع الاستخراج) + → chunk (char_offset، char_length داخل الصفحة) + → page/section (page_number، char_offset، char_length داخل المستند، mime_type، element_types) + → document (الملف الأصلي في أمين المكتبة) +``` + +كل رابط هو مجموعة من الثلاثيات في الرسم البياني المسمى `GRAPH_SOURCE`. + +### تكوين الخدمة + +وسيطات سطر الأوامر: + +``` +--strategy استراتيجية التقسيم: auto, hi_res, fast (افتراضي: auto) +--languages قائمة مفصولة بفواصل برموز لغة OCR (افتراضي: eng) +--section-strategy استراتيجية تجميع القسم: whole-document, heading, element-type, + count, size (افتراضي: whole-document) +--section-element-count عدد العناصر لكل قسم (افتراضي: 20) +--section-max-size الحد الأقصى لحجم القسم (بالأحرف) (افتراضي: 4000) +``` + +### التنفيذ + +خدمة `universal-decoder` واحدة تقوم بما يلي: + +1. تتلقى رسالة `Document` (مضمنة أو عبر مرجع أمين المكتبة) +2. إذا كان مسار أمين المكتبة: استرداد بيانات وصفية المستند (الحصول على نوع MIME)، ثم + استرداد المحتوى. إذا كان المسار المضمن: اكتشاف التنسيق من بايت المحتوى. +3. تستدعي `partition()` لاستخراج العناصر +4. تجميع العناصر: حسب الصفحة للتنسيقات القائمة على الصفحات، حسب استراتيجية القسم المحددة للتنسيقات غير القائمة على الصفحات +5. لكل صفحة/قسم: + - توليد معرف `urn:page:{uuid}` أو `urn:section:{uuid}` + - تجميع نص الصفحة: النص العادي، والجداول كـ HTML، + الصور يتم تخطيها + - حساب إزاحة الأحرف لكل عنصر داخل نص الصفحة + - حفظ في أمين المكتبة كوثيقة فرعية + - حساب ثلاثيات تتبع مع بيانات وصفية موضعية + - إرسال `TextDocument` إلى وحدة تقسيم (chunker) +6. لكل عنصر صورة: + - توليد معرف `urn:image:{uuid}` + - حفظ بيانات الصورة في أمين المكتبة كوثيقة فرعية + - حساب ثلاثيات تتبع (مخزنة فقط، ولا يتم إرسالها إلى وحدة تقسيم) + +### معالجة التنسيقات + +| التنسيق | نوع MIME | قائم على الصفحات | ملاحظات | +|---|---|---|---| +| PDF | application/pdf | نعم | تجميع حسب الصفحة | +| DOCX | application/vnd.openxmlformats... | لا | يستخدم استراتيجية القسم | +| PPTX | application/vnd.openxmlformats... | نعم | تجميع حسب الشريحة | +| XLSX/XLS | application/vnd.openxmlformats... | نعم | تجميع حسب ورقة العمل | +| HTML | text/html | لا | يستخدم استراتيجية القسم | +| Markdown | text/markdown | لا | يستخدم استراتيجية القسم | +| Plain | text/plain | لا | يستخدم استراتيجية القسم | +| CSV | text/csv | لا | يستخدم استراتيجية القسم | +| RST | text/x-rst | لا | يستخدم استراتيجية القسم | +| RTF | application/rtf | لا | يستخدم استراتيجية القسم | +| ODT | application/vnd.oasis... | لا | يستخدم استراتيجية القسم | +| TSV | text/tab-separated-values | لا | يستخدم استراتيجية القسم | + +### بيانات التتبع + +تسجل كل صفحة/قسم كيان بيانات وصفية موضعية على شكل ثلاثيات تتبع في الرسم البياني المصدر (`GRAPH_SOURCE`)، مما يتيح التتبع التام من ثلاثيات KG (رسم بياني للمعرفة) إلى مواضع المستند المصدر. + +#### الحقول الحالية (موجودة بالفعل في `provenance/triples.py`) + +- `page_number` — رقم الصفحة/الورقة/الشريحة (مرقم 1، فقط للتنسيقات القائمة على الصفحات) +- `char_offset` — إزاحة الحرف لهذه الصفحة/القسم داخل نص المستند بالكامل +- `char_length` — طول الحرف لنص هذه الصفحة/القسم + +#### حقول جديدة (قم بتوسيع `provenance/triples.py`) + +- `mime_type` — تنسيق المستند الأصلي (على سبيل المثال، `application/pdf`) +- `element_types` — قائمة `unstructured` لفئات العناصر الموجودة في هذه الصفحة/القسم (على سبيل المثال، "العنوان،النص السردي،الجدول") +- `table_count` — عدد الجداول في هذه الصفحة/القسم +- `image_count` — عدد الصور في هذه الصفحة/القسم + +يتطلب هذا بناء جملة جديد لأسماء النطاقات: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +مخطط URN للصورة: `urn:image:{uuid}` + +(`TG_MIME_TYPE` موجود بالفعل.) + +#### نوع الكيان الجديد + +بالنسبة للتنسيقات غير القائمة على الصفحات (DOCX، HTML، Markdown، إلخ) حيث يقوم جهاز فك الترميز بإخراج المستند بأكمله كقسم واحد بدلاً من التقسيم حسب الصفحة، يحصل الكيان على نوع جديد: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +هذا يميز الأقسام عن الصفحات عند الاستعلام عن التتبع: + +| الكيان | النوع | متى يتم استخدامه | +|---|---|---| +| Document | `tg:Document` | الملف الذي تم رفعه أصلاً | +| Page | `tg:Page` | تنسيقات قائمة على الصفحات (PDF، PPTX، XLSX) | +| Section | `tg:Section` | تنسيقات غير قائمة على الصفحات (DOCX، HTML، MD، إلخ) | +| Image | `tg:Image` | صور مضمنة (مخزنة، وغير معالجة) | +| Chunk | `tg:Chunk` | إخراج وحدة تقسيم المستند | +| Subgraph | `tg:Subgraph` | إخراج KG | + +يتم تعيين النوع بواسطة جهاز فك الترميز بناءً على ما إذا كان يقوم بتجميع حسب الصفحة أم أنه يصدر قسمًا كاملاً للمستند. تكتسب `provenance/triples.py` معلمة اختيارية `section` — عندما تكون `true`، يتم تصنيف الكيان على أنه `tg:Section` بدلاً من `tg:Page`. + +#### سلسلة التتبع الكاملة + +``` +ثلاثية KG + → subgraph (تتبع الاستخراج) + → chunk (char_offset، char_length داخل الصفحة) + → page/section (page_number، char_offset، char_length داخل المستند، mime_type، element_types) + → document (الملف الأصلي في أمين المكتبة) +``` + +كل رابط هو مجموعة من الثلاثيات في الرسم البياني المسمى `GRAPH_SOURCE`. + +### التثبيت + +تأكد من أن لديك Python 3.6+ مثبتًا. + +```bash +pip install unstructured +``` + +### الاستخدام + +```python +from unstructured.partition.auto import partition + +# مثال على ملف PDF +pdf = partition(filename="path/to/your/document.pdf") + +# مثال على ملف HTML +html = partition(filename="path/to/your/document.html") +``` + +سيقوم هذا بتقسيم المستند إلى عناصر مثل العناوين والنصوص والجداول والصور. يمكنك بعد ذلك معالجة هذه العناصر بشكل منفصل. + +### الاعتبارات + +- **الأداء:** قد يكون تقسيم المستندات الكبيرة أمرًا مكلفًا من الناحية الحسابية. ضع في اعتبارك استخدام التخزين المؤقت أو المعالجة المتوازية للمستندات الكبيرة جدًا. +- **الدقة:** دقة التقسيم تعتمد على تنسيق المستند. قد تتطلب بعض المستندات معالجة خاصة للحصول على أفضل النتائج. + +### المساهمة + +إذا كنت ترغب في المساهمة في `unstructured`، فيرجى إرسال طلب سحب. نحن نقبل المساهمات من جميع أنواع. + +### الترخيص + +`unstructured` مرخصة بموجب رخصة Apache 2.0. diff --git a/docs/tech-specs/universal-decoder.es.md b/docs/tech-specs/universal-decoder.es.md new file mode 100644 index 00000000..cc466ed2 --- /dev/null +++ b/docs/tech-specs/universal-decoder.es.md @@ -0,0 +1,404 @@ +--- +layout: default +title: "Decodificador Universal de Documentos" +parent: "Spanish (Beta)" +--- + +# Decodificador Universal 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. + +## Título + +Decodificador universal de documentos impulsado por `unstructured`: ingrese cualquier formato de documento común +a través de un servicio único con un registro completo de la procedencia y la integración de la biblioteca, +registrando las posiciones de origen como metadatos del gráfico de conocimiento para +la trazabilidad de extremo a extremo. + +## Problema + +Actualmente, TrustGraph tiene un decodificador específico para PDF. Para admitir formatos adicionales +(DOCX, XLSX, HTML, Markdown, texto plano, PPTX, etc.), es necesario +escribir un nuevo decodificador por formato o adoptar una biblioteca de extracción universal. +Cada formato tiene una estructura diferente; algunos son basados en páginas, otros no, +y la cadena de procedencia debe registrar de dónde se originó cada parte del texto extraído +en el documento original. + +## Enfoque + +### Biblioteca: `unstructured` + +Utilice `unstructured.partition.auto.partition()`, que detecta automáticamente el formato +a partir del tipo MIME o la extensión del archivo y extrae elementos estructurados +(Título, TextoNarrativo, Tabla, ElementoLista, etc.). Cada elemento lleva +metadatos que incluyen: + +`page_number` (para formatos basados en páginas como PDF, PPTX) +`element_id` (único para cada elemento) +`coordinates` (cuadro delimitador para PDF) +`text` (el contenido de texto extraído) +`category` (tipo de elemento: Título, TextoNarrativo, Tabla, etc.) + +### Tipos de Elemento + +`unstructured` extrae elementos tipados de los documentos. Cada elemento tiene +una categoría y metadatos asociados: + +**Elementos de texto:** +`Title` — encabezados de sección +`NarrativeText` — párrafos del cuerpo +`ListItem` — elementos de lista con viñetas/numerados +`Header`, `Footer` — encabezados/pies de página +`FigureCaption` — leyendas para figuras/imágenes +`Formula` — expresiones matemáticas +`Address`, `EmailAddress` — información de contacto +`CodeSnippet` — bloques de código (de Markdown) + +**Tablas:** +`Table` — datos tabulares estructurados. `unstructured` proporciona tanto + `element.text` (texto plano) como `element.metadata.text_as_html` + (HTML completo `` con filas, columnas y encabezados conservados). + Para formatos con una estructura de tabla explícita (DOCX, XLSX, HTML), + la extracción es muy fiable. Para PDF, la detección de tablas depende de + la estrategia de `hi_res` con el análisis de diseño. + +**Imágenes:** +`Image` — imágenes integradas detectadas mediante el análisis de diseño (requiere + la estrategia de `hi_res`). Con `extract_image_block_to_payload=True`, + devuelve los datos de la imagen como base64 en `element.metadata.image_base64`. + El texto OCR de la imagen está disponible en `element.text`. + +### Manejo de Tablas + +Las tablas son una salida de primera clase. Cuando el decodificador encuentra un elemento `Table`, +conserva la estructura HTML en lugar de aplanarla a texto plano. Esto proporciona +a la biblioteca de extracción LLM descendente una mejor entrada para extraer conocimiento +estructurado de los datos tabulares. + +El texto de la página/sección se ensambla de la siguiente manera: +Elementos de texto: texto plano, unido con saltos de línea +Elementos de tabla: marcado de tabla HTML de `text_as_html`, envuelto en un + marcador `
` para que el LLM pueda distinguir las tablas del texto narrativo. + +Por ejemplo, una página con un encabezado, un párrafo y una tabla produce: + +``` +Financial Overview + +Revenue grew 15% year-over-year driven by enterprise adoption. + +
+ + + +
QuarterRevenueGrowth
Q1$12M12%
Q2$14M17%
+``` + +Esto preserva la estructura de la tabla mediante la segmentación y en la +canalización de extracción, donde el LLM puede extraer relaciones directamente de +celdas estructuradas en lugar de adivinar la alineación de columnas a partir de +espacios en blanco. + +### Manejo de imágenes + +Las imágenes se extraen y se almacenan en la biblioteca como documentos +secundarios con un `document_type="image"` y un ID `urn:image:{uuid}`. Obtienen +tripletas de procedencia con el tipo `tg:Image`, vinculadas a su página/sección +principal a través de `prov:wasDerivedFrom`. Los metadatos de la imagen (coordenadas, +dimensiones, element_id) se registran en la procedencia. + +**Es crucial que las imágenes NO se emitan como salidas de TextDocument.** Se +almacenan únicamente; no se envían a la canalización de segmentación ni a ningún +proceso de texto. Esto es intencional: + +1. Todavía no existe una canalización de procesamiento de imágenes (la integración + del modelo de visión es un trabajo futuro). +2. Alimentar datos de imagen en base64 o fragmentos de OCR en la + canalización de extracción de texto produciría tripletas de KG basura. + +Las imágenes también se excluyen del texto de la página ensamblada; cualquier `Image` +elemento se omite silenciosamente al concatenar los textos de los elementos para una +página/sección. La cadena de procedencia registra que las imágenes existen y dónde +aparecieron en el documento, por lo que pueden ser recuperadas por una futura +canalización de procesamiento de imágenes sin volver a importar el documento. + +#### Trabajo futuro + +Enviar `tg:Image` entidades a un modelo de visión para descripción, + interpretación de diagramas o extracción de datos de gráficos. +Almacenar las descripciones de las imágenes como documentos de texto secundarios que se integran en + la canalización estándar de fragmentación/extracción. +Vincular el conocimiento extraído de nuevo a las imágenes de origen a través de la procedencia. + +### Estrategias de sección + +Para formatos basados en páginas (PDF, PPTX, XLSX), los elementos siempre se agrupan +por página/diapositiva/hoja primero. Para formatos no basados en páginas (DOCX, HTML, Markdown, +etc.), el decodificador necesita una estrategia para dividir el documento en +secciones. Esto se puede configurar en tiempo de ejecución a través de `--section-strategy`. + +Cada estrategia es una función de agrupación sobre la lista de `unstructured` +elementos. La salida es una lista de grupos de elementos; el resto de la +canalización (ensamblaje de texto, almacenamiento en la biblioteca, procedencia, +emisión de TextDocument) es idéntico independientemente de la estrategia. + +#### `whole-document` (predeterminado) + +Emite todo el documento como una sola sección. Permite que el +fragmentador (chunker) posterior gestione todas las divisiones. + +Enfoque más simple, buena línea de base +Puede producir un TextDocument muy grande para archivos grandes, pero el + fragmentador se encarga de eso. +Mejor cuando se desea el máximo contexto por sección. + +#### `heading` + +Divide en elementos de encabezado (`Title`). Cada sección es un encabezado más +todo el contenido hasta el siguiente encabezado de igual o mayor nivel. Los +encabezados anidados crean secciones anidadas. + +Produce unidades temáticamente coherentes. +Funciona bien para documentos estructurados (informes, manuales, especificaciones). +Proporciona al LLM de extracción el contexto del encabezado junto con el contenido. +Retrocede a `whole-document` si no se encuentran encabezados. + +#### `element-type` + +Divide cuando el tipo de elemento cambia significativamente; específicamente, +comienza una nueva sección en las transiciones entre texto narrativo y tablas. +Los elementos consecutivos de la misma categoría general (texto, texto, texto o +tabla, tabla) permanecen agrupados. + +Mantiene las tablas como secciones independientes. +Bueno para documentos con contenido mixto (informes con tablas de datos). +Las tablas reciben una atención de extracción dedicada. + +#### `count` + +Agrupa un número fijo de elementos por sección. Configurable a través de +`--section-element-count` (predeterminado: 20). + +Simple y predecible. +No respeta la estructura del documento. +Útil como alternativa o para la experimentación. + +#### `size` + +Acumula elementos hasta que se alcanza un límite de caracteres, luego comienza una +nueva sección. Respeta los límites de los elementos; nunca los divide a la mitad. +Configurable a través de `--section-max-size` (por defecto: 4000 caracteres). + +Produce tamaños de sección aproximadamente uniformes. +Respeta los límites de los elementos (a diferencia del fragmentador posterior). +Buen compromiso entre estructura y control de tamaño. +Si un solo elemento excede el límite, se convierte en su propia sección. + +#### Interacción con formatos basados en páginas + +Para formatos basados en páginas, el agrupamiento de páginas siempre tiene prioridad. +Las estrategias de sección opcionalmente se pueden aplicar *dentro* de una página si es muy +grande (por ejemplo, una página PDF con una tabla enorme), controlado por +`--section-within-pages` (por defecto: falso). Cuando es falso, cada página es +siempre una sección, independientemente del tamaño. + +### Detección de formato + +El decodificador necesita conocer el tipo MIME del documento para pasarlo a +`unstructured`'s `partition()`. Dos caminos: + +**Ruta del bibliotecario** (`document_id` configurado): primero, recupera los metadatos del documento + del bibliotecario; esto nos da el `kind` (tipo MIME) + que se registró en el momento de la carga. Luego, recupera el contenido del documento. + Dos llamadas al bibliotecario, pero la recuperación de metadatos es ligera. +**Ruta integrada** (compatibilidad con versiones anteriores, `data` configurado): no hay metadatos + disponibles en el mensaje. Usa `python-magic` para detectar el formato + a partir de los bytes del contenido como una opción alternativa. + +No se necesitan cambios en el esquema `Document`; el bibliotecario ya almacena el tipo MIME. + + +### Arquitectura + +Un único servicio `universal-decoder` que: + +1. Recibe un mensaje `Document` (en línea o a través de una referencia a la biblioteca). +2. Si la ruta es a través de la biblioteca: recupera los metadatos del documento (obtiene el tipo MIME), luego + recupera el contenido. Si la ruta es en línea: detecta el formato a partir de los bytes del contenido. +3. Llama a `partition()` para extraer los elementos. +4. Agrupa elementos: por página para formatos basados en páginas, por estrategia de sección configurada para formatos no basados en páginas. + sección. +5. Para cada página/sección: + Genera un ID `urn:page:{uuid}` o `urn:section:{uuid}` + Ensambla el texto de la página: el texto narrativo como texto plano, las tablas como HTML, + imágenes omitidas + Calcula los desplazamientos de caracteres para cada elemento dentro del texto de la página. + Guarda en el sistema de gestión de documentos como documento hijo. + Emite triples de procedencia con metadatos de posición. + Envía `TextDocument` a la siguiente etapa para la segmentación. +6. Para cada elemento de imagen: + Genera un ID `urn:image:{uuid}`. + Guarda los datos de la imagen en el sistema de gestión de documentos como documento hijo. + Emite triples de procedencia (almacenados solo, no enviados a la siguiente etapa). + +### Manejo de formatos + +| Formato | Tipo MIME | Basado en páginas | Notas | +|----------|------------------------------------|------------|--------------------------------| +| PDF | application/pdf | Sí | Agrupación por página | +| DOCX | application/vnd.openxmlformats... | No | Utiliza estrategia de secciones | +| PPTX | application/vnd.openxmlformats... | Sí | Agrupación por diapositiva | +| XLSX/XLS | application/vnd.openxmlformats... | Sí | Agrupación por hoja | +| HTML | text/html | No | Utiliza estrategia de secciones | +| Markdown | text/markdown | No | Utiliza estrategia de secciones | +| Texto plano | text/plain | No | Utiliza estrategia de secciones | +| CSV | text/csv | No | Utiliza estrategia de secciones | +| RST | text/x-rst | No | Utiliza estrategia de secciones | +| RTF | application/rtf | No | Utiliza estrategia de secciones | +| ODT | application/vnd.oasis... | No | Utiliza estrategia de secciones | +| TSV | text/tab-separated-values | No | Utiliza estrategia de secciones | + +### Metadatos de procedencia + +Cada entidad de página/sección registra metadatos de posición como metadatos de procedencia +en `GRAPH_SOURCE`, lo que permite una trazabilidad completa desde las triples del grafo de conocimiento +hasta las posiciones del documento de origen. + +#### Campos existentes (ya están en `derived_entity_triples`) + +`page_number` — número de página/hoja/diapositiva (indexado desde 1, solo para páginas) +`char_offset` — desplazamiento de caracteres de esta página/sección dentro del + texto completo del documento. +`char_length` — longitud de caracteres del texto de esta página/sección. + +#### Nuevos campos (extender `derived_entity_triples`) + +`mime_type` — formato original del documento (por ejemplo, `application/pdf`) +`element_types` — lista separada por comas de categorías de elementos `unstructured` + encontradas en esta página/sección (por ejemplo, "Título,TextoNarrativo,Tabla") +`table_count` — número de tablas en esta página/sección. +`image_count` — número de imágenes en esta página/sección. + +Estos requieren nuevos predicados del espacio de nombres TG: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +Esquema URN de imagen: `urn:image:{uuid}` + +(`TG_MIME_TYPE` ya existe.) + +#### Nuevo tipo de entidad + +Para formatos que no son de página (DOCX, HTML, Markdown, etc.) donde el decodificador +emite todo el documento como una sola unidad en lugar de dividirlo por +página, la entidad obtiene un nuevo tipo: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +Esto distingue las secciones de las páginas al consultar el origen: + +| Entidad | Tipo | Cuándo se utiliza | +|----------|-----------------------------|----------------------------------------| +| Documento | `tg:Document` | Archivo original subido | +| Página | `tg:Page` | Formatos basados en páginas (PDF, PPTX, XLSX) | +| Sección | `tg:Section` | Formatos que no son de página (DOCX, HTML, MD, etc.) | +| Imagen | `tg:Image` | Imágenes incrustadas (almacenadas, no procesadas) | +| Fragmento | `tg:Chunk` | Resultado del fragmentador | +| Subgrafo | `tg:Subgraph` | Resultado de la extracción del grafo de conocimiento | + +El tipo se establece por el decodificador según si se está agrupando por página +o emitiendo una sección de todo el documento. `derived_entity_triples` obtiene +un parámetro booleano opcional `section`; cuando es verdadero, la entidad se +clasifica como `tg:Section` en lugar de `tg:Page`. + +#### Cadena completa de origen + +``` +KG triple + → subgraph (extraction provenance) + → chunk (char_offset, char_length within page) + → page/section (page_number, char_offset, char_length within doc, mime_type, element_types) + → document (original file in librarian) +``` + +Cada enlace es un conjunto de triples en el grafo denominado `GRAPH_SOURCE`. + +### Configuración del servicio + +Argumentos de línea de comandos: + +``` +--strategy Partitioning strategy: auto, hi_res, fast (default: auto) +--languages Comma-separated OCR language codes (default: eng) +--section-strategy Section grouping: whole-document, heading, element-type, + count, size (default: whole-document) +--section-element-count Elements per section for 'count' strategy (default: 20) +--section-max-size Max chars per section for 'size' strategy (default: 4000) +--section-within-pages Apply section strategy within pages too (default: false) +``` + +Además de los argumentos estándar de `FlowProcessor` y la cola del bibliotecario. + +### Integración del flujo + +El decodificador universal ocupa la misma posición en el flujo de procesamiento +que el decodificador PDF actual: + +``` +Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ... +``` + +Se registra: +`input` consumidor (esquema de documento) +`output` productor (esquema de TextDocument) +`triples` productor (esquema de Triples) +Solicitud/respuesta del bibliotecario (para la recuperación y el almacenamiento de documentos secundarios) + +### Despliegue + +Nuevo contenedor: `trustgraph-flow-universal-decoder` +Dependencia: `unstructured[all-docs]` (incluye PDF, DOCX, PPTX, etc.) +Puede ejecutarse junto con o reemplazar el decodificador PDF existente, dependiendo de + la configuración del flujo. +El decodificador PDF existente permanece disponible para entornos donde + las dependencias de `unstructured` son demasiado pesadas. + +### ¿Qué Cambia? + +| Component | Change | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | Add `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` | +| `provenance/triples.py` | Add `mime_type`, `element_types`, `table_count`, `image_count` kwargs | +| `provenance/__init__.py` | Export new constants | +| New: `decoding/universal/` | New decoder service module | +| `setup.cfg` / `pyproject` | Add `unstructured[all-docs]` dependency | +| Docker | New container image | +| Flow definitions | Wire universal-decoder as document input | + +### What Doesn't Change + +Chunker (receives TextDocument, works as before) +Downstream extractors (receive Chunk, unchanged) +Librarian (stores child documents, unchanged) +Schema (Document, TextDocument, Chunk unchanged) +Query-time provenance (unchanged) + +## Risks + +`unstructured[all-docs]` has heavy dependencies (poppler, tesseract, + libreoffice for some formats). Container image will be larger. + Mitigation: offer a `[light]` variant without OCR/office deps. +Some formats may produce poor text extraction (scanned PDFs without + OCR, complex XLSX layouts). Mitigation: configurable `strategy` + parameter, and the existing Mistral OCR decoder remains available + for high-quality PDF OCR. +`unstructured` version updates may change element metadata. + Mitigation: pin version, test extraction quality per format. diff --git a/docs/tech-specs/universal-decoder.he.md b/docs/tech-specs/universal-decoder.he.md new file mode 100644 index 00000000..fec35734 --- /dev/null +++ b/docs/tech-specs/universal-decoder.he.md @@ -0,0 +1,404 @@ +--- +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. + +## כותרת + +מפענח מסמכים אוניברסלי המופעל על ידי `unstructured` - קליטת כל פורמט מסמך נפוץ +דרך שירות יחיד עם תיעוד מלא ושילוב עם ספרייה, תוך רישום מיקומי המקור כמטא-נתונים של גרף ידע +למעקב מקצה לקצה. + +## בעיה + + +כיום, ל-TrustGraph יש מפענח ספציפי ל-PDF. תמיכה בפורמטים נוספים (DOCX, XLSX, HTML, Markdown, טקסט רגיל, PPTX וכו') דורשת +או כתיבת מפענח חדש לכל פורמט או אימוץ ספריית חילוץ אוניברסלית. לכל פורמט יש מבנה שונה - חלקם מבוססי דפים, וחלקם לא - +ושרשרת התיעוד חייבת לתעד מאיפה בכל מסמך המקורי הגיע כל פיסת טקסט שחולצה. + +## גישה +לתעד כל פיסת טקסט שחולצה ולציין את מקורה. + +## גישה + +### ספריה: `unstructured` + +השתמשו ב-`unstructured.partition.auto.partition()` שמזהה אוטומטית את הפורמט +מחלק סוג MIME או סיומת קובץ ומחלץ אלמנטים מובנים +(כותרת, טקסט, טבלה, פריט רשימה, וכו'). כל אלמנט נושא +מטא-דאטה, כולל: + +`page_number` (עבור פורמטים מבוססי דפים כמו PDF, PPTX) +`element_id` (ייחודי לכל אלמנט) +`coordinates` (מלבן תוחם עבור קבצי PDF) +`text` (תוכן הטקסט שנחלץ) +`category` (סוג האלמנט: כותרת, טקסט, טבלה, וכו') + +### סוגי אלמנטים + +`unstructured` מחלץ אלמנטים מסוגים שונים ממסמכים. לכל אלמנט יש +קטגוריה ומטא-דאטה נלווים: + +**אלמנטים טקסטואליים:** +`Title` — כותרות סעיפים +`NarrativeText` — פסקאות גוף הטקסט +`ListItem` — פריטי רשימות (ממוספרות או עם נקודות) +`Header`, `Footer` — כותרות/שוליים של עמודים +`FigureCaption` — כיתובים עבור תמונות/איורים +`Formula` — ביטויים מתמטיים +`Address`, `EmailAddress` — פרטי יצירת קשר +`CodeSnippet` — בלוקי קוד (מתוך markdown) + +**טבלאות:** +`Table` - נתונים טבלאיים מובנים. `unstructured` מספק גם + `element.text` (טקסט רגיל) וגם `element.metadata.text_as_html` + (HTML מלא `` עם שורות, עמודות וכותרות שמורות). + עבור פורמטים עם מבנה טבלה מפורש (DOCX, XLSX, HTML), החילוץ אמין מאוד. עבור קבצי PDF, זיהוי טבלאות תלוי ב + ⟦CODE_0⟧. For PDFs, table detection depends on ⟦CODE_0⟧. + האסטרטגיה של `hi_res` עם ניתוח פריסה. + +**תמונות:** +`Image` — זיהוי תמונות מוטמעות באמצעות ניתוח פריסה (דורש + `hi_res` אסטרטגיה). עם `extract_image_block_to_payload=True`, + מחזיר את נתוני התמונה כ-base64 ב-`element.metadata.image_base64`. + טקסט OCR מהתמונה זמין ב-`element.text`. + +### טיפול בטבלאות + +טבלאות הן פלט ברמה ראשונה. כאשר המפענח נתקל באלמנט `Table`, +הוא שומר על מבנה ה-HTML במקום לשטח לטקסט +רגיל. זה מספק למחלץ ה-LLM במורד קלט טוב בהרבה +לשליפת ידע מובנה מנתונים טבלאיים. + +הטקסט של העמוד/הקטע מורכב באופן הבא: +אלמנטי טקסט: טקסט רגיל, המחוברים בשורות חדשות +אלמנטי טבלה: תגי HTML של טבלה מ-`text_as_html`, עטופים ב- + `
` סימון כך שה-LLM יכול להבחין בין טבלאות לבין טקסט + +לדוגמה, עמוד עם כותרת, פסקה וטבלה מייצר: + +``` +Financial Overview + +Revenue grew 15% year-over-year driven by enterprise adoption. + +
+ + + +
QuarterRevenueGrowth
Q1$12M12%
Q2$14M17%
+``` + +זה שומר על מבנה הטבלאות באמצעות חלוקה לחלקים וליחידת העיבוד +(pipeline), כאשר מודל השפה הגדול (LLM) יכול לחלץ קשרים ישירות מתוך +תאים מובנים, ולא לנחש את יישור העמודות על סמך +רווחים. + +### טיפול בתמונות + +תמונות מחולצות ונשמרות בספרייה כמסמכים משניים +עם `document_type="image"` ו-`urn:image:{uuid}` מזהה. הן מקבלות +טריפלים של מקור (provenance) מסוג `tg:Image`, המקושרים לעמוד/קטע +הראשי שלהן דרך `prov:wasDerivedFrom`. מטא-נתונים של תמונה (קואורדינטות, +מידות, element_id) נרשמים במקור. + +**חשוב מאוד: תמונות אינן משודרות כפלט של מסמך טקסט (TextDocument).** הן +נשמרות בלבד - אינן נשלחות כלפי מטה ליחידת החלוקה (chunker) או לכל +תהליך עיבוד טקסט. זה נעשה בכוונה: + +1. אין עדיין תהליך עיבוד תמונות (שילוב מודל ראייה הוא עבודה + עתידית) +2. העברת נתוני תמונה בפורמט base64 או פיסות OCR ליחידת החילוץ + של טקסט תייצר טריפלים של גרף ידע (KG) לא מועילים. + +תמונות גם אינן נכללות בטקסט המורכב של העמוד - כל `Image` +אלמנטים מתעלמים כאשר מחברים טקסט של אלמנטים עבור +עמוד/קטע. שרשרת המקור (provenance) רושמת שתמונות קיימות ואיפה +הן הופיעו במסמך, כך שניתן יהיה לאסוף אותן על ידי תהליך +עיבוד תמונות עתידי מבלי להכניס מחדש את המסמך. + +#### עבודה עתידית + +להעביר `tg:Image` ישויות למודל ראייה לצורך תיאור, + פרשנות דיאגרמות או חילוץ נתוני טבלה. +לשמור תיאורי תמונה כמסמכי טקסט משניים שמוזנים + לתוך תהליך החלוקה/חילוץ הסטנדרטי. +לקשר ידע מחולץ בחזרה לתמונות המקוריות דרך מקור. + +### אסטרטגיות סעיפים + +עבור פורמטים מבוססי עמודים (PDF, PPTX, XLSX), אלמנטים תמיד מקובצים +לפי עמוד/שקופית/גיליון. עבור פורמטים שאינם מבוססי עמודים (DOCX, HTML, Markdown, +וכו'), למפענח יש אסטרטגיה לחלוקת המסמך לקטעים. +זה מוגדר בזמן ריצה באמצעות `--section-strategy`. + +כל אסטרטגיה היא פונקציית קיבוץ על רשימת `unstructured` +אלמנטים. הפלט הוא רשימה של קבוצות אלמנטים; שאר +התהליך (הרכבת טקסט, אחסון בספרייה, מקור, פלט של מסמך טקסט +(TextDocument)) זהים ללא קשר לאסטרטגיה. + +#### `whole-document` (ברירת מחדל) + +להוציא את כל המסמך כקטע יחיד. לאפשר ליחידת החלוקה +(chunker) לטפל בכל החלוקה. + +גישה פשוטה, קו בסיס טוב +עלול לייצר מסמך טקסט גדול מאוד עבור קבצים גדולים, אך יחידת החלוקה + מטפלת בכך +הטוב ביותר כאשר רוצים הקשר מקסימלי לכל קטע + +#### `heading` + +לחלק בנקודות כותרת (`Title`). כל קטע הוא כותרת וכל +התוכן עד הכותרת הבאה באותו רמה או ברמה גבוהה יותר. +כותרות מקוננות יוצרות קטעים מקוננים. + +מייצר יחידות בעלות קוהרנטיות נושאית +עובד היטב עבור מסמכים מובנים (דוחות, מדריכים, מפרטים) +מספק למודל השפה הגדול (LLM) שמבצע חילוץ הקשר של כותרת יחד עם תוכן +חוזר ל-`whole-document` אם לא נמצאות כותרות + +#### `element-type` + +לחלק כאשר סוג האלמנט משתנה באופן משמעותי - ספציפית, +להתחיל קטע חדש במעברים בין טקסט נרטיבי לטבלאות. +אלמנטים עוקבים מאותה קטגוריה רחבה (טקסט, טקסט, טקסט או +טבלה, טבלה) נשארים מקובצים. + +שומר על טבלאות כקטעים עצמאיים +טוב עבור מסמכים עם תוכן מעורב (דוחות עם טבלאות נתונים) +לטבלאות ניתנת תשומת לב ייעודית לחילוץ + +#### `count` + +לקבץ מספר קבוע של אלמנטים לכל קטע. ניתן להגדרה באמצעות +`--section-element-count` (ברירת מחדל: 20). + +פשוט וצפוי +אינו מכבד את מבנה המסמך +שימושי כברירת מחדל או לניסויים + +#### `size` + +צבירה של אלמנטים עד להגעה למגבלת תווים, ולאחר מכן התחלה של +סעיף חדש. מכבד גבולות של אלמנטים - לעולם לא מפצל באמצע אלמנט. +ניתן להגדיר באמצעות `--section-max-size` (ברירת מחדל: 4000 תווים). + +מייצר גדלי חלקים אחידים בערך. +מכבד גבולות של אלמנטים (בניגוד למחלק החלקים הבא). +פשרה טובה בין מבנה לשליטה בגודל. +אם אלמנט בודד חורג מהמגבלה, הוא הופך לחלק בפני עצמו. + +#### פורמט מבוסס עמודים - אינטראקציה + +עבור פורמטים מבוססי עמודים, קיבוץ העמודים תמיד מקבל עדיפות. +ניתן ליישם אסטרטגיות סעיפים באופן אופציונלי *בתוך* עמוד אם הוא גדול מאוד +(לדוגמה, עמוד PDF עם טבלה עצומה), תוך שליטה באמצעות +`--section-within-pages` (ברירת מחדל: false). כאשר הערך הוא false, כל עמוד הוא +תמיד סעיף אחד ללא קשר לגודלו. + +### זיהוי פורמט + +ה-דקודר צריך לדעת את סוג ה-mime של המסמך כדי להעביר ל- +`unstructured`'s `partition()`. שני מסלולים: + +**נתיב הספרן** (הגדרת `document_id`): אחזור מטא-דאטה של המסמך + מהספרן תחילה - זה נותן לנו את ה-`kind` (סוג ה-mime) + שנרשם בזמן ההעלאה. לאחר מכן, אחזור תוכן המסמך. + שני שימושים בספרן, אך אחזור המטא-דאטה קל משקל. +**נתיב מקוון** (תאימות לאחור, הגדרת `data`): אין מטא-דאטה + זמין בהודעה. השתמש ב-`python-magic` כדי לזהות את הפורמט + מתוך בייטי התוכן כפתרון חלופי. + +אין צורך בשינויים בסכימה של `Document` - הספרן כבר מאחסן את סוג ה-mime. + + +### ארכיטקטורה + +שירות `universal-decoder` יחיד שמבצע: + +1. מקבל הודעה `Document` (בשורת הטקסט או דרך הפניה לספרייה). +2. אם הנתיב הוא דרך הספרייה: שולף מטא-דאטה של המסמך (מקבל את סוג ה-mime), ואז + שולף את התוכן. אם הנתיב הוא בתוך הטקסט: מזהה את הפורמט מהבייטים של התוכן. +3. קורא לפונקציה `partition()` כדי לחלץ אלמנטים. +4. קיבוץ אלמנטים: לפי עמוד עבור פורמטים מבוססי עמוד, לפי אסטרטגיית סעיפים מוגדרת עבור פורמטים שאינם מבוססי עמוד. + סעיף. +5. עבור כל עמוד/קטע: + מייצר מזהה `urn:page:{uuid}` או `urn:section:{uuid}` + מרכיב את תוכן העמוד: טקסט נרטיבי כטקסט רגיל, טבלאות כ-HTML, + תמונות מדלגות + מחשב את ההיסטים של כל תו בתוך הטקסט של העמוד. + שומר ל-librarian כמסמך משני. + משדר משולשי מוצא עם מטא-נתונים מיקומיים. + שולח `TextDocument` במורד הזרם לצורך חלוקה. +6. עבור כל אלמנט תמונה: + מייצר מזהה `urn:image:{uuid}`. + שומר את נתוני התמונה ל-librarian כמסמך משני. + משדר משולשי מוצא (נשמרים בלבד, לא נשלחים במורד הזרם). + +### טיפול בפורמטים + +| פורמט | סוג MIME | מבוסס דפים | הערות | +|----------|------------------------------------|------------|--------------------------------| +| PDF | application/pdf | כן | קיבוץ לפי דף | +| DOCX | application/vnd.openxmlformats... | לא | משתמש באסטרטגיית סעיפים | +| PPTX | application/vnd.openxmlformats... | כן | קיבוץ לפי שקופית | +| XLSX/XLS | application/vnd.openxmlformats... | כן | קיבוץ לפי גיליון | +| HTML | text/html | לא | משתמש באסטרטגיית סעיפים | +| Markdown | text/markdown | לא | משתמש באסטרטגיית סעיפים | +| Plain | text/plain | לא | משתמש באסטרטגיית סעיפים | +| CSV | text/csv | לא | משתמש באסטרטגיית סעיפים | +| RST | text/x-rst | לא | משתמש באסטרטגיית סעיפים | +| RTF | application/rtf | לא | משתמש באסטרטגיית סעיפים | +| ODT | application/vnd.oasis... | לא | משתמש באסטרטגיית סעיפים | +| TSV | text/tab-separated-values | לא | משתמש באסטרטגיית סעיפים | + +### מטא-דאטה של מקור + +כל ישות דף/סעיף מתעדת מטא-דאטה מיקום כמשולשים של מקור +ב-`GRAPH_SOURCE`, המאפשר מעקב מלא ממשולשים של גרף ידע +חזרה למיקומי המסמך המקורי. + +#### שדות קיימים (כבר ב-`derived_entity_triples`) + +`page_number` — מספר דף/גיליון/שקופית (מתחיל מ-1, רק עבור פורמטים מבוססי דפים) +`char_offset` — ההיסט של התווים של דף/סעיף זה בתוך + הטקסט המלא של המסמך +`char_length` — אורך התווים של הטקסט של דף/סעיף זה + +#### שדות חדשים (הרחבה של `derived_entity_triples`) + +`mime_type` — פורמט המסמך המקורי (לדוגמה, `application/pdf`) +`element_types` — רשימה מופרדת בפסיקים של קטגוריות `unstructured` + שנמצאו בדף/סעיף זה (לדוגמה, "כותרת,טקסט נרטיבי,טבלה") +`table_count` — מספר הטבלאות בדף/סעיף זה +`image_count` — מספר התמונות בדף/סעיף זה + +אלה דורשים טווח שמות של טריגרים חדשים: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +סכימת URN לתמונות: `urn:image:{uuid}` + +(`TG_MIME_TYPE` כבר קיים.) + +#### סוג ישות חדש + +עבור פורמטים שאינם דפי אינטרנט (DOCX, HTML, Markdown, וכו') שבהם +ה-דקודר משדר את כל המסמך כיחידה אחת ולא מחלק אותו לדפים, +הישות מקבלת סוג חדש: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +זה מבחין בין חלקים לדפים בעת שאילתת מקור: + +| ישות | סוג | מתי משמש | +|----------|-----------------------------|----------------------------------------| +| מסמך | `tg:Document` | קובץ שהועלה במקור | +| דף | `tg:Page` | פורמטים מבוססי דפים (PDF, PPTX, XLSX) | +| חלק | `tg:Section` | פורמטים שאינם מבוססי דפים (DOCX, HTML, MD, וכו') | +| תמונה | `tg:Image` | תמונות מוטמעות (מאוחסנות, לא מעובדות) | +| מקטע | `tg:Chunk` | פלט של מפריד מקטעים | +| תת-גרף | `tg:Subgraph` | פלט של חילוץ גרף ידע | + +הסוג נקבע על ידי ה-decoder בהתאם לשאלה האם הוא מקבץ לפי עמוד +או פולט חלק שלם מהמסמך. `derived_entity_triples` מקבל +פרמטר בוליאני אופציונלי `section` — כאשר הוא מוגדר כ-true, היישות היא +הוקלד כ-`tg:Section` במקום `tg:Page`. + +#### שרשרת מקור מלאה + +``` +KG triple + → subgraph (extraction provenance) + → chunk (char_offset, char_length within page) + → page/section (page_number, char_offset, char_length within doc, mime_type, element_types) + → document (original file in librarian) +``` + +כל קישור הוא קבוצה של שלשות בגרף המכונה `GRAPH_SOURCE`. + +### תצורת שירות + +ארגומנטים של שורת הפקודה: + +``` +--strategy Partitioning strategy: auto, hi_res, fast (default: auto) +--languages Comma-separated OCR language codes (default: eng) +--section-strategy Section grouping: whole-document, heading, element-type, + count, size (default: whole-document) +--section-element-count Elements per section for 'count' strategy (default: 20) +--section-max-size Max chars per section for 'size' strategy (default: 4000) +--section-within-pages Apply section strategy within pages too (default: false) +``` + +בנוסף ל-`FlowProcessor` הסטנדרטי ולטיעוני תור המאפשרים גישה לספרייה. + +### אינטגרציה של זרימת העבודה + +ה-דקודר האוניברסלי תופס את אותו מיקום בזרימת העיבוד +כמו ה-דקודר של PDF הנוכחי: + +``` +Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ... +``` + +זה רושם: +`input` צרכן (סכימת מסמכים) +`output` מפיק (סכימת TextDocument) +`triples` מפיק (סכימת Triples) +בקשה/תגובה של ספרן (לשליפה ואחסון של מסמכים משניים) + +### פריסה + +קונטיינר חדש: `trustgraph-flow-universal-decoder` +תלות: `unstructured[all-docs]` (כולל PDF, DOCX, PPTX, וכו') +ניתן להפעיל לצד או להחליף את מפענח ה-PDF הקיים, בהתאם + לתצורת זרימת העבודה +מפענח ה-PDF הקיים נשאר זמין עבור סביבות שבהן + התלויות של `unstructured` כבדות מדי + +### מה משתנה + +| רכיב | שינוי | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | הוספת `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` | +| `provenance/triples.py` | הוספת ארגומנטים `mime_type`, `element_types`, `table_count`, `image_count` (kwargs) | +| `provenance/__init__.py` | ייצוא קבועים חדשים | +| חדש: `decoding/universal/` | מודול שירות פענוח חדש | +| `setup.cfg` / `pyproject` | הוספת תלות `unstructured[all-docs]` | +| Docker | תמונת קונטיינר חדשה | +| הגדרות זרימה | חיבור universal-decoder כקלט מסמך | + +### מה שלא משתנה + +Chunker (מקבל TextDocument, פועל כרגיל) +מודולים לחילוץ מידע (מקבלים Chunk, ללא שינוי) +Librarian (מאחסן מסמכים משניים, ללא שינוי) +Schema (Document, TextDocument, Chunk ללא שינוי) +מקור מידע בזמן שאילתה (ללא שינוי) + +## סיכונים + +ל-`unstructured[all-docs]` יש תלות רבה (poppler, tesseract, + libreoffice עבור פורמטים מסוימים). תמונת המכולה תהיה גדולה יותר. + פתרון אפשרי: להציע גרסה של `[light]` ללא תלות ב-OCR/office. +פורמטים מסוימים עשויים לייצר חילוץ טקסט באיכות ירודה (קבצי PDF מסרוקים ללא + OCR, פריסות מורכבות של קבצי XLSX). אמצעי מניעה: פרמטר הניתן להגדרה `strategy`. + ומפענח ה-OCR של Mistral הקיים זמין + עבור OCR באיכות גבוהה של קבצי PDF. +עדכוני גרסה של `unstructured` עשויים לשנות מטא-נתונים של אלמנטים. + אמצעי מניעה: קביעת גרסה, בדיקת איכות החילוץ עבור כל פורמט. diff --git a/docs/tech-specs/universal-decoder.hi.md b/docs/tech-specs/universal-decoder.hi.md new file mode 100644 index 00000000..fcea589e --- /dev/null +++ b/docs/tech-specs/universal-decoder.hi.md @@ -0,0 +1,404 @@ +--- +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. + +## शीर्षक + +यूनिवर्सल डॉक्यूमेंट डिकोडर जो `unstructured` द्वारा संचालित है — किसी भी सामान्य +डॉक्यूमेंट फॉर्मेट को एक ही सेवा के माध्यम से संसाधित करें, जिसमें पूर्ण उत्पत्ति और लाइब्रेरियन +एकीकरण शामिल है, जो स्रोत स्थितियों को ज्ञान ग्राफ मेटाडेटा के रूप में रिकॉर्ड करता है ताकि +एंड-टू-एंड पता लगाया जा सके। + +## समस्या + +वर्तमान में ट्रस्टग्राफ में एक पीडीएफ-विशिष्ट डिकोडर है। अतिरिक्त +फॉर्मेट (DOCX, XLSX, HTML, Markdown, प्लेन टेक्स्ट, PPTX, आदि) का समर्थन करने के लिए +या तो प्रत्येक फॉर्मेट के लिए एक नया डिकोडर लिखना होगा या एक सार्वभौमिक निष्कर्षण +लाइब्रेरी को अपनाना होगा। प्रत्येक फॉर्मेट की संरचना अलग होती है — कुछ पृष्ठ-आधारित होते हैं, कुछ +नहीं होते हैं — और निष्कर्षित पाठ के प्रत्येक टुकड़े की उत्पत्ति मूल +डॉक्यूमेंट में कहां से हुई, इसे उत्पत्ति श्रृंखला में रिकॉर्ड किया जाना चाहिए। + +## दृष्टिकोण + +### लाइब्रेरी: `unstructured` + +`unstructured.partition.auto.partition()` का उपयोग करें जो फॉर्मेट को स्वचालित रूप से पहचानता है +mime टाइप या फ़ाइल एक्सटेंशन से और संरचित तत्वों को निकालता है +(शीर्षक, वर्णनात्मक पाठ, तालिका, सूची आइटम, आदि)। प्रत्येक तत्व में +मेटाडेटा शामिल है: + +`page_number` (पीडीएफ, पीपीटीएक्स जैसे पृष्ठ-आधारित फॉर्मेट के लिए) +`element_id` (प्रत्येक तत्व के लिए अद्वितीय) +`coordinates` (पीडीएफ के लिए बाउंडिंग बॉक्स) +`text` (निष्कर्षित पाठ सामग्री) +`category` (तत्व प्रकार: शीर्षक, वर्णनात्मक पाठ, तालिका, आदि) + +### तत्व प्रकार + +`unstructured` डॉक्यूमेंट से टाइप किए गए तत्वों को निकालता है। प्रत्येक तत्व में +एक श्रेणी और संबंधित मेटाडेटा होता है: + +**पाठ तत्व:** +`Title` — अनुभाग शीर्षक +`NarrativeText` — पैराग्राफ +`ListItem` — बुलेट/क्रमांकित सूची आइटम +`Header`, `Footer` — पृष्ठ हेडर/फुटर +`FigureCaption` — चित्रों/छवियों के लिए कैप्शन +`Formula` — गणितीय व्यंजक +`Address`, `EmailAddress` — संपर्क जानकारी +`CodeSnippet` — कोड ब्लॉक (मार्कडाउन से) + +**तालिकाएँ:** +`Table` — संरचित सारणीबद्ध डेटा। `unstructured` दोनों प्रदान करता है + `element.text` (सादा पाठ) और `element.metadata.text_as_html` + (पंक्तियों, स्तंभों और शीर्षकों को संरक्षित करते हुए पूर्ण HTML ``)। + DOCX, XLSX, HTML जैसे स्पष्ट तालिका संरचना वाले फॉर्मेट के लिए, + निष्कर्षण अत्यधिक विश्वसनीय है। पीडीएफ के लिए, तालिका का पता लगाना + लेआउट विश्लेषण के साथ `hi_res` रणनीति पर निर्भर करता है। + +**छवियाँ:** +`Image` — लेआउट विश्लेषण के माध्यम से पता लगाई गई एम्बेडेड छवियां (आवश्यक + `hi_res` रणनीति)। `extract_image_block_to_payload=True` के साथ, + छवि डेटा को `element.metadata.image_base64` में base64 के रूप में लौटाता है। + छवि से OCR पाठ `element.text` में उपलब्ध है। + +### तालिका हैंडलिंग + +तालिकाओं को एक प्राथमिक आउटपुट माना जाता है। जब डिकोडर एक `Table` +तत्व का सामना करता है, तो यह सादे पाठ में समतल करने के बजाय HTML संरचना को संरक्षित करता है। +यह डाउनस्ट्रीम एलएलएम निष्कर्षण को सारणीबद्ध डेटा से संरचित ज्ञान निकालने के लिए +बहुत बेहतर इनपुट देता है। + +पृष्ठ/अनुभाग पाठ को इस प्रकार जोड़ा जाता है: +पाठ तत्व: सादा पाठ, नई पंक्तियों के साथ जोड़ा गया +तालिका तत्व: `text_as_html` से HTML तालिका मार्कअप, एक + `
` मार्कर में लपेटा गया ताकि एलएलएम तालिकाओं को वर्णनात्मक +पाठ से अलग कर सके। +उदाहरण के लिए, एक शीर्षक, पैराग्राफ और तालिका वाला पृष्ठ इस प्रकार होगा: + +``` +Financial Overview + +Revenue grew 15% year-over-year driven by enterprise adoption. + +
+ + + +
QuarterRevenueGrowth
Q1$12M12%
Q2$14M17%
+``` + +यह चंकिंग के माध्यम से तालिका संरचना को संरक्षित करता है और निष्कर्षण +पाइपलाइन में, जहां एलएलएम सीधे संरचित कोशिकाओं से संबंधों को निकाल सकता है, +कॉलम संरेखण का अनुमान लगाने के बजाय खाली स्थान से। + + +### छवि प्रबंधन + +छवियों को लाइब्रेरियन में चाइल्ड दस्तावेज़ों के रूप में निकाला और संग्रहीत किया जाता है +`document_type="image"` और एक `urn:image:{uuid}` आईडी के साथ। उन्हें +प्रकार `tg:Image` के साथ प्रामाणिकता ट्रिपल मिलते हैं, जो उनके मूल +पृष्ठ/अनुभाग से `prov:wasDerivedFrom` के माध्यम से जुड़े होते हैं। छवि मेटाडेटा (निर्देशांक, +आयाम, तत्व_आईडी) को प्रामाणिकता में दर्ज किया जाता है। + +**महत्वपूर्ण रूप से, छवियों को टेक्स्टडॉक्यूमेंट आउटपुट के रूप में उत्सर्जित नहीं किया जाता है।** वे +केवल संग्रहीत होते हैं - चंकर या किसी भी टेक्स्ट प्रोसेसिंग +पाइपलाइन में नीचे की ओर नहीं भेजे जाते हैं। यह जानबूझकर है: + +1. अभी तक कोई छवि प्रसंस्करण पाइपलाइन नहीं है (विज़न मॉडल एकीकरण + भविष्य का कार्य है) +2. आधार64 छवि डेटा या ओसीआर टुकड़ों को टेक्स्ट निष्कर्षण + पाइपलाइन में फीड करने से कचरा केजी ट्रिपल उत्पन्न होंगे + +छवियों को असेंबल किए गए पृष्ठ टेक्स्ट से भी बाहर रखा गया है - कोई भी `Image` +तत्व एक पृष्ठ/अनुभाग के लिए तत्व टेक्स्ट को संयोजित करते समय चुपचाप छोड़ दिए जाते हैं। प्रामाणिकता श्रृंखला में दर्ज किया गया है कि छवियां मौजूद हैं और वे दस्तावेज़ में कहां दिखाई दीं, ताकि उन्हें भविष्य के +पृष्ठ/अनुभाग। उत्पत्ति श्रृंखला में दर्ज है कि चित्र मौजूद हैं और वे कहाँ स्थित हैं। +छवि प्रसंस्करण पाइपलाइन द्वारा दस्तावेज़ को फिर से संसाधित किए बिना प्राप्त किया जा सके। + + +#### भविष्य का कार्य + +`tg:Image` संस्थाओं को विवरण, + आरेख व्याख्या या चार्ट डेटा निष्कर्षण के लिए एक विज़न मॉडल में रूट करें +छवि विवरण को टेक्स्ट चाइल्ड दस्तावेज़ों के रूप में संग्रहीत करें जो + मानक चंकिंग/निष्कर्षण पाइपलाइन में फीड करते हैं +निकाले गए ज्ञान को प्रामाणिकता के माध्यम से स्रोत छवियों से लिंक करें + +### अनुभाग रणनीतियाँ + +पृष्ठ-आधारित प्रारूपों (पीडीएफ, पीपीटीएक्स, एक्सएलएसएक्स) के लिए, तत्वों को हमेशा +पहले पृष्ठ/स्लाइड/शीट द्वारा समूहीकृत किया जाता है। गैर-पृष्ठ प्रारूपों (डीओसीएक्स, एचटीएमएल, मार्कडाउन, +आदि) के लिए, डिकोडर को दस्तावेज़ को अनुभागों में विभाजित करने के लिए एक रणनीति की आवश्यकता होती है। यह ⟦CODE_0⟧ के माध्यम से रनटाइम पर कॉन्फ़िगर करने योग्य है। +अनुभाग। यह `--section-strategy` के माध्यम से रनटाइम पर कॉन्फ़िगर किया जा सकता है। + +प्रत्येक रणनीति `unstructured` तत्वों की सूची पर एक समूहीकरण फ़ंक्शन है। आउटपुट तत्वों के समूहों की एक सूची है; बाकी +तत्व। आउटपुट तत्वों के समूहों की एक सूची है; बाकी का +पाइपलाइन (टेक्स्ट असेंबली, लाइब्रेरियन स्टोरेज, प्रामाणिकता, टेक्स्टडॉक्यूमेंट +उत्सर्जन) रणनीति की परवाह किए बिना समान है। + +#### `whole-document` (डिफ़ॉल्ट) + +पूरे दस्तावेज़ को एक ही अनुभाग के रूप में उत्सर्जित करें। डाउनस्ट्रीम +चंकर को सभी विभाजन को संभालने दें। + +सबसे सरल दृष्टिकोण, अच्छा आधार रेखा +बड़ी फ़ाइलों के लिए बहुत बड़ा टेक्स्टडॉक्यूमेंट उत्पन्न कर सकता है, लेकिन चंकर + इसे संभालता है +जब आप प्रति अनुभाग अधिकतम संदर्भ चाहते हैं तो सबसे अच्छा + +#### `heading` + +शीर्षलेख तत्वों (`Title`) पर विभाजित करें। प्रत्येक अनुभाग एक शीर्षलेख प्लस +सभी सामग्री है जब तक कि समान या उच्च स्तर का अगला शीर्षलेख न हो। नेस्टेड +शीर्षलेख नेस्टेड अनुभाग बनाते हैं। + +विषयगत रूप से सुसंगत इकाइयाँ उत्पन्न करता है +संरचित दस्तावेज़ों (रिपोर्ट, मैनुअल, विनिर्देश) के लिए अच्छा काम करता है +निष्कर्षण एलएलएम को सामग्री के साथ शीर्षलेख संदर्भ देता है +यदि कोई शीर्षलेख नहीं मिला है तो `whole-document` पर वापस आ जाता है + +#### `element-type` + +जब तत्व प्रकार में महत्वपूर्ण परिवर्तन होता है तो विभाजित करें - विशेष रूप से, +वर्णनात्मक पाठ और तालिकाओं के बीच संक्रमण पर एक नया अनुभाग शुरू करें। लगातार +समान व्यापक श्रेणी (पाठ, पाठ, पाठ या +तालिका, तालिका) के तत्व एक साथ समूहीकृत रहते हैं। + +तालिकाओं को स्टैंडअलोन अनुभागों के रूप में रखता है +मिश्रित सामग्री वाले दस्तावेज़ों (डेटा तालिकाओं वाली रिपोर्ट) के लिए अच्छा है +तालिकाओं को समर्पित निष्कर्षण ध्यान मिलता है + +#### `count` + +तत्वों की एक निश्चित संख्या को प्रति अनुभाग समूहीकृत करें। ⟦CODE_0⟧ के माध्यम से कॉन्फ़िगर करने योग्य (डिफ़ॉल्ट: 20)। +`--section-element-count` (डिफ़ॉल्ट: 20)। + +सरल और अनुमानित +दस्तावेज़ संरचना का सम्मान नहीं करता है +प्रयोग के लिए एक फ़ॉलबैक या उपयोगी + +#### `size` + +तत्वों को तब तक जमा करें जब तक कि एक वर्ण सीमा तक न पहुँच जाए, फिर एक नया अनुभाग शुरू करें। तत्वों की सीमाओं का सम्मान करता है - कभी भी किसी तत्व के बीच में विभाजन नहीं करता है। +नए अनुभाग। तत्वों की सीमाओं का सम्मान करता है - कभी भी किसी तत्व के बीच में विभाजन नहीं करता है। +`--section-max-size` के माध्यम से कॉन्फ़िगर किया जा सकता है (डिफ़ॉल्ट: 4000 अक्षर)। + +लगभग समान खंड आकार उत्पन्न करता है। +तत्वों की सीमाओं का सम्मान करता है (डाउनस्ट्रीम चंकर के विपरीत)। +संरचना और आकार नियंत्रण के बीच एक अच्छा समझौता। +यदि कोई एकल तत्व सीमा से अधिक है, तो वह अपने आप में एक खंड बन जाता है। + +#### पृष्ठ-आधारित प्रारूप इंटरैक्शन + +पृष्ठ-आधारित स्वरूपों के लिए, पृष्ठ समूहीकरण हमेशा प्राथमिकता लेता है। +अनुभाग रणनीतियों को वैकल्पिक रूप से एक पृष्ठ के *अंदर* लागू किया जा सकता है यदि वह बहुत बड़ा है (उदाहरण के लिए, एक बहुत बड़े तालिका वाला पीडीएफ पृष्ठ), जिसे द्वारा नियंत्रित किया जाता है। +बड़ा (उदाहरण के लिए, एक पीडीएफ पृष्ठ जिसमें एक बहुत बड़ा तालिका है), जिसे नियंत्रित किया जाता है। +`--section-within-pages` (डिफ़ॉल्ट: गलत)। जब गलत होता है, तो प्रत्येक पृष्ठ का +आकार की परवाह किए बिना हमेशा एक ही खंड होता है। + +### प्रारूप का पता लगाना + +डीकोडर को दस्तावेज़ के एमआईएमई प्रकार के बारे में पता होना चाहिए ताकि इसे आगे बढ़ाया जा सके। +`unstructured` का `partition()`। दो रास्ते: + +**लाइब्रेरियन पथ** (`document_id` सेट): दस्तावेज़ मेटाडेटा प्राप्त करें। + सबसे पहले लाइब्रेरियन से जानकारी प्राप्त करें - यह हमें `kind` (मिम टाइप) देता है। + जो अपलोड के समय दर्ज किया गया था। फिर दस्तावेज़ सामग्री प्राप्त करें। + दो लाइब्रेरियन कॉल, लेकिन मेटाडेटा प्राप्त करना आसान है। +**इनलाइन पथ** (पिछला संगतता, `data` सेट): संदेश पर कोई मेटाडेटा उपलब्ध नहीं है। + प्रारूप का पता लगाने के लिए `python-magic` का उपयोग करें। + सामग्री बाइट्स से एक वैकल्पिक विधि के रूप में। + +`Document` स्कीमा में कोई बदलाव आवश्यक नहीं है - लाइब्रेरियन पहले से ही MIME प्रकार संग्रहीत करता है। + + +### वास्तुकला + +एक एकल `universal-decoder` सेवा जो: + +1. एक `Document` संदेश प्राप्त होता है (इनलाइन या लाइब्रेरियन संदर्भ के माध्यम से)। +2. यदि लाइब्रेरियन पथ है: दस्तावेज़ मेटाडेटा प्राप्त करें (मिम प्रकार प्राप्त करें), फिर + सामग्री प्राप्त करें। यदि इनलाइन पथ है: सामग्री बाइट्स से प्रारूप का पता लगाएं। +3. तत्वों को निकालने के लिए `partition()` को कॉल करता है। +4. तत्वों को समूहीकृत करता है: पृष्ठ-आधारित प्रारूपों के लिए पृष्ठ द्वारा, गैर-पृष्ठ प्रारूपों के लिए कॉन्फ़िगर किए गए + अनुभाग रणनीति द्वारा। +5. प्रत्येक पृष्ठ/अनुभाग के लिए: + एक `urn:page:{uuid}` या `urn:section:{uuid}` आईडी उत्पन्न करता है। + पृष्ठ पाठ को असेंबल करता है: वर्णनात्मक पाठ को सादे पाठ के रूप में, तालिकाओं को HTML के रूप में, + छवियों को छोड़ दिया जाता है। + पृष्ठ पाठ के भीतर प्रत्येक तत्व के लिए वर्ण अद्ययनों की गणना करता है। + लाइब्रेरियन में एक चाइल्ड दस्तावेज़ के रूप में सहेजता है। + स्थिति संबंधी मेटाडेटा के साथ प्रामाणिकता ट्रिपल उत्सर्जित करता है। + टुकड़ों में विभाजित करने के लिए `TextDocument` को आगे भेजता है। +6. प्रत्येक छवि तत्व के लिए: + एक `urn:image:{uuid}` आईडी उत्पन्न करता है। + छवि डेटा को लाइब्रेरियन में एक चाइल्ड दस्तावेज़ के रूप में सहेजता है। + प्रामाणिकता ट्रिपल उत्सर्जित करता है (केवल संग्रहीत, आगे नहीं भेजा गया)। + +### प्रारूप प्रबंधन + +| प्रारूप | MIME प्रकार | पृष्ठ-आधारित | नोट्स | +|----------|------------------------------------|------------|--------------------------------| +| PDF | application/pdf | हाँ | प्रति-पृष्ठ समूहीकरण | +| DOCX | application/vnd.openxmlformats... | नहीं | अनुभाग रणनीति का उपयोग करता है | +| PPTX | application/vnd.openxmlformats... | हाँ | प्रति-स्लाइड समूहीकरण | +| XLSX/XLS | application/vnd.openxmlformats... | हाँ | प्रति-शीट समूहीकरण | +| HTML | text/html | नहीं | अनुभाग रणनीति का उपयोग करता है | +| Markdown | text/markdown | नहीं | अनुभाग रणनीति का उपयोग करता है | +| सादा | text/plain | नहीं | अनुभाग रणनीति का उपयोग करता है | +| CSV | text/csv | नहीं | अनुभाग रणनीति का उपयोग करता है | +| RST | text/x-rst | नहीं | अनुभाग रणनीति का उपयोग करता है | +| RTF | application/rtf | नहीं | अनुभाग रणनीति का उपयोग करता है | +| ODT | application/vnd.oasis... | नहीं | अनुभाग रणनीति का उपयोग करता है | +| TSV | text/tab-separated-values | नहीं | अनुभाग रणनीति का उपयोग करता है | + +### उत्पत्ति मेटाडेटा + +प्रत्येक पृष्ठ/अनुभाग इकाई, प्रामाणिकता के रूप में स्थिति संबंधी मेटाडेटा को रिकॉर्ड करती है। +`GRAPH_SOURCE` में ट्रिपल, जो नॉलेज ग्राफ (KG) ट्रिपल से स्रोत दस्तावेज़ की स्थिति तक पूर्ण पता लगाने की क्षमता प्रदान करते हैं। + + +#### मौजूदा फ़ील्ड (पहले से ही `derived_entity_triples` में) + +`page_number` — पृष्ठ/शीट/स्लाइड संख्या (1 से शुरू, केवल पृष्ठ-आधारित) +`char_offset` — इस पृष्ठ/खंड के भीतर का वर्ण ऑफ़सेट। + पूर्ण दस्तावेज़ पाठ +`char_length` — इस पृष्ठ/खंड के पाठ की वर्ण संख्या + +#### नए फ़ील्ड (`derived_entity_triples` का विस्तार करें) + +`mime_type` — मूल दस्तावेज़ का प्रारूप (उदाहरण के लिए, `application/pdf`) +`element_types` — `unstructured` तत्वों की अल्पविराम-विभाजित सूची + इस पृष्ठ/अनुभाग में पाए गए श्रेणियाँ (उदाहरण के लिए, "शीर्षक, वर्णनात्मक पाठ, तालिका") +`table_count` — इस पृष्ठ/अनुभाग में तालिकाओं की संख्या +`image_count` — इस पृष्ठ/अनुभाग में छवियों की संख्या + +इनके लिए नए टीजी नेमस्पेस विधेयकों की आवश्यकता है: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +इमेज यूआरएन योजना: `urn:image:{uuid}` + +(`TG_MIME_TYPE` पहले से मौजूद है।) + +#### नया इकाई प्रकार + +गैर-पेज प्रारूपों (DOCX, HTML, Markdown, आदि) के लिए जहां डिकोडर +पूरे दस्तावेज़ को एक इकाई के रूप में उत्सर्जित करता है, न कि पृष्ठों में विभाजित करके, +इकाई को एक नया प्रकार मिलता है: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +यह अनुभागों को पृष्ठों से अलग करता है जब मूल जानकारी प्राप्त करने के लिए क्वेरी की जाती है: + +| इकाई | प्रकार | उपयोग कब | +|---|---|---| +| दस्तावेज़ | `tg:Document` | मूल अपलोड की गई फ़ाइल | +| पृष्ठ | `tg:Page` | पृष्ठ-आधारित प्रारूप (पीडीएफ, पीपीटीएक्स, एक्सएलएसएक्स) | +| अनुभाग | `tg:Section` | गैर-पृष्ठ प्रारूप (डीओएक्स, एचटीएमएल, एमडी, आदि) | +| छवि | `tg:Image` | एम्बेडेड छवियां (संग्रहित, संसाधित नहीं) | +| भाग | `tg:Chunk` | चंकर का आउटपुट | +| उपग्राफ | `tg:Subgraph` | केजी निष्कर्षण आउटपुट | + +प्रकार को डिकोडर द्वारा यह निर्धारित किया जाता है कि यह पृष्ठ द्वारा समूहीकृत है या पूरे दस्तावेज़ अनुभाग को उत्सर्जित कर रहा है। ⟦CODE_0⟧ प्राप्त होता है। +या पूरे दस्तावेज़ अनुभाग को उत्सर्जित कर रहा है। `derived_entity_triples` प्राप्त होता है। +एक वैकल्पिक `section` बूलियन पैरामीटर - जब सत्य होता है, तो इकाई को +`tg:Section` के रूप में टाइप किया जाता है, `tg:Page` के बजाय। + +#### पूर्ण उत्पत्ति श्रृंखला + +``` +KG triple + → subgraph (extraction provenance) + → chunk (char_offset, char_length within page) + → page/section (page_number, char_offset, char_length within doc, mime_type, element_types) + → document (original file in librarian) +``` + +प्रत्येक लिंक, `GRAPH_SOURCE` नामक ग्राफ में ट्रिपल के एक सेट का प्रतिनिधित्व करता है। + +### सेवा कॉन्फ़िगरेशन + +कमांड-लाइन तर्क: + +``` +--strategy Partitioning strategy: auto, hi_res, fast (default: auto) +--languages Comma-separated OCR language codes (default: eng) +--section-strategy Section grouping: whole-document, heading, element-type, + count, size (default: whole-document) +--section-element-count Elements per section for 'count' strategy (default: 20) +--section-max-size Max chars per section for 'size' strategy (default: 4000) +--section-within-pages Apply section strategy within pages too (default: false) +``` + +साथ ही मानक `FlowProcessor` और लाइब्रेरियन क्यू तर्क। + +### फ्लो इंटीग्रेशन (प्रवाह एकीकरण) + +सार्वभौमिक डिकोडर प्रसंस्करण प्रवाह में उसी स्थिति पर होता है +जैसा कि वर्तमान पीडीएफ डिकोडर: + +``` +Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ... +``` + +यह पंजीकृत करता है: +`input` उपभोक्ता (दस्तावेज़ स्कीमा) +`output` उत्पादक (टेक्स्टडॉक्यूमेंट स्कीमा) +`triples` उत्पादक (ट्रिपल्स स्कीमा) +लाइब्रेरियन अनुरोध/प्रतिक्रिया (फ़ेच और चाइल्ड दस्तावेज़ भंडारण के लिए) + +### परिनियोजन + +नया कंटेनर: `trustgraph-flow-universal-decoder` +निर्भरता: `unstructured[all-docs]` (इसमें पीडीएफ, डॉक्स, पीपीटीएक्स, आदि शामिल हैं) +यह मौजूदा पीडीएफ डिकोडर के साथ समानांतर रूप से चल सकता है या उसकी जगह ले सकता है, यह इस बात पर निर्भर करता है। + प्रवाह विन्यास +मौजूदा पीडीएफ डिकोडर उन वातावरणों में भी उपलब्ध रहेगा जहाँ + `unstructured` निर्भरताएँ बहुत अधिक हैं + +### क्या बदलाव + +| घटक (Component) | परिवर्तन (Change) | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` जोड़ें (Add `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT`) | +| `provenance/triples.py` | `mime_type`, `element_types`, `table_count`, `image_count` kwargs जोड़ें (Add `mime_type`, `element_types`, `table_count`, `image_count` kwargs) | +| `provenance/__init__.py` | नए स्थिरांकों को निर्यात करें (Export new constants) | +| नया: `decoding/universal/` | नया डिकोडर सेवा मॉड्यूल (New decoder service module) | +| `setup.cfg` / `pyproject` | `unstructured[all-docs]` निर्भरता जोड़ें (Add `unstructured[all-docs]` dependency) | +| डॉकर (Docker) | नया कंटेनर इमेज (New container image) | +| फ्लो परिभाषाएँ (Flow definitions) | यूनिवर्सल-डिकोडर को दस्तावेज़ इनपुट के रूप में उपयोग करें (Wire universal-decoder as document input) | + +### क्या नहीं बदलता (What Doesn't Change) + +चंकर (टेक्स्टडॉक्यूमेंट प्राप्त करता है, पहले की तरह काम करता है) +डाउनस्ट्रीम एक्सट्रैक्टर (चंक प्राप्त करते हैं, अपरिवर्तित) +लाइब्रेरियन (चाइल्ड डॉक्यूमेंट्स को संग्रहीत करता है, अपरिवर्तित) +स्कीमा (डॉक्यूमेंट, टेक्स्टडॉक्यूमेंट, चंक अपरिवर्तित) +क्वेरी-टाइम प्रोवेनेंस (अपरिवर्तित) + +## जोखिम + +`unstructured[all-docs]` में भारी निर्भरताएँ हैं (पोप्लर, टेसेरैक्ट, + लिब्रेऑफिस कुछ प्रारूपों के लिए)। कंटेनर इमेज का आकार बड़ा होगा। + निवारण: ओसीआर/ऑफिस निर्भरताओं के बिना `[light]` का एक संस्करण प्रदान करें। +कुछ प्रारूपों से खराब टेक्स्ट निष्कर्षण हो सकता है (बिना ओसीआर वाले स्कैन किए गए पीडीएफ)। + ओसीआर, जटिल एक्सेल (XLSX) लेआउट)। निवारण: कॉन्फ़िगर करने योग्य `strategy` + पैरामीटर, और मौजूदा मिस्ट्रल ओसीआर डिकोडर अभी भी उपलब्ध है। + उच्च-गुणवत्ता वाले पीडीएफ ओसीआर के लिए। +`unstructured` संस्करण अपडेट से तत्व मेटाडेटा में परिवर्तन हो सकता है। + निवारण: संस्करण को स्थिर करें, प्रत्येक प्रारूप के लिए निष्कर्षण गुणवत्ता का परीक्षण करें। diff --git a/docs/tech-specs/universal-decoder.md b/docs/tech-specs/universal-decoder.md index 3b451628..eda1cac3 100644 --- a/docs/tech-specs/universal-decoder.md +++ b/docs/tech-specs/universal-decoder.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Universal Document Decoder" +parent: "Tech Specs" +--- + # Universal Document Decoder ## Headline diff --git a/docs/tech-specs/universal-decoder.pt.md b/docs/tech-specs/universal-decoder.pt.md new file mode 100644 index 00000000..2342b6cd --- /dev/null +++ b/docs/tech-specs/universal-decoder.pt.md @@ -0,0 +1,404 @@ +--- +layout: default +title: "Decodificador Universal de Documentos" +parent: "Portuguese (Beta)" +--- + +# Decodificador Universal 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. + +## Título + +Decodificador universal de documentos alimentado por `unstructured` — ingira qualquer formato de documento comum +através de um único serviço com total rastreabilidade e integração com o sistema de gerenciamento de informações, +registrando as posições de origem como metadados de gráfico de conhecimento para +rastreabilidade de ponta a ponta. + +## Problema + +Atualmente, o TrustGraph possui um decodificador específico para PDF. Suportar formatos adicionais +(DOCX, XLSX, HTML, Markdown, texto simples, PPTX, etc.) requer +ou a escrita de um novo decodificador para cada formato ou a adoção de uma biblioteca de extração universal. +Cada formato tem uma estrutura diferente — alguns são baseados em páginas, outros não — e a cadeia de rastreabilidade +deve registrar de onde em cada documento original cada trecho de texto extraído se originou. + + +## Abordagem + +### Biblioteca: `unstructured` + +Utilize `unstructured.partition.auto.partition()`, que detecta automaticamente o formato +a partir do tipo MIME ou da extensão do arquivo e extrai elementos estruturados +(Título, TextoNarrativo, Tabela, ItemDeLista, etc.). Cada elemento carrega +metadados, incluindo: + +`page_number` (para formatos baseados em páginas, como PDF, PPTX) +`element_id` (único para cada elemento) +`coordinates` (caixa delimitadora para PDFs) +`text` (o conteúdo de texto extraído) +`category` (tipo de elemento: Título, TextoNarrativo, Tabela, etc.) + +### Tipos de Elementos + +`unstructured` extrai elementos tipados de documentos. Cada elemento tem +uma categoria e metadados associados: + +**Elementos de texto:** +`Title` — títulos de seções +`NarrativeText` — parágrafos do corpo do texto +`ListItem` — itens de listas (com marcadores/numerados) +`Header`, `Footer` — cabeçalhos/rodapés de página +`FigureCaption` — legendas para figuras/imagens +`Formula` — expressões matemáticas +`Address`, `EmailAddress` — informações de contato +`CodeSnippet` — blocos de código (do Markdown) + +**Tabelas:** +`Table` — dados tabulares estruturados. `unstructured` fornece ambos + `element.text` (texto simples) e `element.metadata.text_as_html` + (HTML completo `` com linhas, colunas e cabeçalhos preservados). + Para formatos com estrutura de tabela explícita (DOCX, XLSX, HTML), a + extração é altamente confiável. Para PDFs, a detecção de tabelas depende da + estratégia `hi_res` com análise de layout. + +**Imagens:** +`Image` — imagens incorporadas detectadas por meio de análise de layout (requer + `hi_res` estratégia). Com `extract_image_block_to_payload=True`, + retorna os dados da imagem como base64 em `element.metadata.image_base64`. + O texto OCR da imagem está disponível em `element.text`. + +### Tratamento de Tabelas + +Tabelas são um tipo de saída de primeira classe. Quando o decodificador encontra um elemento `Table`, +ele preserva a estrutura HTML em vez de converter para +texto simples. Isso fornece ao extrator LLM downstream uma entrada muito melhor +para extrair conhecimento estruturado de dados tabulares. + +O texto da página/seção é montado da seguinte forma: +Elementos de texto: texto simples, unidos por quebras de linha +Elementos de tabela: marcação de tabela HTML de `text_as_html`, envolvida em um + marcador `
` para que o LLM possa distinguir tabelas de texto narrativo + +Por exemplo, uma página com um título, um parágrafo e uma tabela produz: + +``` +Financial Overview + +Revenue grew 15% year-over-year driven by enterprise adoption. + +
+ + + +
QuarterRevenueGrowth
Q1$12M12%
Q2$14M17%
+``` + +Isso preserva a estrutura da tabela por meio da divisão em partes e no processo de extração +pipeline, onde o LLM pode extrair relacionamentos diretamente de +células estruturadas, em vez de adivinhar o alinhamento das colunas a partir de +espaços em branco. + +### Tratamento de Imagens + +As imagens são extraídas e armazenadas no sistema como documentos filhos +com `document_type="image"` e um ID `urn:image:{uuid}`. Elas recebem +triplas de procedência com o tipo `tg:Image`, vinculadas à página/seção pai +por meio de `prov:wasDerivedFrom`. Os metadados da imagem (coordenadas, +dimensões, element_id) são registrados na procedência. + +**É crucial que as imagens NÃO sejam emitidas como saídas do tipo TextDocument.** Elas são +armazenadas apenas — não enviadas para o chunker ou qualquer processo de texto +pipeline. Isso é intencional: + +1. Ainda não existe um pipeline de processamento de imagens (a integração do modelo de visão + é um trabalho futuro). +2. Alimentar dados de imagem em base64 ou fragmentos de OCR no processo de extração de texto + produziria triplas de grafo de conhecimento (KG) inúteis. + +As imagens também são excluídas do texto da página montado — quaisquer elementos `Image` +são ignorados silenciosamente ao concatenar os textos dos elementos para uma +página/seção. A cadeia de procedência registra que as imagens existem e onde +elas apareceram no documento, para que possam ser recuperadas por um futuro +pipeline de processamento de imagens sem reingestão do documento. + +#### Trabalho futuro + +Direcionar entidades `tg:Image` para um modelo de visão para descrição, + interpretação de diagramas ou extração de dados de gráficos. +Armazenar descrições de imagens como documentos de texto filhos que são alimentados no + processo de divisão/extração padrão. +Vincular o conhecimento extraído de volta às imagens de origem por meio da procedência. + +### Estratégias de Seção + +Para formatos baseados em páginas (PDF, PPTX, XLSX), os elementos são sempre agrupados +por página/slide/planilha primeiro. Para formatos não baseados em páginas (DOCX, HTML, Markdown, +etc.), o decodificador precisa de uma estratégia para dividir o documento em +seções. Isso é configurável em tempo de execução por meio de `--section-strategy`. + +Cada estratégia é uma função de agrupamento sobre a lista de `unstructured` +elementos. A saída é uma lista de grupos de elementos; o restante do +pipeline (montagem de texto, armazenamento do bibliotecário, rastreabilidade, emissão de TextDocument +) é idêntico, independentemente da estratégia. + +#### `whole-document` (padrão) + +Emita todo o documento como uma única seção. Deixe que o +divisor de blocos (chunker) lide com toda a divisão. + +Abordagem mais simples, bom ponto de partida +Pode produzir um TextDocument muito grande para arquivos grandes, mas o divisor de blocos + lida com isso +Melhor quando você deseja o máximo de contexto por seção + +#### `heading` + +Divida nos elementos de cabeçalho (`Title`). Cada seção é um cabeçalho mais +todo o conteúdo até o próximo cabeçalho de nível igual ou superior. Cabeçalhos +aninhados criam seções aninhadas. + +Produz unidades coerentes em termos de tópico +Funciona bem para documentos estruturados (relatórios, manuais, especificações) +Fornece ao LLM de extração o contexto do cabeçalho junto com o conteúdo +Recua para `whole-document` se nenhum cabeçalho for encontrado + +#### `element-type` + +Divida quando o tipo de elemento muda significativamente — especificamente, +comece uma nova seção nas transições entre texto narrativo e tabelas. +Elementos consecutivos da mesma categoria ampla (texto, texto, texto ou +tabela, tabela) permanecem agrupados. + +Mantém as tabelas como seções independentes +Bom para documentos com conteúdo misto (relatórios com tabelas de dados) +As tabelas recebem atenção especial na extração + +#### `count` + +Agrupe um número fixo de elementos por seção. Configurável via +`--section-element-count` (padrão: 20). + +Simples e previsível +Não respeita a estrutura do documento +Útil como uma opção de fallback ou para experimentação + +#### `size` + +Acumula elementos até que um limite de caracteres seja atingido, então inicia uma +nova seção. Respeita os limites dos elementos — nunca divide no meio de um elemento. +Configurável via `--section-max-size` (padrão: 4000 caracteres). + +Produz tamanhos de seção aproximadamente uniformes +Respeita os limites dos elementos (ao contrário do "chunker" subsequente) +Bom compromisso entre estrutura e controle de tamanho +Se um único elemento exceder o limite, ele se torna sua própria seção + +#### Interação com formatos baseados em página + +Para formatos baseados em página, o agrupamento de páginas sempre tem prioridade. +As estratégias de seção podem ser aplicadas opcionalmente *dentro* de uma página se ela for muito +grande (por exemplo, uma página PDF com uma tabela enorme), controlado por +`--section-within-pages` (padrão: falso). Quando falso, cada página é +sempre uma seção, independentemente do tamanho. + +### Detecção de Formato + +O decodificador precisa saber o tipo MIME do documento para passar para +`unstructured`'s `partition()`. Dois caminhos: + +**Caminho do "Librarian"** (`document_id` definido): busca os metadados do documento + do "librarian" primeiro — isso nos dá o `kind` (tipo MIME) + que foi registrado no momento do upload. Em seguida, busca o conteúdo do documento. + Duas chamadas ao "librarian", mas a busca de metadados é leve. +**Caminho "inline"** (compatibilidade com versões anteriores, `data` definido): sem metadados + disponíveis na mensagem. Use `python-magic` para detectar o formato + a partir dos bytes do conteúdo como uma alternativa. + +Não são necessárias alterações no esquema `Document` — o bibliotecário já armazena o tipo MIME. + + +### Arquitetura + +Um único serviço `universal-decoder` que: + +1. Recebe uma mensagem `Document` (inline ou via referência ao bibliotecário). +2. Se o caminho for o do bibliotecário: busca os metadados do documento (obtém o tipo MIME), então + busca o conteúdo. Se o caminho for inline: detecta o formato a partir dos bytes do conteúdo. +3. Chama `partition()` para extrair os elementos. +4. Agrupa elementos: por página para formatos baseados em página, por estratégia de seção configurada para formatos não baseados em página. + seção. +5. Para cada página/seção: + Gera um ID `urn:page:{uuid}` ou `urn:section:{uuid}` + Monta o texto da página: narrativa como texto simples, tabelas como HTML, + imagens ignoradas + Calcula os deslocamentos de caracteres para cada elemento dentro do texto da página. + Salva no "librarian" como documento filho. + Emite triplas de procedência com metadados posicionais. + Envia `TextDocument` para o processo de divisão em partes (chunking). +6. Para cada elemento de imagem: + Gera um ID `urn:image:{uuid}`. + Salva os dados da imagem no "librarian" como documento filho. + Emite triplas de procedência (armazenadas apenas, não enviadas para o processo de divisão em partes). + +### Manipulação de Formato + +| Formato | Tipo MIME | Baseado em Página | Notas | +|----------|------------------------------------|------------|--------------------------------| +| PDF | application/pdf | Sim | Agrupamento por página | +| DOCX | application/vnd.openxmlformats... | Não | Usa estratégia de seção | +| PPTX | application/vnd.openxmlformats... | Sim | Agrupamento por slide | +| XLSX/XLS | application/vnd.openxmlformats... | Sim | Agrupamento por planilha | +| HTML | text/html | Não | Usa estratégia de seção | +| Markdown | text/markdown | Não | Usa estratégia de seção | +| Texto Simples | text/plain | Não | Usa estratégia de seção | +| CSV | text/csv | Não | Usa estratégia de seção | +| RST | text/x-rst | Não | Usa estratégia de seção | +| RTF | application/rtf | Não | Usa estratégia de seção | +| ODT | application/vnd.oasis... | Não | Usa estratégia de seção | +| TSV | text/tab-separated-values | Não | Usa estratégia de seção | + +### Metadados de Proveniência + +Cada entidade de página/seção registra metadados de posição como triplas de proveniência +em `GRAPH_SOURCE`, permitindo rastreabilidade completa desde as triplas do grafo +até as posições no documento de origem. + +#### Campos existentes (já em `derived_entity_triples`) + +`page_number` — número da página/planilha/slide (indexado a partir de 1, apenas para documentos baseados em página) +`char_offset` — deslocamento de caractere desta página/seção dentro do + texto completo do documento +`char_length` — comprimento do caractere do texto desta página/seção + +#### Novos campos (extender `derived_entity_triples`) + +`mime_type` — formato original do documento (por exemplo, `application/pdf`) +`element_types` — lista separada por vírgula de categorias de `unstructured` + encontradas nesta página/seção (por exemplo, "Título,TextoNarrativo,Tabela") +`table_count` — número de tabelas nesta página/seção +`image_count` — número de imagens nesta página/seção + +Estes requerem novos predicados do namespace TG: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +Esquema URN de imagem: `urn:image:{uuid}` + +(`TG_MIME_TYPE` já existe.) + +#### Novo tipo de entidade + +Para formatos não paginados (DOCX, HTML, Markdown, etc.) onde o decodificador +emite todo o documento como uma única unidade em vez de dividi-lo por +página, a entidade recebe um novo tipo: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +Isso distingue seções de páginas ao consultar a procedência: + +| Entidade | Tipo | Quando usado | +|----------|-----------------------------|----------------------------------------| +| Documento | `tg:Document` | Arquivo original carregado | +| Página | `tg:Page` | Formatos baseados em páginas (PDF, PPTX, XLSX) | +| Seção | `tg:Section` | Formatos não baseados em páginas (DOCX, HTML, MD, etc.) | +| Imagem | `tg:Image` | Imagens incorporadas (armazenadas, não processadas) | +| Trecho | `tg:Chunk` | Saída do processador de trechos | +| Subgrafo | `tg:Subgraph` | Saída da extração de grafo de conhecimento | + +O tipo é definido pelo decodificador com base em se está agrupando por página +ou emitindo uma seção de documento inteiro. `derived_entity_triples` recebe +um parâmetro booleano opcional `section` — quando verdadeiro, a entidade é +classificada como `tg:Section` em vez de `tg:Page`. + +#### Cadeia completa de procedência + +``` +KG triple + → subgraph (extraction provenance) + → chunk (char_offset, char_length within page) + → page/section (page_number, char_offset, char_length within doc, mime_type, element_types) + → document (original file in librarian) +``` + +Cada link é um conjunto de triplas no grafo nomeado `GRAPH_SOURCE`. + +### Configuração do Serviço + +Argumentos de linha de comando: + +``` +--strategy Partitioning strategy: auto, hi_res, fast (default: auto) +--languages Comma-separated OCR language codes (default: eng) +--section-strategy Section grouping: whole-document, heading, element-type, + count, size (default: whole-document) +--section-element-count Elements per section for 'count' strategy (default: 20) +--section-max-size Max chars per section for 'size' strategy (default: 4000) +--section-within-pages Apply section strategy within pages too (default: false) +``` + +Além dos argumentos padrão `FlowProcessor` e da fila de bibliotecários. + +### Integração de Fluxo + +O decodificador universal ocupa a mesma posição no fluxo de processamento +que o decodificador PDF atual: + +``` +Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ... +``` + +Ele registra: +`input` consumidor (schema de documento) +`output` produtor (schema TextDocument) +`triples` produtor (schema de triplas) +Requisição/resposta do bibliotecário (para busca e armazenamento de documentos filhos) + +### Implantação + +Novo contêiner: `trustgraph-flow-universal-decoder` +Dependência: `unstructured[all-docs]` (inclui PDF, DOCX, PPTX, etc.) +Pode ser executado em conjunto ou substituir o decodificador PDF existente, dependendo + da configuração do fluxo +O decodificador PDF existente permanece disponível para ambientes onde + as dependências `unstructured` são muito pesadas + +### O que Muda + +| Componento | Alteração | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | Adicionar `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` | +| `provenance/triples.py` | Adicionar argumentos `mime_type`, `element_types`, `table_count`, `image_count` (kwargs) | +| `provenance/__init__.py` | Exportar novas constantes | +| Novo: `decoding/universal/` | Novo módulo de serviço de decodificação | +| `setup.cfg` / `pyproject` | Adicionar dependência `unstructured[all-docs]` | +| Docker | Nova imagem de contêiner | +| Definições de fluxo | Conectar universal-decoder como entrada de documento | + +### O que não muda + +Chunker (recebe TextDocument, funciona como antes) +Extratores subsequentes (recebem Chunk, inalterados) +Librarian (armazena documentos filhos, inalterado) +Schema (Document, TextDocument, Chunk inalterados) +Proveniência em tempo de consulta (inalterado) + +## Riscos + +`unstructured[all-docs]` tem muitas dependências (poppler, tesseract, + libreoffice para alguns formatos). A imagem do contêiner será maior. + Mitigação: oferecer uma variante de `[light]` sem dependências de OCR/office. +Alguns formatos podem produzir extração de texto de baixa qualidade (PDFs digitalizados sem + OCR, layouts complexos de XLSX). Mitigação: parâmetro `strategy` configurável + e o decodificador OCR Mistral existente permanece disponível + para OCR de PDF de alta qualidade. +As atualizações de versão de `unstructured` podem alterar os metadados dos elementos. + Mitigação: fixar a versão, testar a qualidade da extração por formato. diff --git a/docs/tech-specs/universal-decoder.ru.md b/docs/tech-specs/universal-decoder.ru.md new file mode 100644 index 00000000..ecbb8c56 --- /dev/null +++ b/docs/tech-specs/universal-decoder.ru.md @@ -0,0 +1,200 @@ +--- +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. + +## Заголовок + +Универсальный декодер документов, работающий на базе `unstructured` — извлекает любые распространенные форматы документов через единый сервис, обеспечивая полную отслеживаемость и интеграцию с библиотекой, регистрируя позиции источника в качестве метаданных графа знаний для обеспечения полной отслеживаемости. + +## Проблема + +В настоящее время TrustGraph имеет декодер, специфичный для PDF. Поддержка дополнительных форматов (DOCX, XLSX, PPTX и т.д.) требует значительных изменений. + +## Решение + +Мы предлагаем универсальный декодер, который будет поддерживать широкий спектр форматов документов. Этот декодер будет использовать библиотеку `unstructured` для извлечения текста и метаданных из документов. + +## Архитектура + +Универсальный декодер будет состоять из следующих компонентов: + +* **Входной компонент:** Принимает документ в качестве входных данных. +* **Компонент извлечения:** Использует библиотеку `unstructured` для извлечения текста и метаданных из документа. +* **Компонент формирования provenance:** Генерирует provenance-данные, которые содержат информацию о том, откуда взялся каждый фрагмент текста. +* **Компонент выходных данных:** Выдает извлеченные данные и provenance-данные. + +## Процесс + +1. Декодер получает документ в качестве входных данных. +2. Декодер использует библиотеку `unstructured` для извлечения текста и метаданных из документа. +3. Декодер генерирует provenance-данные, которые содержат информацию о том, откуда взялся каждый фрагмент текста. +4. Декодер выдает извлеченные данные и provenance-данные. + +## Форматы Документов + +| Формат | MIME-тип | Поддержка страниц | Примечания | +|---|---|---|---| +| PDF | application/pdf | Да | Группировка по страницам | +| DOCX | application/vnd.openxmlformats... | Нет | Использование стратегии секций | +| PPTX | application/vnd.openxmlformats... | Да | Группировка по слайдам | +| XLSX/XLS | application/vnd.openxmlformats... | Да | Группировка по листам | +| HTML | text/html | Нет | Использование стратегии секций | +| Markdown | text/markdown | Нет | Использование стратегии секций | +| Plain | text/plain | Нет | Использование стратегии секций | +| CSV | text/csv | Нет | Использование стратегии секций | +| RST | text/x-rst | Нет | Использование стратегии секций | +| RTF | application/rtf | Нет | Использование стратегии секций | +| ODT | application/vnd.oasis... | Нет | Использование стратегии секций | +| TSV | text/tab-separated-values | Нет | Использование стратегии секций | + +## Метаданные Provenance + +Каждая сущность страницы/секции регистрирует метаданные о позиции в виде triple в `GRAPH_SOURCE`, обеспечивая полную отслеживаемость от triple в графе знаний обратно к исходным позициям в документе. + +#### Существующие поля (уже в `derived_entity_triples`) + +* `page_number` — номер страницы/листа/слайда (1-indexed, только для страниц) +* `char_offset` — смещение символов для этой страницы/секции в полном тексте +* `char_length` — длина текста для этой страницы/секции в документе + +#### Новые поля (расширяем `derived_entity_triples`) + +* `mime_type` — исходный формат документа (например, `application/pdf`) +* `element_types` — список категорий элементов `unstructured`, найденных на этой странице/секции (например, "Title,NarrativeText,Table") +* `table_count` — количество таблиц на этой странице/секции +* `image_count` — количество изображений на этой странице/секции + +Эти требуют новых префиксов пространства имен TG: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +Схема URN для изображений: `urn:image:{uuid}` + +(`TG_MIME_TYPE` уже существует.) + +#### Новый тип сущности + +Для не-страничных форматов (DOCX, HTML, Markdown и т.д.), где декодер выдает весь документ в виде одной сущности, тип сущности становится: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +Это отличает секции от страниц при запросе provenance: + +| Entity | Type | Когда используется | +|---|---|---| +| Document | `tg:Document` | Оригинальный загруженный файл | +| Page | `tg:Page` | Для page-based форматов (PDF, PPTX, XLSX) | +| Section | `tg:Section` | Для не-page форматов (DOCX, HTML, MD и т.д.) | +| Image | `tg:Image` | Встроенные изображения (сохранены, не обрабатываются) | +| Chunk | `tg:Chunk` | Выход из chunker | +| Subgraph | `tg:Subgraph` | Выход из extraции KG | + +Тип устанавливается декодером в зависимости от группировки по страницам или выдачи всей документа в виде одной сущности. `derived_entity_triples` добавляет необязательный параметр `section` — если он установлен, сущность имеет тип `tg:Section` вместо `tg:Page`. + +#### Полная цепочка provenance + +``` +Triple KG + → subgraph (provenance) + → chunk (char_offset, char_length within page) + → page/section (page_number, char_offset, char_length within doc, mime_type, element_types) + → document (оригинальный файл в librarian) +``` + +Каждый линк — это набор triple в графе `GRAPH_SOURCE`. + +## Конфигурация Сервиса + +Аргументы командной строки: + +``` +--strategy Стратегия партиционирования: auto, hi_res, fast (по умолчанию: auto) +--languages Разделенные кодами OCR (по умолчанию: eng) +--section-strategy Группировка секций: whole-document, heading, element-type, + count, size (по умолчанию: whole-document) +--section-element-count Элементы на секцию для 'count' strategy (по умолчанию: 20) +--section-max-size Макс. символов на секцию для 'size' strategy (по умолчанию: 4000) +--section-within-pages Применение стратегии секций также для страниц (по умолчанию: false) +``` + +Кроме стандартных аргументов для `FlowProcessor` и очереди librarian. + +## Интеграция с Flow + +Универсальный декодер занимает ту же позицию в потоке обработки, что и существующий декодер PDF: + +``` +Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ... +``` + +Он регистрирует: +* Консумент `input` (схема Document) +* Производитель `output` (схема TextDocument) +* Производитель `triples` (схема) +* Запросы/отзывы к librarian (для fetch и хранения child document) + +## Развертывание + +* Новый контейнер: `trustgraph-flow-universal-decoder` +* Зависимость: `unstructured[all-docs]` (включает PDF, DOCX, PPTX и т.д.) +* Можно запускать параллельно или заменять существующий декодер PDF, в зависимости от конфигурации потока +* Существующий декодер PDF остается доступным, если зависимости `unstructured` слишком велики + +## Изменения + +| Компонент | Изменение | +|---|---| +| `provenance/namespaces.py` | Добавить `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` | +| `provenance/triples.py` | Добавить параметры `mime_type`, `element_types`, `table_count`, `image_count` | +| `provenance/__init__.py` | Экспортировать новые константы | +| Новый: `decoding/universal/` | Новый модуль сервиса | +| `setup.cfg` / `pyproject` | Добавить зависимость `unstructured[all-docs]` | +| Docker | Новый образ контейнера | +| Flow definitions | | + +## Что не меняется + +* Chunker (принимает TextDocument, работает как раньше) +* Downstream extractors (принимают Chunk, без изменений) +* Librarian (хранит child document, без изменений) +* Схема (Document, TextDocument, Chunk без изменений) +* Запрос provenance (без изменений) + +## Риски + +* `unstructured[all-docs]` имеет тяжелые зависимости (poppler, tesseract, libreoffice для некоторых форматов) +* Необходимы значительные изменения. + +## Преимущества + +* Поддержка широкого спектра форматов документов +* Использование библиотеки `unstructured` для извлечения текста и метаданных +* Генерация provenance-данных +* Возможность интеграции с существующей системой обработки документов + +## Дополнительные Замечания + +* Эта архитектура требует тщательного тестирования и оптимизации. +* Необходимо учитывать производительность при обработке больших документов. +* Важно обеспечить совместимость с существующими системами обработки документов. +* Следует использовать возможности библиотеки `unstructured` для оптимизации извлечения текста. +* Необходимо провести анализ требований к производительности и выбрать оптимальную конфигурацию. +* Необходимо обеспечить безопасность при обработке конфиденциальных данных. + +## Заключение + +Предлагаемая архитектура универсального декодера представляет собой мощное решение для обработки широкого спектра форматов документов. Она обеспечивает гибкость, масштабируемость и возможность интеграции с существующими системами. При правильной реализации и тестировании, эта архитектура позволит эффективно извлекать данные из различных источников и использовать их в аналитических целях. diff --git a/docs/tech-specs/universal-decoder.sw.md b/docs/tech-specs/universal-decoder.sw.md new file mode 100644 index 00000000..358c817f --- /dev/null +++ b/docs/tech-specs/universal-decoder.sw.md @@ -0,0 +1,228 @@ +--- +layout: default +title: "Derekezi Universal ya Hati" +parent: "Swahili (Beta)" +--- + +# Derekezi Universal ya Hati + +> **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. + +## Mada + +Derekezi universal ya hati inayotumiwa na `unstructured` — ingiza aina yoyote ya hati inayotumika kupitia huduma moja, pamoja na taarifa kamili kuhusu chanzo na ushirikiano na mtaalamu wa maktaba, huku ikiandika nafasi za asili kama metadata ya grafu ya maarifa kwa ufuatiliaji kamili. + +## Tatizo + +Sasa, derekezi ya TrustGraph inalenga tu hati za PDF. Kuunga mkono aina zingine (DOCX, XLSX, HTML, Markdown, maandishi safi, PPTX, n.k.) inahitaji ama kuandika derekezi mpya kwa kila aina au kutumia maktaba ya uondoaji wa universal. Kila aina ina muundo tofauti — baadhi zinategemea kurasa, huku zingine hazitegemei — na mnyororo wa chanzo lazima urekodize ambako kila sehemu ya maandishi iliyopatikana ilitoka kwenye hati asili. + +## Mbinu + +### Maktaba: `unstructured` + +Tumia `unstructured.partition.auto.partition()` ambayo hugundua kiotomatiki aina kutoka kwa mime type au upanuzi wa faili na huondoa vipengele vilivyopangwa (Kichwa, Nakala, Jedwali, Kipengele cha Orodha, n.k.). Kila kipengele kina metadata, pamoja na: + +- `page_number` (kwa aina zinazotumia kurasa kama vile PDF, PPTX) +- `element_id` (ya kipekee kwa kila kipengele) +- `coordinates` (sanduku la mipaka kwa PDFs) +- `text` (maandishi yaliyopatikana) +- `category` (aina ya kipengele: Kichwa, Nakala, Jedwali, n.k.) + +### Aina za Vipengele + +`unstructured` huondoa vipengele vilivyopangwa kutoka kwenye hati. Kila kipengele kina aina na metadata inayohusiana: + +**Vipengele vya maandishi:** +- `Title` — vichwa vya sehemu +- `NarrativeText` — aya za mwili +- `ListItem` — vipengele vya orodha (pointi/nambari) +- `Header`, `Footer` — vichwa/miguu ya ukurasa +- `FigureCaption` — maandishi ya maelezo kwa picha/akili +- `Formula` — maandishi ya hesabu +- `Address`, `EmailAddress` — maelezo ya mawasiliano +- `CodeSnippet` — vipengele vya nambari (kutoka kwenye maandishi) + +**Jedwali:** +- `Table` — data iliyopangwa katika meza. `unstructured` hutoa `element.text` (maandishi safi) na `element.metadata.text_as_html` (HTML kamili ya `` pamoja na mistari, safu, na vichwa). Kwa aina zilizo na muundo wazi wa jedwali (DOCX, XLSX, HTML), uondoaji una uaminifu mkubwa. Kwa PDFs, ugunduzi wa jedwali hutegemea mkakati wa `hi_res` pamoja na uchambuzi wa muundo. + +**Picha:** +- `Image` — picha zilizowekwa ndani ambazo hugunduliwa kupitia uchambuzi wa muundo (inahitaji mkakati wa `hi_res`). Pamoja na `extract_image_block_to_payload=True`, inarudisha data ya picha kama base64 katika `element.metadata.image_base64`. Maandishi ya maandishi kutoka kwenye picha yanapatikana katika `element.text`. + +### Usimamizi wa Jedwali + +Jedwali hupewa umuhimu wa pekee. Pale derekezi inapokutana na kipengele cha `Table`, inahifadhi muundo wa HTML badala ya kuirekebisha kuwa maandishi safi. Hii inatoa derekezi ya LLM (Large Language Model) ya chini ya uondoaji ya taarifa bora kwa kuchimbua maarifa kutoka kwa data iliyopangwa. + +Maandishi ya ukurasa/sehemu yanakusanywa kama ifuatavyo: +- Vipengele vya maandishi: maandishi safi, yakiunganishwa na mistari mipya +- Vipengele vya jedwali: alama ya HTML ya `
` kutoka `text_as_html`, ambayo inazingatiwa ili derekezi ya LLM iweze kutofautisha jedwali na maandishi. + +Kwa mfano, ukurasa wenye kichwa, aya, na jedwali hutengenezwa kama ifuatavyo: + +``` +Muhtasari wa Kifedha + +Mapato yaliongezeka kwa 15% mwaka jana kutokana na matumizi ya kampuni. + +
+ + + +
Kila MaraMapatoKukua
Q1$12M12%
Q2$14M17%
+``` + +Hii inahifadhi muundo wa jedwali wakati wa kuunganisha na katika mlolongo wa uondoaji, ambapo derekezi ya LLM inaweza kuchimbua uhusiano moja kwa moja kutoka kwa seli zilizopangwa badala ya kujaribu nadharia kuhusu ulinganishi wa safu kutoka kwa umbali. + +### Usimamizi wa Picha + +Picha zinaondolewa na kuhifadhiwa katika mtaalamu wa maktaba kama hati ndogo zenye `document_type="image"` na `urn:image:{uuid}` ID. Inapata triples za chanzo pamoja na aina `tg:Image`, ambazo zinahusiana na ukurasa/sehemu yake ya asili kupitia `prov:wasDerivedFrom`. Metadata ya picha (nafasi, vipimo, `element_id`) inarekodiwa katika chanzo. + +**Muhimu, picha HAZIPI tokelezwa kama matokeo ya `TextDocument`.** Inahifadhiwa tu — haitumwi kwa derekezi ya sehemu au mlolongo wowote wa kuchakata maandishi. Hii ni kwa makusudi: + +1. Bado hakuna mlolongo wa kuchakata picha (kuunganisha na modeli ya maono ni kazi ya baadaye) +2. Kupeleka data ya picha au vipande vya maandishi kutoka kwa OCR kwenye mlolongo wa uondoaji wa maandishi kutatoa triples za KG (Knowledge Graph) zisizo na maana. + +Picha pia hazijumuishwi katika maandishi ya ukurasa — vipengele vyovyote vya `Image` hupita bila kutambuliwa wakati wa kuunganisha maandishi ya kipengele kwa ukurasa/sehemu. Mnyororo wa chanzo unaandika kwamba picha zipo na zilipoonekana katika hati, hivyo zinaweza kuchukuliwa na mlolongo wa baadaye wa kuchakata picha bila kuhitajika kurejesha hati. + +#### Kazi za Baadaye + +- Tuma vitu vya `tg:Image` kwa modeli ya maono kwa ajili ya maelezo, tafsiri ya michoro, au uondoaji wa data ya chati. +- Hifadhi maelezo ya picha kama hati ndogo za maandishi ambazo hufika katika mlolongo wa kawaida wa kuunganisha/uondoaji. +- Unganisha maarifa yaliyopatikana nyuma kwenye picha za asili kupitia chanzo. + +### Mikakati ya Sehemu + +Kwa aina zinazotumia kurasa (PDF, PPTX, XLSX), vipengele daima huunganishwa kwa ukurasa/slide/karatasi kwanza. Kwa aina ambazo hazitumii kurasa (DOCX, HTML, Markdown, n.k.), derekezi inahitaji mkakati wa kuainisha hati katika sehemu. Hii inaweza kubadilishwa wakati wa utendaji kupitia `--section-strategy`. + +Kila mkakati ni kazi ya kuunganisha juu ya orodha ya vipengele vya `unstructured`. Matokeo ni orodha ya vikundi vya vipengele; mlolongo mwingine (kuunganisha maandishi, kuhifadhi katika mtaalamu wa maktaba, chanzo, matokeo ya `TextDocument`) ni sawa bila kujali mkakati. + +#### `whole-document` (chaguo-msingi) + +Tuma hati nzima kama sehemu moja. Acha derekezi ya chini ya uunganisha iweze kuainisha yote. + +- Mbinu rahisi, kiwango kizuri +- Inaweza kuzalisha `TextDocument` kubwa kwa faili kubwa, lakini derekezi ya chini ya uunganisha inaweza kushughulikia hili +- Ni bora wakati unataka muktadha mwingi kwa kila sehemu + +#### `heading` + +Aina katika vipengele vya vichwa (`Title`). Kila sehemu ni kichwa na yote yaliyo yafuatayo hadi kichwa cha kiwango sawa au cha juu. Vichwa vilivyoingiliana huunda sehemu zilizounganishwa. + +- Inazalisha vitengo vya mada ambavyo vina maana +- Inafaa kwa hati zilizopangwa (ripoti, manwal, vipimo) +- Inatoa kwa derekezi ya LLM muktadha wa vichwa pamoja na maudhui +- Inarudi kwenye `whole-document` ikiwa hakuna vichwa vilivyopatikana + +#### `element-type` + +Aina wakati aina ya kipengele inabadilika sana — haswa, anza sehemu mpya katika mabadiliko kati ya maandishi na jedwali. Vipengele vilivyofuata vya aina moja (maandishi, maandishi, maandishi au jedwali, jedwali) huendelea kuunganishwa. + +- Inahifadhi jedwali kama sehemu zilizojitenga +- Ni nzuri kwa hati zilizo na maudhui mchanganyiko (ripoti na meza za data) +- Jedwali hupata umakini maalum wa uondoaji + +#### `count` + +Unganisha idadi fulani ya vipengele kwa kila sehemu. Inaweza kubadilishwa kupitia `--section-element-count` (chaguo-msingi: 20). + +- Rahisi na yanayotabirika +- Hayazingati muundo wa hati +- Ni muhimu kama njia mbadala au kwa majaribio + +#### `size` + +Unganisha vipengele hadi kikomo cha herufi kifikie, kisha anza sehemu mpya. Inazingatia mipaka ya kipengele — haigawisi katikati ya kipengele. Inaweza kubadilishwa kupitia `--section-max-size` (chaguo-msingi: 4000 herufi). + +- Inazalisha ukubwa wa sehemu unaozingatia +- Inazingatia mipaka ya kipengele (tofauti na derekezi ya chini ya uunganisha) +- Ni suluhisho bora kati ya muundo na udhibiti wa ukubwa +- Ikiwa kipengele kimoja kinazidi kikomo, kinakuwa sehemu yake mwenyewe + +#### Mwingiliano na Aina Zinazotumia Kurasa + +Kwa aina zinazotumia kurasa, uunganishaji wa ukurasa daima huwapa kipaumbele. Mikakati ya sehemu inaweza kutumika *ndani* ya ukurasa ikiwa ukurasa ni kubwa sana (kwa mfano, ukurasa wa PDF wenye jedwali kubwa sana), hii inadhibitiwa na `--section-within-pages` (chaguo-msingi: false). Wakati chaguo hili limezimwa, kila ukurasa ni sehemu moja bila kujali ukubwa wake. + +### Ugunduzi wa Aina + +Derekezi inahitaji kujua aina ya hati ili iweze kuipitisha kwa `partition()` ya `unstructured`. Kuna njia mbili: + +- **Njia ya mtaalamu wa maktaba** (`document_id` imewekwa): kwanza pata metadata ya hati kutoka kwa mtaalamu wa maktaba — hii inatuonyesha `kind` (aina) ambayo ilirekodiwa wakati wa kupakia. Kisha pata maudhui ya hati. Hii inahitaji simu mbili za mtaalamu wa maktaba, lakini kupata metadata ni rahisi. +- **Njia ya ndani** (utangamano wa nyuma, `data` imewekwa): hakuna metadata inayopatikana kwenye ujumbe. Tumia `python-magic` kuchunguza aina kutoka kwa bytes za maudhui kama njia mbadala. + +Hakuna mabadiliko yanayohitajika kwenye schema ya `Document` — mtaalamu wa maktaba hurejesha aina ya mime. + +### Muundo + +Huduma moja ya `universal-decoder` ambayo: + +1. Inapokea ujumbe wa `Document` (ndani au kupitia marejeleo ya mtaalamu wa maktaba) +2. Ikiwa ni njia ya mtaalamu wa maktaba: pata metadata ya hati (pata aina), kisha pata maudhui. Ikiwa ni njia ya ndani: chunguza aina kutoka kwa bytes za maudhui. +3. Inaitisha `partition()` ili kuondoa vipengele +4. Inaainisha vipengele: kwa ukurasa kwa aina zinazotumia kurasa, kwa mkakati wa sehemu uliopangwa kwa aina ambazo hazitumii kurasa +5. Kwa kila ukurasa/sehemu: + - Inazalisha `urn:page:{uuid}` au `urn:section:{uuid}` ID + - Inaunganisha maandishi ya ukurasa: maandishi safi, jedwali kama HTML, picha zinarudiwa + - Inahesabu nafasi za herufi kwa kila kipengele ndani ya maandishi ya ukurasa + - Inahifadhi katika mtaalamu wa maktaba kama hati ndogo + - Inazalisha triples za chanzo na metadata ya nafasi + - Inatuma `TextDocument` chini ya uunganishaji +6. Kwa kila kipengele cha picha: + - Inazalisha `urn:image:{uuid}` ID + - Inahifadhi data ya picha katika mtaalamu wa maktaba kama hati ndogo + - Inazalisha triples za chanzo (zinawekwa tu, hazitumwi chini) + +### Usanidi wa Huduma + +Majadiliano ya mstari wa amri: + +``` +--strategy Mbinu ya kuainisha: auto, hi_res, fast (chaguo-msingi: auto) +--languages Orodha ya msimbo wa lugha inayotumika kwa OCR (chaguo-msingi: eng) +--section-strategy Mbinu ya kuunganisha sehemu: whole-document, heading, element-type, + count, size (chaguo-msingi: whole-document) +--section-element-count Vipengele kwa kila sehemu kwa mbinu ya 'count' (chaguo-msingi: 20) +--section-max-size Kikomo cha herufi kwa kila sehemu kwa mbinu ya 'size' (chaguo-msingi: 4000) +--section-within-pages Tumia mkakati wa sehemu ndani ya ukurasa pia (chaguo-msingi: false) +``` + +Pia, majadiliano ya kawaida ya `FlowProcessor` na folyo ya mtaalamu wa maktaba. + +### Ushirikiano wa Flow + +Derekezi ya universal huishia katika nafasi sawa ya mlolongo wa uendeshaji kama derekezi ya PDF iliyopo: + +``` +Hati → [derekezi-universal] → TextDocument → [derekezi-ya-kuunganisha] → Sehemu → ... +``` + +Inajisajili: +- Mtumiaji wa `input` (schema ya Hati) +- Mtayarishaji wa `output` (schema ya TextDocument) +- Mtayarishaji wa `triples` (schema ya Triples) +- Ombi/jibu la mtaalamu wa maktaba (kwa kupata na kuhifadhi hati ndogo) + +### Uwekaji + +- Chini mpya: `trustgraph-flow-universal-decoder` +- Utendakazi: `unstructured[all-docs]` (inajumuisha PDF, DOCX, PPTX, n.k.) +- Inaweza kuendeshwa pamoja au kubadilisha derekezi ya PDF iliyopo kulingana na usanidi wa mlolongo +- Derekezi ya PDF iliyopo inabaki inapatikana kwa mazingira ambapo utendakazi wa `unstructured` ni mzito sana. + +### Mabadiliko + +| Komponenti | Mabadiliko | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | Ongeza `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` | +| `provenance/triples.py` | Ongeza `mime_type`, `element_types`, `table_count`, `image_count` kwa `kwargs` | +| `provenance/__init__.py` | Exporti mara kwa mara | +| Mpya: `decoding/universal/` | Moduli mpya ya derekezi | +| `setup.cfg` / `pyproject` | Ongeza utendakazi wa `unstructured[all-docs]` | +| Docker | Pata picha mpya ya chumba | +| Maelezo ya mlolongo | Unganisha derekezi-universal kama input ya hati | + +### Mambo ambayo Hayabadiliki + +- Derekezi ya kuchakata (Inapokea `TextDocument`, inafanya kama ilivyokuwa) +- Vitu vya uondoaji (Inapokea `Sehemu`, inafanya kama ilivyokuwa) +- Schema ya `Document` — inahitaji maelezo yafuatayo: + - `file_name`: Jina la faili. + - `file_type`: Aina ya faili. diff --git a/docs/tech-specs/universal-decoder.tr.md b/docs/tech-specs/universal-decoder.tr.md new file mode 100644 index 00000000..bf10a74c --- /dev/null +++ b/docs/tech-specs/universal-decoder.tr.md @@ -0,0 +1,404 @@ +--- +layout: default +title: "Evrensel Belge Kodlayıcı" +parent: "Turkish (Beta)" +--- + +# Evrensel Belge Kodlayıcı + +> **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. + +## Başlık + +`unstructured` tarafından desteklenen evrensel belge kodlayıcı — tüm kaynak konumlarını, uçtan uca izlenebilirlik için bilgi grafiği meta verisi olarak kaydederek, tam kökenli ve kütüphaneci entegrasyonu ile herhangi bir yaygın belge formatını tek bir hizmet aracılığıyla işleyin. + + + + +## Sorun + +TrustGraph şu anda PDF'ye özel bir çözücüye (decoder) sahip. Ek +formatları (DOCX, XLSX, HTML, Markdown, düz metin, PPTX, vb.) desteklemek, +ya her format için yeni bir çözücü yazmayı veya evrensel bir çıkarma +kütüphanesini kullanmayı gerektirir. Her formatın farklı bir yapısı vardır — bazıları sayfa tabanlıyken, bazıları değildir — ve köken zinciri, çıkarılan her metin parçasının orijinal +belgede nereden geldiğini kaydetmelidir. + +## Yaklaşım +## Yaklaşım + +### Kütüphane: `unstructured` + +`unstructured.partition.auto.partition()`'ı kullanın, bu, formatı otomatik olarak algılar +MIME türünden veya dosya uzantısından yapılandırılmış öğeleri ayıklar +(Başlık, AnlatıMetni, Tablo, Madde, vb.). Her öğe aşağıdaki bilgileri içerir: + + +`page_number` (sayfa tabanlı formatlar için, örneğin PDF, PPTX) +`element_id` (her öğe için benzersiz) +`coordinates` (PDF'ler için sınırlayıcı kutu) +`text` (çıkarılan metin içeriği) +`category` (öğe türü: Başlık, AnlatıMetni, Tablo, vb.) + +### Öğe Türleri + +`unstructured`, belgelerden türlenmiş öğeleri çıkarır. Her öğenin bir kategorisi ve ilişkili meta verileri vardır: + + +**Metin öğeleri:** +`Title` — bölüm başlıkları +`NarrativeText` — ana metin paragrafları +`ListItem` — madde işaretli/numaralandırılmış liste öğeleri +`Header`, `Footer` — sayfa başlıkları/altbilgileri +`FigureCaption` — şekiller/görseller için başlıklar +`Formula` — matematiksel ifadeler +`Address`, `EmailAddress` — iletişim bilgileri +`CodeSnippet` — kod blokları (markdown'dan) + +**Tablolar:** +`Table` — yapılandırılmış tablo verileri. `unstructured`, hem + `element.text` (düz metin) hem de `element.metadata.text_as_html` + (satırlar, sütunlar ve başlıklar korunmuş, tam HTML ``) sağlar. + Açık tablo yapısına sahip formatlar (DOCX, XLSX, HTML) için, + çıkarma işlemi son derece güvenilirdir. PDF'ler için, tablo tespiti, + düzen analizini içeren `hi_res` stratejisine bağlıdır. + +**Görseller:** +`Image` — düzen analizi yoluyla algılanan yerleşik görseller (gerektirir + `hi_res` stratejisi). `extract_image_block_to_payload=True` ile, + görüntü verilerini `element.metadata.image_base64` içinde base64 olarak döndürür. + Görüntüden elde edilen OCR metni `element.text` içinde mevcuttur. + +### Tablo İşleme + +Tablolar, birincil bir çıktı türüdür. Kod çözücü, bir `Table` +öğesiyle karşılaştığında, düz metne dönüştürmek yerine HTML yapısını korur. +Bu, aşağı akış LLM çıkarıcısının, yapılandırılmış verileri içeren +tablo verilerinden daha iyi bilgi almasını sağlar. + +Sayfa/bölüm metni aşağıdaki gibi birleştirilir: +Metin öğeleri: yeni satırlarla birleştirilmiş düz metin +Tablo öğeleri: `text_as_html`'dan HTML tablo işaretlemesi, bir + `
` işaretinin içine sarılır, böylece LLM tabloları, anlatıdan +ayırt edebilir. +Örneğin, bir başlık, paragraf ve tablo içeren bir sayfa şu şekilde üretilir: + +``` +Financial Overview + +Revenue grew 15% year-over-year driven by enterprise adoption. + +
+ + + +
QuarterRevenueGrowth
Q1$12M12%
Q2$14M17%
+``` + +Bu, tablo yapısını parçalara ayırarak ve çıkarma işlemine aktararak korur. +Bu sayede, LLM (Büyük Dil Modeli), sütun hizalamasını boşluklardan tahmin etmek yerine, doğrudan yapılandırılmış hücrelerden ilişkileri çıkarabilir. + + +### Resim İşleme + + +Görüntüler çıkarılır ve kütüphanede alt belgeler olarak saklanır. +`document_type="image"` ile ve `urn:image:{uuid}` kimlik numarasına sahip. Bunlar +`tg:Image` türündeki köken bilgisi üçlülerini içerir ve bunlar, ebeveynlerine bağlanmıştır. +sayfa/bölüm, `prov:wasDerivedFrom` aracılığıyla. Görüntü meta verileri (koordinatlar, +boyutlar, element_id) provenians kısmında kaydedilir. + +**Önemli olarak, resimler, TextDocument çıktıları olarak YAYINLANMAMAKTIR.** +Bunlar yalnızca saklanır; parçalayıcıya veya herhangi bir metin işleme +işlem hattına gönderilmez. Bu kasıtlıdır: + +1. Henüz bir resim işleme işlem hattı yoktur (görsel model entegrasyonu + gelecekteki bir çalışmadır) +2. Base64 resim verilerini veya OCR parçalarını metin çıkarma + işlem hattına vermek, hatalı KG üçlüleri üretir. + +Görüntüler de birleştirilmiş sayfa metninden hariç tutulur; herhangi bir `Image` +öğesi, bir sayfa/bölüm için öğe metinlerini birleştirirken sessizce atlanır. +Kaynak zinciri, görüntülerin var olduğunu ve belgede nerede +bulunduğunu kaydeder, böylece gelecekte bir görüntü işleme hattı tarafından +belgenin yeniden yüklenmesi olmadan da alınabilirler. + +#### Gelecek çalışmalar + +`tg:Image` varlıklarını, açıklama, + diyagram yorumlama veya grafik veri çıkarma için bir görsel modele yönlendirin. +Görüntü açıklamalarını, standart parçalama/çıkarma işlem hattına beslenen metin alt belgeleri olarak kaydedin. + Çıkarılan bilgileri, kaynak görüntüleriyle köken bilgisi aracılığıyla ilişkilendirin. + + +### Bölüm Stratejileri + +Sayfa tabanlı formatlar (PDF, PPTX, XLSX) için, öğeler her zaman önce sayfa/slayt/sayfa içinde gruplandırılır. +Sayfa tabanlı olmayan formatlar (DOCX, HTML, Markdown, +vb.) için, kodlayıcının belgeyi bölümlere ayırmak için bir stratejiye ihtiyacı vardır. +Bu, çalışma zamanında `--section-strategy` aracılığıyla yapılandırılabilir. + +Her strateji, `unstructured` öğelerinin listesi üzerinde bir gruplama fonksiyonudur. +Çıktı, öğe gruplarının bir listesidir; geri kalan işlem hattı (metin birleştirme, kütüphane depolama, köken, TextDocument +oluşturma) stratejiden bağımsız olarak aynıdır. + + +#### `whole-document` (varsayılan) + +Tüm belgeyi tek bir bölüm olarak yayınlayın. Bölme işlemlerinin tümü, sonraki +parçalayıcı tarafından gerçekleştirilir. + +En basit yaklaşım, iyi bir başlangıç noktası. +Büyük dosyalar için çok büyük TextDocument'ler oluşturabilir, ancak parçalayıcı + bunu yönetir. +Her bölüm için maksimum bağlam istediğinizde en iyisidir. + +#### `heading` + +Başlık öğelerinde (`Title`) bölün. Her bölüm, bir başlık ve bir sonraki +aynı veya daha yüksek seviyedeki başlığa kadar olan tüm içeriktir. İç içe +başlıklar, iç içe bölümler oluşturur. + +Konuyla ilgili tutarlı birimler oluşturur. +Yapılandırılmış belgeler (raporlar, kılavuzlar, teknik özellikler) için iyi çalışır. +Çıkarma LLM'sine, içerikle birlikte başlık bağlamı sağlar. +Başlık bulunamazsa `whole-document`'a geri döner. + +#### `element-type` + +Eleman türü önemli ölçüde değiştiğinde bölmeyi yapın — özellikle, +anlatısal metin ile tablolar arasındaki geçişlerde yeni bir bölüm başlatın. +Aynı geniş kategoriye ait ardışık öğeler (metin, metin, metin veya +tablo, tablo) gruplandırılır. + +Tabloları bağımsız bölümler olarak tutar +Karışık içerikli belgeler için uygundur (veri tabloları içeren raporlar) +Tablolar, özel bir çıkarma işlemine tabi tutulur + +#### `count` + +Bir bölümdeki öğe sayısını sabit bir sayıda gruplandırın. ⟦CODE_0⟧ aracılığıyla yapılandırılabilir (varsayılan: 20). +`--section-element-count` (varsayılan: 20). + +Basit ve öngörülebilir +Belge yapısını dikkate almaz +Yedek çözüm olarak veya deneme yapmak için kullanışlıdır + +#### `size` + +Öğeleri, bir karakter limiti dolana kadar biriktirin, ardından yeni bir bölüm başlatın. Öğeler arasındaki sınırları dikkate alır; hiçbir zaman bir öğenin ortasında bölünme yapmaz. +⟦CODE_0⟧ gibi yer tutucuları veya ⟦URL_0⟧ gibi URL'leri çevirmeyin; bunları olduğu gibi bırakın. +`--section-max-size` aracılığıyla yapılandırılabilir (varsayılan: 4000 karakter). + +Yaklaşık olarak homojen bölüm boyutları üretir. +Eleman sınırlarına saygı gösterir (aşağıdaki parçalayıcıdan farklı olarak). +Yapı ve boyut kontrolü arasında iyi bir denge sağlar. +Tek bir eleman limiti aşarsa, kendi bölümü haline gelir. + +#### Sayfa tabanlı format etkileşimi + +Sayfa tabanlı formatlar için, sayfa gruplandırması her zaman önceliklidir. +Bölüm stratejileri, isteğe bağlı olarak, çok büyükse (örneğin, devasa bir tablo içeren bir PDF sayfası) bir sayfa *içinde* uygulanabilir, bu durum ⟦CODE_0⟧ ile kontrol edilir (varsayılan: false). Yanlış olduğunda, her sayfa boyuttan bağımsız olarak her zaman bir bölümdür. + +`--section-within-pages` (varsayılan: false). + + +### Biçim Algılama + +Kodlayıcının, belgeyi ⟦CODE_0⟧'ın ⟦CODE_1⟧'ine iletebilmesi için belgenin MIME türünü bilmesi gerekir. İki yol: +`unstructured`'ın `partition()`'i. + +**Kütüphaneci yolu** (`document_id` ayarı): belge meta verilerini alın. + Öncelikle kütüphaneciden belge meta verilerini alın — bu, `kind` (mime türü) değerini verir. + Ardından belge içeriğini alın. + İki kütüphaneci çağrısı, ancak meta veri alma işlemi hafiftir. +**Satır içi yol** (geriye dönük uyumluluk, `data` ayarı): mesaj üzerinde herhangi bir meta veri bulunmamaktadır. + Biçimi tespit etmek için `python-magic`'ı kullanın. + Bu, içerik baytlarından biçimi algılamak için bir yedek yöntemdir. + +`Document` şemasına herhangi bir değişiklik yapılmasına gerek yok — kütüphaneci zaten MIME türünü saklar. + + +### Mimari + +Tek bir `universal-decoder` hizmeti: + +1. Bir `Document` mesajı alır (doğrudan veya kütüphaneci referansı aracılığıyla) +2. Kütüphaneci yoluysa: belge meta verilerini alır (MIME türünü alır), ardından + içeriği alır. Doğrudan yol ise: içeriğin baytlarından formatı algılar. +3. Öğeleri çıkarmak için `partition()`'ı çağırır +4. Öğeleri gruplandırır: sayfa tabanlı formatlar için sayfalara göre, sayfa dışı formatlar için yapılandırılmış + bölüm stratejisine göre +5. Her sayfa/bölüm için: + Bir `urn:page:{uuid}` veya `urn:section:{uuid}` kimliği oluşturur + Sayfa metnini birleştirir: anlatı düz metin olarak, tablolar HTML olarak, + resimler atlanır + Sayfa metnindeki her öğe için karakter ofsetlerini hesaplar + Kütüphaneciye alt belge olarak kaydeder + Konumsal meta verilerle birlikte kaynak üçlüleri yayınlar + Parçalama için `TextDocument`'ı aşağı akışa gönderir +6. Her resim öğesi için: + Bir `urn:image:{uuid}` kimliği oluşturur + Resim verilerini kütüphaneciye alt belge olarak kaydeder + Kaynak üçlülerini yayınlar (sadece saklanır, aşağı akışa gönderilmez) + +### Biçimlendirme İşlemi + +| Biçim | MIME Tipi | Sayfa Tabanlı | Notlar | +|----------|------------------------------------|------------|--------------------------------| +| PDF | application/pdf | Evet | Sayfaya göre gruplandırma | +| DOCX | application/vnd.openxmlformats... | Hayır | Bölüm stratejisi kullanır | +| PPTX | application/vnd.openxmlformats... | Evet | Slayda göre gruplandırma | +| XLSX/XLS | application/vnd.openxmlformats... | Evet | Sayfaya göre gruplandırma | +| HTML | text/html | Hayır | Bölüm stratejisi kullanır | +| Markdown | text/markdown | Hayır | Bölüm stratejisi kullanır | +| Düz Metin | text/plain | Hayır | Bölüm stratejisi kullanır | +| CSV | text/csv | Hayır | Bölüm stratejisi kullanır | +| RST | text/x-rst | Hayır | Bölüm stratejisi kullanır | +| RTF | application/rtf | Hayır | Bölüm stratejisi kullanır | +| ODT | application/vnd.oasis... | Hayır | Bölüm stratejisi kullanır | +| TSV | text/tab-separated-values | Hayır | Bölüm stratejisi kullanır | + +### Kaynak Veri Meta Verileri + +Her sayfa/bölüm öğesi, köken bilgisi olarak konum bilgisi meta verilerini kaydeder. +`GRAPH_SOURCE` içindeki üçlüler, KG üçlülerinden tam bir izlenebilirlik sağlamaktadır. +Kaynak belge konumlarına geri dönme. + +#### Mevcut alanlar (zaten `derived_entity_triples` içinde) + +`page_number` — sayfa/tablo/slayt numarası (1'den başlayarak, yalnızca sayfa tabanlı) +`char_offset` — bu sayfa/bölümün, + tam belge metni içindeki karakter ofseti +`char_length` — bu sayfa/bölümün metninin karakter uzunluğu + +#### Yeni alanlar (`derived_entity_triples`'ı genişletin) + +`mime_type` — orijinal belge formatı (örneğin, `application/pdf`) +`element_types` — `unstructured` öğelerinden oluşan virgülle ayrılmış liste + bu sayfada/bölümde bulunan kategoriler (örneğin, "Başlık,AnlatıMetni,Tablo") +`table_count` — bu sayfada/bölümdeki tablo sayısı +`image_count` — bu sayfada/bölümdeki resim sayısı + +Bunlar, yeni TG ad alanı özniteliklerini gerektirir: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +Görüntü URN şeması: `urn:image:{uuid}` + +(`TG_MIME_TYPE` zaten mevcut.) + +#### Yeni varlık türü + +Sayfa formatı olmayan (DOCX, HTML, Markdown, vb.) belgeler için, +kodlayıcı, belgeyi sayfalara ayırmak yerine tek bir birim olarak yayınladığında, +varlığa yeni bir tür atanır: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +``` + +Bu, sorgulama sırasında kökeni belirlerken bölümleri sayfalardan ayırır: + +| Varlık | Tür | Ne zaman kullanılır | +|----------|-----------------------------|----------------------------------------| +| Belge | `tg:Document` | Orijinal yüklenen dosya | +| Sayfa | `tg:Page` | Sayfaya dayalı formatlar (PDF, PPTX, XLSX) | +| Bölüm | `tg:Section` | Sayfaya dayalı olmayan formatlar (DOCX, HTML, MD, vb.) | +| Resim | `tg:Image` | Gömülü resimler (saklanan, işlenmeyen) | +| Parça | `tg:Chunk` | Parçalayıcının çıktısı | +| Alt Grafik | `tg:Subgraph` | KG çıkarma çıktısı | + +Tür, kodlayıcı tarafından, sayfalara göre gruplandırılıp gruplandırılmadığına veya tüm belge bölümünün gönderilip gönderilmediğine bağlı olarak belirlenir. ⟦CODE_0⟧ elde edilir. +veya tüm belge bölümünün gönderilip gönderilmediğine bağlı olarak belirlenir. `derived_entity_triples` kazanır. +isteğe bağlı bir `section` boolean parametresi — doğru olduğunda, bu, varlığı belirtir. +`tg:Section` olarak yazılmış, `tg:Page` yerine. + +#### Tam kaynak zinciri + +``` +KG triple + → subgraph (extraction provenance) + → chunk (char_offset, char_length within page) + → page/section (page_number, char_offset, char_length within doc, mime_type, element_types) + → document (original file in librarian) +``` + +Her bağlantı, `GRAPH_SOURCE` adlı grafikte tanımlanan üçlülerden oluşan bir kümedir. + +### Hizmet Yapılandırması + +Komut satırı argümanları: + +``` +--strategy Partitioning strategy: auto, hi_res, fast (default: auto) +--languages Comma-separated OCR language codes (default: eng) +--section-strategy Section grouping: whole-document, heading, element-type, + count, size (default: whole-document) +--section-element-count Elements per section for 'count' strategy (default: 20) +--section-max-size Max chars per section for 'size' strategy (default: 4000) +--section-within-pages Apply section strategy within pages too (default: false) +``` + +Ayrıca standart `FlowProcessor` ve kütüphaneci kuyruk argümanlarını da içerir. + +### Akış Entegrasyonu + +Evrensel kod çözücü, işleme akışında mevcut PDF kod çözücünün bulunduğu aynı konumu işgal eder: + + +``` +Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ... +``` + +Aşağıdakileri kaydeder: +`input` tüketici (Belge şeması) +`output` üretici (MetinBelgesi şeması) +`triples` üretici (Üçlüler şeması) +Kütüphaneci isteği/yanıtı (veri çekme ve alt belge depolama için) + +### Dağıtım + +Yeni kapsayıcı: `trustgraph-flow-universal-decoder` +Bağımlılık: `unstructured[all-docs]` (PDF, DOCX, PPTX vb. içerir) +Mevcut PDF çözücüyü tamamlayıcı olarak veya onun yerine çalışabilir. + akış yapılandırması +Mevcut PDF çözücü, ortamlar için kullanılabilir durumda kalacaktır. + `unstructured` bağımlılıkları çok ağır. + +### Değişiklikler + +| Bileşen | Değişiklik | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` ekleyin | +| `provenance/triples.py` | `mime_type`, `element_types`, `table_count`, `image_count` argümanlarını ekleyin | +| `provenance/__init__.py` | Yeni sabit değerleri dışa aktarın | +| Yeni: `decoding/universal/` | Yeni bir kod çözücü hizmet modülü | +| `setup.cfg` / `pyproject` | `unstructured[all-docs]` bağımlılığını ekleyin | +| Docker | Yeni bir konteyner imajı | +| Akış tanımları | Evrensel kod çözücüyü belge girişi olarak kullanın | + +### Değişmeyenler + +Chunker (MetinBelgesi'ni alır, önceki gibi çalışır) +Aşağı akış ayıklayıcıları (Parçayı alır, değişmeden) +Kütüphaneci (çocuk belgeleri saklar, değişmeden) +Şema (Belge, MetinBelgesi, Parça değişmeden) +Sorgu zamanı köken bilgisi (değişmeden) + +## Riskler + +`unstructured[all-docs]`, önemli bağımlılıklara sahiptir (poppler, tesseract, + libreoffice, bazı formatlar için). Container imajı daha büyük olacaktır. + Çözüm: OCR/ofis bağımlılıkları olmadan `[light]`'ın bir varyantını sunun. +Bazı formatlar, zayıf metin çıkarma sonuçları verebilir (OCR uygulanmamış PDF'ler, + OCR, karmaşık XLSX düzenleri). Çözüm: yapılandırılabilir `strategy` + parametresi ve mevcut Mistral OCR çözücü kullanılabilir durumda. + Yüksek kaliteli PDF OCR için. +`unstructured` sürüm güncellemeleri, öğe meta verilerini değiştirebilir. + Çözüm: sürümü sabitleyin, her format için çıkarma kalitesini test edin. diff --git a/docs/tech-specs/universal-decoder.zh-cn.md b/docs/tech-specs/universal-decoder.zh-cn.md new file mode 100644 index 00000000..89a488cf --- /dev/null +++ b/docs/tech-specs/universal-decoder.zh-cn.md @@ -0,0 +1,297 @@ +--- +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. + +## 概述 + +一个由 `unstructured` 驱动的通用文档解码器,它支持通过单个服务处理各种常见的文档格式。该服务具有完整的溯源功能和库管理员集成,记录源位置作为知识图谱元数据,从而实现端到端的可追溯性。 + +## 问题 + +目前,TrustGraph 仅有一个用于 PDF 文件的解码器。支持其他格式(DOCX、XLSX、HTML、Markdown、纯文本、PPTX 等)需要要么为每种格式编写新的解码器,要么采用一个通用的提取库。每种格式的结构都不同——有些是基于页面的,有些不是——并且溯源链必须记录每个提取的文本片段在原始文档中的位置。 + +## 解决方案 + +### 库:`unstructured` + +使用 `unstructured.partition.auto.partition()` 函数,该函数可以自动检测格式(根据 MIME 类型或文件扩展名),并提取结构化元素(标题、正文、表格、列表项等)。每个元素都包含元数据,包括: + +- `page_number`(对于基于页面的格式,如 PDF、PPTX) +- `element_id`(每个元素唯一) +- `coordinates`(PDF 文件的边界框) +- `text`(提取的文本内容) +- `category`(元素类型:标题、正文、表格等) + +### 元素类型 + +`unstructured` 提取文档中的各种类型的元素,每个元素都有一个类别和相关的元数据: + +**文本元素:** +- `Title` — 段落标题 +- `NarrativeText` — 正文段落 +- `ListItem` — 项目符号/编号列表项 +- `Header`, `Footer` — 页面页眉/页脚 +- `FigureCaption` — 图形/图像的标题 +- `Formula` — 数学表达式 +- `Address`, `EmailAddress` — 联系信息 +- `CodeSnippet` — 代码块(来自 Markdown) + +**表格:** +- `Table` — 结构化的表格数据。`unstructured` 提供了 `element.text`(纯文本)和 `element.metadata.text_as_html`(完整的 HTML `` 标签,保留了行、列和标题)。对于具有显式表格结构的格式(DOCX、XLSX、HTML),提取的可靠性很高。对于 PDF 文件,表格检测依赖于 `hi_res` 策略和布局分析。 + +**图像:** +- `Image` — 检测到的嵌入图像(需要 `hi_res` 策略)。如果设置 `extract_image_block_to_payload=True`,则将图像数据作为 base64 编码的字符串返回到 `element.metadata.image_base64` 中。图像中的 OCR 文本位于 `element.text` 中。 + +### 表格处理 + +表格是主要的输出。当解码器遇到 `Table` 元素时,它会保留 HTML 结构,而不是将其扁平化为纯文本。这为下游的 LLM 提取器提供了更好的输入,以便从表格数据中提取结构化知识。 + +页面/部分文本的组装方式如下: +- 文本元素:纯文本,用换行符连接 +- 表格元素:来自 `text_as_html` 的 HTML 表格标记,并用 `
` 标记包装,以便 LLM 区分表格和正文。 + +例如,一个页面包含标题、段落和表格,其内容如下: + +``` +Financial Overview + +Revenue grew 15% year-over-year driven by enterprise adoption. + +
+ + + +
QuarterRevenueGrowth
Q1$12M12%
Q2$14M17%
+``` + +这在分块和提取流水线中保留了表格结构,LLM 可以直接从结构化单元格中提取关系,而无需猜测列的对齐方式。 + +### 图像处理 + +图像会被提取并存储在库管理员中,作为具有 `document_type="image"` 和 `urn:image:{uuid}` ID 的子文档。它们会生成带有类型 `tg:Image` 的溯源三元组,并通过 `prov:wasDerivedFrom` 链接到其父页面/部分。图像元数据(坐标、尺寸、`element_id`)会记录在溯源信息中。 + +**重要的是,图像不会作为 `TextDocument` 输出。** 它们仅被存储,不会被发送到分块器或任何文本处理流水线。这是故意的: + +1. 尚未建立图像处理流水线(视觉模型集成是未来的工作)。 +2. 将 base64 编码的图像数据或 OCR 片段馈送到文本提取流水线会产生无效的知识图谱三元组。 + +图像也被排除在组装的页面文本之外。当连接一个页面/部分的元素文本时,任何 `Image` 元素都会被静默地跳过。溯源链会记录图像的存在以及它们在文档中出现的位置,以便在将来的图像处理流水线中可以拾取它们,而无需重新导入文档。 + +#### 未来工作 + +- 将 `tg:Image` 实体路由到视觉模型,用于描述、图表解释或图表数据提取。 +- 将图像描述存储为文本子文档,这些子文档会馈送到标准的 chunking/提取流水线。 +- 通过溯源将提取的知识链接回源图像。 + +### 部分策略 + +对于基于页面的格式(PDF、PPTX、XLSX),元素始终首先按页面分组。对于非基于页面的格式(DOCX、HTML、Markdown 等),解码器需要一种策略来将文档拆分为多个部分。这可以通过运行时配置的 `--section-strategy` 参数进行配置。 + +每种策略都是一个分组函数,作用于 `unstructured` 元素的列表。输出是一个元素组的列表;其余流水线(文本组装、库管理员存储、溯源、`TextDocument` 输出)与策略无关。 + +#### `whole-document` (默认) + +将整个文档作为一个单独的部分输出。由下游的分块器处理所有拆分。 + +- 最简单的方案,作为基线。 +- 对于大型文件,可能会生成非常大的 `TextDocument`,但分块器会处理这种情况。 +- 当希望每个部分包含最大的上下文时,使用此选项。 + +#### `heading` + +在标题元素(`Title`)处进行拆分。每个部分是一个标题以及直到下一个相同或更高级别的标题的所有内容。嵌套的标题会创建嵌套的部分。 + +- 生成具有主题相关性的单元。 +- 适用于结构化文档(报告、手册、规范)。 +- 向提取 LLM 提供标题上下文以及内容。 +- 如果未找到标题,则回退到 `whole-document`。 + +#### `element-type` + +当元素类型发生显着变化时进行拆分,特别是,从正文文本和表格之间的转换开始一个新的部分。连续的相同宽泛类别的元素(文本、文本、文本或表格、表格、表格)保持分组。 + +- 保持表格作为独立的部分。 +- 适用于具有混合内容的文档(包含数据表格的报告)。 +- 表格会获得专门的提取关注。 + +#### `count` + +每部分包含固定数量的元素。可以通过 `--section-element-count` 参数进行配置(默认:20)。 + +- 简单且可预测。 +- 不尊重文档结构。 +- 用作回退选项或用于实验。 + +#### `size` + +持续累积元素,直到达到字符限制,然后开始一个新的部分。尊重元素边界,绝不会在元素内部进行拆分。可以通过 `--section-max-size` 参数进行配置(默认:4000 个字符)。 + +- 生成大致均匀大小的部分。 +- 尊重元素边界(与下游分块器不同)。 +- 在结构和大小控制之间取得良好的平衡。 +- 如果单个元素超过限制,则它会成为其自己的部分。 + +#### 基于页面的格式交互 + +对于基于页面的格式,页面分组始终具有优先性。部分策略可以选择性地在非常大的页面内部应用(例如,一个包含非常大的表格的 PDF 页面),由 `--section-within-pages` 参数控制(默认:false)。当设置为 false 时,每个页面始终是一个部分,无论其大小如何。 + +### 格式检测 + +解码器需要知道文档的 MIME 类型,以便将其传递给 `unstructured` 的 `partition()` 函数。有两种方法: + +- **库管理员路径**(设置了 `document_id`):首先从库管理员中获取文档元数据,这会提供 `kind`(MIME 类型),然后获取文档内容。这需要两次库管理员调用,但元数据获取是轻量级的。 +- **内联路径**(后备方案,设置了 `data`):没有关于消息的元数据。使用 `python-magic` 从内容字节中检测格式,作为后备方案。 + +不需要对 `Document` 模式进行任何更改,因为库管理员已经存储了 MIME 类型。 + +### 架构 + +一个名为 `universal-decoder` 的单个服务,该服务: + +1. 接收一个 `Document` 消息(内联或通过库管理员引用)。 +2. 如果使用库管理员路径:获取文档元数据(获取 MIME 类型),然后获取内容。如果使用内联路径:使用 `python-magic` 从内容字节检测格式。 +3. 调用 `partition()` 函数以提取元素。 +4. 按以下方式对元素进行分组:对于基于页面的格式,按页面分组;对于非基于页面的格式,按配置的策略分组。 +5. 对于每个页面/部分: + - 生成一个 `urn:page:{uuid}` 或 `urn:section:{uuid}` ID。 + - 组装页面文本:正文作为纯文本,表格作为 HTML,图像被跳过。 + - 计算每个元素在页面文本中的字符偏移量。 + - 保存到库管理员中作为子文档。 + - 计算带有位置元数据的溯源三元组。 + - 将 `TextDocument` 发送到下游进行分块。 +6. 对于每个图像元素: + - 生成一个 `urn:image:{uuid}` ID。 + - 将图像数据保存到库管理员中作为子文档。 + - 计算溯源三元组(仅存储,不发送到下游)。 + +### 格式处理 + +| 格式 | MIME 类型 | 基于页面 | 备注 | +|-----------|--------------------------------------------|----------|--------------------------------------------| +| PDF | `application/pdf` | 是 | 按页面分组 | +| DOCX | `application/vnd.openxmlformats...` | 否 | 使用部分策略 | +| PPTX | `application/vnd.openxmlformats...` | 是 | 按幻灯片分组 | +| XLSX/XLS | `application/vnd.openxmlformats...` | 是 | 按工作表分组 | +| HTML | `text/html` | 否 | 使用部分策略 | +| Markdown | `text/markdown` | 否 | 使用部分策略 | +| 纯文本 | `text/plain` | 否 | 使用部分策略 | +| CSV | `text/csv` | 否 | 使用部分策略 | +| RST | `text/x-rst` | 否 | 使用部分策略 | +| RTF | `application/rtf` | 否 | 使用部分策略 | +| ODT | `application/vnd.oasis...` | 否 | 使用部分策略 | +| TSV | `text/tab-separated-values` | 否 | 使用部分策略 | + +### 溯源元数据 + +每个页面/部分实体会记录位置元数据,作为 `GRAPH_SOURCE` 命名图中位置元数据的溯源三元组。 + +#### 现有字段(已包含在 `derived_entity_triples` 中) + +- `page_number` — 页面/工作表/幻灯片编号(从 1 开始,仅适用于基于页面的格式) +- `char_offset` — 此页面/部分在整个文档文本中的字符偏移量 +- `char_length` — 此页面/部分的文本的字符长度 + +#### 新字段(扩展 `derived_entity_triples`) + +- `mime_type` — 原始文档格式(例如,`application/pdf`) +- `element_types` — 使用 `unstructured` 提取的元素的类别的逗号分隔列表(例如,`Title,NarrativeText,Table`) +- `table_count` — 此页面/部分中的表格数量 +- `image_count` — 此页面/部分中的图像数量 + +这些需要新的 TG 命名空间谓词: + +``` +TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section" +TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image" +TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes" +TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount" +TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount" +``` + +图像 URN 方案:`urn:image:{uuid}` + +(`TG_MIME_TYPE` 已经存在。) + +#### 完整的溯源链 + +``` +知识图谱三元组 + → subgraph (提取溯源) + → chunk (页面/部分的字符偏移量和长度) + → page/section (页面编号、字符偏移量和长度、MIME 类型、元素类型) + → document (库管理员中的原始文件) +``` + +每个链接都是 `GRAPH_SOURCE` 命名图中一组三元组。 + +### 服务配置 + +命令行参数: + +``` +--strategy 分区策略:auto, hi_res, fast (默认:auto) +--languages 逗号分隔的 OCR 语言代码 (默认: eng) +--section-strategy 部分分组:whole-document, heading, element-type, + count, size (默认: whole-document) +--section-element-count 每个部分包含的元素数量(`count` 策略),(默认: 20) +--section-max-size 每个部分的最大字符数(`size` 策略),(默认: 4000 个字符) +--section-within-pages 是否在页面内部应用部分策略 (默认: false) +``` + +以及标准的 `FlowProcessor` 和库管理员队列参数。 + +### 流集成 + +通用解码器在处理流程中占据与现有 PDF 解码器相同的 position: + +``` +Document → [通用解码器] → TextDocument → [分块器] → Chunk → ... +``` + +它注册: +- `input` 消费者(`Document` 模式) +- `output` 生产者(`TextDocument` 模式) +- `triples` 生产者(`Triples` 模式) +- 库管理员请求/响应(用于获取和创建子文档) + +### 部署 + +- 新的容器:`trustgraph-flow-universal-decoder` +- 依赖项:`unstructured[all-docs]`(包含 PDF、DOCX、PPTX 等) +- 可以与现有的 PDF 解码器并行运行或替换它,具体取决于流程配置。 +- 现有的 PDF 解码器仍然可用,适用于 `unstructured` 依赖项过多的环境。 + +### 变更内容 + +| 组件 | 变更 | +|------------------------------|-------------------------------------------------| +| `provenance/namespaces.py` | 添加 `TG_SECTION_TYPE`、`TG_IMAGE_TYPE`、`TG_ELEMENT_TYPES`、`TG_TABLE_COUNT`、`TG_IMAGE_COUNT` | +| `provenance/triples.py` | 添加 `mime_type`、`element_types`、`table_count`、`image_count` 参数 | +| `provenance/__init__.py` | 导出新的常量 | +| 新的:`decoding/universal/` | 新的解码器服务模块 | +| `setup.cfg` / `pyproject` | 添加 `unstructured[all-docs]` 依赖项 | +| Docker | 新的容器镜像 | +| 流程定义 | 将通用解码器设置为文档输入 | + +### 未变更的内容 + +- 分块器(接收 `TextDocument`,行为与之前相同) +- 下游提取器(接收 `Chunk`,未发生变化) +- 库管理员(存储子文档,未发生变化) +- 模式(`Document`、`TextDocument`、`Chunk` 未发生变化) +- 查询时溯源(未发生变化) + +## 风险 + +- `unstructured[all-docs]` 具有大量的依赖项(包括 poppler、tesseract 和 libreoffice,用于某些格式)。容器镜像会更大。 + 缓解措施:提供不包含 OCR/办公室依赖项的 `[light]` 版本。 +- 某些格式可能导致文本提取效果不佳(扫描的 PDF 文件缺少 OCR,复杂的 XLSX 布局)。 + 缓解措施:配置 `strategy` 参数,并且现有的 Mistral OCR 解码器仍然可用于高质量的 PDF OCR。 +- `unstructured` 版本更新可能会更改元素元数据。 + 缓解措施:固定版本,并为每个格式测试提取质量。 diff --git a/docs/tech-specs/vector-store-lifecycle.ar.md b/docs/tech-specs/vector-store-lifecycle.ar.md new file mode 100644 index 00000000..6ae52325 --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.ar.md @@ -0,0 +1,307 @@ +--- +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 لمجموعات مستودعات المتجهات عبر تطبيقات خلفية مختلفة (Qdrant، Pinecone، Milvus). يعالج التصميم تحدي دعم التضمينات بأبعاد مختلفة دون ترميز قيم الأبعاد بشكل ثابت. + +## بيان المشكلة + +تتطلب مستودعات المتجهات تحديد بُعد التضمين عند إنشاء المجموعات/الفهارس. ومع ذلك: +تنتج نماذج التضمين المختلفة أبعادًا مختلفة (مثل 384، 768، 1536) +لا يتم معرفة البُعد حتى يتم إنشاء أول تضمين +قد تتلقى مجموعة TrustGraph واحدة تضمينات من نماذج متعددة +يؤدي ترميز بُعد (مثل 384) إلى حدوث أعطال مع أحجام تضمين أخرى + +## مبادئ التصميم + +1. **الإنشاء الكسول (Lazy Creation):** يتم إنشاء المجموعات عند الطلب أثناء الكتابة الأولى، وليس أثناء عمليات إدارة المجموعة. +2. **تسمية قائمة على البُعد (Dimension-Based Naming):** تتضمن أسماء المجموعات بُعد التضمين كلاحقة. +3. **التدهور السلس (Graceful Degradation):** تُرجع الاستعلامات التي تستهدف مجموعات غير موجودة نتائج فارغة، وليس أخطاء. +4. **دعم متعدد الأبعاد (Multi-Dimension Support):** يمكن أن تحتوي مجموعة منطقية واحدة على مجموعات فعلية متعددة (واحدة لكل بُعد). + +## البنية + +### اصطلاح تسمية المجموعة + +تستخدم مجموعات مستودعات المتجهات لاحقات الأبعاد لدعم أحجام تضمين متعددة: + +**تضمينات المستندات:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**تضمينات الرسم البياني:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +أمثلة: +`d_alice_papers_384` - مجموعة أوراق أليس مع تضمينات ذات أبعاد 384. +`d_alice_papers_768` - نفس المجموعة المنطقية مع تضمينات ذات أبعاد 768. +`t_bob_knowledge_1536` - رسم بياني معرفة بوب مع تضمينات ذات أبعاد 1536. + +### مراحل دورة الحياة + +#### 1. طلب إنشاء المجموعة + +**تدفق الطلب:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**السلوك:** +يقوم أمين المكتبة ببث طلبات `create-collection` إلى جميع أنظمة التخزين الخلفية. +تقوم معالجات مخازن المتجهات بالاعتراف بالطلب ولكن **لا تقوم بإنشاء مجموعات فعلية**. +يتم إرجاع الاستجابة على الفور مع الإشارة إلى النجاح. +يتم تأجيل إنشاء المجموعة الفعلي حتى أول عملية كتابة. + +**السبب:** +الأبعاد غير معروفة في وقت الإنشاء. +يتجنب إنشاء مجموعات بأبعاد خاطئة. +يبسط منطق إدارة المجموعات. + +#### 2. عمليات الكتابة (الإنشاء المؤجل) + +**تدفق الكتابة:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**السلوك:** +1. استخراج بُعد التضمين من المتجه: `dim = len(vector)` +2. إنشاء اسم المجموعة مع لاحقة البُعد +3. التحقق مما إذا كانت المجموعة موجودة بهذا البُعد المحدد +4. إذا لم تكن موجودة: + إنشاء مجموعة بالبُعد الصحيح + تسجيل: `"Lazily creating collection {name} with dimension {dim}"` +5. إدراج التضمين في المجموعة الخاصة بالبُعد + +**سيناريو مثال:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. عمليات الاستعلام + +**تدفق الاستعلام:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**السلوك:** +1. استخراج البُعد من متجه الاستعلام: `dim = len(vector)` +2. إنشاء اسم المجموعة مع لاحقة البُعد +3. التحقق مما إذا كانت المجموعة موجودة +4. إذا كانت موجودة: + إجراء بحث عن التشابه + إرجاع النتائج +5. إذا لم تكن موجودة: + تسجيل: `"Collection {name} does not exist, returning empty results"` + إرجاع قائمة فارغة (دون إثارة أي خطأ) + +**أبعاد متعددة في نفس الاستعلام:** +إذا كان الاستعلام يحتوي على متجهات بأبعاد مختلفة +تستعلم كل بُعد عن المجموعة المقابلة له +يتم تجميع النتائج +يتم تخطي المجموعات المفقودة (ولا يتم التعامل معها كأخطاء) + +**السبب:** +الاستعلام عن مجموعة فارغة هو حالة استخدام صالحة +إرجاع نتائج فارغة هو أمر منطقي +يتجنب الأخطاء أثناء بدء تشغيل النظام أو قبل استيعاب البيانات + +#### 4. حذف المجموعة + +**عملية الحذف:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**السلوك:** +1. إنشاء نمط البادئة: `d_{user}_{collection}_` (لاحظ الشرطة السفلية في النهاية) +2. سرد جميع المجموعات في مخزن المتجهات. +3. تصفية المجموعات التي تتطابق مع البادئة. +4. حذف جميع المجموعات المتطابقة. +5. تسجيل كل عملية حذف: `"Deleted collection {name}"` +6. سجل ملخص: `"Deleted {count} collection(s) for {user}/{collection}"` + +**مثال:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**الأساس المنطقي:** +يضمن التنظيف الكامل لجميع المتغيرات الأبعاد. +يمنع مطابقة الأنماط الحذف العرضي للمجموعات غير المرتبطة. +عملية ذرية من وجهة نظر المستخدم (يتم حذف جميع الأبعاد معًا). + +## الخصائص السلوكية + +### العمليات العادية + +**إنشاء المجموعة:** +✓ يُرجع النجاح على الفور. +✓ لا يتم تخصيص مساحة تخزين فعلية. +✓ عملية سريعة (لا يوجد إدخال/إخراج خلفي). + +**الكتابة الأولى:** +✓ ينشئ مجموعة بالبعد الصحيح. +✓ أبطأ قليلاً بسبب تكلفة إنشاء المجموعة. +✓ عمليات الكتابة اللاحقة لنفس البعد سريعة. + +**الاستعلامات قبل أي عمليات كتابة:** +✓ تُرجع نتائج فارغة. +✓ لا توجد أخطاء أو استثناءات. +✓ يظل النظام مستقرًا. + +**عمليات كتابة الأبعاد المختلطة:** +✓ ينشئ تلقائيًا مجموعات منفصلة لكل بُعد. +✓ يتم عزل كل بُعد في مجموعته الخاصة. +✓ لا توجد تعارضات في الأبعاد أو أخطاء في المخطط. + +**حذف المجموعة:** +✓ يزيل جميع متغيرات الأبعاد. +✓ تنظيف كامل. +✓ لا توجد مجموعات يتيمة. + +### الحالات الخاصة + +**نماذج تضمين متعددة:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**الكتابات الأولية المتزامنة:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**ترحيل الأبعاد:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**استعلامات المجموعة الفارغة:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## ملاحظات حول التنفيذ + +### تفاصيل حول نظام التخزين الخاص + +**Qdrant:** +يستخدم `collection_exists()` للتحقق من الوجود +يستخدم `get_collections()` لعرض القائمة أثناء الحذف +يتطلب إنشاء المجموعة `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +يستخدم `has_index()` للتحقق من الوجود +يستخدم `list_indexes()` لعرض القائمة أثناء الحذف +يتطلب إنشاء الفهرس الانتظار حتى حالة "جاهز" +يتم تكوين المواصفات بدون خادم مع السحابة/المنطقة + +**Milvus:** +تدير الفئات المباشرة (`DocVectors`، `EntityVectors`) دورة الحياة +ذاكرة تخزين مؤقت داخلية `self.collections[(dim, user, collection)]` للأداء +يتم تنظيف أسماء المجموعات (أحرف وأرقام وشرطة سفلية فقط) +يدعم مخططًا بمعرفات متزايدة تلقائيًا + +### اعتبارات الأداء + +**زمن الوصول للكتابة الأولية:** +تكلفة إضافية بسبب إنشاء المجموعة +Qdrant: ~100-500 مللي ثانية +Pinecone: ~10-30 ثانية (توفير بدون خادم) +Milvus: ~500-2000 مللي ثانية (يتضمن الفهرسة) + +**أداء الاستعلام:** +يضيف التحقق من الوجود تكلفة إضافية ضئيلة (~1-10 مللي ثانية) +لا يوجد تأثير على الأداء بمجرد وجود المجموعة +يتم تحسين كل مجموعة أبعاد بشكل مستقل + +**تكلفة التخزين:** +بيانات وصفية قليلة لكل مجموعة +التكلفة الرئيسية هي التخزين لكل بُعد +مقايضة: مساحة التخزين مقابل مرونة الأبعاد + +## اعتبارات مستقبلية + +**توحيد الأبعاد التلقائي:** +يمكن إضافة عملية خلفية لتحديد ودمج متغيرات الأبعاد غير المستخدمة +سيتطلب ذلك إعادة تضمين أو تقليل الأبعاد + +**اكتشاف الأبعاد:** +يمكن تعريض واجهة برمجة تطبيقات لسرد جميع الأبعاد المستخدمة لمجموعة +مفيد للإدارة والمراقبة + +**تفضيل الأبعاد الافتراضي:** +يمكن تتبع "البُعد الأساسي" لكل مجموعة +يستخدم للاستعلامات عندما يكون سياق البُعد غير متاح + +**حصص التخزين:** +قد تكون هناك حاجة إلى حدود الأبعاد لكل مجموعة +يمنع الانتشار المفرط لمتغيرات الأبعاد + +## ملاحظات حول الترحيل + +**من نظام لاحقة الأبعاد القديم:** +المجموعات القديمة: `d_{user}_{collection}` (بدون لاحقة البُعد) +المجموعات الجديدة: `d_{user}_{collection}_{dim}` (مع لاحقة البُعد) +لا يوجد ترحيل تلقائي - تظل المجموعات القديمة قابلة للوصول +ضع في اعتبارك برنامج ترحيل يدوي إذا لزم الأمر +يمكن تشغيل كلا نظامي التسمية في وقت واحد + +## المراجع + +إدارة المجموعات: `docs/tech-specs/collection-management.md` +مخطط التخزين: `trustgraph-base/trustgraph/schema/services/storage.py` +خدمة أمين المكتبة: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.es.md b/docs/tech-specs/vector-store-lifecycle.es.md new file mode 100644 index 00000000..627206d0 --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.es.md @@ -0,0 +1,307 @@ +--- +layout: default +title: "Gestión del ciclo de vida del almacén de vectores" +parent: "Spanish (Beta)" +--- + +# Gestión del ciclo de vida del almacén de vectores + +> **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 cómo TrustGraph gestiona las colecciones de almacenes de vectores en diferentes implementaciones de backend (Qdrant, Pinecone, Milvus). El diseño aborda el desafío de admitir incrustaciones con diferentes dimensiones sin codificar valores de dimensión. + +## Declaración del problema + +Los almacenes de vectores requieren que se especifique la dimensión de la incrustación al crear colecciones/índices. Sin embargo: +Los diferentes modelos de incrustación producen diferentes dimensiones (por ejemplo, 384, 768, 1536) +La dimensión no se conoce hasta que se genera la primera incrustación +Una sola colección de TrustGraph puede recibir incrustaciones de múltiples modelos +Codificar una dimensión (por ejemplo, 384) causa fallos con otros tamaños de incrustación + +## Principios de diseño + +1. **Creación perezosa**: Las colecciones se crean bajo demanda durante la primera escritura, no durante las operaciones de gestión de colecciones. +2. **Nombres basados en la dimensión**: Los nombres de las colecciones incluyen la dimensión de la incrustación como sufijo. +3. **Degradación gradual**: Las consultas contra colecciones inexistentes devuelven resultados vacíos, no errores. +4. **Soporte para múltiples dimensiones**: Una sola colección lógica puede tener múltiples colecciones físicas (una por dimensión). + +## Arquitectura + +### Convención de nombres de colecciones + +Las colecciones del almacén de vectores utilizan sufijos de dimensión para admitir múltiples tamaños de incrustación: + +**Incrustaciones de documentos:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**Incrustaciones de gráficos:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +Ejemplos: +`d_alice_papers_384` - Colección de documentos de Alice con incrustaciones de 384 dimensiones +`d_alice_papers_768` - Misma colección lógica con incrustaciones de 768 dimensiones +`t_bob_knowledge_1536` - Gráfico de conocimiento de Bob con incrustaciones de 1536 dimensiones + +### Fases del ciclo de vida + +#### 1. Solicitud de creación de colección + +**Flujo de solicitud:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**Comportamiento:** +El bibliotecario transmite las solicitudes `create-collection` a todos los backends de almacenamiento. +Los procesadores de almacenes vectoriales reconocen la solicitud, pero **no crean colecciones físicas**. +La respuesta se devuelve inmediatamente con éxito. +La creación real de la colección se pospone hasta la primera escritura. + +**Justificación:** +La dimensión es desconocida en el momento de la creación. +Evita la creación de colecciones con dimensiones incorrectas. +Simplifica la lógica de gestión de colecciones. + +#### 2. Operaciones de escritura (Creación diferida) + +**Flujo de escritura:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**Comportamiento:** +1. Extraer la dimensión de incrustación del vector: `dim = len(vector)` +2. Construir el nombre de la colección con el sufijo de dimensión +3. Verificar si la colección existe con esa dimensión específica +4. Si no existe: + Crear la colección con la dimensión correcta + Registrar: `"Lazily creating collection {name} with dimension {dim}"` +5. Insertar la incrustación en la colección específica de la dimensión + +**Escenario de ejemplo:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. Operaciones de consulta + +**Flujo de consulta:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**Comportamiento:** +1. Extraer la dimensión del vector de consulta: `dim = len(vector)` +2. Construir el nombre de la colección con el sufijo de dimensión +3. Comprobar si la colección existe +4. Si existe: + Realizar una búsqueda de similitud + Devolver los resultados +5. Si no existe: + Registrar: `"Collection {name} does not exist, returning empty results"` + Devolver una lista vacía (no se genera ningún error) + +**Múltiples Dimensiones en la Misma Consulta:** +Si la consulta contiene vectores de diferentes dimensiones +Cada dimensión consulta su colección correspondiente +Los resultados se agregan +Las colecciones faltantes se omiten (no se consideran errores) + +**Justificación:** +Consultar una colección vacía es un caso de uso válido +Devolver resultados vacíos es semánticamente correcto +Evita errores durante el inicio del sistema o antes de la ingesta de datos + +#### 4. Eliminación de Colecciones + +**Flujo de Eliminación:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**Comportamiento:** +1. Construir el patrón de prefijo: `d_{user}_{collection}_` (observar el guion bajo al final) +2. Listar todas las colecciones en el almacén vectorial +3. Filtrar las colecciones que coincidan con el prefijo +4. Eliminar todas las colecciones que coincidan +5. Registrar cada eliminación: `"Deleted collection {name}"` +6. Registro resumido: `"Deleted {count} collection(s) for {user}/{collection}"` + +**Ejemplo:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**Justificación:** +Asegura una limpieza completa de todas las variantes de dimensión. +La coincidencia de patrones evita la eliminación accidental de colecciones no relacionadas. +Operación atómica desde la perspectiva del usuario (todas las dimensiones se eliminan juntas). + +## Características de comportamiento + +### Operaciones normales + +**Creación de colecciones:** +✓ Devuelve éxito inmediatamente. +✓ No se asigna almacenamiento físico. +✓ Operación rápida (sin E/S de backend). + +**Primera escritura:** +✓ Crea la colección con la dimensión correcta. +✓ Ligeramente más lenta debido a la sobrecarga de la creación de la colección. +✓ Las escrituras posteriores a la misma dimensión son rápidas. + +**Consultas antes de cualquier escritura:** +✓ Devuelve resultados vacíos. +✓ No hay errores ni excepciones. +✓ El sistema permanece estable. + +**Escrituras de dimensiones mixtas:** +✓ Crea automáticamente colecciones separadas por dimensión. +✓ Cada dimensión está aislada en su propia colección. +✓ No hay conflictos de dimensiones ni errores de esquema. + +**Eliminación de colecciones:** +✓ Elimina todas las variantes de dimensión. +✓ Limpieza completa. +✓ No hay colecciones huérfanas. + +### Casos límite + +**Múltiples modelos de incrustación:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**Primeras Escrituras Concurrentes:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**Migración de Dimensiones:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**Consultas de Colecciones Vacías:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## Notas de Implementación + +### Detalles Específicos del Backend de Almacenamiento + +**Qdrant:** +Utiliza `collection_exists()` para verificaciones de existencia +Utiliza `get_collections()` para listar durante la eliminación +La creación de colecciones requiere `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +Utiliza `has_index()` para verificaciones de existencia +Utiliza `list_indexes()` para listar durante la eliminación +La creación de índices requiere esperar el estado "ready" +La especificación serverless se configura con la región de la nube + +**Milvus:** +Las clases directas (`DocVectors`, `EntityVectors`) gestionan el ciclo de vida +Caché interno `self.collections[(dim, user, collection)]` para mejorar el rendimiento +Los nombres de las colecciones se sanitizan (solo alfanumérico y guión bajo) +Admite esquemas con IDs de auto-incremento + +### Consideraciones de Rendimiento + +**Latencia de la Primera Escritura:** +Sobrecarga adicional debido a la creación de la colección +Qdrant: ~100-500ms +Pinecone: ~10-30 segundos (provisionamiento serverless) +Milvus: ~500-2000ms (incluye indexación) + +**Rendimiento de la Consulta:** +La verificación de existencia agrega una sobrecarga mínima (~1-10ms) +No hay impacto en el rendimiento una vez que la colección existe +Cada colección de dimensiones se optimiza de forma independiente + +**Sobrecarga de Almacenamiento:** +Metadatos mínimos por colección +La principal sobrecarga es el almacenamiento por dimensión +Compromiso: Espacio de almacenamiento vs. flexibilidad de las dimensiones + +## Consideraciones Futuras + +**Consolidación Automática de Dimensiones:** +Se podría agregar un proceso en segundo plano para identificar y fusionar variantes de dimensiones no utilizadas +Requeriría re-embedding o reducción de dimensiones + +**Descubrimiento de Dimensiones:** +Se podría exponer una API para listar todas las dimensiones utilizadas para una colección +Útil para la administración y el monitoreo + +**Preferencia de Dimensión Predeterminada:** +Se podría rastrear la dimensión "primaria" por colección +Utilizar para consultas cuando el contexto de la dimensión no está disponible + +**Cuotas de Almacenamiento:** +Es posible que se necesiten límites de dimensiones por colección +Prevenir la proliferación de variantes de dimensiones + +## Notas de Migración + +**Desde el Sistema de Sufijo de Dimensión Anterior:** +Colecciones antiguas: `d_{user}_{collection}` (sin sufijo de dimensión) +Colecciones nuevas: `d_{user}_{collection}_{dim}` (con sufijo de dimensión) +No hay migración automática: las colecciones antiguas permanecen accesibles +Considere un script de migración manual si es necesario +Se pueden ejecutar ambos esquemas de nombres simultáneamente + +## Referencias + +Gestión de Colecciones: `docs/tech-specs/collection-management.md` +Esquema de Almacenamiento: `trustgraph-base/trustgraph/schema/services/storage.py` +Servicio de Bibliotecario: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.he.md b/docs/tech-specs/vector-store-lifecycle.he.md new file mode 100644 index 00000000..e2d0fb1e --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.he.md @@ -0,0 +1,307 @@ +--- +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 מנהלת אוספי מאגרי וקטורים על פני יישומים שונים (Qdrant, Pinecone, Milvus). העיצוב מתמודד עם האתגר של תמיכה בהטבעות עם ממדים שונים מבלי לקודד ערכי ממדים באופן קשיח. + +## הצהרת בעיה + +מאגרי וקטורים דורשים ציון הממד של ההטבעה בעת יצירת אוספים/אינדקסים. עם זאת: +מודלים שונים של הטבעה מייצרים ממדים שונים (לדוגמה, 384, 768, 1536) +הממד אינו ידוע עד ליצירת ההטבעה הראשונה +אוסף TrustGraph יחיד עשוי לקבל הטבעות ממודלים מרובים +קידוד קשיח של ממד (לדוגמה, 384) גורם לכשלים עם גדלי הטבעה אחרים + +## עקרונות עיצוב + +1. **יצירה עצלה**: אוספים נוצרים לפי דרישה במהלך הכתיבה הראשונה, ולא במהלך פעולות ניהול אוספים. +2. **שמות המבוססים על ממד**: שמות האוספים כוללים את הממד כסיומת. +3. **התדרדרות חלקה**: שאילתות לאוספים שאינם קיימים מחזירות תוצאות ריקות, ולא שגיאות. +4. **תמיכה במספר ממדים**: אוסף לוגי יחיד יכול לכלול מספר אוספים פיזיים (אחד לכל ממד). + +## ארכיטקטורה + +### מוסכמות מתן שמות לאוספים + +אוספי מאגרי וקטורים משתמשים בסיומות ממד כדי לתמוך במספר גדלי הטבעה: + +**הטבעות מסמכים:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**הטבעות גרף:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +דוגמאות: +`d_alice_papers_384` - אוסף המאמרים של אליס עם הטבעות ממדיות של 384. +`d_alice_papers_768` - אותו אוסף לוגי עם הטבעות ממדיות של 768. +`t_bob_knowledge_1536` - גרף הידע של בוב עם הטבעות ממדיות של 1536. + +### שלבי מחזור חיים + +#### 1. בקשת יצירת אוסף + +**זרימת בקשה:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**התנהגות:** +הספרן משדר בקשות `create-collection` לכל אחסוני הנתונים. +מעבדי אחסון וקטורים מאשרים את הבקשה, אך **אינם יוצרים אוספים פיזיים**. +התגובה מוחזרת מיד עם הצלחה. +יצירת האוסף בפועל נדחית עד לכתיבה הראשונה. + +**ההצדקה:** +המימד אינו ידוע בזמן היצירה. +מונע יצירת אוספים עם מימדים שגויים. +מפשט את לוגיקת ניהול האוספים. + +#### 2. פעולות כתיבה (יצירה עצלה) + +**זרימת הכתיבה:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**התנהגות:** +1. חילוץ ממד ההטבעה מהווקטור: `dim = len(vector)` +2. יצירת שם אוסף עם סיומת הממד +3. בדיקה האם קיים אוסף עם אותו ממד ספציפי +4. אם לא קיים: + יצירת אוסף עם הממד הנכון + רישום: `"Lazily creating collection {name} with dimension {dim}"` +5. הכנסת ההטבעה לאוסף הספציפי לממד + +**תרחיש לדוגמה:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. פעולות שאילתה + +**זרימת השאילתה:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**התנהגות:** +1. חילוץ מימד מהווקטור של השאילתה: `dim = len(vector)` +2. יצירת שם אוסף עם סיומת המציינת את המימד +3. בדיקה האם האוסף קיים +4. אם קיים: + ביצוע חיפוש דמיון + החזרת תוצאות +5. אם לא קיים: + רישום: `"Collection {name} does not exist, returning empty results"` + החזרת רשימה ריקה (ללא העלאת שגיאה) + +**מימדים מרובים באותה שאילתה:** +אם השאילתה מכילה וקטורים של מימדים שונים +כל מימד מבצע שאילתה על האוסף המתאים לו +התוצאות מאוחדות +אוספים חסרים מדלגים (לא מטופלים כשגיאות) + +**ההצדקה:** +שאילתה על אוסף ריק היא מקרה שימוש חוקי +החזרת תוצאות ריקות היא נכונה מבחינה סמנטית +מונע שגיאות במהלך אתחול המערכת או לפני טעינת נתונים + +#### 4. מחיקת אוסף + +**תהליך מחיקה:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**התנהגות:** +1. בניית תבנית קידומת: `d_{user}_{collection}_` (שימו לב לקו התחתון בסוף) +2. רשימת כל האוספים במאגר הווקטורים +3. סינון אוספים התואמים לקידומת +4. מחיקת כל האוספים התואמים +5. רישום כל מחיקה: `"Deleted collection {name}"` +6. רישום סיכום: `"Deleted {count} collection(s) for {user}/{collection}"` + +**דוגמה:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**הסבר:** +מבטיח ניקוי מלא של כל וריאציות המימדים. +התאמת תבניות מונעת מחיקה בשוגע של אוספים לא קשורים. +פעולה אטומית מנקודת מבטו של המשתמש (כל המימדים נמחקים יחד). + +## מאפיינים התנהגותיים + +### פעולות רגילות + +**יצירת אוסף:** +✓ מחזיר הצלחה באופן מיידי. +✓ לא מוקצה אחסון פיזי. +✓ פעולה מהירה (ללא קלט/פלט של מערכת הפעלה). + +**כתיבה ראשונה:** +✓ יוצר אוסף עם מימד נכון. +✓ מעט איטי יותר עקב תקורה של יצירת האוסף. +✓ כתיבות עוקבות לאותו מימד מהירות. + +**שאילתות לפני כל כתיבה:** +✓ מחזיר תוצאות ריקות. +✓ אין שגיאות או חריגות. +✓ המערכת נשארת יציבה. + +**כתיבות של מימדים שונים:** +✓ יוצר באופן אוטומטי אוספים נפרדים לכל מימד. +✓ כל מימד מבודד באוסף משלו. +✓ אין התנגשויות מימדים או שגיאות סכימה. + +**מחיקת אוסף:** +✓ מסיר את כל וריאציות המימדים. +✓ ניקוי מלא. +✓ אין אוספים יתומים. + +### מקרים קצה + +**מודלים משובצים מרובים:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**כתיבות ראשוניות מקבילות:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**הגירה של ממדים:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**שאילתות לאוספים ריקים:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## הערות יישום + +### פרטים ספציפיים לגבי אחסון + +**Qdrant:** +משתמש ב-`collection_exists()` לבדיקות קיום +משתמש ב-`get_collections()` לרשימה במהלך מחיקה +יצירת אוסף דורשת `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +משתמש ב-`has_index()` לבדיקות קיום +משתמש ב-`list_indexes()` לרשימה במהלך מחיקה +יצירת אינדקס דורשת המתנה למצב "מוכן" +מפרט שרת חסר מוגדר עם ענן/אזור + +**Milvus:** +מחלקות ישירות (`DocVectors`, `EntityVectors`) מנהלות את מחזור החיים +מטמון פנימי `self.collections[(dim, user, collection)]` לביצועים +שמות אוספים עוברים סינון (רק תווים אלפאנומריים וקו תחתון) +תומך בסכימה עם מזהים עם הגדלה אוטומטית + +### שיקולי ביצועים + +**זמן השהייה לכתיבה ראשונה:** +תקורה נוספת עקב יצירת אוסף +Qdrant: ~100-500ms +Pinecone: ~10-30 שניות (הקצאת שרת חסר) +Milvus: ~500-2000ms (כולל אינדקס) + +**ביצועי שאילתות:** +בדיקת קיום מוסיפה תקורה מינימלית (~1-10ms) +אין השפעה על הביצועים לאחר יצירת האוסף +כל אוסף ממד מותאם באופן עצמאי + +**תקורה של אחסון:** +מטא-דאטה מינימלי לכל אוסף +התקורה העיקרית היא אחסון לכל ממד +פשרה: שטח אחסון לעומת גמישות ממדים + +## שיקולים עתידיים + +**איחוד ממדים אוטומטי:** +ניתן להוסיף תהליך רקע לזיהוי ומיזוג גרסאות ממדים לא בשימוש +זה ידרוש הטמעה מחדש או צמצום ממדים + +**גילוי ממדים:** +ניתן לחשוף API לרשימת כל הממדים בשימוש עבור אוסף +שימושי לניהול וניטור + +**העדפה ברירת מחדל לממד:** +ניתן לעקוב אחר "ממד ראשי" לכל אוסף +להשתמש עבור שאילתות כאשר הקשר הממד אינו זמין + +**מכסות אחסון:** +ייתכן שיהיה צורך במגבלות ממדים לכל אוסף +למנוע התרבות של גרסאות ממדים + +## הערות העברה + +**ממערכת קודמת עם סיומת ממד:** +אוספים ישנים: `d_{user}_{collection}` (ללא סיומת ממד) +אוספים חדשים: `d_{user}_{collection}_{dim}` (עם סיומת ממד) +אין העברה אוטומטית - אוספים ישנים נשארים נגישים +שקול סקריפט העברה ידני אם יש צורך +ניתן להפעיל שני סכימות שמות בו זמנית + +## הפניות + +ניהול אוספים: `docs/tech-specs/collection-management.md` +סכימת אחסון: `trustgraph-base/trustgraph/schema/services/storage.py` +שירות ספרית: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.hi.md b/docs/tech-specs/vector-store-lifecycle.hi.md new file mode 100644 index 00000000..f2fdcf7a --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.hi.md @@ -0,0 +1,307 @@ +--- +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. + +## अवलोकन + +यह दस्तावेज़ बताता है कि ट्रस्टग्राफ विभिन्न बैकएंड कार्यान्वयन (क्यूड्रेंट, पाइनकोन, मिल्वस) में वेक्टर स्टोर संग्रहों का प्रबंधन कैसे करता है। डिज़ाइन विभिन्न आयामों वाले एम्बेडिंग का समर्थन करने की चुनौती को संबोधित करता है बिना आयाम मानों को हार्डकोड किए। + +## समस्या विवरण + +वेक्टर स्टोर को संग्रह/इंडेक्स बनाते समय एम्बेडिंग आयाम को निर्दिष्ट करने की आवश्यकता होती है। हालाँकि: +विभिन्न एम्बेडिंग मॉडल अलग-अलग आयाम उत्पन्न करते हैं (उदाहरण के लिए, 384, 768, 1536) +आयाम तब तक ज्ञात नहीं होता है जब तक कि पहला एम्बेडिंग उत्पन्न नहीं हो जाता +एक ही ट्रस्टग्राफ संग्रह कई मॉडलों से एम्बेडिंग प्राप्त कर सकता है +एक आयाम को हार्डकोड करना (उदाहरण के लिए, 384) अन्य एम्बेडिंग आकारों के साथ विफलताओं का कारण बनता है + +## डिज़ाइन सिद्धांत + +1. **आलसी निर्माण**: संग्रह पहली बार लिखने के दौरान ऑन-डिमांड बनाए जाते हैं, संग्रह प्रबंधन कार्यों के दौरान नहीं। +2. **आयाम-आधारित नामकरण**: संग्रह नामों में एम्बेडिंग आयाम को एक प्रत्यय के रूप में शामिल किया जाता है। +3. **सुचारू गिरावट**: गैर-मौजूदा संग्रहों के खिलाफ किए गए प्रश्नों से त्रुटियां नहीं, बल्कि खाली परिणाम मिलते हैं। +4. **बहु-आयाम समर्थन**: एक ही तार्किक संग्रह में कई भौतिक संग्रह (प्रत्येक आयाम के लिए एक) हो सकते हैं। + +## वास्तुकला + +### संग्रह नामकरण सम्मेलन + +वेक्टर स्टोर संग्रह कई एम्बेडिंग आकारों का समर्थन करने के लिए आयाम प्रत्ययों का उपयोग करते हैं: + +**दस्तावेज़ एम्बेडिंग:** +क्यूड्रेंट: `d_{user}_{collection}_{dimension}` +पाइनकोन: `d-{user}-{collection}-{dimension}` +मिल्वस: `doc_{user}_{collection}_{dimension}` + +**ग्राफ एम्बेडिंग:** +क्यूड्रेंट: `t_{user}_{collection}_{dimension}` +पाइनकोन: `t-{user}-{collection}-{dimension}` +मिल्वस: `entity_{user}_{collection}_{dimension}` + +उदाहरण: +`d_alice_papers_384` - 384-आयामी एम्बेडिंग वाले एलिस के पेपर संग्रह +`d_alice_papers_768` - 768-आयामी एम्बेडिंग वाले समान तार्किक संग्रह +`t_bob_knowledge_1536` - 1536-आयामी एम्बेडिंग वाले बॉब के ज्ञान ग्राफ + +### जीवनचक्र चरण + +#### 1. संग्रह निर्माण अनुरोध + +**अनुरोध प्रवाह:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**व्यवहार:** +लाइब्रेरियन `create-collection` अनुरोधों को सभी स्टोरेज बैकएंड्स को भेजता है। +वेक्टर स्टोर प्रोसेसर अनुरोध को स्वीकार करते हैं लेकिन **भौतिक संग्रह नहीं बनाते हैं।** +प्रतिक्रिया तुरंत सफलता के साथ वापस की जाती है। +वास्तविक संग्रह निर्माण पहले लिखने तक स्थगित रहता है। + +**तर्क:** +निर्माण के समय आयाम अज्ञात होता है। +गलत आयाम वाले संग्रह बनाने से बचा जाता है। +संग्रह प्रबंधन तर्क को सरल बनाता है। + +#### 2. लेखन संचालन (आलसी निर्माण) + +**लेखन प्रवाह:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**व्यवहार:** +1. वेक्टर से एम्बेडिंग आयाम निकालें: `dim = len(vector)` +2. आयाम प्रत्यय के साथ संग्रह का नाम बनाएं +3. जांचें कि क्या उस विशिष्ट आयाम के साथ कोई संग्रह मौजूद है +4. यदि मौजूद नहीं है: + सही आयाम के साथ संग्रह बनाएं + लॉग करें: `"Lazily creating collection {name} with dimension {dim}"` +5. एम्बेडिंग को आयाम-विशिष्ट संग्रह में डालें + +**उदाहरण परिदृश्य:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. क्वेरी ऑपरेशन + +**क्वेरी प्रवाह:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**व्यवहार:** +1. क्वेरी वेक्टर से आयाम निकालें: `dim = len(vector)` +2. आयाम प्रत्यय के साथ संग्रह नाम बनाएं +3. जांचें कि संग्रह मौजूद है या नहीं +4. यदि मौजूद है: + समानता खोज करें + परिणाम लौटाएं +5. यदि मौजूद नहीं है: + लॉग करें: `"Collection {name} does not exist, returning empty results"` + खाली सूची लौटाएं (कोई त्रुटि नहीं) + +**एक ही क्वेरी में कई आयाम:** +यदि क्वेरी में विभिन्न आयामों वाले वेक्टर हैं +प्रत्येक आयाम अपने संबंधित संग्रह को क्वेरी करता है +परिणाम एकत्रित किए जाते हैं +गुम संग्रह को छोड़ दिया जाता है (त्रुटियों के रूप में नहीं माना जाता है) + +**तर्क:** +एक खाली संग्रह को क्वेरी करना एक वैध उपयोग मामला है +खाली परिणाम लौटाना अर्थपूर्ण रूप से सही है +सिस्टम स्टार्टअप के दौरान या डेटा इनपुट से पहले त्रुटियों से बचाता है + +#### 4. संग्रह हटाना + +**हटाने की प्रक्रिया:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**व्यवहार:** +1. उपसर्ग पैटर्न का निर्माण करें: `d_{user}_{collection}_` (अंतिम अंडरस्कोर पर ध्यान दें) +2. वेक्टर स्टोर में सभी संग्रहों की सूची बनाएं +3. उपसर्ग से मेल खाने वाले संग्रहों को फ़िल्टर करें +4. सभी मेल खाने वाले संग्रहों को हटाएं +5. प्रत्येक हटाने को लॉग करें: `"Deleted collection {name}"` +6. सारांश लॉग: `"Deleted {count} collection(s) for {user}/{collection}"` + +**उदाहरण:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**तर्क:** +सभी आयाम रूपों की पूरी तरह से सफाई सुनिश्चित करता है। +पैटर्न मिलान से असंबंधित संग्रहों को गलती से हटाने से रोका जाता है। +उपयोगकर्ता के दृष्टिकोण से परमाणु ऑपरेशन (सभी आयाम एक साथ हटा दिए जाते हैं)। + +## व्यवहार संबंधी विशेषताएं + +### सामान्य संचालन + +**संग्रह निर्माण:** +✓ तुरंत सफलता देता है। +✓ कोई भौतिक भंडारण आवंटित नहीं किया जाता है। +✓ तेज़ ऑपरेशन (कोई बैकएंड I/O नहीं)। + +**पहला लेखन:** +✓ सही आयाम के साथ संग्रह बनाता है। +✓ संग्रह निर्माण के ओवरहेड के कारण थोड़ा धीमा। +✓ उसी आयाम में बाद के लेखन तेज़ होते हैं। + +**किसी भी लेखन से पहले प्रश्न:** +✓ खाली परिणाम देता है। +✓ कोई त्रुटि या अपवाद नहीं। +✓ सिस्टम स्थिर रहता है। + +**मिश्रित आयाम लेखन:** +✓ स्वचालित रूप से प्रत्येक आयाम के लिए अलग-अलग संग्रह बनाता है। +✓ प्रत्येक आयाम अपने स्वयं के संग्रह में अलग-थलग होता है। +✓ कोई आयाम संघर्ष या स्कीमा त्रुटि नहीं होती है। + +**संग्रह हटाना:** +✓ सभी आयाम रूपों को हटा देता है। +✓ पूर्ण सफाई। +✓ कोई अनाथ संग्रह नहीं। + +### विशेष स्थितियाँ + +**एकाधिक एम्बेडिंग मॉडल:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**एक साथ प्रारंभिक लेखन:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**आयाम प्रवासन:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**खाली संग्रह प्रश्नों:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## कार्यान्वयन नोट्स + +### स्टोरेज बैकएंड विशिष्ट विवरण + +**Qdrant:** +अस्तित्व जांच के लिए `collection_exists()` का उपयोग करता है +हटाने के दौरान लिस्टिंग के लिए `get_collections()` का उपयोग करता है +संग्रह निर्माण के लिए `VectorParams(size=dim, distance=Distance.COSINE)` की आवश्यकता होती है + +**Pinecone:** +अस्तित्व जांच के लिए `has_index()` का उपयोग करता है +हटाने के दौरान लिस्टिंग के लिए `list_indexes()` का उपयोग करता है +इंडेक्स निर्माण के लिए "तैयार" स्थिति की प्रतीक्षा करने की आवश्यकता होती है +सर्वरलेस विनिर्देश क्लाउड/क्षेत्र के साथ कॉन्फ़िगर किया गया है + +**Milvus:** +डायरेक्ट क्लासेस (`DocVectors`, `EntityVectors`) लाइफसाइकिल का प्रबंधन करती हैं +प्रदर्शन के लिए आंतरिक कैश `self.collections[(dim, user, collection)]` +संग्रह नामों को सैनिटाइज किया जाता है (केवल अल्फ़ान्यूमेरिक + अंडरस्कोर) +ऑटो-इंक्रीमेंटिंग आईडी के साथ स्कीमा का समर्थन करता है + +### प्रदर्शन संबंधी विचार + +**पहली लेखन विलंबता:** +संग्रह निर्माण के कारण अतिरिक्त ओवरहेड +Qdrant: ~100-500ms +Pinecone: ~10-30 सेकंड (सर्वरलेस प्रावधान) +Milvus: ~500-2000ms (इसमें इंडेक्सिंग शामिल है) + +**क्वेरी प्रदर्शन:** +अस्तित्व जांच से न्यूनतम ओवरहेड जुड़ता है (~1-10ms) +एक बार संग्रह मौजूद होने पर कोई प्रदर्शन प्रभाव नहीं पड़ता है +प्रत्येक आयाम संग्रह स्वतंत्र रूप से अनुकूलित है + +**स्टोरेज ओवरहेड:** +प्रति संग्रह न्यूनतम मेटाडेटा +मुख्य ओवरहेड प्रति-आयाम स्टोरेज है +ट्रेड-ऑफ: स्टोरेज स्पेस बनाम आयाम लचीलापन + +## भविष्य के विचार + +**स्वचालित आयाम समेकन:** +अप्रयुक्त आयाम वेरिएंट की पहचान और विलय करने के लिए एक पृष्ठभूमि प्रक्रिया जोड़ी जा सकती है +इसके लिए पुनः एम्बेडिंग या आयाम में कमी की आवश्यकता होगी + +**आयाम खोज:** +एक संग्रह के लिए उपयोग किए जा रहे सभी आयामों को सूचीबद्ध करने के लिए एपीआई उजागर किया जा सकता है +प्रशासन और निगरानी के लिए उपयोगी + +**डिफ़ॉल्ट आयाम प्राथमिकता:** +प्रति संग्रह "प्राथमिक" आयाम को ट्रैक किया जा सकता है +जब आयाम संदर्भ अनुपलब्ध हो तो प्रश्नों के लिए इसका उपयोग करें + +**स्टोरेज कोटा:** +प्रति-संग्रह आयाम सीमाएं आवश्यक हो सकती हैं +आयाम वेरिएंट के प्रसार को रोकें + +## माइग्रेशन नोट्स + +**प्री-डायमेंशन-सफिक्स सिस्टम से:** +पुराने संग्रह: `d_{user}_{collection}` (कोई आयाम प्रत्यय नहीं) +नए संग्रह: `d_{user}_{collection}_{dim}` (आयाम प्रत्यय के साथ) +कोई स्वचालित माइग्रेशन नहीं - पुराने संग्रह सुलभ रहते हैं +यदि आवश्यक हो तो एक मैनुअल माइग्रेशन स्क्रिप्ट पर विचार करें +दोनों नामकरण योजनाओं को एक साथ चलाया जा सकता है + +## संदर्भ + +संग्रह प्रबंधन: `docs/tech-specs/collection-management.md` +स्टोरेज स्कीमा: `trustgraph-base/trustgraph/schema/services/storage.py` +लाइब्रेरियन सेवा: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.md b/docs/tech-specs/vector-store-lifecycle.md index dcbb73e1..d533b49b 100644 --- a/docs/tech-specs/vector-store-lifecycle.md +++ b/docs/tech-specs/vector-store-lifecycle.md @@ -1,3 +1,9 @@ +--- +layout: default +title: "Vector Store Lifecycle Management" +parent: "Tech Specs" +--- + # Vector Store Lifecycle Management ## Overview diff --git a/docs/tech-specs/vector-store-lifecycle.pt.md b/docs/tech-specs/vector-store-lifecycle.pt.md new file mode 100644 index 00000000..d154999e --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.pt.md @@ -0,0 +1,307 @@ +--- +layout: default +title: "Gerenciamento do Ciclo de Vida do Vector Store" +parent: "Portuguese (Beta)" +--- + +# Gerenciamento do Ciclo de Vida do Vector Store + +> **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 como o TrustGraph gerencia coleções de vector store em diferentes implementações de backend (Qdrant, Pinecone, Milvus). O design aborda o desafio de suportar embeddings com diferentes dimensões sem codificar valores de dimensão. + +## Declaração do Problema + +Os vector stores exigem que a dimensão do embedding seja especificada ao criar coleções/índices. No entanto: +Modelos de embedding diferentes produzem dimensões diferentes (por exemplo, 384, 768, 1536) +A dimensão não é conhecida até que o primeiro embedding seja gerado +Uma única coleção do TrustGraph pode receber embeddings de vários modelos +A codificação de uma dimensão (por exemplo, 384) causa falhas com outros tamanhos de embedding + +## Princípios de Design + +1. **Criação Preguiçosa (Lazy Creation)**: As coleções são criadas sob demanda durante a primeira escrita, e não durante as operações de gerenciamento de coleção. +2. **Nomeação Baseada em Dimensão**: Os nomes das coleções incluem a dimensão do embedding como um sufixo. +3. **Degradação Graciosa**: As consultas contra coleções inexistentes retornam resultados vazios, e não erros. +4. **Suporte a Múltiplas Dimensões**: Uma única coleção lógica pode ter várias coleções físicas (uma por dimensão). + +## Arquitetura + +### Convenção de Nomenclatura de Coleções + +As coleções de vector store usam sufixos de dimensão para suportar vários tamanhos de embedding: + +**Embeddings de Documentos:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**Embeddings de Grafos:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +Exemplos: +`d_alice_papers_384` - Coleção de artigos da Alice com embeddings de 384 dimensões +`d_alice_papers_768` - Mesma coleção lógica com embeddings de 768 dimensões +`t_bob_knowledge_1536` - Grafo de conhecimento do Bob com embeddings de 1536 dimensões + +### Fases do Ciclo de Vida + +#### 1. Solicitação de Criação de Coleção + +**Fluxo da Solicitação:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**Comportamento:** +O bibliotecário transmite solicitações `create-collection` para todos os backends de armazenamento. +Os processadores de armazenamento vetorial confirmam a solicitação, mas **não criam coleções físicas**. +A resposta é retornada imediatamente com sucesso. +A criação real da coleção é adiada até a primeira escrita. + +**Justificativa:** +A dimensão é desconhecida no momento da criação. +Evita a criação de coleções com dimensões incorretas. +Simplifica a lógica de gerenciamento de coleções. + +#### 2. Operações de Escrita (Criação Preguiçosa) + +**Fluxo de Escrita:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**Comportamento:** +1. Extrair a dimensão do embedding do vetor: `dim = len(vector)` +2. Construir o nome da coleção com o sufixo da dimensão +3. Verificar se a coleção existe com essa dimensão específica +4. Se não existir: + Criar a coleção com a dimensão correta + Registrar: `"Lazily creating collection {name} with dimension {dim}"` +5. Inserir o embedding na coleção específica da dimensão + +**Cenário de Exemplo:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. Operações de Consulta + +**Fluxo de Consulta:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**Comportamento:** +1. Extrair a dimensão do vetor de consulta: `dim = len(vector)` +2. Construir o nome da coleção com o sufixo da dimensão +3. Verificar se a coleção existe +4. Se existir: + Realizar uma busca de similaridade + Retornar os resultados +5. Se não existir: + Registrar: `"Collection {name} does not exist, returning empty results"` + Retornar uma lista vazia (nenhum erro é gerado) + +**Múltiplas Dimensões na Mesma Consulta:** +Se a consulta contiver vetores de dimensões diferentes +Cada dimensão consulta sua coleção correspondente +Os resultados são agregados +As coleções ausentes são ignoradas (não são tratadas como erros) + +**Justificativa:** +Consultar uma coleção vazia é um caso de uso válido +Retornar resultados vazios é semanticamente correto +Evita erros durante a inicialização do sistema ou antes da ingestão de dados + +#### 4. Exclusão de Coleção + +**Fluxo de Exclusão:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**Comportamento:** +1. Construir o padrão de prefixo: `d_{user}_{collection}_` (observe o sublinhado no final) +2. Listar todas as coleções no armazenamento vetorial +3. Filtrar as coleções que correspondem ao prefixo +4. Excluir todas as coleções correspondentes +5. Registrar cada exclusão: `"Deleted collection {name}"` +6. Registro resumido: `"Deleted {count} collection(s) for {user}/{collection}"` + +**Exemplo:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**Justificativa:** +Garante a limpeza completa de todas as variantes de dimensão. +A correspondência de padrões evita a exclusão acidental de coleções não relacionadas. +Operação atômica da perspectiva do usuário (todas as dimensões são excluídas juntas). + +## Características Comportamentais + +### Operações Normais + +**Criação de Coleção:** +✓ Retorna sucesso imediatamente. +✓ Nenhum armazenamento físico é alocado. +✓ Operação rápida (sem E/S de backend). + +**Primeira Escrita:** +✓ Cria a coleção com a dimensão correta. +✓ Ligeiramente mais lenta devido à sobrecarga da criação da coleção. +✓ Escritas subsequentes na mesma dimensão são rápidas. + +**Consultas Antes de Qualquer Escrita:** +✓ Retorna resultados vazios. +✓ Nenhum erro ou exceção. +✓ O sistema permanece estável. + +**Escritas de Dimensões Mistas:** +✓ Cria automaticamente coleções separadas por dimensão. +✓ Cada dimensão é isolada em sua própria coleção. +✓ Nenhum conflito de dimensão ou erro de esquema. + +**Exclusão de Coleção:** +✓ Remove todas as variantes de dimensão. +✓ Limpeza completa. +✓ Nenhuma coleção órfã. + +### Casos Limite + +**Múltiplos Modelos de Incorporação:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**Primeiras Escritas Concorrentes:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**Migração de Dimensões:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**Consultas de Coleção Vazia:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## Notas de Implementação + +### Especificidades do Backend de Armazenamento + +**Qdrant:** +Usa `collection_exists()` para verificações de existência +Usa `get_collections()` para listagem durante a exclusão +A criação de coleções requer `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +Usa `has_index()` para verificações de existência +Usa `list_indexes()` para listagem durante a exclusão +A criação de índices requer esperar pelo status "ready" +Especificação serverless configurada com cloud/região + +**Milvus:** +Classes diretas (`DocVectors`, `EntityVectors`) gerenciam o ciclo de vida +Cache interno `self.collections[(dim, user, collection)]` para desempenho +Nomes de coleções são sanitizados (apenas alfanumérico + underscore) +Suporta esquema com IDs de incremento automático + +### Considerações de Desempenho + +**Latência da Primeira Gravação:** +Overhead adicional devido à criação da coleção +Qdrant: ~100-500ms +Pinecone: ~10-30 segundos (provisionamento serverless) +Milvus: ~500-2000ms (inclui indexação) + +**Desempenho da Consulta:** +A verificação de existência adiciona um overhead mínimo (~1-10ms) +Nenhum impacto no desempenho depois que a coleção existe +Cada coleção de dimensões é otimizada independentemente + +**Overhead de Armazenamento:** +Metadados mínimos por coleção +O principal overhead é por armazenamento de dimensão +Compromisso: Espaço de armazenamento vs. flexibilidade de dimensão + +## Considerações Futuras + +**Consolidação Automática de Dimensões:** +Poderia adicionar um processo em segundo plano para identificar e mesclar variantes de dimensões não utilizadas +Requereria re-embedding ou redução de dimensão + +**Descoberta de Dimensões:** +Poderia expor uma API para listar todas as dimensões em uso para uma coleção +Útil para administração e monitoramento + +**Preferência de Dimensão Padrão:** +Poderia rastrear a "dimensão primária" por coleção +Usar para consultas quando o contexto da dimensão não está disponível + +**Quotas de Armazenamento:** +Pode ser necessário limites de dimensão por coleção +Prevenir a proliferação de variantes de dimensão + +## Notas de Migração + +**Do Sistema de Sufixo de Pré-Dimensão:** +Coleções antigas: `d_{user}_{collection}` (sem sufixo de dimensão) +Coleções novas: `d_{user}_{collection}_{dim}` (com sufixo de dimensão) +Nenhuma migração automática - coleções antigas permanecem acessíveis +Considere um script de migração manual, se necessário +Pode executar ambos os esquemas de nomenclatura simultaneamente + +## Referências + +Gerenciamento de Coleções: `docs/tech-specs/collection-management.md` +Esquema de Armazenamento: `trustgraph-base/trustgraph/schema/services/storage.py` +Serviço Librarian: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.ru.md b/docs/tech-specs/vector-store-lifecycle.ru.md new file mode 100644 index 00000000..0ee321bb --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.ru.md @@ -0,0 +1,307 @@ +--- +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 управляет коллекциями векторных хранилищ в различных реализациях бэкенда (Qdrant, Pinecone, Milvus). Проект решает проблему поддержки вложений с разными размерностями без жесткой кодировки значений размерностей. + +## Описание проблемы + +Векторные хранилища требуют указания размерности вложений при создании коллекций/индексов. Однако: +Разные модели вложений генерируют разные размерности (например, 384, 768, 1536). +Размерность неизвестна до генерации первого вложения. +Одна коллекция TrustGraph может получать вложения из нескольких моделей. +Жесткая кодировка размерности (например, 384) приводит к сбоям при использовании других размеров вложений. + +## Принципы проектирования + +1. **Отложенное создание**: Коллекции создаются по запросу при первой записи, а не во время операций управления коллекциями. +2. **Именование на основе размерности**: Имена коллекций включают размерность вложения в качестве суффикса. +3. **Плавное снижение функциональности**: Запросы к несуществующим коллекциям возвращают пустые результаты, а не ошибки. +4. **Поддержка нескольких размерностей**: Одна логическая коллекция может иметь несколько физических коллекций (по одной для каждой размерности). + +## Архитектура + +### Соглашение об именовании коллекций + +Коллекции векторных хранилищ используют суффиксы, указывающие размерность, для поддержки нескольких размеров вложений: + +**Вложения документов:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**Вложения графов:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +Примеры: +`d_alice_papers_384` - Коллекция статей Алисы с вложениями размерностью 384. +`d_alice_papers_768` - Та же логическая коллекция с вложениями размерностью 768. +`t_bob_knowledge_1536` - Граф знаний Боба с вложениями размерностью 1536. + +### Фазы жизненного цикла + +#### 1. Запрос на создание коллекции + +**Поток запросов:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**Поведение:** +Библиотекарь отправляет запросы `create-collection` всем хранилищам данных. +Процессоры векторных хранилищ подтверждают запрос, но **не создают физические коллекции**. +Ответ возвращается немедленно с сообщением об успехе. +Фактическое создание коллекции откладывается до первой записи. + +**Обоснование:** +Размерность неизвестна на момент создания. +Предотвращает создание коллекций с неправильными размерами. +Упрощает логику управления коллекциями. + +#### 2. Операции записи (отложенное создание) + +**Поток записи:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**Поведение:** +1. Извлечь размерность вложения из вектора: `dim = len(vector)` +2. Сформировать имя коллекции с суффиксом, указывающим на размерность. +3. Проверить, существует ли коллекция с указанной размерностью. +4. Если коллекция не существует: + Создать коллекцию с правильной размерностью. + Записать в лог: `"Lazily creating collection {name} with dimension {dim}"` +5. Вставить вложение в коллекцию, специфичную для данной размерности. + +**Пример сценария:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. Операции запросов + +**Поток запросов:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**Поведение:** +1. Извлечение размерности из вектора запроса: `dim = len(vector)` +2. Формирование имени коллекции с суффиксом, указывающим размерность. +3. Проверка наличия коллекции. +4. Если коллекция существует: + Выполнение поиска по схожести. + Возврат результатов. +5. Если коллекция не существует: + Запись в журнал: `"Collection {name} does not exist, returning empty results"` + Возврат пустого списка (без возникновения ошибки). + +**Несколько размерностей в одном запросе:** +Если запрос содержит векторы разных размерностей. +Для каждой размерности выполняется поиск в соответствующей коллекции. +Результаты объединяются. +Отсутствующие коллекции пропускаются (не рассматриваются как ошибки). + +**Обоснование:** +Запрос к пустой коллекции является допустимым сценарием использования. +Возврат пустых результатов является семантически правильным. +Предотвращает ошибки при запуске системы или до загрузки данных. + +#### 4. Удаление коллекции + +**Процесс удаления:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**Поведение:** +1. Создание префиксного шаблона: `d_{user}_{collection}_` (обратите внимание на завершающий символ подчеркивания) +2. Перечисление всех коллекций в векторной базе данных. +3. Фильтрация коллекций, соответствующих префиксу. +4. Удаление всех соответствующих коллекций. +5. Запись каждого удаления в журнал: `"Deleted collection {name}"` +6. Итоговый журнал: `"Deleted {count} collection(s) for {user}/{collection}"` + +**Пример:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**Обоснование:** +Обеспечивает полную очистку всех вариантов измерений. +Сопоставление с образцом предотвращает случайное удаление несвязанных коллекций. +Атомарная операция с точки зрения пользователя (все измерения удаляются вместе). + +## Поведенческие характеристики + +### Нормальная работа + +**Создание коллекции:** +✓ Немедленно возвращает успешный результат. +✓ Не выделяется физическое хранилище. +✓ Быстрая операция (без операций ввода-вывода на стороне сервера). + +**Первая запись:** +✓ Создает коллекцию с правильным измерением. +✓ Немного медленнее из-за накладных расходов на создание коллекции. +✓ Последующие записи в то же измерение выполняются быстро. + +**Запросы до любых записей:** +✓ Возвращает пустые результаты. +✓ Без ошибок или исключений. +✓ Система остается стабильной. + +**Смешанные записи измерений:** +✓ Автоматически создает отдельные коллекции для каждого измерения. +✓ Каждое измерение изолировано в своей коллекции. +✓ Отсутствуют конфликты измерений или ошибки схемы. + +**Удаление коллекции:** +✓ Удаляет все варианты измерений. +✓ Полная очистка. +✓ Отсутствуют "осиротевшие" коллекции. + +### Крайние случаи + +**Несколько моделей встраивания:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**Одновременные первые записи:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**Миграция измерений:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**Запросы к пустой коллекции:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## Заметки об реализации + +### Особенности используемого хранилища данных + +**Qdrant:** +Использует `collection_exists()` для проверок существования +Использует `get_collections()` для перечисления при удалении +Создание коллекции требует `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +Использует `has_index()` для проверок существования +Использует `list_indexes()` для перечисления при удалении +Создание индекса требует ожидания статуса "ready" +Serverless режим конфигурируется с указанием облака/региона + +**Milvus:** +Прямые классы (`DocVectors`, `EntityVectors`) управляют жизненным циклом +Внутренний кэш `self.collections[(dim, user, collection)]` для повышения производительности +Имена коллекций очищаются (только буквенно-цифровые символы и подчеркивание) +Поддерживает схему с автоматически увеличивающимися идентификаторами + +### Вопросы производительности + +**Задержка при первой записи:** +Дополнительные накладные расходы, связанные с созданием коллекции +Qdrant: ~100-500 мс +Pinecone: ~10-30 секунд (подготовка serverless режима) +Milvus: ~500-2000 мс (включая индексацию) + +**Производительность запросов:** +Проверка существования добавляет минимальные накладные расходы (~1-10 мс) +Отсутствие влияния на производительность после создания коллекции +Каждая коллекция, соответствующая определенной размерности, оптимизируется независимо + +**Накладные расходы на хранение:** +Минимальный объем метаданных на коллекцию +Основные накладные расходы связаны с хранением данных для каждой размерности +Компромисс: объем хранимых данных против гибкости размерностей + +## Будущие улучшения + +**Автоматическая консолидация размерностей:** +Можно добавить фоновый процесс для выявления и объединения неиспользуемых вариантов размерностей +Это потребует повторной встраиваемости или уменьшения размерности + +**Обнаружение размерностей:** +Можно предоставить API для перечисления всех используемых размерностей для коллекции +Полезно для администрирования и мониторинга + +**Предпочтительная размерность по умолчанию:** +Можно отслеживать "основную" размерность для каждой коллекции +Использовать для запросов, когда контекст размерности недоступен + +**Квоты на хранение:** +Возможно, потребуются ограничения на количество размерностей на коллекцию +Предотвращение чрезмерного количества вариантов размерностей + +## Примечания по миграции + +**Из системы с суффиксом размерности:** +Старые коллекции: `d_{user}_{collection}` (без суффикса размерности) +Новые коллекции: `d_{user}_{collection}_{dim}` (с суффиксом размерности) +Отсутствует автоматическая миграция - старые коллекции остаются доступными +Рассмотрите возможность использования скрипта для ручной миграции, если это необходимо +Можно использовать обе схемы именования одновременно + +## Ссылки + +Управление коллекциями: `docs/tech-specs/collection-management.md` +Схема хранения: `trustgraph-base/trustgraph/schema/services/storage.py` +Сервис Librarian: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.sw.md b/docs/tech-specs/vector-store-lifecycle.sw.md new file mode 100644 index 00000000..7eaf4d5d --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.sw.md @@ -0,0 +1,307 @@ +--- +layout: default +title: "Usimamizi wa Mzunguko wa Hifadhi ya Vektor" +parent: "Swahili (Beta)" +--- + +# Usimamizi wa Mzunguko wa Hifadhi ya Vektor + +> **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 inaeleza jinsi TrustGraph inavyosimamia mkusanyiko wa hifadhi ya vektor katika matumizi tofauti ya backend (Qdrant, Pinecone, Milvus). Muundo huu unashughulikia changamoto ya kusaidia embeddings zenye vipimo tofauti bila kuweka maadili ya vipimo yaliyopangwa awali. + +## Tatizo + +Hifadhi za vektor zinahitaji kipimo cha embedding kuainishwa wakati wa kuunda mkusanyiko/fahirisi. Hata hivyo: +Modeli tofauti za embedding hutoa vipimo tofauti (k.m., 384, 768, 1536) +Kipimo hakijulikani hadi embedding ya kwanza itengenezwe +Mkusaniko mmoja wa TrustGraph unaweza kupokea embeddings kutoka kwa modeli nyingi +Kuweka kipimo (k.m., 384) husababisha hitilafu na saizi zingine za embedding + +## Kanuni za Muundo + +1. **Uundaji wa Kila Mara:** Mikusanyiko huundwa wakati wa kuandika mara ya kwanza, sio wakati wa shughuli za usimamizi wa mkusanyiko. +2. **Jina Kulingana na Kipimo:** Majina ya mkusanyiko yanajumuisha kipimo cha embedding kama sehemu ya mwisho. +3. **Ufanisi:** Maswali dhidi ya mikusanyiko isiyopo hurudisha matokeo tupu, sio makosa. +4. **Usaidizi wa Vipimo Vingi:** Mkusaniko mmoja wa kimantiki unaweza kuwa na mikusanyiko mingi ya kimwili (moja kwa kila kipimo). + +## Muundo + +### Mfumo wa Majina ya Mkusaniko + +Mikusanyiko ya hifadhi ya vektor hutumia sehemu za mwisho za kipimo ili kusaidia saizi nyingi za embedding: + +**Embeddings za Hati:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**Embeddings za Grafu:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +Mifano: +`d_alice_papers_384` - Mkusaniko wa "makala za Alice" wenye embeddings za vipimo 384 +`d_alice_papers_768` - Mkusaniko huo huo wa kimantiki wenye embeddings za vipimo 768 +`t_bob_knowledge_1536` - Grafu ya maarifa ya "Bob" yenye embeddings za vipimo 1536 + +### Awamu za Mzunguko + +#### 1. Ombi la Uundaji wa Mkusaniko + +**Mwendo wa Ombi:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**Tabia:** +Msimamizi wa maktaba hutuma ombi la `create-collection` kwa kila mfumo wa kuhifadhi data. +Vifaa vya usindikaji vya hifadhi ya vector hutambua ombi hilo lakini **havitaunda makusanyo halisi** +Jibu hurudishwa mara moja kwa mafanikio. +Uundaji halisi wa makusanyo huahirishwa hadi wakati wa kuandika wa kwanza. + +**Sababu:** +Vipimo havijulikani wakati wa uundaji. +Inazuia uundaji wa makusanyo yenye vipimo vibaya. +Inarahisha mantiki ya usimamizi wa makusanyo. + +#### 2. Operesheni za Kuandika (Uundaji Ulioahirishwa) + +**Mchakato wa Kuandika:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**Tabia:** +1. Pata kipimo cha pembejeo kutoka kwenye vektari: `dim = len(vector)` +2. Unda jina la mkusanyiko pamoja na kiambishi cha kipimo +3. Angalia ikiwa mkusanyiko unapatikana na kipimo hicho maalum +4. Ikiwa haupo: + Unda mkusanyiko wenye kipimo sahihi + Rekodi: `"Lazily creating collection {name} with dimension {dim}"` +5. Ingiza pembejeo kwenye mkusanyiko maalum wa kipimo + +**Mfano wa Matukio:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. Operesheni za Uchunguzi + +**Mwendo wa Uchunguzi:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**Tabia:** +1. Pata kipimo kutoka kwa vektor ya swali: `dim = len(vector)` +2. Unda jina la mkusanyiko pamoja na kiambishi cha kipimo +3. Angalia ikiwa mkusanyiko unapatikana +4. Ikiwa unapatikana: + Fanya utafutaji wa kufanana + Rudi na matokeo +5. Ikiwa haupatikani: + Rekodi: `"Collection {name} does not exist, returning empty results"` + Rudi na orodha tupu (hakuna kosa lililotokea) + +**Vipimo Vingi katika Swali Moja:** +Ikiwa swali lina vektor za vipimo tofauti +Kila kipimo hufanya utafutaji katika mkusanyiko wake unaohusiana +Matokeo huunganishwa +Mikusanyiko inayokosekana huachwa (hayatibiwi kama madosa) + +**Sababu:** +Kuuliza mkusanyiko ambao hauna data ni matumizi halali +Kurudi na matokeo tupu ni sahihi kwa maana +Inazuia madosa wakati wa kuanza kwa mfumo au kabla ya kuingiza data + +#### 4. Ufutilishaji wa Mkusaniko + +**Mchakato wa Ufutilishaji:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**Tabia:** +1. Unda muundo wa kielelezo: `d_{user}_{collection}_` (angalia alama ya chini) +2. Orodha zote za makusanyo katika hifadhi ya vekta +3. Chuja makusanyo yanayolingana na kielelezo +4. Futa makusanyo yote yanayolingana +5. Rekodi kila kufutwa: `"Deleted collection {name}"` +6. Rekodi ya jumla: `"Deleted {count} collection(s) for {user}/{collection}"` + +**Mfano:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**Sababu:** +Inahakikisha usafishaji kamili wa aina zote za vipimo. +Ulinganishaji wa muundo huuzuia kufutwa kwa makusudi kwa mkusanyiko usiohusiana. +Operesheni ya atomu kutoka kwa mtazamo wa mtumiaji (vipimo vyote hufutwa pamoja). + +## Tabia za Utendaji + +### Operesheni za Kawaida + +**Uundaji wa Mkusanyiko:** +✓ Inarudisha mafanikio mara moja. +✓ Hakuna uhifadhi wa kimwili unaoombwa. +✓ Operesheni ya haraka (hakuna pembejeo/patto la nyuma). + +**Uandishi wa Kwanza:** +✓ Huunda mkusanyiko na kipimo sahihi. +✓ Huwa polepole kidogo kwa sababu ya gharama ya uundaji wa mkusanyiko. +✓ Uandishi wa baadaye kwenye kipimo sawa huwa wa haraka. + +**Umasilisho Kabla ya Uandishi Wowote:** +✓ Inarudisha matokeo tupu. +✓ Hakuna makosa au ubaguzi. +✓ Mfumo unaendelea kuwa thabiti. + +**Uandishi Mseto wa Vipimo:** +✓ Huunda moja kwa moja makusanyiko tofauti kwa kila kipimo. +✓ Kila kipimo kimetengwa katika mkusanyiko wake mwenyewe. +✓ Hakuna migogoro ya kipimo au makosa ya muundo. + +**Ufutaji wa Mkusanyiko:** +✓ Huondoa aina zote za vipimo. +✓ Usafishaji kamili. +✓ Hakuna makusanyiko yaliyotelekezwa. + +### Hali Maalum + +**Miundo Mbalimbali ya Uingizaji:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**Uandikaji wa Kwanza Unaofanyika Pamoja:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**Uhamisho wa Vipimo:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**Maswali ya Mkusanyiko Tupu:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## Maelekezo ya Utendaji + +### Maelezo Maalum ya Hifadhi ya Data + +**Qdrant:** +Hutumia `collection_exists()` kwa upangaji wa kuangalia uwepo +Hutumia `get_collections()` kwa orodha wakati wa kufuta +Uundaji wa mkusanyiko unahitaji `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +Hutumia `has_index()` kwa upangaji wa kuangalia uwepo +Hutumia `list_indexes()` kwa orodha wakati wa kufuta +Uundaji wa faharasa unahitaji kusubiri hali ya "tayari" +Vipimo vya seva zisizo na utunzaji vimepangwa na eneo la wingu + +**Milvus:** +Darasa za moja kwa moja (`DocVectors`, `EntityVectors`) husimamia mzunguko wa maisha +Kumbukumbu ya ndani `self.collections[(dim, user, collection)]` kwa utendaji +Majina ya mkusanyiko husafishwa (herufi na nambari pekee + alama ya nukta) +Inasaidia schema na vitambulisho ambavyo huongezeka kiotomatiki + +### Mambo ya Kuzingatia ya Utendaji + +**Ucheleweshaji wa Uandikishaji wa Kwanza:** +Gharama ya ziada kutokana na uundaji wa mkusanyiko +Qdrant: ~100-500ms +Pinecone: ~10-30 sekunde (utayarishaji wa seva zisizo na utunzaji) +Milvus: ~500-2000ms (pamoja na uwekaji wa faharasa) + +**Utendaji wa Umasilisho:** +Uangaliaji wa uwepo unaongeza gharama ndogo (~1-10ms) +Hakuna athari ya utendaji mara tu mkusanyiko ukiwepo +Kila mkusanyiko wa vipimo unafanywa kazi kwa kujitegemea + +**Gharama ya Hifadhi:** +Meta-data ndogo kwa kila mkusanyiko +Gharama kuu ni kwa kila kipimo +Ulinganisho: Nafasi ya hifadhi dhidi ya uwezekano wa vipimo + +## Mambo ya Kuzingatia ya Baadaye + +**Uunganishaji Otomatiki wa Vipimo:** +Inaweza kuongeza mchakato wa asilia wa kutambua na kuunganisha toleo lisilo la vipimo +Itahitaji kuweka upya au kupunguza vipimo + +**Unyonyaji wa Vipimo:** +Inaweza kuonyesha API ya kuorodhesha vipimo vyote vinavyotumika kwa mkusanyiko +Ni muhimu kwa utawala na ufuatiliaji + +**Upendeleo wa Vipimo vya Msingi:** +Inaweza kufuatilia kipimo "cha msingi" kwa kila mkusanyiko +Tumia kwa masilisho wakati hali ya kipimo haipatikani + +**Mgao wa Hifadhi:** +Inaweza kuhitaji mipaka ya kipimo kwa kila mkusanyiko +Kuzuia ongezeko la toleo la vipimo + +## Maelekezo ya Uhamishaji + +**Kutoka kwa Mfumo wa Zamani wa Jina la Kipimo:** +Mkusanyiko wa zamani: `d_{user}_{collection}` (hakuna jina la kipimo) +Mkusanyiko mpya: `d_{user}_{collection}_{dim}` (na jina la kipimo) +Hakuna uhamishaji otomatiki - mkusanyiko wa zamani wanaendelea kuwa na ufikiaji +Fikiria programu ya uhamishaji ya mwongozo ikiwa inahitajika +Unaweza kuendesha mifumo miwili ya majina kwa wakati mmoja + +## Marejeleo + +Usimamizi wa Mkusanyiko: `docs/tech-specs/collection-management.md` +Schema ya Hifadhi: `trustgraph-base/trustgraph/schema/services/storage.py` +Huduma ya Maktaba: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.tr.md b/docs/tech-specs/vector-store-lifecycle.tr.md new file mode 100644 index 00000000..4ed9cc8a --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.tr.md @@ -0,0 +1,307 @@ +--- +layout: default +title: "Vektör Depolama Yaşam Döngüsü Yönetimi" +parent: "Turkish (Beta)" +--- + +# Vektör Depolama Yaşam Döngüsü Yönetimi + +> **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, TrustGraph'ın farklı arka uç uygulamaları (Qdrant, Pinecone, Milvus) arasında vektör depolama koleksiyonlarını nasıl yönettiğini açıklamaktadır. Tasarım, sabit boyut değerleri kullanmadan farklı boyutlara sahip gömülmeleri destekleme zorluğunu ele almaktadır. + +## Problem Tanımı + +Vektör depoları, koleksiyonlar/indeksler oluşturulurken gömme boyutunun belirtilmesini gerektirir. Ancak: +Farklı gömme modelleri farklı boyutlar üretir (örneğin, 384, 768, 1536). +Boyut, ilk gömme oluşturulana kadar bilinmemektedir. +Tek bir TrustGraph koleksiyonu, birden fazla modelden gömmeler alabilir. +Bir boyutu (örneğin, 384) sabit kodlamak, diğer gömme boyutlarıyla uyumsuzluğa neden olur. + +## Tasarım İlkeleri + +1. **Gecikmeli Oluşturma**: Koleksiyonlar, koleksiyon yönetimi işlemlerinin aksine, ilk yazma sırasında talep üzerine oluşturulur. +2. **Boyut Tabanlı İsimlendirme**: Koleksiyon adları, gömme boyutunu bir sonek olarak içerir. +3. **Nazik Bozulma**: Var olmayan koleksiyonlara yapılan sorgular, hatalar yerine boş sonuçlar döndürür. +4. **Çok Boyutlu Destek**: Tek bir mantıksal koleksiyon, birden fazla fiziksel koleksiyona (her biri bir boyut için bir tane) sahip olabilir. + +## Mimari + +### Koleksiyon İsimlendirme Kuralı + +Vektör depolama koleksiyonları, birden fazla gömme boyutunu desteklemek için boyut soneklerini kullanır: + +**Belge Gömme:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**Graf Gömme:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +Örnekler: +`d_alice_papers_384` - 384 boyutlu gömmelere sahip Alice'in makale koleksiyonu +`d_alice_papers_768` - Aynı mantıksal koleksiyon, 768 boyutlu gömmelerle +`t_bob_knowledge_1536` - 1536 boyutlu gömmelere sahip Bob'un bilgi grafiği + +### Yaşam Döngüsü Aşamaları + +#### 1. Koleksiyon Oluşturma İsteği + +**İstek Akışı:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**Davranış:** +Kütüphaneci, `create-collection` isteklerini tüm depolama arka uçlarına yayınlar. +Vektör depolama işlemcileri isteği kabul eder, ancak **fiziksel koleksiyonlar oluşturmaz**. +Yanıt, başarıyla birlikte hemen döndürülür. +Gerçek koleksiyon oluşturma, ilk yazma işlemine kadar ertelenir. + +**Gerekçe:** +Boyut, oluşturma zamanında bilinmemektedir. +Yanlış boyutlara sahip koleksiyonların oluşturulması engellenir. +Koleksiyon yönetimi mantığını basitleştirir. + +#### 2. Yazma İşlemleri (Gecikmeli Oluşturma) + +**Yazma Akışı:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**Davranış:** +1. Vektörden gömme boyutunu çıkarın: `dim = len(vector)` +2. Boyut sonekiyle koleksiyon adını oluşturun +3. Belirli o boyuta sahip koleksiyonun var olup olmadığını kontrol edin +4. Yoksa: + Doğru boyuta sahip bir koleksiyon oluşturun + Kaydı tutun: `"Lazily creating collection {name} with dimension {dim}"` +5. Gömme değerini, boyutuna özel koleksiyona ekleyin + +**Örnek Senaryo:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. Sorgu İşlemleri + +**Sorgu Akışı:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**Davranış:** +1. Sorgu vektöründen boyutu çıkarın: `dim = len(vector)` +2. Boyut sonekiyle koleksiyon adını oluşturun +3. Koleksiyonun var olup olmadığını kontrol edin +4. Varsa: + Benzerlik araması yapın + Sonuçları döndürün +5. Yoksa: + Kaydı tutun: `"Collection {name} does not exist, returning empty results"` + Boş bir liste döndürün (hata yükseltilmez) + +**Aynı Sorguda Birden Fazla Boyut:** +Sorgu farklı boyutlardaki vektörler içeriyorsa +Her boyut, ilgili koleksiyonunu sorgular +Sonuçlar birleştirilir +Eksik koleksiyonlar atlanır (hata olarak değerlendirilmez) + +**Gerekçe:** +Boş bir koleksiyonu sorgulamak geçerli bir kullanım durumudur +Boş sonuçlar döndürmek anlamsal olarak doğrudur +Sistem başlatılırken veya veri yüklemesinden önce hataları önler + +#### 4. Koleksiyon Silme + +**Silme Akışı:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**Davranış:** +1. Önek kalıbını oluştur: `d_{user}_{collection}_` (sonundaki alt çizgiye dikkat edin) +2. Vektör deposundaki tüm koleksiyonları listele +3. Öneğe uyan koleksiyonları filtrele +4. Tüm eşleşen koleksiyonları sil +5. Her silme işlemini kaydet: `"Deleted collection {name}"` +6. Özet günlük: `"Deleted {count} collection(s) for {user}/{collection}"` + +**Örnek:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**Gerekçe:** +Tüm boyut varyantlarının tamamen temizlenmesini sağlar. +Desen eşleştirme, yanlışlıkla ilgili olmayan koleksiyonların silinmesini önler. +Kullanıcı açısından atomik bir işlem (tüm boyutlar birlikte silinir). + +## Davranışsal Özellikler + +### Normal İşlemler + +**Koleksiyon Oluşturma:** +✓ Hemen başarı döndürür. +✓ Herhangi bir fiziksel depolama alanı ayrılmaz. +✓ Hızlı işlem (arka uç G/Ç yok). + +**İlk Yazma:** +✓ Doğru boyuta sahip koleksiyon oluşturur. +✓ Koleksiyon oluşturma ek yükü nedeniyle biraz daha yavaştır. +✓ Aynı boyuta yapılan sonraki yazmalar hızlıdır. + +**Herhangi Bir Yazmadan Önce Sorgular:** +✓ Boş sonuçlar döndürür. +✓ Herhangi bir hata veya istisna oluşmaz. +✓ Sistem kararlı kalır. + +**Farklı Boyutlara Yazma:** +✓ Otomatik olarak her boyut için ayrı koleksiyonlar oluşturur. +✓ Her boyut kendi koleksiyonunda izole edilir. +✓ Herhangi bir boyut çakışması veya şema hatası oluşmaz. + +**Koleksiyon Silme:** +✓ Tüm boyut varyantlarını kaldırır. +✓ Tam temizleme. +✓ Herhangi bir yetim koleksiyon kalmaz. + +### Sınır Durumlar + +**Çoklu Gömülü Model:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**Eşzamanlı İlk Yazma İşlemleri:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**Boyutların Taşınması:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**Boş Koleksiyon Sorguları:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## Uygulama Notları + +### Depolama Arka Ucu Özellikleri + +**Qdrant:** +Varlık kontrolleri için `collection_exists()` kullanılır. +Silme sırasında listeleme için `get_collections()` kullanılır. +Koleksiyon oluşturma `VectorParams(size=dim, distance=Distance.COSINE)` gerektirir. + +**Pinecone:** +Varlık kontrolleri için `has_index()` kullanılır. +Silme sırasında listeleme için `list_indexes()` kullanılır. +İndeks oluşturma, "hazır" durumunu bekleme gerektirir. +Sunucusuz yapılandırma, bulut/bölge ile yapılır. + +**Milvus:** +Doğrudan sınıflar (`DocVectors`, `EntityVectors`), yaşam döngüsünü yönetir. +Performans için dahili önbellek `self.collections[(dim, user, collection)]`. +Koleksiyon adları, yalnızca alfanümerik ve alt çizgi içeren şekilde temizlenir. +Otomatik artan kimliklere sahip şema desteği. + +### Performans Hususları + +**İlk Yazma Gecikmesi:** +Koleksiyon oluşturma nedeniyle ek yük. +Qdrant: ~100-500ms +Pinecone: ~10-30 saniye (sunucusuz sağlama) +Milvus: ~500-2000ms (indekslemeyi içerir) + +**Sorgu Performansı:** +Varlık kontrolü, minimum ek yük ekler (~1-10ms). +Koleksiyon mevcut olduğunda performans üzerinde etkisi yoktur. +Her boyut koleksiyonu, bağımsız olarak optimize edilir. + +**Depolama Yükü:** +Her koleksiyon için minimum meta veri. +Ana yük, boyut başına depolamadır. +Dengeleme: Depolama alanı ile boyut esnekliği. + +## Gelecek Hususlar + +**Otomatik Boyut Birleştirme:** +Kullanılmayan boyut varyantlarını belirlemek ve birleştirmek için arka plan işlemi eklenebilir. +Yeniden gömme veya boyut azaltma gerektirecektir. + +**Boyut Keşfi:** +Bir koleksiyon için kullanılan tüm boyutları listelemek için bir API açılabilir. +Yönetim ve izleme için kullanışlıdır. + +**Varsayılan Boyut Tercihi:** +Her koleksiyon için "birincil" boyut izlenebilir. +Boyut bağlamı kullanılamadığında sorgular için kullanılır. + +**Depolama Kotaları:** +Her koleksiyon için boyut limitleri gerekebilir. +Boyut varyantlarının yayılmasını önler. + +## Geçiş Notları + +**Ön Boyut-Sonek Sisteminden:** +Eski koleksiyonlar: `d_{user}_{collection}` (boyut soneki yok) +Yeni koleksiyonlar: `d_{user}_{collection}_{dim}` (boyut soneki ile) +Otomatik geçiş yok - eski koleksiyonlar erişilebilir durumda kalır. +Gerekirse, manuel bir geçiş betiği düşünülmelidir. +Her iki adlandırma şeması de aynı anda kullanılabilir. + +## Referanslar + +Koleksiyon Yönetimi: `docs/tech-specs/collection-management.md` +Depolama Şeması: `trustgraph-base/trustgraph/schema/services/storage.py` +Kütüphaneci Hizmeti: `trustgraph-flow/trustgraph/librarian/service.py` diff --git a/docs/tech-specs/vector-store-lifecycle.zh-cn.md b/docs/tech-specs/vector-store-lifecycle.zh-cn.md new file mode 100644 index 00000000..42ca2ff9 --- /dev/null +++ b/docs/tech-specs/vector-store-lifecycle.zh-cn.md @@ -0,0 +1,307 @@ +--- +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 如何管理跨不同后端实现(Qdrant、Pinecone、Milvus)的向量存储集合。该设计解决了在不硬编码维度值的情况下,支持具有不同维度的嵌入向量的挑战。 + +## 问题陈述 + +向量存储在创建集合/索引时需要指定嵌入维度。但是: +不同的嵌入模型会产生不同的维度(例如,384、768、1536) +直到生成第一个嵌入向量,维度才已知 +单个 TrustGraph 集合可能会接收来自多个模型的嵌入向量 +强制指定一个维度(例如,384)会导致使用其他嵌入向量大小时出现故障 + +## 设计原则 + +1. **延迟创建**: 集合是在首次写入时按需创建的,而不是在集合管理操作期间创建的。 +2. **基于维度的命名**: 集合名称包含嵌入维度作为后缀。 +3. **优雅降级**: 对不存在的集合执行的查询返回空结果,而不是错误。 +4. **多维度支持**: 单个逻辑集合可以有多个物理集合(每个维度一个)。 + +## 架构 + +### 集合命名约定 + +向量存储集合使用维度后缀来支持多种嵌入向量大小: + +**文档嵌入:** +Qdrant: `d_{user}_{collection}_{dimension}` +Pinecone: `d-{user}-{collection}-{dimension}` +Milvus: `doc_{user}_{collection}_{dimension}` + +**图嵌入:** +Qdrant: `t_{user}_{collection}_{dimension}` +Pinecone: `t-{user}-{collection}-{dimension}` +Milvus: `entity_{user}_{collection}_{dimension}` + +示例: +`d_alice_papers_384` - Alice 的论文集合,使用 384 维的嵌入向量 +`d_alice_papers_768` - 相同的逻辑集合,使用 768 维的嵌入向量 +`t_bob_knowledge_1536` - Bob 的知识图谱,使用 1536 维的嵌入向量 + +### 生命周期阶段 + +#### 1. 集合创建请求 + +**请求流程:** +``` +User/System → Librarian → Storage Management Topic → Vector Stores +``` + +**行为:** +库管理员将 `create-collection` 请求广播到所有存储后端。 +向量存储处理器确认该请求,但**不创建物理集合**。 +立即返回成功响应。 +实际集合的创建将在第一次写入时延迟。 + +**理由:** +在创建时,维度是未知的。 +避免创建具有错误维度的集合。 +简化集合管理逻辑。 + +#### 2. 写入操作(延迟创建) + +**写入流程:** +``` +Data → Storage Processor → Check Collection → Create if Needed → Insert +``` + +**行为:** +1. 从向量中提取嵌入维度:`dim = len(vector)` +2. 使用维度后缀构建集合名称 +3. 检查是否存在具有该特定维度的集合 +4. 如果不存在: + 创建具有正确维度的集合 + 记录:`"Lazily creating collection {name} with dimension {dim}"` +5. 将嵌入信息插入到特定维度的集合中 + +**示例场景:** +``` +1. User creates collection "papers" + → No physical collections created yet + +2. First document with 384-dim embedding arrives + → Creates d_user_papers_384 + → Inserts data + +3. Second document with 768-dim embedding arrives + → Creates d_user_papers_768 + → Inserts data + +Result: Two physical collections for one logical collection +``` + +#### 3. 查询操作 + +**查询流程:** +``` +Query Vector → Determine Dimension → Check Collection → Search or Return Empty +``` + +**行为:** +1. 从查询向量中提取维度:`dim = len(vector)` +2. 使用维度后缀构建集合名称 +3. 检查集合是否存在 +4. 如果存在: + 执行相似度搜索 + 返回结果 +5. 如果不存在: + 记录日志:`"Collection {name} does not exist, returning empty results"` + 返回空列表(不引发错误) + +**同一查询中的多个维度:** +如果查询包含不同维度的向量 +每个维度查询其对应的集合 +结果进行聚合 +缺失的集合将被跳过(不被视为错误) + +**原理:** +查询空集合是一种有效的用例 +返回空结果在语义上是正确的 +避免在系统启动或在数据摄取之前发生的错误 + +#### 4. 集合删除 + +**删除流程:** +``` +Delete Request → List All Collections → Filter by Prefix → Delete All Matches +``` + +**行为:** +1. 构造前缀模式:`d_{user}_{collection}_` (注意尾随的下划线) +2. 列出向量存储中的所有集合 +3. 过滤与前缀匹配的集合 +4. 删除所有匹配的集合 +5. 记录每个删除操作:`"Deleted collection {name}"` +6. 汇总日志:`"Deleted {count} collection(s) for {user}/{collection}"` + +**示例:** +``` +Collections in store: +- d_alice_papers_384 +- d_alice_papers_768 +- d_alice_reports_384 +- d_bob_papers_384 + +Delete "papers" for alice: +→ Deletes: d_alice_papers_384, d_alice_papers_768 +→ Keeps: d_alice_reports_384, d_bob_papers_384 +``` + +**原理:** +确保彻底清理所有维度变体。 +模式匹配可防止意外删除不相关的集合。 +从用户角度来看,这是一个原子操作(所有维度一起删除)。 + +## 行为特性 + +### 正常操作 + +**集合创建:** +✓ 立即返回成功。 +✓ 不分配任何物理存储空间。 +✓ 快速操作(没有后端 I/O)。 + +**首次写入:** +✓ 创建具有正确维度的集合。 +✓ 由于集合创建的开销,速度略慢。 +✓ 之后对同一维度的写入速度很快。 + +**在任何写入之前进行查询:** +✓ 返回空结果。 +✓ 没有错误或异常。 +✓ 系统保持稳定。 + +**混合维度写入:** +✓ 自动为每个维度创建单独的集合。 +✓ 每个维度都隔离在自己的集合中。 +✓ 没有维度冲突或模式错误。 + +**集合删除:** +✓ 移除所有维度变体。 +✓ 彻底清理。 +✓ 没有孤立的集合。 + +### 边界情况 + +**多个嵌入模型:** +``` +Scenario: User switches from model A (384-dim) to model B (768-dim) +Behavior: +- Both dimensions coexist in separate collections +- Old data (384-dim) remains queryable with 384-dim vectors +- New data (768-dim) queryable with 768-dim vectors +- Cross-dimension queries return results only for matching dimension +``` + +**并发首次写入:** +``` +Scenario: Multiple processes write to same collection simultaneously +Behavior: +- Each process checks for existence before creating +- Most vector stores handle concurrent creation gracefully +- If race condition occurs, second create is typically idempotent +- Final state: Collection exists and both writes succeed +``` + +**维度迁移:** +``` +Scenario: User wants to migrate from 384-dim to 768-dim embeddings +Behavior: +- No automatic migration +- Old collection (384-dim) persists +- New collection (768-dim) created on first new write +- Both dimensions remain accessible +- Manual deletion of old dimension collections possible +``` + +**空集合查询:** +``` +Scenario: Query a collection that has never received data +Behavior: +- Collection doesn't exist (never created) +- Query returns empty list +- No error state +- System logs: "Collection does not exist, returning empty results" +``` + +## 实现说明 + +### 存储后端特定说明 + +**Qdrant:** +使用 `collection_exists()` 进行存在性检查 +使用 `get_collections()` 在删除期间进行列表操作 +集合创建需要 `VectorParams(size=dim, distance=Distance.COSINE)` + +**Pinecone:** +使用 `has_index()` 进行存在性检查 +使用 `list_indexes()` 在删除期间进行列表操作 +索引创建需要等待 "ready" 状态 +Serverless 规格配置为云/区域 + +**Milvus:** +直接类 (`DocVectors`, `EntityVectors`) 管理生命周期 +内部缓存 `self.collections[(dim, user, collection)]` 用于提高性能 +集合名称经过清理(仅限字母数字 + 下划线) +支持具有自动递增 ID 的模式 + +### 性能考虑 + +**首次写入延迟:** +由于集合创建而产生的额外开销 +Qdrant: ~100-500 毫秒 +Pinecone: ~10-30 秒 (serverless 预配置) +Milvus: ~500-2000 毫秒 (包括索引) + +**查询性能:** +存在性检查会增加最小的开销 (~1-10 毫秒) +集合存在后,不会对性能产生影响 +每个维度集合都独立优化 + +**存储开销:** +每个集合的元数据非常少 +主要开销是每个维度的存储 +权衡:存储空间与维度灵活性 + +## 未来考虑 + +**自动维度合并:** +可以添加后台进程来识别和合并未使用的维度变体 +这将需要重新嵌入或降维 + +**维度发现:** +可以公开 API 来列出集合中使用的所有维度 +对于管理和监控非常有用 + +**默认维度偏好:** +可以跟踪每个集合的 "主" 维度 +用于在维度上下文不可用的情况下进行查询 + +**存储配额:** +可能需要每个集合的维度限制 +防止维度变体的过度繁殖 + +## 迁移说明 + +**从预维度后缀系统:** +旧集合:`d_{user}_{collection}` (没有维度后缀) +新集合:`d_{user}_{collection}_{dim}` (带有维度后缀) +没有自动迁移 - 旧集合仍然可以访问 +如果需要,请考虑手动迁移脚本 +可以同时运行这两种命名方案 + +## 引用 + +集合管理:`docs/tech-specs/collection-management.md` +存储模式:`trustgraph-base/trustgraph/schema/services/storage.py` +Librarian 服务:`trustgraph-flow/trustgraph/librarian/service.py` diff --git a/tests/conftest.py b/tests/conftest.py index 7c6ffc13..6f63967c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ import pytest # import asyncio # import tracemalloc # import warnings +import logging from unittest.mock import MagicMock # Uncomment the lines below to enable asyncio debug mode and tracemalloc @@ -33,19 +34,14 @@ def mock_loki_handler(session_mocker=None): # Create a mock LokiHandler that does nothing original_loki_handler = logging_loki.LokiHandler - class MockLokiHandler: + class MockLokiHandler(logging.Handler): """Mock LokiHandler that doesn't make network calls.""" + def __init__(self, *args, **kwargs): - pass + super().__init__() def emit(self, record): - pass - - def flush(self): - pass - - def close(self): - pass + return # Replace the real LokiHandler with our mock logging_loki.LokiHandler = MockLokiHandler diff --git a/tests/unit/test_base/test_i18n.py b/tests/unit/test_base/test_i18n.py new file mode 100644 index 00000000..2d357a1d --- /dev/null +++ b/tests/unit/test_base/test_i18n.py @@ -0,0 +1,40 @@ +from trustgraph.i18n import get_language_pack, get_translator, normalize_language + + +def test_normalize_language_handles_regions_and_accept_language(): + assert normalize_language(None) == "en" + assert normalize_language("") == "en" + + assert normalize_language("es-ES") == "es" + assert normalize_language("pt-BR") == "pt" + assert normalize_language("zh") == "zh-cn" + + assert normalize_language("es-ES,es;q=0.9,en;q=0.8") == "es" + assert normalize_language("unknown") == "en" + + +def test_language_pack_loads_from_resources(): + pack = get_language_pack("en") + assert isinstance(pack, dict) + + # Key should exist and map to a non-empty string. + title = pack.get("cli.verify_system_status.title") + assert isinstance(title, str) + assert title.strip() != "" + + +def test_translator_formats_placeholders(): + tr = get_translator("en") + out = tr.t( + "cli.verify_system_status.checking_attempt", + name="Pulsar", + attempt=2, + ) + + assert "Pulsar" in out + assert "2" in out + + +def test_translator_falls_back_to_key_for_unknown_keys(): + tr = get_translator("en") + assert tr.t("missing.key") == "missing.key" diff --git a/tests/unit/test_gateway/test_endpoint_i18n.py b/tests/unit/test_gateway/test_endpoint_i18n.py new file mode 100644 index 00000000..ab693cdf --- /dev/null +++ b/tests/unit/test_gateway/test_endpoint_i18n.py @@ -0,0 +1,75 @@ +"""Tests for Gateway i18n pack endpoint.""" + +import json +from unittest.mock import MagicMock + +import pytest +from aiohttp import web + +from trustgraph.gateway.endpoint.i18n import I18nPackEndpoint + + +class TestI18nPackEndpoint: + + def test_i18n_endpoint_initialization(self): + mock_auth = MagicMock() + + endpoint = I18nPackEndpoint( + endpoint_path="/api/v1/i18n/packs/{lang}", + auth=mock_auth, + ) + + assert endpoint.path == "/api/v1/i18n/packs/{lang}" + assert endpoint.auth == mock_auth + assert endpoint.operation == "service" + + @pytest.mark.asyncio + async def test_i18n_endpoint_start_method(self): + mock_auth = MagicMock() + endpoint = I18nPackEndpoint("/api/v1/i18n/packs/{lang}", mock_auth) + await endpoint.start() + + def test_add_routes_registers_get_handler(self): + mock_auth = MagicMock() + mock_app = MagicMock() + + endpoint = I18nPackEndpoint("/api/v1/i18n/packs/{lang}", mock_auth) + endpoint.add_routes(mock_app) + + mock_app.add_routes.assert_called_once() + call_args = mock_app.add_routes.call_args[0][0] + assert len(call_args) == 1 + + @pytest.mark.asyncio + async def test_handle_unauthorized_on_invalid_auth_scheme(self): + mock_auth = MagicMock() + mock_auth.permitted.return_value = True + + endpoint = I18nPackEndpoint("/api/v1/i18n/packs/{lang}", mock_auth) + + request = MagicMock() + request.path = "/api/v1/i18n/packs/en" + request.headers = {"Authorization": "Token abc"} + request.match_info = {"lang": "en"} + + resp = await endpoint.handle(request) + assert isinstance(resp, web.HTTPUnauthorized) + + @pytest.mark.asyncio + async def test_handle_returns_pack_when_permitted(self): + mock_auth = MagicMock() + mock_auth.permitted.return_value = True + + endpoint = I18nPackEndpoint("/api/v1/i18n/packs/{lang}", mock_auth) + + request = MagicMock() + request.path = "/api/v1/i18n/packs/en" + request.headers = {} + request.match_info = {"lang": "en"} + + resp = await endpoint.handle(request) + + assert resp.status == 200 + payload = json.loads(resp.body.decode("utf-8")) + assert isinstance(payload, dict) + assert "cli.verify_system_status.title" in payload diff --git a/trustgraph-base/pyproject.toml b/trustgraph-base/pyproject.toml index b7b9757c..216ccbd6 100644 --- a/trustgraph-base/pyproject.toml +++ b/trustgraph-base/pyproject.toml @@ -27,5 +27,8 @@ Homepage = "https://github.com/trustgraph-ai/trustgraph" [tool.setuptools.packages.find] include = ["trustgraph*"] +[tool.setuptools.package-data] +"trustgraph.i18n.packs" = ["*.json"] + [tool.setuptools.dynamic] version = {attr = "trustgraph.base_version.__version__"} \ No newline at end of file diff --git a/trustgraph-base/trustgraph/i18n/__init__.py b/trustgraph-base/trustgraph/i18n/__init__.py new file mode 100644 index 00000000..756738e8 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/__init__.py @@ -0,0 +1,156 @@ +"""Minimal i18n support for TrustGraph. + +This module intentionally stays lightweight: +- No runtime translation calls +- Translations are pre-generated and shipped as language packs + +Consumers (CLI/API/Workbench) select a language code (e.g. "es") and +use `Translator.t(key, **kwargs)` to format localized strings. +""" + +from __future__ import annotations + +import json +from dataclasses import dataclass +from functools import lru_cache +from typing import Any, Dict, Mapping, Optional + +import importlib.resources as importlib_resources + + +SUPPORTED_LANGUAGES: Mapping[str, str] = { + "en": "English", + "es": "Spanish", + "sw": "Swahili", + "pt": "Portuguese", + "tr": "Turkish", + "hi": "Hindi", + "he": "Hebrew", + "ar": "Arabic", + "zh-cn": "Chinese (simplified)", + "ru": "Russian", +} + +_LANGUAGE_ALIASES: Mapping[str, str] = { + "zh": "zh-cn", + "zh-hans": "zh-cn", + "zh-hans-cn": "zh-cn", + "zh-cn": "zh-cn", + "zh_cn": "zh-cn", +} + + +def normalize_language(value: Optional[str]) -> str: + """Normalize language inputs to our supported codes. + + Accepts: + - Simple codes: "es" + - Region tags: "es-ES", "en-US" + - Accept-Language style: "es-ES,es;q=0.9,en;q=0.8" + + Falls back to "en" when unknown. + """ + + if not value: + return "en" + + # Accept-Language: take first entry + token = value.split(",", 1)[0].strip() + if not token: + return "en" + + token = token.replace("_", "-").lower() + + # Exact alias mapping + if token in _LANGUAGE_ALIASES: + token = _LANGUAGE_ALIASES[token] + + # Collapse common regional tags + if token.startswith("en-"): + token = "en" + elif token.startswith("es-"): + token = "es" + elif token.startswith("pt-"): + token = "pt" + elif token.startswith("tr-"): + token = "tr" + elif token.startswith("hi-"): + token = "hi" + elif token.startswith("he-"): + token = "he" + elif token.startswith("ar-"): + token = "ar" + elif token.startswith("sw-"): + token = "sw" + elif token.startswith("ru-"): + token = "ru" + elif token.startswith("zh-"): + token = "zh-cn" + + # Otherwise use primary subtag + primary = token.split("-", 1)[0] + if primary in SUPPORTED_LANGUAGES: + return primary + + if token in SUPPORTED_LANGUAGES: + return token + + return "en" + + +# Returns a mutable object - caller must not mutate! +@lru_cache(maxsize=32) +def get_language_pack(language: str) -> Dict[str, str]: + """Load the language pack for `language` from package resources.""" + + lang = normalize_language(language) + if lang not in SUPPORTED_LANGUAGES: + lang = "en" + + try: + with importlib_resources.open_text( + "trustgraph.i18n.packs", f"{lang}.json", encoding="utf-8" + ) as f: + data = json.load(f) + except FileNotFoundError: + data = {} + + if not isinstance(data, dict): + return {} + + # Ensure values are strings + out: Dict[str, str] = {} + for k, v in data.items(): + if isinstance(k, str) and isinstance(v, str): + out[k] = v + return out + + +@dataclass(frozen=True) +class Translator: + language: str + + def t(self, key: str, **kwargs: Any) -> str: + """Translate `key` using the current language pack. + + Falls back to English pack, then the key itself. + Supports `.format(**kwargs)` placeholder substitution. + """ + + lang = normalize_language(self.language) + pack = get_language_pack(lang) + fallback = get_language_pack("en") + + template = pack.get(key) or fallback.get(key) or key + if not kwargs: + return template + + try: + return template.format(**kwargs) + except Exception: + # If formatting fails, return the untranslated template + return template + + +def get_translator(language: Optional[str]) -> Translator: + return Translator(language=normalize_language(language)) diff --git a/trustgraph-base/trustgraph/i18n/packs/__init__.py b/trustgraph-base/trustgraph/i18n/packs/__init__.py new file mode 100644 index 00000000..db8af56e --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/__init__.py @@ -0,0 +1 @@ +# Language packs live next to this module as JSON files. diff --git a/trustgraph-base/trustgraph/i18n/packs/ar.json b/trustgraph-base/trustgraph/i18n/packs/ar.json new file mode 100644 index 00000000..c910df29 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/ar.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "التحقق من حالة نظام TrustGraph.", + "cli.verify_system_status.phase_1": "المرحلة الأولى: البنية التحتية.", + "cli.verify_system_status.phase_2": "المرحلة الثانية: الخدمات الأساسية.", + "cli.verify_system_status.phase_3": "المرحلة الثالثة: خدمات البيانات.", + "cli.verify_system_status.phase_4": "المرحلة الرابعة: واجهة المستخدم.", + "cli.verify_system_status.summary": "ملخص.", + "cli.verify_system_status.checking": "التحقق من {name}...", + "cli.verify_system_status.checking_attempt": "التحقق من {name}... (المحاولة {attempt}).", + "cli.verify_system_status.failed_timeout": "{name}: فشل (انتهت المهلة بعد {attempt} محاولة).", + "cli.verify_system_status.pulsar_not_responding": "Pulsar لا تستجيب - قد تفشل عمليات التحقق الأخرى.", + "cli.verify_system_status.checks_passed": "عمليات التحقق التي نجحت: {passed}/{total}.", + "cli.verify_system_status.checks_failed": "عمليات التحقق التي فشلت: {failed}/{total}.", + "cli.verify_system_status.total_time": "إجمالي الوقت: {elapsed}.", + "cli.verify_system_status.system_healthy": "النظام يعمل بشكل صحيح!", + "cli.verify_system_status.system_failing": "النظام لديه {failed} عملية تحقق فاشلة.", + "cli.verify_system_status.check_name.pulsar": "Pulsar.", + "cli.verify_system_status.check_name.api_gateway": "بوابة واجهة برمجة التطبيقات (API Gateway).", + "cli.verify_system_status.check_name.processors": "المعالجات (Processors).", + "cli.verify_system_status.check_name.flow_blueprints": "مخططات التدفق (Flow Blueprints).", + "cli.verify_system_status.check_name.flows": "التدفقات (Flows).", + "cli.verify_system_status.check_name.prompts": "المطالبات (Prompts).", + "cli.verify_system_status.check_name.library": "المكتبة (Library).", + "cli.verify_system_status.check_name.workbench_ui": "واجهة المستخدم الخاصة بـ Workbench.", + "cli.verify_system_status.pulsar.healthy": "Pulsar تعمل بشكل صحيح ({clusters} مجموعة).", + "cli.verify_system_status.pulsar.status": "Pulsar أرجعت الحالة {status_code}.", + "cli.verify_system_status.pulsar.timeout": "Pulsar: انتهاء المهلة.", + "cli.verify_system_status.pulsar.cannot_connect": "لا يمكن الاتصال بـ Pulsar.", + "cli.verify_system_status.pulsar.error": "Pulsar: خطأ: {error}.", + "cli.verify_system_status.api_gateway.responding": "بوابة واجهة برمجة التطبيقات (API Gateway) تستجيب.", + "cli.verify_system_status.api_gateway.status": "بوابة واجهة برمجة التطبيقات (API Gateway) أرجعت الحالة {status_code}.", + "cli.verify_system_status.api_gateway.timeout": "بوابة واجهة برمجة التطبيقات (API Gateway): انتهاء المهلة.", + "cli.verify_system_status.api_gateway.cannot_connect": "لا يمكن الاتصال بـ بوابة واجهة برمجة التطبيقات (API Gateway).", + "cli.verify_system_status.api_gateway.error": "بوابة واجهة برمجة التطبيقات (API Gateway): خطأ: {error}.", + "cli.verify_system_status.processors.found": "تم العثور على {count} معالج (≥ {min}).", + "cli.verify_system_status.processors.only": "فقط {count} معالج قيد التشغيل (مطلوب {min}).", + "cli.verify_system_status.processors.metrics_status": "المقاييس أرجعت الحالة {status_code}.", + "cli.verify_system_status.processors.error": "خطأ في فحص المعالج: {error}.", + "cli.verify_system_status.flow_blueprints.found": "تم العثور على {count} مخطط تدفق.", + "cli.verify_system_status.flow_blueprints.none": "لم يتم العثور على أي مخططات تدفق.", + "cli.verify_system_status.flow_blueprints.error": "خطأ في فحص مخططات التدفق: {error}.", + "cli.verify_system_status.flows.responding": "مدير التدفق يستجيب ({count} تدفق).", + "cli.verify_system_status.flows.error": "خطأ في فحص مدير التدفق: {error}.", + "cli.verify_system_status.prompts.found": "تم العثور على {count} مطالبة.", + "cli.verify_system_status.prompts.none": "لم يتم العثور على أي مطالبات.", + "cli.verify_system_status.prompts.error": "خطأ في فحص المطالبات: {error}.", + "cli.verify_system_status.library.responding": "المكتبة تستجيب ({count} مستند).", + "cli.verify_system_status.library.error": "خطأ في فحص المكتبة: {error}.", + "cli.verify_system_status.ui.responding": "واجهة المستخدم الخاصة بـ Workbench تستجيب.", + "cli.verify_system_status.ui.status": "واجهة المستخدم أرجعت الحالة {status_code}.", + "cli.verify_system_status.ui.timeout": "واجهة المستخدم: انتهاء المهلة.", + "cli.verify_system_status.ui.cannot_connect": "لا يمكن الاتصال بواجهة المستخدم.", + "cli.verify_system_status.ui.error": "واجهة المستخدم: خطأ: {error}." +} diff --git a/trustgraph-base/trustgraph/i18n/packs/en.json b/trustgraph-base/trustgraph/i18n/packs/en.json new file mode 100644 index 00000000..8438b7e7 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/en.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "TrustGraph System Status Verification", + "cli.verify_system_status.phase_1": "Phase 1: Infrastructure", + "cli.verify_system_status.phase_2": "Phase 2: Core Services", + "cli.verify_system_status.phase_3": "Phase 3: Data Services", + "cli.verify_system_status.phase_4": "Phase 4: User Interface", + "cli.verify_system_status.summary": "Summary", + "cli.verify_system_status.checking": "Checking {name}...", + "cli.verify_system_status.checking_attempt": "Checking {name}... (attempt {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: Failed (timeout after {attempt} attempts)", + "cli.verify_system_status.pulsar_not_responding": "Pulsar is not responding - other checks may fail", + "cli.verify_system_status.checks_passed": "Checks passed: {passed}/{total}", + "cli.verify_system_status.checks_failed": "Checks failed: {failed}/{total}", + "cli.verify_system_status.total_time": "Total time: {elapsed}", + "cli.verify_system_status.system_healthy": "System is healthy!", + "cli.verify_system_status.system_failing": "System has {failed} failing check(s)", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API Gateway", + "cli.verify_system_status.check_name.processors": "Processors", + "cli.verify_system_status.check_name.flow_blueprints": "Flow Blueprints", + "cli.verify_system_status.check_name.flows": "Flows", + "cli.verify_system_status.check_name.prompts": "Prompts", + "cli.verify_system_status.check_name.library": "Library", + "cli.verify_system_status.check_name.workbench_ui": "Workbench UI", + "cli.verify_system_status.pulsar.healthy": "Pulsar healthy ({clusters} cluster(s))", + "cli.verify_system_status.pulsar.status": "Pulsar returned status {status_code}", + "cli.verify_system_status.pulsar.timeout": "Pulsar connection timeout", + "cli.verify_system_status.pulsar.cannot_connect": "Cannot connect to Pulsar", + "cli.verify_system_status.pulsar.error": "Pulsar error: {error}", + "cli.verify_system_status.api_gateway.responding": "API Gateway is responding", + "cli.verify_system_status.api_gateway.status": "API Gateway returned status {status_code}", + "cli.verify_system_status.api_gateway.timeout": "API Gateway connection timeout", + "cli.verify_system_status.api_gateway.cannot_connect": "Cannot connect to API Gateway", + "cli.verify_system_status.api_gateway.error": "API Gateway error: {error}", + "cli.verify_system_status.processors.found": "Found {count} processors (≥ {min})", + "cli.verify_system_status.processors.only": "Only {count} processors running (need {min})", + "cli.verify_system_status.processors.metrics_status": "Metrics returned status {status_code}", + "cli.verify_system_status.processors.error": "Processor check error: {error}", + "cli.verify_system_status.flow_blueprints.found": "Found {count} flow blueprint(s)", + "cli.verify_system_status.flow_blueprints.none": "No flow blueprints found", + "cli.verify_system_status.flow_blueprints.error": "Flow blueprints check error: {error}", + "cli.verify_system_status.flows.responding": "Flow manager responding ({count} flow(s))", + "cli.verify_system_status.flows.error": "Flow manager check error: {error}", + "cli.verify_system_status.prompts.found": "Found {count} prompt(s)", + "cli.verify_system_status.prompts.none": "No prompts found", + "cli.verify_system_status.prompts.error": "Prompts check error: {error}", + "cli.verify_system_status.library.responding": "Library responding ({count} document(s))", + "cli.verify_system_status.library.error": "Library check error: {error}", + "cli.verify_system_status.ui.responding": "Workbench UI is responding", + "cli.verify_system_status.ui.status": "UI returned status {status_code}", + "cli.verify_system_status.ui.timeout": "UI connection timeout", + "cli.verify_system_status.ui.cannot_connect": "Cannot connect to UI", + "cli.verify_system_status.ui.error": "UI error: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/es.json b/trustgraph-base/trustgraph/i18n/packs/es.json new file mode 100644 index 00000000..64b79cd6 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/es.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "Verificación del estado del sistema TrustGraph", + "cli.verify_system_status.phase_1": "Fase 1: Infraestructura", + "cli.verify_system_status.phase_2": "Fase 2: Servicios principales", + "cli.verify_system_status.phase_3": "Fase 3: Servicios de datos", + "cli.verify_system_status.phase_4": "Fase 4: Interfaz de usuario", + "cli.verify_system_status.summary": "Resumen", + "cli.verify_system_status.checking": "Verificando {name}...", + "cli.verify_system_status.checking_attempt": "Verificando {name}... (intento {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: Fallido (tiempo de espera después de {attempt} intentos)", + "cli.verify_system_status.pulsar_not_responding": "Pulsar no está respondiendo; otras verificaciones pueden fallar", + "cli.verify_system_status.checks_passed": "Verificaciones superadas: {passed}/{total}", + "cli.verify_system_status.checks_failed": "Verificaciones fallidas: {failed}/{total}", + "cli.verify_system_status.total_time": "Tiempo total: {elapsed}", + "cli.verify_system_status.system_healthy": "¡El sistema es saludable!", + "cli.verify_system_status.system_failing": "El sistema tiene {failed} verificación(es) fallida(s)", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API Gateway", + "cli.verify_system_status.check_name.processors": "Procesadores", + "cli.verify_system_status.check_name.flow_blueprints": "Plantillas de flujo", + "cli.verify_system_status.check_name.flows": "Flujos", + "cli.verify_system_status.check_name.prompts": "Indicaciones", + "cli.verify_system_status.check_name.library": "Biblioteca", + "cli.verify_system_status.check_name.workbench_ui": "Interfaz de usuario del entorno de trabajo", + "cli.verify_system_status.pulsar.healthy": "Pulsar saludable ({clusters} clúster(es))", + "cli.verify_system_status.pulsar.status": "Pulsar devolvió el estado {status_code}", + "cli.verify_system_status.pulsar.timeout": "Tiempo de espera de la conexión a Pulsar", + "cli.verify_system_status.pulsar.cannot_connect": "No se puede conectar a Pulsar", + "cli.verify_system_status.pulsar.error": "Error de Pulsar: {error}", + "cli.verify_system_status.api_gateway.responding": "API Gateway está respondiendo", + "cli.verify_system_status.api_gateway.status": "API Gateway devolvió el estado {status_code}", + "cli.verify_system_status.api_gateway.timeout": "Tiempo de espera de la conexión a API Gateway", + "cli.verify_system_status.api_gateway.cannot_connect": "No se puede conectar a API Gateway", + "cli.verify_system_status.api_gateway.error": "Error de API Gateway: {error}", + "cli.verify_system_status.processors.found": "Se encontraron {count} procesadores (≥ {min})", + "cli.verify_system_status.processors.only": "Solo {count} procesadores en ejecución (se necesitan {min})", + "cli.verify_system_status.processors.metrics_status": "Métricas devolvieron el estado {status_code}", + "cli.verify_system_status.processors.error": "Error de verificación del procesador: {error}", + "cli.verify_system_status.flow_blueprints.found": "Se encontraron {count} plantilla(s) de flujo", + "cli.verify_system_status.flow_blueprints.none": "No se encontraron plantillas de flujo", + "cli.verify_system_status.flow_blueprints.error": "Error de verificación de la plantilla de flujo: {error}", + "cli.verify_system_status.flows.responding": "El administrador de flujos está respondiendo ({count} flujo(s))", + "cli.verify_system_status.flows.error": "Error de verificación del administrador de flujos: {error}", + "cli.verify_system_status.prompts.found": "Se encontraron {count} indicación(es)", + "cli.verify_system_status.prompts.none": "No se encontraron indicaciones", + "cli.verify_system_status.prompts.error": "Error de verificación de la indicación: {error}", + "cli.verify_system_status.library.responding": "La biblioteca está respondiendo ({count} documento(s))", + "cli.verify_system_status.library.error": "Error de verificación de la biblioteca: {error}", + "cli.verify_system_status.ui.responding": "La interfaz de usuario del entorno de trabajo está respondiendo", + "cli.verify_system_status.ui.status": "La interfaz de usuario devolvió el estado {status_code}", + "cli.verify_system_status.ui.timeout": "Tiempo de espera de la conexión a la interfaz de usuario", + "cli.verify_system_status.ui.cannot_connect": "No se puede conectar a la interfaz de usuario", + "cli.verify_system_status.ui.error": "Error de la interfaz de usuario: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/he.json b/trustgraph-base/trustgraph/i18n/packs/he.json new file mode 100644 index 00000000..9ad9ad90 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/he.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "אימות סטטוס מערכת TrustGraph", + "cli.verify_system_status.phase_1": "שלב 1: תשתית", + "cli.verify_system_status.phase_2": "שלב 2: שירותים מרכזיים", + "cli.verify_system_status.phase_3": "שלב 3: שירותי נתונים", + "cli.verify_system_status.phase_4": "שלב 4: ממשק משתמש", + "cli.verify_system_status.summary": "סיכום", + "cli.verify_system_status.checking": "בדיקת {name}...", + "cli.verify_system_status.checking_attempt": "בדיקת {name}... (ניסיון {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: נכשל (תפוגה לאחר {attempt} ניסיונות)", + "cli.verify_system_status.pulsar_not_responding": "Pulsar אינו מגיב - בדיקות אחרות עשויות להיכשל", + "cli.verify_system_status.checks_passed": "בדיקות שעברו: {passed}/{total}", + "cli.verify_system_status.checks_failed": "בדיקות שנכשלו: {failed}/{total}", + "cli.verify_system_status.total_time": "זמן כולל: {elapsed}", + "cli.verify_system_status.system_healthy": "המערכת תקינה!", + "cli.verify_system_status.system_failing": "למערכת יש {failed} בדיקה/ות שנכשלו", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API Gateway", + "cli.verify_system_status.check_name.processors": "מעבדים", + "cli.verify_system_status.check_name.flow_blueprints": "תבניות זרימה", + "cli.verify_system_status.check_name.flows": "זרימות", + "cli.verify_system_status.check_name.prompts": "הנחיות", + "cli.verify_system_status.check_name.library": "ספרייה", + "cli.verify_system_status.check_name.workbench_ui": "ממשק משתמש (Workbench UI)", + "cli.verify_system_status.pulsar.healthy": "Pulsar תקין ({clusters} אשכולות)", + "cli.verify_system_status.pulsar.status": "Pulsar החזיר סטטוס {status_code}", + "cli.verify_system_status.pulsar.timeout": "תפוגת זמן חיבור ל-Pulsar", + "cli.verify_system_status.pulsar.cannot_connect": "לא ניתן להתחבר ל-Pulsar", + "cli.verify_system_status.pulsar.error": "שגיאה ב-Pulsar: {error}", + "cli.verify_system_status.api_gateway.responding": "API Gateway מגיב", + "cli.verify_system_status.api_gateway.status": "API Gateway החזיר סטטוס {status_code}", + "cli.verify_system_status.api_gateway.timeout": "תפוגת זמן חיבור ל-API Gateway", + "cli.verify_system_status.api_gateway.cannot_connect": "לא ניתן להתחבר ל-API Gateway", + "cli.verify_system_status.api_gateway.error": "שגיאה ב-API Gateway: {error}", + "cli.verify_system_status.processors.found": "נמצאו {count} מעבדים (≥ {min})", + "cli.verify_system_status.processors.only": "פועלים רק {count} מעבדים (נדרשים {min})", + "cli.verify_system_status.processors.metrics_status": "Metrics החזירו סטטוס {status_code}", + "cli.verify_system_status.processors.error": "שגיאת בדיקת מעבד: {error}", + "cli.verify_system_status.flow_blueprints.found": "נמצאו {count} תבניות זרימה", + "cli.verify_system_status.flow_blueprints.none": "לא נמצאו תבניות זרימה", + "cli.verify_system_status.flow_blueprints.error": "שגיאת בדיקת תבניות זרימה: {error}", + "cli.verify_system_status.flows.responding": "מנהל הזרימה מגיב ({count} זרימות)", + "cli.verify_system_status.flows.error": "שגיאת בדיקת מנהל הזרימה: {error}", + "cli.verify_system_status.prompts.found": "נמצאו {count} הנחיות", + "cli.verify_system_status.prompts.none": "לא נמצאו הנחיות", + "cli.verify_system_status.prompts.error": "שגיאת בדיקת הנחיות: {error}", + "cli.verify_system_status.library.responding": "הספרייה מגיבה ({count} מסמכים)", + "cli.verify_system_status.library.error": "שגיאת בדיקת ספרייה: {error}", + "cli.verify_system_status.ui.responding": "ממשק המשתמש (Workbench UI) מגיב", + "cli.verify_system_status.ui.status": "ממשק המשתמש החזיר סטטוס {status_code}", + "cli.verify_system_status.ui.timeout": "תפוגת זמן חיבור לממשק המשתמש", + "cli.verify_system_status.ui.cannot_connect": "לא ניתן להתחבר לממשק המשתמש", + "cli.verify_system_status.ui.error": "שגיאה בממשק המשתמש: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/hi.json b/trustgraph-base/trustgraph/i18n/packs/hi.json new file mode 100644 index 00000000..9783319b --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/hi.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "ट्रस्टग्राफ सिस्टम स्टेटस वेरिफिकेशन", + "cli.verify_system_status.phase_1": "चरण 1: इंफ्रास्ट्रक्चर", + "cli.verify_system_status.phase_2": "चरण 2: कोर सर्विसेज", + "cli.verify_system_status.phase_3": "चरण 3: डेटा सर्विसेज", + "cli.verify_system_status.phase_4": "चरण 4: यूजर इंटरफेस", + "cli.verify_system_status.summary": "सारांश", + "cli.verify_system_status.checking": "{name} की जाँच की जा रही है...", + "cli.verify_system_status.checking_attempt": "{name} की जाँच की जा रही है... (प्रयास {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: विफल ({attempt} प्रयासों के बाद टाइमआउट)", + "cli.verify_system_status.pulsar_not_responding": "पल्सर प्रतिक्रिया नहीं दे रहा है - अन्य जाँचें विफल हो सकती हैं", + "cli.verify_system_status.checks_passed": "पास हुई जाँचें: {passed}/{total}", + "cli.verify_system_status.checks_failed": "विफल हुई जाँचें: {failed}/{total}", + "cli.verify_system_status.total_time": "कुल समय: {elapsed}", + "cli.verify_system_status.system_healthy": "सिस्टम स्वस्थ है!", + "cli.verify_system_status.system_failing": "सिस्टम में {failed} विफल जाँच(एँ) हैं", + "cli.verify_system_status.check_name.pulsar": "पल्सर", + "cli.verify_system_status.check_name.api_gateway": "एपीआई गेटवे", + "cli.verify_system_status.check_name.processors": "प्रोसेसर", + "cli.verify_system_status.check_name.flow_blueprints": "फ्लो ब्लूप्रिंट्स", + "cli.verify_system_status.check_name.flows": "फ्लोस", + "cli.verify_system_status.check_name.prompts": "प्रॉम्प्ट्स", + "cli.verify_system_status.check_name.library": "लाइब्रेरी", + "cli.verify_system_status.check_name.workbench_ui": "वर्कबेंच यूआई", + "cli.verify_system_status.pulsar.healthy": "पल्सर स्वस्थ ({clusters} क्लस्टर(्स))", + "cli.verify_system_status.pulsar.status": "पल्सर ने स्टेटस {status_code} लौटाया", + "cli.verify_system_status.pulsar.timeout": "पल्सर कनेक्शन टाइमआउट", + "cli.verify_system_status.pulsar.cannot_connect": "पल्सर से कनेक्ट नहीं किया जा सका", + "cli.verify_system_status.pulsar.error": "पल्सर त्रुटि: {error}", + "cli.verify_system_status.api_gateway.responding": "एपीआई गेटवे प्रतिक्रिया दे रहा है", + "cli.verify_system_status.api_gateway.status": "एपीआई गेटवे ने स्टेटस {status_code} लौटाया", + "cli.verify_system_status.api_gateway.timeout": "एपीआई गेटवे कनेक्शन टाइमआउट", + "cli.verify_system_status.api_gateway.cannot_connect": "एपीआई गेटवे से कनेक्ट नहीं किया जा सका", + "cli.verify_system_status.api_gateway.error": "एपीआई गेटवे त्रुटि: {error}", + "cli.verify_system_status.processors.found": "{count} प्रोसेसर पाए गए (≥ {min})", + "cli.verify_system_status.processors.only": "केवल {count} प्रोसेसर चल रहे हैं (आवश्यक {min})", + "cli.verify_system_status.processors.metrics_status": "मेट्रिक्स ने स्टेटस {status_code} लौटाया", + "cli.verify_system_status.processors.error": "प्रोसेसर जाँच त्रुटि: {error}", + "cli.verify_system_status.flow_blueprints.found": "{count} फ्लो ब्लूप्रिंट पाए गए", + "cli.verify_system_status.flow_blueprints.none": "कोई फ्लो ब्लूप्रिंट नहीं मिला", + "cli.verify_system_status.flow_blueprints.error": "फ्लो ब्लूप्रिंट जाँच त्रुटि: {error}", + "cli.verify_system_status.flows.responding": "फ्लो मैनेजर प्रतिक्रिया दे रहा है ({count} फ्लो(्स))", + "cli.verify_system_status.flows.error": "फ्लो मैनेजर जाँच त्रुटि: {error}", + "cli.verify_system_status.prompts.found": "{count} प्रॉम्प्ट पाए गए", + "cli.verify_system_status.prompts.none": "कोई प्रॉम्प्ट नहीं मिला", + "cli.verify_system_status.prompts.error": "प्रॉम्प्ट जाँच त्रुटि: {error}", + "cli.verify_system_status.library.responding": "लाइब्रेरी प्रतिक्रिया दे रही है ({count} दस्तावेज़(्स))", + "cli.verify_system_status.library.error": "लाइब्रेरी जाँच त्रुटि: {error}", + "cli.verify_system_status.ui.responding": "वर्कबेंच यूआई प्रतिक्रिया दे रहा है", + "cli.verify_system_status.ui.status": "यूआई ने स्टेटस {status_code} लौटाया", + "cli.verify_system_status.ui.timeout": "यूआई कनेक्शन टाइमआउट", + "cli.verify_system_status.ui.cannot_connect": "यूआई से कनेक्ट नहीं किया जा सका", + "cli.verify_system_status.ui.error": "यूआई त्रुटि: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/pt.json b/trustgraph-base/trustgraph/i18n/packs/pt.json new file mode 100644 index 00000000..7238f086 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/pt.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "Verificação do Status do Sistema TrustGraph", + "cli.verify_system_status.phase_1": "Fase 1: Infraestrutura", + "cli.verify_system_status.phase_2": "Fase 2: Serviços Essenciais", + "cli.verify_system_status.phase_3": "Fase 3: Serviços de Dados", + "cli.verify_system_status.phase_4": "Fase 4: Interface do Usuário", + "cli.verify_system_status.summary": "Resumo", + "cli.verify_system_status.checking": "Verificando {name}...", + "cli.verify_system_status.checking_attempt": "Verificando {name}... (tentativa {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: Falha (tempo limite após {attempt} tentativas)", + "cli.verify_system_status.pulsar_not_responding": "O Pulsar não está respondendo - outras verificações podem falhar", + "cli.verify_system_status.checks_passed": "Verificações aprovadas: {passed}/{total}", + "cli.verify_system_status.checks_failed": "Verificações falhadas: {failed}/{total}", + "cli.verify_system_status.total_time": "Tempo total: {elapsed}", + "cli.verify_system_status.system_healthy": "O sistema está saudável!", + "cli.verify_system_status.system_failing": "O sistema possui {failed} verificação(ões) com falha", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API Gateway", + "cli.verify_system_status.check_name.processors": "Processadores", + "cli.verify_system_status.check_name.flow_blueprints": "Flow Blueprints", + "cli.verify_system_status.check_name.flows": "Flows", + "cli.verify_system_status.check_name.prompts": "Prompts", + "cli.verify_system_status.check_name.library": "Biblioteca", + "cli.verify_system_status.check_name.workbench_ui": "Workbench UI", + "cli.verify_system_status.pulsar.healthy": "Pulsar saudável ({clusters} cluster(s))", + "cli.verify_system_status.pulsar.status": "O Pulsar retornou o status {status_code}", + "cli.verify_system_status.pulsar.timeout": "Tempo limite de conexão do Pulsar", + "cli.verify_system_status.pulsar.cannot_connect": "Não foi possível conectar ao Pulsar", + "cli.verify_system_status.pulsar.error": "Erro do Pulsar: {error}", + "cli.verify_system_status.api_gateway.responding": "O API Gateway está respondendo", + "cli.verify_system_status.api_gateway.status": "O API Gateway retornou o status {status_code}", + "cli.verify_system_status.api_gateway.timeout": "Tempo limite de conexão do API Gateway", + "cli.verify_system_status.api_gateway.cannot_connect": "Não foi possível conectar ao API Gateway", + "cli.verify_system_status.api_gateway.error": "Erro do API Gateway: {error}", + "cli.verify_system_status.processors.found": "Encontrados {count} processadores (≥ {min})", + "cli.verify_system_status.processors.only": "Apenas {count} processadores em execução (necessários {min})", + "cli.verify_system_status.processors.metrics_status": "As métricas retornaram o status {status_code}", + "cli.verify_system_status.processors.error": "Erro de verificação do processador: {error}", + "cli.verify_system_status.flow_blueprints.found": "Encontrados {count} flow blueprint(s)", + "cli.verify_system_status.flow_blueprints.none": "Nenhum flow blueprint encontrado", + "cli.verify_system_status.flow_blueprints.error": "Erro de verificação do flow blueprint: {error}", + "cli.verify_system_status.flows.responding": "O gerenciador de fluxo está respondendo ({count} flow(s))", + "cli.verify_system_status.flows.error": "Erro de verificação do gerenciador de fluxo: {error}", + "cli.verify_system_status.prompts.found": "Encontrados {count} prompt(s)", + "cli.verify_system_status.prompts.none": "Nenhum prompt encontrado", + "cli.verify_system_status.prompts.error": "Erro de verificação do prompt: {error}", + "cli.verify_system_status.library.responding": "A biblioteca está respondendo ({count} document(s))", + "cli.verify_system_status.library.error": "Erro de verificação da biblioteca: {error}", + "cli.verify_system_status.ui.responding": "O Workbench UI está respondendo", + "cli.verify_system_status.ui.status": "A UI retornou o status {status_code}", + "cli.verify_system_status.ui.timeout": "Tempo limite de conexão da UI", + "cli.verify_system_status.ui.cannot_connect": "Não foi possível conectar à UI", + "cli.verify_system_status.ui.error": "Erro da UI: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/ru.json b/trustgraph-base/trustgraph/i18n/packs/ru.json new file mode 100644 index 00000000..0e8420c2 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/ru.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "Проверка состояния системы TrustGraph", + "cli.verify_system_status.phase_1": "Фаза 1: Инфраструктура", + "cli.verify_system_status.phase_2": "Фаза 2: Основные сервисы", + "cli.verify_system_status.phase_3": "Фаза 3: Сервисы данных", + "cli.verify_system_status.phase_4": "Фаза 4: Пользовательский интерфейс", + "cli.verify_system_status.summary": "Краткое описание", + "cli.verify_system_status.checking": "Проверка {name}...", + "cli.verify_system_status.checking_attempt": "Проверка {name}... (попытка {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: Не удалось (тайм-аут после {attempt} попыток)", + "cli.verify_system_status.pulsar_not_responding": "Pulsar не отвечает - другие проверки могут не пройти", + "cli.verify_system_status.checks_passed": "Проверено: {passed}/{total}", + "cli.verify_system_status.checks_failed": "Не удалось: {failed}/{total}", + "cli.verify_system_status.total_time": "Общее время: {elapsed}", + "cli.verify_system_status.system_healthy": "Система в рабочем состоянии!", + "cli.verify_system_status.system_failing": "В системе {failed} неисправностей.", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API Gateway", + "cli.verify_system_status.check_name.processors": "Процессоры", + "cli.verify_system_status.check_name.flow_blueprints": "Шаблоны потоков", + "cli.verify_system_status.check_name.flows": "Потоки", + "cli.verify_system_status.check_name.prompts": "Подсказки", + "cli.verify_system_status.check_name.library": "Библиотека", + "cli.verify_system_status.check_name.workbench_ui": "Пользовательский интерфейс Workbench", + "cli.verify_system_status.pulsar.healthy": "Pulsar работает ({clusters} кластер(ов))", + "cli.verify_system_status.pulsar.status": "Pulsar вернул статус {status_code}", + "cli.verify_system_status.pulsar.timeout": "Время ожидания соединения с Pulsar истекло", + "cli.verify_system_status.pulsar.cannot_connect": "Не удалось подключиться к Pulsar", + "cli.verify_system_status.pulsar.error": "Ошибка Pulsar: {error}", + "cli.verify_system_status.api_gateway.responding": "API Gateway отвечает", + "cli.verify_system_status.api_gateway.status": "API Gateway вернул статус {status_code}", + "cli.verify_system_status.api_gateway.timeout": "Время ожидания соединения с API Gateway истекло", + "cli.verify_system_status.api_gateway.cannot_connect": "Не удалось подключиться к API Gateway", + "cli.verify_system_status.api_gateway.error": "Ошибка API Gateway: {error}", + "cli.verify_system_status.processors.found": "Обнаружено {count} процессоров (≥ {min})", + "cli.verify_system_status.processors.only": "Работает только {count} процессоров (требуется {min})", + "cli.verify_system_status.processors.metrics_status": "Метрики вернули статус {status_code}", + "cli.verify_system_status.processors.error": "Ошибка проверки процессора: {error}", + "cli.verify_system_status.flow_blueprints.found": "Обнаружено {count} шаблонов потоков", + "cli.verify_system_status.flow_blueprints.none": "Шаблоны потоков не найдены", + "cli.verify_system_status.flow_blueprints.error": "Ошибка проверки шаблонов потоков: {error}", + "cli.verify_system_status.flows.responding": "Менеджер потоков отвечает ({count} поток(ов))", + "cli.verify_system_status.flows.error": "Ошибка проверки менеджера потоков: {error}", + "cli.verify_system_status.prompts.found": "Обнаружено {count} подсказок", + "cli.verify_system_status.prompts.none": "Подсказки не найдены", + "cli.verify_system_status.prompts.error": "Ошибка проверки подсказок: {error}", + "cli.verify_system_status.library.responding": "Библиотека отвечает ({count} документ(ов))", + "cli.verify_system_status.library.error": "Ошибка проверки библиотеки: {error}", + "cli.verify_system_status.ui.responding": "Пользовательский интерфейс Workbench отвечает", + "cli.verify_system_status.ui.status": "Пользовательский интерфейс вернул статус {status_code}", + "cli.verify_system_status.ui.timeout": "Время ожидания соединения с пользовательским интерфейсом истекло", + "cli.verify_system_status.ui.cannot_connect": "Не удалось подключиться к пользовательскому интерфейсу", + "cli.verify_system_status.ui.error": "Ошибка пользовательского интерфейса: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/sw.json b/trustgraph-base/trustgraph/i18n/packs/sw.json new file mode 100644 index 00000000..3aa8288a --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/sw.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "Uthibitisho wa Hali ya Mfumo wa TrustGraph", + "cli.verify_system_status.phase_1": "Awamu ya 1: Miundombinu", + "cli.verify_system_status.phase_2": "Awamu ya 2: Huduma za Msingi", + "cli.verify_system_status.phase_3": "Awamu ya 3: Huduma za Data", + "cli.verify_system_status.phase_4": "Awamu ya 4: Kiolesura cha Mtumiaji", + "cli.verify_system_status.summary": "Muhtasari", + "cli.verify_system_status.checking": "Kuchunguza {name}...", + "cli.verify_system_status.checking_attempt": "Kuchunguza {name}... (jaribio la {attempt})", + "cli.verify_system_status.failed_timeout": "{name}: Imeshindwa (iliyepuka baada ya majaribio {attempt})", + "cli.verify_system_status.pulsar_not_responding": "Pulsar haijibu - vipimo vingine vinaweza kushindwa", + "cli.verify_system_status.checks_passed": "Vipimo vilivyofaulu: {passed}/{total}", + "cli.verify_system_status.checks_failed": "Vipimo vilivyoshindwa: {failed}/{total}", + "cli.verify_system_status.total_time": "Muda jumla: {elapsed}", + "cli.verify_system_status.system_healthy": "Mfumo una afya!", + "cli.verify_system_status.system_failing": "Mfumo una {failed} kipimo(s) kilicho(s) kifeli(s)", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "Milango ya API", + "cli.verify_system_status.check_name.processors": "Wasindikaji", + "cli.verify_system_status.check_name.flow_blueprints": "Mipango ya Mtiririko", + "cli.verify_system_status.check_name.flows": "Mitiririko", + "cli.verify_system_status.check_name.prompts": "Maagizo", + "cli.verify_system_status.check_name.library": "Maktaba", + "cli.verify_system_status.check_name.workbench_ui": "Kiolesura cha Kifaa cha Kazi", + "cli.verify_system_status.pulsar.healthy": "Pulsar ina afya (vikundi {clusters})", + "cli.verify_system_status.pulsar.status": "Pulsar ilirudisha hali {status_code}", + "cli.verify_system_status.pulsar.timeout": "Muda wa kuunganisha na Pulsar umepita", + "cli.verify_system_status.pulsar.cannot_connect": "Haiwezekani kuunganisha na Pulsar", + "cli.verify_system_status.pulsar.error": "Kosa la Pulsar: {error}", + "cli.verify_system_status.api_gateway.responding": "Milango ya API inajibu", + "cli.verify_system_status.api_gateway.status": "Milango ya API ilirudisha hali {status_code}", + "cli.verify_system_status.api_gateway.timeout": "Muda wa kuunganisha na Milango ya API umepita", + "cli.verify_system_status.api_gateway.cannot_connect": "Haiwezekani kuunganisha na Milango ya API", + "cli.verify_system_status.api_gateway.error": "Kosa la Milango ya API: {error}", + "cli.verify_system_status.processors.found": "Imebainika wasindikaji {count} (≥ {min})", + "cli.verify_system_status.processors.only": "Tu wasindikaji {count} wanaendesha (wanahitaji {min})", + "cli.verify_system_status.processors.metrics_status": "Vipimo vilirudisha hali {status_code}", + "cli.verify_system_status.processors.error": "Kosa la ukaguzi wa wasindikaji: {error}", + "cli.verify_system_status.flow_blueprints.found": "Imebainika mipango ya mtiririko {count}", + "cli.verify_system_status.flow_blueprints.none": "Hakuna mipango ya mtiririko iliyobainika", + "cli.verify_system_status.flow_blueprints.error": "Kosa la ukaguzi wa mipango ya mtiririko: {error}", + "cli.verify_system_status.flows.responding": "Kidhibiti cha mtiririko kinajibu (mitiririko {count})", + "cli.verify_system_status.flows.error": "Kosa la ukaguzi wa kidhibiti cha mtiririko: {error}", + "cli.verify_system_status.prompts.found": "Imebainika maagizo {count}", + "cli.verify_system_status.prompts.none": "Hakuna maagizo yaliyobainika", + "cli.verify_system_status.prompts.error": "Kosa la ukaguzi wa maagizo: {error}", + "cli.verify_system_status.library.responding": "Maktaba inajibu (nyaraka {count})", + "cli.verify_system_status.library.error": "Kosa la ukaguzi wa maktaba: {error}", + "cli.verify_system_status.ui.responding": "Kiolesura cha Kifaa cha Kazi kinajibu", + "cli.verify_system_status.ui.status": "Kiolesura kilirudisha hali {status_code}", + "cli.verify_system_status.ui.timeout": "Muda wa kuunganisha na kiolesura umepita", + "cli.verify_system_status.ui.cannot_connect": "Haiwezekani kuunganisha na kiolesura", + "cli.verify_system_status.ui.error": "Kosa la kiolesura: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/tr.json b/trustgraph-base/trustgraph/i18n/packs/tr.json new file mode 100644 index 00000000..0a210043 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/tr.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "TrustGraph Sistem Durumu Doğrulama", + "cli.verify_system_status.phase_1": "Aşama 1: Altyapı", + "cli.verify_system_status.phase_2": "Aşama 2: Temel Hizmetler", + "cli.verify_system_status.phase_3": "Aşama 3: Veri Hizmetleri", + "cli.verify_system_status.phase_4": "Aşama 4: Kullanıcı Arayüzü", + "cli.verify_system_status.summary": "Özet", + "cli.verify_system_status.checking": "{name}'ı kontrol ediliyor...", + "cli.verify_system_status.checking_attempt": "{name}'ı kontrol ediliyor... ({attempt} deneme)", + "cli.verify_system_status.failed_timeout": "{name}: Başarısız ({attempt} denemeden sonra zaman aşımı)", + "cli.verify_system_status.pulsar_not_responding": "Pulsar yanıt vermiyor - diğer kontroller başarısız olabilir", + "cli.verify_system_status.checks_passed": "Başarılı kontroller: {passed}/{total}", + "cli.verify_system_status.checks_failed": "Başarısız kontroller: {failed}/{total}", + "cli.verify_system_status.total_time": "Toplam süre: {elapsed}", + "cli.verify_system_status.system_healthy": "Sistem sağlıklı!", + "cli.verify_system_status.system_failing": "Sistemde {failed} adet başarısız kontrol var", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API Ağ Geçidi", + "cli.verify_system_status.check_name.processors": "İşlemciler", + "cli.verify_system_status.check_name.flow_blueprints": "Akış Şemaları", + "cli.verify_system_status.check_name.flows": "Akışlar", + "cli.verify_system_status.check_name.prompts": "İpuçları", + "cli.verify_system_status.check_name.library": "Kütüphane", + "cli.verify_system_status.check_name.workbench_ui": "Çalışma Alanı Arayüzü", + "cli.verify_system_status.pulsar.healthy": "Pulsar sağlıklı ({clusters} küme)", + "cli.verify_system_status.pulsar.status": "Pulsar, {status_code} durumunu döndürdü", + "cli.verify_system_status.pulsar.timeout": "Pulsar bağlantı zaman aşımı", + "cli.verify_system_status.pulsar.cannot_connect": "Pulsar'a bağlanılamıyor", + "cli.verify_system_status.pulsar.error": "Pulsar hatası: {error}", + "cli.verify_system_status.api_gateway.responding": "API Ağ Geçidi yanıt veriyor", + "cli.verify_system_status.api_gateway.status": "API Ağ Geçidi, {status_code} durumunu döndürdü", + "cli.verify_system_status.api_gateway.timeout": "API Ağ Geçidi bağlantı zaman aşımı", + "cli.verify_system_status.api_gateway.cannot_connect": "API Ağ Geçidi'ne bağlanılamıyor", + "cli.verify_system_status.api_gateway.error": "API Ağ Geçidi hatası: {error}", + "cli.verify_system_status.processors.found": "{count} adet işlemci bulundu (≥ {min})", + "cli.verify_system_status.processors.only": "Sadece {count} adet işlemci çalışıyor (gerekli {min})", + "cli.verify_system_status.processors.metrics_status": "Ölçümler, {status_code} durumunu döndürdü", + "cli.verify_system_status.processors.error": "İşlemci kontrol hatası: {error}", + "cli.verify_system_status.flow_blueprints.found": "{count} adet akış şeması bulundu", + "cli.verify_system_status.flow_blueprints.none": "Akış şeması bulunamadı", + "cli.verify_system_status.flow_blueprints.error": "Akış şeması kontrol hatası: {error}", + "cli.verify_system_status.flows.responding": "Akış yöneticisi yanıt veriyor ({count} akış)", + "cli.verify_system_status.flows.error": "Akış yöneticisi kontrol hatası: {error}", + "cli.verify_system_status.prompts.found": "{count} adet ipucu bulundu", + "cli.verify_system_status.prompts.none": "İpucu bulunamadı", + "cli.verify_system_status.prompts.error": "İpuçları kontrol hatası: {error}", + "cli.verify_system_status.library.responding": "Kütüphane yanıt veriyor ({count} belge)", + "cli.verify_system_status.library.error": "Kütüphane kontrol hatası: {error}", + "cli.verify_system_status.ui.responding": "Çalışma alanı Arayüzü yanıt veriyor", + "cli.verify_system_status.ui.status": "Arayüz, {status_code} durumunu döndürdü", + "cli.verify_system_status.ui.timeout": "Arayüz bağlantı zaman aşımı", + "cli.verify_system_status.ui.cannot_connect": "Arayüze bağlanılamıyor", + "cli.verify_system_status.ui.error": "Arayüz hatası: {error}" +} diff --git a/trustgraph-base/trustgraph/i18n/packs/zh-cn.json b/trustgraph-base/trustgraph/i18n/packs/zh-cn.json new file mode 100644 index 00000000..9084b367 --- /dev/null +++ b/trustgraph-base/trustgraph/i18n/packs/zh-cn.json @@ -0,0 +1,54 @@ +{ + "cli.verify_system_status.title": "TrustGraph 系统状态验证", + "cli.verify_system_status.phase_1": "第一阶段:基础设施", + "cli.verify_system_status.phase_2": "第二阶段:核心服务", + "cli.verify_system_status.phase_3": "第三阶段:数据服务", + "cli.verify_system_status.phase_4": "第四阶段:用户界面", + "cli.verify_system_status.summary": "总结", + "cli.verify_system_status.checking": "正在检查 {name}...", + "cli.verify_system_status.checking_attempt": "正在检查 {name}... (第 {attempt} 次尝试)", + "cli.verify_system_status.failed_timeout": "{name}: 失败 (在 {attempt} 次尝试后超时)", + "cli.verify_system_status.pulsar_not_responding": "Pulsar 未响应 - 其他检查可能失败", + "cli.verify_system_status.checks_passed": "通过检查: {passed}/{total}", + "cli.verify_system_status.checks_failed": "失败检查: {failed}/{total}", + "cli.verify_system_status.total_time": "总时间: {elapsed}", + "cli.verify_system_status.system_healthy": "系统状态良好!", + "cli.verify_system_status.system_failing": "系统有 {failed} 个失败的检查", + "cli.verify_system_status.check_name.pulsar": "Pulsar", + "cli.verify_system_status.check_name.api_gateway": "API 网关", + "cli.verify_system_status.check_name.processors": "处理程序", + "cli.verify_system_status.check_name.flow_blueprints": "流蓝图", + "cli.verify_system_status.check_name.flows": "流", + "cli.verify_system_status.check_name.prompts": "提示", + "cli.verify_system_status.check_name.library": "库", + "cli.verify_system_status.check_name.workbench_ui": "Workbench UI", + "cli.verify_system_status.pulsar.healthy": "Pulsar 状态良好 ({clusters} 个集群)", + "cli.verify_system_status.pulsar.status": "Pulsar 返回状态 {status_code}", + "cli.verify_system_status.pulsar.timeout": "Pulsar 连接超时", + "cli.verify_system_status.pulsar.cannot_connect": "无法连接到 Pulsar", + "cli.verify_system_status.pulsar.error": "Pulsar 错误: {error}", + "cli.verify_system_status.api_gateway.responding": "API 网关正在响应", + "cli.verify_system_status.api_gateway.status": "API 网关返回状态 {status_code}", + "cli.verify_system_status.api_gateway.timeout": "API 网关连接超时", + "cli.verify_system_status.api_gateway.cannot_connect": "无法连接到 API 网关", + "cli.verify_system_status.api_gateway.error": "API 网关错误: {error}", + "cli.verify_system_status.processors.found": "发现 {count} 个处理程序 (≥ {min})", + "cli.verify_system_status.processors.only": "只有 {count} 个处理程序正在运行 (需要 {min} 个)", + "cli.verify_system_status.processors.metrics_status": "Metrics 返回状态 {status_code}", + "cli.verify_system_status.processors.error": "处理程序检查错误: {error}", + "cli.verify_system_status.flow_blueprints.found": "发现 {count} 个流蓝图", + "cli.verify_system_status.flow_blueprints.none": "未发现任何流蓝图", + "cli.verify_system_status.flow_blueprints.error": "流蓝图检查错误: {error}", + "cli.verify_system_status.flows.responding": "流管理器正在响应 ({count} 个流)", + "cli.verify_system_status.flows.error": "流管理器检查错误: {error}", + "cli.verify_system_status.prompts.found": "发现 {count} 个提示", + "cli.verify_system_status.prompts.none": "未发现任何提示", + "cli.verify_system_status.prompts.error": "提示检查错误: {error}", + "cli.verify_system_status.library.responding": "库正在响应 ({count} 个文档)", + "cli.verify_system_status.library.error": "库检查错误: {error}", + "cli.verify_system_status.ui.responding": "Workbench UI 正在响应", + "cli.verify_system_status.ui.status": "UI 返回状态 {status_code}", + "cli.verify_system_status.ui.timeout": "UI 连接超时", + "cli.verify_system_status.ui.cannot_connect": "无法连接到 UI", + "cli.verify_system_status.ui.error": "UI 错误: {error}" +} diff --git a/trustgraph-cli/trustgraph/cli/verify_system_status.py b/trustgraph-cli/trustgraph/cli/verify_system_status.py index fa01898b..d7aa1d93 100644 --- a/trustgraph-cli/trustgraph/cli/verify_system_status.py +++ b/trustgraph-cli/trustgraph/cli/verify_system_status.py @@ -19,6 +19,7 @@ from typing import Tuple, Optional # Import existing CLI functions to reuse logic from trustgraph.api import Api +from trustgraph.i18n import get_translator default_pulsar_url = "http://localhost:8080" default_api_url = os.getenv("TRUSTGRAPH_URL", "http://localhost:8088/") @@ -34,12 +35,14 @@ class HealthChecker: global_timeout: int = 120, check_timeout: int = 10, retry_delay: int = 3, - verbose: bool = False + verbose: bool = False, + translator=None, ): self.global_timeout = global_timeout self.check_timeout = check_timeout self.retry_delay = retry_delay self.verbose = verbose + self.tr = translator self.start_time = time.time() self.checks_passed = 0 self.checks_failed = 0 @@ -98,9 +101,15 @@ class HealthChecker: attempt += 1 if attempt > 1: - self.log(f"Checking {name}... (attempt {attempt})", "progress") + if self.tr: + self.log(self.tr.t("cli.verify_system_status.checking_attempt", name=name, attempt=attempt), "progress") + else: + self.log(f"Checking {name}... (attempt {attempt})", "progress") else: - self.log(f"Checking {name}...", "progress") + if self.tr: + self.log(self.tr.t("cli.verify_system_status.checking", name=name), "progress") + else: + self.log(f"Checking {name}...", "progress") try: # Run the check with timeout @@ -124,29 +133,32 @@ class HealthChecker: time.sleep(self.retry_delay) # Check failed - self.log(f"{name}: Failed (timeout after {attempt} attempts)", "error") + if self.tr: + self.log(self.tr.t("cli.verify_system_status.failed_timeout", name=name, attempt=attempt), "error") + else: + self.log(f"{name}: Failed (timeout after {attempt} attempts)", "error") self.checks_failed += 1 return False -def check_pulsar(url: str, timeout: int) -> Tuple[bool, str]: +def check_pulsar(url: str, timeout: int, tr) -> Tuple[bool, str]: """Check if Pulsar admin API is responding.""" try: resp = requests.get(f"{url}/admin/v2/clusters", timeout=timeout) if resp.status_code == 200: clusters = resp.json() - return True, f"Pulsar healthy ({len(clusters)} cluster(s))" + return True, tr.t("cli.verify_system_status.pulsar.healthy", clusters=len(clusters)) else: - return False, f"Pulsar returned status {resp.status_code}" + return False, tr.t("cli.verify_system_status.pulsar.status", status_code=resp.status_code) except requests.exceptions.Timeout: - return False, "Pulsar connection timeout" + return False, tr.t("cli.verify_system_status.pulsar.timeout") except requests.exceptions.ConnectionError: - return False, "Cannot connect to Pulsar" + return False, tr.t("cli.verify_system_status.pulsar.cannot_connect") except Exception as e: - return False, f"Pulsar error: {e}" + return False, tr.t("cli.verify_system_status.pulsar.error", error=str(e)) -def check_api_gateway(url: str, timeout: int, token: Optional[str] = None) -> Tuple[bool, str]: +def check_api_gateway(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]: """Check if API Gateway is responding.""" try: # Try to hit the base URL @@ -159,18 +171,18 @@ def check_api_gateway(url: str, timeout: int, token: Optional[str] = None) -> Tu resp = requests.get(url, headers=headers, timeout=timeout) if resp.status_code in [200, 404]: # 404 is OK, means gateway is up - return True, "API Gateway is responding" + return True, tr.t("cli.verify_system_status.api_gateway.responding") else: - return False, f"API Gateway returned status {resp.status_code}" + return False, tr.t("cli.verify_system_status.api_gateway.status", status_code=resp.status_code) except requests.exceptions.Timeout: - return False, "API Gateway connection timeout" + return False, tr.t("cli.verify_system_status.api_gateway.timeout") except requests.exceptions.ConnectionError: - return False, "Cannot connect to API Gateway" + return False, tr.t("cli.verify_system_status.api_gateway.cannot_connect") except Exception as e: - return False, f"API Gateway error: {e}" + return False, tr.t("cli.verify_system_status.api_gateway.error", error=str(e)) -def check_processors(url: str, min_processors: int, timeout: int, token: Optional[str] = None) -> Tuple[bool, str]: +def check_processors(url: str, min_processors: int, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]: """Check if processors are running via metrics endpoint.""" try: # Construct metrics URL from API URL @@ -188,17 +200,17 @@ def check_processors(url: str, min_processors: int, timeout: int, token: Optiona processor_count = len(data.get("data", {}).get("result", [])) if processor_count >= min_processors: - return True, f"Found {processor_count} processors (≥ {min_processors})" + return True, tr.t("cli.verify_system_status.processors.found", count=processor_count, min=min_processors) else: - return False, f"Only {processor_count} processors running (need {min_processors})" + return False, tr.t("cli.verify_system_status.processors.only", count=processor_count, min=min_processors) else: - return False, f"Metrics returned status {resp.status_code}" + return False, tr.t("cli.verify_system_status.processors.metrics_status", status_code=resp.status_code) except Exception as e: - return False, f"Processor check error: {e}" + return False, tr.t("cli.verify_system_status.processors.error", error=str(e)) -def check_flow_blueprints(url: str, timeout: int, token: Optional[str] = None) -> Tuple[bool, str]: +def check_flow_blueprints(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]: """Check if flow blueprints are loaded.""" try: api = Api(url, token=token, timeout=timeout) @@ -207,15 +219,15 @@ def check_flow_blueprints(url: str, timeout: int, token: Optional[str] = None) - blueprints = flow_api.list_blueprints() if blueprints and len(blueprints) > 0: - return True, f"Found {len(blueprints)} flow blueprint(s)" + return True, tr.t("cli.verify_system_status.flow_blueprints.found", count=len(blueprints)) else: - return False, "No flow blueprints found" + return False, tr.t("cli.verify_system_status.flow_blueprints.none") except Exception as e: - return False, f"Flow blueprints check error: {e}" + return False, tr.t("cli.verify_system_status.flow_blueprints.error", error=str(e)) -def check_flows(url: str, timeout: int, token: Optional[str] = None) -> Tuple[bool, str]: +def check_flows(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]: """Check if flow manager is responding.""" try: api = Api(url, token=token, timeout=timeout) @@ -224,13 +236,13 @@ def check_flows(url: str, timeout: int, token: Optional[str] = None) -> Tuple[bo flows = flow_api.list() # Success if we get a response (even if empty) - return True, f"Flow manager responding ({len(flows)} flow(s))" + return True, tr.t("cli.verify_system_status.flows.responding", count=len(flows)) except Exception as e: - return False, f"Flow manager check error: {e}" + return False, tr.t("cli.verify_system_status.flows.error", error=str(e)) -def check_prompts(url: str, timeout: int, token: Optional[str] = None) -> Tuple[bool, str]: +def check_prompts(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]: """Check if prompts are loaded.""" try: api = Api(url, token=token, timeout=timeout) @@ -248,15 +260,15 @@ def check_prompts(url: str, timeout: int, token: Optional[str] = None) -> Tuple[ ix = json.loads(values[0].value) if ix and len(ix) > 0: - return True, f"Found {len(ix)} prompt(s)" + return True, tr.t("cli.verify_system_status.prompts.found", count=len(ix)) else: - return False, "No prompts found" + return False, tr.t("cli.verify_system_status.prompts.none") except Exception as e: - return False, f"Prompts check error: {e}" + return False, tr.t("cli.verify_system_status.prompts.error", error=str(e)) -def check_library(url: str, timeout: int, token: Optional[str] = None) -> Tuple[bool, str]: +def check_library(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]: """Check if library service is responding.""" try: api = Api(url, token=token, timeout=timeout) @@ -266,13 +278,13 @@ def check_library(url: str, timeout: int, token: Optional[str] = None) -> Tuple[ docs = library_api.get_documents(user="trustgraph") # Success if we get a valid response (even if empty) - return True, f"Library responding ({len(docs)} document(s))" + return True, tr.t("cli.verify_system_status.library.responding", count=len(docs)) except Exception as e: - return False, f"Library check error: {e}" + return False, tr.t("cli.verify_system_status.library.error", error=str(e)) -def check_ui(url: str, timeout: int) -> Tuple[bool, str]: +def check_ui(url: str, timeout: int, tr) -> Tuple[bool, str]: """Check if Workbench UI is responding.""" try: if not url.endswith('/'): @@ -280,15 +292,15 @@ def check_ui(url: str, timeout: int) -> Tuple[bool, str]: resp = requests.get(f"{url}index.html", timeout=timeout) if resp.status_code == 200: - return True, "Workbench UI is responding" + return True, tr.t("cli.verify_system_status.ui.responding") else: - return False, f"UI returned status {resp.status_code}" + return False, tr.t("cli.verify_system_status.ui.status", status_code=resp.status_code) except requests.exceptions.Timeout: - return False, "UI connection timeout" + return False, tr.t("cli.verify_system_status.ui.timeout") except requests.exceptions.ConnectionError: - return False, "Cannot connect to UI" + return False, tr.t("cli.verify_system_status.ui.cannot_connect") except Exception as e: - return False, f"UI error: {e}" + return False, tr.t("cli.verify_system_status.ui.error", error=str(e)) def main(): @@ -300,6 +312,12 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter, ) + parser.add_argument( + '--lang', + default=os.getenv("TRUSTGRAPH_LANG", "en"), + help='Language code for CLI output (default: $TRUSTGRAPH_LANG or en)' + ) + parser.add_argument( '--global-timeout', type=int, @@ -366,119 +384,135 @@ def main(): args = parser.parse_args() + tr = get_translator(args.lang) + # Create health checker checker = HealthChecker( global_timeout=args.global_timeout, check_timeout=args.check_timeout, retry_delay=args.retry_delay, - verbose=args.verbose + verbose=args.verbose, + translator=tr, ) print("=" * 60) - print("TrustGraph System Status Verification") + print(tr.t("cli.verify_system_status.title")) print("=" * 60) print() # Phase 1: Infrastructure - print("Phase 1: Infrastructure") + print(tr.t("cli.verify_system_status.phase_1")) print("-" * 60) - - # Pulsar check is skipped — not all deployments use Pulsar. - # The API Gateway check covers broker connectivity indirectly. + if not checker.run_check( + tr.t("cli.verify_system_status.check_name.pulsar"), + check_pulsar, + args.pulsar_url, + args.check_timeout, + tr, + ): + print(f"\n⚠️ {tr.t('cli.verify_system_status.pulsar_not_responding')}") + print() checker.run_check( - "API Gateway", + tr.t("cli.verify_system_status.check_name.api_gateway"), check_api_gateway, args.api_url, args.check_timeout, - args.token + tr, + args.token, ) print() # Phase 2: Core Services - print("Phase 2: Core Services") + print(tr.t("cli.verify_system_status.phase_2")) print("-" * 60) checker.run_check( - "Processors", + tr.t("cli.verify_system_status.check_name.processors"), check_processors, args.api_url, args.min_processors, args.check_timeout, - args.token + tr, + args.token, ) checker.run_check( - "Flow Blueprints", + tr.t("cli.verify_system_status.check_name.flow_blueprints"), check_flow_blueprints, args.api_url, args.check_timeout, - args.token + tr, + args.token, ) checker.run_check( - "Flows", + tr.t("cli.verify_system_status.check_name.flows"), check_flows, args.api_url, args.check_timeout, - args.token + tr, + args.token, ) checker.run_check( - "Prompts", + tr.t("cli.verify_system_status.check_name.prompts"), check_prompts, args.api_url, args.check_timeout, - args.token + tr, + args.token, ) print() # Phase 3: Data Services - print("Phase 3: Data Services") + print(tr.t("cli.verify_system_status.phase_3")) print("-" * 60) checker.run_check( - "Library", + tr.t("cli.verify_system_status.check_name.library"), check_library, args.api_url, args.check_timeout, - args.token + tr, + args.token, ) print() # Phase 4: UI (optional) if not args.skip_ui: - print("Phase 4: User Interface") + print(tr.t("cli.verify_system_status.phase_4")) print("-" * 60) checker.run_check( - "Workbench UI", + tr.t("cli.verify_system_status.check_name.workbench_ui"), check_ui, args.ui_url, - args.check_timeout + args.check_timeout, + tr, ) print() # Summary print("=" * 60) - print("Summary") + print(tr.t("cli.verify_system_status.summary")) print("=" * 60) total_checks = checker.checks_passed + checker.checks_failed - print(f"Checks passed: {checker.checks_passed}/{total_checks}") - print(f"Checks failed: {checker.checks_failed}/{total_checks}") - print(f"Total time: {checker.elapsed()}") + print(tr.t("cli.verify_system_status.checks_passed", passed=checker.checks_passed, total=total_checks)) + print(tr.t("cli.verify_system_status.checks_failed", failed=checker.checks_failed, total=total_checks)) + print(tr.t("cli.verify_system_status.total_time", elapsed=checker.elapsed())) if checker.checks_failed == 0: - print("\n✓ System is healthy!") + print(f"\n✓ {tr.t('cli.verify_system_status.system_healthy')}") sys.exit(0) else: - print(f"\n✗ System has {checker.checks_failed} failing check(s)") + print(f"\n✗ {tr.t('cli.verify_system_status.system_failing', failed=checker.checks_failed)}") sys.exit(1) diff --git a/trustgraph-flow/trustgraph/gateway/endpoint/i18n.py b/trustgraph-flow/trustgraph/gateway/endpoint/i18n.py new file mode 100644 index 00000000..b949a499 --- /dev/null +++ b/trustgraph-flow/trustgraph/gateway/endpoint/i18n.py @@ -0,0 +1,51 @@ +import logging + +from aiohttp import web + +from trustgraph.i18n import get_language_pack + +logger = logging.getLogger("endpoint") +logger.setLevel(logging.INFO) + + +class I18nPackEndpoint: + + def __init__(self, endpoint_path: str, auth): + self.path = endpoint_path + self.auth = auth + self.operation = "service" + + async def start(self): + pass + + def add_routes(self, app): + app.add_routes([ + web.get(self.path, self.handle), + ]) + + async def handle(self, request): + logger.debug(f"Processing i18n pack request: {request.path}") + + token = "" + try: + ht = request.headers["Authorization"] + tokens = ht.split(" ", 2) + if tokens[0] != "Bearer": + return web.HTTPUnauthorized() + token = tokens[1] + except Exception: + token = "" + + if not self.auth.permitted(token, self.operation): + return web.HTTPUnauthorized() + + lang = request.match_info.get("lang") or "en" + + # This is a path traversal defense, and is a critical sec defense. + # Do not remove! + if "/" in lang or ".." in lang: + return web.HTTPBadRequest(reason="Invalid language code") + + pack = get_language_pack(lang) + + return web.json_response(pack) diff --git a/trustgraph-flow/trustgraph/gateway/endpoint/manager.py b/trustgraph-flow/trustgraph/gateway/endpoint/manager.py index ff92dca2..fb8b0b76 100644 --- a/trustgraph-flow/trustgraph/gateway/endpoint/manager.py +++ b/trustgraph-flow/trustgraph/gateway/endpoint/manager.py @@ -7,6 +7,7 @@ from . stream_endpoint import StreamEndpoint from . variable_endpoint import VariableEndpoint from . socket import SocketEndpoint from . metrics import MetricsEndpoint +from . i18n import I18nPackEndpoint from .. dispatch.manager import DispatcherManager @@ -23,6 +24,10 @@ class EndpointManager: } self.endpoints = [ + I18nPackEndpoint( + endpoint_path = "/api/v1/i18n/packs/{lang}", + auth = auth, + ), MetricsEndpoint( endpoint_path = "/api/metrics", prometheus_url = prometheus_url,