@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
|
@@ -6,9 +6,8 @@ vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
|
6
6
|
default: vi.fn().mockImplementation((text) => {
|
|
7
7
|
if (/prompt text to match/.test(text)) {
|
|
8
8
|
return 'True';
|
|
9
|
-
} else {
|
|
10
|
-
return 'undefined';
|
|
11
9
|
}
|
|
10
|
+
return 'undefined';
|
|
12
11
|
}),
|
|
13
12
|
}));
|
|
14
13
|
|
|
@@ -16,8 +15,8 @@ const examples = [
|
|
|
16
15
|
{
|
|
17
16
|
name: 'Basic usage',
|
|
18
17
|
inputs: { text: 'test' },
|
|
19
|
-
want: { result: true }
|
|
20
|
-
}
|
|
18
|
+
want: { result: true },
|
|
19
|
+
},
|
|
21
20
|
];
|
|
22
21
|
|
|
23
22
|
describe('Auto verblet', () => {
|
|
@@ -26,8 +25,7 @@ describe('Auto verblet', () => {
|
|
|
26
25
|
const result = await auto(example.inputs.text);
|
|
27
26
|
|
|
28
27
|
if (example.want.typeOfResult) {
|
|
29
|
-
expect(typeof result)
|
|
30
|
-
.toStrictEqual(example.want.typeOfResult);
|
|
28
|
+
expect(typeof result).toStrictEqual(example.want.typeOfResult);
|
|
31
29
|
}
|
|
32
30
|
});
|
|
33
31
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# bool
|
|
2
|
+
|
|
3
|
+
Interpret natural language questions as yes/no decisions and return a boolean.
|
|
4
|
+
The verblet uses ChatGPT to reason about the provided text and responds with
|
|
5
|
+
`true` or `false`.
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import bool from './index.js';
|
|
9
|
+
|
|
10
|
+
const result = await bool('Does Mace Windu have a purple lightsaber?');
|
|
11
|
+
// result === true
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Use case: deployment gate
|
|
15
|
+
|
|
16
|
+
You can feed dynamic context to `bool` to make policy decisions. Combine local
|
|
17
|
+
variables with text to create nuanced yes/no prompts that a large language model
|
|
18
|
+
can reason about:
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
const filesChanged = 3;
|
|
22
|
+
const testsPassing = 247;
|
|
23
|
+
const isFriday = true;
|
|
24
|
+
|
|
25
|
+
const shouldDeploy = await bool(`
|
|
26
|
+
It's ${isFriday ? 'Friday' : 'a weekday'} at 4:45 PM.
|
|
27
|
+
${filesChanged} files changed and all ${testsPassing} tests are passing.
|
|
28
|
+
The deployment window closes at 5 PM. Should we deploy to production?
|
|
29
|
+
`);
|
|
30
|
+
|
|
31
|
+
console.log(shouldDeploy);
|
|
32
|
+
// => false (A cautious answer based on the context)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
This approach enables policy checks and decision gates that rely on natural
|
|
36
|
+
language reasoning rather than hard‑coded rules.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
1
|
+
import { describe, expect, it, beforeAll, afterAll } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import bool from './index.js';
|
|
4
|
+
import aiExpect from '../expect/index.js';
|
|
4
5
|
import { longTestTimeout } from '../../constants/common.js';
|
|
5
6
|
|
|
6
7
|
const examples = [
|
|
@@ -15,14 +16,65 @@ const examples = [
|
|
|
15
16
|
];
|
|
16
17
|
|
|
17
18
|
describe('Bool verblet', () => {
|
|
19
|
+
// Set environment mode to 'none' for all tests to avoid throwing
|
|
20
|
+
const originalMode = process.env.LLM_EXPECT_MODE;
|
|
21
|
+
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
process.env.LLM_EXPECT_MODE = 'none';
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterAll(() => {
|
|
27
|
+
if (originalMode !== undefined) {
|
|
28
|
+
process.env.LLM_EXPECT_MODE = originalMode;
|
|
29
|
+
} else {
|
|
30
|
+
delete process.env.LLM_EXPECT_MODE;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
18
34
|
examples.forEach((example) => {
|
|
19
35
|
it(
|
|
20
36
|
`${example.inputs.text}`,
|
|
21
37
|
async () => {
|
|
22
38
|
const result = await bool(example.inputs.text);
|
|
23
39
|
expect(result).toStrictEqual(example.want.result);
|
|
40
|
+
|
|
41
|
+
// Additional LLM assertion to validate the boolean result makes sense
|
|
42
|
+
const resultMakesSense = await aiExpect({
|
|
43
|
+
question: example.inputs.text,
|
|
44
|
+
answer: result,
|
|
45
|
+
}).toSatisfy('Is this a reasonable yes/no answer to a Star Wars question?');
|
|
46
|
+
expect(resultMakesSense).toBe(true);
|
|
24
47
|
},
|
|
25
48
|
longTestTimeout
|
|
26
49
|
);
|
|
27
50
|
});
|
|
51
|
+
|
|
52
|
+
it(
|
|
53
|
+
'should handle complex contextual decisions',
|
|
54
|
+
async () => {
|
|
55
|
+
const complexQuestion = `
|
|
56
|
+
Given the context: It's Friday at 4:45 PM, we have 3 files changed (150+ lines, 20- lines),
|
|
57
|
+
all 247 tests are passing, and the deployment window closes at 5 PM.
|
|
58
|
+
Should we deploy this change to production?
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
const result = await bool(complexQuestion);
|
|
62
|
+
|
|
63
|
+
// Traditional assertion
|
|
64
|
+
expect(typeof result).toBe('boolean');
|
|
65
|
+
|
|
66
|
+
// LLM assertion to validate the decision reasoning
|
|
67
|
+
const decisionIsReasonable = await aiExpect(
|
|
68
|
+
`The question was about Friday afternoon deployment with passing tests. The decision was: ${result}`
|
|
69
|
+
).toSatisfy('Does this sound like a reasonable deployment decision?');
|
|
70
|
+
expect(decisionIsReasonable).toBe(true);
|
|
71
|
+
|
|
72
|
+
// Additional assertion about the decision being conservative
|
|
73
|
+
const isConservativeDecision = await aiExpect(
|
|
74
|
+
`A boolean decision of ${result} for Friday afternoon deployment`
|
|
75
|
+
).toSatisfy('Is this a cautious approach to deployment timing?');
|
|
76
|
+
expect(isConservativeDecision).toBe(true);
|
|
77
|
+
},
|
|
78
|
+
longTestTimeout
|
|
79
|
+
);
|
|
28
80
|
});
|
|
@@ -3,23 +3,20 @@ import stripResponse from '../../lib/strip-response/index.js';
|
|
|
3
3
|
import toBool from '../../lib/to-bool/index.js';
|
|
4
4
|
import { constants as promptConstants } from '../../prompts/index.js';
|
|
5
5
|
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
asUndefinedByDefault,
|
|
9
|
-
contentIsQuestion,
|
|
10
|
-
explainAndSeparate,
|
|
11
|
-
explainAndSeparatePrimitive,
|
|
12
|
-
} = promptConstants;
|
|
6
|
+
const { asBool, asUndefinedByDefault, explainAndSeparate, explainAndSeparatePrimitive } =
|
|
7
|
+
promptConstants;
|
|
13
8
|
|
|
14
|
-
export default async (text,
|
|
9
|
+
export default async (text, config = {}) => {
|
|
10
|
+
const { llm, ...options } = config;
|
|
15
11
|
const systemPrompt = `
|
|
16
12
|
${explainAndSeparate} ${explainAndSeparatePrimitive}
|
|
17
13
|
|
|
18
14
|
${asBool} ${asUndefinedByDefault}
|
|
19
|
-
|
|
15
|
+
`;
|
|
20
16
|
const response = await chatGPT(text, {
|
|
21
17
|
modelOptions: {
|
|
22
18
|
systemPrompt,
|
|
19
|
+
...llm,
|
|
23
20
|
},
|
|
24
21
|
...options,
|
|
25
22
|
});
|
|
@@ -27,9 +27,7 @@ const examples = [
|
|
|
27
27
|
describe('bool verblet', () => {
|
|
28
28
|
examples.forEach((example) => {
|
|
29
29
|
it(example.name, async () => {
|
|
30
|
-
expect(await bool(example.inputs.text)).toStrictEqual(
|
|
31
|
-
example.want.result
|
|
32
|
-
);
|
|
30
|
+
expect(await bool(example.inputs.text)).toStrictEqual(example.want.result);
|
|
33
31
|
});
|
|
34
32
|
});
|
|
35
33
|
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Central Tendency Verblet
|
|
2
|
+
|
|
3
|
+
A cognitive science-based function for evaluating how central or prototypical an item is within a category. Based on prototype theory and family resemblance principles from cognitive psychology.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `centralTendency` verblet assesses graded typicality by analyzing feature overlap, core characteristics, and functional alignment with seed items. It implements cognitive science principles to provide nuanced category membership evaluation beyond simple binary classification.
|
|
8
|
+
|
|
9
|
+
## Cognitive Science Foundations
|
|
10
|
+
|
|
11
|
+
### Prototype Theory
|
|
12
|
+
Categories have graded structure with central (prototypical) and peripheral members. Some items are better examples of a category than others.
|
|
13
|
+
|
|
14
|
+
### Family Resemblance
|
|
15
|
+
Category members share overlapping features without requiring identical characteristics. Items can belong to a category through different combinations of shared features.
|
|
16
|
+
|
|
17
|
+
### Graded Typicality
|
|
18
|
+
Membership exists on a continuum from highly typical (central) to atypical (peripheral) rather than binary in/out classification.
|
|
19
|
+
|
|
20
|
+
## Basic Usage
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { centralTendency } from './index.js';
|
|
24
|
+
|
|
25
|
+
// Evaluate bird centrality
|
|
26
|
+
const birdSeeds = ['robin', 'sparrow', 'bluejay', 'cardinal'];
|
|
27
|
+
const config = {
|
|
28
|
+
context: 'Evaluate based on typical bird characteristics and behavior',
|
|
29
|
+
coreFeatures: ['feathers', 'beak', 'lays eggs'],
|
|
30
|
+
llm: 'fastGoodCheap'
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const result = await centralTendency('robin', birdSeeds, config);
|
|
34
|
+
// Returns: { score: 0.92, reason: "Robin exemplifies core bird features...", confidence: 0.88 }
|
|
35
|
+
|
|
36
|
+
const penguinResult = await centralTendency('penguin', birdSeeds, config);
|
|
37
|
+
// Returns: { score: 0.65, reason: "Penguin is a bird but lacks flight...", confidence: 0.82 }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Advanced Features
|
|
41
|
+
|
|
42
|
+
### Sample Generation
|
|
43
|
+
Generate representative category examples:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
import categorySamples from '../../chains/category-samples/index.js';
|
|
47
|
+
|
|
48
|
+
const animalSamples = await categorySamples('animal', {
|
|
49
|
+
context: 'Diverse animal kingdom representation across phyla',
|
|
50
|
+
count: 6,
|
|
51
|
+
diversityLevel: 'high', // 'high', 'balanced', or 'focused'
|
|
52
|
+
llm: 'fastGoodCheap'
|
|
53
|
+
});
|
|
54
|
+
// Returns: ['dog', 'eagle', 'salmon', 'butterfly', 'octopus', 'frog']
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Bulk Processing
|
|
58
|
+
Evaluate multiple items efficiently:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
import { bulkCentralTendency } from './index.js';
|
|
62
|
+
|
|
63
|
+
const testAnimals = ['wolf', 'tiger', 'elephant', 'whale'];
|
|
64
|
+
const mammalSeeds = ['dog', 'cat', 'horse', 'cow'];
|
|
65
|
+
|
|
66
|
+
const results = await bulkCentralTendency(
|
|
67
|
+
testAnimals,
|
|
68
|
+
mammalSeeds,
|
|
69
|
+
{
|
|
70
|
+
context: 'Mammalian characteristics and traits',
|
|
71
|
+
coreFeatures: ['warm-blooded', 'hair/fur', 'mammary glands'],
|
|
72
|
+
llm: 'fastGoodCheap',
|
|
73
|
+
chunkSize: 3,
|
|
74
|
+
maxAttempts: 2
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Parameters
|
|
80
|
+
|
|
81
|
+
### centralTendency(item, seedItems, config)
|
|
82
|
+
|
|
83
|
+
- **item** (string): The item to evaluate for centrality
|
|
84
|
+
- **seedItems** (string[]): Array of known category members for comparison
|
|
85
|
+
- **config** (Object): Configuration options
|
|
86
|
+
- **context** (string): Context description for evaluation (default: '')
|
|
87
|
+
- **coreFeatures** (string[]): Known core/definitional features of the category (default: [])
|
|
88
|
+
- **llm** (string): LLM model to use (default: 'fastGoodCheap')
|
|
89
|
+
|
|
90
|
+
### categorySamples(categoryName, config)
|
|
91
|
+
|
|
92
|
+
- **categoryName** (string): Name of the category
|
|
93
|
+
- **config** (Object): Configuration options
|
|
94
|
+
- **context** (string): Context for seed generation (default: '')
|
|
95
|
+
- **count** (number): Number of seed items to generate (default: 8)
|
|
96
|
+
- **diversityLevel** (string): 'high', 'balanced', or 'focused' (default: 'balanced')
|
|
97
|
+
- **llm** (string): LLM model to use (default: 'fastGoodCheap')
|
|
98
|
+
|
|
99
|
+
## Return Values
|
|
100
|
+
|
|
101
|
+
### centralTendency Result
|
|
102
|
+
```javascript
|
|
103
|
+
{
|
|
104
|
+
score: 0.85, // Centrality score (0.0-1.0)
|
|
105
|
+
reason: "...", // Brief explanation of assessment
|
|
106
|
+
confidence: 0.82 // Confidence in assessment (0.0-1.0)
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Cognitive Science Applications
|
|
111
|
+
|
|
112
|
+
### Natural vs Artifact Categories
|
|
113
|
+
```javascript
|
|
114
|
+
// Natural categories often have clearer prototypes
|
|
115
|
+
const fruitConfig = {
|
|
116
|
+
context: 'Botanical fruit classification based on plant biology',
|
|
117
|
+
coreFeatures: ['seed-bearing', 'develops from flower']
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Artifact categories may be more functionally defined
|
|
121
|
+
const toolConfig = {
|
|
122
|
+
context: 'Hand tools for mechanical work and construction',
|
|
123
|
+
coreFeatures: ['handheld', 'mechanical advantage']
|
|
124
|
+
};
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Context Effects on Categorization
|
|
128
|
+
```javascript
|
|
129
|
+
// Same item, different contexts
|
|
130
|
+
const classicalConfig = {
|
|
131
|
+
context: 'Classical orchestral instruments for formal concerts',
|
|
132
|
+
coreFeatures: ['acoustic', 'complex technique', 'wide range']
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const folkConfig = {
|
|
136
|
+
context: 'Portable folk instruments for informal music',
|
|
137
|
+
coreFeatures: ['portable', 'easy to learn', 'expressive']
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Harmonica will score differently in each context
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Category Types
|
|
144
|
+
The verblet works best with:
|
|
145
|
+
- **Natural categories**: Birds, mammals, fruits, minerals
|
|
146
|
+
- **Artifact categories**: Tools, vehicles, furniture, instruments
|
|
147
|
+
- **Activity categories**: Sports, games, professions, hobbies
|
|
148
|
+
- **Abstract categories**: Emotions, concepts, relationships
|
|
149
|
+
|
|
150
|
+
Note: Avoid arbitrary collections (e.g., "things in my room") as these lack the coherent structure that prototype theory describes.
|
|
151
|
+
|
|
152
|
+
## Integration with Concept Science Chains
|
|
153
|
+
|
|
154
|
+
The `centralTendency` verblet integrates seamlessly with other concept science tools:
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
// Generate seeds, then evaluate centrality
|
|
158
|
+
const seeds = await categorySamples('vehicle', { context: 'Land transportation' });
|
|
159
|
+
const centrality = await centralTendency('bicycle', seeds, { context: 'Personal transportation' });
|
|
160
|
+
|
|
161
|
+
// Use in concept hierarchies
|
|
162
|
+
const superordinateSeeds = await categorySamples('animal');
|
|
163
|
+
const basicLevelSeeds = await categorySamples('bird');
|
|
164
|
+
const subordinateResult = await centralTendency('robin', basicLevelSeeds);
|
|
165
|
+
```
|
|
166
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"properties": {
|
|
6
|
+
"score": {
|
|
7
|
+
"type": "number",
|
|
8
|
+
"minimum": 0,
|
|
9
|
+
"maximum": 1,
|
|
10
|
+
"description": "Centrality score from 0.0 (peripheral) to 1.0 (prototypical)"
|
|
11
|
+
},
|
|
12
|
+
"reason": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Brief explanation of centrality assessment"
|
|
15
|
+
},
|
|
16
|
+
"confidence": {
|
|
17
|
+
"type": "number",
|
|
18
|
+
"minimum": 0,
|
|
19
|
+
"maximum": 1,
|
|
20
|
+
"description": "Confidence in this assessment"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"required": ["score", "reason", "confidence"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Examples for centralTendency verblet
|
|
3
|
+
* Demonstrates cognitive science applications in prototype theory and graded typicality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, expect, it } from 'vitest';
|
|
7
|
+
import centralTendency from './index.js';
|
|
8
|
+
import categorySamples from '../../chains/category-samples/index.js';
|
|
9
|
+
import bulkCentralTendency from '../../chains/bulk-central-tendency/index.js';
|
|
10
|
+
import { longTestTimeout } from '../../constants/common.js';
|
|
11
|
+
|
|
12
|
+
describe('centralTendency examples', () => {
|
|
13
|
+
it(
|
|
14
|
+
'evaluates bird centrality with new config format',
|
|
15
|
+
async () => {
|
|
16
|
+
const birdSeeds = ['robin', 'sparrow', 'bluejay', 'cardinal'];
|
|
17
|
+
|
|
18
|
+
const config = {
|
|
19
|
+
context: 'Evaluate based on typical bird characteristics and behavior',
|
|
20
|
+
coreFeatures: ['feathers', 'beak', 'lays eggs', 'flight'],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Test prototypical bird
|
|
24
|
+
const robinResult = await centralTendency('robin', birdSeeds, config);
|
|
25
|
+
expect(robinResult).toHaveProperty('score');
|
|
26
|
+
expect(robinResult).toHaveProperty('reason');
|
|
27
|
+
expect(robinResult).toHaveProperty('confidence');
|
|
28
|
+
expect(robinResult.score).toBeGreaterThanOrEqual(0.7); // Should be high centrality
|
|
29
|
+
|
|
30
|
+
// Test atypical but valid bird
|
|
31
|
+
const penguinResult = await centralTendency('penguin', birdSeeds, config);
|
|
32
|
+
expect(penguinResult.score).toBeGreaterThan(0.3);
|
|
33
|
+
expect(penguinResult.score).toBeLessThan(robinResult.score); // Should be lower than robin
|
|
34
|
+
|
|
35
|
+
// Test non-bird that flies
|
|
36
|
+
const batResult = await centralTendency('bat', birdSeeds, config);
|
|
37
|
+
expect(batResult.score).toBeLessThan(0.4); // Should be low centrality
|
|
38
|
+
},
|
|
39
|
+
longTestTimeout
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
it(
|
|
43
|
+
'compares natural vs artifact categories with fruit example',
|
|
44
|
+
async () => {
|
|
45
|
+
const fruitSeeds = ['apple', 'orange', 'banana', 'grape'];
|
|
46
|
+
|
|
47
|
+
// Biological/botanical context
|
|
48
|
+
const botanicalConfig = {
|
|
49
|
+
context: 'Judge by botanical definition and structure',
|
|
50
|
+
coreFeatures: ['seed-bearing', 'develops from flower', 'fleshy pericarp'],
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Culinary/folk context
|
|
54
|
+
const culinaryConfig = {
|
|
55
|
+
context: 'Judge by culinary use and folk categorization',
|
|
56
|
+
coreFeatures: ['sweet taste', 'eaten fresh', 'dessert-like'],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const botanicalResult = await centralTendency('tomato', fruitSeeds, botanicalConfig);
|
|
60
|
+
const culinaryResult = await centralTendency('tomato', fruitSeeds, culinaryConfig);
|
|
61
|
+
|
|
62
|
+
expect(botanicalResult.score).toBeGreaterThan(culinaryResult.score);
|
|
63
|
+
},
|
|
64
|
+
longTestTimeout
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
it(
|
|
68
|
+
'evaluates tool centrality with core features',
|
|
69
|
+
async () => {
|
|
70
|
+
const toolSeeds = ['hammer', 'screwdriver', 'wrench', 'pliers'];
|
|
71
|
+
|
|
72
|
+
const config = {
|
|
73
|
+
context: 'Hand tools for mechanical work and construction',
|
|
74
|
+
coreFeatures: ['handheld', 'mechanical advantage', 'durable materials'],
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const drillResult = await centralTendency('drill', toolSeeds, config);
|
|
78
|
+
const computerResult = await centralTendency('computer', toolSeeds, config);
|
|
79
|
+
|
|
80
|
+
expect(drillResult.score).toBeGreaterThan(computerResult.score);
|
|
81
|
+
expect(drillResult.score).toBeGreaterThanOrEqual(0.6); // Drill should be high (allow boundary)
|
|
82
|
+
expect(computerResult.score).toBeLessThan(0.5); // Computer should be low
|
|
83
|
+
},
|
|
84
|
+
longTestTimeout
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
it(
|
|
88
|
+
'generates seeds with different diversity levels',
|
|
89
|
+
async () => {
|
|
90
|
+
// High diversity seeds
|
|
91
|
+
const highDiversitySeeds = await categorySamples('animal', {
|
|
92
|
+
context: 'Diverse animal kingdom representation across phyla',
|
|
93
|
+
count: 6,
|
|
94
|
+
diversityLevel: 'high',
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(Array.isArray(highDiversitySeeds)).toBe(true);
|
|
98
|
+
expect(highDiversitySeeds.length).toBeGreaterThan(0);
|
|
99
|
+
expect(highDiversitySeeds.length).toBeLessThanOrEqual(6);
|
|
100
|
+
|
|
101
|
+
// Focused seeds
|
|
102
|
+
const focusedSeeds = await categorySamples('bird', {
|
|
103
|
+
context: 'Common backyard birds',
|
|
104
|
+
count: 5,
|
|
105
|
+
diversityLevel: 'focused',
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(Array.isArray(focusedSeeds)).toBe(true);
|
|
109
|
+
expect(focusedSeeds.length).toBeGreaterThan(0);
|
|
110
|
+
},
|
|
111
|
+
longTestTimeout
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
it(
|
|
115
|
+
'processes bulk items with error handling',
|
|
116
|
+
async () => {
|
|
117
|
+
const mammalSeeds = ['dog', 'cat', 'horse', 'cow'];
|
|
118
|
+
const testAnimals = ['wolf', 'tiger', 'elephant', 'whale', 'bat'];
|
|
119
|
+
|
|
120
|
+
const config = {
|
|
121
|
+
context: 'Mammalian characteristics and traits',
|
|
122
|
+
coreFeatures: ['warm-blooded', 'hair/fur', 'mammary glands', 'live birth'],
|
|
123
|
+
chunkSize: 3,
|
|
124
|
+
maxAttempts: 2,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const results = await bulkCentralTendency(testAnimals, mammalSeeds, config);
|
|
128
|
+
|
|
129
|
+
expect(results).toHaveLength(testAnimals.length);
|
|
130
|
+
|
|
131
|
+
// Check that most results are valid
|
|
132
|
+
const validResults = results.filter((r) => r !== undefined);
|
|
133
|
+
expect(validResults.length).toBeGreaterThan(testAnimals.length * 0.6);
|
|
134
|
+
|
|
135
|
+
// Validate structure of valid results
|
|
136
|
+
validResults.forEach((result) => {
|
|
137
|
+
expect(result).toHaveProperty('score');
|
|
138
|
+
expect(result).toHaveProperty('reason');
|
|
139
|
+
expect(result).toHaveProperty('confidence');
|
|
140
|
+
expect(result.score).toBeGreaterThanOrEqual(0);
|
|
141
|
+
expect(result.score).toBeLessThanOrEqual(1);
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
longTestTimeout
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
it(
|
|
148
|
+
'demonstrates graded typicality in sports',
|
|
149
|
+
async () => {
|
|
150
|
+
const sportsSeeds = ['basketball', 'football', 'tennis', 'swimming'];
|
|
151
|
+
|
|
152
|
+
const config = {
|
|
153
|
+
context: 'Competitive physical activities with rules and scoring',
|
|
154
|
+
coreFeatures: ['rules', 'competition', 'physical skill', 'scoring'],
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const soccerResult = await centralTendency('soccer', sportsSeeds, config);
|
|
158
|
+
const chessResult = await centralTendency('chess', sportsSeeds, config);
|
|
159
|
+
const videoGamesResult = await centralTendency('video games', sportsSeeds, config);
|
|
160
|
+
|
|
161
|
+
// Expect graded typicality: soccer should be more central than chess for physical sports
|
|
162
|
+
expect(soccerResult.score).toBeGreaterThan(chessResult.score);
|
|
163
|
+
// All results should be valid scores
|
|
164
|
+
expect(chessResult.score).toBeGreaterThanOrEqual(0);
|
|
165
|
+
expect(videoGamesResult.score).toBeGreaterThanOrEqual(0);
|
|
166
|
+
},
|
|
167
|
+
longTestTimeout
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
it(
|
|
171
|
+
'demonstrates context steering effects',
|
|
172
|
+
async () => {
|
|
173
|
+
const musicSeeds = ['piano', 'guitar', 'violin', 'drums'];
|
|
174
|
+
const testItem = 'harmonica';
|
|
175
|
+
|
|
176
|
+
// Traditional/classical music context
|
|
177
|
+
const classicalConfig = {
|
|
178
|
+
context: 'Classical and orchestral instruments for formal concerts',
|
|
179
|
+
coreFeatures: ['acoustic', 'complex technique', 'wide range'],
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Folk/portable music context
|
|
183
|
+
const folkConfig = {
|
|
184
|
+
context: 'Portable folk and street instruments',
|
|
185
|
+
coreFeatures: ['portable', 'easy to learn', 'expressive'],
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const classicalResult = await centralTendency(testItem, musicSeeds, classicalConfig);
|
|
189
|
+
const folkResult = await centralTendency(testItem, musicSeeds, folkConfig);
|
|
190
|
+
|
|
191
|
+
// Harmonica should score higher in folk context
|
|
192
|
+
expect(folkResult.score).toBeGreaterThan(classicalResult.score);
|
|
193
|
+
},
|
|
194
|
+
longTestTimeout
|
|
195
|
+
);
|
|
196
|
+
});
|