Class: LangExtract::Core::FuzzyAligner

Inherits:
Object
  • Object
show all
Defined in:
lib/langextract/core/fuzzy_aligner.rb

Overview

Coordinates indexed ordered-subsequence fuzzy alignment and candidate selection. Index construction and dynamic planning live separately.

Constant Summary collapse

MAX_FUZZY_CANDIDATE_STARTS =

Historical limit retained for compatibility. Indexed planning no longer truncates candidate starts.

4_000
SubsequenceAlignment =
FuzzyAlignmentPlanner::SubsequenceAlignment

Instance Method Summary collapse

Constructor Details

#initialize(source_tokens:, fuzzy_threshold:, min_coverage:, min_density:, allow_overlaps:, alignment_index: nil) ⇒ FuzzyAligner

Returns a new instance of FuzzyAligner.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/langextract/core/fuzzy_aligner.rb', line 18

def initialize(source_tokens:, fuzzy_threshold:, min_coverage:, min_density:, allow_overlaps:,
               alignment_index: nil)
  @source_tokens = source_tokens
  @fuzzy_threshold = fuzzy_threshold
  @allow_overlaps = allow_overlaps
  @alignment_index = alignment_index || FuzzyAlignmentIndex.new(source_tokens)
  @policy = FuzzyAlignmentPolicy.new(source_tokens: source_tokens, fuzzy_threshold: fuzzy_threshold)
  @planner = FuzzyAlignmentPlanner.new(
    source_tokens: source_tokens,
    alignment_index: @alignment_index,
    fuzzy_threshold: fuzzy_threshold,
    min_coverage: min_coverage,
    min_density: min_density
  )
end

Instance Method Details

#candidates(target_tokens, range, occupied) ⇒ Object

Returns [CharInterval, score] candidates ranked by score, then position.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/langextract/core/fuzzy_aligner.rb', line 35

def candidates(target_tokens, range, occupied)
  alignments = all_subsequence_alignments(target_tokens)
  return [] if alignments.empty?

  found = alignments.filter_map do |alignment|
    next unless planner.feasible?(alignment, target_tokens.length)

    score = policy.score_for(target_tokens, alignment.token_indices)
    next unless score

    interval = interval_for_alignment(alignment.token_indices, range)
    next unless interval

    match = [interval, score]
    return [match] if perfect_non_overlapping?(match, occupied)

    match
  end

  ranked_unique_candidates(found)
end