Add human-led conversation learning loop
This commit is contained in:
1 parent
bc42c55555
commit
687abab82b
52 files changed
+2112
-53
No files matched your search
@@ -0,0 +1,129 @@
|
||||
import { z } from 'zod';
|
||||
import type { AttributionConfidence, ConversationEventKind } from '../database/conversation-event-repository.js';
|
||||
import type { ConversationPolicyMode } from './conversation-state.js';
|
||||
|
||||
export const LearningStageSchema = z.enum([
|
||||
'rapport',
|
||||
'answer',
|
||||
'flirt',
|
||||
'disclosure',
|
||||
'media-invitation',
|
||||
'handoff',
|
||||
'unknown',
|
||||
]);
|
||||
export type LearningStage = z.infer<typeof LearningStageSchema>;
|
||||
|
||||
export const LearningTurnSchema = z.strictObject({
|
||||
eventId: z.string(),
|
||||
timestamp: z.number(),
|
||||
role: z.enum(['recipient', 'operator']),
|
||||
actor: z.enum(['recipient', 'ai', 'human']),
|
||||
kind: z.enum([
|
||||
'inbound-text',
|
||||
'opener',
|
||||
'automation-reply',
|
||||
'manual-text',
|
||||
'library-reciprocal',
|
||||
]),
|
||||
text: z.string(),
|
||||
});
|
||||
export type LearningTurn = z.infer<typeof LearningTurnSchema>;
|
||||
|
||||
export const LearningCreditClasses = [
|
||||
'human-created-success',
|
||||
'human-improved-success',
|
||||
'human-completed-ai-trajectory',
|
||||
'autonomous-success',
|
||||
'recipient-initiated-media',
|
||||
'uncertain',
|
||||
] as const;
|
||||
export type LearningCreditClass = (typeof LearningCreditClasses)[number];
|
||||
|
||||
export type LearningTrajectoryStatus = 'provisional' | 'eligible' | 'excluded' | 'invalidated' | 'needs-review';
|
||||
export type LearningDecisionStatus = 'eligible' | 'excluded' | 'invalidated' | 'needs-review';
|
||||
|
||||
export interface LearningTrajectoryRecord {
|
||||
id: string;
|
||||
accountId: string;
|
||||
conversationId: string;
|
||||
sentMessageId: number | null;
|
||||
subreddit: string | null;
|
||||
sourceType: 'image' | 'chat' | null;
|
||||
policyMode: ConversationPolicyMode | null;
|
||||
firstHumanEventId: string | null;
|
||||
outcomeEventId: string;
|
||||
outcomeType: 'image-received' | 'reciprocal-engagement';
|
||||
creditClass: LearningCreditClass;
|
||||
attributionConfidence: AttributionConfidence;
|
||||
status: LearningTrajectoryStatus;
|
||||
maturityAt: number;
|
||||
invalidatedAt: number | null;
|
||||
invalidationReason: string | null;
|
||||
reviewedAt: number | null;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export interface LearningDecisionRecord {
|
||||
id: string;
|
||||
trajectoryId: string;
|
||||
accountId: string;
|
||||
decisionEventId: string;
|
||||
stage: LearningStage;
|
||||
context: LearningTurn[];
|
||||
chosenResponse: string;
|
||||
turnsUntilOutcome: number;
|
||||
isDirectMediaInvitation: boolean;
|
||||
qualityStatus: LearningDecisionStatus;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export interface LearningTrajectoryDetail extends LearningTrajectoryRecord {
|
||||
decisions: LearningDecisionRecord[];
|
||||
}
|
||||
|
||||
export interface RetrievedLearningExample {
|
||||
decisionId: string;
|
||||
trajectoryId: string;
|
||||
creditClass: LearningCreditClass;
|
||||
stage: LearningStage;
|
||||
context: LearningTurn[];
|
||||
chosenResponse: string;
|
||||
turnsUntilOutcome: number;
|
||||
subreddit: string | null;
|
||||
policyMode: ConversationPolicyMode | null;
|
||||
}
|
||||
|
||||
export interface ConversationLearningQuery {
|
||||
accountId: string;
|
||||
conversationId: string;
|
||||
subreddit: string | null;
|
||||
policyMode: ConversationPolicyMode;
|
||||
stage: LearningStage;
|
||||
purpose: 'reply' | 'media-ask';
|
||||
incomingEventId: string;
|
||||
}
|
||||
|
||||
export interface ConversationLearningProvider {
|
||||
getExamples(query: ConversationLearningQuery): readonly RetrievedLearningExample[];
|
||||
recordGeneration(input: {
|
||||
query: ConversationLearningQuery;
|
||||
mode: 'shadow' | 'injected';
|
||||
policyVersion: string;
|
||||
exampleIds: readonly string[];
|
||||
promptSha256?: string | null;
|
||||
generatedAt?: number;
|
||||
}): void;
|
||||
}
|
||||
|
||||
export interface AttributedConversationMessage {
|
||||
eventId: string;
|
||||
timestamp: number;
|
||||
isSelf: boolean;
|
||||
text: string;
|
||||
mediaCount: number;
|
||||
actor: 'recipient' | 'ai' | 'human' | 'unknown';
|
||||
kind: ConversationEventKind;
|
||||
confidence: AttributionConfidence;
|
||||
}
|
||||
Reference in new issue
Block a user