openai-api-mock 0.1.4 → 0.1.5
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/main.js +22 -10
- package/package.json +3 -2
- package/readme.md +8 -1
- package/src/chat.js +122 -0
- package/src/image.js +26 -0
- package/src/responce.js +0 -102
package/main.js
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
const nock = require('nock');
|
|
2
|
-
const {
|
|
2
|
+
const { getChatResponce } = require('./src/chat.js');
|
|
3
|
+
const { getImageResponce } = require('./src/image.js');
|
|
3
4
|
|
|
4
5
|
function mockOpenAIResponse(force = false) {
|
|
5
|
-
// Define the OpenAI
|
|
6
|
-
const
|
|
7
|
-
|
|
6
|
+
// Define the OpenAI endpoints
|
|
7
|
+
const openaiCompletionEndpoint = 'https://api.openai.com/v1/chat/completions';
|
|
8
|
+
const imageEndpoint = 'https://api.openai.com/v1/images/generations';
|
|
9
|
+
var env = process.env.NODE_ENV || 'development';
|
|
10
|
+
|
|
8
11
|
// Intercept the HTTP call and return the mock response
|
|
9
12
|
if (env === 'development' || force) {
|
|
10
|
-
nock(
|
|
13
|
+
nock(openaiCompletionEndpoint)
|
|
14
|
+
.post('')
|
|
15
|
+
.reply(function (uri, requestBody) {
|
|
16
|
+
return [200, getChatResponce(requestBody)];
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
nock(imageEndpoint)
|
|
11
20
|
.post('')
|
|
12
|
-
.reply(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
.reply(function (uri, requestBody) {
|
|
22
|
+
return [200, getImageResponce(requestBody)];
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Mocking only the chat completion endpoint, not blocking other requests
|
|
26
|
+
nock.emitter.on('no match', function (req) {
|
|
27
|
+
nock.enableNetConnect(req);
|
|
28
|
+
});
|
|
17
29
|
}
|
|
18
30
|
}
|
|
19
31
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openai-api-mock",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A Node.js module for mocking OpenAI API responses in a development environment",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"main": "main.js",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@faker-js/faker": "^8.4.0",
|
|
21
|
-
"nock": "^13.5.1"
|
|
21
|
+
"nock": "^13.5.1",
|
|
22
|
+
"openai": "^4.26.0"
|
|
22
23
|
}
|
|
23
24
|
}
|
package/readme.md
CHANGED
|
@@ -4,6 +4,7 @@ This is a Node.js module for mocking OpenAI API responses in a development envir
|
|
|
4
4
|
It's useful for testing and development purposes when you don't want to make actual API calls.
|
|
5
5
|
The module also supports mocking function_calling
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
## Installation
|
|
8
9
|
|
|
9
10
|
You can install this module using npm as a dev dependency :
|
|
@@ -12,12 +13,12 @@ You can install this module using npm as a dev dependency :
|
|
|
12
13
|
npm install -D openai-api-mock
|
|
13
14
|
```
|
|
14
15
|
|
|
16
|
+
|
|
15
17
|
## Usage
|
|
16
18
|
```js
|
|
17
19
|
const { mockOpenAIResponse } = require('openai-api-mock');
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
|
|
21
22
|
Then, call the mockOpenAIResponse function to set up the mock response:
|
|
22
23
|
|
|
23
24
|
```js
|
|
@@ -31,6 +32,12 @@ mockOpenAIResponse(force = true);
|
|
|
31
32
|
The force parameter is a boolean that determines whether the mock response should be used regardless of the environment.
|
|
32
33
|
If force is true, the mock response will be used regardless of the environment. If force is false or not provided, the mock response will only be used if the <code>NODE_ENV</code> environment variable is set to 'development'.
|
|
33
34
|
|
|
35
|
+
## Intercepted URLs
|
|
36
|
+
|
|
37
|
+
This module uses the `nock` library to intercept HTTP calls to the following OpenAI API endpoints:
|
|
38
|
+
|
|
39
|
+
- `https://api.openai.com/v1/chat/completions`: This endpoint is used for generating chat completions.
|
|
40
|
+
- `https://api.openai.com/v1/images/generations`: This endpoint is used for generating images.
|
|
34
41
|
|
|
35
42
|
|
|
36
43
|
## Dependencies
|
package/src/chat.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const { faker } = require('@faker-js/faker');
|
|
2
|
+
|
|
3
|
+
function getChatResponce(requestBody) {
|
|
4
|
+
const created = Math.floor(Date.now() / 1000);
|
|
5
|
+
|
|
6
|
+
if (!requestBody.functions) {
|
|
7
|
+
return createDefaultResponse(created);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return createFunctionCallingResponse(requestBody, created);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createDefaultResponse(created) {
|
|
14
|
+
return {
|
|
15
|
+
choices: [
|
|
16
|
+
{
|
|
17
|
+
finish_reason: 'stop',
|
|
18
|
+
index: 0,
|
|
19
|
+
message: {
|
|
20
|
+
content: faker.lorem.words(5),
|
|
21
|
+
role: 'assistant',
|
|
22
|
+
},
|
|
23
|
+
logprobs: null,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
created: created,
|
|
27
|
+
id: `chatcmpl-${faker.string.alphanumeric(30)}`,
|
|
28
|
+
model: `gpt-3.5-mock`,
|
|
29
|
+
object: 'chat.completion',
|
|
30
|
+
usage: {
|
|
31
|
+
completion_tokens: 17,
|
|
32
|
+
prompt_tokens: 57,
|
|
33
|
+
total_tokens: 74,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function createFunctionCallingResponse(requestBody, created) {
|
|
39
|
+
const functionCallingResponse = {
|
|
40
|
+
id: `chatcmpl-${faker.string.alphanumeric(30)}`,
|
|
41
|
+
object: 'chat.completion',
|
|
42
|
+
created: created,
|
|
43
|
+
model: 'gpt-3.5-mock',
|
|
44
|
+
choices: [
|
|
45
|
+
{
|
|
46
|
+
index: 0,
|
|
47
|
+
message: {
|
|
48
|
+
role: 'assistant',
|
|
49
|
+
content: null,
|
|
50
|
+
function_call: createFunctionCallObject(requestBody),
|
|
51
|
+
},
|
|
52
|
+
finish_reason: 'function_call',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
usage: {
|
|
56
|
+
prompt_tokens: 81,
|
|
57
|
+
completion_tokens: 19,
|
|
58
|
+
total_tokens: 100,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return functionCallingResponse;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function createFunctionCallObject(requestBody) {
|
|
66
|
+
return {
|
|
67
|
+
name: `${requestBody.functions[0].name}`,
|
|
68
|
+
arguments: `${generateFunctionCallArguments(requestBody)}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function generateFakeData(type, properties) {
|
|
73
|
+
switch (type) {
|
|
74
|
+
case 'string':
|
|
75
|
+
return faker.lorem.words(5);
|
|
76
|
+
case 'number':
|
|
77
|
+
return faker.number.int();
|
|
78
|
+
case 'array':
|
|
79
|
+
return generateFakeArray(properties);
|
|
80
|
+
case 'object':
|
|
81
|
+
return generateFakeObject(properties);
|
|
82
|
+
case 'boolean':
|
|
83
|
+
return faker.datatype.boolean();
|
|
84
|
+
default:
|
|
85
|
+
return faker.lorem.words(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function generateFakeArray(properties) {
|
|
90
|
+
const arrayItemsType = properties.items.type;
|
|
91
|
+
return Array.from({ length: 5 }, () => {
|
|
92
|
+
if (arrayItemsType === 'string') {
|
|
93
|
+
return faker.lorem.words(1);
|
|
94
|
+
} else if (arrayItemsType === 'object') {
|
|
95
|
+
const itemProperties = properties.items.properties;
|
|
96
|
+
return generateFakeData('object', { properties: itemProperties });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function generateFakeObject(properties) {
|
|
102
|
+
const itemObject = {};
|
|
103
|
+
Object.entries(properties.properties).forEach(([itemName, itemDetails]) => {
|
|
104
|
+
itemObject[itemName] = generateFakeData(itemDetails.type, itemDetails);
|
|
105
|
+
});
|
|
106
|
+
return itemObject;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function generateFunctionCallArguments(requestBody) {
|
|
110
|
+
const { parameters } = requestBody.functions[0];
|
|
111
|
+
const argumentsObject = {};
|
|
112
|
+
|
|
113
|
+
Object.entries(parameters.properties).forEach(([paramName, paramDetails]) => {
|
|
114
|
+
argumentsObject[paramName] = generateFakeData(paramDetails.type, paramDetails);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return JSON.stringify(argumentsObject, null, 2);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = {
|
|
121
|
+
getChatResponce,
|
|
122
|
+
};
|
package/src/image.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const { faker } = require('@faker-js/faker');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function getImageResponce(requestBody) {
|
|
5
|
+
|
|
6
|
+
const n = requestBody.n || 1;
|
|
7
|
+
const data = [];
|
|
8
|
+
for (let i = 0; i < n; i++) {
|
|
9
|
+
data.push({
|
|
10
|
+
revised_prompt: faker.lorem.words(5),
|
|
11
|
+
url: "http://via.placeholder.com/" + requestBody.size
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
created: Math.floor(Date.now() / 1000),
|
|
17
|
+
data: data
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
getImageResponce,
|
|
26
|
+
};
|
package/src/responce.js
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
const { faker } = require('@faker-js/faker');
|
|
2
|
-
|
|
3
|
-
function getResponce(requestBody) {
|
|
4
|
-
const created = Math.floor(Date.now() / 1000)
|
|
5
|
-
if (!requestBody.functions) {
|
|
6
|
-
return {
|
|
7
|
-
choices: [
|
|
8
|
-
{
|
|
9
|
-
finish_reason: 'stop',
|
|
10
|
-
index: 0,
|
|
11
|
-
message: {
|
|
12
|
-
content: faker.lorem.words(5),
|
|
13
|
-
role: 'assistant',
|
|
14
|
-
},
|
|
15
|
-
logprobs: null,
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
created: created,
|
|
19
|
-
id: `chatcmpl-${faker.string.alphanumeric(30)}`,
|
|
20
|
-
model: `gpt-3.5-mock`,
|
|
21
|
-
object: 'chat.completion',
|
|
22
|
-
usage: {
|
|
23
|
-
completion_tokens: 17,
|
|
24
|
-
prompt_tokens: 57,
|
|
25
|
-
total_tokens: 74,
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let functionCallingResponse = {
|
|
31
|
-
id: `chatcmpl-${faker.string.alphanumeric(30)}`,
|
|
32
|
-
object: 'chat.completion',
|
|
33
|
-
created: created,
|
|
34
|
-
model: 'gpt-3.5-mock',
|
|
35
|
-
choices: [
|
|
36
|
-
{
|
|
37
|
-
index: 0,
|
|
38
|
-
message: {
|
|
39
|
-
role: 'assistant',
|
|
40
|
-
content: null,
|
|
41
|
-
function_call: {
|
|
42
|
-
name: `${requestBody.functions[0].name}`,
|
|
43
|
-
arguments: `${generateFunctionCallArguments(requestBody)}`,
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
finish_reason: 'function_call'
|
|
47
|
-
}
|
|
48
|
-
],
|
|
49
|
-
usage: {
|
|
50
|
-
prompt_tokens: 81,
|
|
51
|
-
completion_tokens: 19,
|
|
52
|
-
total_tokens: 100
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
return functionCallingResponse;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function generateFakeData(type, properties) {
|
|
59
|
-
if (type === 'string') {
|
|
60
|
-
return faker.lorem.words(5);
|
|
61
|
-
} else if (type === 'number') {
|
|
62
|
-
return faker.number.int();
|
|
63
|
-
} else if (type === 'array') {
|
|
64
|
-
const arrayItemsType = properties.items.type;
|
|
65
|
-
let arrayItems = [];
|
|
66
|
-
if (arrayItemsType === 'string') {
|
|
67
|
-
arrayItems = Array.from({ length: 5 }, () => faker.lorem.words(1));
|
|
68
|
-
} else if (arrayItemsType === 'object') {
|
|
69
|
-
const itemProperties = properties.items.properties;
|
|
70
|
-
arrayItems = Array.from({ length: 5 }, () => generateFakeData('object', { properties: itemProperties }));
|
|
71
|
-
}
|
|
72
|
-
return arrayItems;
|
|
73
|
-
} else if (type === 'object') {
|
|
74
|
-
const itemObject = {};
|
|
75
|
-
Object.entries(properties.properties).forEach(([itemName, itemDetails]) => {
|
|
76
|
-
itemObject[itemName] = generateFakeData(itemDetails.type, itemDetails);
|
|
77
|
-
});
|
|
78
|
-
return itemObject;
|
|
79
|
-
}else if (type === 'boolean') {
|
|
80
|
-
return faker.datatype.boolean();
|
|
81
|
-
}else {
|
|
82
|
-
return faker.lorem.words(1);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/*
|
|
87
|
-
* Generate function call arguments
|
|
88
|
-
*/
|
|
89
|
-
function generateFunctionCallArguments(requestBody) {
|
|
90
|
-
const { parameters } = requestBody.functions[0];
|
|
91
|
-
const argumentsObject = {};
|
|
92
|
-
|
|
93
|
-
Object.entries(parameters.properties).forEach(([paramName, paramDetails]) => {
|
|
94
|
-
argumentsObject[paramName] = generateFakeData(paramDetails.type, paramDetails);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
return JSON.stringify(argumentsObject, null, 2);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
module.exports = {
|
|
101
|
-
getResponce
|
|
102
|
-
}
|