@exulu/backend 1.48.2 → 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 (164) hide show
  1. package/dist/index.cjs +351 -42
  2. package/dist/index.d.cts +96 -1
  3. package/dist/index.d.ts +96 -1
  4. package/dist/index.js +340 -38
  5. package/ee/{markdown.ts → chunking/markdown.ts} +2 -2
  6. package/ee/python/README.md +295 -0
  7. package/ee/python/documents/processing/README.md +155 -0
  8. package/ee/{documents → python/documents}/processing/doc_processor.ts +25 -17
  9. package/ee/{documents/processing/pdf_to_markdown.py → python/documents/processing/document_to_markdown.py} +3 -10
  10. package/ee/python/setup.sh +180 -0
  11. package/package.json +14 -3
  12. package/scripts/postinstall.cjs +149 -0
  13. package/.agents/skills/mintlify/SKILL.md +0 -347
  14. package/.editorconfig +0 -15
  15. package/.eslintrc.json +0 -52
  16. package/.github/workflows/release-backend.yml +0 -38
  17. package/.husky/commit-msg +0 -1
  18. package/.jscpd.json +0 -18
  19. package/.mcp.json +0 -25
  20. package/.nvmrc +0 -1
  21. package/.prettierignore +0 -5
  22. package/.prettierrc.json +0 -12
  23. package/CHANGELOG.md +0 -8
  24. package/SECURITY.md +0 -5
  25. package/commitlint.config.js +0 -4
  26. package/devops/documentation/patch-older-releases.md +0 -42
  27. package/ee/documents/processing/build_pdf_processor.sh +0 -35
  28. package/ee/documents/processing/chunk_markdown.py +0 -263
  29. package/ee/documents/processing/pdf_processor.spec +0 -115
  30. package/eslint.config.js +0 -88
  31. package/jest.config.ts +0 -25
  32. package/mintlify-docs/.mintignore +0 -7
  33. package/mintlify-docs/AGENTS.md +0 -33
  34. package/mintlify-docs/CLAUDE.MD +0 -50
  35. package/mintlify-docs/CONTRIBUTING.md +0 -32
  36. package/mintlify-docs/LICENSE +0 -21
  37. package/mintlify-docs/README.md +0 -55
  38. package/mintlify-docs/ai-tools/claude-code.mdx +0 -43
  39. package/mintlify-docs/ai-tools/cursor.mdx +0 -39
  40. package/mintlify-docs/ai-tools/windsurf.mdx +0 -39
  41. package/mintlify-docs/api-reference/core-types/agent-types.mdx +0 -110
  42. package/mintlify-docs/api-reference/core-types/analytics-types.mdx +0 -95
  43. package/mintlify-docs/api-reference/core-types/configuration-types.mdx +0 -83
  44. package/mintlify-docs/api-reference/core-types/evaluation-types.mdx +0 -106
  45. package/mintlify-docs/api-reference/core-types/job-types.mdx +0 -135
  46. package/mintlify-docs/api-reference/core-types/overview.mdx +0 -73
  47. package/mintlify-docs/api-reference/core-types/prompt-types.mdx +0 -102
  48. package/mintlify-docs/api-reference/core-types/rbac-types.mdx +0 -163
  49. package/mintlify-docs/api-reference/core-types/session-types.mdx +0 -77
  50. package/mintlify-docs/api-reference/core-types/user-management.mdx +0 -112
  51. package/mintlify-docs/api-reference/core-types/workflow-types.mdx +0 -88
  52. package/mintlify-docs/api-reference/core-types.mdx +0 -585
  53. package/mintlify-docs/api-reference/dynamic-types.mdx +0 -851
  54. package/mintlify-docs/api-reference/endpoint/create.mdx +0 -4
  55. package/mintlify-docs/api-reference/endpoint/delete.mdx +0 -4
  56. package/mintlify-docs/api-reference/endpoint/get.mdx +0 -4
  57. package/mintlify-docs/api-reference/endpoint/webhook.mdx +0 -4
  58. package/mintlify-docs/api-reference/introduction.mdx +0 -661
  59. package/mintlify-docs/api-reference/mutations.mdx +0 -1012
  60. package/mintlify-docs/api-reference/openapi.json +0 -217
  61. package/mintlify-docs/api-reference/queries.mdx +0 -1154
  62. package/mintlify-docs/backend/introduction.mdx +0 -218
  63. package/mintlify-docs/changelog.mdx +0 -387
  64. package/mintlify-docs/community-edition.mdx +0 -304
  65. package/mintlify-docs/core/exulu-agent/api-reference.mdx +0 -894
  66. package/mintlify-docs/core/exulu-agent/configuration.mdx +0 -690
  67. package/mintlify-docs/core/exulu-agent/introduction.mdx +0 -552
  68. package/mintlify-docs/core/exulu-app/api-reference.mdx +0 -481
  69. package/mintlify-docs/core/exulu-app/configuration.mdx +0 -319
  70. package/mintlify-docs/core/exulu-app/introduction.mdx +0 -117
  71. package/mintlify-docs/core/exulu-authentication.mdx +0 -810
  72. package/mintlify-docs/core/exulu-chunkers/api-reference.mdx +0 -1011
  73. package/mintlify-docs/core/exulu-chunkers/configuration.mdx +0 -596
  74. package/mintlify-docs/core/exulu-chunkers/introduction.mdx +0 -403
  75. package/mintlify-docs/core/exulu-context/api-reference.mdx +0 -911
  76. package/mintlify-docs/core/exulu-context/configuration.mdx +0 -648
  77. package/mintlify-docs/core/exulu-context/introduction.mdx +0 -394
  78. package/mintlify-docs/core/exulu-database.mdx +0 -811
  79. package/mintlify-docs/core/exulu-default-agents.mdx +0 -545
  80. package/mintlify-docs/core/exulu-eval/api-reference.mdx +0 -772
  81. package/mintlify-docs/core/exulu-eval/configuration.mdx +0 -680
  82. package/mintlify-docs/core/exulu-eval/introduction.mdx +0 -459
  83. package/mintlify-docs/core/exulu-logging.mdx +0 -464
  84. package/mintlify-docs/core/exulu-otel.mdx +0 -670
  85. package/mintlify-docs/core/exulu-queues/api-reference.mdx +0 -648
  86. package/mintlify-docs/core/exulu-queues/configuration.mdx +0 -650
  87. package/mintlify-docs/core/exulu-queues/introduction.mdx +0 -474
  88. package/mintlify-docs/core/exulu-reranker/api-reference.mdx +0 -630
  89. package/mintlify-docs/core/exulu-reranker/configuration.mdx +0 -663
  90. package/mintlify-docs/core/exulu-reranker/introduction.mdx +0 -516
  91. package/mintlify-docs/core/exulu-tool/api-reference.mdx +0 -723
  92. package/mintlify-docs/core/exulu-tool/configuration.mdx +0 -805
  93. package/mintlify-docs/core/exulu-tool/introduction.mdx +0 -539
  94. package/mintlify-docs/core/exulu-variables/api-reference.mdx +0 -699
  95. package/mintlify-docs/core/exulu-variables/configuration.mdx +0 -736
  96. package/mintlify-docs/core/exulu-variables/introduction.mdx +0 -511
  97. package/mintlify-docs/development.mdx +0 -94
  98. package/mintlify-docs/docs.json +0 -248
  99. package/mintlify-docs/enterprise-edition.mdx +0 -538
  100. package/mintlify-docs/essentials/code.mdx +0 -35
  101. package/mintlify-docs/essentials/images.mdx +0 -59
  102. package/mintlify-docs/essentials/markdown.mdx +0 -88
  103. package/mintlify-docs/essentials/navigation.mdx +0 -87
  104. package/mintlify-docs/essentials/reusable-snippets.mdx +0 -110
  105. package/mintlify-docs/essentials/settings.mdx +0 -318
  106. package/mintlify-docs/favicon.svg +0 -3
  107. package/mintlify-docs/frontend/introduction.mdx +0 -39
  108. package/mintlify-docs/getting-started.mdx +0 -267
  109. package/mintlify-docs/guides/custom-agent.mdx +0 -608
  110. package/mintlify-docs/guides/first-agent.mdx +0 -315
  111. package/mintlify-docs/images/admin_ui.png +0 -0
  112. package/mintlify-docs/images/contexts.png +0 -0
  113. package/mintlify-docs/images/create_agents.png +0 -0
  114. package/mintlify-docs/images/evals.png +0 -0
  115. package/mintlify-docs/images/graphql.png +0 -0
  116. package/mintlify-docs/images/graphql_api.png +0 -0
  117. package/mintlify-docs/images/hero-dark.png +0 -0
  118. package/mintlify-docs/images/hero-light.png +0 -0
  119. package/mintlify-docs/images/hero.png +0 -0
  120. package/mintlify-docs/images/knowledge_sources.png +0 -0
  121. package/mintlify-docs/images/mcp.png +0 -0
  122. package/mintlify-docs/images/scaling.png +0 -0
  123. package/mintlify-docs/index.mdx +0 -411
  124. package/mintlify-docs/logo/dark.svg +0 -9
  125. package/mintlify-docs/logo/light.svg +0 -9
  126. package/mintlify-docs/partners.mdx +0 -558
  127. package/mintlify-docs/products.mdx +0 -77
  128. package/mintlify-docs/snippets/snippet-intro.mdx +0 -4
  129. package/mintlify-docs/styles.css +0 -207
  130. package/ngrok.bash +0 -1
  131. package/ngrok.md +0 -6
  132. package/ngrok.yml +0 -10
  133. package/release.config.cjs +0 -15
  134. package/skills-lock.json +0 -10
  135. package/types/context-processor.ts +0 -45
  136. package/types/enums/eval-types.ts +0 -5
  137. package/types/enums/field-types.ts +0 -1
  138. package/types/enums/jobs.ts +0 -11
  139. package/types/enums/statistics.ts +0 -13
  140. package/types/exulu-table-definition.ts +0 -79
  141. package/types/file-types.ts +0 -18
  142. package/types/models/agent-session.ts +0 -27
  143. package/types/models/agent.ts +0 -68
  144. package/types/models/context.ts +0 -53
  145. package/types/models/embedding.ts +0 -17
  146. package/types/models/eval-run.ts +0 -40
  147. package/types/models/exulu-agent-tool-config.ts +0 -11
  148. package/types/models/item.ts +0 -21
  149. package/types/models/job.ts +0 -8
  150. package/types/models/project.ts +0 -16
  151. package/types/models/rate-limiter-rules.ts +0 -7
  152. package/types/models/test-case.ts +0 -25
  153. package/types/models/tool.ts +0 -9
  154. package/types/models/user-role.ts +0 -12
  155. package/types/models/user.ts +0 -20
  156. package/types/models/variable.ts +0 -8
  157. package/types/models/vector-methods.ts +0 -7
  158. package/types/provider-config.ts +0 -21
  159. package/types/queue-config.ts +0 -16
  160. package/types/rbac-rights-modes.ts +0 -1
  161. package/types/statistics.ts +0 -20
  162. package/types/workflow.ts +0 -31
  163. /package/ee/{documents → python/documents}/THIRD_PARTY_LICENSES/docling.txt +0 -0
  164. /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>