feat: make birth-time rectification conversational
This commit is contained in:
@@ -21,7 +21,10 @@ import {
|
||||
type DeclaredBirthInput,
|
||||
type LifeEventEvidence,
|
||||
} from "../../../lib/conversational-rectification/persistence-contracts.ts";
|
||||
import type { RectificationNarrativeGenerator } from "../../../lib/conversational-rectification/narrative-agent.ts";
|
||||
import {
|
||||
rectificationNarrativeOutputSchema,
|
||||
type RectificationNarrativeGenerator,
|
||||
} from "../../../lib/conversational-rectification/narrative-agent.ts";
|
||||
import type { BirthTimeJourneyEngine, RectificationQuestionnaire } from "../../../lib/birth-time-journey-service.ts";
|
||||
import type { CandidateResult, LifeEvent } from "../../../lib/birth-time-evidence.ts";
|
||||
import type { CandidateDifferenceBuild } from "../../../lib/birth-time-dynamic-choice-internal.ts";
|
||||
@@ -353,6 +356,7 @@ function scoreableLifeEvents(
|
||||
domain: item.domain,
|
||||
precision: item.datePrecision as "day" | "month" | "year",
|
||||
date: item.dateValue,
|
||||
summary: item.eventSummary,
|
||||
} as LifeEvent];
|
||||
}).slice(-MAXIMUM_SCOREABLE_EVENTS);
|
||||
}
|
||||
@@ -671,13 +675,21 @@ async function productionNarrativeGenerator(): Promise<RectificationNarrativeGen
|
||||
name: "Conversational Rectification Narrator",
|
||||
model: model.model,
|
||||
skills: [jyotishSkillPath],
|
||||
instructions: "Return only the exact JSON object requested by the user prompt. Use the Jyotish Skill only to choose a natural, one-question-at-a-time evidence strategy and wording. Treat supplied packet facts as the exclusive source of candidate times, status, dates, layers, scores, references, and confirmation permissions. Never invent, recalculate, or confirm candidate data.",
|
||||
instructions: "Return only the exact JSON object requested by the user prompt. Load the Jyotish Skill to choose a natural, one-question-at-a-time evidence strategy and to explain the supplied expert workflow. Treat supplied packet facts as the exclusive source of candidate times, status, dates, layers, scores, technique states, references, and confirmation permissions. Never invent, recalculate, or confirm candidate data. A blocked or not_evaluated technique must never be described as used. On final turns, include a concise user-readable Technique Audit Table from packet.expertWorkflow; on collecting turns, keep the reply conversational and ask exactly one next question.",
|
||||
});
|
||||
return {
|
||||
modelId: model.id,
|
||||
async generate(prompt) {
|
||||
const result = await agent.generate([{ role: "user", content: prompt }]);
|
||||
return { text: result.text };
|
||||
const result = await agent.generate(
|
||||
[{ role: "user", content: prompt }],
|
||||
{
|
||||
structuredOutput: {
|
||||
schema: rectificationNarrativeOutputSchema,
|
||||
jsonPromptInjection: "inline",
|
||||
},
|
||||
},
|
||||
);
|
||||
return { text: JSON.stringify(rectificationNarrativeOutputSchema.parse(result.object)) };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
+16
-25
@@ -830,8 +830,6 @@ export default function Home() {
|
||||
const activeOnboardingRequestIdentity = useRef("");
|
||||
const accountRefreshGuard = useRef(createLatestAccountRequestGuard());
|
||||
const rectificationQuestionHandoff = useRef(createRectificationQuestionHandoffCoordinator<Theme>());
|
||||
const continueRectificationQuestion = useRef<(question: string) => void>(() => undefined);
|
||||
const automaticRectificationContinuation = useRef("");
|
||||
const durableRectificationQuestionHandoff = useRef(
|
||||
createDurableRectificationQuestionHandoffClient(),
|
||||
);
|
||||
@@ -2632,6 +2630,19 @@ export default function Home() {
|
||||
&& !sessions.some((session) => session.id === rectificationQuestionHandoff.current.peek()?.sessionId)) {
|
||||
rectificationQuestionHandoff.current.clear();
|
||||
}
|
||||
const localHandoff = rectificationQuestionHandoff.current.peek();
|
||||
const returnSession = (localHandoff
|
||||
? sessions.find((session) => session.id === localHandoff.sessionId)
|
||||
: null)
|
||||
?? (rectificationReturnSessionId
|
||||
? sessions.find((session) => session.id === rectificationReturnSessionId)
|
||||
: null)
|
||||
?? sessions.find((session) => session.sessionType === "consultation")
|
||||
?? null;
|
||||
if (!returnSession) {
|
||||
setComposerNotice("没有找到原问题所在的会话,请从会话列表打开原问题后重试。");
|
||||
return;
|
||||
}
|
||||
|
||||
rectificationContinuationInFlight.current = true;
|
||||
setRectificationContinuationPending(true);
|
||||
@@ -2647,12 +2658,8 @@ export default function Home() {
|
||||
return;
|
||||
}
|
||||
if (durableClaim.status === "consumed") {
|
||||
const returnSessionId = rectificationQuestionHandoff.current.peek()?.sessionId
|
||||
?? rectificationReturnSessionId;
|
||||
if (returnSessionId && sessions.some((session) => session.id === returnSessionId)) {
|
||||
activeSessionIdRef.current = returnSessionId;
|
||||
setActiveSessionId(returnSessionId);
|
||||
}
|
||||
activeSessionIdRef.current = returnSession.id;
|
||||
setActiveSessionId(returnSession.id);
|
||||
setRectificationPendingQuestion(null);
|
||||
setComposerNotice("原问题已经继续回答,不会再次发送或扣点。");
|
||||
return;
|
||||
@@ -2663,7 +2670,7 @@ export default function Home() {
|
||||
}
|
||||
const completed = await rectificationQuestionHandoff.current.continueOriginalQuestion(
|
||||
question,
|
||||
{ sessionId: activeSession.id, theme: activeSession.theme },
|
||||
{ sessionId: returnSession.id, theme: returnSession.theme },
|
||||
async (context) => {
|
||||
activeSessionIdRef.current = context.sessionId;
|
||||
setActiveSessionId(context.sessionId);
|
||||
@@ -2702,22 +2709,6 @@ export default function Home() {
|
||||
}
|
||||
}
|
||||
|
||||
continueRectificationQuestion.current = (question) => {
|
||||
void continueRectificationOriginalQuestion(question);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const turn = rectificationInitialTurn;
|
||||
const question = turn?.pendingConsultationQuestion;
|
||||
if (!turn || turn.status !== "completed" || !question
|
||||
|| !turn.actions.includes("continue_original_question")
|
||||
|| rectificationLoading || rectificationMutationPending) return;
|
||||
const continuationIdentity = `${turn.caseId}:${turn.turnVersion}:${question}`;
|
||||
if (automaticRectificationContinuation.current === continuationIdentity) return;
|
||||
automaticRectificationContinuation.current = continuationIdentity;
|
||||
continueRectificationQuestion.current(question);
|
||||
}, [rectificationInitialTurn, rectificationLoading, rectificationMutationPending]);
|
||||
|
||||
useGSAP(() => {
|
||||
if (!starterHomeVisible || !starterWorkbench.current) return;
|
||||
const motion = gsap.matchMedia();
|
||||
|
||||
Reference in New Issue
Block a user