Module: RubynCode::Learning::Extractor

Defined in:
lib/rubyn_code/learning/extractor.rb

Overview

Extracts reusable patterns from session messages using an LLM.

After a session, the extractor sends recent conversation history to a cheaper model (Haiku) and asks it to identify patterns that could be useful in future sessions for the same project.

Constant Summary collapse

MESSAGE_WINDOW =

Maximum number of recent messages to analyze.

30
VALID_TYPES =

Valid pattern types that the LLM is asked to produce.

%w[
  error_resolution
  user_correction
  workaround
  debugging_technique
  project_specific
].freeze
EXTRACTION_PROMPT =
"Analyze the following conversation between a developer and an AI coding assistant.\n" \
"Extract reusable patterns that could help in future sessions for this project.\n\n" \
"For each pattern, provide:\n" \
"- type: one of #{VALID_TYPES.join(', ')}\n" \
"- pattern: a concise description of the learned behavior or fix\n" \
"- context_tags: relevant tags (e.g., framework names, error types, file patterns)\n" \
"- confidence: initial confidence score between 0.3 and 0.8\n\n" \
"Respond with a JSON array of objects. If no patterns are found, respond with [].\n" \
'Only extract patterns that are genuinely reusable, not one-off fixes.'.freeze
DECAY_RATES =
{
  'project_specific' => 0.02,
  'error_resolution' => 0.03,
  'debugging_technique' => 0.04,
  'user_correction' => 0.05,
  'workaround' => 0.07
}.freeze

Class Method Summary collapse

Class Method Details

.call(messages, llm_client:, project_path:) ⇒ Array<Hash>

Extracts instinct patterns from a session’s message history.

Parameters:

  • messages (Array<Hash>)

    the conversation messages

  • llm_client (LLM::Client)

    the LLM client for extraction

  • project_path (String)

    the project root path

Returns:

  • (Array<Hash>)

    extracted instinct hashes ready for persistence



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rubyn_code/learning/extractor.rb', line 43

def call(messages, llm_client:, project_path:)
  recent = messages.last(MESSAGE_WINDOW)
  return [] if recent.empty?

  response = request_extraction(recent, llm_client)
  raw_patterns = parse_response(response)

  instincts = raw_patterns.filter_map do |raw|
    normalize_pattern(raw, project_path)
  end

  save_to_db(instincts) unless instincts.empty?

  instincts
end