Class: AIA::PromptDecomposer
- Inherits:
-
Object
- Object
- AIA::PromptDecomposer
- Includes:
- ContentExtractor
- Defined in:
- lib/aia/prompt_decomposer.rb
Constant Summary collapse
- DECOMPOSITION_PROMPT =
<<~PROMPT Analyze this user request and determine if it can be broken into independent sub-tasks. Rules: - Only decompose if sub-tasks are truly independent (can run in parallel) - Each sub-task should be self-contained - 2-5 sub-tasks maximum - Keep sub-task descriptions clear and specific - Use an empty subtasks array if the request cannot be meaningfully decomposed User request: %{prompt} PROMPT
- FALLBACK_JSON_INSTRUCTION =
Appended to DECOMPOSITION_PROMPT when the model does not support structured output and with_schema cannot be used.
<<~INSTRUCTION Respond with ONLY a JSON object — no explanation, no markdown, no prose: {"subtasks": ["sub-task description 1", "sub-task description 2"]} INSTRUCTION
- SUBTASKS_SCHEMA =
JSON schema for structured-output-capable models. Uses a wrapper object because Claude requires a top-level object.
{ name: 'subtask_decomposition', schema: { type: 'object', properties: { subtasks: { type: 'array', items: { type: 'string' }, description: 'Independent sub-task descriptions. Empty array if not decomposable.' } }, required: ['subtasks'], additionalProperties: false }, strict: true }.freeze
- SYNTHESIS_TEMPLATE =
<<~PROMPT Original request: %{prompt} Sub-task results: %{results} Synthesize these results into a coherent final response that fully addresses the original request. PROMPT
Instance Method Summary collapse
-
#decompose(prompt) ⇒ Array<String>
Attempt to decompose a prompt into sub-tasks.
-
#initialize(robot) ⇒ PromptDecomposer
constructor
A new instance of PromptDecomposer.
-
#synthesize(prompt, results) ⇒ Object
Synthesize sub-task results into a final response.
Methods included from ContentExtractor
#extract_content, #extract_network_content, #format_duration, #output_to_file, #present_result, #store_results_in_memory
Constructor Details
#initialize(robot) ⇒ PromptDecomposer
Returns a new instance of PromptDecomposer.
64 65 66 |
# File 'lib/aia/prompt_decomposer.rb', line 64 def initialize(robot) @robot = robot end |
Instance Method Details
#decompose(prompt) ⇒ Array<String>
Attempt to decompose a prompt into sub-tasks.
Uses a temporary probe robot so the decomposition prompt and response do not pollute the main conversation history. When the configured model supports structured output (structured_output? == true) with_schema is used to get a guaranteed Hash back. Otherwise a JSON instruction is appended to the prompt and the text response is parsed manually.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/aia/prompt_decomposer.rb', line 78 def decompose(prompt) probe = build_probe_robot use_schema = structured_output? if use_schema probe.with_schema(SUBTASKS_SCHEMA) full_prompt = DECOMPOSITION_PROMPT % { prompt: prompt } else AIA.logger.warn("PromptDecomposer: configured model does not support structured output — using JSON prompt fallback") full_prompt = (DECOMPOSITION_PROMPT + FALLBACK_JSON_INSTRUCTION) % { prompt: prompt } end result = probe.run(full_prompt, mcp: :none, tools: :none) content = extract_content(result) AIA.logger.debug("PromptDecomposer#decompose content class=#{content.class}") subtasks = extract_subtasks(content) subtasks.is_a?(Array) ? subtasks.select { |t| t.is_a?(String) && !t.empty? } : [] rescue StandardError => e AIA.logger.warn("PromptDecomposer#decompose failed: #{e.class}: #{e.}") [] end |
#synthesize(prompt, results) ⇒ Object
Synthesize sub-task results into a final response.
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/aia/prompt_decomposer.rb', line 105 def synthesize(prompt, results) formatted_results = results.each_with_index.map do |r, i| "Sub-task #{i + 1}:\n#{r}" end.join("\n\n") @robot.run( SYNTHESIS_TEMPLATE % { prompt: prompt, results: formatted_results }, mcp: :none, tools: :none ) end |