ai-functions 0.2.1 → 0.2.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/functions/ai.test.ts +15 -5
- package/functions/ai.ts +16 -4
- package/package.json +2 -2
- package/utils/schema.ts +4 -4
package/functions/ai.test.ts
CHANGED
|
@@ -13,6 +13,8 @@ describe('AI Functions', async () => {
|
|
|
13
13
|
|
|
14
14
|
const categorizeWord = ai.categorizeWord({
|
|
15
15
|
type: 'Noun | Verb | Adjective | Adverb | Pronoun | Preposition | Conjunction | Interjection | Other',
|
|
16
|
+
example: 'use the word in a sentence',
|
|
17
|
+
// partOfSpeech: 'Part of speech'
|
|
16
18
|
}, { seed: 1, model: 'gpt-3.5-turbo' })
|
|
17
19
|
|
|
18
20
|
it('should be a function', () => {
|
|
@@ -20,12 +22,20 @@ describe('AI Functions', async () => {
|
|
|
20
22
|
expect(typeof categorizeWord).toBe('function')
|
|
21
23
|
})
|
|
22
24
|
|
|
23
|
-
it('should
|
|
24
|
-
expect(await categorizeWord('destroy')).toMatchObject({ type: 'Verb' })
|
|
25
|
+
it('Destroy should be a verb', async () => {
|
|
26
|
+
expect(await categorizeWord('destroy')).toMatchObject({ type: 'Verb', example: 'I will destroy the old building.' })
|
|
25
27
|
})
|
|
26
28
|
|
|
27
|
-
it('should
|
|
28
|
-
|
|
29
|
+
it('Dog should be a Noun', async () => {
|
|
30
|
+
const dog = await categorizeWord({ word: 'dog' })
|
|
31
|
+
expect(dog).toMatchObject({ type: 'Noun', example: 'I have a dog.' })
|
|
29
32
|
})
|
|
30
|
-
|
|
33
|
+
|
|
34
|
+
it('Large should be an Adjective', async () => {
|
|
35
|
+
expect(await categorizeWord({ word: 'large' })).toMatchObject({ type: 'Adjective', example: 'She has a large collection of books.' })
|
|
36
|
+
})
|
|
37
|
+
it('To should be an Preposition', async () => {
|
|
38
|
+
expect(await categorizeWord('to')).toMatchObject({ type: 'Preposition', example: "I'm going to the park." })
|
|
39
|
+
})
|
|
40
|
+
|
|
31
41
|
})
|
package/functions/ai.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ChatCompletion, ChatCompletionCreateParamsBase } from 'openai/resources
|
|
|
3
3
|
import { AIDB, AIDBConfig } from '../db/mongo'
|
|
4
4
|
import { dump } from 'js-yaml'
|
|
5
5
|
import { generateSchema } from '../utils/schema'
|
|
6
|
+
import { FromSchema } from 'json-schema-to-ts'
|
|
6
7
|
|
|
7
8
|
export type AIConfig = ClientOptions & {
|
|
8
9
|
db?: AIDBConfig
|
|
@@ -17,6 +18,16 @@ export type FunctionCallOptions = Omit<ChatCompletionCreateParamsBase, 'messages
|
|
|
17
18
|
description?: string
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
type AIFunctions<T extends Record<string, any> = Record<string,any>> = {
|
|
22
|
+
[K in keyof T]: (
|
|
23
|
+
returnSchema: T[K],
|
|
24
|
+
callOptions?: FunctionCallOptions
|
|
25
|
+
) => (
|
|
26
|
+
args: string | object,
|
|
27
|
+
callOptions?: FunctionCallOptions
|
|
28
|
+
) => Promise<{ [P in keyof T[K]]: T[K][P] }>
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
export const AI = (config: AIConfig = {}) => {
|
|
21
32
|
const { model = 'gpt-4-1106-preview', system, ...rest } = config
|
|
22
33
|
const openai = config.openai ?? new OpenAI(rest)
|
|
@@ -32,8 +43,7 @@ export const AI = (config: AIConfig = {}) => {
|
|
|
32
43
|
// messages: [{ role: 'user', content: 'hello' }],
|
|
33
44
|
// })
|
|
34
45
|
|
|
35
|
-
const ai:
|
|
36
|
-
(args: string | object, callOptions?: FunctionCallOptions) => Promise<any>> = new Proxy(
|
|
46
|
+
const ai: AIFunctions = new Proxy(
|
|
37
47
|
{},
|
|
38
48
|
{
|
|
39
49
|
get: (target, functionName: string, receiver) => {
|
|
@@ -69,7 +79,9 @@ export const AI = (config: AIConfig = {}) => {
|
|
|
69
79
|
}
|
|
70
80
|
if (system) prompt.messages.unshift({ role: 'system', content: system })
|
|
71
81
|
const completion = await openai.chat.completions.create(prompt) as ChatCompletion
|
|
72
|
-
|
|
82
|
+
const schema = generateSchema(returnSchema)
|
|
83
|
+
let data: FromSchema<typeof schema>
|
|
84
|
+
let error
|
|
73
85
|
const { message } = completion.choices?.[0]
|
|
74
86
|
console.log({ message })
|
|
75
87
|
prompt.messages.push(message)
|
|
@@ -89,7 +101,7 @@ export const AI = (config: AIConfig = {}) => {
|
|
|
89
101
|
: completion.usage.prompt_tokens * 0.00015 + completion.usage.completion_tokens * 0.0002) * 100000
|
|
90
102
|
) / 100000 : undefined
|
|
91
103
|
// completion.usage = camelcaseKeys(completion.usage)
|
|
92
|
-
console.log({ data, content, error, cost })
|
|
104
|
+
console.log({ data, content, error, cost, usage: completion.usage })
|
|
93
105
|
return meta ? { prompt, content, data, error, cost, ...completion } : data ?? content
|
|
94
106
|
}
|
|
95
107
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-functions",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Library for Developing and Managing AI Functions (including OpenAI GPT4 / GPT3.5)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"js-yaml": "^4.1.0",
|
|
40
|
-
"json-schema-to-ts": "^
|
|
40
|
+
"json-schema-to-ts": "^3.0.0",
|
|
41
41
|
"kafkajs": "^2.2.4",
|
|
42
42
|
"lodash-es": "^4.17.21",
|
|
43
43
|
"mongodb": "^6.2.0",
|
package/utils/schema.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSONSchema } from 'json-schema-to-ts'
|
|
2
2
|
|
|
3
3
|
// This is a helper function to generate a JSON schema for string properties.
|
|
4
4
|
// It checks if a string includes '|' which would indicate an enum,
|
|
5
5
|
// or if it starts with 'number: ' or 'boolean: ' which would indicate
|
|
6
6
|
// a number or boolean type respectively, otherwise it defaults to string.
|
|
7
|
-
export const parseStringDescription = (description: string):
|
|
7
|
+
export const parseStringDescription = (description: string): JSONSchema => {
|
|
8
8
|
// Check if the description indicates an enum for string type
|
|
9
9
|
if (description.includes('|')) {
|
|
10
10
|
return { type: 'string', enum: description.split('|').map((v) => v.trim()) }
|
|
@@ -37,13 +37,13 @@ export const parseStringDescription = (description: string): JSONSchema7 => {
|
|
|
37
37
|
* and values as descriptions or nested property description objects.
|
|
38
38
|
* @returns A JSON schema object based on the provided descriptions.
|
|
39
39
|
*/
|
|
40
|
-
export const generateSchema = (propDescriptions: Record<string, string | Record<string, any>>):
|
|
40
|
+
export const generateSchema = (propDescriptions: Record<string, string | Record<string, any>>): JSONSchema => {
|
|
41
41
|
// If the propDescriptions is for an object structure
|
|
42
42
|
if (typeof propDescriptions !== 'object' || propDescriptions === null || Array.isArray(propDescriptions)) {
|
|
43
43
|
throw new Error('The propDescriptions parameter should be an object.')
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const properties: Record<string,
|
|
46
|
+
const properties: Record<string, JSONSchema> = {}
|
|
47
47
|
const required: string[] = Object.keys(propDescriptions)
|
|
48
48
|
|
|
49
49
|
for (const [key, description] of Object.entries(propDescriptions)) {
|