Skip to content

Commit add3cad

Browse files
authored
Merge pull request #85 from Ontos-AI/fix/wangbinqi/retrieval-response-contract
fix: sync retrieval response SDK contract
2 parents 8e95c73 + 25b8c30 commit add3cad

5 files changed

Lines changed: 99 additions & 14 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ontos-ai/knowhere-sdk": patch
3+
---
4+
5+
Sync retrieval response types with the current API contract, including evidence text, stop/failure reasons, and typed referenced chunks.

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ const response = await client.retrieval.query({
198198

199199
console.log(response.answerText); // LLM-generated answer
200200
console.log(response.referencedChunks); // cited evidence chunks
201+
console.log(response.evidenceText); // rendered evidence context, when returned
202+
console.log(response.stopReason); // agentic termination reason, when returned
203+
console.log(response.failureReason); // no-answer reason, when returned
201204

202205
for (const result of response.results) {
203206
console.log(result.content);
@@ -218,6 +221,20 @@ result.source.sourceFileName;
218221
result.source.sectionPath;
219222
```
220223

224+
Agentic references expose the current retrieval citation fields:
225+
226+
```typescript
227+
const reference = response.referencedChunks[0];
228+
229+
reference.chunkId;
230+
reference.documentId;
231+
reference.chunkType;
232+
reference.sectionPath;
233+
reference.filePath;
234+
reference.jobId;
235+
reference.assetUrl;
236+
```
237+
221238
Use `documentId` to update or archive a document:
222239

223240
```typescript

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export type {
3030
RetrievalQueryParams,
3131
RetrievalSource,
3232
RetrievalResult,
33+
RetrievalReferencedChunk,
3334
RetrievalQueryResponse,
3435
// Parameter types
3536
ParsingParams,

src/resources/__tests__/retrieval.test.ts

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, it, expect, beforeEach, vi } from 'vitest';
22
import { Retrieval } from '../retrieval.js';
33
import type { HttpClient } from '../../lib/http-client.js';
4+
import type { RetrievalQueryResponse, RetrievalReferencedChunk } from '../../types/retrieval.js';
45

56
describe('Retrieval Resource', () => {
67
let retrieval: Retrieval;
@@ -20,6 +21,8 @@ describe('Retrieval Resource', () => {
2021
namespace: 'support-center',
2122
query: 'refund policy',
2223
routerUsed: 'discovery+agent',
24+
answerText: null,
25+
referencedChunks: [],
2326
results: [
2427
{
2528
content: 'Annual plans may be refunded within 30 days.',
@@ -95,6 +98,9 @@ describe('Retrieval Resource', () => {
9598
mockHttpClient.post.mockResolvedValue({
9699
namespace: 'default',
97100
query: 'refund policy',
101+
routerUsed: 'small_corpus_all',
102+
answerText: null,
103+
referencedChunks: [],
98104
results: [],
99105
});
100106

@@ -111,7 +117,17 @@ describe('Retrieval Resource', () => {
111117
query: 'test',
112118
routerUsed: 'workflow_single_step',
113119
answerText: 'Generated answer',
114-
referencedChunks: [{ chunkId: 'chunk-1', assetUrl: 'https://example.com' }],
120+
referencedChunks: [
121+
{
122+
chunkId: 'chunk-1',
123+
documentId: 'doc-1',
124+
chunkType: 'image',
125+
sectionPath: 'Images',
126+
filePath: 'images/chunk-1.png',
127+
jobId: 'job-1',
128+
assetUrl: 'https://example.com',
129+
},
130+
],
115131
results: [],
116132
});
117133

@@ -129,30 +145,50 @@ describe('Retrieval Resource', () => {
129145
query: 'test',
130146
routerUsed: 'workflow_single_step',
131147
answerText: 'LLM-generated answer',
148+
evidenceText: 'Rendered retrieval evidence',
149+
stopReason: 'answer_done',
150+
failureReason: 'insufficient evidence',
132151
referencedChunks: [
133-
{ chunkId: 'chunk-1', documentId: 'doc-1', assetUrl: 'https://example.com/1' },
152+
{
153+
chunkId: 'chunk-1',
154+
documentId: 'doc-1',
155+
chunkType: 'text',
156+
sectionPath: 'Root',
157+
filePath: null,
158+
jobId: 'job-1',
159+
assetUrl: 'https://example.com/1',
160+
},
134161
],
135162
results: [],
136163
});
137164

138165
const response = await retrieval.query({ query: 'test', useAgentic: true });
166+
const typedResponse: RetrievalQueryResponse = response;
167+
const referencedChunk: RetrievalReferencedChunk | undefined = response.referencedChunks[0];
139168

140-
expect(response.answerText).toBe('LLM-generated answer');
169+
expect(typedResponse.answerText).toBe('LLM-generated answer');
170+
expect(response.evidenceText).toBe('Rendered retrieval evidence');
171+
expect(response.stopReason).toBe('answer_done');
172+
expect(response.failureReason).toBe('insufficient evidence');
141173
expect(response.referencedChunks).toHaveLength(1);
142-
expect(response.referencedChunks?.[0]?.chunkId).toBe('chunk-1');
174+
expect(referencedChunk?.chunkId).toBe('chunk-1');
175+
expect(referencedChunk?.filePath).toBeNull();
143176
});
144177

145178
it('should handle legacy response without agentic fields', async () => {
146179
mockHttpClient.post.mockResolvedValue({
147180
namespace: 'default',
148181
query: 'refund policy',
182+
routerUsed: 'small_corpus_all',
183+
answerText: null,
184+
referencedChunks: [],
149185
results: [],
150186
});
151187

152188
const response = await retrieval.query({ query: 'refund policy' });
153189

154-
expect(response.answerText).toBeUndefined();
155-
expect(response.referencedChunks).toBeUndefined();
190+
expect(response.answerText).toBeNull();
191+
expect(response.referencedChunks).toEqual([]);
156192
expect(response.results).toEqual([]);
157193
});
158194

src/types/retrieval.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ export interface RetrievalQueryParams {
6363
*/
6464
export interface RetrievalSource {
6565
/** Stable document identifier */
66-
documentId?: string;
66+
documentId?: string | null;
6767
/** Original source file name */
68-
sourceFileName?: string;
68+
sourceFileName?: string | null;
6969
/** Human-readable section path */
70-
sectionPath?: string;
70+
sectionPath?: string | null;
7171
}
7272

7373
/**
@@ -86,6 +86,26 @@ export interface RetrievalResult {
8686
source: RetrievalSource;
8787
}
8888

89+
/**
90+
* Cited evidence chunk returned by agentic retrieval.
91+
*/
92+
export interface RetrievalReferencedChunk {
93+
/** Parser-provided chunk identifier */
94+
chunkId: string;
95+
/** Stable document identifier */
96+
documentId: string;
97+
/** Chunk type, for example text, image, or table */
98+
chunkType: string;
99+
/** Human-readable section path */
100+
sectionPath: string;
101+
/** Generated artifact file path for media chunks */
102+
filePath?: string | null;
103+
/** Published job identifier for the referenced chunk */
104+
jobId?: string | null;
105+
/** Presigned asset URL for media chunks when available */
106+
assetUrl?: string | null;
107+
}
108+
89109
/**
90110
* Response from POST /v1/retrieval/query.
91111
*/
@@ -95,11 +115,17 @@ export interface RetrievalQueryResponse {
95115
/** Echoed query text */
96116
query: string;
97117
/** Retrieval router path used by the API for this query */
98-
routerUsed?: string;
99-
/** LLM-generated natural-language answer (agentic mode only) */
100-
answerText?: string | null;
101-
/** Cited evidence chunks with asset URLs (agentic mode only) */
102-
referencedChunks?: Array<Record<string, unknown>> | null;
118+
routerUsed: string;
119+
/** LLM-generated natural-language answer, or null when no answer was produced */
120+
answerText: string | null;
121+
/** Cited evidence chunks with asset URLs when available */
122+
referencedChunks: RetrievalReferencedChunk[];
123+
/** Rendered evidence context used by agentic answer synthesis */
124+
evidenceText?: string;
125+
/** Agentic termination reason when provided by the API */
126+
stopReason?: string;
127+
/** Semantic failure reason when no answer could be produced */
128+
failureReason?: string;
103129
/** Ranked retrieval results */
104130
results: RetrievalResult[];
105131
}

0 commit comments

Comments
 (0)