qtype 0.1.10__py3-none-any.whl → 0.1.12__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 (216) hide show
  1. docs/Concepts/mental-model-and-philosophy.md +363 -0
  2. docs/Contributing/index.md +276 -0
  3. docs/Contributing/roadmap.md +81 -0
  4. docs/Decisions/ADR-001-Chat-vs-Completion-Endpoint-Features.md +56 -0
  5. docs/Gallery/dataflow_pipelines.md +80 -0
  6. docs/Gallery/dataflow_pipelines.mermaid +45 -0
  7. docs/Gallery/research_assistant.md +98 -0
  8. docs/Gallery/research_assistant.mermaid +42 -0
  9. docs/Gallery/simple_chatbot.md +36 -0
  10. docs/Gallery/simple_chatbot.mermaid +35 -0
  11. docs/How To/Authentication/configure_aws_authentication.md +60 -0
  12. docs/How To/Authentication/use_api_key_authentication.md +40 -0
  13. docs/How To/Command Line Usage/load_multiple_inputs_from_files.md +62 -0
  14. docs/How To/Command Line Usage/pass_inputs_on_the_cli.md +52 -0
  15. docs/How To/Command Line Usage/serve_with_auto_reload.md +26 -0
  16. docs/How To/Data Processing/adjust_concurrency.md +41 -0
  17. docs/How To/Data Processing/cache_step_results.md +71 -0
  18. docs/How To/Data Processing/decode_json_xml.md +24 -0
  19. docs/How To/Data Processing/explode_collections.md +40 -0
  20. docs/How To/Data Processing/gather_results.md +68 -0
  21. docs/How To/Data Processing/read_data_from_files.md +35 -0
  22. docs/How To/Data Processing/read_sql_databases.md +47 -0
  23. docs/How To/Data Processing/write_data_to_file.md +40 -0
  24. docs/How To/Invoke Models/call_large_language_models.md +51 -0
  25. docs/How To/Invoke Models/create_embeddings.md +49 -0
  26. docs/How To/Invoke Models/reuse_prompts_with_templates.md +39 -0
  27. docs/How To/Language Features/include_qtype_yaml.md +45 -0
  28. docs/How To/Language Features/include_raw_text_from_other_files.md +47 -0
  29. docs/How To/Language Features/reference_entities_by_id.md +51 -0
  30. docs/How To/Language Features/use_environment_variables.md +47 -0
  31. docs/How To/Language Features/use_qtype_mcp.md +59 -0
  32. docs/How To/Observability & Debugging/trace_calls_with_open_telemetry.md +49 -0
  33. docs/How To/Observability & Debugging/validate_qtype_yaml.md +35 -0
  34. docs/How To/Observability & Debugging/visualize_application_architecture.md +61 -0
  35. docs/How To/Observability & Debugging/visualize_example.mermaid +35 -0
  36. docs/How To/Qtype Server/flow_as_ui.png +0 -0
  37. docs/How To/Qtype Server/serve_flows_as_apis.md +40 -0
  38. docs/How To/Qtype Server/serve_flows_as_ui.md +42 -0
  39. docs/How To/Qtype Server/use_conversational_interfaces.md +59 -0
  40. docs/How To/Qtype Server/use_variables_with_ui_hints.md +47 -0
  41. docs/How To/Tools & Integration/bind_tool_inputs_and_outputs.md +48 -0
  42. docs/How To/Tools & Integration/create_tools_from_openapi_specifications.md +89 -0
  43. docs/How To/Tools & Integration/create_tools_from_python_modules.md +90 -0
  44. docs/Reference/cli.md +338 -0
  45. docs/Reference/plugins.md +95 -0
  46. docs/Reference/semantic-validation-rules.md +179 -0
  47. docs/Tutorials/01-first-qtype-application.md +248 -0
  48. docs/Tutorials/02-conversational-chatbot.md +327 -0
  49. docs/Tutorials/03-structured-data.md +481 -0
  50. docs/Tutorials/04-tools-and-function-calling.md +483 -0
  51. docs/Tutorials/example_chat.png +0 -0
  52. docs/Tutorials/index.md +92 -0
  53. docs/components/APIKeyAuthProvider.md +7 -0
  54. docs/components/APITool.md +10 -0
  55. docs/components/AWSAuthProvider.md +13 -0
  56. docs/components/AWSSecretManager.md +5 -0
  57. docs/components/Agent.md +6 -0
  58. docs/components/Aggregate.md +8 -0
  59. docs/components/AggregateStats.md +7 -0
  60. docs/components/Application.md +22 -0
  61. docs/components/AuthorizationProvider.md +6 -0
  62. docs/components/AuthorizationProviderList.md +5 -0
  63. docs/components/BearerTokenAuthProvider.md +6 -0
  64. docs/components/BedrockReranker.md +8 -0
  65. docs/components/ChatContent.md +7 -0
  66. docs/components/ChatMessage.md +6 -0
  67. docs/components/ConstantPath.md +5 -0
  68. docs/components/CustomType.md +7 -0
  69. docs/components/Decoder.md +8 -0
  70. docs/components/DecoderFormat.md +8 -0
  71. docs/components/DocToTextConverter.md +7 -0
  72. docs/components/Document.md +7 -0
  73. docs/components/DocumentEmbedder.md +7 -0
  74. docs/components/DocumentIndex.md +7 -0
  75. docs/components/DocumentSearch.md +7 -0
  76. docs/components/DocumentSource.md +12 -0
  77. docs/components/DocumentSplitter.md +10 -0
  78. docs/components/Echo.md +8 -0
  79. docs/components/Embedding.md +7 -0
  80. docs/components/EmbeddingModel.md +6 -0
  81. docs/components/FieldExtractor.md +20 -0
  82. docs/components/FileSource.md +6 -0
  83. docs/components/FileWriter.md +7 -0
  84. docs/components/Flow.md +14 -0
  85. docs/components/FlowInterface.md +7 -0
  86. docs/components/Index.md +8 -0
  87. docs/components/IndexUpsert.md +6 -0
  88. docs/components/InvokeEmbedding.md +7 -0
  89. docs/components/InvokeFlow.md +8 -0
  90. docs/components/InvokeTool.md +8 -0
  91. docs/components/LLMInference.md +9 -0
  92. docs/components/ListType.md +5 -0
  93. docs/components/Memory.md +8 -0
  94. docs/components/MessageRole.md +14 -0
  95. docs/components/Model.md +10 -0
  96. docs/components/ModelList.md +5 -0
  97. docs/components/OAuth2AuthProvider.md +9 -0
  98. docs/components/PrimitiveTypeEnum.md +21 -0
  99. docs/components/PromptTemplate.md +7 -0
  100. docs/components/PythonFunctionTool.md +7 -0
  101. docs/components/RAGChunk.md +7 -0
  102. docs/components/RAGDocument.md +10 -0
  103. docs/components/RAGSearchResult.md +8 -0
  104. docs/components/Reranker.md +5 -0
  105. docs/components/SQLSource.md +8 -0
  106. docs/components/Search.md +7 -0
  107. docs/components/SearchResult.md +7 -0
  108. docs/components/SecretManager.md +7 -0
  109. docs/components/SecretReference.md +7 -0
  110. docs/components/Source.md +6 -0
  111. docs/components/Step.md +9 -0
  112. docs/components/TelemetrySink.md +9 -0
  113. docs/components/Tool.md +9 -0
  114. docs/components/ToolList.md +5 -0
  115. docs/components/ToolParameter.md +6 -0
  116. docs/components/TypeList.md +5 -0
  117. docs/components/Variable.md +6 -0
  118. docs/components/VariableList.md +5 -0
  119. docs/components/VectorIndex.md +7 -0
  120. docs/components/VectorSearch.md +6 -0
  121. docs/components/VertexAuthProvider.md +9 -0
  122. docs/components/Writer.md +5 -0
  123. docs/example_ui.png +0 -0
  124. docs/index.md +81 -0
  125. docs/legacy_how_tos/Configuration/modular-yaml.md +366 -0
  126. docs/legacy_how_tos/Configuration/phoenix_projects.png +0 -0
  127. docs/legacy_how_tos/Configuration/phoenix_traces.png +0 -0
  128. docs/legacy_how_tos/Configuration/reference-by-id.md +251 -0
  129. docs/legacy_how_tos/Configuration/telemetry-setup.md +259 -0
  130. docs/legacy_how_tos/Data Types/custom-types.md +52 -0
  131. docs/legacy_how_tos/Data Types/domain-types.md +113 -0
  132. docs/legacy_how_tos/Debugging/visualize-apps.md +147 -0
  133. docs/legacy_how_tos/Tools/api-tools.md +29 -0
  134. docs/legacy_how_tos/Tools/python-tools.md +299 -0
  135. examples/authentication/aws_authentication.qtype.yaml +63 -0
  136. examples/conversational_ai/hello_world_chat.qtype.yaml +43 -0
  137. examples/conversational_ai/simple_chatbot.qtype.yaml +40 -0
  138. examples/data_processing/batch_processing.qtype.yaml +54 -0
  139. examples/data_processing/cache_step_results.qtype.yaml +78 -0
  140. examples/data_processing/collect_results.qtype.yaml +55 -0
  141. examples/data_processing/dataflow_pipelines.qtype.yaml +108 -0
  142. examples/data_processing/decode_json.qtype.yaml +23 -0
  143. examples/data_processing/explode_items.qtype.yaml +25 -0
  144. examples/data_processing/read_file.qtype.yaml +60 -0
  145. examples/invoke_models/create_embeddings.qtype.yaml +28 -0
  146. examples/invoke_models/simple_llm_call.qtype.yaml +32 -0
  147. examples/language_features/include_raw.qtype.yaml +27 -0
  148. examples/language_features/ui_hints.qtype.yaml +52 -0
  149. examples/legacy/bedrock/data_analysis_with_telemetry.qtype.yaml +169 -0
  150. examples/legacy/bedrock/hello_world.qtype.yaml +39 -0
  151. examples/legacy/bedrock/hello_world_chat.qtype.yaml +37 -0
  152. examples/legacy/bedrock/hello_world_chat_with_telemetry.qtype.yaml +40 -0
  153. examples/legacy/bedrock/hello_world_chat_with_thinking.qtype.yaml +40 -0
  154. examples/legacy/bedrock/hello_world_completion.qtype.yaml +41 -0
  155. examples/legacy/bedrock/hello_world_completion_with_auth.qtype.yaml +44 -0
  156. examples/legacy/bedrock/simple_agent_chat.qtype.yaml +46 -0
  157. examples/legacy/chat_with_langfuse.qtype.yaml +50 -0
  158. examples/legacy/data_processor.qtype.yaml +48 -0
  159. examples/legacy/echo/debug_example.qtype.yaml +59 -0
  160. examples/legacy/echo/prompt.qtype.yaml +22 -0
  161. examples/legacy/echo/test.qtype.yaml +26 -0
  162. examples/legacy/echo/video.qtype.yaml +20 -0
  163. examples/legacy/field_extractor_example.qtype.yaml +137 -0
  164. examples/legacy/multi_flow_example.qtype.yaml +125 -0
  165. examples/legacy/openai/hello_world_chat.qtype.yaml +43 -0
  166. examples/legacy/openai/hello_world_chat_with_telemetry.qtype.yaml +46 -0
  167. examples/legacy/rag.qtype.yaml +207 -0
  168. examples/legacy/time_utilities.qtype.yaml +64 -0
  169. examples/legacy/vertex/hello_world_chat.qtype.yaml +36 -0
  170. examples/legacy/vertex/hello_world_completion.qtype.yaml +40 -0
  171. examples/legacy/vertex/hello_world_completion_with_auth.qtype.yaml +45 -0
  172. examples/observability_debugging/trace_with_opentelemetry.qtype.yaml +40 -0
  173. examples/research_assistant/research_assistant.qtype.yaml +94 -0
  174. examples/research_assistant/tavily.oas.yaml +722 -0
  175. examples/research_assistant/tavily.qtype.yaml +289 -0
  176. examples/tutorials/01_hello_world.qtype.yaml +48 -0
  177. examples/tutorials/02_conversational_chat.qtype.yaml +37 -0
  178. examples/tutorials/03_structured_data.qtype.yaml +130 -0
  179. examples/tutorials/04_tools_and_function_calling.qtype.yaml +89 -0
  180. qtype/application/converters/tools_from_api.py +39 -35
  181. qtype/base/types.py +6 -1
  182. qtype/commands/convert.py +3 -6
  183. qtype/commands/generate.py +7 -3
  184. qtype/commands/mcp.py +68 -0
  185. qtype/commands/validate.py +4 -4
  186. qtype/dsl/custom_types.py +2 -1
  187. qtype/dsl/linker.py +15 -7
  188. qtype/dsl/loader.py +3 -3
  189. qtype/dsl/model.py +24 -3
  190. qtype/interpreter/api.py +4 -1
  191. qtype/interpreter/base/base_step_executor.py +3 -1
  192. qtype/interpreter/conversions.py +7 -3
  193. qtype/interpreter/executors/construct_executor.py +1 -1
  194. qtype/interpreter/executors/document_splitter_executor.py +4 -1
  195. qtype/interpreter/executors/file_source_executor.py +3 -3
  196. qtype/interpreter/executors/file_writer_executor.py +4 -4
  197. qtype/interpreter/executors/index_upsert_executor.py +1 -1
  198. qtype/interpreter/executors/sql_source_executor.py +1 -1
  199. qtype/interpreter/resource_cache.py +3 -1
  200. qtype/interpreter/rich_progress.py +6 -3
  201. qtype/interpreter/stream/chat/converter.py +25 -17
  202. qtype/interpreter/stream/chat/ui_request_to_domain_type.py +2 -2
  203. qtype/interpreter/typing.py +5 -7
  204. qtype/mcp/__init__.py +0 -0
  205. qtype/mcp/server.py +467 -0
  206. qtype/semantic/checker.py +1 -1
  207. qtype/semantic/generate.py +3 -3
  208. qtype/semantic/visualize.py +38 -51
  209. {qtype-0.1.10.dist-info → qtype-0.1.12.dist-info}/METADATA +21 -1
  210. qtype-0.1.12.dist-info/RECORD +325 -0
  211. {qtype-0.1.10.dist-info → qtype-0.1.12.dist-info}/WHEEL +1 -1
  212. schema/qtype.schema.json +4018 -0
  213. qtype-0.1.10.dist-info/RECORD +0 -142
  214. {qtype-0.1.10.dist-info → qtype-0.1.12.dist-info}/entry_points.txt +0 -0
  215. {qtype-0.1.10.dist-info → qtype-0.1.12.dist-info}/licenses/LICENSE +0 -0
  216. {qtype-0.1.10.dist-info → qtype-0.1.12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,289 @@
1
+ auths:
2
+ - id: tavily-api_bearerauth_token
3
+ token: ${TAVILY-API_BEARER}
4
+ type: bearer_token
5
+ description: Tools created from API specification tavily.oas.yaml
6
+ flows: []
7
+ id: tavily-api
8
+ indexes: []
9
+ memories: []
10
+ models: []
11
+ references: []
12
+ tools:
13
+ - auth: tavily-api_bearerauth_token
14
+ description: 'Perform a web search with various filtering and customization options.
15
+ Returns search results with content, URLs, scores, and optional answers. '
16
+ endpoint: https://api.tavily.com/search
17
+ headers: {}
18
+ id: search
19
+ inputs:
20
+ auto_parameters:
21
+ optional: true
22
+ type: boolean
23
+ country:
24
+ optional: true
25
+ type: text
26
+ days:
27
+ optional: true
28
+ type: int
29
+ end_date:
30
+ optional: true
31
+ type: text
32
+ exclude_domains:
33
+ optional: true
34
+ type:
35
+ element_type: text
36
+ include_answer:
37
+ optional: true
38
+ type: text
39
+ include_domains:
40
+ optional: true
41
+ type:
42
+ element_type: text
43
+ include_favicon:
44
+ optional: true
45
+ type: boolean
46
+ include_images:
47
+ optional: true
48
+ type: boolean
49
+ include_raw_content:
50
+ optional: true
51
+ type: text
52
+ max_results:
53
+ optional: true
54
+ type: int
55
+ query:
56
+ optional: false
57
+ type: text
58
+ search_depth:
59
+ optional: true
60
+ type: text
61
+ start_date:
62
+ optional: true
63
+ type: text
64
+ time_range:
65
+ optional: true
66
+ type: text
67
+ topic:
68
+ optional: true
69
+ type: text
70
+ method: POST
71
+ name: Search the web
72
+ outputs:
73
+ answer:
74
+ optional: true
75
+ type: text
76
+ follow_up_questions:
77
+ optional: true
78
+ type:
79
+ element_type: text
80
+ images:
81
+ optional: true
82
+ type:
83
+ element_type: schema_4844015520
84
+ query:
85
+ optional: true
86
+ type: text
87
+ response_time:
88
+ optional: true
89
+ type: float
90
+ results:
91
+ optional: true
92
+ type:
93
+ element_type: schema_4844016144
94
+ parameters: {}
95
+ type: APITool
96
+ - auth: tavily-api_bearerauth_token
97
+ description: 'Extract and process content from one or more URLs with various formatting
98
+ options. Returns extracted content in text or markdown format. '
99
+ endpoint: https://api.tavily.com/extract
100
+ headers: {}
101
+ id: extract
102
+ inputs:
103
+ extract_depth:
104
+ optional: true
105
+ type: text
106
+ format:
107
+ optional: true
108
+ type: text
109
+ include_favicon:
110
+ optional: true
111
+ type: boolean
112
+ include_images:
113
+ optional: true
114
+ type: boolean
115
+ urls:
116
+ optional: false
117
+ type:
118
+ element_type: text
119
+ method: POST
120
+ name: Extract content from URLs
121
+ outputs:
122
+ failed_results:
123
+ optional: true
124
+ type:
125
+ element_type: schema_4844027472
126
+ results:
127
+ optional: true
128
+ type:
129
+ element_type: schema_4844024880
130
+ parameters: {}
131
+ type: APITool
132
+ - auth: tavily-api_bearerauth_token
133
+ description: 'Crawl a website starting from a given URL with depth and breadth controls.
134
+ Extract content from discovered pages with various filtering options. '
135
+ endpoint: https://api.tavily.com/crawl
136
+ headers: {}
137
+ id: crawl
138
+ inputs:
139
+ allow_external:
140
+ optional: true
141
+ type: boolean
142
+ exclude_domains:
143
+ optional: true
144
+ type:
145
+ element_type: text
146
+ exclude_paths:
147
+ optional: true
148
+ type:
149
+ element_type: text
150
+ extract_depth:
151
+ optional: true
152
+ type: text
153
+ format:
154
+ optional: true
155
+ type: text
156
+ include_favicon:
157
+ optional: true
158
+ type: boolean
159
+ include_images:
160
+ optional: true
161
+ type: boolean
162
+ instructions:
163
+ optional: true
164
+ type: text
165
+ limit:
166
+ optional: true
167
+ type: int
168
+ max_breadth:
169
+ optional: true
170
+ type: int
171
+ max_depth:
172
+ optional: true
173
+ type: int
174
+ select_domains:
175
+ optional: true
176
+ type:
177
+ element_type: text
178
+ select_paths:
179
+ optional: true
180
+ type:
181
+ element_type: text
182
+ url:
183
+ optional: false
184
+ type: text
185
+ method: POST
186
+ name: Crawl websites
187
+ outputs:
188
+ results:
189
+ optional: true
190
+ type:
191
+ element_type: schema_4844408352
192
+ parameters: {}
193
+ type: APITool
194
+ - auth: tavily-api_bearerauth_token
195
+ description: "Map the structure and links of a website starting from a given URL.
196
+ Discover the website's architecture and page hierarchy. "
197
+ endpoint: https://api.tavily.com/map
198
+ headers: {}
199
+ id: map
200
+ inputs:
201
+ allow_external:
202
+ optional: true
203
+ type: boolean
204
+ exclude_domains:
205
+ optional: true
206
+ type:
207
+ element_type: text
208
+ exclude_paths:
209
+ optional: true
210
+ type:
211
+ element_type: text
212
+ include_images:
213
+ optional: true
214
+ type: boolean
215
+ instructions:
216
+ optional: true
217
+ type: text
218
+ limit:
219
+ optional: true
220
+ type: int
221
+ max_breadth:
222
+ optional: true
223
+ type: int
224
+ max_depth:
225
+ optional: true
226
+ type: int
227
+ select_domains:
228
+ optional: true
229
+ type:
230
+ element_type: text
231
+ select_paths:
232
+ optional: true
233
+ type:
234
+ element_type: text
235
+ url:
236
+ optional: false
237
+ type: text
238
+ method: POST
239
+ name: Map website structure
240
+ outputs:
241
+ results:
242
+ optional: true
243
+ type:
244
+ element_type: schema_4844415936
245
+ parameters: {}
246
+ type: APITool
247
+ types:
248
+ - description: Generated from OpenAPI schema
249
+ id: schema_4844015520
250
+ properties:
251
+ alt_text: text?
252
+ title: text?
253
+ url: text?
254
+ - description: Generated from OpenAPI schema
255
+ id: schema_4844016144
256
+ properties:
257
+ content: text?
258
+ favicon: text?
259
+ raw_content: text?
260
+ score: float?
261
+ title: text?
262
+ url: text?
263
+ - description: Generated from OpenAPI schema
264
+ id: schema_4844024880
265
+ properties:
266
+ content: text?
267
+ favicon: text?
268
+ title: text?
269
+ url: text?
270
+ - description: Generated from OpenAPI schema
271
+ id: schema_4844027472
272
+ properties:
273
+ error: text?
274
+ url: text?
275
+ - description: Generated from OpenAPI schema
276
+ id: schema_4844408352
277
+ properties:
278
+ content: text?
279
+ favicon: text?
280
+ links: list[text]?
281
+ title: text?
282
+ url: text?
283
+ - description: Generated from OpenAPI schema
284
+ id: schema_4844415936
285
+ properties:
286
+ depth: int?
287
+ links: list[text]?
288
+ title: text?
289
+ url: text?
@@ -0,0 +1,48 @@
1
+ id: 01_hello_world
2
+ description: My first QType application
3
+
4
+ auths:
5
+ - type: api_key
6
+ id: openai_auth
7
+ api_key: ${OPENAI_KEY}
8
+ host: https://api.openai.com
9
+
10
+ models:
11
+ - type: Model
12
+ id: gpt-4
13
+ provider: openai
14
+ model_id: gpt-4-turbo
15
+ auth: openai_auth
16
+ inference_params:
17
+ temperature: 0.7
18
+
19
+ flows:
20
+ - type: Flow
21
+ id: simple_example
22
+ variables:
23
+ - id: question
24
+ type: text
25
+ - id: formatted_prompt
26
+ type: text
27
+ - id: answer
28
+ type: text
29
+ inputs:
30
+ - question
31
+ outputs:
32
+ - answer
33
+ steps:
34
+ - id: format_prompt
35
+ type: PromptTemplate
36
+ template: "You are a helpful assistant. Answer the following question:\n{question}\n"
37
+ inputs:
38
+ - question
39
+ outputs:
40
+ - formatted_prompt
41
+
42
+ - id: llm_step
43
+ type: LLMInference
44
+ model: gpt-4
45
+ inputs:
46
+ - formatted_prompt
47
+ outputs:
48
+ - answer
@@ -0,0 +1,37 @@
1
+ id: 02_conversational_chat
2
+ description: A simple stateful chat flow with AWS Bedrock
3
+ models:
4
+ - type: Model
5
+ id: nova_lite
6
+ provider: aws-bedrock
7
+ model_id: amazon.nova-lite-v1:0
8
+ inference_params:
9
+ temperature: 0.7
10
+ max_tokens: 512
11
+ memories:
12
+ - id: chat_memory
13
+ token_limit: 10000
14
+ flows:
15
+ - type: Flow
16
+ id: simple_chat_example
17
+ interface:
18
+ type: Conversational
19
+ variables:
20
+ - id: user_message
21
+ type: ChatMessage
22
+ - id: response_message
23
+ type: ChatMessage
24
+ inputs:
25
+ - user_message
26
+ outputs:
27
+ - response_message
28
+ steps:
29
+ - id: llm_inference_step
30
+ type: LLMInference
31
+ model: nova_lite
32
+ system_message: "You are a helpful assistant."
33
+ memory: chat_memory
34
+ inputs:
35
+ - user_message
36
+ outputs:
37
+ - response_message
@@ -0,0 +1,130 @@
1
+ # Tutorial 3: Working with Types and Structured Data
2
+ #
3
+ # This tutorial demonstrates how to:
4
+ # 1. Define a CustomType for your domain
5
+ # 2. Extract fields from structured data using JSONPath (FieldExtractor)
6
+ # 3. Parse LLM output into structured format (Decoder)
7
+ # 4. Construct typed objects from extracted data (Construct)
8
+ #
9
+ # Scenario: Analyze a product review to extract structured sentiment
10
+ #
11
+ # Run with:
12
+ # uv run run -i '{"review_text":"These headphones are amazing! Great sound quality and super comfortable. Battery lasts all day."}' examples/tutorials/03_structured_data.qtype.yaml
13
+
14
+ id: review_sentiment_analyzer
15
+ description: |
16
+ Analyzes a product review to extract structured sentiment insights.
17
+ Demonstrates custom types and structured data extraction.
18
+
19
+ # Define a custom type for sentiment analysis
20
+ types:
21
+ - id: ReviewSentiment
22
+ description: Structured sentiment analysis of a review
23
+ properties:
24
+ sentiment: text
25
+ confidence: float
26
+ key_points: list[text]
27
+ rating: int
28
+
29
+ models:
30
+ - type: Model
31
+ id: analyzer_model
32
+ provider: aws-bedrock
33
+ model_id: amazon.nova-lite-v1:0
34
+ inference_params:
35
+ temperature: 0.7
36
+ max_tokens: 512
37
+
38
+ flows:
39
+ - id: analyze_review
40
+ description: Analyzes a single review and extracts structured sentiment
41
+ inputs:
42
+ - review_text
43
+ outputs:
44
+ - result
45
+
46
+ variables:
47
+ - id: review_text
48
+ type: text
49
+ - id: raw_llm_response
50
+ type: text
51
+ - id: llm_response
52
+ type: text
53
+ - id: sentiment
54
+ type: text
55
+ - id: confidence
56
+ type: float
57
+ - id: key_points
58
+ type: list[text]
59
+ - id: rating
60
+ type: int
61
+ - id: result
62
+ type: ReviewSentiment
63
+
64
+ steps:
65
+ # Step 1: Create analysis prompt
66
+ - id: analysis_prompt
67
+ type: PromptTemplate
68
+ template: |
69
+ Analyze this product review and extract structured information.
70
+
71
+ Review: {{review_text}}
72
+
73
+ Respond with ONLY valid JSON, no other text or markdown. Use this exact structure:
74
+ {{
75
+ "sentiment": "positive|negative|neutral|mixed",
76
+ "confidence": 0.95,
77
+ "key_points": ["point 1", "point 2"],
78
+ "rating": 4
79
+ }}
80
+
81
+ Where:
82
+ - sentiment: overall sentiment (positive/negative/neutral/mixed)
83
+ - confidence: your confidence score (0.0-1.0)
84
+ - key_points: 2-3 main points from the review
85
+ - rating: estimated star rating 1-5 based on the tone
86
+
87
+ Return ONLY the JSON object, nothing else.
88
+ inputs:
89
+ - review_text
90
+ outputs:
91
+ - raw_llm_response
92
+
93
+ # Step 2: Run LLM inference
94
+ - id: analyze
95
+ type: LLMInference
96
+ model: analyzer_model
97
+ inputs:
98
+ - raw_llm_response
99
+ outputs:
100
+ - llm_response
101
+
102
+ # Step 3: Parse the JSON response and build the ReviewSentiment object
103
+ # Decoder converts the JSON string into structured data
104
+ - id: parse_and_build
105
+ type: Decoder
106
+ format: json
107
+ inputs:
108
+ - llm_response
109
+ outputs:
110
+ - sentiment
111
+ - confidence
112
+ - key_points
113
+ - rating
114
+
115
+ # Step 4: Construct a ReviewSentiment object
116
+ # Construct builds typed objects from the decoded fields
117
+ - id: build_result
118
+ type: Construct
119
+ field_mapping:
120
+ sentiment: sentiment
121
+ confidence: confidence
122
+ key_points: key_points
123
+ rating: rating
124
+ inputs:
125
+ - sentiment
126
+ - confidence
127
+ - key_points
128
+ - rating
129
+ outputs:
130
+ - result
@@ -0,0 +1,89 @@
1
+ # Tutorial 4: Adding Tools to Your Application
2
+ #
3
+ # This tutorial demonstrates how to:
4
+ # 1. Import pre-built tools from the commons library
5
+ # 2. Use InvokeTool to call Python functions
6
+ # 3. Chain multiple tools together with input/output bindings
7
+ #
8
+ # Scenario: Calculate a deadline by adding days to the current time
9
+ #
10
+ # Run with:
11
+ # uv run qtype run -i '{"days_until_due": 3}' examples/tutorials/04_tools_and_function_calling.qtype.yaml
12
+
13
+ id: deadline_calculator
14
+ description: |
15
+ Calculates a deadline by adding days to the current timestamp.
16
+ Demonstrates tool imports, InvokeTool step, and tool chaining.
17
+
18
+ # Import pre-built tools from the commons library
19
+ references:
20
+ - !include https://raw.githubusercontent.com/bazaarvoice/qtype/refs/tags/v0.1.11/common/tools.qtype.yaml
21
+
22
+ flows:
23
+ - id: calculate_deadline
24
+ description: Calculate a formatted deadline from current time plus days
25
+ inputs:
26
+ - days_until_due
27
+ outputs:
28
+ - deadline_formatted
29
+
30
+ variables:
31
+ # Input
32
+ - id: days_until_due
33
+ type: int
34
+
35
+ # Tool outputs
36
+ - id: current_time
37
+ type: datetime
38
+ - id: deadline_time
39
+ type: datetime
40
+ - id: format_string
41
+ type: text
42
+ - id: deadline_formatted
43
+ type: text
44
+
45
+ steps:
46
+ # Step 1: Get current timestamp using a tool
47
+ # This tool takes no inputs and returns the current UTC time
48
+ - id: get_current_time
49
+ type: InvokeTool
50
+ tool: qtype.application.commons.tools.get_current_timestamp
51
+ input_bindings: {}
52
+ output_bindings:
53
+ result: current_time
54
+ outputs:
55
+ - current_time
56
+
57
+ # Step 2: Create a format string constant
58
+ - id: create_format_string
59
+ type: PromptTemplate
60
+ template: "%B %d, %Y at %I:%M %p UTC"
61
+ inputs: []
62
+ outputs:
63
+ - format_string
64
+
65
+ # Step 3: Calculate deadline by adding days to current time
66
+ # input_bindings maps flow variables to tool parameters
67
+ - id: add_days
68
+ type: InvokeTool
69
+ tool: qtype.application.commons.tools.timedelta
70
+ input_bindings:
71
+ timestamp: current_time
72
+ days: days_until_due
73
+ output_bindings:
74
+ result: deadline_time
75
+ outputs:
76
+ - deadline_time
77
+
78
+ # Step 4: Format deadline for human readability
79
+ # Shows chaining: output from previous tool becomes input to this one
80
+ - id: format_deadline
81
+ type: InvokeTool
82
+ tool: qtype.application.commons.tools.format_datetime
83
+ input_bindings:
84
+ timestamp: deadline_time
85
+ format_string: format_string
86
+ output_bindings:
87
+ result: deadline_formatted
88
+ outputs:
89
+ - deadline_formatted
@@ -86,47 +86,53 @@ def _create_custom_type_from_schema(
86
86
  schema_name_map: dict[int, str],
87
87
  ) -> CustomType:
88
88
  """Create a CustomType from an Object schema."""
89
- # Generate a unique ID for this schema-based type
90
- type_id = None
89
+ # Use object id instead of hash(str()) to avoid recursion with circular refs
90
+ schema_id = id(schema)
91
+
92
+ # Check if we already have this type (prevents circular reference issues)
93
+ if schema_id in schema_name_map:
94
+ type_id = schema_name_map[schema_id]
95
+ if type_id in existing_custom_types:
96
+ return existing_custom_types[type_id]
91
97
 
92
- schema_hash = hash(str(schema))
93
- if schema_hash in schema_name_map:
94
- type_id = schema_name_map[schema_hash]
98
+ # Generate a unique ID for this schema-based type
99
+ if schema.title:
100
+ # Use title if available, make it lowercase, alphanumeric, snake_case
101
+ base_id = schema.title.lower().replace(" ", "_").replace("-", "_")
102
+ # Remove non-alphanumeric characters except underscores
103
+ type_id = "schema_" + "".join(
104
+ c for c in base_id if c.isalnum() or c == "_"
105
+ )
95
106
  else:
96
- # make a type id manually
97
- if schema.title:
98
- # Use title if available, make it lowercase, alphanumeric, snake_case
99
- base_id = schema.title.lower().replace(" ", "_").replace("-", "_")
100
- # Remove non-alphanumeric characters except underscores
101
- type_id = "schema_" + "".join(
102
- c for c in base_id if c.isalnum() or c == "_"
103
- )
104
- else:
105
- # Fallback to hash if no title
106
- type_id = f"schema_{hash(str(schema))}"
107
+ # Fallback to object id if no title
108
+ type_id = f"schema_{schema_id}"
107
109
 
108
- # Check if we already have this type
110
+ # Check again with the generated type_id
109
111
  if type_id in existing_custom_types:
110
112
  return existing_custom_types[type_id]
111
113
 
112
- # Create properties from the schema
113
- properties = _schema_to_qtype_properties(
114
- schema, existing_custom_types, schema_name_map
115
- )
116
-
117
- # Create the custom type
118
- custom_type = CustomType(
114
+ # Create a placeholder to prevent infinite recursion
115
+ # This will be updated with properties below
116
+ placeholder = CustomType(
119
117
  id=type_id,
120
118
  description=schema.description
121
119
  or schema.title
122
120
  or "Generated from OpenAPI schema",
123
- properties=properties,
121
+ properties={}, # Empty initially
124
122
  )
125
123
 
126
- # Store it in the registry to prevent infinite recursion
127
- existing_custom_types[type_id] = custom_type
124
+ # Store it BEFORE processing properties to break circular references
125
+ existing_custom_types[type_id] = placeholder
128
126
 
129
- return custom_type
127
+ # Now process properties (which may reference back to this type)
128
+ properties = _schema_to_qtype_properties(
129
+ schema, existing_custom_types, schema_name_map
130
+ )
131
+
132
+ # Update the placeholder with actual properties
133
+ placeholder.properties = properties
134
+
135
+ return placeholder
130
136
 
131
137
 
132
138
  def _schema_to_qtype_type(
@@ -353,9 +359,6 @@ def to_api_tool(
353
359
  def to_authorization_provider(
354
360
  api_name: str, scheme_name: str, security: Security
355
361
  ) -> AuthProviderType:
356
- if security.scheme is None:
357
- raise ValueError("Security scheme is missing")
358
-
359
362
  match security.type:
360
363
  case SecurityType.API_KEY:
361
364
  return APIKeyAuthProvider(
@@ -364,6 +367,8 @@ def to_authorization_provider(
364
367
  host=None, # Will be set from base URL if available
365
368
  )
366
369
  case SecurityType.HTTP:
370
+ if security.scheme is None:
371
+ raise ValueError("HTTP security scheme is missing")
367
372
  if security.scheme == AuthenticationScheme.BEARER:
368
373
  return BearerTokenAuthProvider(
369
374
  id=f"{api_name}_{scheme_name}_{security.bearer_format or 'token'}",
@@ -452,11 +457,10 @@ def tools_from_api(
452
457
  existing_custom_types: dict[str, CustomType] = {}
453
458
  tools = []
454
459
 
455
- # Create a mapping from schema hash to their names in the OpenAPI spec
456
- # Note: We can't monkey-patch here since the openapi_parser duplicates instances in memory
457
- # if they are $ref'd in the content
460
+ # Create a mapping from schema id to their names in the OpenAPI spec
461
+ # Use id() instead of hash(str()) to avoid infinite recursion with circular refs
458
462
  schema_name_map: dict[int, str] = {
459
- hash(str(schema)): name.replace(" ", "-").replace("_", "-")
463
+ id(schema): name.replace(" ", "-").replace("_", "-")
460
464
  for name, schema in specification.schemas.items()
461
465
  }
462
466