Skip to content

Commit 7c93eb3

Browse files
committed
render web citations
1 parent bbb73b2 commit 7c93eb3

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

app/frontend/src/components/Answer/Answer.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import rehypeRaw from "rehype-raw";
88

99
import styles from "./Answer.module.css";
1010
import { ChatAppResponse, getCitationFilePath, SpeechConfig } from "../../api";
11-
import { parseAnswerToHtml } from "./AnswerParser";
11+
import { citationIdToCitation, parseAnswerToHtml } from "./AnswerParser";
1212
import { AnswerIcon } from "./AnswerIcon";
1313
import { SpeechOutputBrowser } from "./SpeechOutputBrowser";
1414
import { SpeechOutputAzure } from "./SpeechOutputAzure";
15+
import { WebPage } from "../SupportingContent";
1516

1617
interface Props {
1718
answer: ChatAppResponse;
@@ -110,11 +111,23 @@ export const Answer = ({
110111
<span className={styles.citationLearnMore}>{t("citationWithColon")}</span>
111112
{parsedAnswer.citations.map((x, i) => {
112113
const path = getCitationFilePath(x);
113-
return (
114-
<a key={i} className={styles.citation} title={x} onClick={() => onCitationClicked(path)}>
115-
{`${++i}. ${x}`}
116-
</a>
117-
);
114+
const citation = citationIdToCitation(x, answer.context.data_points);
115+
116+
if (citation.type === "document")
117+
return (
118+
<a key={i} className={styles.citation} title={x} onClick={() => onCitationClicked(path)}>
119+
{`${++i}. ${x}`}
120+
</a>
121+
);
122+
else if (citation.type === "web") {
123+
const webPage = citation.citation as WebPage;
124+
const label = webPage.siteName ? webPage.siteName : webPage.url;
125+
return (
126+
<a key={i} className={styles.citation} title={label} href={webPage.url} target="_blank" rel="noreferrer">
127+
{`${++i}. ${label}`}
128+
</a>
129+
);
130+
}
118131
})}
119132
</Stack>
120133
</Stack.Item>

app/frontend/src/components/Answer/AnswerParser.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,40 @@
11
import { renderToStaticMarkup } from "react-dom/server";
22
import { ChatAppResponse, getCitationFilePath } from "../../api";
3+
import { WebPage } from "../SupportingContent";
34

45
type HtmlParsedAnswer = {
56
answerHtml: string;
67
citations: string[];
78
};
89

10+
type Citation = {
11+
id: string;
12+
type: "document" | "web";
13+
citation: string | WebPage;
14+
};
15+
16+
export function citationIdToCitation(citationId: string, contextDataPoints: any): Citation {
17+
// See if this is a web page citation
18+
const webSearch = contextDataPoints.web_search;
19+
if (Array.isArray(webSearch)) {
20+
const webPage = webSearch.find((page: WebPage) => page.id === citationId);
21+
if (webPage) {
22+
return {
23+
id: citationId,
24+
type: "web",
25+
citation: webPage
26+
};
27+
}
28+
}
29+
30+
// Otherwise, assume it's a document citation
31+
return {
32+
id: citationId,
33+
type: "document",
34+
citation: citationId
35+
};
36+
}
37+
938
// Function to validate citation format and check if dataPoint starts with possible citation
1039
function isCitationValid(contextDataPoints: any, citationCandidate: string): boolean {
1140
const regex = /.+\.\w{1,}(?:#\S*)?$/;
@@ -22,6 +51,14 @@ function isCitationValid(contextDataPoints: any, citationCandidate: string): boo
2251
} else {
2352
return false;
2453
}
54+
// If there are web_sources, add those to the list of identifiers
55+
if (Array.isArray(contextDataPoints.web_search)) {
56+
contextDataPoints.web_search.forEach((source: any) => {
57+
if (source.id) {
58+
dataPointsArray.push(source.id);
59+
}
60+
});
61+
}
2562

2663
const isValidCitation = dataPointsArray.some(dataPoint => {
2764
return dataPoint.startsWith(citationCandidate);

app/frontend/src/components/SupportingContent/SupportingContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { parseSupportingContentItem } from "./SupportingContentParser";
22

33
import styles from "./SupportingContent.module.css";
44

5-
interface WebPage {
5+
export interface WebPage {
66
id: string;
77
name: string;
88
url: string;

0 commit comments

Comments
 (0)