trustgraph-base 2.2.26__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/PKG-INFO +1 -1
  2. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/__init__.py +2 -0
  3. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/async_flow.py +13 -7
  4. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/async_socket_client.py +27 -13
  5. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/flow.py +32 -10
  6. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/socket_client.py +66 -32
  7. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/types.py +37 -8
  8. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/__init__.py +4 -2
  9. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/agent_client.py +3 -3
  10. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/prompt_client.py +73 -14
  11. trustgraph_base-2.3.1/trustgraph/base/text_completion_client.py +80 -0
  12. trustgraph_base-2.3.1/trustgraph/base_version.py +1 -0
  13. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/agent_client.py +4 -4
  14. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/agent.py +9 -2
  15. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/prompt.py +7 -0
  16. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/retrieval.py +14 -0
  17. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/text_completion.py +3 -3
  18. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/provenance/__init__.py +14 -0
  19. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/provenance/agent.py +141 -0
  20. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/provenance/namespaces.py +12 -0
  21. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/provenance/triples.py +33 -0
  22. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/provenance/uris.py +5 -0
  23. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/agent.py +7 -2
  24. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/llm.py +3 -3
  25. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/prompt.py +5 -0
  26. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/retrieval.py +6 -0
  27. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph_base.egg-info/PKG-INFO +1 -1
  28. trustgraph_base-2.2.26/trustgraph/base/text_completion_client.py +0 -57
  29. trustgraph_base-2.2.26/trustgraph/base_version.py +0 -1
  30. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/README.md +0 -0
  31. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/pyproject.toml +0 -0
  32. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/setup.cfg +0 -0
  33. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/api.py +0 -0
  34. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/async_bulk_client.py +0 -0
  35. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/async_metrics.py +0 -0
  36. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/bulk_client.py +0 -0
  37. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/collection.py +0 -0
  38. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/config.py +0 -0
  39. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/exceptions.py +0 -0
  40. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/explainability.py +0 -0
  41. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/knowledge.py +0 -0
  42. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/library.py +0 -0
  43. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/api/metrics.py +0 -0
  44. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/agent_service.py +0 -0
  45. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/async_processor.py +0 -0
  46. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/backend.py +0 -0
  47. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/cassandra_config.py +0 -0
  48. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/chunking_service.py +0 -0
  49. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/collection_config_handler.py +0 -0
  50. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/consumer.py +0 -0
  51. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/consumer_spec.py +0 -0
  52. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/document_embeddings_client.py +0 -0
  53. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/document_embeddings_query_service.py +0 -0
  54. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/document_embeddings_store_service.py +0 -0
  55. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/dynamic_tool_service.py +0 -0
  56. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/embeddings_client.py +0 -0
  57. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/embeddings_service.py +0 -0
  58. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/flow.py +0 -0
  59. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/flow_processor.py +0 -0
  60. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/graph_embeddings_client.py +0 -0
  61. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/graph_embeddings_query_service.py +0 -0
  62. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/graph_embeddings_store_service.py +0 -0
  63. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/graph_rag_client.py +0 -0
  64. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/librarian_client.py +0 -0
  65. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/llm_service.py +0 -0
  66. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/logging.py +0 -0
  67. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/metrics.py +0 -0
  68. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/parameter_spec.py +0 -0
  69. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/producer.py +0 -0
  70. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/producer_spec.py +0 -0
  71. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/publisher.py +0 -0
  72. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/pubsub.py +0 -0
  73. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/pulsar_backend.py +0 -0
  74. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/rabbitmq_backend.py +0 -0
  75. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/request_response_spec.py +0 -0
  76. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/row_embeddings_query_client.py +0 -0
  77. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/serialization.py +0 -0
  78. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/spec.py +0 -0
  79. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/structured_query_client.py +0 -0
  80. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/subscriber.py +0 -0
  81. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/subscriber_spec.py +0 -0
  82. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/tool_client.py +0 -0
  83. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/tool_service.py +0 -0
  84. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/tool_service_client.py +0 -0
  85. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/triples_client.py +0 -0
  86. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/triples_query_service.py +0 -0
  87. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/base/triples_store_service.py +0 -0
  88. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/__init__.py +0 -0
  89. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/base.py +0 -0
  90. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/config_client.py +0 -0
  91. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/document_embeddings_client.py +0 -0
  92. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/document_rag_client.py +0 -0
  93. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/embeddings_client.py +0 -0
  94. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/graph_embeddings_client.py +0 -0
  95. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/graph_rag_client.py +0 -0
  96. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/llm_client.py +0 -0
  97. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/prompt_client.py +0 -0
  98. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/row_embeddings_client.py +0 -0
  99. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/clients/triples_query_client.py +0 -0
  100. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/exceptions.py +0 -0
  101. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/knowledge/__init__.py +0 -0
  102. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/knowledge/defs.py +0 -0
  103. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/knowledge/document.py +0 -0
  104. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/knowledge/identifier.py +0 -0
  105. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/knowledge/organization.py +0 -0
  106. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/knowledge/publication.py +0 -0
  107. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/log_level.py +0 -0
  108. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/__init__.py +0 -0
  109. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/registry.py +0 -0
  110. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/__init__.py +0 -0
  111. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/base.py +0 -0
  112. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/collection.py +0 -0
  113. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/config.py +0 -0
  114. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/diagnosis.py +0 -0
  115. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/document_loading.py +0 -0
  116. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/embeddings.py +0 -0
  117. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/embeddings_query.py +0 -0
  118. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/flow.py +0 -0
  119. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/knowledge.py +0 -0
  120. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/library.py +0 -0
  121. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/metadata.py +0 -0
  122. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/nlp_query.py +0 -0
  123. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/primitives.py +0 -0
  124. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/rows_query.py +0 -0
  125. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/sparql_query.py +0 -0
  126. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/structured_query.py +0 -0
  127. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/tool.py +0 -0
  128. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/messaging/translators/triples.py +0 -0
  129. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/objects/__init__.py +0 -0
  130. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/objects/field.py +0 -0
  131. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/objects/object.py +0 -0
  132. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/provenance/vocabulary.py +0 -0
  133. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/rdf.py +0 -0
  134. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/__init__.py +0 -0
  135. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/core/__init__.py +0 -0
  136. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/core/metadata.py +0 -0
  137. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/core/primitives.py +0 -0
  138. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/core/topic.py +0 -0
  139. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/__init__.py +0 -0
  140. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/document.py +0 -0
  141. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/embeddings.py +0 -0
  142. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/graph.py +0 -0
  143. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/knowledge.py +0 -0
  144. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/nlp.py +0 -0
  145. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/object.py +0 -0
  146. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/rows.py +0 -0
  147. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/knowledge/structured.py +0 -0
  148. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/__init__.py +0 -0
  149. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/collection.py +0 -0
  150. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/config.py +0 -0
  151. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/diagnosis.py +0 -0
  152. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/flow.py +0 -0
  153. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/library.py +0 -0
  154. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/lookup.py +0 -0
  155. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/nlp_query.py +0 -0
  156. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/query.py +0 -0
  157. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/rows_query.py +0 -0
  158. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/sparql_query.py +0 -0
  159. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/storage.py +0 -0
  160. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/structured_query.py +0 -0
  161. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph/schema/services/tool_service.py +0 -0
  162. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph_base.egg-info/SOURCES.txt +0 -0
  163. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph_base.egg-info/dependency_links.txt +0 -0
  164. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph_base.egg-info/requires.txt +0 -0
  165. {trustgraph_base-2.2.26 → trustgraph_base-2.3.1}/trustgraph_base.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trustgraph-base
3
- Version: 2.2.26
3
+ Version: 2.3.1
4
4
  Summary: TrustGraph provides a means to run a pipeline of flexible AI processing components in a flexible means to achieve a processing pipeline.
5
5
  Author-email: "trustgraph.ai" <security@trustgraph.ai>
6
6
  Project-URL: Homepage, https://github.com/trustgraph-ai/trustgraph
@@ -107,6 +107,7 @@ from .types import (
107
107
  AgentObservation,
108
108
  AgentAnswer,
109
109
  RAGChunk,
110
+ TextCompletionResult,
110
111
  ProvenanceEvent,
111
112
  )
112
113
 
@@ -185,6 +186,7 @@ __all__ = [
185
186
  "AgentObservation",
186
187
  "AgentAnswer",
187
188
  "RAGChunk",
189
+ "TextCompletionResult",
188
190
  "ProvenanceEvent",
189
191
 
190
192
  # Exceptions
@@ -14,6 +14,8 @@ import aiohttp
14
14
  import json
15
15
  from typing import Optional, Dict, Any, List
16
16
 
17
+ from . types import TextCompletionResult
18
+
17
19
  from . exceptions import ProtocolException, ApplicationException
18
20
 
19
21
 
@@ -434,12 +436,11 @@ class AsyncFlowInstance:
434
436
 
435
437
  return await self.request("agent", request_data)
436
438
 
437
- async def text_completion(self, system: str, prompt: str, **kwargs: Any) -> str:
439
+ async def text_completion(self, system: str, prompt: str, **kwargs: Any) -> TextCompletionResult:
438
440
  """
439
441
  Generate text completion (non-streaming).
440
442
 
441
443
  Generates a text response from an LLM given a system prompt and user prompt.
442
- Returns the complete response text.
443
444
 
444
445
  Note: This method does not support streaming. For streaming text generation,
445
446
  use AsyncSocketFlowInstance.text_completion() instead.
@@ -450,19 +451,19 @@ class AsyncFlowInstance:
450
451
  **kwargs: Additional service-specific parameters
451
452
 
452
453
  Returns:
453
- str: Complete generated text response
454
+ TextCompletionResult: Result with text, in_token, out_token, model
454
455
 
455
456
  Example:
456
457
  ```python
457
458
  async_flow = await api.async_flow()
458
459
  flow = async_flow.id("default")
459
460
 
460
- # Generate text
461
- response = await flow.text_completion(
461
+ result = await flow.text_completion(
462
462
  system="You are a helpful assistant.",
463
463
  prompt="Explain quantum computing in simple terms."
464
464
  )
465
- print(response)
465
+ print(result.text)
466
+ print(f"Tokens: {result.in_token} in, {result.out_token} out")
466
467
  ```
467
468
  """
468
469
  request_data = {
@@ -473,7 +474,12 @@ class AsyncFlowInstance:
473
474
  request_data.update(kwargs)
474
475
 
475
476
  result = await self.request("text-completion", request_data)
476
- return result.get("response", "")
477
+ return TextCompletionResult(
478
+ text=result.get("response", ""),
479
+ in_token=result.get("in_token"),
480
+ out_token=result.get("out_token"),
481
+ model=result.get("model"),
482
+ )
477
483
 
478
484
  async def graph_rag(self, query: str, user: str, collection: str,
479
485
  max_subgraph_size: int = 1000, max_subgraph_count: int = 5,
@@ -4,7 +4,7 @@ import asyncio
4
4
  import websockets
5
5
  from typing import Optional, Dict, Any, AsyncIterator, Union
6
6
 
7
- from . types import AgentThought, AgentObservation, AgentAnswer, RAGChunk
7
+ from . types import AgentThought, AgentObservation, AgentAnswer, RAGChunk, TextCompletionResult
8
8
  from . exceptions import ProtocolException, ApplicationException
9
9
 
10
10
 
@@ -178,30 +178,32 @@ class AsyncSocketClient:
178
178
 
179
179
  def _parse_chunk(self, resp: Dict[str, Any]):
180
180
  """Parse response chunk into appropriate type. Returns None for non-content messages."""
181
- chunk_type = resp.get("chunk_type")
182
181
  message_type = resp.get("message_type")
183
182
 
184
183
  # Handle new GraphRAG message format with message_type
185
184
  if message_type == "provenance":
186
185
  return None
187
186
 
188
- if chunk_type == "thought":
187
+ if message_type == "thought":
189
188
  return AgentThought(
190
189
  content=resp.get("content", ""),
191
190
  end_of_message=resp.get("end_of_message", False)
192
191
  )
193
- elif chunk_type == "observation":
192
+ elif message_type == "observation":
194
193
  return AgentObservation(
195
194
  content=resp.get("content", ""),
196
195
  end_of_message=resp.get("end_of_message", False)
197
196
  )
198
- elif chunk_type == "answer" or chunk_type == "final-answer":
197
+ elif message_type == "answer" or message_type == "final-answer":
199
198
  return AgentAnswer(
200
199
  content=resp.get("content", ""),
201
200
  end_of_message=resp.get("end_of_message", False),
202
- end_of_dialog=resp.get("end_of_dialog", False)
201
+ end_of_dialog=resp.get("end_of_dialog", False),
202
+ in_token=resp.get("in_token"),
203
+ out_token=resp.get("out_token"),
204
+ model=resp.get("model"),
203
205
  )
204
- elif chunk_type == "action":
206
+ elif message_type == "action":
205
207
  return AgentThought(
206
208
  content=resp.get("content", ""),
207
209
  end_of_message=resp.get("end_of_message", False)
@@ -211,7 +213,10 @@ class AsyncSocketClient:
211
213
  return RAGChunk(
212
214
  content=content,
213
215
  end_of_stream=resp.get("end_of_stream", False),
214
- error=None
216
+ error=None,
217
+ in_token=resp.get("in_token"),
218
+ out_token=resp.get("out_token"),
219
+ model=resp.get("model"),
215
220
  )
216
221
 
217
222
  async def aclose(self):
@@ -269,7 +274,11 @@ class AsyncSocketFlowInstance:
269
274
  return await self.client._send_request("agent", self.flow_id, request)
270
275
 
271
276
  async def text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs):
272
- """Text completion with optional streaming"""
277
+ """Text completion with optional streaming.
278
+
279
+ Non-streaming: returns a TextCompletionResult with text and token counts.
280
+ Streaming: returns an async iterator of RAGChunk (with token counts on the final chunk).
281
+ """
273
282
  request = {
274
283
  "system": system,
275
284
  "prompt": prompt,
@@ -281,13 +290,18 @@ class AsyncSocketFlowInstance:
281
290
  return self._text_completion_streaming(request)
282
291
  else:
283
292
  result = await self.client._send_request("text-completion", self.flow_id, request)
284
- return result.get("response", "")
293
+ return TextCompletionResult(
294
+ text=result.get("response", ""),
295
+ in_token=result.get("in_token"),
296
+ out_token=result.get("out_token"),
297
+ model=result.get("model"),
298
+ )
285
299
 
286
300
  async def _text_completion_streaming(self, request):
287
- """Helper for streaming text completion"""
301
+ """Helper for streaming text completion. Yields RAGChunk objects."""
288
302
  async for chunk in self.client._send_request_streaming("text-completion", self.flow_id, request):
289
- if hasattr(chunk, 'content'):
290
- yield chunk.content
303
+ if isinstance(chunk, RAGChunk):
304
+ yield chunk
291
305
 
292
306
  async def graph_rag(self, query: str, user: str, collection: str,
293
307
  max_subgraph_size: int = 1000, max_subgraph_count: int = 5,
@@ -11,7 +11,7 @@ import base64
11
11
 
12
12
  from .. knowledge import hash, Uri, Literal, QuotedTriple
13
13
  from .. schema import IRI, LITERAL, TRIPLE
14
- from . types import Triple
14
+ from . types import Triple, TextCompletionResult
15
15
  from . exceptions import ProtocolException
16
16
 
17
17
 
@@ -360,16 +360,17 @@ class FlowInstance:
360
360
  prompt: User prompt/question
361
361
 
362
362
  Returns:
363
- str: Generated response text
363
+ TextCompletionResult: Result with text, in_token, out_token, model
364
364
 
365
365
  Example:
366
366
  ```python
367
367
  flow = api.flow().id("default")
368
- response = flow.text_completion(
368
+ result = flow.text_completion(
369
369
  system="You are a helpful assistant",
370
370
  prompt="What is quantum computing?"
371
371
  )
372
- print(response)
372
+ print(result.text)
373
+ print(f"Tokens: {result.in_token} in, {result.out_token} out")
373
374
  ```
374
375
  """
375
376
 
@@ -379,10 +380,17 @@ class FlowInstance:
379
380
  "prompt": prompt
380
381
  }
381
382
 
382
- return self.request(
383
+ result = self.request(
383
384
  "service/text-completion",
384
385
  input
385
- )["response"]
386
+ )
387
+
388
+ return TextCompletionResult(
389
+ text=result.get("response", ""),
390
+ in_token=result.get("in_token"),
391
+ out_token=result.get("out_token"),
392
+ model=result.get("model"),
393
+ )
386
394
 
387
395
  def agent(self, question, user="trustgraph", state=None, group=None, history=None):
388
396
  """
@@ -498,10 +506,17 @@ class FlowInstance:
498
506
  "edge-limit": edge_limit,
499
507
  }
500
508
 
501
- return self.request(
509
+ result = self.request(
502
510
  "service/graph-rag",
503
511
  input
504
- )["response"]
512
+ )
513
+
514
+ return TextCompletionResult(
515
+ text=result.get("response", ""),
516
+ in_token=result.get("in_token"),
517
+ out_token=result.get("out_token"),
518
+ model=result.get("model"),
519
+ )
505
520
 
506
521
  def document_rag(
507
522
  self, query, user="trustgraph", collection="default",
@@ -543,10 +558,17 @@ class FlowInstance:
543
558
  "doc-limit": doc_limit,
544
559
  }
545
560
 
546
- return self.request(
561
+ result = self.request(
547
562
  "service/document-rag",
548
563
  input
549
- )["response"]
564
+ )
565
+
566
+ return TextCompletionResult(
567
+ text=result.get("response", ""),
568
+ in_token=result.get("in_token"),
569
+ out_token=result.get("out_token"),
570
+ model=result.get("model"),
571
+ )
550
572
 
551
573
  def embeddings(self, texts):
552
574
  """
@@ -14,7 +14,7 @@ import websockets
14
14
  from typing import Optional, Dict, Any, Iterator, Union, List
15
15
  from threading import Lock
16
16
 
17
- from . types import AgentThought, AgentObservation, AgentAnswer, RAGChunk, StreamingChunk, ProvenanceEvent
17
+ from . types import AgentThought, AgentObservation, AgentAnswer, RAGChunk, StreamingChunk, ProvenanceEvent, TextCompletionResult
18
18
  from . exceptions import ProtocolException, raise_from_error_dict
19
19
 
20
20
 
@@ -360,41 +360,36 @@ class SocketClient:
360
360
 
361
361
  def _parse_chunk(self, resp: Dict[str, Any], include_provenance: bool = False) -> Optional[StreamingChunk]:
362
362
  """Parse response chunk into appropriate type. Returns None for non-content messages."""
363
- chunk_type = resp.get("chunk_type")
364
363
  message_type = resp.get("message_type")
365
364
 
366
- # Handle GraphRAG/DocRAG message format with message_type
367
365
  if message_type == "explain":
368
366
  if include_provenance:
369
367
  return self._build_provenance_event(resp)
370
368
  return None
371
369
 
372
- # Handle Agent message format with chunk_type="explain"
373
- if chunk_type == "explain":
374
- if include_provenance:
375
- return self._build_provenance_event(resp)
376
- return None
377
-
378
- if chunk_type == "thought":
370
+ if message_type == "thought":
379
371
  return AgentThought(
380
372
  content=resp.get("content", ""),
381
373
  end_of_message=resp.get("end_of_message", False),
382
374
  message_id=resp.get("message_id", ""),
383
375
  )
384
- elif chunk_type == "observation":
376
+ elif message_type == "observation":
385
377
  return AgentObservation(
386
378
  content=resp.get("content", ""),
387
379
  end_of_message=resp.get("end_of_message", False),
388
380
  message_id=resp.get("message_id", ""),
389
381
  )
390
- elif chunk_type == "answer" or chunk_type == "final-answer":
382
+ elif message_type == "answer" or message_type == "final-answer":
391
383
  return AgentAnswer(
392
384
  content=resp.get("content", ""),
393
385
  end_of_message=resp.get("end_of_message", False),
394
386
  end_of_dialog=resp.get("end_of_dialog", False),
395
387
  message_id=resp.get("message_id", ""),
388
+ in_token=resp.get("in_token"),
389
+ out_token=resp.get("out_token"),
390
+ model=resp.get("model"),
396
391
  )
397
- elif chunk_type == "action":
392
+ elif message_type == "action":
398
393
  return AgentThought(
399
394
  content=resp.get("content", ""),
400
395
  end_of_message=resp.get("end_of_message", False)
@@ -404,7 +399,10 @@ class SocketClient:
404
399
  return RAGChunk(
405
400
  content=content,
406
401
  end_of_stream=resp.get("end_of_stream", False),
407
- error=None
402
+ error=None,
403
+ in_token=resp.get("in_token"),
404
+ out_token=resp.get("out_token"),
405
+ model=resp.get("model"),
408
406
  )
409
407
 
410
408
  def _build_provenance_event(self, resp: Dict[str, Any]) -> ProvenanceEvent:
@@ -543,8 +541,12 @@ class SocketFlowInstance:
543
541
  streaming=True, include_provenance=True
544
542
  )
545
543
 
546
- def text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> Union[str, Iterator[str]]:
547
- """Execute text completion with optional streaming."""
544
+ def text_completion(self, system: str, prompt: str, streaming: bool = False, **kwargs) -> Union[TextCompletionResult, Iterator[RAGChunk]]:
545
+ """Execute text completion with optional streaming.
546
+
547
+ Non-streaming: returns a TextCompletionResult with text and token counts.
548
+ Streaming: returns an iterator of RAGChunk (with token counts on the final chunk).
549
+ """
548
550
  request = {
549
551
  "system": system,
550
552
  "prompt": prompt,
@@ -557,12 +559,17 @@ class SocketFlowInstance:
557
559
  if streaming:
558
560
  return self._text_completion_generator(result)
559
561
  else:
560
- return result.get("response", "")
562
+ return TextCompletionResult(
563
+ text=result.get("response", ""),
564
+ in_token=result.get("in_token"),
565
+ out_token=result.get("out_token"),
566
+ model=result.get("model"),
567
+ )
561
568
 
562
- def _text_completion_generator(self, result: Iterator[StreamingChunk]) -> Iterator[str]:
569
+ def _text_completion_generator(self, result: Iterator[StreamingChunk]) -> Iterator[RAGChunk]:
563
570
  for chunk in result:
564
- if hasattr(chunk, 'content'):
565
- yield chunk.content
571
+ if isinstance(chunk, RAGChunk):
572
+ yield chunk
566
573
 
567
574
  def graph_rag(
568
575
  self,
@@ -577,8 +584,12 @@ class SocketFlowInstance:
577
584
  edge_limit: int = 25,
578
585
  streaming: bool = False,
579
586
  **kwargs: Any
580
- ) -> Union[str, Iterator[str]]:
581
- """Execute graph-based RAG query with optional streaming."""
587
+ ) -> Union[TextCompletionResult, Iterator[RAGChunk]]:
588
+ """Execute graph-based RAG query with optional streaming.
589
+
590
+ Non-streaming: returns a TextCompletionResult with text and token counts.
591
+ Streaming: returns an iterator of RAGChunk (with token counts on the final chunk).
592
+ """
582
593
  request = {
583
594
  "query": query,
584
595
  "user": user,
@@ -598,7 +609,12 @@ class SocketFlowInstance:
598
609
  if streaming:
599
610
  return self._rag_generator(result)
600
611
  else:
601
- return result.get("response", "")
612
+ return TextCompletionResult(
613
+ text=result.get("response", ""),
614
+ in_token=result.get("in_token"),
615
+ out_token=result.get("out_token"),
616
+ model=result.get("model"),
617
+ )
602
618
 
603
619
  def graph_rag_explain(
604
620
  self,
@@ -642,8 +658,12 @@ class SocketFlowInstance:
642
658
  doc_limit: int = 10,
643
659
  streaming: bool = False,
644
660
  **kwargs: Any
645
- ) -> Union[str, Iterator[str]]:
646
- """Execute document-based RAG query with optional streaming."""
661
+ ) -> Union[TextCompletionResult, Iterator[RAGChunk]]:
662
+ """Execute document-based RAG query with optional streaming.
663
+
664
+ Non-streaming: returns a TextCompletionResult with text and token counts.
665
+ Streaming: returns an iterator of RAGChunk (with token counts on the final chunk).
666
+ """
647
667
  request = {
648
668
  "query": query,
649
669
  "user": user,
@@ -658,7 +678,12 @@ class SocketFlowInstance:
658
678
  if streaming:
659
679
  return self._rag_generator(result)
660
680
  else:
661
- return result.get("response", "")
681
+ return TextCompletionResult(
682
+ text=result.get("response", ""),
683
+ in_token=result.get("in_token"),
684
+ out_token=result.get("out_token"),
685
+ model=result.get("model"),
686
+ )
662
687
 
663
688
  def document_rag_explain(
664
689
  self,
@@ -684,10 +709,10 @@ class SocketFlowInstance:
684
709
  streaming=True, include_provenance=True
685
710
  )
686
711
 
687
- def _rag_generator(self, result: Iterator[StreamingChunk]) -> Iterator[str]:
712
+ def _rag_generator(self, result: Iterator[StreamingChunk]) -> Iterator[RAGChunk]:
688
713
  for chunk in result:
689
- if hasattr(chunk, 'content'):
690
- yield chunk.content
714
+ if isinstance(chunk, RAGChunk):
715
+ yield chunk
691
716
 
692
717
  def prompt(
693
718
  self,
@@ -695,8 +720,12 @@ class SocketFlowInstance:
695
720
  variables: Dict[str, str],
696
721
  streaming: bool = False,
697
722
  **kwargs: Any
698
- ) -> Union[str, Iterator[str]]:
699
- """Execute a prompt template with optional streaming."""
723
+ ) -> Union[TextCompletionResult, Iterator[RAGChunk]]:
724
+ """Execute a prompt template with optional streaming.
725
+
726
+ Non-streaming: returns a TextCompletionResult with text and token counts.
727
+ Streaming: returns an iterator of RAGChunk (with token counts on the final chunk).
728
+ """
700
729
  request = {
701
730
  "id": id,
702
731
  "variables": variables,
@@ -709,7 +738,12 @@ class SocketFlowInstance:
709
738
  if streaming:
710
739
  return self._rag_generator(result)
711
740
  else:
712
- return result.get("response", "")
741
+ return TextCompletionResult(
742
+ text=result.get("text", result.get("response", "")),
743
+ in_token=result.get("in_token"),
744
+ out_token=result.get("out_token"),
745
+ model=result.get("model"),
746
+ )
713
747
 
714
748
  def graph_embeddings_query(
715
749
  self,
@@ -149,10 +149,10 @@ class AgentThought(StreamingChunk):
149
149
  Attributes:
150
150
  content: Agent's thought text
151
151
  end_of_message: True if this completes the current thought
152
- chunk_type: Always "thought"
152
+ message_type: Always "thought"
153
153
  message_id: Provenance URI of the entity being built
154
154
  """
155
- chunk_type: str = "thought"
155
+ message_type: str = "thought"
156
156
  message_id: str = ""
157
157
 
158
158
  @dataclasses.dataclass
@@ -166,10 +166,10 @@ class AgentObservation(StreamingChunk):
166
166
  Attributes:
167
167
  content: Observation text describing tool results
168
168
  end_of_message: True if this completes the current observation
169
- chunk_type: Always "observation"
169
+ message_type: Always "observation"
170
170
  message_id: Provenance URI of the entity being built
171
171
  """
172
- chunk_type: str = "observation"
172
+ message_type: str = "observation"
173
173
  message_id: str = ""
174
174
 
175
175
  @dataclasses.dataclass
@@ -184,11 +184,14 @@ class AgentAnswer(StreamingChunk):
184
184
  content: Answer text
185
185
  end_of_message: True if this completes the current answer segment
186
186
  end_of_dialog: True if this completes the entire agent interaction
187
- chunk_type: Always "final-answer"
187
+ message_type: Always "final-answer"
188
188
  """
189
- chunk_type: str = "final-answer"
189
+ message_type: str = "final-answer"
190
190
  end_of_dialog: bool = False
191
191
  message_id: str = ""
192
+ in_token: Optional[int] = None
193
+ out_token: Optional[int] = None
194
+ model: Optional[str] = None
192
195
 
193
196
  @dataclasses.dataclass
194
197
  class RAGChunk(StreamingChunk):
@@ -202,11 +205,37 @@ class RAGChunk(StreamingChunk):
202
205
  content: Generated text content
203
206
  end_of_stream: True if this is the final chunk of the stream
204
207
  error: Optional error information if an error occurred
205
- chunk_type: Always "rag"
208
+ in_token: Input token count (populated on the final chunk, 0 otherwise)
209
+ out_token: Output token count (populated on the final chunk, 0 otherwise)
210
+ model: Model identifier (populated on the final chunk, empty otherwise)
211
+ message_type: Always "rag"
206
212
  """
207
- chunk_type: str = "rag"
213
+ message_type: str = "rag"
208
214
  end_of_stream: bool = False
209
215
  error: Optional[Dict[str, str]] = None
216
+ in_token: Optional[int] = None
217
+ out_token: Optional[int] = None
218
+ model: Optional[str] = None
219
+
220
+ @dataclasses.dataclass
221
+ class TextCompletionResult:
222
+ """
223
+ Result from a text completion request.
224
+
225
+ Returned by text_completion() in both streaming and non-streaming modes.
226
+ In streaming mode, text is None (chunks are delivered via the iterator).
227
+ In non-streaming mode, text contains the complete response.
228
+
229
+ Attributes:
230
+ text: Complete response text (None in streaming mode)
231
+ in_token: Input token count (None if not available)
232
+ out_token: Output token count (None if not available)
233
+ model: Model identifier (None if not available)
234
+ """
235
+ text: Optional[str]
236
+ in_token: Optional[int] = None
237
+ out_token: Optional[int] = None
238
+ model: Optional[str] = None
210
239
 
211
240
  @dataclasses.dataclass
212
241
  class ProvenanceEvent:
@@ -18,8 +18,10 @@ from . librarian_client import LibrarianClient
18
18
  from . chunking_service import ChunkingService
19
19
  from . embeddings_service import EmbeddingsService
20
20
  from . embeddings_client import EmbeddingsClientSpec
21
- from . text_completion_client import TextCompletionClientSpec
22
- from . prompt_client import PromptClientSpec
21
+ from . text_completion_client import (
22
+ TextCompletionClientSpec, TextCompletionClient, TextCompletionResult,
23
+ )
24
+ from . prompt_client import PromptClientSpec, PromptClient, PromptResult
23
25
  from . triples_store_service import TriplesStoreService
24
26
  from . graph_embeddings_store_service import GraphEmbeddingsStoreService
25
27
  from . document_embeddings_store_service import DocumentEmbeddingsStoreService
@@ -30,19 +30,19 @@ class AgentClient(RequestResponse):
30
30
  raise RuntimeError(resp.error.message)
31
31
 
32
32
  # Handle thought chunks
33
- if resp.chunk_type == 'thought':
33
+ if resp.message_type == 'thought':
34
34
  if think:
35
35
  await think(resp.content, resp.end_of_message)
36
36
  return False # Continue receiving
37
37
 
38
38
  # Handle observation chunks
39
- if resp.chunk_type == 'observation':
39
+ if resp.message_type == 'observation':
40
40
  if observe:
41
41
  await observe(resp.content, resp.end_of_message)
42
42
  return False # Continue receiving
43
43
 
44
44
  # Handle answer chunks
45
- if resp.chunk_type == 'answer':
45
+ if resp.message_type == 'answer':
46
46
  if resp.content:
47
47
  accumulated_answer.append(resp.content)
48
48
  if answer_callback: