Skip to content

Commit 125c528

Browse files
committed
allow calling createChatMessage and summarizeChatThread without authorization
1 parent 73e3d34 commit 125c528

File tree

2 files changed

+124
-7
lines changed

2 files changed

+124
-7
lines changed

src/actions/createChatMessage.js

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ const connect = require('../../src/db');
55

66
const CreateChatMessageParams = new Archetype({
77
authorization: {
8-
$type: 'string',
9-
$required: true
8+
$type: 'string'
9+
},
10+
modelDescriptions: {
11+
$type: 'string'
1012
},
1113
messages: [{
1214
role: {
@@ -18,18 +20,61 @@ const CreateChatMessageParams = new Archetype({
1820
}]
1921
}).compile('CreateChatMessageParams');
2022

23+
const systemPrompt = `
24+
You are a data querying assistant who writes scripts for users accessing MongoDB data using Node.js and Mongoose.
25+
26+
Keep scripts concise. Avoid unnecessary comments, error handling, and temporary variables.
27+
28+
Do not write any imports or require() statements, that will cause the script to break.
29+
30+
If the user approves the script, the script will run in the Node.js server and then send the response via JSON to the client. Be aware that the result of the query will be serialized to JSON before being displayed to the user.
31+
32+
Assume the user has pre-defined schemas and models. Do not define any new schemas or models for the user.
33+
34+
Use async/await where possible. Assume top-level await is allowed.
35+
36+
Write at most one script, unless the user explicitly asks for multiple scripts.
37+
38+
Think carefully about the user's input and identify the models referred to by the user's query.
39+
40+
Format output as Markdown, including code fences for any scripts the user requested.
41+
42+
Add a brief text description of what the script does.
43+
44+
If the user's query is best answered with a chart, return a Chart.js 4 configuration as \`return { $chart: chartJSConfig };\`. Disable ChartJS animation by default unless user asks for it. Set responsive: true, maintainAspectRatio: false options unless the user explicitly asks.
45+
46+
Example output:
47+
48+
The following script counts the number of users which are not deleted.
49+
50+
\`\`\`javascript
51+
const users = await db.model('User').find({ isDeleted: false });
52+
return { numUsers: users.length };
53+
\`\`\`
54+
55+
-----------
56+
57+
Here is a description of the user's models. Assume these are the only models available in the system unless explicitly instructed otherwise by the user.
58+
`.trim();
59+
2160
module.exports = async function createChatMessage(params) {
22-
const { authorization, messages } = new CreateChatMessageParams(params);
61+
const { authorization, modelDescriptions, messages } = new CreateChatMessageParams(params);
2362

2463
const db = await connect();
2564
const { AccessToken, RateLimit } = db.models;
2665

27-
await RateLimit.checkRateLimit('openai', 1000);
66+
let userId = null;
67+
if (authorization) {
68+
const accessToken = await AccessToken.findById(authorization).orFail(new Error('Invalid access token'));
69+
userId = accessToken.userId;
70+
}
2871

29-
// Find the user linked to the access token
30-
const accessToken = await AccessToken.findById(authorization).orFail(new Error('Invalid access token'));
31-
const userId = accessToken.userId;
72+
await RateLimit.checkRateLimit('openai', 1000);
3273

74+
messages.unshift({
75+
role: 'system',
76+
content: systemPrompt + (modelDescriptions ?? '')
77+
});
3378
const res = await getChatCompletion(messages);
3479

3580
return {
@@ -53,5 +98,9 @@ async function getChatCompletion(messages, options = {}) {
5398
})
5499
});
55100

101+
if (!response.ok) {
102+
throw new Error(`OpenAI API request failed with status ${response.status}: ${await response.text()}`);
103+
}
104+
56105
return await response.json();
57106
}

src/actions/summarizeChatThread.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
'use strict';
2+
3+
const Archetype = require('archetype');
4+
const connect = require('../../src/db');
5+
6+
const SummarizeChatThreadParams = new Archetype({
7+
authorization: {
8+
$type: 'string'
9+
},
10+
messages: [{
11+
role: {
12+
$type: 'string'
13+
},
14+
content: {
15+
$type: 'string'
16+
}
17+
}]
18+
}).compile('SummarizeChatThreadParams');
19+
20+
const systemPrompt = 'Summarize the following chat thread in 6 words or less, as a helpful thread title';
21+
22+
module.exports = async function createChatMessage(params) {
23+
const { authorization, messages } = new SummarizeChatThreadParams(params);
24+
25+
const db = await connect();
26+
const { AccessToken, RateLimit } = db.models;
27+
28+
let userId = null;
29+
if (authorization) {
30+
const accessToken = await AccessToken.findById(authorization).orFail(new Error('Invalid access token'));
31+
userId = accessToken.userId;
32+
}
33+
34+
await RateLimit.checkRateLimit('openai', 1000);
35+
36+
messages.unshift({
37+
role: 'system',
38+
content: systemPrompt
39+
});
40+
const res = await getChatCompletion(messages);
41+
42+
return {
43+
response: res.choices?.[0]?.message?.content,
44+
userId
45+
};
46+
};
47+
48+
async function getChatCompletion(messages, options = {}) {
49+
const response = await fetch('https://api.openai.com/v1/chat/completions', {
50+
method: 'POST',
51+
headers: {
52+
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
53+
'Content-Type': 'application/json'
54+
},
55+
body: JSON.stringify({
56+
model: 'gpt-4o',
57+
max_tokens: 2500,
58+
...options,
59+
messages
60+
})
61+
});
62+
63+
if (!response.ok) {
64+
throw new Error(`OpenAI API request failed with status ${response.status}: ${await response.text()}`);
65+
}
66+
67+
return await response.json();
68+
}

0 commit comments

Comments
 (0)