Module: Legion::Extensions::Llm::Responses::ThinkingExtractor
- Defined in:
- lib/legion/extensions/llm/responses/thinking_extractor.rb
Overview
Separates provider thinking markup from caller-visible text.
Defined Under Namespace
Classes: Extraction
Constant Summary collapse
- THINK_TAG_PAIRS =
[ ['<thinking>', '</thinking>'], ['<think>', '</think>'] ].freeze
- UNTAGGED_PREAMBLE_MAX_LENGTH =
4_000- UNTAGGED_PREAMBLE_STARTS =
[ 'the user', 'the request', 'the prompt', 'the question', 'i need', 'i should', 'i will', "i'll", 'i can', 'we need', 'we should', 'we will', "we'll", 'we can', 'let me' ].freeze
- UNTAGGED_PREAMBLE_PATTERNS =
[ / \AThe\s+(?:user|request|prompt|question)\b.*\b (?:let\s+me|i'll|i\s+will|i\s+should|i\s+need|i\s+can|respond|answer|reply)\b /imx, / \A(?:I|We)\s+(?:need|should|will|can)\s+(?:to\s+)? (?:answer|respond|reply|confirm|provide|explain|help)\b /imx, /\ALet me\s+(?:answer|respond|reply|confirm|provide|explain|help)\b/im ].freeze
- THINKING_METADATA_KEYS =
%i[ reasoning_content reasoning thinking thinking_text thinking_signature reasoning_signature thought_signature ].freeze
- RAW_METADATA_KEYS =
%i[ raw raw_response response_body provider_body provider_response ].freeze
Class Method Summary collapse
- .extract(content, metadata: {}) ⇒ Object
- .extract_untagged_preamble(content) ⇒ Object
- .untagged_reasoning_preamble_candidate?(content) ⇒ Boolean
Class Method Details
.extract(content, metadata: {}) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/legion/extensions/llm/responses/thinking_extractor.rb', line 53 def extract(content, metadata: {}) = () content, extracted_thinking = extract_from_content(content) = () = () Extraction.new( content: content, thinking: compact_thinking([, extracted_thinking]), signature: , metadata: () ) end |
.extract_untagged_preamble(content) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/legion/extensions/llm/responses/thinking_extractor.rb', line 82 def extract_untagged_preamble(content) return [content, nil] unless content.is_a?(String) match = content.match(/\A(?<preamble>.+?)\n{2,}(?<visible>.+)\z/m) return [content, nil] unless match preamble = match[:preamble].strip return [content, nil] unless untagged_reasoning_preamble?(preamble) [match[:visible].sub(/\A[[:space:]]+/, '').strip, preamble] end |
.untagged_reasoning_preamble_candidate?(content) ⇒ Boolean
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/legion/extensions/llm/responses/thinking_extractor.rb', line 94 def untagged_reasoning_preamble_candidate?(content) return false unless content.is_a?(String) text = content.lstrip.downcase return false if text.empty? UNTAGGED_PREAMBLE_STARTS.any? do |start| start.start_with?(text) || text.start_with?(start) end end |