Class: Chocomint::Logger::SqliteLogger

Inherits:
Object
  • Object
show all
Defined in:
lib/chocomint/logger/sqlite_logger.rb

Overview

全試行を SQLite に記録する (DESIGN §12)。

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ SqliteLogger

Returns a new instance of SqliteLogger.



12
13
14
15
16
# File 'lib/chocomint/logger/sqlite_logger.rb', line 12

def initialize(path)
  FileUtils.mkdir_p(File.dirname(path)) unless File.dirname(path).empty?
  @db = SQLite3::Database.new(path)
  create_schema
end

Instance Method Details

#closeObject



185
# File 'lib/chocomint/logger/sqlite_logger.rb', line 185

def close = @db.close

#count(trace_id: nil) ⇒ Object

ページネーション用の総件数。trace_id 指定時はその trace の件数。



176
177
178
179
180
181
182
183
# File 'lib/chocomint/logger/sqlite_logger.rb', line 176

def count(trace_id: nil)
  trace_id = normalize_text(trace_id)
  if trace_id
    @db.execute("SELECT COUNT(*) FROM executions WHERE trace_id = ?", [trace_id])
  else
    @db.execute("SELECT COUNT(*) FROM executions")
  end.first.first
end

#execution(id) ⇒ Object

監査ログ 1 件を id 指定で取得する。無ければ nil。



161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/chocomint/logger/sqlite_logger.rb', line 161

def execution(id)
  @db.results_as_hash = true
  @db.execute(
    <<~SQL,
      SELECT id, trace_id, attempt, request, proposal, result,
             verifier_output, status, created_at
      FROM executions WHERE id = ?
    SQL
    [id]
  ).first
ensure
  @db.results_as_hash = false
end

#llm_payload(id) ⇒ Object

LLM ペイロード 1 件を id 指定で取得する。無ければ nil。



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/chocomint/logger/sqlite_logger.rb', line 113

def llm_payload(id)
  @db.results_as_hash = true
  @db.execute(
    <<~SQL,
      SELECT id, trace_id, role, model, request_body, request_headers,
             response_status, response_body, created_at
      FROM llm_payloads WHERE id = ?
    SQL
    [id]
  ).first
ensure
  @db.results_as_hash = false
end

#llm_payload_count(trace_id: nil) ⇒ Object

LLM ペイロードの総件数。trace_id 指定時はその trace の件数。



128
129
130
131
132
133
134
135
# File 'lib/chocomint/logger/sqlite_logger.rb', line 128

def llm_payload_count(trace_id: nil)
  trace_id = normalize_text(trace_id)
  if trace_id
    @db.execute("SELECT COUNT(*) FROM llm_payloads WHERE trace_id = ?", [trace_id])
  else
    @db.execute("SELECT COUNT(*) FROM llm_payloads")
  end.first.first
end

#recent(limit: 100, offset: 0, trace_id: nil) ⇒ Object

監査ログを新しい順に取得する。ブラウザ表示 (GET /logs) 用。 trace_id を指定するとその trace のみに絞る。offset でページ送り。 返り値は各行を Hash(カラム名 => 値) にした配列。



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/chocomint/logger/sqlite_logger.rb', line 140

def recent(limit: 100, offset: 0, trace_id: nil)
  trace_id = normalize_text(trace_id)
  where = trace_id ? "WHERE trace_id = ?" : ""
  params = trace_id ? [trace_id, limit, offset] : [limit, offset]
  @db.results_as_hash = true
  @db.execute(
    <<~SQL,
      SELECT id, trace_id, attempt, request, proposal, result,
             verifier_output, status, created_at
      FROM executions
      #{where}
      ORDER BY id DESC
      LIMIT ? OFFSET ?
    SQL
    params
  )
ensure
  @db.results_as_hash = false
end

#recent_llm_payloads(limit: 100, offset: 0, trace_id: nil) ⇒ Object

LLM 送信ペイロードを新しい順に取得する。trace_id で絞り込み可能。



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/chocomint/logger/sqlite_logger.rb', line 73

def recent_llm_payloads(limit: 100, offset: 0, trace_id: nil)
  trace_id = normalize_text(trace_id)
  where = trace_id ? "WHERE trace_id = ?" : ""
  params = trace_id ? [trace_id, limit, offset] : [limit, offset]
  @db.results_as_hash = true
  @db.execute(
    <<~SQL,
      SELECT id, trace_id, role, model, request_body, request_headers,
             response_status, response_body, created_at
      FROM llm_payloads
      #{where}
      ORDER BY id DESC
      LIMIT ? OFFSET ?
    SQL
    params
  )
ensure
  @db.results_as_hash = false
end

#record(trace_id:, attempt:, request:, proposal:, result:, status:, verifier_output: nil) ⇒ Object

1 attempt を 1 行として保存する。



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/chocomint/logger/sqlite_logger.rb', line 19

def record(trace_id:, attempt:, request:, proposal:, result:, status:, verifier_output: nil)
  @db.execute(
    <<~SQL,
      INSERT INTO executions
        (trace_id, attempt, request, proposal, result, verifier_output, status, created_at)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    SQL
    [
      trace_id,
      attempt,
      request.to_s,
      serialize(proposal),
      serialize(result),
      verifier_output,
      status,
      Time.now.utc.iso8601
    ]
  )
end

#record_llm_payload(role:, model:, request_body:, request_headers:, trace_id: nil) ⇒ Object

LLM への送信内容 (ヘッダ含む生ボディ全体) を 1 呼び出し 1 行で記録する。 role: "primary" / "verifier"。body/headers は Hash を渡すと JSON 化する。 戻り値: 挿入した行の id (後で update_llm_payload_response に渡す)。



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/chocomint/logger/sqlite_logger.rb', line 42

def record_llm_payload(role:, model:, request_body:, request_headers:, trace_id: nil)
  @db.execute(
    <<~SQL,
      INSERT INTO llm_payloads
        (trace_id, role, model, request_body, request_headers, created_at)
      VALUES (?, ?, ?, ?, ?, ?)
    SQL
    [
      trace_id,
      role.to_s,
      model.to_s,
      serialize(request_body),
      serialize(request_headers),
      Time.now.utc.iso8601
    ]
  )
  @db.last_insert_row_id
end

#tool_outcomes(trace_id) ⇒ Object

trace_id に紐づくツール実行の正常性判定 (status / verifier_output) を attempt 昇順で返す。LLM ペイロード詳細で「判定結果」を併記するため。



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/chocomint/logger/sqlite_logger.rb', line 95

def tool_outcomes(trace_id)
  trace_id = normalize_text(trace_id)
  return [] if trace_id.nil?

  @db.results_as_hash = true
  @db.execute(
    <<~SQL,
      SELECT attempt, status, verifier_output, proposal
      FROM executions WHERE trace_id = ?
      ORDER BY attempt ASC, id ASC
    SQL
    [trace_id]
  )
ensure
  @db.results_as_hash = false
end

#update_llm_payload_response(id, response_status:, response_body:) ⇒ Object

記録済みペイロード行に LLM レスポンス (HTTP ステータス + 生ボディ) を追記する。 id は record_llm_payload の戻り値。body は文字列/Hash どちらも可。



63
64
65
66
67
68
69
70
# File 'lib/chocomint/logger/sqlite_logger.rb', line 63

def update_llm_payload_response(id, response_status:, response_body:)
  return if id.nil?

  @db.execute(
    "UPDATE llm_payloads SET response_status = ?, response_body = ? WHERE id = ?",
    [response_status, serialize(response_body), id]
  )
end