Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 45 additions & 11 deletions code/frontend/src/components/Answer/AnswerParser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,56 @@ export function parseAnswer(answer: AskResponse): ParsedAnswer {

filteredCitations = [] as Citation[];
let citationReindex = 0;

// Track the last citation to detect consecutive duplicates
let lastCitationKey: string | null = null;

citationLinks?.forEach(link => {
// Replacing the links/citations with number
// Extract citation index from [docN]
let citationIndex = link.slice(lengthDocN, link.length - 1);
let citation = cloneDeep(answer.citations[Number(citationIndex) - 1]) as Citation;
if (!isDuplicate(citation, citationIndex) && citation !== undefined) {
answerText = answerText.replaceAll(link, ` ^${++citationReindex}^ `);
citation.reindex_id = citationReindex.toString(); // reindex from 1 for display
filteredCitations.push(citation);
}else{
// Replacing duplicate citation with original index
let matchingCitation = filteredCitations.find((ct) => citation.chunk_id === ct.chunk_id && citation.id === ct.id);
if (matchingCitation) {
answerText= answerText.replaceAll(link, ` ^${matchingCitation.reindex_id}^ `)

if (citation === undefined) {
answerText = answerText.replace(link, '');
return;
}

// Create unique key for this citation
const citationKey = `${citation.chunk_id}_${citation.id}`;

// Check if this is a consecutive duplicate
if (citationKey === lastCitationKey) {
// Remove consecutive duplicate
answerText = answerText.replace(link, '');
} else {
// Not a duplicate or not consecutive - process it
if (!isDuplicate(citation, citationIndex)) {
// This is a new unique citation - add to list
citation.reindex_id = (++citationReindex).toString();
filteredCitations.push(citation);
} else {
// This citation was seen before (but not consecutive) - find its reindex_id
const existingCitation = filteredCitations.find(
(c) => c.chunk_id === citation.chunk_id && c.id === citation.id
);
if (existingCitation) {
citation.reindex_id = existingCitation.reindex_id;
} else {
// Fallback: should not happen, but handle it
citation.reindex_id = (++citationReindex).toString();
filteredCitations.push(citation);
}
}

// Replace with the citation number (use replace to only replace first occurrence)
if (citation.reindex_id) {
answerText = answerText.replace(link, ` ^${citation.reindex_id}^ `);
}
}
})

// Update last citation key
lastCitationKey = citationKey;
});


return {
Expand Down
44 changes: 30 additions & 14 deletions extensions/teams/cards/cardBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,29 +92,45 @@ export function cardBodyBuilder(citations: any[], assistantAnswer: string): any
export function cwydResponseBuilder(citations: Citation[], assistantAnswer: string): Attachment {
let citationActions: any[] = [];
let docId = 1;
let deleteEnd = "";
let deleteEndSpace = "";
let refCount = 1;
let findPart = {};
let reIndex = 0;

// Track the last citation to detect consecutive duplicates
let lastCitationKey: string | null = null;

citations.map((citation: Citation) => {
if (!(citation.chunk_id in findPart)) {
reIndex = docId;
citationActions.push(actionBuilder(citation, reIndex));
findPart[citation.chunk_id] = reIndex;
docId++;
const citationKey = `${citation.chunk_id}_${citation.id}`;
const docMarker = `[doc${refCount}]`;

// Check if this is a consecutive duplicate
if (citationKey === lastCitationKey) {
// Remove consecutive duplicate
assistantAnswer = assistantAnswer.replace(docMarker, '');
} else {
reIndex = findPart[citation.chunk_id];
}
// Not consecutive - process it
if (!(citation.chunk_id in findPart)) {
// New unique citation
reIndex = docId;
citationActions.push(actionBuilder(citation, reIndex));
findPart[citation.chunk_id] = reIndex;
docId++;
} else {
// Citation seen before (but not consecutive)
reIndex = findPart[citation.chunk_id];
}

deleteEnd += `[${reIndex}]`;
deleteEndSpace += ` [${reIndex}]`;
assistantAnswer = assistantAnswer.replaceAll(`[doc${refCount}]`, `[${reIndex}]`);
// Replace with the reindexed number
if (reIndex) {
assistantAnswer = assistantAnswer.replace(docMarker, `[${reIndex}]`);
}
}

// Update last citation key
lastCitationKey = citationKey;
refCount++;
});
assistantAnswer = assistantAnswer.replaceAll(deleteEnd, "");
assistantAnswer = assistantAnswer.replaceAll(deleteEndSpace, "");

let answerCard = CardFactory.adaptiveCard(cardBodyBuilder(citationActions, assistantAnswer));
return answerCard;
}