@far-world-labs/verblets 0.1.1 → 0.1.3
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/.cursor/launch.json +30 -0
- package/.cursor/settings.json +20 -0
- package/.github/workflows/branch-protection.yml +22 -0
- package/.github/workflows/ci.yml +120 -0
- package/.prettierrc +6 -0
- package/.release-it.json +4 -1
- package/.vscode/launch.json +31 -0
- package/AGENTS.md +220 -0
- package/DEVELOPING.md +105 -0
- package/README.md +254 -0
- package/eslint.config.js +80 -0
- package/package.json +29 -17
- package/scripts/generate-test/index.js +29 -3
- package/scripts/runner/index.js +26 -0
- package/scripts/simple-editor/index.js +29 -18
- package/scripts/summarize-files/index.js +28 -4
- package/src/chains/README.md +30 -0
- package/src/chains/anonymize/README.md +21 -0
- package/src/chains/anonymize/index.examples.js +75 -0
- package/src/chains/anonymize/index.js +121 -0
- package/src/chains/anonymize/index.spec.js +78 -0
- package/src/chains/bulk-central-tendency/index.examples.js +138 -0
- package/src/chains/bulk-central-tendency/index.js +91 -0
- package/src/chains/bulk-filter/README.md +21 -0
- package/src/chains/bulk-filter/index.examples.js +22 -0
- package/src/chains/bulk-filter/index.js +58 -0
- package/src/chains/bulk-filter/index.spec.js +38 -0
- package/src/chains/bulk-find/README.md +16 -0
- package/src/chains/bulk-find/index.examples.js +20 -0
- package/src/chains/bulk-find/index.js +30 -0
- package/src/chains/bulk-find/index.spec.js +26 -0
- package/src/chains/bulk-group/README.md +23 -0
- package/src/chains/bulk-group/index.examples.js +18 -0
- package/src/chains/bulk-group/index.js +34 -0
- package/src/chains/bulk-group/index.spec.js +41 -0
- package/src/chains/bulk-map/README.md +43 -0
- package/src/chains/bulk-map/index.examples.js +17 -0
- package/src/chains/bulk-map/index.js +86 -0
- package/src/chains/bulk-map/index.spec.js +44 -0
- package/src/chains/bulk-reduce/README.md +12 -0
- package/src/chains/bulk-reduce/index.examples.js +15 -0
- package/src/chains/bulk-reduce/index.js +13 -0
- package/src/chains/bulk-reduce/index.spec.js +25 -0
- package/src/chains/bulk-score/README.md +16 -0
- package/src/chains/bulk-score/bulk-score-result.json +18 -0
- package/src/chains/bulk-score/index.examples.js +22 -0
- package/src/chains/bulk-score/index.js +133 -0
- package/src/chains/bulk-score/index.spec.js +30 -0
- package/src/chains/category-samples/README.md +61 -0
- package/src/chains/category-samples/index.examples.js +103 -0
- package/src/chains/category-samples/index.js +134 -0
- package/src/chains/collect-terms/README.md +12 -0
- package/src/chains/collect-terms/index.examples.js +16 -0
- package/src/chains/collect-terms/index.js +44 -0
- package/src/chains/collect-terms/index.spec.js +25 -0
- package/src/chains/date/README.md +12 -0
- package/src/chains/date/index.examples.js +47 -0
- package/src/chains/date/index.js +74 -0
- package/src/chains/date/index.spec.js +62 -0
- package/src/chains/disambiguate/README.md +22 -0
- package/src/chains/disambiguate/disambiguate-meanings-result.json +16 -0
- package/src/chains/disambiguate/index.examples.js +18 -0
- package/src/chains/disambiguate/index.js +92 -0
- package/src/chains/disambiguate/index.spec.js +25 -0
- package/src/chains/dismantle/README.md +67 -0
- package/src/chains/dismantle/dismantle.examples.js +27 -0
- package/src/chains/dismantle/index.js +6 -17
- package/src/chains/dismantle/index.spec.js +1 -2
- package/src/chains/expect/README.md +171 -0
- package/src/chains/expect/index.examples.js +146 -0
- package/src/chains/expect/index.js +173 -0
- package/src/chains/expect/index.spec.js +324 -0
- package/src/chains/filter-ambiguous/README.md +11 -0
- package/src/chains/filter-ambiguous/index.examples.js +20 -0
- package/src/chains/filter-ambiguous/index.js +49 -0
- package/src/chains/filter-ambiguous/index.spec.js +31 -0
- package/src/chains/glossary/README.md +19 -0
- package/src/chains/glossary/index.examples.js +386 -0
- package/src/chains/glossary/index.js +75 -0
- package/src/chains/glossary/index.spec.js +19 -0
- package/src/chains/intersections/README.md +152 -0
- package/src/chains/intersections/index.examples.js +279 -0
- package/src/chains/intersections/index.js +366 -0
- package/src/chains/intersections/intersection-result.json +38 -0
- package/src/chains/list/index.examples.js +12 -16
- package/src/chains/list/index.js +106 -53
- package/src/chains/list/index.spec.js +8 -9
- package/src/chains/list/list-result.json +16 -0
- package/src/chains/llm-logger/README.md +208 -0
- package/src/chains/llm-logger/index.js +205 -0
- package/src/chains/llm-logger/index.spec.js +330 -0
- package/src/chains/questions/index.examples.js +2 -1
- package/src/chains/questions/index.js +14 -15
- package/src/chains/scan-js/index.js +6 -9
- package/src/chains/set-interval/README.md +81 -0
- package/src/chains/set-interval/index.examples.js +36 -0
- package/src/chains/set-interval/index.js +131 -0
- package/src/chains/set-interval/index.spec.js +70 -0
- package/src/chains/socratic/README.md +17 -0
- package/src/chains/socratic/index.js +64 -0
- package/src/chains/socratic/index.spec.js +24 -0
- package/src/chains/sort/index.examples.js +3 -7
- package/src/chains/sort/index.js +65 -15
- package/src/chains/sort/index.spec.js +5 -8
- package/src/chains/sort/sort-result.json +16 -0
- package/src/chains/summary-map/README.md +9 -1
- package/src/chains/summary-map/index.examples.js +9 -2
- package/src/chains/summary-map/index.js +43 -25
- package/src/chains/summary-map/index.spec.js +78 -3
- package/src/chains/test/index.js +9 -13
- package/src/chains/test-advice/index.js +4 -5
- package/src/chains/themes/README.md +20 -0
- package/src/chains/themes/index.examples.js +17 -0
- package/src/chains/themes/index.js +28 -0
- package/src/chains/themes/index.spec.js +19 -0
- package/src/chains/veiled-variants/index.examples.js +18 -0
- package/src/chains/veiled-variants/index.js +107 -0
- package/src/chains/veiled-variants/index.spec.js +40 -0
- package/src/constants/common.js +0 -2
- package/src/constants/models.js +172 -0
- package/src/index.js +178 -18
- package/src/json-schemas/README.md +13 -0
- package/src/json-schemas/index.js +8 -14
- package/src/json-schemas/schema-dot-org-photograph.json +11 -5
- package/src/json-schemas/schema-dot-org-place.json +78 -5
- package/src/lib/README.md +26 -0
- package/src/lib/bulk-filter/README.md +22 -0
- package/src/lib/bulk-filter/index.examples.js +27 -0
- package/src/lib/bulk-filter/index.js +63 -0
- package/src/lib/bulk-filter/index.spec.js +38 -0
- package/src/lib/bulk-find/README.md +18 -0
- package/src/lib/bulk-find/index.examples.js +19 -0
- package/src/lib/bulk-find/index.js +30 -0
- package/src/lib/bulk-find/index.spec.js +41 -0
- package/src/lib/chatgpt/index.js +63 -43
- package/src/lib/combinations/index.js +30 -0
- package/src/lib/combinations/index.spec.js +23 -0
- package/src/lib/functional/index.js +28 -0
- package/src/lib/logger-service/index.js +32 -0
- package/src/lib/parse-js-parts/index.js +9 -21
- package/src/lib/parse-llm-list/README.md +39 -0
- package/src/lib/parse-llm-list/index.js +54 -0
- package/src/lib/parse-llm-list/index.spec.js +59 -0
- package/src/lib/path-aliases/index.js +1 -3
- package/src/lib/path-aliases/index.spec.js +2 -8
- package/src/lib/pave/index.js +4 -4
- package/src/lib/pave/index.spec.js +6 -3
- package/src/lib/prompt-cache/index.js +14 -10
- package/src/lib/retry/index.js +11 -8
- package/src/lib/ring-buffer/README.md +460 -0
- package/src/lib/ring-buffer/index.js +1074 -0
- package/src/lib/search-best-first/city-walk.spec.js +37 -0
- package/src/lib/search-best-first/index.js +42 -11
- package/src/lib/search-best-first/index.spec.js +35 -0
- package/src/lib/search-js-files/index.js +44 -47
- package/src/lib/search-js-files/scan-file.js +10 -21
- package/src/lib/shorten-text/index.js +2 -7
- package/src/lib/shorten-text/index.spec.js +3 -3
- package/src/lib/strip-response/index.js +2 -7
- package/src/lib/template-replace/index.js +23 -0
- package/src/lib/template-replace/index.spec.js +60 -0
- package/src/lib/to-date/index.js +11 -0
- package/src/lib/to-number/index.js +1 -1
- package/src/lib/transcribe/index.js +26 -9
- package/src/prompts/README.md +3 -1
- package/src/prompts/as-object-with-schema.js +3 -8
- package/src/prompts/as-schema-org-text.js +10 -2
- package/src/prompts/code-features.js +1 -5
- package/src/prompts/constants.js +27 -27
- package/src/prompts/generate-collection.js +1 -1
- package/src/prompts/intent.js +16 -22
- package/src/prompts/select-from-threshold.js +1 -2
- package/src/prompts/sort.js +4 -8
- package/src/prompts/style.js +4 -7
- package/src/prompts/wrap-list.js +1 -4
- package/src/services/llm-model/global-overrides.spec.js +432 -0
- package/src/services/llm-model/index.js +234 -40
- package/src/services/llm-model/model.js +2 -2
- package/src/services/llm-model/negotiate.spec.js +447 -0
- package/src/services/redis/index.js +70 -7
- package/src/test/setup.js +20 -0
- package/src/verblets/README.md +26 -0
- package/src/verblets/auto/index.examples.js +12 -9
- package/src/verblets/auto/index.js +10 -10
- package/src/verblets/auto/index.spec.js +4 -6
- package/src/verblets/bool/README.md +36 -0
- package/src/verblets/bool/index.examples.js +53 -1
- package/src/verblets/bool/index.js +6 -9
- package/src/verblets/bool/index.spec.js +1 -3
- package/src/verblets/central-tendency/README.md +166 -0
- package/src/verblets/central-tendency/central-tendency-result.json +24 -0
- package/src/verblets/central-tendency/index.examples.js +196 -0
- package/src/verblets/central-tendency/index.js +171 -0
- package/src/verblets/central-tendency/index.spec.js +148 -0
- package/src/verblets/enum/index.examples.js +1 -4
- package/src/verblets/enum/index.js +7 -4
- package/src/verblets/expect/README.md +64 -0
- package/src/verblets/expect/index.examples.js +109 -0
- package/src/verblets/expect/index.js +75 -0
- package/src/verblets/expect/index.spec.js +127 -0
- package/src/verblets/intent/index.examples.js +95 -7
- package/src/verblets/intent/index.js +56 -68
- package/src/verblets/intersection/README.md +16 -0
- package/src/verblets/intersection/index.examples.js +89 -0
- package/src/verblets/intersection/index.js +84 -0
- package/src/verblets/intersection/index.spec.js +60 -0
- package/src/verblets/intersection/intersection-result.json +16 -0
- package/src/verblets/list-expand/README.md +10 -0
- package/src/verblets/list-expand/index.examples.js +14 -0
- package/src/verblets/list-expand/index.js +104 -0
- package/src/verblets/list-expand/index.spec.js +18 -0
- package/src/verblets/list-expand/list-expand-result.json +16 -0
- package/src/verblets/list-filter/README.md +22 -0
- package/src/verblets/list-filter/index.examples.js +26 -0
- package/src/verblets/list-filter/index.js +18 -0
- package/src/verblets/list-filter/index.spec.js +19 -0
- package/src/verblets/list-find/README.md +11 -0
- package/src/verblets/list-find/index.examples.js +15 -0
- package/src/verblets/list-find/index.js +17 -0
- package/src/verblets/list-find/index.spec.js +19 -0
- package/src/verblets/list-group/README.md +16 -0
- package/src/verblets/list-group/index.examples.js +16 -0
- package/src/verblets/list-group/index.js +112 -0
- package/src/verblets/list-group/index.spec.js +35 -0
- package/src/verblets/list-group/list-group-result.json +16 -0
- package/src/verblets/list-map/README.md +11 -0
- package/src/verblets/list-map/index.examples.js +15 -0
- package/src/verblets/list-map/index.js +26 -0
- package/src/verblets/list-map/index.spec.js +17 -0
- package/src/verblets/list-reduce/README.md +10 -0
- package/src/verblets/list-reduce/index.examples.js +14 -0
- package/src/verblets/list-reduce/index.js +21 -0
- package/src/verblets/list-reduce/index.spec.js +27 -0
- package/src/verblets/list-reduce/index.spec.jsx +27 -0
- package/src/verblets/name/README.md +15 -0
- package/src/verblets/name/index.examples.js +28 -0
- package/src/verblets/name/index.js +19 -0
- package/src/verblets/name/index.spec.js +33 -0
- package/src/verblets/name-similar-to/README.md +26 -0
- package/src/verblets/name-similar-to/index.examples.js +18 -0
- package/src/verblets/name-similar-to/index.js +20 -0
- package/src/verblets/name-similar-to/index.spec.js +13 -0
- package/src/verblets/number/index.examples.js +173 -7
- package/src/verblets/number/index.js +5 -2
- package/src/verblets/number/index.spec.js +1 -3
- package/src/verblets/number-with-units/index.examples.js +5 -1
- package/src/verblets/number-with-units/index.js +74 -9
- package/src/verblets/number-with-units/number-with-units-result.json +23 -0
- package/src/verblets/schema-org/index.examples.js +2 -7
- package/src/verblets/schema-org/index.js +32 -3
- package/src/verblets/sentiment/README.md +10 -0
- package/src/verblets/sentiment/index.examples.js +20 -0
- package/src/verblets/sentiment/index.js +9 -0
- package/src/verblets/sentiment/index.spec.js +20 -0
- package/src/verblets/to-object/index.js +10 -15
- package/src/verblets/to-object/index.spec.js +1 -4
- package/.eslintrc.json +0 -42
- package/docs/README.md +0 -41
- package/docs/babel.config.js +0 -3
- package/docs/blog/2019-05-28-first-blog-post.md +0 -12
- package/docs/blog/2019-05-29-long-blog-post.md +0 -44
- package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -20
- package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs/blog/2021-08-26-welcome/index.md +0 -25
- package/docs/blog/authors.yml +0 -17
- package/docs/docs/api/bool.md +0 -74
- package/docs/docs/api/search.md +0 -51
- package/docs/docs/intro.md +0 -47
- package/docs/docs/tutorial-basics/_category_.json +0 -8
- package/docs/docs/tutorial-basics/congratulations.md +0 -23
- package/docs/docs/tutorial-basics/create-a-blog-post.md +0 -34
- package/docs/docs/tutorial-basics/create-a-document.md +0 -57
- package/docs/docs/tutorial-basics/create-a-page.md +0 -43
- package/docs/docs/tutorial-basics/deploy-your-site.md +0 -31
- package/docs/docs/tutorial-basics/markdown-features.mdx +0 -152
- package/docs/docs/tutorial-extras/_category_.json +0 -7
- package/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
- package/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
- package/docs/docs/tutorial-extras/manage-docs-versions.md +0 -55
- package/docs/docs/tutorial-extras/translate-your-site.md +0 -88
- package/docs/docusaurus.config.js +0 -120
- package/docs/package.json +0 -44
- package/docs/sidebars.js +0 -31
- package/docs/src/components/HomepageFeatures/index.js +0 -61
- package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
- package/docs/src/css/custom.css +0 -30
- package/docs/src/pages/index.js +0 -43
- package/docs/src/pages/index.module.css +0 -23
- package/docs/src/pages/markdown-page.md +0 -7
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.svg +0 -1
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/src/constants/openai.js +0 -65
- /package/{.vite.config.examples.js → .vitest.config.examples.js} +0 -0
- /package/{.vite.config.js → .vitest.config.js} +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# setInterval
|
|
2
|
+
|
|
3
|
+
AI-guided replacement for `setInterval`.
|
|
4
|
+
Feed it your own natural-language heuristic; it will keep time, remember history, and supply your callback with rich context so you can build self-tuning workflows, creative generators, or living UIs.
|
|
5
|
+
|
|
6
|
+
## Example: Photography Alarm
|
|
7
|
+
|
|
8
|
+
*Because the universe waits for no one (but this will wait for the universe).*
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
import setInterval from './index.js';
|
|
12
|
+
import { getWeather, getCelestialEvents } from './apis.js';
|
|
13
|
+
import chatGPT from '../../lib/chatgpt/index.js';
|
|
14
|
+
|
|
15
|
+
const stop = setInterval({
|
|
16
|
+
prompt: `
|
|
17
|
+
Based on upcoming celestial events and weather, decide when to check next
|
|
18
|
+
for photography opportunities.
|
|
19
|
+
|
|
20
|
+
Current conditions: {cloudCover}% clouds
|
|
21
|
+
|
|
22
|
+
Upcoming celestial events:
|
|
23
|
+
<options>
|
|
24
|
+
{events}
|
|
25
|
+
<options>
|
|
26
|
+
`,
|
|
27
|
+
|
|
28
|
+
// Called every time to get data for AI scheduling decisions
|
|
29
|
+
async getData() {
|
|
30
|
+
const weather = await getWeather({ days: 1 });
|
|
31
|
+
const events = await getCelestialEvents({ days: 7 });
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
cloudCover: weather.current.cloudCover,
|
|
35
|
+
events: events.map(e => `${e.name} - ${e.description}`).join('\n')
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Called when the tick happens - handle the scheduled event
|
|
40
|
+
async onTick({ timingString, data, nextDate }) {
|
|
41
|
+
// Get current conditions for photography
|
|
42
|
+
const currentWeather = await getWeather({ hours: 1 });
|
|
43
|
+
const currentEvents = await getCelestialEvents({
|
|
44
|
+
hours: 1,
|
|
45
|
+
types: ['solar', 'lunar', 'meteor', 'planetary', 'aurora', 'eclipse']
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const description = await chatGPT(`
|
|
49
|
+
Describe what celestial event should be photographed right now based on current conditions.
|
|
50
|
+
Current Weather: ${JSON.stringify(currentWeather)}
|
|
51
|
+
Current Events: ${JSON.stringify(currentEvents)}
|
|
52
|
+
|
|
53
|
+
Provide a clear description of the photography opportunity.
|
|
54
|
+
`);
|
|
55
|
+
|
|
56
|
+
console.log(description);
|
|
57
|
+
console.log(`Next check in: ${timingString} (${nextDate.toLocaleString()})`);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
Function to stop the interval timer.
|
|
62
|
+
|
|
63
|
+
## API Reference
|
|
64
|
+
|
|
65
|
+
### `setInterval(options)`
|
|
66
|
+
|
|
67
|
+
Creates an AI-guided interval timer that uses natural language to determine timing.
|
|
68
|
+
|
|
69
|
+
#### Parameters
|
|
70
|
+
|
|
71
|
+
- **`prompt`** (string, required): Instructions for AI timing decisions. Supports `{variable}` interpolation from `getData` results
|
|
72
|
+
- **`getData`** (function, required): Called to get data for AI decisions. Should return an object whose properties can be used as `{variable}` in the prompt
|
|
73
|
+
- **`historySize`** (number, default: 5): How many timing decisions to remember
|
|
74
|
+
- **`initial`** (any, default: null): Initial data to start with
|
|
75
|
+
- **`model`** (string, optional): AI model to use
|
|
76
|
+
- **`llm`** (object, optional): Model configuration
|
|
77
|
+
- **`onTick`** (function, optional): Called when the tick happens
|
|
78
|
+
|
|
79
|
+
#### Returns
|
|
80
|
+
|
|
81
|
+
Function to stop the interval timer.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, it } from 'vitest';
|
|
2
|
+
import setInterval from './index.js';
|
|
3
|
+
import { longTestTimeout } from '../../constants/common.js';
|
|
4
|
+
|
|
5
|
+
describe('setInterval (example)', () => {
|
|
6
|
+
it(
|
|
7
|
+
'adjusts meditation sessions using wearable stress levels',
|
|
8
|
+
async () => {
|
|
9
|
+
const stop = setInterval({
|
|
10
|
+
prompt:
|
|
11
|
+
'Current stress level: {stress}. Start at 3 min. If stress > 70, shorten by 1 min; if below 30, lengthen by 2 min.',
|
|
12
|
+
getData: () => ({ stress: Math.floor(Math.random() * 100) }),
|
|
13
|
+
onTick: ({ data }) => console.log(`Meditation session with stress level: ${data.stress}`),
|
|
14
|
+
});
|
|
15
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
16
|
+
stop();
|
|
17
|
+
},
|
|
18
|
+
longTestTimeout
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
it(
|
|
22
|
+
'paces game events to match player skill',
|
|
23
|
+
async () => {
|
|
24
|
+
const stop = setInterval({
|
|
25
|
+
prompt:
|
|
26
|
+
'Player win rate: {winRate}%. Begin at 10 sec. If winRate > 80, decrease by 2 sec; if under 40, increase by 5 sec.',
|
|
27
|
+
getData: () => ({ winRate: Math.floor(Math.random() * 100) }),
|
|
28
|
+
onTick: ({ data }) =>
|
|
29
|
+
console.log(`Game event triggered for player with ${data.winRate}% win rate`),
|
|
30
|
+
});
|
|
31
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
32
|
+
stop();
|
|
33
|
+
},
|
|
34
|
+
longTestTimeout
|
|
35
|
+
);
|
|
36
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import chatGPT from '../../lib/chatgpt/index.js';
|
|
2
|
+
import numberWithUnits from '../../verblets/number-with-units/index.js';
|
|
3
|
+
import number from '../../verblets/number/index.js';
|
|
4
|
+
import date from '../date/index.js';
|
|
5
|
+
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
6
|
+
import templateReplace from '../../lib/template-replace/index.js';
|
|
7
|
+
import { constants as promptConstants } from '../../prompts/index.js';
|
|
8
|
+
|
|
9
|
+
const { contentIsInstructions, explainAndSeparate, explainAndSeparatePrimitive } = promptConstants;
|
|
10
|
+
|
|
11
|
+
const UNIT_MS = {
|
|
12
|
+
ms: 1,
|
|
13
|
+
millisecond: 1,
|
|
14
|
+
milliseconds: 1,
|
|
15
|
+
s: 1000,
|
|
16
|
+
sec: 1000,
|
|
17
|
+
secs: 1000,
|
|
18
|
+
second: 1000,
|
|
19
|
+
seconds: 1000,
|
|
20
|
+
m: 60000,
|
|
21
|
+
min: 60000,
|
|
22
|
+
mins: 60000,
|
|
23
|
+
minute: 60000,
|
|
24
|
+
minutes: 60000,
|
|
25
|
+
h: 3600000,
|
|
26
|
+
hr: 3600000,
|
|
27
|
+
hrs: 3600000,
|
|
28
|
+
hour: 3600000,
|
|
29
|
+
hours: 3600000,
|
|
30
|
+
d: 86400000,
|
|
31
|
+
day: 86400000,
|
|
32
|
+
days: 86400000,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
|
|
36
|
+
|
|
37
|
+
async function toMs(text, config = {}) {
|
|
38
|
+
const clean = String(text).trim();
|
|
39
|
+
if (ISO_DATE_RE.test(clean)) {
|
|
40
|
+
const diff = new Date(clean).getTime() - Date.now();
|
|
41
|
+
if (diff > 0) return diff;
|
|
42
|
+
}
|
|
43
|
+
const nu = await numberWithUnits(clean, config);
|
|
44
|
+
if (nu && nu.value !== undefined) {
|
|
45
|
+
const unit = (nu.unit || 'ms').toLowerCase();
|
|
46
|
+
if (UNIT_MS[unit]) return nu.value * UNIT_MS[unit];
|
|
47
|
+
}
|
|
48
|
+
const dt = await date(clean, config);
|
|
49
|
+
if (dt instanceof Date) {
|
|
50
|
+
const diff = dt.getTime() - Date.now();
|
|
51
|
+
if (diff > 0) return diff;
|
|
52
|
+
}
|
|
53
|
+
const n = await number(clean, config);
|
|
54
|
+
if (typeof n === 'number') return n;
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default function setInterval({
|
|
59
|
+
prompt,
|
|
60
|
+
getData,
|
|
61
|
+
historySize = 5,
|
|
62
|
+
initial = null,
|
|
63
|
+
onTick,
|
|
64
|
+
model,
|
|
65
|
+
llm,
|
|
66
|
+
...options
|
|
67
|
+
} = {}) {
|
|
68
|
+
let timer;
|
|
69
|
+
let count = 0;
|
|
70
|
+
let lastResult = initial;
|
|
71
|
+
const history = [];
|
|
72
|
+
let active = true;
|
|
73
|
+
|
|
74
|
+
const step = async () => {
|
|
75
|
+
if (!active) return;
|
|
76
|
+
|
|
77
|
+
// Get data for AI decision making
|
|
78
|
+
lastResult = await getData({
|
|
79
|
+
count,
|
|
80
|
+
lastInvocationResult: lastResult,
|
|
81
|
+
initial,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Replace {variable} placeholders in the prompt with actual values from lastResult
|
|
85
|
+
const processedPrompt = templateReplace(prompt, lastResult);
|
|
86
|
+
|
|
87
|
+
// Always invoke the prompt to determine the next interval
|
|
88
|
+
const intervalPrompt = `${contentIsInstructions} ${processedPrompt}
|
|
89
|
+
|
|
90
|
+
${explainAndSeparate} ${explainAndSeparatePrimitive}
|
|
91
|
+
|
|
92
|
+
Your response should be an ISO date or a short duration like "10 minutes".
|
|
93
|
+
${wrapVariable(lastResult, { tag: 'last-result', title: 'Last result:' })}
|
|
94
|
+
${wrapVariable(history, { tag: 'history', title: 'History:', forceHTML: true })}
|
|
95
|
+
${wrapVariable(count, { tag: 'count', title: 'Count:' })}
|
|
96
|
+
Next wait:`;
|
|
97
|
+
|
|
98
|
+
const intervalText = await chatGPT(intervalPrompt, {
|
|
99
|
+
modelOptions: model ? { modelName: model, ...llm } : { ...llm },
|
|
100
|
+
...options,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
history.push(intervalText);
|
|
104
|
+
if (history.length > historySize) history.shift();
|
|
105
|
+
|
|
106
|
+
const delay = await toMs(intervalText, { llm, ...options });
|
|
107
|
+
|
|
108
|
+
// Call onTick callback if provided - this is when the tick happens
|
|
109
|
+
if (onTick) {
|
|
110
|
+
const nextTime = new Date(Date.now() + delay);
|
|
111
|
+
await onTick({
|
|
112
|
+
timingString: intervalText,
|
|
113
|
+
data: lastResult,
|
|
114
|
+
nextDate: nextTime,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
count += 1;
|
|
119
|
+
|
|
120
|
+
// Schedule the next iteration
|
|
121
|
+
timer = setTimeout(step, delay);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// Start immediately - the prompt will determine the first interval
|
|
125
|
+
timer = setTimeout(step, 0);
|
|
126
|
+
|
|
127
|
+
return () => {
|
|
128
|
+
active = false;
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
};
|
|
131
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import setInterval from './index.js';
|
|
3
|
+
|
|
4
|
+
vi.useFakeTimers();
|
|
5
|
+
|
|
6
|
+
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
7
|
+
default: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
vi.mock('../date/index.js', () => ({
|
|
10
|
+
default: vi.fn(),
|
|
11
|
+
}));
|
|
12
|
+
vi.mock('../../verblets/number-with-units/index.js', () => ({
|
|
13
|
+
default: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
vi.mock('../../verblets/number/index.js', () => ({
|
|
16
|
+
default: vi.fn(),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const chatGPT = (await import('../../lib/chatgpt/index.js')).default;
|
|
20
|
+
const date = (await import('../date/index.js')).default;
|
|
21
|
+
const numberWithUnits = (await import('../../verblets/number-with-units/index.js')).default;
|
|
22
|
+
const number = (await import('../../verblets/number/index.js')).default;
|
|
23
|
+
|
|
24
|
+
describe('setInterval', () => {
|
|
25
|
+
it('runs callback with dynamic delays', async () => {
|
|
26
|
+
chatGPT.mockResolvedValueOnce('1 second').mockResolvedValueOnce('2 seconds');
|
|
27
|
+
numberWithUnits
|
|
28
|
+
.mockResolvedValueOnce({ value: 1, unit: 'second' })
|
|
29
|
+
.mockResolvedValueOnce({ value: 2, unit: 'second' });
|
|
30
|
+
date.mockResolvedValue(undefined);
|
|
31
|
+
number.mockResolvedValue(undefined);
|
|
32
|
+
|
|
33
|
+
const getData = vi.fn().mockResolvedValue('test data');
|
|
34
|
+
const stop = setInterval({ prompt: 'prompt', getData });
|
|
35
|
+
await Promise.resolve();
|
|
36
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
37
|
+
expect(getData).toHaveBeenCalledTimes(1);
|
|
38
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
39
|
+
expect(getData).toHaveBeenCalledTimes(2);
|
|
40
|
+
await vi.advanceTimersByTimeAsync(2000);
|
|
41
|
+
expect(getData).toHaveBeenCalledTimes(3);
|
|
42
|
+
stop();
|
|
43
|
+
await vi.runOnlyPendingTimersAsync();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('interpolates variables from getData results in prompt', async () => {
|
|
47
|
+
chatGPT.mockResolvedValueOnce('1 second');
|
|
48
|
+
numberWithUnits.mockResolvedValueOnce({ value: 1, unit: 'second' });
|
|
49
|
+
date.mockResolvedValue(undefined);
|
|
50
|
+
number.mockResolvedValue(undefined);
|
|
51
|
+
|
|
52
|
+
const getData = vi.fn().mockResolvedValue({ stress: 85, mood: 'anxious' });
|
|
53
|
+
const stop = setInterval({
|
|
54
|
+
prompt: 'Current stress: {stress}, mood: {mood}. Wait time?',
|
|
55
|
+
getData,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
await Promise.resolve();
|
|
59
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
60
|
+
|
|
61
|
+
// Check that chatGPT was called with interpolated values
|
|
62
|
+
expect(chatGPT).toHaveBeenCalledWith(
|
|
63
|
+
expect.stringContaining('Current stress: 85, mood: anxious. Wait time?'),
|
|
64
|
+
expect.any(Object)
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
stop();
|
|
68
|
+
await vi.runOnlyPendingTimersAsync();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# socratic
|
|
2
|
+
|
|
3
|
+
Guide yourself or a user toward deeper understanding by automatically posing and answering a short series of Socratic questions. The chain uses your configured LLM to generate each question and then supplies a concise answer, building a dialogue.
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
import { socratic } from './index.js';
|
|
7
|
+
|
|
8
|
+
const dialogue = await socratic('I want to start exercising more').run(3);
|
|
9
|
+
console.log(dialogue);
|
|
10
|
+
/*
|
|
11
|
+
[
|
|
12
|
+
{ question: 'What benefits do you hope to gain from exercising?', answer: 'I want more energy during the day.' },
|
|
13
|
+
{ question: 'Why is having more energy important to you?', answer: 'So I can keep up with my kids after work.' },
|
|
14
|
+
{ question: 'How might regular exercise help you achieve that?', answer: 'It will improve my stamina and mood.' }
|
|
15
|
+
]
|
|
16
|
+
*/
|
|
17
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import chatGPT from '../../lib/chatgpt/index.js';
|
|
2
|
+
import modelService from '../../services/llm-model/index.js';
|
|
3
|
+
|
|
4
|
+
const defaultAsk = async ({
|
|
5
|
+
topic,
|
|
6
|
+
history = [],
|
|
7
|
+
model = modelService.getBestPublicModel(),
|
|
8
|
+
} = {}) => {
|
|
9
|
+
const historyText = history.map((turn) => `Q: ${turn.question}\nA: ${turn.answer}`).join('\n');
|
|
10
|
+
|
|
11
|
+
const prompt = `${
|
|
12
|
+
historyText ? `${historyText}\n` : ''
|
|
13
|
+
}Using the Socratic method, ask one short question that challenges assumptions about "${topic}".`;
|
|
14
|
+
const budget = model.budgetTokens(prompt);
|
|
15
|
+
return await chatGPT(prompt, { maxTokens: budget.completion, temperature: 0.7 });
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const defaultAnswer = async ({
|
|
19
|
+
question,
|
|
20
|
+
history = [],
|
|
21
|
+
_topic,
|
|
22
|
+
model = modelService.getBestPublicModel(),
|
|
23
|
+
} = {}) => {
|
|
24
|
+
const historyText = history.map((turn) => `Q: ${turn.question}\nA: ${turn.answer}`).join('\n');
|
|
25
|
+
|
|
26
|
+
const prompt = `${
|
|
27
|
+
historyText ? `${historyText}\n` : ''
|
|
28
|
+
}Answer the question thoughtfully and briefly:\n"${question}"`;
|
|
29
|
+
const budget = model.budgetTokens(prompt);
|
|
30
|
+
return await chatGPT(prompt, { maxTokens: budget.completion, temperature: 0.7 });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
class SocraticMethod {
|
|
34
|
+
constructor(statement, { ask = defaultAsk, answer = defaultAnswer } = {}) {
|
|
35
|
+
this.statement = statement;
|
|
36
|
+
this.ask = ask;
|
|
37
|
+
this.answer = answer;
|
|
38
|
+
this.history = [];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getDialogue() {
|
|
42
|
+
return this.history;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async step() {
|
|
46
|
+
const question = await this.ask({ topic: this.statement, history: this.history });
|
|
47
|
+
const answer = await this.answer({ question, history: this.history, topic: this.statement });
|
|
48
|
+
const turn = { question, answer };
|
|
49
|
+
this.history.push(turn);
|
|
50
|
+
return turn;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async run(depth = 3) {
|
|
54
|
+
for (let i = 0; i < depth; i += 1) {
|
|
55
|
+
// eslint-disable-next-line no-await-in-loop
|
|
56
|
+
await this.step();
|
|
57
|
+
}
|
|
58
|
+
return this.history;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const socratic = (statement, options) => new SocraticMethod(statement, options);
|
|
63
|
+
|
|
64
|
+
export default SocraticMethod;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { socratic } from './index.js';
|
|
3
|
+
|
|
4
|
+
vi.mock('../../lib/chatgpt/index.js', () => {
|
|
5
|
+
let call = 0;
|
|
6
|
+
return {
|
|
7
|
+
default: vi.fn(() => {
|
|
8
|
+
call += 1;
|
|
9
|
+
return call % 2 === 1 ? `Q${call}` : `A${call}`;
|
|
10
|
+
}),
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('socratic chain', () => {
|
|
15
|
+
it('runs dialogue for specified depth', async () => {
|
|
16
|
+
const chain = socratic('topic');
|
|
17
|
+
const result = await chain.run(2);
|
|
18
|
+
expect(result).toHaveLength(2);
|
|
19
|
+
result.forEach((turn) => {
|
|
20
|
+
expect(turn).toHaveProperty('question');
|
|
21
|
+
expect(turn).toHaveProperty('answer');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -22,13 +22,9 @@ describe('Sort chain', () => {
|
|
|
22
22
|
async () => {
|
|
23
23
|
const listResults = await list(example.inputs.listText);
|
|
24
24
|
|
|
25
|
-
const result = await sort(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
iterations: 1,
|
|
29
|
-
},
|
|
30
|
-
listResults
|
|
31
|
-
);
|
|
25
|
+
const result = await sort(listResults, example.inputs.sortText, {
|
|
26
|
+
iterations: 1,
|
|
27
|
+
});
|
|
32
28
|
|
|
33
29
|
// console.error(result);
|
|
34
30
|
|
package/src/chains/sort/index.js
CHANGED
|
@@ -1,10 +1,54 @@
|
|
|
1
1
|
import * as R from 'ramda';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
2
5
|
|
|
3
6
|
import chatGPT from '../../lib/chatgpt/index.js';
|
|
4
|
-
import toObject from '../../verblets/to-object/index.js';
|
|
5
7
|
import { sort as sortPromptInitial } from '../../prompts/index.js';
|
|
6
8
|
import modelService from '../../services/llm-model/index.js';
|
|
7
9
|
|
|
10
|
+
// Get the directory of this module
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Load the JSON schema for sort results
|
|
16
|
+
* @returns {Promise<Object>} JSON schema for validation
|
|
17
|
+
*/
|
|
18
|
+
async function getSortSchema() {
|
|
19
|
+
const schemaPath = path.join(__dirname, 'sort-result.json');
|
|
20
|
+
return JSON.parse(await fs.readFile(schemaPath, 'utf8'));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create model options for structured outputs
|
|
25
|
+
* @param {string|Object} llm - LLM model name or configuration object
|
|
26
|
+
* @returns {Promise<Object>} Model options for chatGPT
|
|
27
|
+
*/
|
|
28
|
+
async function createModelOptions(llm = 'fastGoodCheap') {
|
|
29
|
+
const schema = await getSortSchema();
|
|
30
|
+
|
|
31
|
+
const responseFormat = {
|
|
32
|
+
type: 'json_schema',
|
|
33
|
+
json_schema: {
|
|
34
|
+
name: 'sort_result',
|
|
35
|
+
schema,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (typeof llm === 'string') {
|
|
40
|
+
return {
|
|
41
|
+
modelName: llm,
|
|
42
|
+
response_format: responseFormat,
|
|
43
|
+
};
|
|
44
|
+
} else {
|
|
45
|
+
return {
|
|
46
|
+
...llm,
|
|
47
|
+
response_format: responseFormat,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
8
52
|
// redeclared so it's clearer how tests can override the sorter
|
|
9
53
|
let sortPrompt = sortPromptInitial;
|
|
10
54
|
|
|
@@ -32,7 +76,8 @@ const sanitizeList = (list) => {
|
|
|
32
76
|
const sort = async (
|
|
33
77
|
options,
|
|
34
78
|
listInitial,
|
|
35
|
-
model = modelService.
|
|
79
|
+
model = modelService.getBestPublicModel(),
|
|
80
|
+
config = {}
|
|
36
81
|
) => {
|
|
37
82
|
const {
|
|
38
83
|
by,
|
|
@@ -41,6 +86,8 @@ const sort = async (
|
|
|
41
86
|
iterations = defaultSortIterations,
|
|
42
87
|
} = options;
|
|
43
88
|
|
|
89
|
+
const { llm, ...passThroughOptions } = config;
|
|
90
|
+
|
|
44
91
|
const list = sanitizeList(listInitial);
|
|
45
92
|
let i = iterations;
|
|
46
93
|
let top = [];
|
|
@@ -63,30 +110,30 @@ const sort = async (
|
|
|
63
110
|
);
|
|
64
111
|
|
|
65
112
|
const budget = model.budgetTokens(prompt);
|
|
113
|
+
const modelOptions = await createModelOptions(llm);
|
|
66
114
|
|
|
67
115
|
// eslint-disable-next-line no-await-in-loop
|
|
68
116
|
const result = await chatGPT(prompt, {
|
|
69
117
|
modelOptions: {
|
|
118
|
+
...modelOptions,
|
|
70
119
|
maxTokens: budget.completion,
|
|
71
120
|
requestTimeout: model.requestTimeout * 1.5,
|
|
72
121
|
},
|
|
122
|
+
...passThroughOptions,
|
|
73
123
|
});
|
|
74
124
|
|
|
75
|
-
//
|
|
76
|
-
const batchSorted =
|
|
125
|
+
// With structured outputs, response should already be parsed and validated
|
|
126
|
+
const batchSorted = typeof result === 'string' ? JSON.parse(result) : result;
|
|
127
|
+
// Extract items from the object structure
|
|
128
|
+
const resultArray = batchSorted?.items || batchSorted;
|
|
129
|
+
const sortedArray = Array.isArray(resultArray) ? resultArray.filter(Boolean) : [];
|
|
77
130
|
|
|
78
|
-
const batchTop =
|
|
79
|
-
const batchBottom =
|
|
131
|
+
const batchTop = sortedArray.slice(0, extremeK);
|
|
132
|
+
const batchBottom = sortedArray.slice(-extremeK);
|
|
80
133
|
|
|
81
|
-
discardedTop = [
|
|
82
|
-
...newTop.filter((x) => !batchTop.includes(x)),
|
|
83
|
-
...discardedTop,
|
|
84
|
-
];
|
|
134
|
+
discardedTop = [...newTop.filter((x) => !batchTop.includes(x)), ...discardedTop];
|
|
85
135
|
|
|
86
|
-
discardedBottom = [
|
|
87
|
-
...discardedBottom,
|
|
88
|
-
...newBottom.filter((x) => !batchBottom.includes(x)),
|
|
89
|
-
];
|
|
136
|
+
discardedBottom = [...discardedBottom, ...newBottom.filter((x) => !batchBottom.includes(x))];
|
|
90
137
|
|
|
91
138
|
newTop = batchTop;
|
|
92
139
|
newBottom = batchBottom;
|
|
@@ -110,4 +157,7 @@ const sort = async (
|
|
|
110
157
|
return finalList;
|
|
111
158
|
};
|
|
112
159
|
|
|
113
|
-
export default
|
|
160
|
+
export default async function sortWrapper(list, criteria, config = {}) {
|
|
161
|
+
const { model = modelService.getBestPublicModel(), ...options } = config;
|
|
162
|
+
return await sort({ by: criteria, ...options }, list, model, config);
|
|
163
|
+
}
|
|
@@ -101,15 +101,12 @@ describe('Sort', () => {
|
|
|
101
101
|
examples.forEach((example) => {
|
|
102
102
|
it(example.name, async () => {
|
|
103
103
|
const iterations = example.inputs.options.iterations ?? 1;
|
|
104
|
-
const result = await sort(example.inputs.
|
|
105
|
-
budgetTokens: () => ({ completion: 0 }),
|
|
104
|
+
const result = await sort(example.inputs.list, example.inputs.options.by, {
|
|
105
|
+
model: { budgetTokens: () => ({ completion: 0 }) },
|
|
106
|
+
...example.inputs.options,
|
|
106
107
|
});
|
|
107
|
-
expect(result.slice(0, extremeK * iterations)).toStrictEqual(
|
|
108
|
-
|
|
109
|
-
);
|
|
110
|
-
expect(result.slice(-(extremeK * iterations))).toStrictEqual(
|
|
111
|
-
example.want.lowest
|
|
112
|
-
);
|
|
108
|
+
expect(result.slice(0, extremeK * iterations)).toStrictEqual(example.want.highest);
|
|
109
|
+
expect(result.slice(-(extremeK * iterations))).toStrictEqual(example.want.lowest);
|
|
113
110
|
});
|
|
114
111
|
});
|
|
115
112
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"items": {
|
|
6
|
+
"type": "array",
|
|
7
|
+
"description": "Array of sorted items",
|
|
8
|
+
"items": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "A sorted item"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": ["items"],
|
|
15
|
+
"additionalProperties": false
|
|
16
|
+
}
|
|
@@ -19,7 +19,7 @@ ${data.example.code}`;
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const variableTokens = 100;
|
|
22
|
-
const promptTokens = modelService.
|
|
22
|
+
const promptTokens = modelService.getBestPublicModel().toTokens(promptFunction).length;
|
|
23
23
|
const solutionTokens = 200;
|
|
24
24
|
const maxTokens = promptTokens + variableTokens + solutionTokens
|
|
25
25
|
|
|
@@ -30,4 +30,12 @@ summaryMap.set('example.code', { value: 'Long code data...', weight: 0.5, type:
|
|
|
30
30
|
const promptInputs = await summaryMap.pavedSummaryResult();
|
|
31
31
|
const prompt = promptFunction(promptInputs);
|
|
32
32
|
const response = await chatGPT(prompt, { modelOptions: { maxTokens }});
|
|
33
|
+
|
|
34
|
+
// Privacy example
|
|
35
|
+
const privacyMap = new SummaryMap({ targetTokens: 50 });
|
|
36
|
+
privacyMap.set('example.text', {
|
|
37
|
+
value: 'Sensitive text with names',
|
|
38
|
+
privacy: { blacklist: 'names' },
|
|
39
|
+
});
|
|
40
|
+
const result = await privacyMap.pavedSummaryResult();
|
|
33
41
|
```
|
|
@@ -37,9 +37,16 @@ describe('Summary map', () => {
|
|
|
37
37
|
it(
|
|
38
38
|
'Example',
|
|
39
39
|
async () => {
|
|
40
|
-
const map = new SummaryMap({
|
|
40
|
+
const map = new SummaryMap({
|
|
41
|
+
targetTokens: 600,
|
|
42
|
+
modelOptions: { modelName: 'fastGood' },
|
|
43
|
+
});
|
|
41
44
|
|
|
42
|
-
map.set('a.b.c', {
|
|
45
|
+
map.set('a.b.c', {
|
|
46
|
+
value: legalText,
|
|
47
|
+
weight: 0.01,
|
|
48
|
+
privacy: { blacklist: 'names and addresses' },
|
|
49
|
+
});
|
|
43
50
|
map.set('a.d', { value: codeText, type: 'code', weight: 0.7 });
|
|
44
51
|
map.set('e.0', { value: 'abc', weight: 0.01 });
|
|
45
52
|
map.set('e.3', {
|