fix: inline citations now upgrade to highlighted view (Phase 5.4)
- Added sub_question_text to frontend SourceMetadata type - SubQuestionSection enriches sources with parent sub-question text - buildCitationUrl routes to highlight page when sub_question_text present - processCitations threads highlightReadyKeys through inline citations
This commit is contained in:
parent
c632b9ea3b
commit
1c490ce2fa
|
|
@ -98,10 +98,13 @@ function SubQuestionSection({
|
||||||
highlightReadyKeys: Set<string>
|
highlightReadyKeys: Set<string>
|
||||||
}) {
|
}) {
|
||||||
const [expanded, setExpanded] = useState(false)
|
const [expanded, setExpanded] = useState(false)
|
||||||
|
// Enrich sources with sub_question_text so buildCitationUrl can route to highlight page.
|
||||||
// Look up citations across ALL sub-questions' sources because the LLM
|
// Look up citations across ALL sub-questions' sources because the LLM
|
||||||
// may cite chunks from other sub-questions' contexts.
|
// may cite chunks from other sub-questions' contexts.
|
||||||
const allSources = allSubQuestionSources.flatMap(sq => sq.sources)
|
const allSources = allSubQuestionSources.flatMap(sq =>
|
||||||
const processedAnswer = processCitations(answerSection, allSources)
|
sq.sources.map(s => ({ ...s, sub_question_text: sq.sub_question_text }))
|
||||||
|
)
|
||||||
|
const processedAnswer = processCitations(answerSection, allSources, highlightReadyKeys)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export interface SourceMetadata {
|
||||||
page_number: number | null
|
page_number: number | null
|
||||||
chunk_file_path: string | null
|
chunk_file_path: string | null
|
||||||
document_id: string | null
|
document_id: string | null
|
||||||
|
sub_question_text?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SubQuestionSources {
|
export interface SubQuestionSources {
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,17 @@ export function buildCitationLookupForSubq(
|
||||||
export function processCitationsForSubq(
|
export function processCitationsForSubq(
|
||||||
answerSection: string,
|
answerSection: string,
|
||||||
subQuestionSources: SubQuestionSources[],
|
subQuestionSources: SubQuestionSources[],
|
||||||
subqIndex: number
|
subqIndex: number,
|
||||||
|
highlightKeys?: Set<string>
|
||||||
): string {
|
): string {
|
||||||
const lookup = buildCitationLookupForSubq(subQuestionSources, subqIndex)
|
const lookup = buildCitationLookupForSubq(subQuestionSources, subqIndex)
|
||||||
return replaceCitationPatterns(answerSection, lookup)
|
return replaceCitationPatterns(answerSection, lookup, highlightKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCitationUrl(source: SourceMetadata): string | null {
|
function buildCitationUrl(source: SourceMetadata, highlightReady?: boolean): string | null {
|
||||||
|
if (highlightReady && source.document_id && source.sub_question_text) {
|
||||||
|
return `/api/v1/v2/highlights?document_id=${encodeURIComponent(source.document_id)}&chunk_index=${source.chunk_index}&sub_question=${encodeURIComponent(source.sub_question_text)}`
|
||||||
|
}
|
||||||
if (source.chunk_file_path) {
|
if (source.chunk_file_path) {
|
||||||
return getPdfViewerUrl(
|
return getPdfViewerUrl(
|
||||||
source.chunk_file_path,
|
source.chunk_file_path,
|
||||||
|
|
@ -99,7 +103,8 @@ function findSource(
|
||||||
|
|
||||||
function replaceCitationPatterns(
|
function replaceCitationPatterns(
|
||||||
text: string,
|
text: string,
|
||||||
lookup: Map<string, SourceMetadata>
|
lookup: Map<string, SourceMetadata>,
|
||||||
|
highlightKeys?: Set<string>
|
||||||
): string {
|
): string {
|
||||||
const citationPattern = /(?<!!)\[([^\]]+)\](?!\()/g
|
const citationPattern = /(?<!!)\[([^\]]+)\](?!\()/g
|
||||||
|
|
||||||
|
|
@ -108,7 +113,13 @@ function replaceCitationPatterns(
|
||||||
const source = findSource(trimmed, lookup)
|
const source = findSource(trimmed, lookup)
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
const url = buildCitationUrl(source)
|
let isReady = false
|
||||||
|
if (highlightKeys && source.document_id && source.sub_question_text) {
|
||||||
|
isReady = highlightKeys.has(
|
||||||
|
`${source.document_id}_${source.chunk_index}_${encodeURIComponent(source.sub_question_text)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const url = buildCitationUrl(source, isReady)
|
||||||
if (url) {
|
if (url) {
|
||||||
return `[${trimmed}](${url})`
|
return `[${trimmed}](${url})`
|
||||||
}
|
}
|
||||||
|
|
@ -118,11 +129,11 @@ function replaceCitationPatterns(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processCitations(text: string, sources: SourceMetadata[]): string {
|
export function processCitations(text: string, sources: SourceMetadata[], highlightKeys?: Set<string>): string {
|
||||||
if (!sources.length) return text
|
if (!sources.length) return text
|
||||||
|
|
||||||
const lookup = buildCitationLookup(sources)
|
const lookup = buildCitationLookup(sources)
|
||||||
return replaceCitationPatterns(text, lookup)
|
return replaceCitationPatterns(text, lookup, highlightKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractCitedSources(answerText: string, sources: SourceMetadata[]): SourceMetadata[] {
|
export function extractCitedSources(answerText: string, sources: SourceMetadata[]): SourceMetadata[] {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue