@absolutejs/absolute 0.19.0-beta.525 → 0.19.0-beta.527
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/dist/ai/client/index.js +5 -5
- package/dist/ai/client/index.js.map +1 -1
- package/dist/ai/index.js +4 -4
- package/dist/ai/index.js.map +1 -1
- package/dist/ai-client/angular/ai/index.js +880 -862
- package/dist/ai-client/react/ai/index.js +24 -24
- package/dist/ai-client/vue/ai/index.js +21 -21
- package/dist/angular/ai/index.js +873 -855
- package/dist/angular/ai/index.js.map +7 -6
- package/dist/angular/index.js +2 -2
- package/dist/angular/index.js.map +1 -1
- package/dist/angular/server.js +2 -2
- package/dist/angular/server.js.map +1 -1
- package/dist/build.js +2 -2
- package/dist/build.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react/ai/index.js +25 -25
- package/dist/react/ai/index.js.map +6 -6
- package/dist/src/ai/client/createRAGStream.d.ts +2 -0
- package/dist/src/ai/client/createRAGWorkflow.d.ts +3 -0
- package/dist/src/ai/client/index.d.ts +8 -7
- package/dist/src/ai/index.d.ts +5 -4
- package/dist/src/ai/rag/index.d.ts +2 -2
- package/dist/src/angular/ai/ai-rag-stream.service.d.ts +1 -1
- package/dist/src/angular/ai/ai-rag-workflow.service.d.ts +33 -0
- package/dist/src/angular/ai/index.d.ts +2 -1
- package/dist/src/react/ai/index.d.ts +6 -3
- package/dist/src/react/ai/useRAG.d.ts +3 -2
- package/dist/src/svelte/ai/createRAG.d.ts +5 -4
- package/dist/src/svelte/ai/createRAGStream.d.ts +1 -1
- package/dist/src/svelte/ai/createRAGStreamProgress.d.ts +1 -1
- package/dist/src/svelte/ai/createRAGWorkflow.d.ts +1 -1
- package/dist/src/svelte/ai/index.d.ts +4 -2
- package/dist/src/vue/ai/index.d.ts +5 -3
- package/dist/src/vue/ai/useRAG.d.ts +5 -4
- package/dist/src/vue/ai/useRAGStream.d.ts +1 -1
- package/dist/src/vue/ai/useRAGStreamProgress.d.ts +1 -1
- package/dist/src/vue/ai/useRAGWorkflow.d.ts +1 -1
- package/dist/svelte/ai/index.js +22 -22
- package/dist/svelte/ai/index.js.map +5 -5
- package/dist/vue/ai/index.js +22 -22
- package/dist/vue/ai/index.js.map +6 -6
- package/package.json +7 -7
- package/dist/src/ai/client/createRAGTransport.d.ts +0 -2
- package/dist/src/angular/ai/ai-rag-transport.service.d.ts +0 -1
- package/dist/src/react/ai/useRAGTransport.d.ts +0 -2
- package/dist/src/react/ai/useRAGTransportProgress.d.ts +0 -2
- package/dist/src/svelte/ai/createRAGTransport.d.ts +0 -2
- package/dist/src/svelte/ai/createRAGTransportProgress.d.ts +0 -2
- package/dist/src/vue/ai/useRAGTransport.d.ts +0 -2
- package/dist/src/vue/ai/useRAGTransportProgress.d.ts +0 -2
|
@@ -703,917 +703,935 @@ class AIStreamService {
|
|
|
703
703
|
AIStreamService = __legacyDecorateClassTS([
|
|
704
704
|
Injectable({ providedIn: "root" })
|
|
705
705
|
], AIStreamService);
|
|
706
|
-
// src/angular/ai/rag-
|
|
707
|
-
import { Injectable as
|
|
706
|
+
// src/angular/ai/ai-rag-workflow.service.ts
|
|
707
|
+
import { computed as computed3, Injectable as Injectable3 } from "@angular/core";
|
|
708
708
|
|
|
709
|
-
// src/
|
|
710
|
-
|
|
711
|
-
var MILLISECONDS_IN_A_SECOND = 1000;
|
|
712
|
-
var MINUTES_IN_AN_HOUR = 60;
|
|
713
|
-
var SECONDS_IN_A_MINUTE = 60;
|
|
714
|
-
var MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
|
|
715
|
-
var MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
|
|
716
|
-
var TWO_THIRDS = 2 / 3;
|
|
717
|
-
var UNFOUND_INDEX = -1;
|
|
709
|
+
// src/angular/ai/ai-rag-stream.service.ts
|
|
710
|
+
import { computed as computed2, Injectable as Injectable2 } from "@angular/core";
|
|
718
711
|
|
|
719
|
-
// src/ai/
|
|
720
|
-
var
|
|
721
|
-
|
|
712
|
+
// src/ai/rag/presentation.ts
|
|
713
|
+
var buildSourceGroupKey = (source) => source.source ?? source.title ?? source.chunkId;
|
|
714
|
+
var buildSourceLabel = (source) => source.source ?? source.title ?? source.chunkId;
|
|
715
|
+
var getContextNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
716
|
+
var getContextString = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
717
|
+
var formatTimestampLabel = (value) => {
|
|
718
|
+
const timestamp = typeof value === "number" && Number.isFinite(value) ? value : typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
719
|
+
if (!Number.isFinite(timestamp)) {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
return new Date(timestamp).toLocaleString("en-US", {
|
|
723
|
+
dateStyle: "medium",
|
|
724
|
+
timeStyle: "short"
|
|
725
|
+
});
|
|
722
726
|
};
|
|
723
|
-
var
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
+
var formatMediaTimestamp = (value) => {
|
|
728
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const totalSeconds = Math.floor(value / 1000);
|
|
732
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
733
|
+
const seconds = totalSeconds % 60;
|
|
734
|
+
const milliseconds = Math.floor(value % 1000);
|
|
735
|
+
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(milliseconds).padStart(3, "0")}`;
|
|
727
736
|
};
|
|
728
|
-
var
|
|
729
|
-
|
|
730
|
-
|
|
737
|
+
var getAttachmentName = (source, title) => {
|
|
738
|
+
const sourceAttachment = source?.split("/").at(-1);
|
|
739
|
+
if (sourceAttachment && sourceAttachment.includes(".")) {
|
|
740
|
+
return sourceAttachment;
|
|
731
741
|
}
|
|
732
|
-
|
|
742
|
+
const titleAttachment = title?.split(" · ").at(-1);
|
|
743
|
+
if (titleAttachment && titleAttachment.includes(".")) {
|
|
744
|
+
return titleAttachment;
|
|
745
|
+
}
|
|
746
|
+
return;
|
|
733
747
|
};
|
|
734
|
-
var
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
748
|
+
var buildContextLabel = (metadata) => {
|
|
749
|
+
if (!metadata) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const emailKind = getContextString(metadata.emailKind);
|
|
753
|
+
if (emailKind === "attachment") {
|
|
754
|
+
return "Attachment evidence";
|
|
755
|
+
}
|
|
756
|
+
if (emailKind === "message") {
|
|
757
|
+
const from = getContextString(metadata.from);
|
|
758
|
+
return from ? `Message from ${from}` : "Message evidence";
|
|
759
|
+
}
|
|
760
|
+
const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
|
|
761
|
+
if (page) {
|
|
762
|
+
return `Page ${page}`;
|
|
763
|
+
}
|
|
764
|
+
const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
|
|
765
|
+
if (sheet) {
|
|
766
|
+
return `Sheet ${sheet}`;
|
|
767
|
+
}
|
|
768
|
+
const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
|
|
769
|
+
if (slide) {
|
|
770
|
+
return `Slide ${slide}`;
|
|
771
|
+
}
|
|
772
|
+
const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
|
|
773
|
+
if (archiveEntry) {
|
|
774
|
+
return `Archive entry ${archiveEntry}`;
|
|
775
|
+
}
|
|
776
|
+
const threadTopic = getContextString(metadata.threadTopic);
|
|
777
|
+
if (threadTopic) {
|
|
778
|
+
return `Thread ${threadTopic}`;
|
|
779
|
+
}
|
|
780
|
+
const speaker = getContextString(metadata.speaker);
|
|
781
|
+
if (speaker) {
|
|
782
|
+
return `Speaker ${speaker}`;
|
|
783
|
+
}
|
|
784
|
+
return;
|
|
785
|
+
};
|
|
786
|
+
var buildLocatorLabel = (metadata, source, title) => {
|
|
787
|
+
if (!metadata) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
|
|
791
|
+
if (page) {
|
|
792
|
+
return `Page ${page}`;
|
|
793
|
+
}
|
|
794
|
+
const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
|
|
795
|
+
if (sheet) {
|
|
796
|
+
return `Sheet ${sheet}`;
|
|
797
|
+
}
|
|
798
|
+
const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
|
|
799
|
+
if (slide) {
|
|
800
|
+
return `Slide ${slide}`;
|
|
801
|
+
}
|
|
802
|
+
const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
|
|
803
|
+
if (archiveEntry) {
|
|
804
|
+
return `Archive entry ${archiveEntry}`;
|
|
805
|
+
}
|
|
806
|
+
const emailKind = getContextString(metadata.emailKind);
|
|
807
|
+
if (emailKind === "attachment") {
|
|
808
|
+
const attachmentName = getContextString(metadata.attachmentName) ?? getAttachmentName(source, title);
|
|
809
|
+
return attachmentName ? `Attachment ${attachmentName}` : "Attachment";
|
|
810
|
+
}
|
|
811
|
+
const mediaStart = formatMediaTimestamp(metadata.startMs);
|
|
812
|
+
const mediaEnd = formatMediaTimestamp(metadata.endMs);
|
|
813
|
+
if (mediaStart && mediaEnd) {
|
|
814
|
+
return `Timestamp ${mediaStart} - ${mediaEnd}`;
|
|
815
|
+
}
|
|
816
|
+
if (mediaStart) {
|
|
817
|
+
return `Timestamp ${mediaStart}`;
|
|
818
|
+
}
|
|
819
|
+
return;
|
|
820
|
+
};
|
|
821
|
+
var buildProvenanceLabel = (metadata) => {
|
|
822
|
+
if (!metadata) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
const threadTopic = getContextString(metadata.threadTopic);
|
|
826
|
+
const from = getContextString(metadata.from);
|
|
827
|
+
const sentAt = formatTimestampLabel(metadata.sentAt) ?? formatTimestampLabel(metadata.receivedAt);
|
|
828
|
+
const speaker = getContextString(metadata.speaker);
|
|
829
|
+
const mediaKind = getContextString(metadata.mediaKind);
|
|
830
|
+
const transcriptSource = getContextString(metadata.transcriptSource);
|
|
831
|
+
const pdfTextMode = getContextString(metadata.pdfTextMode);
|
|
832
|
+
const ocrEngine = getContextString(metadata.ocrEngine);
|
|
833
|
+
const labels = [
|
|
834
|
+
pdfTextMode ? `PDF ${pdfTextMode}` : "",
|
|
835
|
+
ocrEngine ? `OCR ${ocrEngine}` : "",
|
|
836
|
+
mediaKind ? `Media ${mediaKind}` : "",
|
|
837
|
+
transcriptSource ? `Transcript ${transcriptSource}` : "",
|
|
838
|
+
threadTopic ? `Thread ${threadTopic}` : "",
|
|
839
|
+
speaker ? `Speaker ${speaker}` : "",
|
|
840
|
+
from ? `Sender ${from}` : "",
|
|
841
|
+
sentAt ? `Sent ${sentAt}` : ""
|
|
842
|
+
].filter((value) => value.length > 0);
|
|
843
|
+
return labels.length > 0 ? labels.join(" · ") : undefined;
|
|
844
|
+
};
|
|
845
|
+
var buildRAGCitationReferenceMap = (citations) => Object.fromEntries(citations.map((citation, index) => [citation.chunkId, index + 1]));
|
|
846
|
+
var buildRAGCitations = (sources) => {
|
|
847
|
+
const unique = new Map;
|
|
848
|
+
for (const source of sources) {
|
|
849
|
+
const key = source.chunkId;
|
|
850
|
+
const existing = unique.get(key);
|
|
851
|
+
const hasBetterExisting = existing !== undefined && existing.score >= source.score;
|
|
852
|
+
if (hasBetterExisting)
|
|
853
|
+
continue;
|
|
854
|
+
unique.set(key, {
|
|
855
|
+
chunkId: source.chunkId,
|
|
856
|
+
contextLabel: buildContextLabel(source.metadata),
|
|
857
|
+
key,
|
|
858
|
+
label: buildSourceLabel(source),
|
|
859
|
+
locatorLabel: buildLocatorLabel(source.metadata, source.source, source.title),
|
|
860
|
+
metadata: source.metadata,
|
|
861
|
+
provenanceLabel: buildProvenanceLabel(source.metadata),
|
|
862
|
+
score: source.score,
|
|
863
|
+
source: source.source,
|
|
864
|
+
text: source.text,
|
|
865
|
+
title: source.title
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
return [...unique.values()].sort((left, right) => {
|
|
869
|
+
if (right.score !== left.score) {
|
|
870
|
+
return right.score - left.score;
|
|
739
871
|
}
|
|
740
|
-
|
|
741
|
-
|
|
872
|
+
return left.label.localeCompare(right.label);
|
|
873
|
+
});
|
|
742
874
|
};
|
|
743
|
-
var
|
|
744
|
-
const
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
875
|
+
var buildExcerpt = (text, maxLength = 160) => {
|
|
876
|
+
const normalized = text.replaceAll(/\s+/g, " ").trim();
|
|
877
|
+
if (normalized.length <= maxLength) {
|
|
878
|
+
return normalized;
|
|
879
|
+
}
|
|
880
|
+
return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
|
|
881
|
+
};
|
|
882
|
+
var buildGroundingReferenceEvidenceLabel = (reference) => [reference.label, reference.locatorLabel, reference.contextLabel].filter((value) => Boolean(value && value.length > 0)).filter((value, index, values) => values.findIndex((entry) => entry === value) === index).join(" · ");
|
|
883
|
+
var buildGroundingReferenceEvidenceSummary = (reference) => [
|
|
884
|
+
reference.source ?? reference.title ?? reference.chunkId,
|
|
885
|
+
reference.provenanceLabel
|
|
886
|
+
].filter((value) => Boolean(value && value.length > 0)).join(" · ");
|
|
887
|
+
var buildGroundedAnswerCitationDetail = (reference) => ({
|
|
888
|
+
contextLabel: reference.contextLabel,
|
|
889
|
+
evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
|
|
890
|
+
evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
|
|
891
|
+
excerpt: reference.excerpt,
|
|
892
|
+
label: reference.label,
|
|
893
|
+
locatorLabel: reference.locatorLabel,
|
|
894
|
+
number: reference.number,
|
|
895
|
+
provenanceLabel: reference.provenanceLabel,
|
|
896
|
+
source: reference.source,
|
|
897
|
+
title: reference.title
|
|
898
|
+
});
|
|
899
|
+
var buildRAGGroundedAnswer = (content, sources) => {
|
|
900
|
+
const references = buildRAGGroundingReferences(sources);
|
|
901
|
+
const referenceMap = new Map(references.map((reference) => [reference.number, reference]));
|
|
902
|
+
const parts = [];
|
|
903
|
+
const ungroundedReferenceNumbers = new Set;
|
|
904
|
+
const citationPattern = /\[(\d+(?:\s*,\s*\d+)*)\]/g;
|
|
905
|
+
let cursor = 0;
|
|
906
|
+
for (const match of content.matchAll(citationPattern)) {
|
|
907
|
+
const raw = match[0];
|
|
908
|
+
const numbers = (match[1] ?? "").split(",").map((value) => Number.parseInt(value.trim(), 10)).filter((value) => Number.isInteger(value) && value > 0);
|
|
909
|
+
const start = match.index ?? cursor;
|
|
910
|
+
if (start > cursor) {
|
|
911
|
+
parts.push({
|
|
912
|
+
text: content.slice(cursor, start),
|
|
913
|
+
type: "text"
|
|
757
914
|
});
|
|
758
|
-
|
|
759
|
-
|
|
915
|
+
}
|
|
916
|
+
const resolvedReferences = numbers.map((number) => referenceMap.get(number)).filter((reference) => Boolean(reference));
|
|
917
|
+
for (const number of numbers) {
|
|
918
|
+
if (!referenceMap.has(number)) {
|
|
919
|
+
ungroundedReferenceNumbers.add(number);
|
|
760
920
|
}
|
|
761
|
-
return parseJson(response);
|
|
762
|
-
},
|
|
763
|
-
async createDocument(input) {
|
|
764
|
-
const response = await fetchImpl(`${basePath}/documents`, {
|
|
765
|
-
body: JSON.stringify(input),
|
|
766
|
-
headers: jsonHeaders,
|
|
767
|
-
method: "POST"
|
|
768
|
-
});
|
|
769
|
-
if (!response.ok) {
|
|
770
|
-
return {
|
|
771
|
-
error: await toErrorMessage(response),
|
|
772
|
-
ok: false
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
return parseJson(response);
|
|
776
|
-
},
|
|
777
|
-
async deleteDocument(id) {
|
|
778
|
-
const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}`, {
|
|
779
|
-
method: "DELETE"
|
|
780
|
-
});
|
|
781
|
-
if (!response.ok) {
|
|
782
|
-
return {
|
|
783
|
-
error: await toErrorMessage(response),
|
|
784
|
-
ok: false
|
|
785
|
-
};
|
|
786
|
-
}
|
|
787
|
-
return parseJson(response);
|
|
788
|
-
},
|
|
789
|
-
async documentChunks(id) {
|
|
790
|
-
const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}/chunks`);
|
|
791
|
-
if (!response.ok) {
|
|
792
|
-
const error = await toErrorMessage(response);
|
|
793
|
-
const errorResponse = {
|
|
794
|
-
error,
|
|
795
|
-
ok: false
|
|
796
|
-
};
|
|
797
|
-
return errorResponse;
|
|
798
|
-
}
|
|
799
|
-
return parseJson(response);
|
|
800
|
-
},
|
|
801
|
-
async documents(kind) {
|
|
802
|
-
const query = kind ? `?kind=${encodeURIComponent(kind)}` : "";
|
|
803
|
-
const response = await fetchImpl(`${basePath}/documents${query}`);
|
|
804
|
-
if (!response.ok) {
|
|
805
|
-
throw new Error(await toErrorMessage(response));
|
|
806
|
-
}
|
|
807
|
-
return parseJson(response);
|
|
808
|
-
},
|
|
809
|
-
async evaluate(input) {
|
|
810
|
-
const response = await fetchImpl(`${basePath}/evaluate`, {
|
|
811
|
-
body: JSON.stringify(input),
|
|
812
|
-
headers: jsonHeaders,
|
|
813
|
-
method: "POST"
|
|
814
|
-
});
|
|
815
|
-
if (!response.ok) {
|
|
816
|
-
throw new Error(await toErrorMessage(response));
|
|
817
|
-
}
|
|
818
|
-
return parseJson(response);
|
|
819
|
-
},
|
|
820
|
-
async ingest(chunks) {
|
|
821
|
-
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
822
|
-
body: JSON.stringify({ chunks }),
|
|
823
|
-
headers: jsonHeaders,
|
|
824
|
-
method: "POST"
|
|
825
|
-
});
|
|
826
|
-
if (!response.ok) {
|
|
827
|
-
return {
|
|
828
|
-
error: await toErrorMessage(response),
|
|
829
|
-
ok: false
|
|
830
|
-
};
|
|
831
|
-
}
|
|
832
|
-
return parseJson(response);
|
|
833
|
-
},
|
|
834
|
-
async ingestDocuments(input) {
|
|
835
|
-
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
836
|
-
body: JSON.stringify(input),
|
|
837
|
-
headers: jsonHeaders,
|
|
838
|
-
method: "POST"
|
|
839
|
-
});
|
|
840
|
-
if (!response.ok) {
|
|
841
|
-
return {
|
|
842
|
-
error: await toErrorMessage(response),
|
|
843
|
-
ok: false
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
return parseJson(response);
|
|
847
|
-
},
|
|
848
|
-
async ingestUploads(input) {
|
|
849
|
-
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
850
|
-
body: JSON.stringify(input),
|
|
851
|
-
headers: jsonHeaders,
|
|
852
|
-
method: "POST"
|
|
853
|
-
});
|
|
854
|
-
if (!response.ok) {
|
|
855
|
-
return {
|
|
856
|
-
error: await toErrorMessage(response),
|
|
857
|
-
ok: false
|
|
858
|
-
};
|
|
859
|
-
}
|
|
860
|
-
return parseJson(response);
|
|
861
|
-
},
|
|
862
|
-
async ingestUrls(input) {
|
|
863
|
-
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
864
|
-
body: JSON.stringify(input),
|
|
865
|
-
headers: jsonHeaders,
|
|
866
|
-
method: "POST"
|
|
867
|
-
});
|
|
868
|
-
if (!response.ok) {
|
|
869
|
-
return {
|
|
870
|
-
error: await toErrorMessage(response),
|
|
871
|
-
ok: false
|
|
872
|
-
};
|
|
873
|
-
}
|
|
874
|
-
return parseJson(response);
|
|
875
|
-
},
|
|
876
|
-
async ops() {
|
|
877
|
-
const response = await fetchImpl(`${basePath}/ops`);
|
|
878
|
-
if (!response.ok) {
|
|
879
|
-
throw new Error(await toErrorMessage(response));
|
|
880
|
-
}
|
|
881
|
-
return parseJson(response);
|
|
882
|
-
},
|
|
883
|
-
async syncSources() {
|
|
884
|
-
const response = await fetchImpl(`${basePath}/sync`);
|
|
885
|
-
if (!response.ok) {
|
|
886
|
-
throw new Error(await toErrorMessage(response));
|
|
887
|
-
}
|
|
888
|
-
return parseJson(response);
|
|
889
|
-
},
|
|
890
|
-
async syncAllSources(options2) {
|
|
891
|
-
const response = await fetchImpl(`${basePath}/sync`, {
|
|
892
|
-
body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
|
|
893
|
-
headers: options2?.background === true ? jsonHeaders : undefined,
|
|
894
|
-
method: "POST"
|
|
895
|
-
});
|
|
896
|
-
if (!response.ok) {
|
|
897
|
-
return {
|
|
898
|
-
error: await toErrorMessage(response),
|
|
899
|
-
ok: false
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
|
-
return parseJson(response);
|
|
903
|
-
},
|
|
904
|
-
async syncSource(id, options2) {
|
|
905
|
-
const response = await fetchImpl(`${basePath}/sync/${encodeURIComponent(id)}`, {
|
|
906
|
-
body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
|
|
907
|
-
headers: options2?.background === true ? jsonHeaders : undefined,
|
|
908
|
-
method: "POST"
|
|
909
|
-
});
|
|
910
|
-
if (!response.ok) {
|
|
911
|
-
return {
|
|
912
|
-
error: await toErrorMessage(response),
|
|
913
|
-
ok: false
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
return parseJson(response);
|
|
917
|
-
},
|
|
918
|
-
async reindexDocument(id) {
|
|
919
|
-
const response = await fetchImpl(`${basePath}/reindex/documents/${encodeURIComponent(id)}`, {
|
|
920
|
-
method: "POST"
|
|
921
|
-
});
|
|
922
|
-
if (!response.ok) {
|
|
923
|
-
return {
|
|
924
|
-
error: await toErrorMessage(response),
|
|
925
|
-
ok: false
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
return parseJson(response);
|
|
929
|
-
},
|
|
930
|
-
async reindexSource(source) {
|
|
931
|
-
const response = await fetchImpl(`${basePath}/reindex/source`, {
|
|
932
|
-
body: JSON.stringify({ source }),
|
|
933
|
-
headers: jsonHeaders,
|
|
934
|
-
method: "POST"
|
|
935
|
-
});
|
|
936
|
-
if (!response.ok) {
|
|
937
|
-
return {
|
|
938
|
-
error: await toErrorMessage(response),
|
|
939
|
-
ok: false
|
|
940
|
-
};
|
|
941
|
-
}
|
|
942
|
-
return parseJson(response);
|
|
943
|
-
},
|
|
944
|
-
async reseed() {
|
|
945
|
-
const response = await fetchImpl(`${basePath}/reseed`, {
|
|
946
|
-
method: "POST"
|
|
947
|
-
});
|
|
948
|
-
if (!response.ok) {
|
|
949
|
-
return {
|
|
950
|
-
error: await toErrorMessage(response),
|
|
951
|
-
ok: false
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
return parseJson(response);
|
|
955
|
-
},
|
|
956
|
-
async reset() {
|
|
957
|
-
const response = await fetchImpl(`${basePath}/reset`, {
|
|
958
|
-
method: "POST"
|
|
959
|
-
});
|
|
960
|
-
if (!response.ok) {
|
|
961
|
-
return {
|
|
962
|
-
error: await toErrorMessage(response),
|
|
963
|
-
ok: false
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
return parseJson(response);
|
|
967
|
-
},
|
|
968
|
-
async search(input) {
|
|
969
|
-
const response = await fetchImpl(`${basePath}/search`, {
|
|
970
|
-
body: JSON.stringify(input),
|
|
971
|
-
headers: jsonHeaders,
|
|
972
|
-
method: "POST"
|
|
973
|
-
});
|
|
974
|
-
if (!response.ok) {
|
|
975
|
-
throw new Error(await toErrorMessage(response));
|
|
976
|
-
}
|
|
977
|
-
const payload = await parseJson(response);
|
|
978
|
-
if (!payload.ok) {
|
|
979
|
-
throw new Error(payload.error ?? "RAG search failed");
|
|
980
|
-
}
|
|
981
|
-
return payload.results ?? [];
|
|
982
|
-
},
|
|
983
|
-
async status() {
|
|
984
|
-
const response = await fetchImpl(`${basePath}/status`);
|
|
985
|
-
if (!response.ok) {
|
|
986
|
-
throw new Error(await toErrorMessage(response));
|
|
987
|
-
}
|
|
988
|
-
return parseJson(response);
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
};
|
|
992
|
-
|
|
993
|
-
// src/angular/ai/rag-client.service.ts
|
|
994
|
-
class RAGClientService {
|
|
995
|
-
clients = new Map;
|
|
996
|
-
client(path) {
|
|
997
|
-
const existing = this.clients.get(path);
|
|
998
|
-
if (existing) {
|
|
999
|
-
return existing;
|
|
1000
921
|
}
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
922
|
+
const unresolvedNumbers = numbers.filter((number) => !referenceMap.has(number));
|
|
923
|
+
parts.push({
|
|
924
|
+
referenceNumbers: numbers,
|
|
925
|
+
referenceDetails: resolvedReferences.map(buildGroundedAnswerCitationDetail),
|
|
926
|
+
references: resolvedReferences,
|
|
927
|
+
text: raw,
|
|
928
|
+
type: "citation",
|
|
929
|
+
unresolvedReferenceNumbers: unresolvedNumbers
|
|
930
|
+
});
|
|
931
|
+
cursor = start + raw.length;
|
|
1010
932
|
}
|
|
1011
|
-
|
|
1012
|
-
|
|
933
|
+
if (cursor < content.length || parts.length === 0) {
|
|
934
|
+
parts.push({
|
|
935
|
+
text: content.slice(cursor),
|
|
936
|
+
type: "text"
|
|
937
|
+
});
|
|
1013
938
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
939
|
+
const hasCitations = parts.some((part) => part.type === "citation");
|
|
940
|
+
const coverage = !hasCitations ? "ungrounded" : ungroundedReferenceNumbers.size === 0 ? "grounded" : references.length > 0 ? "partial" : "ungrounded";
|
|
941
|
+
return {
|
|
942
|
+
content,
|
|
943
|
+
coverage,
|
|
944
|
+
hasCitations,
|
|
945
|
+
parts,
|
|
946
|
+
references,
|
|
947
|
+
ungroundedReferenceNumbers: [...ungroundedReferenceNumbers].sort((left, right) => left - right)
|
|
948
|
+
};
|
|
949
|
+
};
|
|
950
|
+
var buildRAGGroundingReferences = (sources) => {
|
|
951
|
+
const citations = buildRAGCitations(sources);
|
|
952
|
+
const citationReferenceMap = buildRAGCitationReferenceMap(citations);
|
|
953
|
+
return citations.map((citation) => ({
|
|
954
|
+
chunkId: citation.chunkId,
|
|
955
|
+
contextLabel: buildContextLabel(citation.metadata),
|
|
956
|
+
excerpt: buildExcerpt(citation.text),
|
|
957
|
+
label: citation.label,
|
|
958
|
+
locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
|
|
959
|
+
metadata: citation.metadata,
|
|
960
|
+
number: citationReferenceMap[citation.chunkId] ?? 0,
|
|
961
|
+
provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
|
|
962
|
+
score: citation.score,
|
|
963
|
+
source: citation.source,
|
|
964
|
+
text: citation.text,
|
|
965
|
+
title: citation.title
|
|
966
|
+
}));
|
|
967
|
+
};
|
|
968
|
+
var buildRAGRetrievedState = (messages) => {
|
|
969
|
+
const message = getLatestRetrievedMessage(messages);
|
|
970
|
+
if (!message) {
|
|
971
|
+
return null;
|
|
1019
972
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
973
|
+
const sources = message.sources ?? [];
|
|
974
|
+
const groundedAnswer = buildRAGGroundedAnswer(message.content, sources);
|
|
975
|
+
return {
|
|
976
|
+
citationReferenceMap: buildRAGCitationReferenceMap(buildRAGCitations(sources)),
|
|
977
|
+
citations: buildRAGCitations(sources),
|
|
978
|
+
conversationId: message.conversationId,
|
|
979
|
+
groundedAnswer,
|
|
980
|
+
messageId: message.id,
|
|
981
|
+
retrievalDurationMs: message.retrievalDurationMs,
|
|
982
|
+
retrievalStartedAt: message.retrievalStartedAt,
|
|
983
|
+
retrievedAt: message.retrievedAt,
|
|
984
|
+
sourceGroups: buildRAGSourceGroups(sources),
|
|
985
|
+
sourceSummaries: buildRAGSourceSummaries(sources),
|
|
986
|
+
sources
|
|
987
|
+
};
|
|
988
|
+
};
|
|
989
|
+
var buildRAGSourceSummaries = (sources) => {
|
|
990
|
+
const sourceGroups = buildRAGSourceGroups(sources);
|
|
991
|
+
const citations = buildRAGCitations(sources);
|
|
992
|
+
const citationReferenceMap = buildRAGCitationReferenceMap(citations);
|
|
993
|
+
return sourceGroups.map((group) => {
|
|
994
|
+
const groupCitations = citations.filter((citation) => group.chunks.some((chunk) => chunk.chunkId === citation.chunkId));
|
|
995
|
+
const leadChunk = group.chunks.slice().sort((left, right) => right.score - left.score)[0];
|
|
996
|
+
return {
|
|
997
|
+
bestScore: group.bestScore,
|
|
998
|
+
citationNumbers: groupCitations.map((citation) => citationReferenceMap[citation.chunkId] ?? 0),
|
|
999
|
+
citations: groupCitations,
|
|
1000
|
+
chunkIds: group.chunks.map((chunk) => chunk.chunkId),
|
|
1001
|
+
contextLabel: buildContextLabel(leadChunk?.metadata),
|
|
1002
|
+
count: group.count,
|
|
1003
|
+
excerpt: buildExcerpt(leadChunk?.text ?? ""),
|
|
1004
|
+
key: group.key,
|
|
1005
|
+
label: group.label,
|
|
1006
|
+
locatorLabel: buildLocatorLabel(leadChunk?.metadata, leadChunk?.source, leadChunk?.title),
|
|
1007
|
+
provenanceLabel: buildProvenanceLabel(leadChunk?.metadata),
|
|
1008
|
+
source: group.source,
|
|
1009
|
+
title: group.title
|
|
1010
|
+
};
|
|
1011
|
+
});
|
|
1012
|
+
};
|
|
1013
|
+
var buildStreamProgressState = (messages) => {
|
|
1014
|
+
const latestMessage = getLatestAssistantMessage(messages);
|
|
1015
|
+
const retrieved = latestMessage ? buildRAGRetrievedState(messages) : undefined;
|
|
1016
|
+
return {
|
|
1017
|
+
conversationId: latestMessage?.conversationId,
|
|
1018
|
+
latestMessage,
|
|
1019
|
+
messageId: latestMessage?.id,
|
|
1020
|
+
retrieved,
|
|
1021
|
+
sourceCount: retrieved?.sources.length ?? latestMessage?.sources?.length ?? 0
|
|
1022
|
+
};
|
|
1023
|
+
};
|
|
1024
|
+
var buildRAGStreamProgress = ({
|
|
1025
|
+
error,
|
|
1026
|
+
isStreaming,
|
|
1027
|
+
messages
|
|
1028
|
+
}) => {
|
|
1029
|
+
const stage = resolveRAGStreamStage({
|
|
1030
|
+
error,
|
|
1031
|
+
isStreaming,
|
|
1032
|
+
messages
|
|
1033
|
+
});
|
|
1034
|
+
const state = buildStreamProgressState(messages);
|
|
1035
|
+
const hasSources = state.sourceCount > 0;
|
|
1036
|
+
const hasRetrieved = stage === "retrieved" || state.retrieved !== undefined || state.latestMessage?.retrievedAt !== undefined;
|
|
1037
|
+
const hasThinking = typeof state.latestMessage?.thinking === "string" && state.latestMessage.thinking.length > 0;
|
|
1038
|
+
const hasToolCalls = (state.latestMessage?.toolCalls?.length ?? 0) > 0;
|
|
1039
|
+
return {
|
|
1040
|
+
conversationId: state.conversationId,
|
|
1041
|
+
hasContent: typeof state.latestMessage?.content === "string" && state.latestMessage.content.length > 0,
|
|
1042
|
+
hasRetrieved,
|
|
1043
|
+
hasSources,
|
|
1044
|
+
hasThinking,
|
|
1045
|
+
hasToolCalls,
|
|
1046
|
+
isComplete: stage === "complete",
|
|
1047
|
+
isError: stage === "error",
|
|
1048
|
+
isIdle: stage === "idle",
|
|
1049
|
+
isRetrieved: stage === "retrieved",
|
|
1050
|
+
isRetrieving: stage === "submitting" || stage === "retrieving",
|
|
1051
|
+
isStreaming: stage === "streaming",
|
|
1052
|
+
isSubmitting: stage === "submitting",
|
|
1053
|
+
latestMessage: state.latestMessage,
|
|
1054
|
+
messageId: state.messageId,
|
|
1055
|
+
retrievalDurationMs: state.retrieved?.retrievalDurationMs,
|
|
1056
|
+
retrievalStartedAt: state.retrieved?.retrievalStartedAt,
|
|
1057
|
+
retrievedAt: state.retrieved?.retrievedAt,
|
|
1058
|
+
sourceCount: state.sourceCount,
|
|
1059
|
+
stage
|
|
1060
|
+
};
|
|
1061
|
+
};
|
|
1062
|
+
var buildRAGAnswerWorkflowState = ({
|
|
1063
|
+
error,
|
|
1064
|
+
isStreaming,
|
|
1065
|
+
messages
|
|
1066
|
+
}) => {
|
|
1067
|
+
const latestAssistantMessage = getLatestAssistantMessage(messages);
|
|
1068
|
+
const sources = getLatestRAGSources(messages);
|
|
1069
|
+
const sourceGroups = buildRAGSourceGroups(sources);
|
|
1070
|
+
const citations = buildRAGCitations(sources);
|
|
1071
|
+
const citationReferenceMap = buildRAGCitationReferenceMap(citations);
|
|
1072
|
+
const sourceSummaries = buildRAGSourceSummaries(sources);
|
|
1073
|
+
const groundingReferences = buildRAGGroundingReferences(sources);
|
|
1074
|
+
const groundedAnswer = buildRAGGroundedAnswer(latestAssistantMessage?.content ?? "", sources);
|
|
1075
|
+
const retrieval = buildRAGRetrievedState(messages);
|
|
1076
|
+
const progress = buildRAGStreamProgress({
|
|
1077
|
+
error,
|
|
1078
|
+
isStreaming,
|
|
1079
|
+
messages
|
|
1080
|
+
});
|
|
1081
|
+
return {
|
|
1082
|
+
citationReferenceMap,
|
|
1083
|
+
citations,
|
|
1084
|
+
coverage: groundedAnswer.coverage,
|
|
1085
|
+
error,
|
|
1086
|
+
groundedAnswer,
|
|
1087
|
+
groundingReferences,
|
|
1088
|
+
hasCitations: groundedAnswer.hasCitations,
|
|
1089
|
+
hasGrounding: groundingReferences.length > 0,
|
|
1090
|
+
hasRetrieved: progress.hasRetrieved,
|
|
1091
|
+
hasSources: sources.length > 0,
|
|
1092
|
+
isAnswerStreaming: progress.isStreaming,
|
|
1093
|
+
isComplete: progress.isComplete,
|
|
1094
|
+
isError: progress.isError,
|
|
1095
|
+
isIdle: progress.isIdle,
|
|
1096
|
+
isRetrieved: progress.isRetrieved,
|
|
1097
|
+
isRetrieving: progress.isRetrieving,
|
|
1098
|
+
isRunning: progress.isSubmitting || progress.isRetrieving || progress.isStreaming,
|
|
1099
|
+
isSubmitting: progress.isSubmitting,
|
|
1100
|
+
latestAssistantMessage,
|
|
1101
|
+
messages,
|
|
1102
|
+
retrieval,
|
|
1103
|
+
retrievalDurationMs: retrieval?.retrievalDurationMs,
|
|
1104
|
+
retrievalStartedAt: retrieval?.retrievalStartedAt,
|
|
1105
|
+
retrievedAt: retrieval?.retrievedAt,
|
|
1106
|
+
sourceGroups,
|
|
1107
|
+
sourceSummaries,
|
|
1108
|
+
sources,
|
|
1109
|
+
stage: progress.stage,
|
|
1110
|
+
ungroundedReferenceNumbers: groundedAnswer.ungroundedReferenceNumbers
|
|
1111
|
+
};
|
|
1112
|
+
};
|
|
1113
|
+
var buildRAGSourceGroups = (sources) => {
|
|
1114
|
+
const groups = new Map;
|
|
1115
|
+
for (const source of sources) {
|
|
1116
|
+
updateSourceGroup(groups, source);
|
|
1022
1117
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1118
|
+
return [...groups.values()].sort((left, right) => {
|
|
1119
|
+
if (right.bestScore !== left.bestScore) {
|
|
1120
|
+
return right.bestScore - left.bestScore;
|
|
1121
|
+
}
|
|
1122
|
+
return left.label.localeCompare(right.label);
|
|
1123
|
+
});
|
|
1124
|
+
};
|
|
1125
|
+
var buildSourceGroup = (source, key) => ({
|
|
1126
|
+
bestScore: source.score,
|
|
1127
|
+
chunks: [source],
|
|
1128
|
+
count: 1,
|
|
1129
|
+
key,
|
|
1130
|
+
label: buildSourceLabel(source),
|
|
1131
|
+
source: source.source,
|
|
1132
|
+
title: source.title
|
|
1133
|
+
});
|
|
1134
|
+
var updateSourceGroup = (groups, source) => {
|
|
1135
|
+
const key = buildSourceGroupKey(source);
|
|
1136
|
+
const existing = groups.get(key);
|
|
1137
|
+
if (!existing) {
|
|
1138
|
+
groups.set(key, buildSourceGroup(source, key));
|
|
1139
|
+
return;
|
|
1025
1140
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1141
|
+
existing.bestScore = Math.max(existing.bestScore, source.score);
|
|
1142
|
+
existing.count += 1;
|
|
1143
|
+
existing.chunks.push(source);
|
|
1144
|
+
};
|
|
1145
|
+
var getLatestAssistantMessage = (messages) => {
|
|
1146
|
+
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
1147
|
+
const message = messages[index];
|
|
1148
|
+
if (message?.role === "assistant") {
|
|
1149
|
+
return message;
|
|
1150
|
+
}
|
|
1028
1151
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1152
|
+
return;
|
|
1153
|
+
};
|
|
1154
|
+
var getLatestRAGSources = (messages) => getLatestAssistantMessage(messages)?.sources ?? [];
|
|
1155
|
+
var getLatestRetrievedMessage = (messages) => {
|
|
1156
|
+
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
1157
|
+
const message = messages[index];
|
|
1158
|
+
if (message?.role === "assistant" && (typeof message.retrievedAt === "number" || (message.sources?.length ?? 0) > 0)) {
|
|
1159
|
+
return message;
|
|
1160
|
+
}
|
|
1031
1161
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1162
|
+
return;
|
|
1163
|
+
};
|
|
1164
|
+
var resolveRAGStreamStage = ({
|
|
1165
|
+
error,
|
|
1166
|
+
isStreaming,
|
|
1167
|
+
messages
|
|
1168
|
+
}) => {
|
|
1169
|
+
if (error) {
|
|
1170
|
+
return "error";
|
|
1034
1171
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1172
|
+
const assistantMessage = getLatestAssistantMessage(messages);
|
|
1173
|
+
if (!assistantMessage) {
|
|
1174
|
+
return isStreaming ? "submitting" : "idle";
|
|
1037
1175
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1176
|
+
const isRetrieving = typeof assistantMessage.retrievalStartedAt === "number" && typeof assistantMessage.retrievedAt !== "number";
|
|
1177
|
+
if (isRetrieving) {
|
|
1178
|
+
return "retrieving";
|
|
1040
1179
|
}
|
|
1041
|
-
|
|
1042
|
-
return
|
|
1180
|
+
if (!isStreaming) {
|
|
1181
|
+
return "complete";
|
|
1043
1182
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
return this.client(path).deleteDocument(id);
|
|
1049
|
-
}
|
|
1050
|
-
reseed(path) {
|
|
1051
|
-
return this.client(path).reseed();
|
|
1052
|
-
}
|
|
1053
|
-
reset(path) {
|
|
1054
|
-
return this.client(path).reset();
|
|
1055
|
-
}
|
|
1056
|
-
reindexDocument(path, id) {
|
|
1057
|
-
return this.client(path).reindexDocument(id);
|
|
1058
|
-
}
|
|
1059
|
-
reindexSource(path, source) {
|
|
1060
|
-
return this.client(path).reindexSource(source);
|
|
1061
|
-
}
|
|
1062
|
-
backends(path) {
|
|
1063
|
-
return this.client(path).backends();
|
|
1183
|
+
const hasRetrieved = typeof assistantMessage.retrievedAt === "number";
|
|
1184
|
+
const hasContent = assistantMessage.content.trim().length > 0 || assistantMessage.thinking?.trim().length || (assistantMessage.toolCalls?.length ?? 0) > 0 || (assistantMessage.images?.length ?? 0) > 0;
|
|
1185
|
+
if (hasRetrieved && !hasContent) {
|
|
1186
|
+
return "retrieved";
|
|
1064
1187
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1188
|
+
return "streaming";
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
// src/angular/ai/ai-rag-stream.service.ts
|
|
1192
|
+
class RAGStreamService extends AIStreamService {
|
|
1193
|
+
connect(path, conversationId) {
|
|
1194
|
+
const stream = super.connect(path, conversationId);
|
|
1195
|
+
const workflow = computed2(() => buildRAGAnswerWorkflowState({
|
|
1196
|
+
error: stream.error(),
|
|
1197
|
+
isStreaming: stream.isStreaming(),
|
|
1198
|
+
messages: stream.messages()
|
|
1199
|
+
}));
|
|
1200
|
+
const progress = computed2(() => buildRAGStreamProgress({
|
|
1201
|
+
error: stream.error(),
|
|
1202
|
+
isStreaming: stream.isStreaming(),
|
|
1203
|
+
messages: stream.messages()
|
|
1204
|
+
}));
|
|
1205
|
+
const latestAssistantMessage = computed2(() => workflow().latestAssistantMessage);
|
|
1206
|
+
const sources = computed2(() => workflow().sources);
|
|
1207
|
+
const sourceGroups = computed2(() => workflow().sourceGroups);
|
|
1208
|
+
const citations = computed2(() => workflow().citations);
|
|
1209
|
+
const sourceSummaries = computed2(() => workflow().sourceSummaries);
|
|
1210
|
+
const citationReferenceMap = computed2(() => workflow().citationReferenceMap);
|
|
1211
|
+
const retrieval = computed2(() => workflow().retrieval);
|
|
1212
|
+
const groundedAnswer = computed2(() => workflow().groundedAnswer);
|
|
1213
|
+
const groundingReferences = computed2(() => workflow().groundingReferences);
|
|
1214
|
+
const hasRetrieved = computed2(() => workflow().hasRetrieved);
|
|
1215
|
+
const hasSources = computed2(() => workflow().hasSources);
|
|
1216
|
+
const isRetrieving = computed2(() => workflow().isRetrieving);
|
|
1217
|
+
const isRetrieved = computed2(() => workflow().isRetrieved);
|
|
1218
|
+
const isAnswerStreaming = computed2(() => workflow().isAnswerStreaming);
|
|
1219
|
+
const isComplete = computed2(() => workflow().isComplete);
|
|
1220
|
+
const isError = computed2(() => workflow().isError);
|
|
1221
|
+
const isRunning = computed2(() => workflow().isRunning);
|
|
1222
|
+
const stage = computed2(() => workflow().stage);
|
|
1223
|
+
return {
|
|
1224
|
+
...stream,
|
|
1225
|
+
citations,
|
|
1226
|
+
citationReferenceMap,
|
|
1227
|
+
groundedAnswer,
|
|
1228
|
+
groundingReferences,
|
|
1229
|
+
hasRetrieved,
|
|
1230
|
+
hasSources,
|
|
1231
|
+
isAnswerStreaming,
|
|
1232
|
+
isComplete,
|
|
1233
|
+
isError,
|
|
1234
|
+
isRetrieved,
|
|
1235
|
+
isRetrieving,
|
|
1236
|
+
isRunning,
|
|
1237
|
+
latestAssistantMessage,
|
|
1238
|
+
progress,
|
|
1239
|
+
query: stream.send,
|
|
1240
|
+
retrieval,
|
|
1241
|
+
sourceGroups,
|
|
1242
|
+
sourceSummaries,
|
|
1243
|
+
sources,
|
|
1244
|
+
stage,
|
|
1245
|
+
workflow
|
|
1246
|
+
};
|
|
1067
1247
|
}
|
|
1068
1248
|
}
|
|
1069
|
-
|
|
1249
|
+
RAGStreamService = __legacyDecorateClassTS([
|
|
1070
1250
|
Injectable2({ providedIn: "root" })
|
|
1071
|
-
],
|
|
1072
|
-
// src/angular/ai/ai-rag-stream.service.ts
|
|
1073
|
-
import { computed as computed2, Injectable as Injectable3 } from "@angular/core";
|
|
1251
|
+
], RAGStreamService);
|
|
1074
1252
|
|
|
1075
|
-
// src/ai/rag
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
return;
|
|
1084
|
-
}
|
|
1085
|
-
return new Date(timestamp).toLocaleString("en-US", {
|
|
1086
|
-
dateStyle: "medium",
|
|
1087
|
-
timeStyle: "short"
|
|
1088
|
-
});
|
|
1089
|
-
};
|
|
1090
|
-
var formatMediaTimestamp = (value) => {
|
|
1091
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
1092
|
-
return;
|
|
1093
|
-
}
|
|
1094
|
-
const totalSeconds = Math.floor(value / 1000);
|
|
1095
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
1096
|
-
const seconds = totalSeconds % 60;
|
|
1097
|
-
const milliseconds = Math.floor(value % 1000);
|
|
1098
|
-
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(milliseconds).padStart(3, "0")}`;
|
|
1099
|
-
};
|
|
1100
|
-
var getAttachmentName = (source, title) => {
|
|
1101
|
-
const sourceAttachment = source?.split("/").at(-1);
|
|
1102
|
-
if (sourceAttachment && sourceAttachment.includes(".")) {
|
|
1103
|
-
return sourceAttachment;
|
|
1104
|
-
}
|
|
1105
|
-
const titleAttachment = title?.split(" · ").at(-1);
|
|
1106
|
-
if (titleAttachment && titleAttachment.includes(".")) {
|
|
1107
|
-
return titleAttachment;
|
|
1253
|
+
// src/angular/ai/ai-rag-workflow.service.ts
|
|
1254
|
+
class RAGWorkflowService extends RAGStreamService {
|
|
1255
|
+
connect(path, conversationId) {
|
|
1256
|
+
const stream = super.connect(path, conversationId);
|
|
1257
|
+
return {
|
|
1258
|
+
...stream,
|
|
1259
|
+
state: computed3(() => stream.workflow())
|
|
1260
|
+
};
|
|
1108
1261
|
}
|
|
1109
|
-
|
|
1262
|
+
}
|
|
1263
|
+
RAGWorkflowService = __legacyDecorateClassTS([
|
|
1264
|
+
Injectable3({ providedIn: "root" })
|
|
1265
|
+
], RAGWorkflowService);
|
|
1266
|
+
// src/angular/ai/rag-client.service.ts
|
|
1267
|
+
import { Injectable as Injectable4 } from "@angular/core";
|
|
1268
|
+
|
|
1269
|
+
// src/constants.ts
|
|
1270
|
+
var HOURS_IN_DAY = 24;
|
|
1271
|
+
var MILLISECONDS_IN_A_SECOND = 1000;
|
|
1272
|
+
var MINUTES_IN_AN_HOUR = 60;
|
|
1273
|
+
var SECONDS_IN_A_MINUTE = 60;
|
|
1274
|
+
var MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
|
|
1275
|
+
var MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
|
|
1276
|
+
var TWO_THIRDS = 2 / 3;
|
|
1277
|
+
var UNFOUND_INDEX = -1;
|
|
1278
|
+
|
|
1279
|
+
// src/ai/client/ragClient.ts
|
|
1280
|
+
var jsonHeaders = {
|
|
1281
|
+
"Content-Type": "application/json"
|
|
1110
1282
|
};
|
|
1111
|
-
var
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
const emailKind = getContextString(metadata.emailKind);
|
|
1116
|
-
if (emailKind === "attachment") {
|
|
1117
|
-
return "Attachment evidence";
|
|
1118
|
-
}
|
|
1119
|
-
if (emailKind === "message") {
|
|
1120
|
-
const from = getContextString(metadata.from);
|
|
1121
|
-
return from ? `Message from ${from}` : "Message evidence";
|
|
1122
|
-
}
|
|
1123
|
-
const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
|
|
1124
|
-
if (page) {
|
|
1125
|
-
return `Page ${page}`;
|
|
1126
|
-
}
|
|
1127
|
-
const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
|
|
1128
|
-
if (sheet) {
|
|
1129
|
-
return `Sheet ${sheet}`;
|
|
1130
|
-
}
|
|
1131
|
-
const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
|
|
1132
|
-
if (slide) {
|
|
1133
|
-
return `Slide ${slide}`;
|
|
1134
|
-
}
|
|
1135
|
-
const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
|
|
1136
|
-
if (archiveEntry) {
|
|
1137
|
-
return `Archive entry ${archiveEntry}`;
|
|
1138
|
-
}
|
|
1139
|
-
const threadTopic = getContextString(metadata.threadTopic);
|
|
1140
|
-
if (threadTopic) {
|
|
1141
|
-
return `Thread ${threadTopic}`;
|
|
1142
|
-
}
|
|
1143
|
-
const speaker = getContextString(metadata.speaker);
|
|
1144
|
-
if (speaker) {
|
|
1145
|
-
return `Speaker ${speaker}`;
|
|
1146
|
-
}
|
|
1147
|
-
return;
|
|
1283
|
+
var normalizeBasePath = (path) => path.endsWith("/") ? path.slice(0, UNFOUND_INDEX) : path;
|
|
1284
|
+
var parseJson = async (response) => {
|
|
1285
|
+
const payload = JSON.parse(await response.text());
|
|
1286
|
+
return payload;
|
|
1148
1287
|
};
|
|
1149
|
-
var
|
|
1150
|
-
if (!
|
|
1151
|
-
return;
|
|
1152
|
-
}
|
|
1153
|
-
const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
|
|
1154
|
-
if (page) {
|
|
1155
|
-
return `Page ${page}`;
|
|
1156
|
-
}
|
|
1157
|
-
const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
|
|
1158
|
-
if (sheet) {
|
|
1159
|
-
return `Sheet ${sheet}`;
|
|
1160
|
-
}
|
|
1161
|
-
const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
|
|
1162
|
-
if (slide) {
|
|
1163
|
-
return `Slide ${slide}`;
|
|
1164
|
-
}
|
|
1165
|
-
const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
|
|
1166
|
-
if (archiveEntry) {
|
|
1167
|
-
return `Archive entry ${archiveEntry}`;
|
|
1168
|
-
}
|
|
1169
|
-
const emailKind = getContextString(metadata.emailKind);
|
|
1170
|
-
if (emailKind === "attachment") {
|
|
1171
|
-
const attachmentName = getContextString(metadata.attachmentName) ?? getAttachmentName(source, title);
|
|
1172
|
-
return attachmentName ? `Attachment ${attachmentName}` : "Attachment";
|
|
1173
|
-
}
|
|
1174
|
-
const mediaStart = formatMediaTimestamp(metadata.startMs);
|
|
1175
|
-
const mediaEnd = formatMediaTimestamp(metadata.endMs);
|
|
1176
|
-
if (mediaStart && mediaEnd) {
|
|
1177
|
-
return `Timestamp ${mediaStart} - ${mediaEnd}`;
|
|
1178
|
-
}
|
|
1179
|
-
if (mediaStart) {
|
|
1180
|
-
return `Timestamp ${mediaStart}`;
|
|
1288
|
+
var isErrorPayload = (value) => {
|
|
1289
|
+
if (!value || typeof value !== "object") {
|
|
1290
|
+
return false;
|
|
1181
1291
|
}
|
|
1182
|
-
return;
|
|
1292
|
+
return !("error" in value) || typeof value.error === "string";
|
|
1183
1293
|
};
|
|
1184
|
-
var
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
const mediaKind = getContextString(metadata.mediaKind);
|
|
1193
|
-
const transcriptSource = getContextString(metadata.transcriptSource);
|
|
1194
|
-
const pdfTextMode = getContextString(metadata.pdfTextMode);
|
|
1195
|
-
const ocrEngine = getContextString(metadata.ocrEngine);
|
|
1196
|
-
const labels = [
|
|
1197
|
-
pdfTextMode ? `PDF ${pdfTextMode}` : "",
|
|
1198
|
-
ocrEngine ? `OCR ${ocrEngine}` : "",
|
|
1199
|
-
mediaKind ? `Media ${mediaKind}` : "",
|
|
1200
|
-
transcriptSource ? `Transcript ${transcriptSource}` : "",
|
|
1201
|
-
threadTopic ? `Thread ${threadTopic}` : "",
|
|
1202
|
-
speaker ? `Speaker ${speaker}` : "",
|
|
1203
|
-
from ? `Sender ${from}` : "",
|
|
1204
|
-
sentAt ? `Sent ${sentAt}` : ""
|
|
1205
|
-
].filter((value) => value.length > 0);
|
|
1206
|
-
return labels.length > 0 ? labels.join(" · ") : undefined;
|
|
1294
|
+
var toErrorMessage = async (response) => {
|
|
1295
|
+
try {
|
|
1296
|
+
const payload = JSON.parse(await response.text());
|
|
1297
|
+
if (isErrorPayload(payload) && typeof payload.error === "string" && payload.error) {
|
|
1298
|
+
return payload.error;
|
|
1299
|
+
}
|
|
1300
|
+
} catch {}
|
|
1301
|
+
return `Request failed with status ${response.status}`;
|
|
1207
1302
|
};
|
|
1208
|
-
var
|
|
1209
|
-
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
locatorLabel: buildLocatorLabel(source.metadata, source.source, source.title),
|
|
1223
|
-
metadata: source.metadata,
|
|
1224
|
-
provenanceLabel: buildProvenanceLabel(source.metadata),
|
|
1225
|
-
score: source.score,
|
|
1226
|
-
source: source.source,
|
|
1227
|
-
text: source.text,
|
|
1228
|
-
title: source.title
|
|
1229
|
-
});
|
|
1230
|
-
}
|
|
1231
|
-
return [...unique.values()].sort((left, right) => {
|
|
1232
|
-
if (right.score !== left.score) {
|
|
1233
|
-
return right.score - left.score;
|
|
1234
|
-
}
|
|
1235
|
-
return left.label.localeCompare(right.label);
|
|
1236
|
-
});
|
|
1237
|
-
};
|
|
1238
|
-
var buildExcerpt = (text, maxLength = 160) => {
|
|
1239
|
-
const normalized = text.replaceAll(/\s+/g, " ").trim();
|
|
1240
|
-
if (normalized.length <= maxLength) {
|
|
1241
|
-
return normalized;
|
|
1242
|
-
}
|
|
1243
|
-
return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
|
|
1244
|
-
};
|
|
1245
|
-
var buildGroundingReferenceEvidenceLabel = (reference) => [reference.label, reference.locatorLabel, reference.contextLabel].filter((value) => Boolean(value && value.length > 0)).filter((value, index, values) => values.findIndex((entry) => entry === value) === index).join(" · ");
|
|
1246
|
-
var buildGroundingReferenceEvidenceSummary = (reference) => [
|
|
1247
|
-
reference.source ?? reference.title ?? reference.chunkId,
|
|
1248
|
-
reference.provenanceLabel
|
|
1249
|
-
].filter((value) => Boolean(value && value.length > 0)).join(" · ");
|
|
1250
|
-
var buildGroundedAnswerCitationDetail = (reference) => ({
|
|
1251
|
-
contextLabel: reference.contextLabel,
|
|
1252
|
-
evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
|
|
1253
|
-
evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
|
|
1254
|
-
excerpt: reference.excerpt,
|
|
1255
|
-
label: reference.label,
|
|
1256
|
-
locatorLabel: reference.locatorLabel,
|
|
1257
|
-
number: reference.number,
|
|
1258
|
-
provenanceLabel: reference.provenanceLabel,
|
|
1259
|
-
source: reference.source,
|
|
1260
|
-
title: reference.title
|
|
1261
|
-
});
|
|
1262
|
-
var buildRAGGroundedAnswer = (content, sources) => {
|
|
1263
|
-
const references = buildRAGGroundingReferences(sources);
|
|
1264
|
-
const referenceMap = new Map(references.map((reference) => [reference.number, reference]));
|
|
1265
|
-
const parts = [];
|
|
1266
|
-
const ungroundedReferenceNumbers = new Set;
|
|
1267
|
-
const citationPattern = /\[(\d+(?:\s*,\s*\d+)*)\]/g;
|
|
1268
|
-
let cursor = 0;
|
|
1269
|
-
for (const match of content.matchAll(citationPattern)) {
|
|
1270
|
-
const raw = match[0];
|
|
1271
|
-
const numbers = (match[1] ?? "").split(",").map((value) => Number.parseInt(value.trim(), 10)).filter((value) => Number.isInteger(value) && value > 0);
|
|
1272
|
-
const start = match.index ?? cursor;
|
|
1273
|
-
if (start > cursor) {
|
|
1274
|
-
parts.push({
|
|
1275
|
-
text: content.slice(cursor, start),
|
|
1276
|
-
type: "text"
|
|
1303
|
+
var createRAGClient = (options) => {
|
|
1304
|
+
const basePath = normalizeBasePath(options.path);
|
|
1305
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
1306
|
+
return {
|
|
1307
|
+
async backends() {
|
|
1308
|
+
const response = await fetchImpl(`${basePath}/backends`);
|
|
1309
|
+
if (!response.ok) {
|
|
1310
|
+
throw new Error(await toErrorMessage(response));
|
|
1311
|
+
}
|
|
1312
|
+
return parseJson(response);
|
|
1313
|
+
},
|
|
1314
|
+
async clearIndex() {
|
|
1315
|
+
const response = await fetchImpl(`${basePath}/index`, {
|
|
1316
|
+
method: "DELETE"
|
|
1277
1317
|
});
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
for (const number of numbers) {
|
|
1281
|
-
if (!referenceMap.has(number)) {
|
|
1282
|
-
ungroundedReferenceNumbers.add(number);
|
|
1318
|
+
if (!response.ok) {
|
|
1319
|
+
throw new Error(await toErrorMessage(response));
|
|
1283
1320
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
})
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1321
|
+
return parseJson(response);
|
|
1322
|
+
},
|
|
1323
|
+
async createDocument(input) {
|
|
1324
|
+
const response = await fetchImpl(`${basePath}/documents`, {
|
|
1325
|
+
body: JSON.stringify(input),
|
|
1326
|
+
headers: jsonHeaders,
|
|
1327
|
+
method: "POST"
|
|
1328
|
+
});
|
|
1329
|
+
if (!response.ok) {
|
|
1330
|
+
return {
|
|
1331
|
+
error: await toErrorMessage(response),
|
|
1332
|
+
ok: false
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
return parseJson(response);
|
|
1336
|
+
},
|
|
1337
|
+
async deleteDocument(id) {
|
|
1338
|
+
const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}`, {
|
|
1339
|
+
method: "DELETE"
|
|
1340
|
+
});
|
|
1341
|
+
if (!response.ok) {
|
|
1342
|
+
return {
|
|
1343
|
+
error: await toErrorMessage(response),
|
|
1344
|
+
ok: false
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
return parseJson(response);
|
|
1348
|
+
},
|
|
1349
|
+
async documentChunks(id) {
|
|
1350
|
+
const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}/chunks`);
|
|
1351
|
+
if (!response.ok) {
|
|
1352
|
+
const error = await toErrorMessage(response);
|
|
1353
|
+
const errorResponse = {
|
|
1354
|
+
error,
|
|
1355
|
+
ok: false
|
|
1356
|
+
};
|
|
1357
|
+
return errorResponse;
|
|
1358
|
+
}
|
|
1359
|
+
return parseJson(response);
|
|
1360
|
+
},
|
|
1361
|
+
async documents(kind) {
|
|
1362
|
+
const query = kind ? `?kind=${encodeURIComponent(kind)}` : "";
|
|
1363
|
+
const response = await fetchImpl(`${basePath}/documents${query}`);
|
|
1364
|
+
if (!response.ok) {
|
|
1365
|
+
throw new Error(await toErrorMessage(response));
|
|
1366
|
+
}
|
|
1367
|
+
return parseJson(response);
|
|
1368
|
+
},
|
|
1369
|
+
async evaluate(input) {
|
|
1370
|
+
const response = await fetchImpl(`${basePath}/evaluate`, {
|
|
1371
|
+
body: JSON.stringify(input),
|
|
1372
|
+
headers: jsonHeaders,
|
|
1373
|
+
method: "POST"
|
|
1374
|
+
});
|
|
1375
|
+
if (!response.ok) {
|
|
1376
|
+
throw new Error(await toErrorMessage(response));
|
|
1377
|
+
}
|
|
1378
|
+
return parseJson(response);
|
|
1379
|
+
},
|
|
1380
|
+
async ingest(chunks) {
|
|
1381
|
+
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
1382
|
+
body: JSON.stringify({ chunks }),
|
|
1383
|
+
headers: jsonHeaders,
|
|
1384
|
+
method: "POST"
|
|
1385
|
+
});
|
|
1386
|
+
if (!response.ok) {
|
|
1387
|
+
return {
|
|
1388
|
+
error: await toErrorMessage(response),
|
|
1389
|
+
ok: false
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
return parseJson(response);
|
|
1393
|
+
},
|
|
1394
|
+
async ingestDocuments(input) {
|
|
1395
|
+
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
1396
|
+
body: JSON.stringify(input),
|
|
1397
|
+
headers: jsonHeaders,
|
|
1398
|
+
method: "POST"
|
|
1399
|
+
});
|
|
1400
|
+
if (!response.ok) {
|
|
1401
|
+
return {
|
|
1402
|
+
error: await toErrorMessage(response),
|
|
1403
|
+
ok: false
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
return parseJson(response);
|
|
1407
|
+
},
|
|
1408
|
+
async ingestUploads(input) {
|
|
1409
|
+
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
1410
|
+
body: JSON.stringify(input),
|
|
1411
|
+
headers: jsonHeaders,
|
|
1412
|
+
method: "POST"
|
|
1413
|
+
});
|
|
1414
|
+
if (!response.ok) {
|
|
1415
|
+
return {
|
|
1416
|
+
error: await toErrorMessage(response),
|
|
1417
|
+
ok: false
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
return parseJson(response);
|
|
1421
|
+
},
|
|
1422
|
+
async ingestUrls(input) {
|
|
1423
|
+
const response = await fetchImpl(`${basePath}/ingest`, {
|
|
1424
|
+
body: JSON.stringify(input),
|
|
1425
|
+
headers: jsonHeaders,
|
|
1426
|
+
method: "POST"
|
|
1427
|
+
});
|
|
1428
|
+
if (!response.ok) {
|
|
1429
|
+
return {
|
|
1430
|
+
error: await toErrorMessage(response),
|
|
1431
|
+
ok: false
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
return parseJson(response);
|
|
1435
|
+
},
|
|
1436
|
+
async ops() {
|
|
1437
|
+
const response = await fetchImpl(`${basePath}/ops`);
|
|
1438
|
+
if (!response.ok) {
|
|
1439
|
+
throw new Error(await toErrorMessage(response));
|
|
1440
|
+
}
|
|
1441
|
+
return parseJson(response);
|
|
1442
|
+
},
|
|
1443
|
+
async syncSources() {
|
|
1444
|
+
const response = await fetchImpl(`${basePath}/sync`);
|
|
1445
|
+
if (!response.ok) {
|
|
1446
|
+
throw new Error(await toErrorMessage(response));
|
|
1447
|
+
}
|
|
1448
|
+
return parseJson(response);
|
|
1449
|
+
},
|
|
1450
|
+
async syncAllSources(options2) {
|
|
1451
|
+
const response = await fetchImpl(`${basePath}/sync`, {
|
|
1452
|
+
body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
|
|
1453
|
+
headers: options2?.background === true ? jsonHeaders : undefined,
|
|
1454
|
+
method: "POST"
|
|
1455
|
+
});
|
|
1456
|
+
if (!response.ok) {
|
|
1457
|
+
return {
|
|
1458
|
+
error: await toErrorMessage(response),
|
|
1459
|
+
ok: false
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
return parseJson(response);
|
|
1463
|
+
},
|
|
1464
|
+
async syncSource(id, options2) {
|
|
1465
|
+
const response = await fetchImpl(`${basePath}/sync/${encodeURIComponent(id)}`, {
|
|
1466
|
+
body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
|
|
1467
|
+
headers: options2?.background === true ? jsonHeaders : undefined,
|
|
1468
|
+
method: "POST"
|
|
1469
|
+
});
|
|
1470
|
+
if (!response.ok) {
|
|
1471
|
+
return {
|
|
1472
|
+
error: await toErrorMessage(response),
|
|
1473
|
+
ok: false
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
return parseJson(response);
|
|
1477
|
+
},
|
|
1478
|
+
async reindexDocument(id) {
|
|
1479
|
+
const response = await fetchImpl(`${basePath}/reindex/documents/${encodeURIComponent(id)}`, {
|
|
1480
|
+
method: "POST"
|
|
1481
|
+
});
|
|
1482
|
+
if (!response.ok) {
|
|
1483
|
+
return {
|
|
1484
|
+
error: await toErrorMessage(response),
|
|
1485
|
+
ok: false
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
return parseJson(response);
|
|
1489
|
+
},
|
|
1490
|
+
async reindexSource(source) {
|
|
1491
|
+
const response = await fetchImpl(`${basePath}/reindex/source`, {
|
|
1492
|
+
body: JSON.stringify({ source }),
|
|
1493
|
+
headers: jsonHeaders,
|
|
1494
|
+
method: "POST"
|
|
1495
|
+
});
|
|
1496
|
+
if (!response.ok) {
|
|
1497
|
+
return {
|
|
1498
|
+
error: await toErrorMessage(response),
|
|
1499
|
+
ok: false
|
|
1500
|
+
};
|
|
1501
|
+
}
|
|
1502
|
+
return parseJson(response);
|
|
1503
|
+
},
|
|
1504
|
+
async reseed() {
|
|
1505
|
+
const response = await fetchImpl(`${basePath}/reseed`, {
|
|
1506
|
+
method: "POST"
|
|
1507
|
+
});
|
|
1508
|
+
if (!response.ok) {
|
|
1509
|
+
return {
|
|
1510
|
+
error: await toErrorMessage(response),
|
|
1511
|
+
ok: false
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
return parseJson(response);
|
|
1515
|
+
},
|
|
1516
|
+
async reset() {
|
|
1517
|
+
const response = await fetchImpl(`${basePath}/reset`, {
|
|
1518
|
+
method: "POST"
|
|
1519
|
+
});
|
|
1520
|
+
if (!response.ok) {
|
|
1521
|
+
return {
|
|
1522
|
+
error: await toErrorMessage(response),
|
|
1523
|
+
ok: false
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
return parseJson(response);
|
|
1527
|
+
},
|
|
1528
|
+
async search(input) {
|
|
1529
|
+
const response = await fetchImpl(`${basePath}/search`, {
|
|
1530
|
+
body: JSON.stringify(input),
|
|
1531
|
+
headers: jsonHeaders,
|
|
1532
|
+
method: "POST"
|
|
1533
|
+
});
|
|
1534
|
+
if (!response.ok) {
|
|
1535
|
+
throw new Error(await toErrorMessage(response));
|
|
1536
|
+
}
|
|
1537
|
+
const payload = await parseJson(response);
|
|
1538
|
+
if (!payload.ok) {
|
|
1539
|
+
throw new Error(payload.error ?? "RAG search failed");
|
|
1540
|
+
}
|
|
1541
|
+
return payload.results ?? [];
|
|
1542
|
+
},
|
|
1543
|
+
async status() {
|
|
1544
|
+
const response = await fetchImpl(`${basePath}/status`);
|
|
1545
|
+
if (!response.ok) {
|
|
1546
|
+
throw new Error(await toErrorMessage(response));
|
|
1547
|
+
}
|
|
1548
|
+
return parseJson(response);
|
|
1549
|
+
}
|
|
1474
1550
|
};
|
|
1475
1551
|
};
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
if (
|
|
1483
|
-
return
|
|
1552
|
+
|
|
1553
|
+
// src/angular/ai/rag-client.service.ts
|
|
1554
|
+
class RAGClientService {
|
|
1555
|
+
clients = new Map;
|
|
1556
|
+
client(path) {
|
|
1557
|
+
const existing = this.clients.get(path);
|
|
1558
|
+
if (existing) {
|
|
1559
|
+
return existing;
|
|
1484
1560
|
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
var buildSourceGroup = (source, key) => ({
|
|
1489
|
-
bestScore: source.score,
|
|
1490
|
-
chunks: [source],
|
|
1491
|
-
count: 1,
|
|
1492
|
-
key,
|
|
1493
|
-
label: buildSourceLabel(source),
|
|
1494
|
-
source: source.source,
|
|
1495
|
-
title: source.title
|
|
1496
|
-
});
|
|
1497
|
-
var updateSourceGroup = (groups, source) => {
|
|
1498
|
-
const key = buildSourceGroupKey(source);
|
|
1499
|
-
const existing = groups.get(key);
|
|
1500
|
-
if (!existing) {
|
|
1501
|
-
groups.set(key, buildSourceGroup(source, key));
|
|
1502
|
-
return;
|
|
1561
|
+
const created = createRAGClient({ path });
|
|
1562
|
+
this.clients.set(path, created);
|
|
1563
|
+
return created;
|
|
1503
1564
|
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
existing.chunks.push(source);
|
|
1507
|
-
};
|
|
1508
|
-
var getLatestAssistantMessage = (messages) => {
|
|
1509
|
-
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
1510
|
-
const message = messages[index];
|
|
1511
|
-
if (message?.role === "assistant") {
|
|
1512
|
-
return message;
|
|
1513
|
-
}
|
|
1565
|
+
ingest(path, chunks) {
|
|
1566
|
+
return this.client(path).ingest(chunks);
|
|
1514
1567
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
var getLatestRAGSources = (messages) => getLatestAssistantMessage(messages)?.sources ?? [];
|
|
1518
|
-
var getLatestRetrievedMessage = (messages) => {
|
|
1519
|
-
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
1520
|
-
const message = messages[index];
|
|
1521
|
-
if (message?.role === "assistant" && (typeof message.retrievedAt === "number" || (message.sources?.length ?? 0) > 0)) {
|
|
1522
|
-
return message;
|
|
1523
|
-
}
|
|
1568
|
+
ingestDocuments(path, input) {
|
|
1569
|
+
return this.client(path).ingestDocuments(input);
|
|
1524
1570
|
}
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
var resolveRAGStreamStage = ({
|
|
1528
|
-
error,
|
|
1529
|
-
isStreaming,
|
|
1530
|
-
messages
|
|
1531
|
-
}) => {
|
|
1532
|
-
if (error) {
|
|
1533
|
-
return "error";
|
|
1571
|
+
ingestUrls(path, input) {
|
|
1572
|
+
return this.client(path).ingestUrls(input);
|
|
1534
1573
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
return isStreaming ? "submitting" : "idle";
|
|
1574
|
+
ingestUploads(path, input) {
|
|
1575
|
+
return this.client(path).ingestUploads(input);
|
|
1538
1576
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
return "retrieving";
|
|
1577
|
+
search(path, input) {
|
|
1578
|
+
return this.client(path).search(input);
|
|
1542
1579
|
}
|
|
1543
|
-
|
|
1544
|
-
return
|
|
1580
|
+
evaluate(path, input) {
|
|
1581
|
+
return this.client(path).evaluate(input);
|
|
1545
1582
|
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
if (hasRetrieved && !hasContent) {
|
|
1549
|
-
return "retrieved";
|
|
1583
|
+
status(path) {
|
|
1584
|
+
return this.client(path).status();
|
|
1550
1585
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
hasRetrieved,
|
|
1593
|
-
hasSources,
|
|
1594
|
-
isAnswerStreaming,
|
|
1595
|
-
isComplete,
|
|
1596
|
-
isError,
|
|
1597
|
-
isRetrieved,
|
|
1598
|
-
isRetrieving,
|
|
1599
|
-
isRunning,
|
|
1600
|
-
latestAssistantMessage,
|
|
1601
|
-
progress,
|
|
1602
|
-
query: stream.send,
|
|
1603
|
-
retrieval,
|
|
1604
|
-
sourceGroups,
|
|
1605
|
-
sourceSummaries,
|
|
1606
|
-
sources,
|
|
1607
|
-
stage,
|
|
1608
|
-
workflow
|
|
1609
|
-
};
|
|
1586
|
+
ops(path) {
|
|
1587
|
+
return this.client(path).ops();
|
|
1588
|
+
}
|
|
1589
|
+
syncSources(path) {
|
|
1590
|
+
return this.client(path).syncSources();
|
|
1591
|
+
}
|
|
1592
|
+
syncAllSources(path, options) {
|
|
1593
|
+
return this.client(path).syncAllSources(options);
|
|
1594
|
+
}
|
|
1595
|
+
syncSource(path, id, options) {
|
|
1596
|
+
return this.client(path).syncSource(id, options);
|
|
1597
|
+
}
|
|
1598
|
+
documents(path, kind) {
|
|
1599
|
+
return this.client(path).documents(kind);
|
|
1600
|
+
}
|
|
1601
|
+
documentChunks(path, id) {
|
|
1602
|
+
return this.client(path).documentChunks(id);
|
|
1603
|
+
}
|
|
1604
|
+
createDocument(path, input) {
|
|
1605
|
+
return this.client(path).createDocument(input);
|
|
1606
|
+
}
|
|
1607
|
+
deleteDocument(path, id) {
|
|
1608
|
+
return this.client(path).deleteDocument(id);
|
|
1609
|
+
}
|
|
1610
|
+
reseed(path) {
|
|
1611
|
+
return this.client(path).reseed();
|
|
1612
|
+
}
|
|
1613
|
+
reset(path) {
|
|
1614
|
+
return this.client(path).reset();
|
|
1615
|
+
}
|
|
1616
|
+
reindexDocument(path, id) {
|
|
1617
|
+
return this.client(path).reindexDocument(id);
|
|
1618
|
+
}
|
|
1619
|
+
reindexSource(path, source) {
|
|
1620
|
+
return this.client(path).reindexSource(source);
|
|
1621
|
+
}
|
|
1622
|
+
backends(path) {
|
|
1623
|
+
return this.client(path).backends();
|
|
1624
|
+
}
|
|
1625
|
+
clearIndex(path) {
|
|
1626
|
+
return this.client(path).clearIndex();
|
|
1610
1627
|
}
|
|
1611
1628
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
],
|
|
1629
|
+
RAGClientService = __legacyDecorateClassTS([
|
|
1630
|
+
Injectable4({ providedIn: "root" })
|
|
1631
|
+
], RAGClientService);
|
|
1615
1632
|
export {
|
|
1616
|
-
|
|
1633
|
+
RAGWorkflowService,
|
|
1634
|
+
RAGStreamService,
|
|
1617
1635
|
RAGClientService,
|
|
1618
1636
|
AIStreamService
|
|
1619
1637
|
};
|