feat: behind-the-scenes 👍/👎 rating system (fine-tune data collection)
Brian can rate Lyra's outputs as he uses her; each rating is stored as a (context, content, rating) triple — the shape a future fine-tune / preference dataset wants, collected passively during real use. - memory: ratings table + add_rating (upsert: one row per item, re-rating replaces), list_ratings, rating_counts - server: POST /rate, GET /ratings/counts, GET /ratings/export (JSONL download) - chat UI: subtle 👍/👎 on each assistant reply, captures the prompting message as context - journal/reflection UI: 👍/👎 on each thought - tests: counts + upsert-replace behavior Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -354,12 +354,46 @@
|
||||
return out.join("\n");
|
||||
}
|
||||
|
||||
function addRateBar(div) {
|
||||
const bar = document.createElement("div");
|
||||
bar.className = "rate-bar";
|
||||
const up = document.createElement("button");
|
||||
up.className = "rate-btn"; up.textContent = "👍"; up.title = "Good — more like this";
|
||||
const down = document.createElement("button");
|
||||
down.className = "rate-btn"; down.textContent = "👎"; down.title = "Off — less like this";
|
||||
up.addEventListener("click", () => rateMessage(div, 1, up, down));
|
||||
down.addEventListener("click", () => rateMessage(div, -1, up, down));
|
||||
bar.appendChild(up); bar.appendChild(down);
|
||||
div.appendChild(bar);
|
||||
}
|
||||
|
||||
function rateMessage(div, value, up, down) {
|
||||
// context = the nearest preceding user message
|
||||
let ctx = "", p = div.previousElementSibling;
|
||||
while (p) {
|
||||
if (p.classList && p.classList.contains("user")) { ctx = p.textContent; break; }
|
||||
p = p.previousElementSibling;
|
||||
}
|
||||
fetch(`${RELAY_BASE}/rate`, {
|
||||
method: "POST", headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ kind: "chat", rating: value, content: div.dataset.raw || "", context: ctx, session_id: currentSession })
|
||||
}).catch(() => {});
|
||||
up.classList.toggle("rated", value === 1);
|
||||
down.classList.toggle("rated", value === -1);
|
||||
}
|
||||
|
||||
function addMessage(role, text, autoScroll = true) {
|
||||
const messagesEl = document.getElementById("messages");
|
||||
|
||||
const msgDiv = document.createElement("div");
|
||||
msgDiv.className = `msg ${role}`;
|
||||
if (role === "assistant") { msgDiv.innerHTML = renderMarkdown(text); } else { msgDiv.textContent = text; }
|
||||
if (role === "assistant") {
|
||||
msgDiv.innerHTML = renderMarkdown(text);
|
||||
msgDiv.dataset.raw = text;
|
||||
addRateBar(msgDiv);
|
||||
} else {
|
||||
msgDiv.textContent = text;
|
||||
}
|
||||
messagesEl.appendChild(msgDiv);
|
||||
|
||||
// Auto-scroll to bottom if enabled
|
||||
|
||||
Reference in New Issue
Block a user