gaard-core 0.2.7__tar.gz → 0.2.8__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 (62) hide show
  1. {gaard_core-0.2.7 → gaard_core-0.2.8}/PKG-INFO +2 -2
  2. {gaard_core-0.2.7 → gaard_core-0.2.8}/pyproject.toml +2 -2
  3. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_pipeline/llm_sql_generator.py +26 -0
  4. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_pipeline/models.py +1 -0
  5. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_pipeline/pipeline.py +46 -13
  6. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core.egg-info/PKG-INFO +2 -2
  7. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core.egg-info/requires.txt +1 -1
  8. {gaard_core-0.2.7 → gaard_core-0.2.8}/README.md +0 -0
  9. {gaard_core-0.2.7 → gaard_core-0.2.8}/setup.cfg +0 -0
  10. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/__init__.py +0 -0
  11. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/conversation_context/__init__.py +0 -0
  12. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/conversation_context/llm_classifier.py +0 -0
  13. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/conversation_context/mock_classifier.py +0 -0
  14. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/errors.py +0 -0
  15. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/execution/__init__.py +0 -0
  16. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/execution/mock_executor.py +0 -0
  17. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/json_utils.py +0 -0
  18. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/llm_output.py +0 -0
  19. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/__init__.py +0 -0
  20. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/conversation_context_prompt.py +0 -0
  21. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/intent_classification_prompt.py +0 -0
  22. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/models.py +0 -0
  23. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/result_classification_prompt.py +0 -0
  24. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/result_interpretation_prompt.py +0 -0
  25. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/schema_formatter.py +0 -0
  26. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/prompt_compiler/sql_generation_prompt.py +0 -0
  27. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/py.typed +0 -0
  28. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_intent/__init__.py +0 -0
  29. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_intent/llm_classifier.py +0 -0
  30. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_intent/mock_classifier.py +0 -0
  31. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_pipeline/__init__.py +0 -0
  32. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/query_pipeline/mock_sql_generator.py +0 -0
  33. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/result_classifier/__init__.py +0 -0
  34. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/result_classifier/llm_classifier.py +0 -0
  35. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/result_classifier/mock_classifier.py +0 -0
  36. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/result_interpreter/__init__.py +0 -0
  37. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/result_interpreter/llm_interpreter.py +0 -0
  38. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/result_interpreter/mock_interpreter.py +0 -0
  39. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/schema/__init__.py +0 -0
  40. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/schema/cache.py +0 -0
  41. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/schema/context.py +0 -0
  42. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/schema/models.py +0 -0
  43. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/sql_validator/__init__.py +0 -0
  44. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core/sql_validator/select_only.py +0 -0
  45. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core.egg-info/SOURCES.txt +0 -0
  46. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core.egg-info/dependency_links.txt +0 -0
  47. {gaard_core-0.2.7 → gaard_core-0.2.8}/src/gaard_core.egg-info/top_level.txt +0 -0
  48. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_conversation_context_classifier.py +0 -0
  49. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_json_utils.py +0 -0
  50. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_llm_output.py +0 -0
  51. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_llm_query_intent_classifier.py +0 -0
  52. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_llm_result_classifier.py +0 -0
  53. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_llm_result_interpreter.py +0 -0
  54. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_llm_sql_generator.py +0 -0
  55. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_query_pipeline.py +0 -0
  56. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_result_classification_prompt_compiler.py +0 -0
  57. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_result_interpretation_prompt_compiler.py +0 -0
  58. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_schema_context_cache.py +0 -0
  59. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_schema_context_service.py +0 -0
  60. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_schema_prompt_formatter.py +0 -0
  61. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_sql_generation_prompt_compiler.py +0 -0
  62. {gaard_core-0.2.7 → gaard_core-0.2.8}/tests/test_sql_validator.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gaard-core
3
- Version: 0.2.7
3
+ Version: 0.2.8
4
4
  Summary: Core GAARD query pipeline, prompt compiler, policies and SQL validation
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
- Requires-Dist: gaard-plugin-api<0.3.0,>=0.2.7
7
+ Requires-Dist: gaard-plugin-api<0.3.0,>=0.2.8
8
8
  Requires-Dist: pydantic>=2.7.0
9
9
  Requires-Dist: sqlglot>=25.0.0
10
10
  Provides-Extra: dev
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gaard-core"
7
- version = "0.2.7"
7
+ version = "0.2.8"
8
8
  description = "Core GAARD query pipeline, prompt compiler, policies and SQL validation"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
11
11
  dependencies = [
12
- "gaard-plugin-api>=0.2.7,<0.3.0",
12
+ "gaard-plugin-api>=0.2.8,<0.3.0",
13
13
  "pydantic>=2.7.0",
14
14
  "sqlglot>=25.0.0",
15
15
  ]
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from typing import Any, Protocol
2
3
 
3
4
  from gaard_core.prompt_compiler.models import CompiledPrompt, SqlGenerationPromptRequest
@@ -8,6 +9,9 @@ from gaard_llm.openai_compatible.client import OpenAICompatibleClient
8
9
  from gaard_llm.providers.models import ChatCompletionRequest, ChatMessage
9
10
 
10
11
 
12
+ logger = logging.getLogger(__name__)
13
+
14
+
11
15
  class SqlPromptCompiler(Protocol):
12
16
  def compile(self, request: SqlGenerationPromptRequest) -> CompiledPrompt:
13
17
  pass
@@ -42,6 +46,20 @@ class LlmSqlGenerator:
42
46
  )
43
47
  )
44
48
 
49
+ # This is deliberately logged as separate fields so a failed text-to-SQL
50
+ # request can be reconstructed from the service log without guessing
51
+ # which dialect or schema context reached the model.
52
+ logger.info(
53
+ "SQL generation request: model=%r dialect=%r max_rows=%s question=%r "
54
+ "system_prompt=%r user_prompt=%r",
55
+ self.model,
56
+ self.dialect,
57
+ self.max_rows,
58
+ request.question,
59
+ compiled_prompt.system_prompt,
60
+ compiled_prompt.user_prompt,
61
+ )
62
+
45
63
  response = self.client.create_chat_completion(
46
64
  ChatCompletionRequest(
47
65
  model=self.model,
@@ -62,12 +80,20 @@ class LlmSqlGenerator:
62
80
 
63
81
  sql = self._clean_sql(response.content)
64
82
 
83
+ logger.info(
84
+ "SQL generation response: model=%r raw_response=%r cleaned_sql=%r",
85
+ self.model,
86
+ response.content,
87
+ sql,
88
+ )
89
+
65
90
  return GeneratedSql(
66
91
  sql=sql,
67
92
  confidence=0.0,
68
93
  assumptions=[
69
94
  "SQL generated by OpenAI-compatible LLM provider.",
70
95
  ],
96
+ prompt_metadata=compiled_prompt.metadata,
71
97
  )
72
98
 
73
99
  def _clean_sql(self, value: str) -> str:
@@ -62,6 +62,7 @@ class GeneratedSql(BaseModel):
62
62
  sql: str
63
63
  confidence: float = 0.0
64
64
  assumptions: list[str] = Field(default_factory=list)
65
+ prompt_metadata: dict[str, Any] = Field(default_factory=dict)
65
66
 
66
67
 
67
68
  class QueryResult(BaseModel):
@@ -1,4 +1,6 @@
1
+ import logging
1
2
  import time
3
+ from collections.abc import Callable
2
4
  from typing import Protocol
3
5
 
4
6
  from gaard_core.execution.mock_executor import MockQueryExecutor
@@ -16,6 +18,9 @@ from gaard_core.result_interpreter.mock_interpreter import MockResultInterpreter
16
18
  from gaard_core.sql_validator.select_only import SelectOnlySqlValidator
17
19
 
18
20
 
21
+ logger = logging.getLogger(__name__)
22
+
23
+
19
24
  class SqlGenerator(Protocol):
20
25
  def generate(self, request: QueryRequest) -> GeneratedSql:
21
26
  pass
@@ -57,7 +62,11 @@ class QueryPipeline:
57
62
  self.result_interpretation_mode = result_interpretation_mode
58
63
  self.output_classification_mode = output_classification_mode
59
64
 
60
- def handle(self, request: QueryRequest) -> QueryResponse:
65
+ def handle(
66
+ self,
67
+ request: QueryRequest,
68
+ on_stage: Callable[[str], None] | None = None,
69
+ ) -> QueryResponse:
61
70
  started_at = time.perf_counter()
62
71
 
63
72
  try:
@@ -70,28 +79,49 @@ class QueryPipeline:
70
79
  error_detail=exc.message,
71
80
  ) from exc
72
81
 
82
+ logger.info(
83
+ "SQL pipeline generated query: datasource_id=%r datasource_ids=%r sql=%r "
84
+ "validator=%s executor=%s",
85
+ request.datasource_id,
86
+ request.datasource_ids,
87
+ generated_sql.sql,
88
+ type(self.sql_validator).__name__,
89
+ type(self.executor).__name__,
90
+ )
73
91
  self.sql_validator.validate(generated_sql.sql)
92
+ logger.info("SQL pipeline validation passed: sql=%r", generated_sql.sql)
74
93
 
94
+ if on_stage is not None:
95
+ on_stage("waiting_on_data_server")
75
96
  result = self.executor.execute(generated_sql.sql)
97
+ logger.info(
98
+ "SQL pipeline execution completed: sql=%r columns=%r row_count=%s",
99
+ generated_sql.sql,
100
+ result.columns,
101
+ len(result.rows),
102
+ )
76
103
  if not request.interpret:
77
104
  duration_ms = round((time.perf_counter() - started_at) * 1000, 2)
105
+ metadata = {
106
+ "duration_ms": duration_ms,
107
+ "datasource_id": request.datasource_id,
108
+ "user_id": request.user_id,
109
+ "confidence": generated_sql.confidence,
110
+ "assumptions": generated_sql.assumptions,
111
+ "sql_generation_mode": self.sql_generation_mode,
112
+ "result_interpretation_mode": "none",
113
+ "output_classification_mode": "none",
114
+ "output_classification": OutputClassification.UNKNOWN.value,
115
+ "raw_sql_output": True,
116
+ }
117
+ if generated_sql.prompt_metadata:
118
+ metadata["sql_generation_prompt_metadata"] = generated_sql.prompt_metadata
78
119
  return QueryResponse(
79
120
  question=request.question,
80
121
  answer="",
81
122
  sql=generated_sql.sql,
82
123
  rows=result.rows,
83
- metadata={
84
- "duration_ms": duration_ms,
85
- "datasource_id": request.datasource_id,
86
- "user_id": request.user_id,
87
- "confidence": generated_sql.confidence,
88
- "assumptions": generated_sql.assumptions,
89
- "sql_generation_mode": self.sql_generation_mode,
90
- "result_interpretation_mode": "none",
91
- "output_classification_mode": "none",
92
- "output_classification": OutputClassification.UNKNOWN.value,
93
- "raw_sql_output": True,
94
- },
124
+ metadata=metadata,
95
125
  )
96
126
 
97
127
  try:
@@ -135,6 +165,9 @@ class QueryPipeline:
135
165
  if classification_error:
136
166
  metadata["output_classification_error"] = classification_error
137
167
 
168
+ if generated_sql.prompt_metadata:
169
+ metadata["sql_generation_prompt_metadata"] = generated_sql.prompt_metadata
170
+
138
171
  return QueryResponse(
139
172
  question=request.question,
140
173
  answer=answer,
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gaard-core
3
- Version: 0.2.7
3
+ Version: 0.2.8
4
4
  Summary: Core GAARD query pipeline, prompt compiler, policies and SQL validation
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
- Requires-Dist: gaard-plugin-api<0.3.0,>=0.2.7
7
+ Requires-Dist: gaard-plugin-api<0.3.0,>=0.2.8
8
8
  Requires-Dist: pydantic>=2.7.0
9
9
  Requires-Dist: sqlglot>=25.0.0
10
10
  Provides-Extra: dev
@@ -1,4 +1,4 @@
1
- gaard-plugin-api<0.3.0,>=0.2.7
1
+ gaard-plugin-api<0.3.0,>=0.2.8
2
2
  pydantic>=2.7.0
3
3
  sqlglot>=25.0.0
4
4
 
File without changes
File without changes