qtype 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

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.
qtype/dsl/model.py CHANGED
@@ -765,8 +765,9 @@ class AWSAuthProvider(AuthorizationProvider):
765
765
  has_keys = self.access_key_id and self.secret_access_key
766
766
  has_profile = self.profile_name
767
767
  has_role = self.role_arn
768
+ has_region = self.region
768
769
 
769
- if not (has_keys or has_profile or has_role):
770
+ if not (has_keys or has_profile or has_role or has_region):
770
771
  raise ValueError(
771
772
  "AWSAuthProvider must specify at least one authentication method: "
772
773
  "access keys, profile name, or role ARN."
qtype/dsl/parser.py CHANGED
@@ -153,12 +153,12 @@ def _format_validation_errors(
153
153
  error_msg = "Validation failed (see details above)"
154
154
  else:
155
155
  error_msg = "Validation failed:\n"
156
- for error in relevant_errors[:5]: # Show max 5 errors
156
+ for error in relevant_errors[:30]: # Show max 5 errors
157
157
  loc_path = _simplify_field_path(error["loc"])
158
158
  error_msg += f" {loc_path}: {error['msg']}\n"
159
159
 
160
- if len(relevant_errors) > 5:
161
- error_msg += f" ... and {len(relevant_errors) - 5} more errors\n"
160
+ if len(relevant_errors) > 30:
161
+ error_msg += f" ... and {len(relevant_errors) - 30} more errors\n"
162
162
 
163
163
  if source_name:
164
164
  error_msg = f"In {source_name}:\n{error_msg}"
@@ -241,7 +241,7 @@ class StepExecutor(ABC):
241
241
 
242
242
  # Track message counts for telemetry
243
243
  message_count = 0
244
- error_count = len(failed_messages)
244
+ error_count = 0
245
245
 
246
246
  # Stream results and track progress
247
247
  async with all_results.stream() as streamer:
@@ -34,6 +34,7 @@ from qtype.interpreter.base.secrets import SecretManagerBase
34
34
  from qtype.interpreter.types import InterpreterError
35
35
  from qtype.semantic.model import (
36
36
  APIKeyAuthProvider,
37
+ AWSAuthProvider,
37
38
  DocumentIndex,
38
39
  DocumentSplitter,
39
40
  Model,
@@ -302,7 +303,9 @@ def to_vector_store(
302
303
 
303
304
 
304
305
  @cached_resource
305
- def to_embedding_model(model: Model) -> BaseEmbedding:
306
+ def to_embedding_model(
307
+ model: Model, secret_manager: SecretManagerBase
308
+ ) -> BaseEmbedding:
306
309
  """Convert a qtype Model to a LlamaIndex embedding model."""
307
310
 
308
311
  if model.provider == "aws-bedrock":
@@ -310,7 +313,14 @@ def to_embedding_model(model: Model) -> BaseEmbedding:
310
313
  BedrockEmbedding,
311
314
  )
312
315
 
316
+ session = None
317
+ if model.auth is not None:
318
+ assert isinstance(model.auth, AWSAuthProvider)
319
+ with aws(model.auth, secret_manager) as session:
320
+ session = session._session
321
+
313
322
  bedrock_embedding: BaseEmbedding = BedrockEmbedding(
323
+ botocore_session=session,
314
324
  model_name=model.model_id if model.model_id else model.id,
315
325
  max_retries=100,
316
326
  )
@@ -320,8 +330,20 @@ def to_embedding_model(model: Model) -> BaseEmbedding:
320
330
  OpenAIEmbedding,
321
331
  )
322
332
 
333
+ api_key = None
334
+ if model.auth:
335
+ with auth(model.auth, secret_manager) as provider:
336
+ if not isinstance(provider, APIKeyAuthProvider):
337
+ raise InterpreterError(
338
+ f"OpenAI provider requires APIKeyAuthProvider, "
339
+ f"got {type(provider).__name__}"
340
+ )
341
+ # api_key is guaranteed to be str after auth() resolves it
342
+ api_key = provider.api_key # type: ignore[assignment]
343
+
323
344
  openai_embedding: BaseEmbedding = OpenAIEmbedding(
324
- model_name=model.model_id if model.model_id else model.id
345
+ api_key=api_key,
346
+ model_name=model.model_id if model.model_id else model.id,
325
347
  )
326
348
  return openai_embedding
327
349
  else:
@@ -566,7 +588,7 @@ def to_llama_vector_store_and_retriever(
566
588
  vector_store = to_vector_store(index, secret_manager)
567
589
 
568
590
  # Get the embedding model
569
- embedding_model = to_embedding_model(index.embedding_model)
591
+ embedding_model = to_embedding_model(index.embedding_model, secret_manager)
570
592
 
571
593
  # Create a VectorStoreIndex with the vector store and embedding model
572
594
  vector_index = VectorStoreIndex.from_vector_store(
@@ -41,7 +41,7 @@ class DocumentEmbedderExecutor(StepExecutor):
41
41
  self.step: DocumentEmbedder = step
42
42
  # Initialize the embedding model once for the executor
43
43
  self.embedding_model: BaseEmbedding = to_embedding_model(
44
- self.step.model
44
+ self.step.model, context.secret_manager
45
45
  )
46
46
 
47
47
  # TODO: properly abstract this into a mixin
@@ -71,7 +71,7 @@ class DocumentSplitterExecutor(StepExecutor):
71
71
  # Convert to LlamaIndex Document for splitting
72
72
  llama_doc = LlamaDocument(
73
73
  text=content_text,
74
- metadata=document.metadata or {},
74
+ metadata={}, # ommit metadata here as it's added back later and we don't want the chunk size checks
75
75
  doc_id=document.file_id,
76
76
  )
77
77
 
@@ -30,7 +30,9 @@ class InvokeEmbeddingExecutor(StepExecutor):
30
30
  )
31
31
  self.step: InvokeEmbedding = step
32
32
  # Initialize the embedding model once for the executor
33
- self.embedding_model = to_embedding_model(self.step.model)
33
+ self.embedding_model = to_embedding_model(
34
+ self.step.model, context.secret_manager
35
+ )
34
36
 
35
37
  async def process_message(
36
38
  self,
qtype/interpreter/flow.py CHANGED
@@ -11,9 +11,12 @@ from openinference.semconv.trace import (
11
11
  from opentelemetry import context as otel_context
12
12
  from opentelemetry import trace
13
13
  from opentelemetry.trace import Status, StatusCode
14
+ from rich.console import Console
15
+ from transformers import ProgressCallback
14
16
 
15
17
  from qtype.interpreter.base import factory
16
18
  from qtype.interpreter.base.executor_context import ExecutorContext
19
+ from qtype.interpreter.logging_progress import LoggingProgressCallback
17
20
  from qtype.interpreter.rich_progress import RichProgressCallback
18
21
  from qtype.interpreter.types import FlowMessage
19
22
  from qtype.semantic.model import Flow
@@ -42,9 +45,17 @@ async def run_flow(
42
45
  """
43
46
  from qtype.interpreter.base.secrets import NoOpSecretManager
44
47
 
48
+ # Wire up progress callback if requested
49
+ progress_callback: ProgressCallback | None = None
50
+ if show_progress:
51
+ console = Console()
52
+ if console.is_terminal:
53
+ progress_callback = RichProgressCallback()
54
+ else:
55
+ progress_callback = LoggingProgressCallback(log_every_seconds=120)
56
+
45
57
  # Extract or create ExecutorContext
46
58
  exec_context = kwargs.pop("context", None)
47
- progress_callback = RichProgressCallback() if show_progress else None
48
59
  if exec_context is None:
49
60
  exec_context = ExecutorContext(
50
61
  secret_manager=NoOpSecretManager(),
@@ -0,0 +1,61 @@
1
+ import logging
2
+ import time
3
+
4
+ from qtype.interpreter.types import ProgressCallback
5
+
6
+
7
+ class LoggingProgressCallback(ProgressCallback):
8
+ def __init__(self, log_every_seconds: float = 120.0) -> None:
9
+ super().__init__()
10
+ self.log_every_seconds = log_every_seconds
11
+ self._last_log: dict[str, float] = {}
12
+ self._totals: dict[str, int | None] = {}
13
+
14
+ def __call__(
15
+ self,
16
+ step_id: str,
17
+ items_processed: int,
18
+ items_in_error: int,
19
+ items_succeeded: int,
20
+ total_items: int | None,
21
+ cache_hits: int | None,
22
+ cache_misses: int | None,
23
+ ) -> None:
24
+ logger = logging.getLogger(__name__)
25
+ now = time.monotonic()
26
+ last = self._last_log.get(step_id, 0.0)
27
+
28
+ self._totals[step_id] = total_items
29
+
30
+ if now - last < self.log_every_seconds:
31
+ return
32
+
33
+ self._last_log[step_id] = now
34
+ total_str = (
35
+ f"{items_processed}/{total_items}"
36
+ if total_items is not None
37
+ else f"{items_processed}"
38
+ )
39
+ if cache_hits is not None or cache_misses is not None:
40
+ logger.info(
41
+ "Step %s: processed=%s, succeeded=%s, errors=%s, "
42
+ "cache_hits=%s, cache_misses=%s",
43
+ step_id,
44
+ total_str,
45
+ items_succeeded,
46
+ items_in_error,
47
+ cache_hits if cache_hits is not None else "-",
48
+ cache_misses if cache_misses is not None else "-",
49
+ )
50
+ else:
51
+ logger.info(
52
+ "Step %s: processed=%s, succeeded=%s, errors=%s",
53
+ step_id,
54
+ total_str,
55
+ items_succeeded,
56
+ items_in_error,
57
+ )
58
+
59
+ def close(self) -> None:
60
+ # optional: final summary logging
61
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qtype
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: DSL for Generative AI Prototyping
5
5
  Author-email: Lou Kratz <lou.kratz+qtype@bazaarvoice.com>
6
6
  License-Expression: Apache-2.0
@@ -25,15 +25,16 @@ qtype/dsl/custom_types.py,sha256=N3qswimv0foH40YDubHaTZ3HYF9RUbZ2x5eQ4i798Ko,290
25
25
  qtype/dsl/domain_types.py,sha256=-pX74DKwrRanoXBxYqAdN_f44ike6ssRV3tZ20R2PhQ,4319
26
26
  qtype/dsl/linker.py,sha256=c7PPTULy7_z_9u_qeseIaomR_B8kBa9YzOhQpjeGaSM,12975
27
27
  qtype/dsl/loader.py,sha256=mht0BqfmyTNHIEDaF3iTEmYQLJBP5GIZULwexxw9Dpg,9771
28
- qtype/dsl/model.py,sha256=0yKl3fKAWQ_BDH-z62oI47IiJQhaH6HFzYRD1tUZhME,40860
29
- qtype/dsl/parser.py,sha256=jpz32zyvOIo-R6Xr1lshzQiGfeo-2-fZczkdfURBufo,5487
28
+ qtype/dsl/model.py,sha256=g3cZ4-vh_WxrjJ1ev6kFfQcX2-NOZHb70ZT-7m-nHHY,40907
29
+ qtype/dsl/parser.py,sha256=Ww32bLQ2vGOObsA-vWjaMh4TOKRwEA7FAt9U6wjKZkw,5490
30
30
  qtype/dsl/types.py,sha256=k6cgThA287bZ_pvTKQvxWhatcYCPNne8zpqOYOvLvOg,1687
31
31
  qtype/interpreter/__init__.py,sha256=IaRF90JLFbsTLKz9LTOMI_Pz4xwVaEyXPNaXV7sLou8,43
32
32
  qtype/interpreter/api.py,sha256=V7hjsmDhe1IwbcwdM5bnPGBiwH3TtlMLjUJdGJumCdA,4193
33
- qtype/interpreter/conversions.py,sha256=SHtVVN8k36_iODKvHt1MV6V08GRaEBwE4yCN6VQvlHA,20986
33
+ qtype/interpreter/conversions.py,sha256=VKRJm5ofM3tWzXKg_zLTvKzi7GNBDv6MiE4HnQ52eFY,21871
34
34
  qtype/interpreter/converters.py,sha256=gWyfizl7d-DT6jJ2aOrneUcZcwB-LdMDEvl-VT0-mLQ,2348
35
35
  qtype/interpreter/endpoints.py,sha256=un4iCYCk86lYKpTDFdzlByvebdctNwRF3n4oD4ZwpTw,11946
36
- qtype/interpreter/flow.py,sha256=eitRE1Hh6avmMzjLKKcrWztviSzJHFu4yZSbtIeMLQ0,6188
36
+ qtype/interpreter/flow.py,sha256=_RuOxGG34Ccvb3pS_f2e2xmpmmMcq7CakWBdS8ezZqY,6590
37
+ qtype/interpreter/logging_progress.py,sha256=RmyNXdbpPZ7ye8cbSab0Tw10x3T38U3S8rj2bOTfbso,1848
37
38
  qtype/interpreter/metadata_api.py,sha256=LfJjt9atsgiAra6aVBXLoJrPa06_CBUagYysT556nt8,3267
38
39
  qtype/interpreter/resource_cache.py,sha256=K0kzpm223COWk7FN9qyOvNOEoOcABR4yLeADL9ekE_o,1188
39
40
  qtype/interpreter/rich_progress.py,sha256=J7TokOIqIUVWJZCfGEexQCwvvj6b1SjRtKThk2DU0CA,6761
@@ -44,7 +45,7 @@ qtype/interpreter/auth/__init__.py,sha256=L98AxaSizb6LMdXEr8FGe9MBtPBnfCeWxjI0oi
44
45
  qtype/interpreter/auth/aws.py,sha256=eMXyEBqzv7I243fS-A1zHPQkN--yPFEh1Hxp4rxmyEs,8154
45
46
  qtype/interpreter/auth/cache.py,sha256=uVyJ_jkbprRdlvbnm1DVIaYyTDLEsPXvi3xjuRneH2k,1825
46
47
  qtype/interpreter/auth/generic.py,sha256=WHXu3SxWzxJn_bv6R20Aod84Vwe73xTYHx754dY1MSg,6178
47
- qtype/interpreter/base/base_step_executor.py,sha256=DFQOwRVXStxPLov-unG4IXq-iBQ66JVPeetNnUcdlZ8,16497
48
+ qtype/interpreter/base/base_step_executor.py,sha256=HntCYGGki0xnl29AwH98DXf3i9kaeFFgr52JC9EQHGM,16478
48
49
  qtype/interpreter/base/batch_step_executor.py,sha256=g5_yPd5VTy_slW5ZXyamgFyTRd0CoaeVfDHj8x4PvUk,5906
49
50
  qtype/interpreter/base/exceptions.py,sha256=7CIexzDfIjvAA0c6qwg4jsDcTQM1pKQLj6szxcqil_c,1586
50
51
  qtype/interpreter/base/executor_context.py,sha256=qDMb7GJebCw3E6oMiCSpu0-aRq-l6MPx6yPLwM2quOs,3561
@@ -58,16 +59,16 @@ qtype/interpreter/executors/aggregate_executor.py,sha256=Z3NJekpeo7aqqvOcXQqb6d6
58
59
  qtype/interpreter/executors/bedrock_reranker_executor.py,sha256=p25BMmM1paAlK2vfpwJ9T5st_2B-bmZoDnVFp9ynZIY,7154
59
60
  qtype/interpreter/executors/decoder_executor.py,sha256=KqLhnhiclMIcUNf3bu7H4vDAOXCQeVO0rc2hIXm1qZ4,5610
60
61
  qtype/interpreter/executors/doc_to_text_executor.py,sha256=ZkTtKUL0BfNIiuj-OcYybn1f0By6ujRmd1U4VEAtJt4,3804
61
- qtype/interpreter/executors/document_embedder_executor.py,sha256=wvARlFPb2dmMdxjW8L1422a-XmcUVxEJXWf24bDR9BE,3529
62
+ qtype/interpreter/executors/document_embedder_executor.py,sha256=cvteGIQOpVC94ZZX6vB7G9Pb8GXdKgNgkHubRbcgYQQ,3553
62
63
  qtype/interpreter/executors/document_search_executor.py,sha256=ZmKAt__jC5cxZY0gSm9AgpC6n7MFavTHE01tQED3zFk,4051
63
64
  qtype/interpreter/executors/document_source_executor.py,sha256=ZpBrBaE16YeRk750TxvE08NnCIUzArjESZImESomaIo,4247
64
- qtype/interpreter/executors/document_splitter_executor.py,sha256=2mzrkkNqsPb5erDUd_VapnrykgywMXGXZnkWT1YJe_w,3815
65
+ qtype/interpreter/executors/document_splitter_executor.py,sha256=00x32yo1wGUvW88_lUahfGU94prUPGaOTk5GBUJbBJA,3882
65
66
  qtype/interpreter/executors/echo_executor.py,sha256=oQUgzQTHruT4on7wgEBOcikwOy6KP82d5zrul5QLoRU,2194
66
67
  qtype/interpreter/executors/field_extractor_executor.py,sha256=geDmT6GyvbDDJvPX1hPChAydDZ_LSHlOdskK-6ZGvbI,5796
67
68
  qtype/interpreter/executors/file_source_executor.py,sha256=OUT_zJrYN3iFMUgLECde93C4rv8PthcQsuJ--CJvEsI,3605
68
69
  qtype/interpreter/executors/file_writer_executor.py,sha256=x4BpgdXM7Xhz1tJJ5MmBIjFO4y80VC1V1ow3tox_Xrw,4099
69
70
  qtype/interpreter/executors/index_upsert_executor.py,sha256=5MxG3GX2bbjX6jhCpCdEZ0YFJOshn649cfaOT50PLCA,8518
70
- qtype/interpreter/executors/invoke_embedding_executor.py,sha256=OPvd--x8iimjODLJkRpRfQDahL8LnYaPy3A8WVB5h00,3311
71
+ qtype/interpreter/executors/invoke_embedding_executor.py,sha256=PAD982r-1zBtbDOOacwFd3K5y5-jiYTiPoCNr3VIOuw,3357
71
72
  qtype/interpreter/executors/invoke_flow_executor.py,sha256=U30cYM3F_zy1_2CD1Dde59xyZD0rDa5W46lST1hxF6s,1682
72
73
  qtype/interpreter/executors/invoke_tool_executor.py,sha256=hhbE8YTr0x5-kz_xsvdWGGzkLkVdvDoAVAF-3ZUK5as,12786
73
74
  qtype/interpreter/executors/llm_inference_executor.py,sha256=A6b_Ns_734TCn_DMhdNSqWc5qX970FryhpsX_jtEu_4,9593
@@ -128,9 +129,9 @@ qtype/semantic/loader.py,sha256=QRhTc_AJfsWSMn8ThaW60GmIGjFMN-3bBUy4pktFjz4,3041
128
129
  qtype/semantic/model.py,sha256=7yZ-Ufuo-gNJbhFXALuKZxILdhNB5zbL3a3oQQARI8g,28602
129
130
  qtype/semantic/resolver.py,sha256=bWPCSB8KJpVqN_n41U_r-qzUiT8vAMBOD3pOGmxL6TY,4618
130
131
  qtype/semantic/visualize.py,sha256=thjrZcfQuZJWrZ9EMAPhAa2kNikR5rLIJrfcD3hJ8XY,17426
131
- qtype-0.1.2.dist-info/licenses/LICENSE,sha256=1KA5EgYBSR0O6nCH2HEvk6Di53YKJ9r_VCR7G8G8qAY,11341
132
- qtype-0.1.2.dist-info/METADATA,sha256=lxoxEpkpLqsOuf7OIqjBliN6tq0YlUUXwfvty3CxGdk,5657
133
- qtype-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
134
- qtype-0.1.2.dist-info/entry_points.txt,sha256=5y4vj8RLvgl2tXSj-Hm7v5-Tn3kP4-UonjNoN-mfaQE,41
135
- qtype-0.1.2.dist-info/top_level.txt,sha256=ONroH5B0mZ51jr7NSWCK0weFwwCO7wBLmyVS1YqNU14,6
136
- qtype-0.1.2.dist-info/RECORD,,
132
+ qtype-0.1.4.dist-info/licenses/LICENSE,sha256=1KA5EgYBSR0O6nCH2HEvk6Di53YKJ9r_VCR7G8G8qAY,11341
133
+ qtype-0.1.4.dist-info/METADATA,sha256=xTA-mrWr4HvK6BOBTq6CBnuERaj_a84AdJIrywWtokU,5657
134
+ qtype-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
135
+ qtype-0.1.4.dist-info/entry_points.txt,sha256=5y4vj8RLvgl2tXSj-Hm7v5-Tn3kP4-UonjNoN-mfaQE,41
136
+ qtype-0.1.4.dist-info/top_level.txt,sha256=ONroH5B0mZ51jr7NSWCK0weFwwCO7wBLmyVS1YqNU14,6
137
+ qtype-0.1.4.dist-info/RECORD,,
File without changes