@with-logic/intent 0.1.0 → 0.1.2

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.
package/README.md CHANGED
@@ -1,4 +1,18 @@
1
- # Intent
1
+ <p align="center">
2
+ <img src="logo.png" alt="Intent" width="200" />
3
+ </p>
4
+
5
+ <h2 align="center">An LLM-based Reranker Library That Explains Itself</h2>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@with-logic/intent"><img src="https://img.shields.io/npm/v/@with-logic/intent.svg" alt="npm version"></a>
9
+ <a href="https://www.npmjs.com/package/@with-logic/intent"><img src="https://img.shields.io/npm/dm/@with-logic/intent.svg" alt="npm downloads"></a>
10
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
11
+ <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/@with-logic/intent.svg" alt="Node.js"></a>
12
+ <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.0+-blue.svg" alt="TypeScript"></a>
13
+ </p>
14
+
15
+ ## Overview
2
16
 
3
17
  `intent` is an LLM-based reranker library that offers ranking, filtering, and choice all with explicit, inspectable reasoning.
4
18
 
@@ -28,7 +42,33 @@ const docs = [
28
42
  ];
29
43
 
30
44
  const ranked = await intent.rank("exponential backoff retries", docs);
31
- // => [doc1, doc2] (doc3 is filtered out via relevancy threshold)
45
+ // => [
46
+ // "To reduce flaky tests, add exponential backoff with jitter to HTTP retries.",
47
+ // "Many network requests can fail intermittently due to transient issues."
48
+ // ]
49
+ ```
50
+
51
+ ### With explanations
52
+
53
+ Pass `{ explain: true }` to see why each item was ranked:
54
+
55
+ ```ts
56
+ const results = await intent.rank("exponential backoff retries", docs, { explain: true });
57
+
58
+ for (const { item, explanation } of results) {
59
+ console.log(`- "${item.slice(0, 50)}..."`);
60
+ console.log(` ${explanation}`);
61
+ }
62
+ ```
63
+
64
+ ```
65
+ - "To reduce flaky tests, add exponential backoff wit..."
66
+ This entry explains adding exponential backoff with jitter to HTTP
67
+ retries, directly addressing the requested technique.
68
+
69
+ - "Many network requests can fail intermittently due ..."
70
+ The summary mentions transient failures in network requests, which can
71
+ motivate using backoff retries but does not describe the method.
32
72
  ```
33
73
 
34
74
  Intent will use a default Groq client when `GROQ_API_KEY` is set.
@@ -71,11 +111,11 @@ const docs: Doc[] = [
71
111
  const results = await intent.rank("Find expense reports and anything about spend approvals", docs);
72
112
  ```
73
113
 
74
- ### Include explanations
114
+ ### With explanations
75
115
 
76
116
  ```ts
77
117
  const results = await intent.rank("expense reports", docs, { explain: true });
78
- // => [{ item: Doc, explanation: string }, ...]
118
+ // => [{ item: Doc, explanation: "Covers Q2 travel and meal expenses..." }, ...]
79
119
  ```
80
120
 
81
121
  ## 2) Tool filtering with `filter()`
@@ -106,14 +146,23 @@ const tools: Tool[] = [
106
146
  const task = "Find the customer's last invoice total and email it to them.";
107
147
 
108
148
  const relevantTools = await intent.filter(task, tools);
109
- // [sendEmail, runSQL]
149
+ // => [sendEmail, runSQL]
110
150
  ```
111
151
 
112
- ### Filter with explanations
152
+ ### With explanations
113
153
 
114
154
  ```ts
115
- const relevantTools = await intent.filter(task, tools, { explain: true });
116
- // => [{ item: Tool, explanation: string }, ...]
155
+ const results = await intent.filter(task, tools, { explain: true });
156
+
157
+ for (const { item, explanation } of results) {
158
+ console.log(`- ${item.name}: ${explanation}`);
159
+ }
160
+ ```
161
+
162
+ ```
163
+ - sendEmail: Sending an email is necessary to deliver the invoice total to the customer.
164
+ - runSQL: Running a SQL query against the analytics DB can retrieve the last invoice
165
+ total needed for the task.
117
166
  ```
118
167
 
119
168
  ## 3) Model routing with `choice()`
@@ -155,7 +204,15 @@ const models: Model[] = [
155
204
  const task = "Implement a feature to add retries with exponential backoff and tests.";
156
205
 
157
206
  const { item: selected, explanation } = await intent.choice(task, models, { explain: true });
158
- // selected.id => gpt-5.2
207
+
208
+ console.log(`Selected: ${selected.id}`);
209
+ console.log(`Why: ${explanation}`);
210
+ ```
211
+
212
+ ```
213
+ Selected: gpt-5.2
214
+ Why: Feature implementation and testing fall under code generation and
215
+ refactoring, which gpt-5.2 excels at.
159
216
  ```
160
217
 
161
218
  ## Configuration
@@ -243,8 +300,18 @@ Hard timeout per LLM call.
243
300
  - Increase it when you have larger batches, longer summaries, or slower models.
244
301
  - Decrease it when you prefer quick fallbacks over waiting.
245
302
 
246
- If we timeout, we never throw an error; instead, we return the original
247
- results.
303
+ ### Error handling
304
+
305
+ Intent is designed to fail gracefully. On **any** LLM error (timeout, invalid API
306
+ key, rate limit, malformed response), we return items in their original order
307
+ rather than throwing. This ensures your application keeps working even when the
308
+ LLM is unavailable.
309
+
310
+ - `rank()` → returns all candidates in original order
311
+ - `filter()` → returns all candidates (nothing filtered out)
312
+ - `choice()` → returns the first candidate
313
+
314
+ When `{ explain: true }` is set, failed calls return empty explanation strings.
248
315
 
249
316
  #### `INTENT_BATCH_SIZE`
250
317