@far-world-labs/verblets 0.1.7 → 0.3.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 +86 -213
- package/dist/index.browser.js +74 -0
- package/dist/index.js +548 -0
- package/dist/shared-C6kPWghF.js +7806 -0
- package/package.json +32 -8
- package/.cursor/launch.json +0 -30
- package/.cursor/settings.json +0 -20
- package/.github/workflows/branch-protection.yml +0 -22
- package/.github/workflows/ci.yml +0 -165
- package/.husky/pre-commit +0 -4
- package/.prettierrc +0 -6
- package/.release-it.json +0 -12
- package/.vitest.config.examples.js +0 -8
- package/.vitest.config.js +0 -8
- package/.vscode/launch.json +0 -31
- package/AGENTS.md +0 -220
- package/DEVELOPING.md +0 -105
- package/docker-compose.yml +0 -7
- package/eslint.config.js +0 -80
- package/scripts/generate-chain/index.js +0 -111
- package/scripts/generate-lib/index.js +0 -68
- package/scripts/generate-test/index.js +0 -137
- package/scripts/generate-verblet/README.md +0 -17
- package/scripts/generate-verblet/index.js +0 -110
- package/scripts/run.sh +0 -15
- package/scripts/runner/index.js +0 -56
- package/scripts/simple-editor/README.md +0 -34
- package/scripts/simple-editor/index.js +0 -79
- package/scripts/summarize-files/index.js +0 -70
- package/src/chains/README.md +0 -30
- package/src/chains/anonymize/README.md +0 -21
- package/src/chains/anonymize/index.examples.js +0 -75
- package/src/chains/anonymize/index.js +0 -121
- package/src/chains/anonymize/index.spec.js +0 -78
- package/src/chains/bulk-central-tendency/index.examples.js +0 -138
- package/src/chains/bulk-central-tendency/index.js +0 -91
- package/src/chains/bulk-filter/README.md +0 -21
- package/src/chains/bulk-filter/index.examples.js +0 -22
- package/src/chains/bulk-filter/index.js +0 -58
- package/src/chains/bulk-filter/index.spec.js +0 -38
- package/src/chains/bulk-find/README.md +0 -16
- package/src/chains/bulk-find/index.examples.js +0 -20
- package/src/chains/bulk-find/index.js +0 -30
- package/src/chains/bulk-find/index.spec.js +0 -26
- package/src/chains/bulk-group/README.md +0 -23
- package/src/chains/bulk-group/index.examples.js +0 -18
- package/src/chains/bulk-group/index.js +0 -34
- package/src/chains/bulk-group/index.spec.js +0 -41
- package/src/chains/bulk-map/README.md +0 -43
- package/src/chains/bulk-map/index.examples.js +0 -17
- package/src/chains/bulk-map/index.js +0 -86
- package/src/chains/bulk-map/index.spec.js +0 -44
- package/src/chains/bulk-reduce/README.md +0 -12
- package/src/chains/bulk-reduce/index.examples.js +0 -15
- package/src/chains/bulk-reduce/index.js +0 -13
- package/src/chains/bulk-reduce/index.spec.js +0 -25
- package/src/chains/bulk-score/README.md +0 -16
- package/src/chains/bulk-score/bulk-score-result.json +0 -18
- package/src/chains/bulk-score/index.examples.js +0 -22
- package/src/chains/bulk-score/index.js +0 -133
- package/src/chains/bulk-score/index.spec.js +0 -30
- package/src/chains/category-samples/README.md +0 -61
- package/src/chains/category-samples/index.examples.js +0 -103
- package/src/chains/category-samples/index.js +0 -134
- package/src/chains/collect-terms/README.md +0 -12
- package/src/chains/collect-terms/index.examples.js +0 -16
- package/src/chains/collect-terms/index.js +0 -44
- package/src/chains/collect-terms/index.spec.js +0 -25
- package/src/chains/date/README.md +0 -12
- package/src/chains/date/index.examples.js +0 -47
- package/src/chains/date/index.js +0 -74
- package/src/chains/date/index.spec.js +0 -62
- package/src/chains/disambiguate/README.md +0 -22
- package/src/chains/disambiguate/disambiguate-meanings-result.json +0 -16
- package/src/chains/disambiguate/index.examples.js +0 -18
- package/src/chains/disambiguate/index.js +0 -92
- package/src/chains/disambiguate/index.spec.js +0 -25
- package/src/chains/dismantle/README.md +0 -67
- package/src/chains/dismantle/dismantle.examples.js +0 -27
- package/src/chains/dismantle/index.examples.js +0 -30
- package/src/chains/dismantle/index.js +0 -303
- package/src/chains/dismantle/index.spec.js +0 -32
- package/src/chains/expect/README.md +0 -171
- package/src/chains/expect/index.examples.js +0 -146
- package/src/chains/expect/index.js +0 -173
- package/src/chains/expect/index.spec.js +0 -324
- package/src/chains/filter-ambiguous/README.md +0 -11
- package/src/chains/filter-ambiguous/index.examples.js +0 -20
- package/src/chains/filter-ambiguous/index.js +0 -49
- package/src/chains/filter-ambiguous/index.spec.js +0 -31
- package/src/chains/glossary/README.md +0 -19
- package/src/chains/glossary/index.examples.js +0 -386
- package/src/chains/glossary/index.js +0 -75
- package/src/chains/glossary/index.spec.js +0 -19
- package/src/chains/intersections/README.md +0 -152
- package/src/chains/intersections/index.examples.js +0 -279
- package/src/chains/intersections/index.js +0 -366
- package/src/chains/intersections/intersection-result.json +0 -38
- package/src/chains/list/index.examples.js +0 -68
- package/src/chains/list/index.js +0 -214
- package/src/chains/list/index.spec.js +0 -67
- package/src/chains/list/list-result.json +0 -16
- package/src/chains/list/schema.json +0 -24
- package/src/chains/llm-logger/README.md +0 -208
- package/src/chains/llm-logger/index.js +0 -205
- package/src/chains/llm-logger/index.spec.js +0 -330
- package/src/chains/questions/index.examples.js +0 -69
- package/src/chains/questions/index.js +0 -135
- package/src/chains/questions/index.spec.js +0 -29
- package/src/chains/scan-js/index.js +0 -116
- package/src/chains/set-interval/README.md +0 -81
- package/src/chains/set-interval/index.examples.js +0 -36
- package/src/chains/set-interval/index.js +0 -131
- package/src/chains/set-interval/index.spec.js +0 -70
- package/src/chains/socratic/README.md +0 -17
- package/src/chains/socratic/index.js +0 -64
- package/src/chains/socratic/index.spec.js +0 -24
- package/src/chains/sort/index.examples.js +0 -36
- package/src/chains/sort/index.js +0 -163
- package/src/chains/sort/index.spec.js +0 -112
- package/src/chains/sort/sort-result.json +0 -16
- package/src/chains/summary-map/README.md +0 -41
- package/src/chains/summary-map/index.examples.js +0 -64
- package/src/chains/summary-map/index.js +0 -226
- package/src/chains/summary-map/index.spec.js +0 -153
- package/src/chains/test/index.js +0 -114
- package/src/chains/test-advice/index.js +0 -35
- package/src/chains/themes/README.md +0 -20
- package/src/chains/themes/index.examples.js +0 -17
- package/src/chains/themes/index.js +0 -28
- package/src/chains/themes/index.spec.js +0 -19
- package/src/chains/veiled-variants/index.examples.js +0 -18
- package/src/chains/veiled-variants/index.js +0 -107
- package/src/chains/veiled-variants/index.spec.js +0 -40
- package/src/constants/common.js +0 -7
- package/src/constants/messages.js +0 -3
- package/src/constants/models.js +0 -183
- package/src/index.js +0 -193
- package/src/json-schemas/README.md +0 -13
- package/src/json-schemas/cars-test.json +0 -11
- package/src/json-schemas/index.js +0 -12
- package/src/json-schemas/intent.json +0 -38
- package/src/json-schemas/schema-dot-org-photograph.json +0 -133
- package/src/json-schemas/schema-dot-org-place.json +0 -129
- package/src/lib/README.md +0 -26
- package/src/lib/any-signal/index.js +0 -28
- package/src/lib/bulk-filter/README.md +0 -22
- package/src/lib/bulk-filter/index.examples.js +0 -27
- package/src/lib/bulk-filter/index.js +0 -63
- package/src/lib/bulk-filter/index.spec.js +0 -38
- package/src/lib/bulk-find/README.md +0 -18
- package/src/lib/bulk-find/index.examples.js +0 -19
- package/src/lib/bulk-find/index.js +0 -30
- package/src/lib/bulk-find/index.spec.js +0 -41
- package/src/lib/chatgpt/index.js +0 -163
- package/src/lib/combinations/index.js +0 -30
- package/src/lib/combinations/index.spec.js +0 -23
- package/src/lib/editor/index.js +0 -31
- package/src/lib/functional/index.js +0 -28
- package/src/lib/logger-service/index.js +0 -32
- package/src/lib/parse-js-parts/index.js +0 -321
- package/src/lib/parse-js-parts/index.spec.js +0 -156
- package/src/lib/parse-llm-list/README.md +0 -39
- package/src/lib/parse-llm-list/index.js +0 -54
- package/src/lib/parse-llm-list/index.spec.js +0 -59
- package/src/lib/path-aliases/index.js +0 -37
- package/src/lib/path-aliases/index.spec.js +0 -64
- package/src/lib/pave/index.js +0 -34
- package/src/lib/pave/index.spec.js +0 -76
- package/src/lib/prompt-cache/index.js +0 -50
- package/src/lib/retry/index.js +0 -66
- package/src/lib/retry/index.spec.js +0 -86
- package/src/lib/ring-buffer/README.md +0 -460
- package/src/lib/ring-buffer/index.js +0 -1074
- package/src/lib/search-best-first/city-walk.spec.js +0 -37
- package/src/lib/search-best-first/index.js +0 -97
- package/src/lib/search-best-first/index.spec.js +0 -35
- package/src/lib/search-js-files/code-features-property-definitions.json +0 -123
- package/src/lib/search-js-files/index.examples.js +0 -22
- package/src/lib/search-js-files/index.js +0 -155
- package/src/lib/search-js-files/index.spec.js +0 -34
- package/src/lib/search-js-files/scan-file.js +0 -242
- package/src/lib/shorten-text/index.js +0 -25
- package/src/lib/shorten-text/index.spec.js +0 -68
- package/src/lib/strip-numeric/index.js +0 -5
- package/src/lib/strip-response/index.js +0 -30
- package/src/lib/template-replace/index.js +0 -23
- package/src/lib/template-replace/index.spec.js +0 -60
- package/src/lib/timed-abort-controller/index.js +0 -41
- package/src/lib/to-bool/index.js +0 -8
- package/src/lib/to-date/index.js +0 -11
- package/src/lib/to-enum/index.js +0 -14
- package/src/lib/to-number/index.js +0 -12
- package/src/lib/to-number-with-units/index.js +0 -51
- package/src/lib/transcribe/index.js +0 -78
- package/src/prompts/README.md +0 -17
- package/src/prompts/as-enum.js +0 -5
- package/src/prompts/as-json-schema.js +0 -9
- package/src/prompts/as-object-with-schema.js +0 -26
- package/src/prompts/as-schema-org-text.js +0 -25
- package/src/prompts/as-schema-org-type.js +0 -1
- package/src/prompts/blog-post.js +0 -7
- package/src/prompts/code-features.js +0 -24
- package/src/prompts/constants.js +0 -101
- package/src/prompts/features-json-schema.js +0 -27
- package/src/prompts/generate-collection.js +0 -26
- package/src/prompts/generate-list.js +0 -48
- package/src/prompts/generate-questions.js +0 -19
- package/src/prompts/index.js +0 -20
- package/src/prompts/intent.js +0 -60
- package/src/prompts/output-succinct-names.js +0 -3
- package/src/prompts/select-from-threshold.js +0 -17
- package/src/prompts/sort.js +0 -31
- package/src/prompts/style.js +0 -38
- package/src/prompts/summarize.js +0 -13
- package/src/prompts/token-budget.js +0 -3
- package/src/prompts/wrap-list.js +0 -11
- package/src/prompts/wrap-variable.js +0 -36
- package/src/services/llm-model/global-overrides.spec.js +0 -432
- package/src/services/llm-model/index.js +0 -308
- package/src/services/llm-model/model.js +0 -21
- package/src/services/llm-model/negotiate.spec.js +0 -447
- package/src/services/redis/index.js +0 -147
- package/src/test/setup.js +0 -20
- package/src/verblets/README.md +0 -26
- package/src/verblets/auto/index.examples.js +0 -31
- package/src/verblets/auto/index.js +0 -28
- package/src/verblets/auto/index.spec.js +0 -32
- package/src/verblets/bool/README.md +0 -36
- package/src/verblets/bool/index.examples.js +0 -80
- package/src/verblets/bool/index.js +0 -25
- package/src/verblets/bool/index.schema.json +0 -14
- package/src/verblets/bool/index.spec.js +0 -33
- package/src/verblets/central-tendency/README.md +0 -166
- package/src/verblets/central-tendency/central-tendency-result.json +0 -24
- package/src/verblets/central-tendency/index.examples.js +0 -196
- package/src/verblets/central-tendency/index.js +0 -171
- package/src/verblets/central-tendency/index.spec.js +0 -148
- package/src/verblets/enum/index.examples.js +0 -30
- package/src/verblets/enum/index.js +0 -18
- package/src/verblets/enum/index.spec.js +0 -35
- package/src/verblets/expect/README.md +0 -64
- package/src/verblets/expect/index.examples.js +0 -109
- package/src/verblets/expect/index.js +0 -75
- package/src/verblets/expect/index.spec.js +0 -127
- package/src/verblets/intent/index.examples.js +0 -139
- package/src/verblets/intent/index.js +0 -60
- package/src/verblets/intent/index.spec.js +0 -31
- package/src/verblets/intersection/README.md +0 -16
- package/src/verblets/intersection/index.examples.js +0 -89
- package/src/verblets/intersection/index.js +0 -84
- package/src/verblets/intersection/index.spec.js +0 -60
- package/src/verblets/intersection/intersection-result.json +0 -16
- package/src/verblets/list-expand/README.md +0 -10
- package/src/verblets/list-expand/index.examples.js +0 -14
- package/src/verblets/list-expand/index.js +0 -104
- package/src/verblets/list-expand/index.spec.js +0 -18
- package/src/verblets/list-expand/list-expand-result.json +0 -16
- package/src/verblets/list-filter/README.md +0 -22
- package/src/verblets/list-filter/index.examples.js +0 -26
- package/src/verblets/list-filter/index.js +0 -18
- package/src/verblets/list-filter/index.spec.js +0 -19
- package/src/verblets/list-find/README.md +0 -11
- package/src/verblets/list-find/index.examples.js +0 -15
- package/src/verblets/list-find/index.js +0 -17
- package/src/verblets/list-find/index.spec.js +0 -19
- package/src/verblets/list-group/README.md +0 -16
- package/src/verblets/list-group/index.examples.js +0 -16
- package/src/verblets/list-group/index.js +0 -112
- package/src/verblets/list-group/index.spec.js +0 -35
- package/src/verblets/list-group/list-group-result.json +0 -16
- package/src/verblets/list-map/README.md +0 -11
- package/src/verblets/list-map/index.examples.js +0 -15
- package/src/verblets/list-map/index.js +0 -26
- package/src/verblets/list-map/index.spec.js +0 -17
- package/src/verblets/list-reduce/README.md +0 -10
- package/src/verblets/list-reduce/index.examples.js +0 -14
- package/src/verblets/list-reduce/index.js +0 -21
- package/src/verblets/list-reduce/index.spec.js +0 -27
- package/src/verblets/list-reduce/index.spec.jsx +0 -27
- package/src/verblets/name/README.md +0 -15
- package/src/verblets/name/index.examples.js +0 -28
- package/src/verblets/name/index.js +0 -19
- package/src/verblets/name/index.spec.js +0 -33
- package/src/verblets/name-similar-to/README.md +0 -26
- package/src/verblets/name-similar-to/index.examples.js +0 -18
- package/src/verblets/name-similar-to/index.js +0 -20
- package/src/verblets/name-similar-to/index.spec.js +0 -13
- package/src/verblets/number/index.examples.js +0 -199
- package/src/verblets/number/index.js +0 -25
- package/src/verblets/number/index.spec.js +0 -33
- package/src/verblets/number-with-units/index.examples.js +0 -38
- package/src/verblets/number-with-units/index.js +0 -84
- package/src/verblets/number-with-units/index.spec.js +0 -46
- package/src/verblets/number-with-units/number-with-units-result.json +0 -23
- package/src/verblets/schema-org/index.examples.js +0 -51
- package/src/verblets/schema-org/index.js +0 -37
- package/src/verblets/schema-org/index.spec.js +0 -39
- package/src/verblets/sentiment/README.md +0 -10
- package/src/verblets/sentiment/index.examples.js +0 -20
- package/src/verblets/sentiment/index.js +0 -9
- package/src/verblets/sentiment/index.spec.js +0 -20
- package/src/verblets/to-object/README.md +0 -38
- package/src/verblets/to-object/index.examples.js +0 -29
- package/src/verblets/to-object/index.js +0 -131
- package/src/verblets/to-object/index.spec.js +0 -71
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import chatGPT from '../../lib/chatgpt/index.js';
|
|
5
|
-
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
6
|
-
|
|
7
|
-
// Get the directory of this module
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Load the JSON schema for list expand results
|
|
13
|
-
* @returns {Promise<Object>} JSON schema for validation
|
|
14
|
-
*/
|
|
15
|
-
async function getListExpandSchema() {
|
|
16
|
-
const schemaPath = path.join(__dirname, 'list-expand-result.json');
|
|
17
|
-
return JSON.parse(await fs.readFile(schemaPath, 'utf8'));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Create model options for structured outputs
|
|
22
|
-
* @param {string|Object} llm - LLM model name or configuration object
|
|
23
|
-
* @returns {Promise<Object>} Model options for chatGPT
|
|
24
|
-
*/
|
|
25
|
-
async function createModelOptions(llm = 'fastGoodCheap') {
|
|
26
|
-
const schema = await getListExpandSchema();
|
|
27
|
-
|
|
28
|
-
const responseFormat = {
|
|
29
|
-
type: 'json_schema',
|
|
30
|
-
json_schema: {
|
|
31
|
-
name: 'list_expand_result',
|
|
32
|
-
schema,
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
if (typeof llm === 'string') {
|
|
37
|
-
return {
|
|
38
|
-
modelName: llm,
|
|
39
|
-
response_format: responseFormat,
|
|
40
|
-
};
|
|
41
|
-
} else {
|
|
42
|
-
return {
|
|
43
|
-
...llm,
|
|
44
|
-
response_format: responseFormat,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// TODO: This could potentially be refactored to use the list chain (../../chains/list/index.js)
|
|
50
|
-
// for better consistency, but would require adapting the list chain to support this simpler
|
|
51
|
-
// expansion use case without changing the current behavior and test expectations.
|
|
52
|
-
|
|
53
|
-
const buildPrompt = function (list, count) {
|
|
54
|
-
const listBlock = wrapVariable(list.join('\n'), { tag: 'list' });
|
|
55
|
-
return (
|
|
56
|
-
`Expand <list> with new items that belong to the same category and ` +
|
|
57
|
-
`match the style of the existing entries. Avoid duplicates or extraneous ` +
|
|
58
|
-
`text. Continue adding entries until there are at least ${count} in total. ` +
|
|
59
|
-
`Return a JSON object with an "items" array containing all the expanded items.\n\n${listBlock}`
|
|
60
|
-
);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Expand a list with new items that belong to the same category and match the style.
|
|
65
|
-
* This is a simplified interface to the list chain for expansion use cases.
|
|
66
|
-
*
|
|
67
|
-
* @param {string[]} existingList - The list to expand
|
|
68
|
-
* @param {number} targetCount - Target total count (default: double the input)
|
|
69
|
-
* @param {Object} config - Configuration options including llm settings
|
|
70
|
-
* @returns {Promise<string[]>} Expanded list
|
|
71
|
-
*/
|
|
72
|
-
export default async function listExpand(list, count = list.length * 2, config = {}) {
|
|
73
|
-
const { llm, ...options } = config;
|
|
74
|
-
const modelOptions = await createModelOptions(llm);
|
|
75
|
-
const output = await chatGPT(buildPrompt(list, count), { modelOptions, ...options });
|
|
76
|
-
|
|
77
|
-
// With structured outputs, response should already be parsed and validated
|
|
78
|
-
let parsed;
|
|
79
|
-
if (typeof output === 'string') {
|
|
80
|
-
try {
|
|
81
|
-
parsed = JSON.parse(output);
|
|
82
|
-
} catch {
|
|
83
|
-
// Handle non-JSON responses (e.g., from mocks or fallback cases)
|
|
84
|
-
// Split by newlines and filter out empty lines
|
|
85
|
-
const lines = output
|
|
86
|
-
.split('\n')
|
|
87
|
-
.map((line) => line.trim())
|
|
88
|
-
.filter((line) => line.length > 0);
|
|
89
|
-
parsed = { items: lines };
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
parsed = output;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Extract items from the object structure
|
|
96
|
-
const items = parsed?.items || parsed;
|
|
97
|
-
|
|
98
|
-
if (!Array.isArray(items)) {
|
|
99
|
-
console.warn('Expected items array, got:', typeof items);
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return items;
|
|
104
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import listExpand from './index.js';
|
|
3
|
-
|
|
4
|
-
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
5
|
-
default: vi.fn(async (prompt) => {
|
|
6
|
-
const match = prompt.match(/<list>\n([\s\S]*?)\n<\/list>/);
|
|
7
|
-
const lines = match ? match[1].split('\n') : [];
|
|
8
|
-
const extras = lines.map((l) => `${l}-extra`);
|
|
9
|
-
return [...lines, ...extras].join('\n');
|
|
10
|
-
}),
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
describe('list-expand verblet', () => {
|
|
14
|
-
it('expands items to at least the requested count', async () => {
|
|
15
|
-
const result = await listExpand(['alpha', 'beta'], 4);
|
|
16
|
-
expect(result).toStrictEqual(['alpha', 'beta', 'alpha-extra', 'beta-extra']);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"type": "object",
|
|
4
|
-
"properties": {
|
|
5
|
-
"items": {
|
|
6
|
-
"type": "array",
|
|
7
|
-
"description": "Array of expanded list items",
|
|
8
|
-
"items": {
|
|
9
|
-
"type": "string",
|
|
10
|
-
"description": "A list item that belongs to the same category and matches the style"
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"required": ["items"],
|
|
15
|
-
"additionalProperties": false
|
|
16
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# list-filter
|
|
2
|
-
|
|
3
|
-
Filter a list with a single ChatGPT call using custom instructions.
|
|
4
|
-
|
|
5
|
-
```javascript
|
|
6
|
-
import listFilter from './index.js';
|
|
7
|
-
|
|
8
|
-
const reflections = [
|
|
9
|
-
'Losing that match taught me the value of persistence.',
|
|
10
|
-
"I hate losing and it proves I'm worthless.",
|
|
11
|
-
'After failing my exam, I studied harder and passed the retake.',
|
|
12
|
-
"No matter what I do, I'll never succeed.",
|
|
13
|
-
];
|
|
14
|
-
const growth = await listFilter(
|
|
15
|
-
reflections,
|
|
16
|
-
'keep only reflections that show personal growth or learning from mistakes'
|
|
17
|
-
);
|
|
18
|
-
// => [
|
|
19
|
-
// 'Losing that match taught me the value of persistence.',
|
|
20
|
-
// 'After failing my exam, I studied harder and passed the retake.',
|
|
21
|
-
// ]
|
|
22
|
-
```
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import listFilter from './index.js';
|
|
3
|
-
import { longTestTimeout } from '../../constants/common.js';
|
|
4
|
-
|
|
5
|
-
describe('list-filter examples', () => {
|
|
6
|
-
it(
|
|
7
|
-
'filters items with custom instructions',
|
|
8
|
-
async () => {
|
|
9
|
-
const entries = [
|
|
10
|
-
'Losing that match taught me the value of persistence.',
|
|
11
|
-
"I hate losing and it proves I'm worthless.",
|
|
12
|
-
'After failing my exam, I studied harder and passed the retake.',
|
|
13
|
-
"No matter what I do, I'll never succeed.",
|
|
14
|
-
];
|
|
15
|
-
const result = await listFilter(
|
|
16
|
-
entries,
|
|
17
|
-
'keep only reflections that show personal growth or learning from mistakes'
|
|
18
|
-
);
|
|
19
|
-
expect(result).toStrictEqual([
|
|
20
|
-
'Losing that match taught me the value of persistence.',
|
|
21
|
-
'After failing my exam, I studied harder and passed the retake.',
|
|
22
|
-
]);
|
|
23
|
-
},
|
|
24
|
-
longTestTimeout
|
|
25
|
-
);
|
|
26
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import chatGPT from '../../lib/chatgpt/index.js';
|
|
2
|
-
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
3
|
-
|
|
4
|
-
function buildPrompt(list, instructions) {
|
|
5
|
-
const instructionsBlock = wrapVariable(instructions, { tag: 'instructions' });
|
|
6
|
-
const listBlock = wrapVariable(list.join('\n'), { tag: 'list' });
|
|
7
|
-
return `From the <list>, select only the items that satisfy the <instructions>. Return one item per line without numbering. If none match, return an empty string.\n\n${instructionsBlock}\n${listBlock}`;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default async function listFilter(list, instructions, config = {}) {
|
|
11
|
-
const { llm, ...options } = config;
|
|
12
|
-
const output = await chatGPT(buildPrompt(list, instructions), {
|
|
13
|
-
modelOptions: { ...llm },
|
|
14
|
-
...options,
|
|
15
|
-
});
|
|
16
|
-
const trimmed = output.trim();
|
|
17
|
-
return trimmed ? trimmed.split('\n') : [];
|
|
18
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import listFilter from './index.js';
|
|
3
|
-
|
|
4
|
-
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
5
|
-
default: vi.fn(async (prompt) => {
|
|
6
|
-
const listMatch = prompt.match(/<list>\n([\s\S]*?)\n<\/list>/);
|
|
7
|
-
const lines = listMatch ? listMatch[1].split('\n') : [];
|
|
8
|
-
const instMatch = prompt.match(/"([^"]+)"/);
|
|
9
|
-
const letter = instMatch ? instMatch[1] : '';
|
|
10
|
-
return lines.filter((l) => l.includes(letter)).join('\n');
|
|
11
|
-
}),
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
describe('list-filter verblet', () => {
|
|
15
|
-
it('filters items using instructions', async () => {
|
|
16
|
-
const result = await listFilter(['alpha', 'beta', 'gamma'], 'm');
|
|
17
|
-
expect(result).toStrictEqual(['gamma']);
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# list-find
|
|
2
|
-
|
|
3
|
-
Find the single best match in a list using natural language instructions.
|
|
4
|
-
|
|
5
|
-
```javascript
|
|
6
|
-
import listFind from './index.js';
|
|
7
|
-
|
|
8
|
-
const snacks = ['apple pie', 'fruit roll-up', 'carrot sticks'];
|
|
9
|
-
await listFind(snacks, 'which snack feels most nostalgic for kids of the 90s?');
|
|
10
|
-
// => 'fruit roll-up'
|
|
11
|
-
```
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import listFind from './index.js';
|
|
3
|
-
import { longTestTimeout } from '../../constants/common.js';
|
|
4
|
-
|
|
5
|
-
describe('list-find examples', () => {
|
|
6
|
-
it(
|
|
7
|
-
'finds the item that best fits the instructions',
|
|
8
|
-
async () => {
|
|
9
|
-
const books = ['space adventure', 'medieval romance', 'futuristic mystery'];
|
|
10
|
-
const result = await listFind(books, 'which book sounds most futuristic?');
|
|
11
|
-
expect(result).toBeDefined();
|
|
12
|
-
},
|
|
13
|
-
longTestTimeout
|
|
14
|
-
);
|
|
15
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import chatGPT from '../../lib/chatgpt/index.js';
|
|
2
|
-
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
3
|
-
|
|
4
|
-
const buildPrompt = (list, instructions) => {
|
|
5
|
-
const instructionsBlock = wrapVariable(instructions, { tag: 'instructions' });
|
|
6
|
-
const listBlock = wrapVariable(list.join('\n'), { tag: 'list' });
|
|
7
|
-
return `From the <list>, select the single item that best satisfies the <instructions>. If none apply, return an empty string.\n\n${instructionsBlock}\n${listBlock}`;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default async function listFind(list, instructions, config = {}) {
|
|
11
|
-
const { llm, ...options } = config;
|
|
12
|
-
const output = await chatGPT(buildPrompt(list, instructions), {
|
|
13
|
-
modelOptions: { ...llm },
|
|
14
|
-
...options,
|
|
15
|
-
});
|
|
16
|
-
return output.trim();
|
|
17
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import listFind from './index.js';
|
|
3
|
-
|
|
4
|
-
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
5
|
-
default: vi.fn(async (prompt) => {
|
|
6
|
-
const listMatch = prompt.match(/<list>\n([\s\S]*?)\n<\/list>/);
|
|
7
|
-
const lines = listMatch ? listMatch[1].split('\n') : [];
|
|
8
|
-
const parts = prompt.split('"');
|
|
9
|
-
const letter = [...parts].reverse().find((p) => /^[a-z]+$/i.test(p.trim())) || '';
|
|
10
|
-
return lines.find((l) => l.includes(letter)) || '';
|
|
11
|
-
}),
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
describe('list-find verblet', () => {
|
|
15
|
-
it('finds item using instructions', async () => {
|
|
16
|
-
const result = await listFind(['alpha', 'beta', 'gamma'], 'find "b"');
|
|
17
|
-
expect(result).toBe('beta');
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# list-group
|
|
2
|
-
|
|
3
|
-
Group a list into stable groups using custom instructions. Optionally
|
|
4
|
-
provide a list of categories to maintain consistency across runs.
|
|
5
|
-
|
|
6
|
-
```javascript
|
|
7
|
-
import listGroup from './index.js';
|
|
8
|
-
|
|
9
|
-
const categories = ['fruit', 'vegetable'];
|
|
10
|
-
await listGroup(
|
|
11
|
-
['apple', 'banana', 'carrot'],
|
|
12
|
-
'Classify each item',
|
|
13
|
-
categories
|
|
14
|
-
);
|
|
15
|
-
// => { fruit: ['apple', 'banana'], vegetable: ['carrot'] }
|
|
16
|
-
```
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import listGroup from './index.js';
|
|
3
|
-
import { longTestTimeout } from '../../constants/common.js';
|
|
4
|
-
|
|
5
|
-
describe('list-group examples', () => {
|
|
6
|
-
it(
|
|
7
|
-
'groups a list into categories',
|
|
8
|
-
async () => {
|
|
9
|
-
const items = ['apple', 'beer', 'orange', 'wine', 'banana'];
|
|
10
|
-
const result = await listGroup(items, 'Group as drinks or food', ['drink', 'food']);
|
|
11
|
-
expect(typeof result).toBe('object');
|
|
12
|
-
expect(Object.keys(result).length).toBeGreaterThan(0);
|
|
13
|
-
},
|
|
14
|
-
longTestTimeout
|
|
15
|
-
);
|
|
16
|
-
});
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import chatGPT from '../../lib/chatgpt/index.js';
|
|
5
|
-
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
6
|
-
|
|
7
|
-
// Get the directory of this module
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Load the JSON schema for list group results
|
|
13
|
-
* @returns {Promise<Object>} JSON schema for validation
|
|
14
|
-
*/
|
|
15
|
-
async function getListGroupSchema() {
|
|
16
|
-
const schemaPath = path.join(__dirname, 'list-group-result.json');
|
|
17
|
-
return JSON.parse(await fs.readFile(schemaPath, 'utf8'));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Create model options for structured outputs
|
|
22
|
-
* @param {string|Object} llm - LLM model name or configuration object
|
|
23
|
-
* @returns {Promise<Object>} Model options for chatGPT
|
|
24
|
-
*/
|
|
25
|
-
async function createModelOptions(llm = 'fastGoodCheap') {
|
|
26
|
-
const schema = await getListGroupSchema();
|
|
27
|
-
|
|
28
|
-
const responseFormat = {
|
|
29
|
-
type: 'json_schema',
|
|
30
|
-
json_schema: {
|
|
31
|
-
name: 'list_group_result',
|
|
32
|
-
schema,
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
if (typeof llm === 'string') {
|
|
37
|
-
return {
|
|
38
|
-
modelName: llm,
|
|
39
|
-
response_format: responseFormat,
|
|
40
|
-
};
|
|
41
|
-
} else {
|
|
42
|
-
return {
|
|
43
|
-
...llm,
|
|
44
|
-
response_format: responseFormat,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const buildPrompt = (list, instructions, categories) => {
|
|
50
|
-
const instructionsBlock = wrapVariable(instructions, { tag: 'instructions' });
|
|
51
|
-
const listBlock = wrapVariable(list.join('\n'), { tag: 'list' });
|
|
52
|
-
const categoryBlock =
|
|
53
|
-
categories && categories.length
|
|
54
|
-
? `${wrapVariable(categories.join('\n'), { tag: 'categories' })}\n`
|
|
55
|
-
: '';
|
|
56
|
-
const categoryText = categories && categories.length ? 'one of the <categories>' : 'a group';
|
|
57
|
-
|
|
58
|
-
return `Assign each line in <list> to ${categoryText} according to <instructions>.
|
|
59
|
-
|
|
60
|
-
Return a JSON object with a "labels" array containing exactly ${list.length} group names, one for each item in the same order as the input list.
|
|
61
|
-
|
|
62
|
-
${instructionsBlock}
|
|
63
|
-
${categoryBlock}${listBlock}
|
|
64
|
-
|
|
65
|
-
Output format: {"labels": [array with exactly ${list.length} group names]}`;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export default async function listGroup(list, instructions, categories, config = {}) {
|
|
69
|
-
const { llm, ...options } = config;
|
|
70
|
-
const modelOptions = await createModelOptions(llm);
|
|
71
|
-
const output = await chatGPT(buildPrompt(list, instructions, categories), {
|
|
72
|
-
modelOptions,
|
|
73
|
-
...options,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// With structured outputs, response should already be parsed and validated
|
|
77
|
-
let parsed;
|
|
78
|
-
if (typeof output === 'string') {
|
|
79
|
-
try {
|
|
80
|
-
parsed = JSON.parse(output);
|
|
81
|
-
} catch {
|
|
82
|
-
// Handle non-JSON responses (e.g., from mocks or fallback cases)
|
|
83
|
-
// Split by newlines and filter out empty lines
|
|
84
|
-
const lines = output
|
|
85
|
-
.split('\n')
|
|
86
|
-
.map((line) => line.trim())
|
|
87
|
-
.filter((line) => line.length > 0);
|
|
88
|
-
parsed = { labels: lines };
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
parsed = output;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Extract labels from the object structure
|
|
95
|
-
const labels = parsed?.labels || parsed;
|
|
96
|
-
|
|
97
|
-
if (!Array.isArray(labels) || labels.length !== list.length) {
|
|
98
|
-
console.warn(`Expected ${list.length} labels, got ${labels?.length || 0}`);
|
|
99
|
-
// Fallback to default labels if parsing fails
|
|
100
|
-
return { other: [...list] };
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Group items by their labels
|
|
104
|
-
const result = {};
|
|
105
|
-
labels.forEach((label, idx) => {
|
|
106
|
-
const key = String(label).trim() || 'other';
|
|
107
|
-
if (!result[key]) result[key] = [];
|
|
108
|
-
result[key].push(list[idx]);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
return result;
|
|
112
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import listGroup from './index.js';
|
|
2
|
-
import { vi, describe, it, expect } from 'vitest';
|
|
3
|
-
|
|
4
|
-
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
5
|
-
default: vi.fn(() => 'odd\neven\nodd'),
|
|
6
|
-
}));
|
|
7
|
-
|
|
8
|
-
const examples = [
|
|
9
|
-
{
|
|
10
|
-
inputs: {
|
|
11
|
-
list: ['a', 'bb', 'ccc'],
|
|
12
|
-
instructions: 'odd or even length',
|
|
13
|
-
categories: ['odd', 'even'],
|
|
14
|
-
},
|
|
15
|
-
want: { result: { odd: ['a', 'ccc'], even: ['bb'] } },
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
describe('list-group verblet', () => {
|
|
20
|
-
it('groups items using instructions', async () => {
|
|
21
|
-
const result = await listGroup(['a', 'bb', 'ccc'], 'odd or even length', ['odd', 'even']);
|
|
22
|
-
expect(result).toStrictEqual({ odd: ['a', 'ccc'], even: ['bb'] });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
examples.forEach((example) => {
|
|
26
|
-
it(example.inputs.instructions, async () => {
|
|
27
|
-
const result = await listGroup(
|
|
28
|
-
example.inputs.list,
|
|
29
|
-
example.inputs.instructions,
|
|
30
|
-
example.inputs.categories
|
|
31
|
-
);
|
|
32
|
-
expect(result).toStrictEqual(example.want.result);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"type": "object",
|
|
4
|
-
"properties": {
|
|
5
|
-
"labels": {
|
|
6
|
-
"type": "array",
|
|
7
|
-
"description": "Array of group labels corresponding to input items in the same order",
|
|
8
|
-
"items": {
|
|
9
|
-
"type": "string",
|
|
10
|
-
"description": "Group label for the corresponding item"
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"required": ["labels"],
|
|
15
|
-
"additionalProperties": false
|
|
16
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# list-map
|
|
2
|
-
|
|
3
|
-
Transform a list with a single ChatGPT call by providing mapping instructions.
|
|
4
|
-
The function hides the boilerplate prompting so you only supply the instructions.
|
|
5
|
-
|
|
6
|
-
```javascript
|
|
7
|
-
import { listMap } from '../../index.js';
|
|
8
|
-
|
|
9
|
-
await listMap(['Budget smartphone', 'Luxury watch'], 'Write a short playful tagline');
|
|
10
|
-
// => ['Affordable tech for everyone', 'Elegance that tells time']
|
|
11
|
-
```
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import listMap from './index.js';
|
|
3
|
-
import { longTestTimeout } from '../../constants/common.js';
|
|
4
|
-
|
|
5
|
-
describe('list-map examples', () => {
|
|
6
|
-
it(
|
|
7
|
-
'maps creative slogans',
|
|
8
|
-
async () => {
|
|
9
|
-
const items = ['smart toaster', 'robot vacuum'];
|
|
10
|
-
const result = await listMap(items, 'Give a playful marketing slogan');
|
|
11
|
-
expect(result.length).toBe(2);
|
|
12
|
-
},
|
|
13
|
-
longTestTimeout
|
|
14
|
-
);
|
|
15
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import chatGPT from '../../lib/chatgpt/index.js';
|
|
2
|
-
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
3
|
-
|
|
4
|
-
const buildPrompt = function (list, instructions) {
|
|
5
|
-
const instructionsBlock = wrapVariable(instructions, { tag: 'instructions' });
|
|
6
|
-
const listBlock = wrapVariable(list.join('\n'), { tag: 'list' });
|
|
7
|
-
return `For each line in <list>, apply the <instructions> to transform it.\nReturn the same number of lines without numbering.\n\n${instructionsBlock}\n${listBlock}`;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default async function listMap(list, instructions, config = {}) {
|
|
11
|
-
const { llm, ...options } = config;
|
|
12
|
-
const output = await chatGPT(buildPrompt(list, instructions), {
|
|
13
|
-
modelOptions: { ...llm },
|
|
14
|
-
...options,
|
|
15
|
-
});
|
|
16
|
-
const lines = output
|
|
17
|
-
.split('\n')
|
|
18
|
-
.map((line) => line.trim())
|
|
19
|
-
.filter((line) => line.length > 0);
|
|
20
|
-
if (lines.length !== list.length) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
`Batch output line count mismatch (expected ${list.length}, got ${lines.length})`
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
return lines;
|
|
26
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import listMap from './index.js';
|
|
3
|
-
|
|
4
|
-
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
5
|
-
default: vi.fn(async (prompt) => {
|
|
6
|
-
const match = prompt.match(/<list>\n([\s\S]*?)\n<\/list>/);
|
|
7
|
-
const lines = match ? match[1].split('\n') : [];
|
|
8
|
-
return lines.map((l) => l.toUpperCase()).join('\n');
|
|
9
|
-
}),
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
describe('list-map verblet', () => {
|
|
13
|
-
it('maps items using instructions', async () => {
|
|
14
|
-
const result = await listMap(['alpha', 'beta'], 'uppercase');
|
|
15
|
-
expect(result).toStrictEqual(['ALPHA', 'BETA']);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# list-reduce
|
|
2
|
-
|
|
3
|
-
Combine an accumulator value with a list of strings using custom instructions in a single ChatGPT call. Returns the final accumulator.
|
|
4
|
-
|
|
5
|
-
```javascript
|
|
6
|
-
import listReduce from './index.js';
|
|
7
|
-
|
|
8
|
-
await listReduce('', ['alpha', 'beta', 'gamma'], 'Concatenate them');
|
|
9
|
-
// => 'alpha beta gamma'
|
|
10
|
-
```
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import listReduce from './index.js';
|
|
3
|
-
import { longTestTimeout } from '../../constants/common.js';
|
|
4
|
-
|
|
5
|
-
describe('list-reduce examples', () => {
|
|
6
|
-
it(
|
|
7
|
-
'combines items with custom instructions',
|
|
8
|
-
async () => {
|
|
9
|
-
const result = await listReduce('', ['red', 'green', 'blue'], 'join with commas');
|
|
10
|
-
expect(result.length).toBeGreaterThan(0);
|
|
11
|
-
},
|
|
12
|
-
longTestTimeout
|
|
13
|
-
);
|
|
14
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import chatGPT from '../../lib/chatgpt/index.js';
|
|
2
|
-
import wrapVariable from '../../prompts/wrap-variable.js';
|
|
3
|
-
|
|
4
|
-
function buildPrompt(acc, list, instructions) {
|
|
5
|
-
const instructionsBlock = wrapVariable(instructions, {
|
|
6
|
-
tag: 'instructions',
|
|
7
|
-
forceHTML: true,
|
|
8
|
-
});
|
|
9
|
-
const accBlock = wrapVariable(acc, { tag: 'accumulator', forceHTML: true });
|
|
10
|
-
const listBlock = wrapVariable(list.join('\n'), { tag: 'list' });
|
|
11
|
-
return `Start with the given accumulator. Apply the <instructions> to each item in <list> sequentially, using the result as the new accumulator each time. Return only the final accumulator.\n\n${instructionsBlock}\n${accBlock}\n${listBlock}`;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default async function listReduce(acc, list, instructions, config = {}) {
|
|
15
|
-
const { llm, ...options } = config;
|
|
16
|
-
const output = await chatGPT(buildPrompt(acc, list, instructions), {
|
|
17
|
-
modelOptions: { ...llm },
|
|
18
|
-
...options,
|
|
19
|
-
});
|
|
20
|
-
return output.trim();
|
|
21
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import listReduce from './index.js';
|
|
3
|
-
|
|
4
|
-
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
5
|
-
default: vi.fn((prompt) => {
|
|
6
|
-
const listMatch = prompt.match(/<list>\n([\s\S]*?)\n<\/list>/);
|
|
7
|
-
const accMatch = prompt.match(/<accumulator>\n([\s\S]*?)\n<\/accumulator>/);
|
|
8
|
-
let lines = [];
|
|
9
|
-
|
|
10
|
-
if (listMatch && accMatch) {
|
|
11
|
-
lines = listMatch[1]
|
|
12
|
-
.split('\n')
|
|
13
|
-
.map((line) => line.trim())
|
|
14
|
-
.filter(Boolean);
|
|
15
|
-
return lines.join('+');
|
|
16
|
-
}
|
|
17
|
-
// Return just the joined list items
|
|
18
|
-
return lines.join('+');
|
|
19
|
-
}),
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
describe('list-reduce verblet', () => {
|
|
23
|
-
it('reduces items using instructions', async () => {
|
|
24
|
-
const result = await listReduce('0', ['a', 'b', 'c'], 'join');
|
|
25
|
-
expect(result).toBe('a+b+c');
|
|
26
|
-
});
|
|
27
|
-
});
|