Repository navigation
feat(citations): carry structured citations from retrieval into the answer - #113
Merged
Merged
Conversation
…nswer The prompt numbered its sources but threw the provenance away: by the time an answer existed there was no page, block or span to point back at. `SearchResult` already carries a `locator` (#74), so assemble it into a shared `Citation` snapshot — document, page range, block id, char span and the retrieved quote — and persist it under `chat_messages.metadata.citations`. The citation is a snapshot, not a reference: re-indexing or deleting the source later must not erase where the answer was grounded. A defensive reader (`parseCitations`) drops malformed rows individually so one bad entry cannot hide the rest. The renderer's in-memory message never sees the DB row written before streaming, so the persisted metadata also rides along on the `finish` event; otherwise an answer would stay un-citable until the session was reloaded. Refs #69
5 of 7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Makes an answer's sources resolvable to a page and paragraph. Retrieval already knows the source's
locator(page range, block ids, char span) after #74; this PR assembles it into a sharedCitation, asks the model to mark sources with[n], and persists the result underchat_messages.metadata.citations— with no schema change.Why?
The prompt numbered its sources (
[来源 1: …]) but droppedchunkId,documentId, page and block. Once an answer existed there was no way back to the original document, which is the point of the v1.4 Trusted Research Loop epic (#82).Related issue
Fixes #69
What changed?
src/shared/types/citation.ts— theCitationcontract (document, page range, block id, char span, quote, score). A snapshot, not a reference, so re-indexing or deleting the source cannot erase where the answer was grounded.src/main/services/citations.ts— purecitationFromSearchResult/buildCitations, plus the RAG context assembly moved out ofchatHandlersso it is testable without Electron. The prompt now instructs the model to mark sources with[n].src/main/ipc/chatHandlers.ts— persistscitationsalongside the existingsources, and sends the persisted metadata on thefinishstreaming event.src/shared/utils/citations.ts— defensiveparseCitationsreader; drops malformed rows individually, keeps citations whose document was deleted.src/shared/types/chat.ts—citationsonChatMessageMetadata.chatStoreappliesmessageMetadataonfinishso an answer is citable without a session reload.How was this tested?
npm run typecheck— passes (node, web, test).npm test— 138 tests pass, including 15 new cases intest/citations.test.ts(page/block/span assembly, multi-block spans, unpaginated sources,[n]prompt instruction, defensive parsing, deleted-document record).Manual UI verification of the chat flow (two-page fixture) is pending; the streaming metadata handoff is covered structurally by the
finishevent change.Screenshots / recordings
Not applicable (no visible UI change yet; citation chips land in #72).
Checklist
npm run typecheckpasses.npm run buildpasses.Desktop / build changes