Class: Chocomint::LLM::ChatClient

Inherits:
Object
  • Object
show all
Defined in:
lib/chocomint/llm/chat_client.rb

Overview

/edit チャットの補助 LLM 処理 (要約・抽出・圧縮) を担う軽量クライアント。

現在の役割:

- summarize 

かつて指示を task/chat に振り分けていた classify / answer は、全指示を Planner に 流す方針 (ツールを自律実行して解決) に変更したため削除済み。

Constant Summary collapse

SUMMARIZE_SYSTEM_PROMPT =

実行結果の要約プロンプト。実行済みのツール列とその結果をもとに、 ユーザー要求に対して何を行い・どうなったかを自然文でまとめさせる。

"\u3042\u306A\u305F\u306F\u30B3\u30FC\u30C9\u30A8\u30C7\u30A3\u30BF\u306E\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u3067\u3059\u3002\u30E6\u30FC\u30B6\u30FC\u8981\u6C42\u3092\u9054\u6210\u3059\u308B\u305F\u3081\u306B\n\u3044\u304F\u3064\u304B\u306E\u30C4\u30FC\u30EB (\u30D5\u30A1\u30A4\u30EB\u7DE8\u96C6\u3084\u30B3\u30DE\u30F3\u30C9\u5B9F\u884C) \u3092\u5B9F\u884C\u3057\u307E\u3057\u305F\u3002\n\u5B9F\u884C\u3057\u305F\u30C4\u30FC\u30EB\u3068\u305D\u306E\u7D50\u679C\u3092\u3075\u307E\u3048\u3001\u300C\u4F55\u3092\u3057\u3066\u30FB\u7D50\u679C\u3069\u3046\u306A\u3063\u305F\u304B\u300D\u3092\n\u30E6\u30FC\u30B6\u30FC\u5411\u3051\u306B\u7C21\u6F54\u306A\u65E5\u672C\u8A9E\u3067\u307E\u3068\u3081\u3066\u304F\u3060\u3055\u3044\u3002\n\u30B3\u30DE\u30F3\u30C9\u306E\u751F\u51FA\u529B\u3092\u305D\u306E\u307E\u307E\u8CBC\u308B\u306E\u3067\u306F\u306A\u304F\u3001\u8981\u70B9\u3092\u77ED\u304F\u8AAC\u660E\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n\u7D75\u6587\u5B57\u306F\u4E00\u5207\u4F7F\u308F\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n"
EXTRACT_SYSTEM_PROMPT =

ウェブページ内容の抽出プロンプト。fetch_url ツールが取得した本文テキストから、 ユーザーの目的 (query) に沿って必要な情報を抜き出し・要約させる。

"\u3042\u306A\u305F\u306F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u5185\u5BB9\u3092\u8AAD\u307F\u53D6\u308B\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u3067\u3059\u3002\u3042\u308B\u30DA\u30FC\u30B8\u306E\u672C\u6587\u30C6\u30AD\u30B9\u30C8\u3068\u3001\n\u30E6\u30FC\u30B6\u30FC\u304C\u77E5\u308A\u305F\u3044\u3053\u3068 (\u76EE\u7684) \u304C\u6E21\u3055\u308C\u307E\u3059\u3002\u672C\u6587\u304B\u3089\u76EE\u7684\u306B\u95A2\u4FC2\u3059\u308B\u60C5\u5831\u3060\u3051\u3092\n\u629C\u304D\u51FA\u3057\u3001\u7C21\u6F54\u3067\u6B63\u78BA\u306A\u65E5\u672C\u8A9E\u306B\u307E\u3068\u3081\u3066\u304F\u3060\u3055\u3044\u3002\n\u672C\u6587\u306B\u7B54\u3048\u304C\u66F8\u304B\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u306F\u3001\u305D\u306E\u65E8\u3092\u6B63\u76F4\u306B\u8FF0\u3079\u3066\u304F\u3060\u3055\u3044\u3002\n\u63A8\u6E2C\u3067\u88DC\u308F\u305A\u3001\u672C\u6587\u306B\u66F8\u304B\u308C\u3066\u3044\u308B\u4E8B\u5B9F\u3060\u3051\u3092\u6839\u62E0\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n\u7D75\u6587\u5B57\u306F\u4E00\u5207\u4F7F\u308F\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n"
COMPACT_SYSTEM_PROMPT =

会話履歴の圧縮プロンプト。これまでのやり取りを、後から見返して文脈を 思い出せる短い要約に畳み込ませる (/compact 用)。

"\u3042\u306A\u305F\u306F\u30B3\u30FC\u30C9\u30A8\u30C7\u30A3\u30BF\u306E\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u3067\u3059\u3002\u3053\u308C\u307E\u3067\u306E\u30E6\u30FC\u30B6\u30FC\u3068\u306E\n\u3084\u308A\u53D6\u308A\u306E\u8A18\u9332\u3092\u6E21\u3057\u307E\u3059\u3002\u5F8C\u304B\u3089\u8AAD\u307F\u8FD4\u3057\u3066\u6587\u8108\u3092\u601D\u3044\u51FA\u305B\u308B\u3088\u3046\u3001\n\u300C\u4F55\u3092\u76F8\u8AC7\u3057\u30FB\u4F55\u3092\u884C\u3044\u30FB\u3069\u3046\u6C7A\u7740\u3057\u305F\u304B\u300D\u306E\u8981\u70B9\u3092\u3001\u7C21\u6F54\u306A\u65E5\u672C\u8A9E\u306E\n\u7B87\u6761\u66F8\u304D\u3067\u307E\u3068\u3081\u3066\u304F\u3060\u3055\u3044\u3002\u672A\u89E3\u6C7A\u306E\u8AB2\u984C\u3084\u6B21\u306E\u4E00\u624B\u304C\u3042\u308C\u3070\u6B8B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n\u7D30\u90E8\u306E\u751F\u51FA\u529B\u306F\u7701\u304D\u3001\u91CD\u8981\u306A\u4E8B\u5B9F\u3068\u7D50\u8AD6\u3060\u3051\u3092\u6B8B\u3057\u307E\u3059\u3002\n\u7D75\u6587\u5B57\u306F\u4E00\u5207\u4F7F\u308F\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n"

Instance Method Summary collapse

Constructor Details

#initialize(base_client:) ⇒ ChatClient



51
52
53
# File 'lib/chocomint/llm/chat_client.rb', line 51

def initialize(base_client:)
  @client = base_client
end

Instance Method Details

#compact(transcript, trace_id: nil) ⇒ Object

これまでの会話ログ (プレーンテキスト) を短い要約に畳み込む (/compact 用)。 要約できないときは Chocomint::Error を投げる (呼び出し側で 500 にする)。

Raises:



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/chocomint/llm/chat_client.rb', line 100

def compact(transcript, trace_id: nil)
  response = @client.create_message(
    system: COMPACT_SYSTEM_PROMPT,
    messages: [{ "role" => "user", "content" => transcript.to_s }],
    trace_id: trace_id
  )
  text = strip_emoji(extract_text(response))
  raise Chocomint::Error, "compact response is empty" if text.nil? || text.empty?

  text
end

#extract(query, text, url: nil, trace_id: nil) ⇒ Object

ウェブページ本文 (text) から、目的 (query) に沿った情報を抽出・要約する。 fetch_url ツールから呼ばれる。抽出できないときは Chocomint::Error を投げる。

Raises:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/chocomint/llm/chat_client.rb', line 79

def extract(query, text, url: nil, trace_id: nil)
  content = "    \u5BFE\u8C61URL: \#{url}\n    \u77E5\u308A\u305F\u3044\u3053\u3068: \#{query.to_s.empty? ? '(\u6307\u5B9A\u306A\u3057\u3002\u30DA\u30FC\u30B8\u306E\u8981\u70B9\u3092\u307E\u3068\u3081\u308B)' : query}\n\n    \u30DA\u30FC\u30B8\u672C\u6587:\n    \#{text}\n  MSG\n  response = @client.create_message(\n    system: EXTRACT_SYSTEM_PROMPT,\n    messages: [{ \"role\" => \"user\", \"content\" => content }],\n    trace_id: trace_id\n  )\n  result = strip_emoji(extract_text(response))\n  raise Chocomint::Error, \"extract response is empty\" if result.nil? || result.empty?\n\n  result\nend\n"

#summarize(request, steps, trace_id: nil) ⇒ Object

実行済みステップ列を自然文でまとめる。失敗しても要約なしで続行できるよう 例外時は nil を返す (呼び出し側は生の結果表示にフォールバックする)。 steps: [{ tool:, label:, target:, status:, exit_code:, output: }, ...] 形式。

かつては全ステップの生出力を 1 本の巨大な user メッセージに連結し、その後は 要求と各ステップを別々の user メッセージに分割していた。だが Messages API は user/assistant が交互になる形を想定しており、user メッセージの連投は素直でない。 そこで「ユーザー要求」と「実行トレース (ステップの構造化 JSON 配列)」を、 1 本の user メッセージにまとめて渡す (要求とトレースは見出しで切り分ける)。



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/chocomint/llm/chat_client.rb', line 64

def summarize(request, steps, trace_id: nil)
  messages = build_summarize_messages(request, steps)
  response = @client.create_message(
    system: SUMMARIZE_SYSTEM_PROMPT,
    messages: messages,
    trace_id: trace_id
  )
  text = strip_emoji(extract_text(response))
  text.nil? || text.empty? ? nil : text
rescue Chocomint::Error
  nil
end