ai-functions 0.2.11 → 0.2.13
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/db/mongo.ts +3 -3
- package/dist/cjs/db/cache.d.ts +1 -0
- package/dist/cjs/db/cache.js +12 -0
- package/dist/cjs/db/mongo.d.ts +31 -0
- package/dist/cjs/db/mongo.js +47 -0
- package/dist/cjs/examples/data.d.ts +1105 -0
- package/dist/cjs/examples/data.js +1108 -0
- package/dist/cjs/functions/ai.d.ts +18 -0
- package/dist/cjs/functions/ai.js +99 -0
- package/dist/cjs/functions/ai.test.d.ts +1 -0
- package/dist/cjs/functions/ai.test.js +40 -0
- package/dist/cjs/functions/gpt.d.ts +4 -0
- package/dist/cjs/functions/gpt.js +24 -0
- package/dist/cjs/functions/list.d.ts +7 -0
- package/dist/cjs/functions/list.js +134 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/queue/kafka.d.ts +0 -0
- package/dist/cjs/queue/kafka.js +1 -0
- package/dist/cjs/queue/memory.d.ts +0 -0
- package/dist/cjs/queue/memory.js +1 -0
- package/dist/cjs/queue/mongo.d.ts +30 -0
- package/dist/cjs/queue/mongo.js +69 -0
- package/dist/cjs/streams/kafka.d.ts +0 -0
- package/dist/cjs/streams/kafka.js +1 -0
- package/dist/cjs/streams/memory.d.ts +0 -0
- package/dist/cjs/streams/memory.js +1 -0
- package/dist/cjs/streams/mongo.d.ts +0 -0
- package/dist/cjs/streams/mongo.js +1 -0
- package/dist/cjs/streams/types.d.ts +0 -0
- package/dist/cjs/streams/types.js +1 -0
- package/dist/cjs/types.d.ts +11 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils/completion.d.ts +9 -0
- package/dist/cjs/utils/completion.js +45 -0
- package/dist/cjs/utils/schema.d.ts +10 -0
- package/dist/cjs/utils/schema.js +64 -0
- package/dist/cjs/utils/schema.test.d.ts +1 -0
- package/dist/cjs/utils/schema.test.js +62 -0
- package/dist/cjs/utils/state.d.ts +1 -0
- package/dist/cjs/utils/state.js +21 -0
- package/dist/mjs/db/cache.d.ts +1 -0
- package/dist/mjs/db/cache.js +5 -0
- package/dist/mjs/db/mongo.d.ts +31 -0
- package/dist/mjs/db/mongo.js +48 -0
- package/dist/mjs/examples/data.d.ts +1105 -0
- package/dist/mjs/examples/data.js +1105 -0
- package/dist/mjs/functions/ai.d.ts +18 -0
- package/dist/mjs/functions/ai.js +79 -0
- package/dist/mjs/functions/ai.test.d.ts +1 -0
- package/dist/mjs/functions/ai.test.js +29 -0
- package/dist/mjs/functions/gpt.d.ts +4 -0
- package/dist/mjs/functions/gpt.js +10 -0
- package/dist/mjs/functions/list.d.ts +7 -0
- package/dist/mjs/functions/list.js +72 -0
- package/dist/mjs/index.d.ts +3 -0
- package/dist/mjs/index.js +3 -0
- package/dist/mjs/package.json +3 -0
- package/dist/mjs/queue/kafka.d.ts +0 -0
- package/dist/mjs/queue/kafka.js +1 -0
- package/dist/mjs/queue/memory.d.ts +0 -0
- package/dist/mjs/queue/memory.js +1 -0
- package/dist/mjs/queue/mongo.d.ts +30 -0
- package/dist/mjs/queue/mongo.js +42 -0
- package/dist/mjs/streams/kafka.d.ts +0 -0
- package/dist/mjs/streams/kafka.js +1 -0
- package/dist/mjs/streams/memory.d.ts +0 -0
- package/dist/mjs/streams/memory.js +1 -0
- package/dist/mjs/streams/mongo.d.ts +0 -0
- package/dist/mjs/streams/mongo.js +1 -0
- package/dist/mjs/streams/types.d.ts +0 -0
- package/dist/mjs/streams/types.js +1 -0
- package/dist/mjs/types.d.ts +11 -0
- package/dist/mjs/types.js +1 -0
- package/dist/mjs/utils/completion.d.ts +9 -0
- package/dist/mjs/utils/completion.js +20 -0
- package/dist/mjs/utils/schema.d.ts +10 -0
- package/dist/mjs/utils/schema.js +59 -0
- package/dist/mjs/utils/schema.test.d.ts +1 -0
- package/dist/mjs/utils/schema.test.js +60 -0
- package/dist/mjs/utils/state.d.ts +1 -0
- package/dist/mjs/utils/state.js +19 -0
- package/fixup +11 -0
- package/functions/list.ts +1 -1
- package/package.json +10 -3
- package/tsconfig-backup.json +105 -0
- package/tsconfig-base.json +26 -0
- package/tsconfig-cjs.json +8 -0
- package/tsconfig.json +5 -102
- package/types.ts +1 -1
- package/utils/completion.ts +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ClientOptions, OpenAI } from 'openai';
|
|
2
|
+
import { ChatCompletionCreateParamsBase } from 'openai/resources/chat/completions';
|
|
3
|
+
export type AIConfig = ClientOptions & {
|
|
4
|
+
openai?: OpenAI;
|
|
5
|
+
system?: string;
|
|
6
|
+
model?: ChatCompletionCreateParamsBase['model'];
|
|
7
|
+
};
|
|
8
|
+
export type FunctionCallOptions = Omit<ChatCompletionCreateParamsBase, 'messages' | 'stream'> & {
|
|
9
|
+
system?: string;
|
|
10
|
+
meta?: boolean;
|
|
11
|
+
description?: string;
|
|
12
|
+
};
|
|
13
|
+
type AIFunctions<T = Record<string, string>> = Record<string, (returnSchema: T, options?: Partial<FunctionCallOptions>) => (args: string | object, callOptions?: Partial<FunctionCallOptions>) => Promise<T>>;
|
|
14
|
+
export declare const AI: (config?: AIConfig) => {
|
|
15
|
+
ai: AIFunctions<Record<string, string>>;
|
|
16
|
+
openai: OpenAI;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.AI = void 0;
|
|
24
|
+
const openai_1 = require("openai");
|
|
25
|
+
// import { AIDB, AIDBConfig } from '../db/mongo'
|
|
26
|
+
const js_yaml_1 = require("js-yaml");
|
|
27
|
+
const schema_1 = require("../utils/schema");
|
|
28
|
+
const AI = (config = {}) => {
|
|
29
|
+
var _a;
|
|
30
|
+
const { model = 'gpt-4-1106-preview', system } = config, rest = __rest(config, ["model", "system"]);
|
|
31
|
+
const openai = (_a = config.openai) !== null && _a !== void 0 ? _a : new openai_1.OpenAI(rest);
|
|
32
|
+
// const { client, db, cache, events, queue } = config.db ? AIDB(config.db) : {}
|
|
33
|
+
// const prompt = {
|
|
34
|
+
// model,
|
|
35
|
+
// messages: [{ role: 'user', content: user }],
|
|
36
|
+
// }
|
|
37
|
+
// if (system) prompt.messages.unshift({ role: 'system', content: system })
|
|
38
|
+
// const messages = system ? [{ role: 'system', content: system }] : []
|
|
39
|
+
// const completion = openai.chat.completions.create({
|
|
40
|
+
// model,
|
|
41
|
+
// messages: [{ role: 'user', content: 'hello' }],
|
|
42
|
+
// })
|
|
43
|
+
const ai = new Proxy({}, {
|
|
44
|
+
get: (target, functionName, receiver) => {
|
|
45
|
+
target[functionName] = (returnSchema, options) => (args, callOptions) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
+
var _a;
|
|
47
|
+
console.log((0, schema_1.generateSchema)(returnSchema));
|
|
48
|
+
const _b = Object.assign(Object.assign({}, options), callOptions), { system, description, model = 'gpt-3.5-turbo', meta = false } = _b, rest = __rest(_b, ["system", "description", "model", "meta"]);
|
|
49
|
+
const prompt = Object.assign({ model, messages: [
|
|
50
|
+
{
|
|
51
|
+
role: 'user',
|
|
52
|
+
content: `Call ${functionName} given the context:\n${(0, js_yaml_1.dump)(args)}`,
|
|
53
|
+
}, // \nThere is no additional information, so make assumptions/guesses as necessary` },
|
|
54
|
+
], tools: [
|
|
55
|
+
{
|
|
56
|
+
type: 'function',
|
|
57
|
+
function: {
|
|
58
|
+
name: functionName,
|
|
59
|
+
description,
|
|
60
|
+
parameters: (0, schema_1.generateSchema)(returnSchema),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
], tool_choice: {
|
|
64
|
+
type: 'function',
|
|
65
|
+
function: { name: functionName }
|
|
66
|
+
} }, rest);
|
|
67
|
+
if (system)
|
|
68
|
+
prompt.messages.unshift({ role: 'system', content: system });
|
|
69
|
+
const completion = yield openai.chat.completions.create(prompt);
|
|
70
|
+
const schema = (0, schema_1.generateSchema)(returnSchema);
|
|
71
|
+
let data;
|
|
72
|
+
let error;
|
|
73
|
+
const { message } = (_a = completion.choices) === null || _a === void 0 ? void 0 : _a[0];
|
|
74
|
+
console.log({ message });
|
|
75
|
+
prompt.messages.push(message);
|
|
76
|
+
const { content, tool_calls } = message;
|
|
77
|
+
if (tool_calls) {
|
|
78
|
+
try {
|
|
79
|
+
data = JSON.parse(tool_calls[0].function.arguments);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
error = err.message;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const gpt4 = model.includes('gpt-4');
|
|
86
|
+
const cost = completion.usage ?
|
|
87
|
+
Math.round((gpt4
|
|
88
|
+
? completion.usage.prompt_tokens * 0.003 + completion.usage.completion_tokens * 0.006
|
|
89
|
+
: completion.usage.prompt_tokens * 0.00015 + completion.usage.completion_tokens * 0.0002) * 100000) / 100000 : undefined;
|
|
90
|
+
// completion.usage = camelcaseKeys(completion.usage)
|
|
91
|
+
console.log({ data, content, error, cost, usage: completion.usage });
|
|
92
|
+
return meta ? Object.assign({ prompt, content, data, error, cost }, completion) : data !== null && data !== void 0 ? data : content;
|
|
93
|
+
});
|
|
94
|
+
return target[functionName];
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
return { ai, openai }; //, client, db, cache, events, queue }
|
|
98
|
+
};
|
|
99
|
+
exports.AI = AI;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const vitest_1 = require("vitest");
|
|
13
|
+
const ai_1 = require("./ai");
|
|
14
|
+
(0, vitest_1.describe)('AI Functions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
const { ai } = (0, ai_1.AI)();
|
|
16
|
+
(0, vitest_1.it)('should be initialized', () => {
|
|
17
|
+
(0, vitest_1.expect)(ai).toBeDefined();
|
|
18
|
+
});
|
|
19
|
+
const categorizeWord = ai.categorizeWord({
|
|
20
|
+
type: 'Noun | Verb | Adjective | Adverb | Pronoun | Preposition | Conjunction | Interjection | Other',
|
|
21
|
+
example: 'use the word in a sentence',
|
|
22
|
+
// partOfSpeech: 'Part of speech'
|
|
23
|
+
}, { seed: 1, model: 'gpt-3.5-turbo' });
|
|
24
|
+
(0, vitest_1.it)('should be a function', () => {
|
|
25
|
+
(0, vitest_1.expect)(typeof categorizeWord).toBe('function');
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.it)('Destroy should be a verb', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
(0, vitest_1.expect)(yield categorizeWord('destroy')).toMatchObject({ type: 'Verb', example: 'I will destroy the old building.' });
|
|
29
|
+
}));
|
|
30
|
+
(0, vitest_1.it)('Dog should be a Noun', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
const dog = yield categorizeWord({ word: 'dog' });
|
|
32
|
+
(0, vitest_1.expect)(dog).toMatchObject({ type: 'Noun', example: 'I have a dog.' });
|
|
33
|
+
}));
|
|
34
|
+
(0, vitest_1.it)('Large should be an Adjective', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
(0, vitest_1.expect)(yield categorizeWord({ word: 'large' })).toMatchObject({ type: 'Adjective', example: 'She has a large collection of books.' });
|
|
36
|
+
}));
|
|
37
|
+
(0, vitest_1.it)('To should be an Preposition', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
(0, vitest_1.expect)(yield categorizeWord('to')).toMatchObject({ type: 'Preposition', example: "I'm going to the park." });
|
|
39
|
+
}));
|
|
40
|
+
}));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.GPT = void 0;
|
|
13
|
+
const completion_1 = require("../utils/completion");
|
|
14
|
+
const GPT = (config) => {
|
|
15
|
+
const gpt = (strings, ...values) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
var _a;
|
|
17
|
+
const user = values.map((value, i) => strings[i] + value).join('') + strings[strings.length - 1];
|
|
18
|
+
const completion = yield (0, completion_1.chatCompletion)(Object.assign({ user }, config));
|
|
19
|
+
const content = (_a = completion.choices) === null || _a === void 0 ? void 0 : _a[0].message.content;
|
|
20
|
+
return content;
|
|
21
|
+
});
|
|
22
|
+
return { gpt };
|
|
23
|
+
};
|
|
24
|
+
exports.GPT = GPT;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GPTConfig } from '../types';
|
|
2
|
+
export declare const List: (config: GPTConfig) => {
|
|
3
|
+
list: (strings: string[], ...values: string[]) => Promise<string[]>;
|
|
4
|
+
};
|
|
5
|
+
export declare const StreamingList: (config: GPTConfig) => {
|
|
6
|
+
list: (strings: string[], ...values: string[]) => AsyncGenerator<string | undefined, void, unknown>;
|
|
7
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
22
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
23
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
24
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
25
|
+
var m = o[Symbol.asyncIterator], i;
|
|
26
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
27
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
28
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
29
|
+
};
|
|
30
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
31
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
32
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
33
|
+
return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
34
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
35
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
36
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
37
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
38
|
+
function fulfill(value) { resume("next", value); }
|
|
39
|
+
function reject(value) { resume("throw", value); }
|
|
40
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.StreamingList = exports.List = void 0;
|
|
44
|
+
const openai_1 = require("openai");
|
|
45
|
+
const completion_1 = require("../utils/completion");
|
|
46
|
+
const List = (config) => {
|
|
47
|
+
const list = (strings, ...values) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
var _a;
|
|
49
|
+
const user = values.map((value, i) => strings[i] + value).join('') + strings[strings.length - 1];
|
|
50
|
+
const completion = yield (0, completion_1.chatCompletion)(Object.assign({ user }, config));
|
|
51
|
+
const content = (_a = completion.choices) === null || _a === void 0 ? void 0 : _a[0].message.content;
|
|
52
|
+
return content ? parseList(content) : [];
|
|
53
|
+
});
|
|
54
|
+
return { list };
|
|
55
|
+
};
|
|
56
|
+
exports.List = List;
|
|
57
|
+
function parseList(listStr) {
|
|
58
|
+
// Define a regex pattern to match lines with '1. value', '1) value', '- value', or ' - value'
|
|
59
|
+
const listItemRegex = /^\s*\d+\.\s*(.+)|^\s*\d+\)\s*(.+)|^\s*-\s*(.+)$/gm;
|
|
60
|
+
let match;
|
|
61
|
+
const result = [];
|
|
62
|
+
// Loop over the list string, finding matches with the regex pattern
|
|
63
|
+
while ((match = listItemRegex.exec(listStr)) !== null) {
|
|
64
|
+
// The actual value is in one of the capturing groups (1, 2 or 3)
|
|
65
|
+
const value = match[1] || match[2] || match[3];
|
|
66
|
+
if (value) {
|
|
67
|
+
result.push(value.trim());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
const StreamingList = (config) => {
|
|
73
|
+
function list(strings, ...values) {
|
|
74
|
+
var _a, _b, _c;
|
|
75
|
+
return __asyncGenerator(this, arguments, function* list_1() {
|
|
76
|
+
var _d, e_1, _e, _f;
|
|
77
|
+
const user = values.map((value, i) => strings[i] + value).join('') + strings[strings.length - 1];
|
|
78
|
+
const { system, model, db, queue } = config, rest = __rest(config, ["system", "model", "db", "queue"]);
|
|
79
|
+
const openai = (_a = config.openai) !== null && _a !== void 0 ? _a : new openai_1.OpenAI(rest);
|
|
80
|
+
const prompt = {
|
|
81
|
+
model,
|
|
82
|
+
messages: [{ role: 'user', content: user }],
|
|
83
|
+
stream: true,
|
|
84
|
+
};
|
|
85
|
+
if (system)
|
|
86
|
+
prompt.messages.unshift({ role: 'system', content: system });
|
|
87
|
+
const completion = yield __await(openai.chat.completions.create(prompt));
|
|
88
|
+
const stream = yield __await(openai.chat.completions.create(prompt));
|
|
89
|
+
let content = '';
|
|
90
|
+
let seperator;
|
|
91
|
+
let numberedList;
|
|
92
|
+
try {
|
|
93
|
+
for (var _g = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = yield __await(stream_1.next()), _d = stream_1_1.done, !_d; _g = true) {
|
|
94
|
+
_f = stream_1_1.value;
|
|
95
|
+
_g = false;
|
|
96
|
+
const part = _f;
|
|
97
|
+
const { delta, finish_reason } = part.choices[0];
|
|
98
|
+
content += (delta === null || delta === void 0 ? void 0 : delta.content) || '';
|
|
99
|
+
if (seperator === undefined && content.length > 4) {
|
|
100
|
+
numberedList = content.match(/(\d+\.\s)/g);
|
|
101
|
+
seperator = numberedList ? '\n' : ', ';
|
|
102
|
+
}
|
|
103
|
+
const numberedRegex = /\d+\.\s(?:")?([^"]+)(?:")?/;
|
|
104
|
+
if (seperator && content.includes(seperator)) {
|
|
105
|
+
// get the string before the newline, and modify `content` to be the string after the newline
|
|
106
|
+
// then yield the string before the newline
|
|
107
|
+
const items = content.split(seperator);
|
|
108
|
+
while (items.length > 1) {
|
|
109
|
+
const item = items.shift();
|
|
110
|
+
yield yield __await(numberedList ? (_b = item === null || item === void 0 ? void 0 : item.match(numberedRegex)) === null || _b === void 0 ? void 0 : _b[1] : item);
|
|
111
|
+
}
|
|
112
|
+
content = items[0];
|
|
113
|
+
}
|
|
114
|
+
if (finish_reason) {
|
|
115
|
+
// TODO: Figure out DB saving strategy for streaming
|
|
116
|
+
// if (db) {
|
|
117
|
+
// db.log(prompt, completion as ChatCompletion)
|
|
118
|
+
// }
|
|
119
|
+
yield yield __await(numberedList ? (_c = content.match(numberedRegex)) === null || _c === void 0 ? void 0 : _c[1] : content);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
124
|
+
finally {
|
|
125
|
+
try {
|
|
126
|
+
if (!_g && !_d && (_e = stream_1.return)) yield __await(_e.call(stream_1));
|
|
127
|
+
}
|
|
128
|
+
finally { if (e_1) throw e_1.error; }
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return { list };
|
|
133
|
+
};
|
|
134
|
+
exports.StreamingList = StreamingList;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./functions/ai"), exports);
|
|
18
|
+
__exportStar(require("./functions/gpt"), exports);
|
|
19
|
+
__exportStar(require("./functions/list"), exports);
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AIDB } from '../db/mongo';
|
|
2
|
+
import { CompletionInput } from '../utils/completion';
|
|
3
|
+
import { BSON, ObjectId } from 'mongodb';
|
|
4
|
+
export type QueueConfig = AIDB & {
|
|
5
|
+
batchSize?: number;
|
|
6
|
+
concurrency?: number;
|
|
7
|
+
lockExpiration?: number;
|
|
8
|
+
};
|
|
9
|
+
export type QueueInputMerge = {
|
|
10
|
+
into: string;
|
|
11
|
+
on?: BSON.Document;
|
|
12
|
+
let?: BSON.Document;
|
|
13
|
+
contentAs?: string;
|
|
14
|
+
itemsAs?: string;
|
|
15
|
+
functionDataAs?: string;
|
|
16
|
+
forEachItem?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type QueueInput = (CompletionInput | ({
|
|
19
|
+
list: string;
|
|
20
|
+
} & Partial<CompletionInput>)) & {
|
|
21
|
+
_id?: ObjectId;
|
|
22
|
+
metadata?: object;
|
|
23
|
+
merge?: string | QueueInputMerge;
|
|
24
|
+
target?: string;
|
|
25
|
+
};
|
|
26
|
+
export type QueueDocument = QueueInput & {
|
|
27
|
+
lockedAt: Date;
|
|
28
|
+
lockedBy: string;
|
|
29
|
+
};
|
|
30
|
+
export declare const startQueue: (config: QueueConfig) => Promise<void>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.startQueue = void 0;
|
|
27
|
+
const p_queue_1 = __importDefault(require("p-queue"));
|
|
28
|
+
const completion_1 = require("../utils/completion");
|
|
29
|
+
let localQueue;
|
|
30
|
+
const startQueue = (config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
const { concurrency = 10, batchSize = 100, lockExpiration = 3600 } = config, db = __rest(config, ["concurrency", "batchSize", "lockExpiration"]);
|
|
32
|
+
const instance = Math.random().toString(36).substring(2, 6);
|
|
33
|
+
const queue = new p_queue_1.default({ concurrency });
|
|
34
|
+
const clearExpiredLocks = () => db.queue.updateMany({ lockedAt: { $lt: new Date(Date.now() - lockExpiration * 1000) } }, { $unset: { lockedAt: '', lockedBy: '' } });
|
|
35
|
+
const lockBatch = () => db.queue.aggregate([
|
|
36
|
+
{ $match: { lockedAt: { $exists: false } } },
|
|
37
|
+
{ $limit: batchSize },
|
|
38
|
+
{ $set: { lockedAt: new Date(), lockedBy: instance } },
|
|
39
|
+
{ $merge: { into: 'queue', on: '_id', whenMatched: 'replace' } }, // TODO: Change the `into` to the name of the `queue` collection
|
|
40
|
+
]).toArray();
|
|
41
|
+
db.queue.watch([
|
|
42
|
+
{ $match: { lockedBy: instance } },
|
|
43
|
+
]).on('change', (change) => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
const _a = change.fullDocument, { _id, metadata, merge, target } = _a, input = __rest(_a, ["_id", "metadata", "merge", "target"]); // TODO: Move input to child object not catchall spread
|
|
45
|
+
const completion = yield queue.add(() => (0, completion_1.chatCompletion)(input));
|
|
46
|
+
if (merge) {
|
|
47
|
+
const coll = typeof merge === 'string' ? merge : merge.into;
|
|
48
|
+
const match = typeof merge === 'string' ? undefined : merge.on;
|
|
49
|
+
// TODO: Add support to make completion optional, and specify field names for content, items, and functionData
|
|
50
|
+
const mergeResult = match
|
|
51
|
+
? yield db.db.collection(coll).updateOne(match, { $set: Object.assign({ completion }, metadata !== null && metadata !== void 0 ? metadata : {}) })
|
|
52
|
+
: yield db.db.collection(coll).insertOne(Object.assign({ completion }, metadata !== null && metadata !== void 0 ? metadata : {}));
|
|
53
|
+
if (mergeResult.acknowledged && (mergeResult.modifiedCount ||
|
|
54
|
+
mergeResult.insertedId)) {
|
|
55
|
+
// TODO: We may want to store the merge result in the Events collection to link the queue input to the merge result
|
|
56
|
+
yield db.queue.deleteOne({ _id });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
queue.on('idle', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
+
yield clearExpiredLocks();
|
|
62
|
+
yield lockBatch();
|
|
63
|
+
}));
|
|
64
|
+
queue.start();
|
|
65
|
+
// TODO: Add Find() and Watch() for Actors collection
|
|
66
|
+
// TODO: For each actor, create a state machine and start it
|
|
67
|
+
// TODO: Figure out how to create new queued jobs from the results of the state machine
|
|
68
|
+
});
|
|
69
|
+
exports.startQueue = startQueue;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OpenAI, ClientOptions } from 'openai';
|
|
2
|
+
import type { ChatCompletionCreateParamsNonStreaming } from 'openai/resources';
|
|
3
|
+
import type { AIDB } from './db/mongo';
|
|
4
|
+
import type PQueue from 'p-queue';
|
|
5
|
+
export type GPTConfig = {
|
|
6
|
+
openai?: OpenAI;
|
|
7
|
+
system?: string;
|
|
8
|
+
model?: ChatCompletionCreateParamsNonStreaming['model'] | 'gpt-4-1106-preview' | 'gpt-3.5-turbo-1106';
|
|
9
|
+
db?: AIDB;
|
|
10
|
+
queue?: PQueue;
|
|
11
|
+
} & ClientOptions;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OpenAI } from 'openai';
|
|
2
|
+
import type { ChatCompletionCreateParamsNonStreaming } from 'openai/resources';
|
|
3
|
+
import { GPTConfig } from '../types';
|
|
4
|
+
export type CompletionInput = GPTConfig & ((({
|
|
5
|
+
user: string;
|
|
6
|
+
} | {
|
|
7
|
+
list: string;
|
|
8
|
+
}) & Partial<ChatCompletionCreateParamsNonStreaming>) | ChatCompletionCreateParamsNonStreaming);
|
|
9
|
+
export declare const chatCompletion: (config: CompletionInput) => Promise<OpenAI.Chat.Completions.ChatCompletion>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.chatCompletion = void 0;
|
|
24
|
+
const openai_1 = require("openai");
|
|
25
|
+
// TODO: add support for list input and parsing
|
|
26
|
+
// TODO: add support for caching w/ seed generation for unit tests
|
|
27
|
+
const chatCompletion = (config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
var _a;
|
|
29
|
+
const { user, system, model, db, queue } = config, rest = __rest(config, ["user", "system", "model", "db", "queue"]);
|
|
30
|
+
const openai = (_a = config.openai) !== null && _a !== void 0 ? _a : new openai_1.OpenAI(rest);
|
|
31
|
+
const prompt = {
|
|
32
|
+
model,
|
|
33
|
+
messages: [{ role: 'user', content: user }],
|
|
34
|
+
};
|
|
35
|
+
if (system)
|
|
36
|
+
prompt.messages.unshift({ role: 'system', content: system });
|
|
37
|
+
const completion = queue
|
|
38
|
+
? yield queue.add(() => openai.chat.completions.create(prompt))
|
|
39
|
+
: yield openai.chat.completions.create(prompt);
|
|
40
|
+
if (db) {
|
|
41
|
+
db.log(prompt, completion);
|
|
42
|
+
}
|
|
43
|
+
return completion;
|
|
44
|
+
});
|
|
45
|
+
exports.chatCompletion = chatCompletion;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { JSONSchema } from 'json-schema-to-ts';
|
|
2
|
+
export declare const parseStringDescription: (description: string) => JSONSchema;
|
|
3
|
+
/**
|
|
4
|
+
* Given a property description object, generate a JSON schema.
|
|
5
|
+
*
|
|
6
|
+
* @param propDescriptions - A record object with keys as property names
|
|
7
|
+
* and values as descriptions or nested property description objects.
|
|
8
|
+
* @returns A JSON schema object based on the provided descriptions.
|
|
9
|
+
*/
|
|
10
|
+
export declare const generateSchema: (propDescriptions: Record<string, string | Record<string, any>>) => JSONSchema;
|