Class: Vivlio::Starter::CLI::IndexCommands::IndexCandidateExtractor
- Inherits:
-
Object
- Object
- Vivlio::Starter::CLI::IndexCommands::IndexCandidateExtractor
- Defined in:
- lib/vivlio/starter/cli/index/index_candidate_extractor.rb
Overview
索引候補語自動抽出クラス
Constant Summary collapse
- BANNER =
<<~BANNER # ================================================================ # 索引候補リスト(config/index_candidates.yml) # ================================================================ # vs index:candidate(内部コマンド)によって自動生成される索引用語候補です。 # # 使い方: # 1. contexts で示される章・抜粋を参照し、索引に載せたい語を確認する # 2. enabled を true/false に切り替えて採用可否を管理する # 3. 採用する語は原稿に [用語|読み] でマークアップ、または index_glossary_terms.yml へ登録する # 4. 読みが誤っている場合は index_glossary_terms.yml に正しい yomi を追加してから再生成する # ================================================================ BANNER
- DEFINITION_PATTERNS =
定義パターン(「〜とは」「〜について」など)
[ /(.{2,20})とは[、,]?[^。]*(?:である|です|を意味|を指|という)/, /(.{2,20})(?:について|に関して)(?:は|の)/, /(.{2,20})(?:を|が)(?:定義|説明|解説)/, /「(.{2,20})」(?:とは|は|について)/, /(.{2,20})(?:の概念|の定義|の意味)/ ].freeze
- TECHNICAL_TERM_PATTERNS =
専門用語パターン(カタカナ語、英字語など)
[ /[ァ-ヶー]{3,}/, # カタカナ3文字以上 /[A-Z][a-zA-Z]{2,}/, # 英語の単語 /[A-Z]{2,}/ # 略語(HTML, CSS など) ].freeze
Instance Attribute Summary collapse
-
#documents ⇒ Object
readonly
Returns the value of attribute documents.
-
#term_contexts ⇒ Object
readonly
Returns the value of attribute term_contexts.
-
#term_scores ⇒ Object
readonly
Returns the value of attribute term_scores.
Instance Method Summary collapse
-
#all_candidates ⇒ Object
全ての候補語を取得.
-
#export_candidates!(output_file = 'config/index_candidates.yml', threshold = 150) ⇒ Object
索引候補を YAML ファイルに出力.
-
#extract_from_chapters!(chapters) ⇒ Object
全章を解析して索引候補を抽出.
-
#initialize ⇒ IndexCandidateExtractor
constructor
A new instance of IndexCandidateExtractor.
Constructor Details
#initialize ⇒ IndexCandidateExtractor
Returns a new instance of IndexCandidateExtractor.
65 66 67 68 69 70 71 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 65 def initialize @documents = {} @term_scores = Hash.new(0.0) @term_contexts = Hash.new { |h, k| h[k] = [] } @yomi_inferrer = YomiInferrer.new @context_width = load_context_width end |
Instance Attribute Details
#documents ⇒ Object (readonly)
Returns the value of attribute documents.
58 59 60 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 58 def documents @documents end |
#term_contexts ⇒ Object (readonly)
Returns the value of attribute term_contexts.
58 59 60 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 58 def term_contexts @term_contexts end |
#term_scores ⇒ Object (readonly)
Returns the value of attribute term_scores.
58 59 60 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 58 def term_scores @term_scores end |
Instance Method Details
#all_candidates ⇒ Object
全ての候補語を取得
61 62 63 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 61 def all_candidates @term_scores.keys end |
#export_candidates!(output_file = 'config/index_candidates.yml', threshold = 150) ⇒ Object
索引候補を YAML ファイルに出力
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 105 def export_candidates!(output_file = 'config/index_candidates.yml', threshold = 150) FileUtils.mkdir_p(File.dirname(output_file)) candidates = @term_scores .select { |_, score| score >= threshold } .sort_by { |_, score| -score } .map do |term, score| yomi = @yomi_inferrer.available? ? @yomi_inferrer.infer(term) : term contexts = @term_contexts[term] .uniq { |ctx| [ctx[:chapter], ctx[:context]] } .first(3) { 'term' => term, 'yomi' => yomi, 'score' => score.round(1), 'contexts' => contexts, 'enabled' => true } end data = { 'generated_at' => Time.now.iso8601, 'threshold' => threshold, 'total_candidates' => candidates.size, 'candidates' => candidates } yaml = data.to_yaml(line_width: -1) yaml_with_spacing = yaml .sub("candidates:\n- term:", "candidates:\n\n- term:") .gsub("\n- term:", "\n\n- term:") File.write(output_file, "#{BANNER}#{yaml_with_spacing}", encoding: 'utf-8') Common.log_success("索引候補を #{output_file} に出力しました") rescue StandardError => e Common.log_error("索引候補の出力に失敗しました: #{e.}") end |
#extract_from_chapters!(chapters) ⇒ Object
全章を解析して索引候補を抽出
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/vivlio/starter/cli/index/index_candidate_extractor.rb', line 75 def extract_from_chapters!(chapters) Common.log_action('索引候補の自動抽出を開始します...') # ドキュメントを読み込み (contents/ 配下のみ) chapters.each do |chapter| md_file = File.join(Common::CONTENTS_DIR, "#{chapter}.md") unless File.exist?(md_file) Common.log_warn("索引候補抽出: contents/ に #{chapter}.md が見つからないためスキップします") next end content = File.read(md_file, encoding: 'utf-8') @documents[chapter] = content end # 各種抽出を実行 extract_definition_patterns! extract_technical_terms! extract_noun_sequences! if @yomi_inferrer.available? # TF-IDF スコアリング calculate_tfidf_scores! Common.log_success("#{@term_scores.size} 件の候補語を抽出しました") end |