@claritylabs/cl-sdk 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -1
- package/dist/index.d.mts +69 -11
- package/dist/index.d.ts +69 -11
- package/dist/index.js +199 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +195 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -6
package/dist/index.mjs
CHANGED
|
@@ -6336,7 +6336,7 @@ Respond with the explanation text only \u2014 no JSON, no field ID, no extra for
|
|
|
6336
6336
|
}
|
|
6337
6337
|
|
|
6338
6338
|
// src/prompts/query/classify.ts
|
|
6339
|
-
function buildQueryClassifyPrompt(question, conversationContext) {
|
|
6339
|
+
function buildQueryClassifyPrompt(question, conversationContext, attachmentContext) {
|
|
6340
6340
|
return `You are a query classifier for an insurance document intelligence system.
|
|
6341
6341
|
|
|
6342
6342
|
Analyze the user's question and produce a structured classification.
|
|
@@ -6346,6 +6346,9 @@ ${question}
|
|
|
6346
6346
|
${conversationContext ? `
|
|
6347
6347
|
CONVERSATION CONTEXT:
|
|
6348
6348
|
${conversationContext}` : ""}
|
|
6349
|
+
${attachmentContext ? `
|
|
6350
|
+
ATTACHMENT CONTEXT:
|
|
6351
|
+
${attachmentContext}` : ""}
|
|
6349
6352
|
|
|
6350
6353
|
INSTRUCTIONS:
|
|
6351
6354
|
|
|
@@ -6366,6 +6369,7 @@ INSTRUCTIONS:
|
|
|
6366
6369
|
- requiresDocumentLookup: true if a specific document needs to be fetched by ID/number/carrier
|
|
6367
6370
|
- requiresChunkSearch: true if semantic search over document chunks is needed
|
|
6368
6371
|
- requiresConversationHistory: true if the question references prior conversation
|
|
6372
|
+
- If the user's attachment already contains critical facts, still request chunk/document lookup when policy or quote details should be cross-checked against stored records
|
|
6369
6373
|
|
|
6370
6374
|
CHUNK TYPES (for chunkTypes filter):
|
|
6371
6375
|
carrier_info, named_insured, coverage, endorsement, exclusion, condition, section, declaration, loss_history, premium, supplementary
|
|
@@ -6407,6 +6411,16 @@ var QueryIntentSchema = z35.enum([
|
|
|
6407
6411
|
"claims_inquiry",
|
|
6408
6412
|
"general_knowledge"
|
|
6409
6413
|
]);
|
|
6414
|
+
var QueryAttachmentKindSchema = z35.enum(["image", "pdf", "text"]);
|
|
6415
|
+
var QueryAttachmentSchema = z35.object({
|
|
6416
|
+
id: z35.string().optional().describe("Optional stable attachment ID from the caller"),
|
|
6417
|
+
kind: QueryAttachmentKindSchema,
|
|
6418
|
+
name: z35.string().optional().describe("Original filename or user-facing label"),
|
|
6419
|
+
mimeType: z35.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
|
|
6420
|
+
base64: z35.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
|
|
6421
|
+
text: z35.string().optional().describe("Plain-text attachment content when available"),
|
|
6422
|
+
description: z35.string().optional().describe("Caller-provided description of the attachment")
|
|
6423
|
+
});
|
|
6410
6424
|
var SubQuestionSchema = z35.object({
|
|
6411
6425
|
question: z35.string().describe("Atomic sub-question to retrieve and answer independently"),
|
|
6412
6426
|
intent: QueryIntentSchema,
|
|
@@ -6427,14 +6441,21 @@ var QueryClassifyResultSchema = z35.object({
|
|
|
6427
6441
|
requiresConversationHistory: z35.boolean().describe("Whether conversation history is relevant")
|
|
6428
6442
|
});
|
|
6429
6443
|
var EvidenceItemSchema = z35.object({
|
|
6430
|
-
source: z35.enum(["chunk", "document", "conversation"]),
|
|
6444
|
+
source: z35.enum(["chunk", "document", "conversation", "attachment"]),
|
|
6431
6445
|
chunkId: z35.string().optional(),
|
|
6432
6446
|
documentId: z35.string().optional(),
|
|
6433
6447
|
turnId: z35.string().optional(),
|
|
6448
|
+
attachmentId: z35.string().optional(),
|
|
6434
6449
|
text: z35.string().describe("Text excerpt from the source"),
|
|
6435
6450
|
relevance: z35.number().min(0).max(1),
|
|
6436
6451
|
metadata: z35.array(z35.object({ key: z35.string(), value: z35.string() })).optional()
|
|
6437
6452
|
});
|
|
6453
|
+
var AttachmentInterpretationSchema = z35.object({
|
|
6454
|
+
summary: z35.string().describe("Concise summary of what the attachment shows or contains"),
|
|
6455
|
+
extractedFacts: z35.array(z35.string()).describe("Specific observable or document facts grounded in the attachment"),
|
|
6456
|
+
recommendedFocus: z35.array(z35.string()).describe("Important details to incorporate when answering follow-up questions"),
|
|
6457
|
+
confidence: z35.number().min(0).max(1)
|
|
6458
|
+
});
|
|
6438
6459
|
var RetrievalResultSchema = z35.object({
|
|
6439
6460
|
subQuestion: z35.string(),
|
|
6440
6461
|
evidence: z35.array(EvidenceItemSchema)
|
|
@@ -6755,7 +6776,7 @@ async function verify(originalQuestion, subAnswers, allEvidence, config) {
|
|
|
6755
6776
|
|
|
6756
6777
|
// src/query/quality.ts
|
|
6757
6778
|
function sourceIdForEvidence(evidence) {
|
|
6758
|
-
return evidence.chunkId ?? evidence.documentId ?? evidence.turnId;
|
|
6779
|
+
return evidence.chunkId ?? evidence.documentId ?? evidence.turnId ?? evidence.attachmentId;
|
|
6759
6780
|
}
|
|
6760
6781
|
function citationSourceId(citation) {
|
|
6761
6782
|
return citation.chunkId || citation.documentId;
|
|
@@ -6859,6 +6880,152 @@ function buildQueryReviewReport(params) {
|
|
|
6859
6880
|
};
|
|
6860
6881
|
}
|
|
6861
6882
|
|
|
6883
|
+
// src/prompts/query/interpret-attachment.ts
|
|
6884
|
+
function buildInterpretAttachmentPrompt(question, attachment) {
|
|
6885
|
+
const attachmentLabel = attachment.name ?? attachment.id ?? "attachment";
|
|
6886
|
+
const descriptor = [
|
|
6887
|
+
`Attachment: ${attachmentLabel}`,
|
|
6888
|
+
`Kind: ${attachment.kind}`,
|
|
6889
|
+
attachment.mimeType ? `MIME type: ${attachment.mimeType}` : null,
|
|
6890
|
+
attachment.description ? `Caller description: ${attachment.description}` : null
|
|
6891
|
+
].filter(Boolean).join("\n");
|
|
6892
|
+
return `You are interpreting a user-supplied attachment for an insurance-support question.
|
|
6893
|
+
|
|
6894
|
+
USER QUESTION:
|
|
6895
|
+
${question}
|
|
6896
|
+
|
|
6897
|
+
ATTACHMENT METADATA:
|
|
6898
|
+
${descriptor}
|
|
6899
|
+
|
|
6900
|
+
${attachment.kind === "text" && attachment.text ? `ATTACHMENT TEXT:
|
|
6901
|
+
${attachment.text}
|
|
6902
|
+
` : "The attachment content is provided separately as a file or image input.\n"}
|
|
6903
|
+
INSTRUCTIONS:
|
|
6904
|
+
1. Describe what the attachment appears to show or contain in a concise summary.
|
|
6905
|
+
2. Extract concrete facts that may matter when answering the user's question.
|
|
6906
|
+
3. Note the most important details to carry forward into follow-up questions.
|
|
6907
|
+
4. If the attachment is a document, identify the key business or insurance details visible.
|
|
6908
|
+
5. If the attachment is a photo of damage or a real-world issue, describe the observable issue without guessing beyond what is visible.
|
|
6909
|
+
6. Do not invent unreadable text. If something is unclear, say so in the summary or extracted facts.
|
|
6910
|
+
|
|
6911
|
+
Respond with the structured interpretation.`;
|
|
6912
|
+
}
|
|
6913
|
+
|
|
6914
|
+
// src/query/multimodal.ts
|
|
6915
|
+
function attachmentSourceId(attachment, index) {
|
|
6916
|
+
return attachment.id ?? `attachment-${index + 1}`;
|
|
6917
|
+
}
|
|
6918
|
+
function buildAttachmentProviderOptions(attachment, providerOptions) {
|
|
6919
|
+
const merged = {
|
|
6920
|
+
...providerOptions,
|
|
6921
|
+
attachments: [
|
|
6922
|
+
{
|
|
6923
|
+
kind: attachment.kind,
|
|
6924
|
+
name: attachment.name,
|
|
6925
|
+
mimeType: attachment.mimeType,
|
|
6926
|
+
base64: attachment.base64,
|
|
6927
|
+
text: attachment.text,
|
|
6928
|
+
description: attachment.description
|
|
6929
|
+
}
|
|
6930
|
+
]
|
|
6931
|
+
};
|
|
6932
|
+
if (attachment.kind === "pdf" && attachment.base64) {
|
|
6933
|
+
merged.pdfBase64 = attachment.base64;
|
|
6934
|
+
}
|
|
6935
|
+
if (attachment.kind === "image" && attachment.base64) {
|
|
6936
|
+
merged.images = [
|
|
6937
|
+
{
|
|
6938
|
+
imageBase64: attachment.base64,
|
|
6939
|
+
mimeType: attachment.mimeType ?? "image/jpeg"
|
|
6940
|
+
}
|
|
6941
|
+
];
|
|
6942
|
+
}
|
|
6943
|
+
return merged;
|
|
6944
|
+
}
|
|
6945
|
+
function buildAttachmentEvidenceText(attachment, interpretation) {
|
|
6946
|
+
const lines = [
|
|
6947
|
+
`Attachment kind: ${attachment.kind}`,
|
|
6948
|
+
attachment.name ? `Attachment name: ${attachment.name}` : null,
|
|
6949
|
+
attachment.mimeType ? `MIME type: ${attachment.mimeType}` : null,
|
|
6950
|
+
attachment.description ? `Caller description: ${attachment.description}` : null,
|
|
6951
|
+
`Summary: ${interpretation.summary}`,
|
|
6952
|
+
interpretation.extractedFacts.length > 0 ? `Extracted facts:
|
|
6953
|
+
${interpretation.extractedFacts.map((fact) => `- ${fact}`).join("\n")}` : null,
|
|
6954
|
+
interpretation.recommendedFocus.length > 0 ? `Important follow-up details:
|
|
6955
|
+
${interpretation.recommendedFocus.map((item) => `- ${item}`).join("\n")}` : null,
|
|
6956
|
+
attachment.kind === "text" && attachment.text ? `Original text:
|
|
6957
|
+
${attachment.text}` : null
|
|
6958
|
+
];
|
|
6959
|
+
return lines.filter(Boolean).join("\n");
|
|
6960
|
+
}
|
|
6961
|
+
async function interpretAttachments(params) {
|
|
6962
|
+
const { attachments = [], question, generateObject, providerOptions, log, onUsage } = params;
|
|
6963
|
+
if (attachments.length === 0) {
|
|
6964
|
+
return { evidence: [] };
|
|
6965
|
+
}
|
|
6966
|
+
const evidence = [];
|
|
6967
|
+
for (const [index, attachment] of attachments.entries()) {
|
|
6968
|
+
const id = attachmentSourceId(attachment, index);
|
|
6969
|
+
if (attachment.kind === "text" && attachment.text) {
|
|
6970
|
+
const textEvidence = buildAttachmentEvidenceText(attachment, {
|
|
6971
|
+
summary: attachment.description ?? "User supplied text context.",
|
|
6972
|
+
extractedFacts: [attachment.text],
|
|
6973
|
+
recommendedFocus: [],
|
|
6974
|
+
confidence: 1
|
|
6975
|
+
});
|
|
6976
|
+
evidence.push({
|
|
6977
|
+
source: "attachment",
|
|
6978
|
+
attachmentId: id,
|
|
6979
|
+
chunkId: id,
|
|
6980
|
+
documentId: id,
|
|
6981
|
+
text: textEvidence,
|
|
6982
|
+
relevance: 0.95,
|
|
6983
|
+
metadata: [
|
|
6984
|
+
{ key: "kind", value: attachment.kind },
|
|
6985
|
+
...attachment.name ? [{ key: "name", value: attachment.name }] : []
|
|
6986
|
+
]
|
|
6987
|
+
});
|
|
6988
|
+
continue;
|
|
6989
|
+
}
|
|
6990
|
+
const prompt = buildInterpretAttachmentPrompt(question, attachment);
|
|
6991
|
+
const { object, usage } = await safeGenerateObject(
|
|
6992
|
+
generateObject,
|
|
6993
|
+
{
|
|
6994
|
+
prompt,
|
|
6995
|
+
schema: AttachmentInterpretationSchema,
|
|
6996
|
+
maxTokens: 2048,
|
|
6997
|
+
providerOptions: buildAttachmentProviderOptions(attachment, providerOptions)
|
|
6998
|
+
},
|
|
6999
|
+
{
|
|
7000
|
+
fallback: {
|
|
7001
|
+
summary: attachment.description ?? `User supplied ${attachment.kind} attachment.`,
|
|
7002
|
+
extractedFacts: [],
|
|
7003
|
+
recommendedFocus: [],
|
|
7004
|
+
confidence: 0.2
|
|
7005
|
+
},
|
|
7006
|
+
log,
|
|
7007
|
+
onError: (error, attempt) => log?.(`Attachment interpretation attempt ${attempt + 1} failed for "${attachment.name ?? id}": ${error}`)
|
|
7008
|
+
}
|
|
7009
|
+
);
|
|
7010
|
+
onUsage?.(usage);
|
|
7011
|
+
evidence.push({
|
|
7012
|
+
source: "attachment",
|
|
7013
|
+
attachmentId: id,
|
|
7014
|
+
chunkId: id,
|
|
7015
|
+
documentId: id,
|
|
7016
|
+
text: buildAttachmentEvidenceText(attachment, object),
|
|
7017
|
+
relevance: Math.max(0.7, object.confidence),
|
|
7018
|
+
metadata: [
|
|
7019
|
+
{ key: "kind", value: attachment.kind },
|
|
7020
|
+
...attachment.name ? [{ key: "name", value: attachment.name }] : []
|
|
7021
|
+
]
|
|
7022
|
+
});
|
|
7023
|
+
}
|
|
7024
|
+
const contextSummary = evidence.map((item, index) => `Attachment ${index + 1}:
|
|
7025
|
+
${item.text}`).join("\n\n");
|
|
7026
|
+
return { evidence, contextSummary };
|
|
7027
|
+
}
|
|
7028
|
+
|
|
6862
7029
|
// src/query/coordinator.ts
|
|
6863
7030
|
function createQueryAgent(config) {
|
|
6864
7031
|
const {
|
|
@@ -6886,13 +7053,23 @@ function createQueryAgent(config) {
|
|
|
6886
7053
|
}
|
|
6887
7054
|
async function query(input) {
|
|
6888
7055
|
totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
6889
|
-
const { question, conversationId, context } = input;
|
|
7056
|
+
const { question, conversationId, context, attachments } = input;
|
|
6890
7057
|
const pipelineCtx = createPipelineContext({
|
|
6891
7058
|
id: `query-${Date.now()}`
|
|
6892
7059
|
});
|
|
7060
|
+
onProgress?.("Interpreting attachments...");
|
|
7061
|
+
const { evidence: attachmentEvidence, contextSummary: attachmentContext } = await interpretAttachments({
|
|
7062
|
+
attachments,
|
|
7063
|
+
question,
|
|
7064
|
+
generateObject,
|
|
7065
|
+
providerOptions,
|
|
7066
|
+
log,
|
|
7067
|
+
onUsage: trackUsage
|
|
7068
|
+
});
|
|
7069
|
+
await pipelineCtx.save("attachments", { attachmentEvidence });
|
|
6893
7070
|
onProgress?.("Classifying query...");
|
|
6894
|
-
const classification = await classify(question, conversationId);
|
|
6895
|
-
await pipelineCtx.save("classify", { classification });
|
|
7071
|
+
const classification = await classify(question, conversationId, attachmentContext);
|
|
7072
|
+
await pipelineCtx.save("classify", { classification, attachmentEvidence });
|
|
6896
7073
|
onProgress?.(`Retrieving evidence for ${classification.subQuestions.length} sub-question(s)...`);
|
|
6897
7074
|
const retrieverConfig = {
|
|
6898
7075
|
documentStore,
|
|
@@ -6905,8 +7082,8 @@ function createQueryAgent(config) {
|
|
|
6905
7082
|
(sq) => limit(() => retrieve(sq, conversationId, retrieverConfig))
|
|
6906
7083
|
)
|
|
6907
7084
|
);
|
|
6908
|
-
const allEvidence = retrievalResults.flatMap((r) => r.evidence);
|
|
6909
|
-
await pipelineCtx.save("retrieve", { classification, evidence: allEvidence });
|
|
7085
|
+
const allEvidence = [...attachmentEvidence, ...retrievalResults.flatMap((r) => r.evidence)];
|
|
7086
|
+
await pipelineCtx.save("retrieve", { classification, attachmentEvidence, evidence: allEvidence });
|
|
6910
7087
|
onProgress?.("Reasoning over evidence...");
|
|
6911
7088
|
const reasonerConfig = { generateObject, providerOptions };
|
|
6912
7089
|
const reasonResults = await Promise.allSettled(
|
|
@@ -6915,7 +7092,7 @@ function createQueryAgent(config) {
|
|
|
6915
7092
|
const { subAnswer, usage } = await reason(
|
|
6916
7093
|
sq.question,
|
|
6917
7094
|
sq.intent,
|
|
6918
|
-
retrievalResults[i].evidence,
|
|
7095
|
+
[...attachmentEvidence, ...retrievalResults[i].evidence],
|
|
6919
7096
|
reasonerConfig
|
|
6920
7097
|
);
|
|
6921
7098
|
trackUsage(usage);
|
|
@@ -6939,7 +7116,7 @@ function createQueryAgent(config) {
|
|
|
6939
7116
|
});
|
|
6940
7117
|
}
|
|
6941
7118
|
}
|
|
6942
|
-
await pipelineCtx.save("reason", { classification, evidence: allEvidence, subAnswers });
|
|
7119
|
+
await pipelineCtx.save("reason", { classification, attachmentEvidence, evidence: allEvidence, subAnswers });
|
|
6943
7120
|
onProgress?.("Verifying answer grounding...");
|
|
6944
7121
|
const verifierConfig = { generateObject, providerOptions };
|
|
6945
7122
|
const verifyRounds = [];
|
|
@@ -6987,7 +7164,7 @@ function createQueryAgent(config) {
|
|
|
6987
7164
|
const { subAnswer, usage: u } = await reason(
|
|
6988
7165
|
sq.question,
|
|
6989
7166
|
sq.intent,
|
|
6990
|
-
retryRetrievals[i].evidence,
|
|
7167
|
+
[...attachmentEvidence, ...retryRetrievals[i].evidence],
|
|
6991
7168
|
reasonerConfig
|
|
6992
7169
|
);
|
|
6993
7170
|
trackUsage(u);
|
|
@@ -7022,6 +7199,7 @@ function createQueryAgent(config) {
|
|
|
7022
7199
|
});
|
|
7023
7200
|
await pipelineCtx.save("review", {
|
|
7024
7201
|
classification,
|
|
7202
|
+
attachmentEvidence,
|
|
7025
7203
|
evidence: allEvidence,
|
|
7026
7204
|
subAnswers,
|
|
7027
7205
|
reviewReport
|
|
@@ -7054,7 +7232,7 @@ function createQueryAgent(config) {
|
|
|
7054
7232
|
}
|
|
7055
7233
|
return { ...queryResult, tokenUsage: totalUsage, reviewReport };
|
|
7056
7234
|
}
|
|
7057
|
-
async function classify(question, conversationId) {
|
|
7235
|
+
async function classify(question, conversationId, attachmentContext) {
|
|
7058
7236
|
let conversationContext;
|
|
7059
7237
|
if (conversationId) {
|
|
7060
7238
|
try {
|
|
@@ -7065,7 +7243,7 @@ function createQueryAgent(config) {
|
|
|
7065
7243
|
} catch {
|
|
7066
7244
|
}
|
|
7067
7245
|
}
|
|
7068
|
-
const prompt = buildQueryClassifyPrompt(question, conversationContext);
|
|
7246
|
+
const prompt = buildQueryClassifyPrompt(question, conversationContext, attachmentContext);
|
|
7069
7247
|
const { object, usage } = await safeGenerateObject(
|
|
7070
7248
|
generateObject,
|
|
7071
7249
|
{
|
|
@@ -7280,6 +7458,7 @@ export {
|
|
|
7280
7458
|
ApplicationQualityReportSchema,
|
|
7281
7459
|
ApplicationQualityRoundSchema,
|
|
7282
7460
|
ApplicationStateSchema,
|
|
7461
|
+
AttachmentInterpretationSchema,
|
|
7283
7462
|
AuditTypeSchema,
|
|
7284
7463
|
AutoFillMatchSchema,
|
|
7285
7464
|
AutoFillResultSchema,
|
|
@@ -7401,6 +7580,8 @@ export {
|
|
|
7401
7580
|
ProducerInfoSchema,
|
|
7402
7581
|
ProfessionalLiabilityDeclarationsSchema,
|
|
7403
7582
|
QUOTE_SECTION_TYPES,
|
|
7583
|
+
QueryAttachmentKindSchema,
|
|
7584
|
+
QueryAttachmentSchema,
|
|
7404
7585
|
QueryClassifyResultSchema,
|
|
7405
7586
|
QueryIntentSchema,
|
|
7406
7587
|
QueryResultSchema,
|
|
@@ -7459,6 +7640,7 @@ export {
|
|
|
7459
7640
|
buildFormattingPrompt,
|
|
7460
7641
|
buildIdentityPrompt,
|
|
7461
7642
|
buildIntentPrompt,
|
|
7643
|
+
buildInterpretAttachmentPrompt,
|
|
7462
7644
|
buildLookupFillPrompt,
|
|
7463
7645
|
buildQueryClassifyPrompt,
|
|
7464
7646
|
buildQuestionBatchPrompt,
|