qtype 0.0.16__py3-none-any.whl → 0.1.1__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.
Files changed (128) hide show
  1. qtype/application/commons/tools.py +1 -1
  2. qtype/application/converters/tools_from_api.py +5 -5
  3. qtype/application/converters/tools_from_module.py +2 -2
  4. qtype/application/converters/types.py +14 -43
  5. qtype/application/documentation.py +1 -1
  6. qtype/application/facade.py +94 -73
  7. qtype/base/types.py +227 -7
  8. qtype/cli.py +4 -0
  9. qtype/commands/convert.py +20 -8
  10. qtype/commands/generate.py +19 -27
  11. qtype/commands/run.py +73 -36
  12. qtype/commands/serve.py +74 -54
  13. qtype/commands/validate.py +34 -8
  14. qtype/commands/visualize.py +46 -22
  15. qtype/dsl/__init__.py +6 -5
  16. qtype/dsl/custom_types.py +1 -1
  17. qtype/dsl/domain_types.py +65 -5
  18. qtype/dsl/linker.py +384 -0
  19. qtype/dsl/loader.py +315 -0
  20. qtype/dsl/model.py +612 -363
  21. qtype/dsl/parser.py +200 -0
  22. qtype/dsl/types.py +50 -0
  23. qtype/interpreter/api.py +57 -136
  24. qtype/interpreter/auth/aws.py +19 -9
  25. qtype/interpreter/auth/generic.py +93 -16
  26. qtype/interpreter/base/base_step_executor.py +436 -0
  27. qtype/interpreter/base/batch_step_executor.py +171 -0
  28. qtype/interpreter/base/exceptions.py +50 -0
  29. qtype/interpreter/base/executor_context.py +74 -0
  30. qtype/interpreter/base/factory.py +117 -0
  31. qtype/interpreter/base/progress_tracker.py +110 -0
  32. qtype/interpreter/base/secrets.py +339 -0
  33. qtype/interpreter/base/step_cache.py +74 -0
  34. qtype/interpreter/base/stream_emitter.py +469 -0
  35. qtype/interpreter/conversions.py +462 -22
  36. qtype/interpreter/converters.py +77 -0
  37. qtype/interpreter/endpoints.py +355 -0
  38. qtype/interpreter/executors/agent_executor.py +242 -0
  39. qtype/interpreter/executors/aggregate_executor.py +93 -0
  40. qtype/interpreter/executors/decoder_executor.py +163 -0
  41. qtype/interpreter/executors/doc_to_text_executor.py +112 -0
  42. qtype/interpreter/executors/document_embedder_executor.py +107 -0
  43. qtype/interpreter/executors/document_search_executor.py +122 -0
  44. qtype/interpreter/executors/document_source_executor.py +118 -0
  45. qtype/interpreter/executors/document_splitter_executor.py +105 -0
  46. qtype/interpreter/executors/echo_executor.py +63 -0
  47. qtype/interpreter/executors/field_extractor_executor.py +160 -0
  48. qtype/interpreter/executors/file_source_executor.py +101 -0
  49. qtype/interpreter/executors/file_writer_executor.py +110 -0
  50. qtype/interpreter/executors/index_upsert_executor.py +228 -0
  51. qtype/interpreter/executors/invoke_embedding_executor.py +92 -0
  52. qtype/interpreter/executors/invoke_flow_executor.py +51 -0
  53. qtype/interpreter/executors/invoke_tool_executor.py +358 -0
  54. qtype/interpreter/executors/llm_inference_executor.py +272 -0
  55. qtype/interpreter/executors/prompt_template_executor.py +78 -0
  56. qtype/interpreter/executors/sql_source_executor.py +106 -0
  57. qtype/interpreter/executors/vector_search_executor.py +91 -0
  58. qtype/interpreter/flow.py +159 -22
  59. qtype/interpreter/metadata_api.py +115 -0
  60. qtype/interpreter/resource_cache.py +5 -4
  61. qtype/interpreter/rich_progress.py +225 -0
  62. qtype/interpreter/stream/chat/__init__.py +15 -0
  63. qtype/interpreter/stream/chat/converter.py +391 -0
  64. qtype/interpreter/{chat → stream/chat}/file_conversions.py +2 -2
  65. qtype/interpreter/stream/chat/ui_request_to_domain_type.py +140 -0
  66. qtype/interpreter/stream/chat/vercel.py +609 -0
  67. qtype/interpreter/stream/utils/__init__.py +15 -0
  68. qtype/interpreter/stream/utils/build_vercel_ai_formatter.py +74 -0
  69. qtype/interpreter/stream/utils/callback_to_stream.py +66 -0
  70. qtype/interpreter/stream/utils/create_streaming_response.py +18 -0
  71. qtype/interpreter/stream/utils/default_chat_extract_text.py +20 -0
  72. qtype/interpreter/stream/utils/error_streaming_response.py +20 -0
  73. qtype/interpreter/telemetry.py +135 -8
  74. qtype/interpreter/tools/__init__.py +5 -0
  75. qtype/interpreter/tools/function_tool_helper.py +265 -0
  76. qtype/interpreter/types.py +330 -0
  77. qtype/interpreter/typing.py +83 -89
  78. qtype/interpreter/ui/404/index.html +1 -1
  79. qtype/interpreter/ui/404.html +1 -1
  80. qtype/interpreter/ui/_next/static/{nUaw6_IwRwPqkzwe5s725 → 20HoJN6otZ_LyHLHpCPE6}/_buildManifest.js +1 -1
  81. qtype/interpreter/ui/_next/static/chunks/{393-8fd474427f8e19ce.js → 434-b2112d19f25c44ff.js} +3 -3
  82. qtype/interpreter/ui/_next/static/chunks/app/page-8c67d16ac90d23cb.js +1 -0
  83. qtype/interpreter/ui/_next/static/chunks/ba12c10f-546f2714ff8abc66.js +1 -0
  84. qtype/interpreter/ui/_next/static/css/8a8d1269e362fef7.css +3 -0
  85. qtype/interpreter/ui/icon.png +0 -0
  86. qtype/interpreter/ui/index.html +1 -1
  87. qtype/interpreter/ui/index.txt +4 -4
  88. qtype/semantic/checker.py +583 -0
  89. qtype/semantic/generate.py +262 -83
  90. qtype/semantic/loader.py +95 -0
  91. qtype/semantic/model.py +436 -159
  92. qtype/semantic/resolver.py +63 -19
  93. qtype/semantic/visualize.py +28 -31
  94. {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/METADATA +16 -3
  95. qtype-0.1.1.dist-info/RECORD +135 -0
  96. qtype/dsl/base_types.py +0 -38
  97. qtype/dsl/validator.py +0 -465
  98. qtype/interpreter/batch/__init__.py +0 -0
  99. qtype/interpreter/batch/file_sink_source.py +0 -162
  100. qtype/interpreter/batch/flow.py +0 -95
  101. qtype/interpreter/batch/sql_source.py +0 -92
  102. qtype/interpreter/batch/step.py +0 -74
  103. qtype/interpreter/batch/types.py +0 -41
  104. qtype/interpreter/batch/utils.py +0 -178
  105. qtype/interpreter/chat/chat_api.py +0 -237
  106. qtype/interpreter/chat/vercel.py +0 -314
  107. qtype/interpreter/exceptions.py +0 -10
  108. qtype/interpreter/step.py +0 -67
  109. qtype/interpreter/steps/__init__.py +0 -0
  110. qtype/interpreter/steps/agent.py +0 -114
  111. qtype/interpreter/steps/condition.py +0 -36
  112. qtype/interpreter/steps/decoder.py +0 -88
  113. qtype/interpreter/steps/llm_inference.py +0 -171
  114. qtype/interpreter/steps/prompt_template.py +0 -54
  115. qtype/interpreter/steps/search.py +0 -24
  116. qtype/interpreter/steps/tool.py +0 -219
  117. qtype/interpreter/streaming_helpers.py +0 -123
  118. qtype/interpreter/ui/_next/static/chunks/app/page-7e26b6156cfb55d3.js +0 -1
  119. qtype/interpreter/ui/_next/static/chunks/ba12c10f-22556063851a6df2.js +0 -1
  120. qtype/interpreter/ui/_next/static/css/b40532b0db09cce3.css +0 -3
  121. qtype/interpreter/ui/favicon.ico +0 -0
  122. qtype/loader.py +0 -390
  123. qtype-0.0.16.dist-info/RECORD +0 -106
  124. /qtype/interpreter/ui/_next/static/{nUaw6_IwRwPqkzwe5s725 → 20HoJN6otZ_LyHLHpCPE6}/_ssgManifest.js +0 -0
  125. {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/WHEEL +0 -0
  126. {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/entry_points.txt +0 -0
  127. {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/licenses/LICENSE +0 -0
  128. {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/top_level.txt +0 -0
@@ -1,114 +0,0 @@
1
- import asyncio
2
- import importlib
3
- import logging
4
- from typing import Any
5
-
6
- from llama_index.core.agent.workflow import ReActAgent
7
- from llama_index.core.base.llms.types import ChatMessage as LlamaChatMessage
8
- from llama_index.core.tools import AsyncBaseTool, FunctionTool
9
- from llama_index.core.workflow import Context
10
- from llama_index.core.workflow.handler import WorkflowHandler # type: ignore
11
-
12
- from qtype.dsl.domain_types import ChatMessage
13
- from qtype.interpreter.conversions import (
14
- from_chat_message,
15
- to_chat_message,
16
- to_llm,
17
- to_memory,
18
- )
19
- from qtype.interpreter.exceptions import InterpreterError
20
- from qtype.semantic.model import Agent, APITool, PythonFunctionTool, Variable
21
-
22
- logger = logging.getLogger(__name__)
23
-
24
-
25
- def to_llama_tool(tool: PythonFunctionTool) -> AsyncBaseTool:
26
- """Convert a qtype Tool to a LlamaIndex Tool."""
27
- # We want to get the function named by the tool -- get ".tools.<tool_name>"
28
- # This assumes the tool name matches a function in the .tools module
29
- module = importlib.import_module(tool.module_path)
30
- function = getattr(module, tool.function_name, None)
31
- if function is None:
32
- raise ValueError(
33
- f"Tool function '{tool.function_name}' not found in module '{tool.module_path}'."
34
- )
35
-
36
- return FunctionTool.from_defaults(
37
- fn=function, name=tool.name, description=tool.description
38
- )
39
-
40
-
41
- def execute(agent: Agent, **kwargs: dict[str, Any]) -> list[Variable]:
42
- """Execute an agent step.
43
-
44
- Args:
45
- agent: The agent step to execute.
46
- **kwargs: Additional keyword arguments.
47
- """
48
- logger.debug(f"Executing agent step: {agent.id}")
49
- if len(agent.outputs) != 1:
50
- raise InterpreterError(
51
- "LLMInference step must have exactly one output variable."
52
- )
53
- output_variable = agent.outputs[0]
54
-
55
- # prepare the input for the agent
56
- if len(agent.inputs) != 1:
57
- # TODO: Support multiple inputs by shoving it into the chat history?
58
- raise InterpreterError(
59
- "Agent step must have exactly one input variable."
60
- )
61
-
62
- input_variable = agent.inputs[0]
63
- if input_variable.type == ChatMessage:
64
- input: LlamaChatMessage | str = to_chat_message(input_variable.value) # type: ignore
65
- else:
66
- input: LlamaChatMessage | str = input_variable.value # type: ignore
67
-
68
- # Pepare the tools
69
- # TODO: support api tools
70
- if any(isinstance(tool, APITool) for tool in agent.tools):
71
- raise NotImplementedError(
72
- "APITool is not supported in the current implementation. Please use PythonFunctionTool."
73
- )
74
- tools = [
75
- to_llama_tool(tool) # type: ignore
76
- for tool in (agent.tools if agent.tools else [])
77
- ]
78
-
79
- # prep memory
80
- # Note to_memory is a cached resource so this will get existing memory if available
81
- memory = (
82
- to_memory(kwargs.get("session_id"), agent.memory)
83
- if agent.memory
84
- else None
85
- )
86
-
87
- # Run the agent
88
- async def run_agent() -> WorkflowHandler:
89
- logger.debug(
90
- f"Starting agent '{agent.id}' execution with input length: {len(str(input))} (ReAct mode)"
91
- )
92
- re_agent = ReActAgent(
93
- name=agent.id,
94
- tools=tools, # type: ignore
95
- system_prompt=agent.system_message,
96
- llm=to_llm(agent.model, agent.system_message), # type: ignore
97
- )
98
- ctx = Context(re_agent) # type: ignore
99
- # TODO: implement checkpoint_callback to call stream_fn?
100
- handler = re_agent.run(input, chat_memory=memory, ctx=ctx)
101
- result = await handler
102
- logger.debug(
103
- f"Agent '{agent.id}' execution completed successfully (ReAct mode)"
104
- )
105
- return result
106
-
107
- result = asyncio.run(run_agent())
108
-
109
- if output_variable.type == ChatMessage:
110
- output_variable.value = from_chat_message(result.response) # type: ignore
111
- else:
112
- output_variable.value = result.response.content # type: ignore
113
-
114
- return agent.outputs
@@ -1,36 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from qtype.semantic.model import Condition, Variable
6
-
7
-
8
- def execute(condition: Condition, **kwargs: dict[str, Any]) -> list[Variable]:
9
- """Execute a condition step.
10
-
11
- Args:
12
- condition: The condition step to execute.
13
-
14
- Returns:
15
- A list of variables that are set based on the condition evaluation.
16
- """
17
- from qtype.interpreter.step import execute_step
18
-
19
- if not condition.inputs:
20
- raise ValueError(
21
- "Condition step requires at least one input variable."
22
- )
23
-
24
- if len(condition.inputs) != 1:
25
- raise ValueError(
26
- f"Condition step {condition.id} must have exactly one input, found {len(condition.inputs)}."
27
- )
28
- input_var = condition.inputs[0]
29
- if condition.equals.value == input_var.value: # type: ignore
30
- # If the condition is met, return the outputs
31
- return execute_step(condition.then, **kwargs)
32
- elif condition.else_:
33
- return execute_step(condition.else_, **kwargs)
34
- else:
35
- # If no else branch is defined, return an empty list
36
- return []
@@ -1,88 +0,0 @@
1
- import json
2
- import xml.etree.ElementTree as ET
3
- from typing import Any
4
-
5
- from qtype.dsl.model import DecoderFormat
6
- from qtype.semantic.model import Decoder, Variable
7
-
8
-
9
- def parse_json(input: str) -> dict[str, Any]:
10
- """Parse a JSON string into a Python object."""
11
- try:
12
- cleaned_response = input.strip()
13
- if cleaned_response.startswith("```json"):
14
- cleaned_response = cleaned_response[7:]
15
- if cleaned_response.endswith("```"):
16
- cleaned_response = cleaned_response[:-3]
17
- cleaned_response = cleaned_response.strip()
18
-
19
- # Parse the JSON
20
- parsed = json.loads(cleaned_response)
21
- if not isinstance(parsed, dict):
22
- raise ValueError(f"Parsed JSON is not an object: {parsed}")
23
- return parsed
24
- except json.JSONDecodeError as e:
25
- raise ValueError(f"Invalid JSON input: {e}")
26
-
27
-
28
- def parse_xml(input: str) -> dict[str, Any]:
29
- """Parse an XML string into a Python object."""
30
- try:
31
- cleaned_response = input.strip()
32
- if cleaned_response.startswith("```xml"):
33
- cleaned_response = cleaned_response[6:]
34
- if cleaned_response.endswith("```"):
35
- cleaned_response = cleaned_response[:-3]
36
- cleaned_response = cleaned_response.strip()
37
-
38
- cleaned_response = cleaned_response.replace("&", "&amp;")
39
- tree = ET.fromstring(cleaned_response)
40
- result = {c.tag: c.text for c in tree}
41
-
42
- return result
43
- except Exception as e:
44
- raise ValueError(f"Invalid XML input: {e}")
45
-
46
-
47
- def parse(input: str, format: DecoderFormat) -> dict[str, Any]:
48
- if format == DecoderFormat.json:
49
- return parse_json(input)
50
- elif format == DecoderFormat.xml:
51
- return parse_xml(input)
52
- else:
53
- raise ValueError(
54
- f"Unsupported decoder format: {format}. Supported formats are: {DecoderFormat.json}, {DecoderFormat.xml}."
55
- )
56
-
57
-
58
- def execute(decoder: Decoder, **kwargs: dict[str, Any]) -> list[Variable]:
59
- """Execute a decoder step with the provided arguments.
60
-
61
- Args:
62
- decoder: The decoder step to execute.
63
- **kwargs: Additional keyword arguments.
64
- """
65
-
66
- if len(decoder.inputs) != 1:
67
- raise ValueError(
68
- f"Decoder step {decoder.id} must have exactly one input, found {len(decoder.inputs)}."
69
- )
70
-
71
- # get the string value to decode
72
- input = decoder.inputs[0].value
73
- if not isinstance(input, str):
74
- raise ValueError(
75
- f"Input to decoder step {decoder.id} must be a string, found {type(input).__name__}."
76
- )
77
-
78
- result_dict = parse(input, decoder.format)
79
-
80
- # Set the output variables with the parsed results
81
- for output in decoder.outputs:
82
- if output.id in result_dict:
83
- output.value = result_dict[output.id]
84
- else:
85
- raise ValueError(
86
- f"Output variable {output.id} not found in decoded result: {result_dict}"
87
- )
88
- return decoder.outputs # type: ignore[no-any-return]
@@ -1,171 +0,0 @@
1
- import logging
2
- from typing import Any, Callable
3
-
4
- from llama_cloud import MessageRole as LlamaMessageRole
5
- from llama_index.core.base.llms.types import ChatResponse, CompletionResponse
6
-
7
- from qtype.dsl.base_types import PrimitiveTypeEnum
8
- from qtype.dsl.domain_types import (
9
- ChatContent,
10
- ChatMessage,
11
- Embedding,
12
- MessageRole,
13
- )
14
- from qtype.interpreter.conversions import (
15
- from_chat_message,
16
- to_chat_message,
17
- to_embedding_model,
18
- to_llm,
19
- to_memory,
20
- )
21
- from qtype.interpreter.exceptions import InterpreterError
22
- from qtype.semantic.model import EmbeddingModel, LLMInference, Variable
23
-
24
- logger = logging.getLogger(__name__)
25
-
26
-
27
- def execute(
28
- li: LLMInference,
29
- stream_fn: Callable | None = None,
30
- **kwargs: dict[Any, Any],
31
- ) -> list[Variable]:
32
- """Execute a LLM inference step.
33
-
34
- Args:
35
- li: The LLM inference step to execute.
36
- stream_fn: Optional streaming callback function.
37
- **kwargs: Additional keyword arguments including conversation_history.
38
- """
39
- logger.debug(f"Executing LLM inference step: {li.id}")
40
-
41
- # Ensure we only have one output variable set.
42
- if len(li.outputs) != 1:
43
- raise InterpreterError(
44
- "LLMInference step must have exactly one output variable."
45
- )
46
- output_variable = li.outputs[0]
47
-
48
- # Determine if this is a chat session, completion, or embedding inference
49
- if output_variable.type == Embedding:
50
- if not isinstance(li.model, EmbeddingModel):
51
- raise InterpreterError(
52
- f"LLMInference step with Embedding output must use an embedding model, got {type(li.model)}"
53
- )
54
- if len(li.inputs) != 1:
55
- raise InterpreterError(
56
- "LLMInference step for completion must have exactly one input variable."
57
- )
58
-
59
- input = li.inputs[0].value
60
- model = to_embedding_model(li.model)
61
- result = model.get_text_embedding(text=input)
62
- output_variable.value = Embedding(
63
- vector=result,
64
- source_text=input if isinstance(input, str) else None,
65
- metadata=None,
66
- )
67
- elif output_variable.type == ChatMessage:
68
- model = to_llm(li.model, li.system_message)
69
- if not all(
70
- isinstance(input.value, ChatMessage) for input in li.inputs
71
- ):
72
- raise InterpreterError(
73
- f"LLMInference step with ChatMessage output must have ChatMessage inputs. Got {li.inputs}"
74
- )
75
-
76
- # Current user input
77
- inputs = [
78
- to_chat_message(input.value) # type: ignore
79
- for input in li.inputs
80
- ]
81
-
82
- # The session id is used to isolate the memory from other "users"
83
- session_id = kwargs.get("session_id")
84
-
85
- # If memory is defined, use it.
86
- if li.memory:
87
- memory = to_memory(session_id, li.memory)
88
-
89
- from llama_index.core.async_utils import asyncio_run
90
-
91
- # add the inputs to the memory
92
- asyncio_run(memory.aput_messages(inputs))
93
- # Use the whole memory state as inputs to the llm
94
- inputs = memory.get_all()
95
- else:
96
- # If memory is not defined, see if a conversation history was provided.
97
- # This is the list of messages from the front end
98
- conversation_history = kwargs.get("conversation_history", []) # type: ignore
99
- if not isinstance(conversation_history, list):
100
- raise ValueError(
101
- "Unexpected error: conversation history is not a list."
102
- )
103
- history: list[ChatMessage] = conversation_history
104
- inputs = [to_chat_message(msg) for msg in history] + inputs
105
-
106
- if li.system_message and inputs[0].role != LlamaMessageRole.SYSTEM:
107
- # There is a system prompt we should append
108
- # Note system_prompt on the llm doesn't work for chat -- is only used for predict https://github.com/run-llama/llama_index/issues/13983
109
- system_message = ChatMessage(
110
- role=MessageRole.system,
111
- blocks=[
112
- ChatContent(
113
- type=PrimitiveTypeEnum.text,
114
- content=li.system_message,
115
- )
116
- ],
117
- )
118
- inputs = [to_chat_message(system_message)] + inputs
119
-
120
- # If the stream function is set, we'll stream the results
121
- chat_result: ChatResponse
122
- if stream_fn:
123
- generator = model.stream_chat(
124
- messages=inputs,
125
- **(
126
- li.model.inference_params
127
- if li.model.inference_params
128
- else {}
129
- ),
130
- )
131
- for chat_response in generator:
132
- stream_fn(li, chat_response.delta)
133
- # Get the final result for processing
134
- chat_result = chat_response # Use the last result from streaming
135
- else:
136
- chat_result = model.chat(
137
- messages=inputs,
138
- **(
139
- li.model.inference_params
140
- if li.model.inference_params
141
- else {}
142
- ),
143
- )
144
- output_variable.value = from_chat_message(chat_result.message)
145
- if li.memory:
146
- memory.put(chat_result.message)
147
- else:
148
- model = to_llm(li.model, li.system_message)
149
-
150
- if len(li.inputs) != 1:
151
- raise InterpreterError(
152
- "LLMInference step for completion must have exactly one input variable."
153
- )
154
-
155
- input = li.inputs[0].value
156
- if not isinstance(input, str):
157
- logger.warning(
158
- f"Input to LLMInference step {li.id} is not a string, converting: {input}"
159
- )
160
- input = str(input)
161
-
162
- complete_result: CompletionResponse
163
- if stream_fn:
164
- generator = model.stream_complete(prompt=input)
165
- for complete_result in generator:
166
- stream_fn(li, complete_result.delta)
167
- else:
168
- complete_result = model.complete(prompt=input)
169
- output_variable.value = complete_result.text
170
-
171
- return li.outputs # type: ignore[return-value]
@@ -1,54 +0,0 @@
1
- import logging
2
- import string
3
- from typing import Any
4
-
5
- from qtype.interpreter.exceptions import InterpreterError
6
- from qtype.semantic.model import PromptTemplate, Variable
7
-
8
- logger = logging.getLogger(__name__)
9
-
10
-
11
- def get_format_arguments(format_string: str) -> set[str]:
12
- formatter = string.Formatter()
13
- arguments = []
14
- for literal_text, field_name, format_spec, conversion in formatter.parse(
15
- format_string
16
- ):
17
- if field_name:
18
- arguments.append(field_name)
19
- return set(arguments)
20
-
21
-
22
- def execute(step: PromptTemplate, **kwargs: dict[str, Any]) -> list[Variable]:
23
- """Execute a prompt template step.
24
-
25
- Args:
26
- step: The prompt template step to execute.
27
- **kwargs: Additional keyword arguments.
28
- """
29
-
30
- logger.debug(
31
- f"Executing prompt template step: {step.id} with kwargs: {kwargs}"
32
- )
33
-
34
- format_args = get_format_arguments(step.template)
35
- input_map = {
36
- var.id: var.value
37
- for var in step.inputs
38
- if var.is_set() and var.id in format_args
39
- }
40
- missing = format_args - input_map.keys()
41
- if missing:
42
- raise InterpreterError(
43
- f"The following fields are in the prompt template but not in the inputs: {missing}"
44
- )
45
- # Drop inputs that are not in format_args
46
- result = step.template.format(**input_map)
47
-
48
- if len(step.outputs) != 1:
49
- raise InterpreterError(
50
- f"PromptTemplate step {step.id} must have exactly one output variable."
51
- )
52
- step.outputs[0].value = result
53
-
54
- return step.outputs # type: ignore[return-value, no-any-return]
@@ -1,24 +0,0 @@
1
- import logging
2
- from typing import Any
3
-
4
- from qtype.semantic.model import Search, Variable
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
-
9
- def execute(search: Search, **kwargs: dict[str, Any]) -> list[Variable]:
10
- """Execute a search step.
11
-
12
- Args:
13
- search: The search step to execute.
14
-
15
- Returns:
16
- A list of variables that are set based on the search results.
17
- """
18
- logger.info("Executing Search on: %s", search.index.id)
19
- # TODO: implement search execution logic
20
- raise NotImplementedError(
21
- "Search execution is not yet implemented. This will be handled in a future update."
22
- )
23
-
24
- return [] # Return an empty list for now