@exulu/backend 1.48.1 → 1.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +353 -42
  3. package/dist/index.d.cts +422 -327
  4. package/dist/index.d.ts +422 -327
  5. package/dist/index.js +341 -38
  6. package/ee/{markdown.ts → chunking/markdown.ts} +2 -2
  7. package/ee/python/README.md +295 -0
  8. package/ee/python/documents/processing/README.md +155 -0
  9. package/ee/{documents → python/documents}/processing/doc_processor.ts +25 -17
  10. package/ee/{documents/processing/pdf_to_markdown.py → python/documents/processing/document_to_markdown.py} +3 -10
  11. package/ee/python/setup.sh +180 -0
  12. package/package.json +17 -5
  13. package/scripts/postinstall.cjs +149 -0
  14. package/.agents/skills/mintlify/SKILL.md +0 -347
  15. package/.editorconfig +0 -15
  16. package/.eslintrc.json +0 -52
  17. package/.github/workflows/release-backend.yml +0 -38
  18. package/.husky/commit-msg +0 -1
  19. package/.jscpd.json +0 -18
  20. package/.mcp.json +0 -18
  21. package/.nvmrc +0 -1
  22. package/.prettierignore +0 -5
  23. package/.prettierrc.json +0 -12
  24. package/CHANGELOG.md +0 -6
  25. package/SECURITY.md +0 -5
  26. package/commitlint.config.js +0 -4
  27. package/devops/documentation/patch-older-releases.md +0 -42
  28. package/ee/documents/processing/build_pdf_processor.sh +0 -35
  29. package/ee/documents/processing/chunk_markdown.py +0 -263
  30. package/ee/documents/processing/pdf_processor.spec +0 -115
  31. package/eslint.config.js +0 -88
  32. package/jest.config.ts +0 -25
  33. package/mintlify-docs/.mintignore +0 -7
  34. package/mintlify-docs/AGENTS.md +0 -33
  35. package/mintlify-docs/CLAUDE.MD +0 -50
  36. package/mintlify-docs/CONTRIBUTING.md +0 -32
  37. package/mintlify-docs/LICENSE +0 -21
  38. package/mintlify-docs/README.md +0 -55
  39. package/mintlify-docs/ai-tools/claude-code.mdx +0 -43
  40. package/mintlify-docs/ai-tools/cursor.mdx +0 -39
  41. package/mintlify-docs/ai-tools/windsurf.mdx +0 -39
  42. package/mintlify-docs/api-reference/core-types/agent-types.mdx +0 -110
  43. package/mintlify-docs/api-reference/core-types/analytics-types.mdx +0 -95
  44. package/mintlify-docs/api-reference/core-types/configuration-types.mdx +0 -83
  45. package/mintlify-docs/api-reference/core-types/evaluation-types.mdx +0 -106
  46. package/mintlify-docs/api-reference/core-types/job-types.mdx +0 -135
  47. package/mintlify-docs/api-reference/core-types/overview.mdx +0 -73
  48. package/mintlify-docs/api-reference/core-types/prompt-types.mdx +0 -102
  49. package/mintlify-docs/api-reference/core-types/rbac-types.mdx +0 -163
  50. package/mintlify-docs/api-reference/core-types/session-types.mdx +0 -77
  51. package/mintlify-docs/api-reference/core-types/user-management.mdx +0 -112
  52. package/mintlify-docs/api-reference/core-types/workflow-types.mdx +0 -88
  53. package/mintlify-docs/api-reference/core-types.mdx +0 -585
  54. package/mintlify-docs/api-reference/dynamic-types.mdx +0 -851
  55. package/mintlify-docs/api-reference/endpoint/create.mdx +0 -4
  56. package/mintlify-docs/api-reference/endpoint/delete.mdx +0 -4
  57. package/mintlify-docs/api-reference/endpoint/get.mdx +0 -4
  58. package/mintlify-docs/api-reference/endpoint/webhook.mdx +0 -4
  59. package/mintlify-docs/api-reference/introduction.mdx +0 -661
  60. package/mintlify-docs/api-reference/mutations.mdx +0 -1012
  61. package/mintlify-docs/api-reference/openapi.json +0 -217
  62. package/mintlify-docs/api-reference/queries.mdx +0 -1154
  63. package/mintlify-docs/backend/introduction.mdx +0 -218
  64. package/mintlify-docs/changelog.mdx +0 -387
  65. package/mintlify-docs/community-edition.mdx +0 -304
  66. package/mintlify-docs/core/exulu-agent/api-reference.mdx +0 -894
  67. package/mintlify-docs/core/exulu-agent/configuration.mdx +0 -690
  68. package/mintlify-docs/core/exulu-agent/introduction.mdx +0 -552
  69. package/mintlify-docs/core/exulu-app/api-reference.mdx +0 -481
  70. package/mintlify-docs/core/exulu-app/configuration.mdx +0 -319
  71. package/mintlify-docs/core/exulu-app/introduction.mdx +0 -117
  72. package/mintlify-docs/core/exulu-authentication.mdx +0 -810
  73. package/mintlify-docs/core/exulu-chunkers/api-reference.mdx +0 -1011
  74. package/mintlify-docs/core/exulu-chunkers/configuration.mdx +0 -596
  75. package/mintlify-docs/core/exulu-chunkers/introduction.mdx +0 -403
  76. package/mintlify-docs/core/exulu-context/api-reference.mdx +0 -911
  77. package/mintlify-docs/core/exulu-context/configuration.mdx +0 -648
  78. package/mintlify-docs/core/exulu-context/introduction.mdx +0 -394
  79. package/mintlify-docs/core/exulu-database.mdx +0 -811
  80. package/mintlify-docs/core/exulu-default-agents.mdx +0 -545
  81. package/mintlify-docs/core/exulu-eval/api-reference.mdx +0 -772
  82. package/mintlify-docs/core/exulu-eval/configuration.mdx +0 -680
  83. package/mintlify-docs/core/exulu-eval/introduction.mdx +0 -459
  84. package/mintlify-docs/core/exulu-logging.mdx +0 -464
  85. package/mintlify-docs/core/exulu-otel.mdx +0 -670
  86. package/mintlify-docs/core/exulu-queues/api-reference.mdx +0 -648
  87. package/mintlify-docs/core/exulu-queues/configuration.mdx +0 -650
  88. package/mintlify-docs/core/exulu-queues/introduction.mdx +0 -474
  89. package/mintlify-docs/core/exulu-reranker/api-reference.mdx +0 -630
  90. package/mintlify-docs/core/exulu-reranker/configuration.mdx +0 -663
  91. package/mintlify-docs/core/exulu-reranker/introduction.mdx +0 -516
  92. package/mintlify-docs/core/exulu-tool/api-reference.mdx +0 -723
  93. package/mintlify-docs/core/exulu-tool/configuration.mdx +0 -805
  94. package/mintlify-docs/core/exulu-tool/introduction.mdx +0 -539
  95. package/mintlify-docs/core/exulu-variables/api-reference.mdx +0 -699
  96. package/mintlify-docs/core/exulu-variables/configuration.mdx +0 -736
  97. package/mintlify-docs/core/exulu-variables/introduction.mdx +0 -511
  98. package/mintlify-docs/development.mdx +0 -94
  99. package/mintlify-docs/docs.json +0 -248
  100. package/mintlify-docs/enterprise-edition.mdx +0 -538
  101. package/mintlify-docs/essentials/code.mdx +0 -35
  102. package/mintlify-docs/essentials/images.mdx +0 -59
  103. package/mintlify-docs/essentials/markdown.mdx +0 -88
  104. package/mintlify-docs/essentials/navigation.mdx +0 -87
  105. package/mintlify-docs/essentials/reusable-snippets.mdx +0 -110
  106. package/mintlify-docs/essentials/settings.mdx +0 -318
  107. package/mintlify-docs/favicon.svg +0 -3
  108. package/mintlify-docs/frontend/introduction.mdx +0 -39
  109. package/mintlify-docs/getting-started.mdx +0 -267
  110. package/mintlify-docs/guides/custom-agent.mdx +0 -608
  111. package/mintlify-docs/guides/first-agent.mdx +0 -315
  112. package/mintlify-docs/images/admin_ui.png +0 -0
  113. package/mintlify-docs/images/contexts.png +0 -0
  114. package/mintlify-docs/images/create_agents.png +0 -0
  115. package/mintlify-docs/images/evals.png +0 -0
  116. package/mintlify-docs/images/graphql.png +0 -0
  117. package/mintlify-docs/images/graphql_api.png +0 -0
  118. package/mintlify-docs/images/hero-dark.png +0 -0
  119. package/mintlify-docs/images/hero-light.png +0 -0
  120. package/mintlify-docs/images/hero.png +0 -0
  121. package/mintlify-docs/images/knowledge_sources.png +0 -0
  122. package/mintlify-docs/images/mcp.png +0 -0
  123. package/mintlify-docs/images/scaling.png +0 -0
  124. package/mintlify-docs/index.mdx +0 -411
  125. package/mintlify-docs/logo/dark.svg +0 -9
  126. package/mintlify-docs/logo/light.svg +0 -9
  127. package/mintlify-docs/partners.mdx +0 -558
  128. package/mintlify-docs/products.mdx +0 -77
  129. package/mintlify-docs/snippets/snippet-intro.mdx +0 -4
  130. package/mintlify-docs/styles.css +0 -207
  131. package/ngrok.bash +0 -1
  132. package/ngrok.md +0 -6
  133. package/ngrok.yml +0 -10
  134. package/release.config.cjs +0 -15
  135. package/skills-lock.json +0 -10
  136. package/types/context-processor.ts +0 -45
  137. package/types/enums/eval-types.ts +0 -5
  138. package/types/enums/field-types.ts +0 -1
  139. package/types/enums/jobs.ts +0 -11
  140. package/types/enums/statistics.ts +0 -13
  141. package/types/exulu-table-definition.ts +0 -79
  142. package/types/file-types.ts +0 -18
  143. package/types/models/agent-session.ts +0 -27
  144. package/types/models/agent.ts +0 -68
  145. package/types/models/context.ts +0 -53
  146. package/types/models/embedding.ts +0 -17
  147. package/types/models/eval-run.ts +0 -40
  148. package/types/models/exulu-agent-tool-config.ts +0 -11
  149. package/types/models/item.ts +0 -21
  150. package/types/models/job.ts +0 -8
  151. package/types/models/project.ts +0 -16
  152. package/types/models/rate-limiter-rules.ts +0 -7
  153. package/types/models/test-case.ts +0 -25
  154. package/types/models/tool.ts +0 -9
  155. package/types/models/user-role.ts +0 -12
  156. package/types/models/user.ts +0 -20
  157. package/types/models/variable.ts +0 -8
  158. package/types/models/vector-methods.ts +0 -7
  159. package/types/provider-config.ts +0 -21
  160. package/types/queue-config.ts +0 -16
  161. package/types/rbac-rights-modes.ts +0 -1
  162. package/types/statistics.ts +0 -20
  163. package/types/workflow.ts +0 -31
  164. /package/ee/{documents → python/documents}/THIRD_PARTY_LICENSES/docling.txt +0 -0
  165. /package/ee/{documents/processing → python}/requirements.txt +0 -0
@@ -1,630 +0,0 @@
1
- ---
2
- title: "API reference"
3
- description: "Complete method and property reference for ExuluReranker"
4
- ---
5
-
6
- ## Constructor
7
-
8
- ```typescript
9
- const reranker = new ExuluReranker(options: ExuluRerankerOptions);
10
- ```
11
-
12
- Creates a new ExuluReranker instance. See the [configuration guide](/core/exulu-reranker/configuration) for all available options.
13
-
14
- ## Methods
15
-
16
- ### run()
17
-
18
- Executes the reranker to reorder search result chunks based on relevance to the query.
19
-
20
- ```typescript
21
- async run(
22
- query: string,
23
- chunks: VectorSearchChunkResult[]
24
- ): Promise<VectorSearchChunkResult[]>
25
- ```
26
-
27
- <ParamField path="query" type="string" required>
28
- The user's search query that the chunks should be ranked against
29
- </ParamField>
30
-
31
- <ParamField path="chunks" type="VectorSearchChunkResult[]" required>
32
- Array of search result chunks to rerank
33
- </ParamField>
34
-
35
- <ResponseField name="return" type="Promise<VectorSearchChunkResult[]>">
36
- Reordered array of chunks, typically sorted by relevance (most relevant first)
37
- </ResponseField>
38
-
39
- ```typescript
40
- const reranker = new ExuluReranker({
41
- id: "cohere_rerank",
42
- name: "Cohere Reranker",
43
- description: "Uses Cohere's rerank API",
44
- execute: async ({ query, chunks }) => {
45
- // Reranking logic
46
- return reorderedChunks;
47
- }
48
- });
49
-
50
- // Get initial search results
51
- const searchResults = await context.search({
52
- query: "How do I authenticate users?",
53
- method: "hybridSearch",
54
- limit: 20,
55
- // ...
56
- });
57
-
58
- // Rerank the results
59
- const rerankedChunks = await reranker.run(
60
- "How do I authenticate users?",
61
- searchResults.chunks
62
- );
63
-
64
- console.log(rerankedChunks[0].chunk_content); // Most relevant chunk
65
- ```
66
-
67
- <Note>
68
- The `run()` method is a convenience wrapper that calls the `execute()` function with the proper parameter structure.
69
- </Note>
70
-
71
- ## Properties
72
-
73
- ### id
74
-
75
- <ResponseField name="id" type="string">
76
- Unique identifier for the reranker
77
- </ResponseField>
78
-
79
- ```typescript
80
- console.log(reranker.id); // "cohere_rerank_v3"
81
- ```
82
-
83
- ### name
84
-
85
- <ResponseField name="name" type="string">
86
- Human-readable name for the reranker
87
- </ResponseField>
88
-
89
- ```typescript
90
- console.log(reranker.name); // "Cohere Rerank English v3"
91
- ```
92
-
93
- ### description
94
-
95
- <ResponseField name="description" type="string">
96
- Description of what the reranker does
97
- </ResponseField>
98
-
99
- ```typescript
100
- console.log(reranker.description);
101
- // "Reranks search results using Cohere's rerank-english-v3.0 model"
102
- ```
103
-
104
- ### execute
105
-
106
- <ResponseField name="execute" type="ExecuteFunction">
107
- The function that implements the reranking logic
108
- </ResponseField>
109
-
110
- ```typescript
111
- // The execute function has this signature
112
- type ExecuteFunction = (params: {
113
- query: string;
114
- chunks: VectorSearchChunkResult[];
115
- }) => Promise<VectorSearchChunkResult[]>;
116
-
117
- // Access it directly
118
- const result = await reranker.execute({
119
- query: "test query",
120
- chunks: chunks
121
- });
122
- ```
123
-
124
- <Info>
125
- While you can call `execute()` directly, it's recommended to use the `run()` method for better readability.
126
- </Info>
127
-
128
- ## Type definitions
129
-
130
- ```typescript
131
- // Reranker constructor options
132
- type ExuluRerankerOptions = {
133
- id: string;
134
- name: string;
135
- description: string;
136
- execute: ExecuteFunction;
137
- };
138
-
139
- // Execute function type
140
- type ExecuteFunction = (params: {
141
- query: string;
142
- chunks: VectorSearchChunkResult[];
143
- }) => Promise<VectorSearchChunkResult[]>;
144
-
145
- // Chunk result type
146
- type VectorSearchChunkResult = {
147
- chunk_content: string;
148
- chunk_index: number;
149
- chunk_id: string;
150
- chunk_source: string;
151
- chunk_metadata: Record<string, string>;
152
- chunk_created_at: string;
153
- chunk_updated_at: string;
154
- item_id: string;
155
- item_external_id: string;
156
- item_name: string;
157
- item_updated_at: string;
158
- item_created_at: string;
159
- chunk_cosine_distance?: number;
160
- chunk_fts_rank?: number;
161
- chunk_hybrid_score?: number;
162
- context?: {
163
- name: string;
164
- id: string;
165
- };
166
- };
167
- ```
168
-
169
- ## Usage examples
170
-
171
- ### Basic usage
172
-
173
- ```typescript
174
- import { ExuluReranker } from "@exulu/backend";
175
-
176
- const reranker = new ExuluReranker({
177
- id: "simple_reranker",
178
- name: "Simple Reranker",
179
- description: "Reranks by chunk length",
180
- execute: async ({ query, chunks }) => {
181
- // Sort by content length (example)
182
- return chunks.sort((a, b) =>
183
- b.chunk_content.length - a.chunk_content.length
184
- );
185
- }
186
- });
187
-
188
- const reranked = await reranker.run(query, chunks);
189
- ```
190
-
191
- ### With Cohere API
192
-
193
- ```typescript
194
- const cohereReranker = new ExuluReranker({
195
- id: "cohere_rerank",
196
- name: "Cohere Reranker",
197
- description: "Uses Cohere rerank-english-v3.0",
198
- execute: async ({ query, chunks }) => {
199
- const response = await fetch("https://api.cohere.com/v1/rerank", {
200
- method: "POST",
201
- headers: {
202
- "Authorization": `Bearer ${process.env.COHERE_API_KEY}`,
203
- "Content-Type": "application/json"
204
- },
205
- body: JSON.stringify({
206
- model: "rerank-english-v3.0",
207
- query: query,
208
- documents: chunks.map(c => c.chunk_content),
209
- top_n: 20
210
- })
211
- });
212
-
213
- const data = await response.json();
214
-
215
- return data.results
216
- .sort((a, b) => b.relevance_score - a.relevance_score)
217
- .map(result => chunks[result.index]);
218
- }
219
- });
220
-
221
- // Use it
222
- const results = await context.search({
223
- query: "authentication",
224
- method: "hybridSearch",
225
- limit: 50
226
- });
227
-
228
- const reranked = await cohereReranker.run(
229
- "authentication",
230
- results.chunks
231
- );
232
- ```
233
-
234
- ### With ExuluContext integration
235
-
236
- ```typescript
237
- import { ExuluContext, ExuluReranker } from "@exulu/backend";
238
-
239
- // Create reranker
240
- const reranker = new ExuluReranker({
241
- id: "my_reranker",
242
- name: "My Reranker",
243
- description: "Custom reranking logic",
244
- execute: async ({ query, chunks }) => {
245
- // Your reranking implementation
246
- return reorderedChunks;
247
- }
248
- });
249
-
250
- // Use with context
251
- const context = new ExuluContext({
252
- id: "docs",
253
- name: "Documentation",
254
- description: "Product documentation",
255
- active: true,
256
- fields: [
257
- { name: "title", type: "text", required: true },
258
- { name: "content", type: "longtext", required: true }
259
- ],
260
- sources: [],
261
- embedder: myEmbedder,
262
- resultReranker: async (chunks) => {
263
- // Extract query from first chunk's context
264
- const query = chunks[0]?.context?.query || "";
265
-
266
- // Run reranker
267
- return reranker.run(query, chunks);
268
- }
269
- });
270
-
271
- // Now all searches through this context will be reranked
272
- const results = await context.search({
273
- query: "How do I configure logging?",
274
- method: "hybridSearch",
275
- limit: 10
276
- });
277
-
278
- // results.chunks are already reranked
279
- ```
280
-
281
- ### Custom scoring reranker
282
-
283
- ```typescript
284
- const customReranker = new ExuluReranker({
285
- id: "custom_scorer",
286
- name: "Custom Scorer",
287
- description: "Reranks with custom business logic",
288
- execute: async ({ query, chunks }) => {
289
- // Compute custom score for each chunk
290
- const scored = chunks.map(chunk => {
291
- let score = chunk.chunk_hybrid_score || 0;
292
-
293
- // Boost recent content
294
- const daysSinceUpdate = (Date.now() - new Date(chunk.chunk_updated_at).getTime()) / (1000 * 60 * 60 * 24);
295
- score += Math.max(0, 1 - daysSinceUpdate / 365);
296
-
297
- // Boost certain categories
298
- if (chunk.chunk_metadata.category === "tutorial") {
299
- score *= 1.5;
300
- }
301
-
302
- // Boost exact keyword matches
303
- const queryLower = query.toLowerCase();
304
- const contentLower = chunk.chunk_content.toLowerCase();
305
- if (contentLower.includes(queryLower)) {
306
- score *= 1.2;
307
- }
308
-
309
- return { chunk, score };
310
- });
311
-
312
- // Sort by score descending
313
- scored.sort((a, b) => b.score - a.score);
314
-
315
- return scored.map(s => s.chunk);
316
- }
317
- });
318
-
319
- // Use it
320
- const reranked = await customReranker.run(
321
- "authentication setup",
322
- searchResults.chunks
323
- );
324
- ```
325
-
326
- ### Error-resilient reranker
327
-
328
- ```typescript
329
- const resilientReranker = new ExuluReranker({
330
- id: "resilient",
331
- name: "Resilient Reranker",
332
- description: "Falls back to original order on errors",
333
- execute: async ({ query, chunks }) => {
334
- try {
335
- // Attempt reranking
336
- const response = await fetch(RERANK_API_URL, {
337
- method: "POST",
338
- headers: { /* ... */ },
339
- body: JSON.stringify({
340
- query,
341
- documents: chunks.map(c => c.chunk_content)
342
- })
343
- });
344
-
345
- if (!response.ok) {
346
- throw new Error(`API returned ${response.status}`);
347
- }
348
-
349
- const data = await response.json();
350
- return data.results.map(r => chunks[r.index]);
351
-
352
- } catch (error) {
353
- console.error("Reranking failed, using original order:", error);
354
-
355
- // Return original order as fallback
356
- return chunks;
357
- }
358
- }
359
- });
360
- ```
361
-
362
- ### Caching reranker
363
-
364
- ```typescript
365
- import crypto from "crypto";
366
-
367
- const cache = new Map<string, VectorSearchChunkResult[]>();
368
-
369
- const cachedReranker = new ExuluReranker({
370
- id: "cached",
371
- name: "Cached Reranker",
372
- description: "Caches reranking results",
373
- execute: async ({ query, chunks }) => {
374
- // Create cache key
375
- const chunkIds = chunks.map(c => c.chunk_id).sort().join(",");
376
- const cacheKey = crypto
377
- .createHash("md5")
378
- .update(`${query}:${chunkIds}`)
379
- .digest("hex");
380
-
381
- // Check cache
382
- if (cache.has(cacheKey)) {
383
- console.log("Cache hit");
384
- return cache.get(cacheKey)!;
385
- }
386
-
387
- // Perform reranking
388
- const reranked = await performReranking(query, chunks);
389
-
390
- // Store in cache
391
- cache.set(cacheKey, reranked);
392
-
393
- return reranked;
394
- }
395
- });
396
- ```
397
-
398
- ### Hybrid reranker (API + custom)
399
-
400
- ```typescript
401
- const hybridReranker = new ExuluReranker({
402
- id: "hybrid",
403
- name: "Hybrid Reranker",
404
- description: "Combines API reranking with custom scoring",
405
- execute: async ({ query, chunks }) => {
406
- // Get API scores
407
- const apiResponse = await fetch(RERANK_API_URL, {
408
- method: "POST",
409
- headers: { /* ... */ },
410
- body: JSON.stringify({
411
- query,
412
- documents: chunks.map(c => c.chunk_content)
413
- })
414
- });
415
-
416
- const apiData = await apiResponse.json();
417
-
418
- // Combine with custom scoring
419
- const scored = chunks.map((chunk, idx) => {
420
- // API relevance score (0-1)
421
- const apiScore = apiData.results.find(r => r.index === idx)?.relevance_score || 0;
422
-
423
- // Custom score (0-1)
424
- const recency = Math.max(0, 1 - (Date.now() - new Date(chunk.chunk_updated_at).getTime()) / (365 * 24 * 60 * 60 * 1000));
425
- const categoryBoost = chunk.chunk_metadata.priority === "high" ? 0.2 : 0;
426
- const customScore = Math.min(1, recency + categoryBoost);
427
-
428
- // Weighted combination: 70% API, 30% custom
429
- const finalScore = (apiScore * 0.7) + (customScore * 0.3);
430
-
431
- return { chunk, score: finalScore };
432
- });
433
-
434
- scored.sort((a, b) => b.score - a.score);
435
- return scored.map(s => s.chunk);
436
- }
437
- });
438
- ```
439
-
440
- ### LLM-based reranker
441
-
442
- ```typescript
443
- import OpenAI from "openai";
444
-
445
- const openai = new OpenAI();
446
-
447
- const llmReranker = new ExuluReranker({
448
- id: "llm_rerank",
449
- name: "LLM Reranker",
450
- description: "Uses GPT-4 to judge relevance",
451
- execute: async ({ query, chunks }) => {
452
- // Limit to top 10 for cost control
453
- const topChunks = chunks.slice(0, 10);
454
-
455
- // Score in parallel
456
- const scored = await Promise.all(
457
- topChunks.map(async (chunk) => {
458
- const response = await openai.chat.completions.create({
459
- model: "gpt-4o-mini",
460
- messages: [{
461
- role: "user",
462
- content: `On a scale of 0-10, how relevant is this passage to the query?
463
-
464
- Query: "${query}"
465
-
466
- Passage: "${chunk.chunk_content}"
467
-
468
- Respond with only a number.`
469
- }],
470
- temperature: 0,
471
- max_tokens: 5
472
- });
473
-
474
- const score = parseFloat(response.choices[0].message.content || "0");
475
-
476
- return { chunk, score };
477
- })
478
- );
479
-
480
- scored.sort((a, b) => b.score - a.score);
481
-
482
- return [
483
- ...scored.map(s => s.chunk),
484
- ...chunks.slice(10) // Append remaining chunks
485
- ];
486
- }
487
- });
488
- ```
489
-
490
- ### Accessing reranker properties
491
-
492
- ```typescript
493
- const reranker = new ExuluReranker({
494
- id: "example",
495
- name: "Example Reranker",
496
- description: "For demonstration",
497
- execute: async ({ query, chunks }) => chunks
498
- });
499
-
500
- // Access properties
501
- console.log(reranker.id); // "example"
502
- console.log(reranker.name); // "Example Reranker"
503
- console.log(reranker.description); // "For demonstration"
504
-
505
- // Call execute directly
506
- const result = await reranker.execute({
507
- query: "test",
508
- chunks: myChunks
509
- });
510
-
511
- // Or use run() for cleaner API
512
- const result2 = await reranker.run("test", myChunks);
513
- ```
514
-
515
- ## Comparison: run() vs execute()
516
-
517
- Both methods do the same thing, but `run()` provides a cleaner API:
518
-
519
- ```typescript
520
- // Using execute() - verbose
521
- const result = await reranker.execute({
522
- query: "test query",
523
- chunks: myChunks
524
- });
525
-
526
- // Using run() - cleaner
527
- const result = await reranker.run("test query", myChunks);
528
- ```
529
-
530
- <Tip>
531
- Use `run()` for external calls and `execute()` when you need to pass the function as a callback.
532
- </Tip>
533
-
534
- ## Integration patterns
535
-
536
- ### Direct usage
537
-
538
- ```typescript
539
- // Get search results
540
- const results = await context.search({
541
- query: "authentication",
542
- method: "hybridSearch",
543
- limit: 50
544
- });
545
-
546
- // Apply reranking
547
- const reranked = await reranker.run(
548
- "authentication",
549
- results.chunks
550
- );
551
-
552
- // Use top results
553
- const topResults = reranked.slice(0, 10);
554
- ```
555
-
556
- ### As context configuration
557
-
558
- ```typescript
559
- const context = new ExuluContext({
560
- // ... other config
561
- resultReranker: async (chunks) => {
562
- const query = chunks[0]?.context?.query || "";
563
- return reranker.run(query, chunks);
564
- }
565
- });
566
-
567
- // Reranking happens automatically
568
- const results = await context.search({
569
- query: "authentication",
570
- method: "hybridSearch"
571
- });
572
- // results.chunks are already reranked
573
- ```
574
-
575
- ### Conditional reranking
576
-
577
- ```typescript
578
- const context = new ExuluContext({
579
- // ... other config
580
- resultReranker: async (chunks) => {
581
- // Only rerank if we have enough results
582
- if (chunks.length < 5) {
583
- return chunks;
584
- }
585
-
586
- // Only rerank if scores are close (ambiguous ranking)
587
- const scores = chunks.map(c => c.chunk_hybrid_score || 0);
588
- const maxScore = Math.max(...scores);
589
- const minScore = Math.min(...scores);
590
-
591
- if (maxScore - minScore > 0.3) {
592
- // Clear winner, skip reranking
593
- return chunks;
594
- }
595
-
596
- // Ambiguous results, apply reranking
597
- const query = chunks[0]?.context?.query || "";
598
- return reranker.run(query, chunks);
599
- }
600
- });
601
- ```
602
-
603
- ## Best practices
604
-
605
- <Tip>
606
- **Always preserve chunk objects**: Return the exact same chunk objects in a new order. Don't create new objects or modify existing ones.
607
- </Tip>
608
-
609
- <Note>
610
- **Handle errors gracefully**: Always return the original chunk order if reranking fails. Don't throw errors.
611
- </Note>
612
-
613
- <Warning>
614
- **Watch latency**: Reranking adds latency. For high-traffic applications, consider caching or limiting the number of chunks to rerank.
615
- </Warning>
616
-
617
- <Info>
618
- **Monitor costs**: API-based reranking has costs. Track usage and consider caching for repeated queries.
619
- </Info>
620
-
621
- ## Next steps
622
-
623
- <CardGroup cols={2}>
624
- <Card title="Configuration guide" icon="gear" href="/core/exulu-reranker/configuration">
625
- Learn about configuration options
626
- </Card>
627
- <Card title="ExuluContext" icon="database" href="/core/exulu-context/introduction">
628
- Learn about search contexts
629
- </Card>
630
- </CardGroup>