feat: TipCandidate shared schema — typed candidates through the bandit pipeline #89

Closed
opened 2026-04-17 08:11:11 +00:00 by alvis · 0 comments
Owner

Goal

Define a first-class TipCandidate type that flows from the LLM generator through the bandit scorer to the recommender API.

Schema

// packages/shared-types/src/tip.ts
export interface TipCandidate {
  id: string;            // uuid, stable for dedup
  content: string;       // the tip text shown to the user
  kind: TipKind;         // task | advice | insight | reminder
  source: TipSource;     // llm | task_direct | fallback
  model?: string;        // e.g. "qwen2.5:7b" — null for task_direct
  prompt_version?: string; // e.g. "v2" — null for task_direct
  confidence?: number;   // 0–1, model self-reported
  task_id?: string;      // set when source=task_direct or kind=task
}

export type TipKind = "task" | "advice" | "insight" | "reminder";
export type TipSource = "llm" | "task_direct" | "fallback";

Changes

  • Add to packages/shared-types
  • Update ml/serving /score endpoints to accept + return TipCandidate[]
  • Update services/api/src/routes/recommender.ts to pipe TipCandidate through scoring
  • Update tip_scores table: add kind, source, model, prompt_version columns
  • Update admin reward analytics dashboard to group by these new columns

Why now

This schema is the seam between the LLM generator (#79) and the bandit scorer. Defining it first lets both sides develop independently. The bandit doesn't care whether a candidate came from an LLM or a task list — it just scores features.

## Goal Define a first-class `TipCandidate` type that flows from the LLM generator through the bandit scorer to the recommender API. ## Schema ```typescript // packages/shared-types/src/tip.ts export interface TipCandidate { id: string; // uuid, stable for dedup content: string; // the tip text shown to the user kind: TipKind; // task | advice | insight | reminder source: TipSource; // llm | task_direct | fallback model?: string; // e.g. "qwen2.5:7b" — null for task_direct prompt_version?: string; // e.g. "v2" — null for task_direct confidence?: number; // 0–1, model self-reported task_id?: string; // set when source=task_direct or kind=task } export type TipKind = "task" | "advice" | "insight" | "reminder"; export type TipSource = "llm" | "task_direct" | "fallback"; ``` ## Changes - Add to `packages/shared-types` - Update `ml/serving` `/score` endpoints to accept + return `TipCandidate[]` - Update `services/api/src/routes/recommender.ts` to pipe `TipCandidate` through scoring - Update `tip_scores` table: add `kind`, `source`, `model`, `prompt_version` columns - Update admin reward analytics dashboard to group by these new columns ## Why now This schema is the seam between the LLM generator (#79) and the bandit scorer. Defining it first lets both sides develop independently. The bandit doesn't care whether a candidate came from an LLM or a task list — it just scores features.
alvis added this to the M2 — AI tips + multi-source signals milestone 2026-04-17 08:11:11 +00:00
alvis closed this issue 2026-04-17 14:22:49 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alvis/oO#89