1
0
Fork 0
forked from lthn/LEM
LEM/influx.go
Claude e0d352c803
feat: add Go lem CLI and scoring-agent scripts
Go lem CLI (stdlib + DuckDB) replaces scattered Python scripts:
- score: heuristic regex + LLM-as-judge scoring
- probe: generate responses then score
- compare: diff two score files
- status: InfluxDB training/generation progress
- export: golden set to training JSONL splits
- expand: distributed expansion via API + InfluxDB coordination

New scripts from Feb 14 creative session:
- scoring_agent.py: ROCm daemon that auto-scores checkpoints
- probes.py: 23 binary pass/fail capability probes
- convert_adapter.py: MLX to PEFT adapter conversion
- score_r1_capability.py: DeepSeek R1 checkpoint scoring
- lek_content_scorer.py: 6-dimension ethics content scorer
- lem_train_15k.py: InfluxDB-coordinated training script
- pipeline.py: DuckDB pipeline (seeds, golden set, expansion)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:22:13 +00:00

134 lines
3.4 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
// InfluxClient talks to an InfluxDB v3 instance.
type InfluxClient struct {
url string // e.g. "http://10.69.69.165:8181"
db string // e.g. "training"
token string // bearer token
}
// NewInfluxClient creates an InfluxClient for the given URL and database.
// Reads token from INFLUX_TOKEN env var first, then ~/.influx_token file.
// If url is empty, defaults to "http://10.69.69.165:8181".
// If db is empty, defaults to "training".
func NewInfluxClient(url, db string) *InfluxClient {
if url == "" {
url = "http://10.69.69.165:8181"
}
if db == "" {
db = "training"
}
token := os.Getenv("INFLUX_TOKEN")
if token == "" {
home, err := os.UserHomeDir()
if err == nil {
data, err := os.ReadFile(filepath.Join(home, ".influx_token"))
if err == nil {
token = strings.TrimSpace(string(data))
}
}
}
return &InfluxClient{
url: url,
db: db,
token: token,
}
}
// WriteLp writes line protocol data to InfluxDB.
// POST to /api/v3/write_lp?db={db} with lines joined by newlines.
func (c *InfluxClient) WriteLp(lines []string) error {
body := strings.Join(lines, "\n")
url := fmt.Sprintf("%s/api/v3/write_lp?db=%s", c.url, c.db)
req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(body))
if err != nil {
return fmt.Errorf("create write request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.token)
req.Header.Set("Content-Type", "text/plain")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("write request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
return fmt.Errorf("write failed %d: %s", resp.StatusCode, string(respBody))
}
return nil
}
// QuerySQL runs a SQL query against InfluxDB and returns the result rows.
// POST to /api/v3/query_sql with JSON body {"db": db, "q": sql}.
func (c *InfluxClient) QuerySQL(sql string) ([]map[string]interface{}, error) {
reqBody := map[string]string{
"db": c.db,
"q": sql,
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, fmt.Errorf("marshal query request: %w", err)
}
url := c.url + "/api/v3/query_sql"
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(jsonBody))
if err != nil {
return nil, fmt.Errorf("create query request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("query request: %w", err)
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read query response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("query failed %d: %s", resp.StatusCode, string(respBody))
}
var rows []map[string]interface{}
if err := json.Unmarshal(respBody, &rows); err != nil {
return nil, fmt.Errorf("unmarshal query response: %w", err)
}
return rows, nil
}
// escapeLp escapes spaces, commas, and equals signs for InfluxDB line protocol
// tag values.
func escapeLp(s string) string {
s = strings.ReplaceAll(s, `,`, `\,`)
s = strings.ReplaceAll(s, `=`, `\=`)
s = strings.ReplaceAll(s, ` `, `\ `)
return s
}