dify/mock-server/api/apps.js
2023-05-15 08:51:32 +08:00

551 lines
14 KiB
JavaScript

const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'
function randomString (length) {
let result = ''
for (let i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]
return result
}
// https://www.notion.so/55773516a0194781ae211792a44a3663?pvs=4
const VirtualData = new Array(10).fill().map((_, index) => {
const date = new Date(Date.now() - index * 24 * 60 * 60 * 1000)
return {
date: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`,
conversation_count: Math.floor(Math.random() * 10) + index,
terminal_count: Math.floor(Math.random() * 10) + index,
token_count: Math.floor(Math.random() * 10) + index,
total_price: Math.floor(Math.random() * 10) + index,
}
})
const registerAPI = function (app) {
const apps = [{
id: '1',
name: 'chat app',
mode: 'chat',
description: 'description01',
enable_site: true,
enable_api: true,
api_rpm: 60,
api_rph: 3600,
is_demo: false,
model_config: {
provider: 'OPENAI',
model_id: 'gpt-3.5-turbo',
configs: {
prompt_template: '你是我的解梦小助手,请参考 {{book}} 回答我有关梦境的问题。在回答前请称呼我为 {{myName}}。',
prompt_variables: [
{
key: 'book',
name: '书',
value: '《梦境解析》',
type: 'string',
description: '请具体说下书名'
},
{
key: 'myName',
name: 'your name',
value: 'Book',
type: 'string',
description: 'please tell me your name'
}
],
completion_params: {
max_token: 16,
temperature: 1, // 0-2
top_p: 1,
presence_penalty: 1, // -2-2
frequency_penalty: 1, // -2-2
}
}
},
site: {
access_token: '1000',
title: 'site 01',
author: 'John',
default_language: 'zh-Hans-CN',
customize_domain: 'http://customize_domain',
theme: 'theme',
customize_token_strategy: 'must',
prompt_public: true
}
},
{
id: '2',
name: 'completion app',
mode: 'completion', // genertation text
description: 'description 02', // genertation text
enable_site: false,
enable_api: false,
api_rpm: 60,
api_rph: 3600,
is_demo: false,
model_config: {
provider: 'OPENAI',
model_id: 'text-davinci-003',
configs: {
prompt_template: '你是我的翻译小助手,请把以下内容 {{langA}} 翻译成 {{langB}},以下的内容:',
prompt_variables: [
{
key: 'langA',
name: '原始语音',
value: '中文',
type: 'string',
description: '这是中文格式的原始语音'
},
{
key: 'langB',
name: '目标语言',
value: '英语',
type: 'string',
description: '这是英语格式的目标语言'
}
],
completion_params: {
max_token: 16,
temperature: 1, // 0-2
top_p: 1,
presence_penalty: 1, // -2-2
frequency_penalty: 1, // -2-2
}
}
},
site: {
access_token: '2000',
title: 'site 02',
author: 'Mark',
default_language: 'en-US',
customize_domain: 'http://customize_domain',
theme: 'theme',
customize_token_strategy: 'must',
prompt_public: false
}
},
]
const apikeys = [{
id: '111121312313132',
token: 'sk-DEFGHJKMNPQRSTWXYZabcdefhijk1234',
last_used_at: '1679212138000',
created_at: '1673316000000'
}, {
id: '43441242131223123',
token: 'sk-EEFGHJKMNPQRSTWXYZabcdefhijk5678',
last_used_at: '1679212721000',
created_at: '1679212731000'
}]
// create app
app.post('/apps', async (req, res) => {
apps.push({
id: apps.length + 1 + '',
...req.body,
})
res.send({
result: 'success'
})
})
// app list
app.get('/apps', async (req, res) => {
res.send({
data: apps
})
})
// app detail
app.get('/apps/:id', async (req, res) => {
const item = apps.find(item => item.id === req.params.id) || apps[0]
res.send(item)
})
// update app name
app.post('/apps/:id/name', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
item.name = req.body.name
res.send(item || null)
})
// update app site-enable status
app.post('/apps/:id/site-enable', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
console.log(item)
item.enable_site = req.body.enable_site
res.send(item || null)
})
// update app api-enable status
app.post('/apps/:id/api-enable', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
console.log(item)
item.enable_api = req.body.enable_api
res.send(item || null)
})
// update app rate-limit
app.post('/apps/:id/rate-limit', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
console.log(item)
item.api_rpm = req.body.api_rpm
item.api_rph = req.body.api_rph
res.send(item || null)
})
// update app url including code
app.post('/apps/:id/site/access-token-reset', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
console.log(item)
item.site.access_token = randomString(12)
res.send(item || null)
})
// update app config
app.post('/apps/:id/site', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
console.log(item)
item.name = req.body.title
item.description = req.body.description
item.prompt_public = req.body.prompt_public
item.default_language = req.body.default_language
res.send(item || null)
})
// get statistics daily-conversations
app.get('/apps/:id/statistics/daily-conversations', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
if (item) {
res.send({
data: VirtualData
})
} else {
res.send({
data: []
})
}
})
// get statistics daily-end-users
app.get('/apps/:id/statistics/daily-end-users', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
if (item) {
res.send({
data: VirtualData
})
} else {
res.send({
data: []
})
}
})
// get statistics token-costs
app.get('/apps/:id/statistics/token-costs', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
if (item) {
res.send({
data: VirtualData
})
} else {
res.send({
data: []
})
}
})
// update app model config
app.post('/apps/:id/model-config', async (req, res) => {
const item = apps.find(item => item.id === req.params.id)
console.log(item)
item.model_config = req.body
res.send(item || null)
})
// get api keys list
app.get('/apps/:id/api-keys', async (req, res) => {
res.send({
data: apikeys
})
})
// del api key
app.delete('/apps/:id/api-keys/:api_key_id', async (req, res) => {
res.send({
result: 'success'
})
})
// create api key
app.post('/apps/:id/api-keys', async (req, res) => {
res.send({
id: 'e2424241313131',
token: 'sk-GEFGHJKMNPQRSTWXYZabcdefhijk0124',
created_at: '1679216688962'
})
})
// get completion-conversations
app.get('/apps/:id/completion-conversations', async (req, res) => {
const data = {
data: [{
id: 1,
from_end_user_id: 'user 1',
summary: 'summary1',
created_at: '2023-10-11',
annotated: true,
message_count: 100,
user_feedback_stats: {
like: 4, dislike: 5
},
admin_feedback_stats: {
like: 1, dislike: 2
},
message: {
message: 'message1',
query: 'question1',
answer: 'answer1'
}
}, {
id: 12,
from_end_user_id: 'user 2',
summary: 'summary2',
created_at: '2023-10-01',
annotated: false,
message_count: 10,
user_feedback_stats: {
like: 2, dislike: 20
},
admin_feedback_stats: {
like: 12, dislike: 21
},
message: {
message: 'message2',
query: 'question2',
answer: 'answer2'
}
}, {
id: 13,
from_end_user_id: 'user 3',
summary: 'summary3',
created_at: '2023-10-11',
annotated: false,
message_count: 20,
user_feedback_stats: {
like: 2, dislike: 0
},
admin_feedback_stats: {
like: 0, dislike: 21
},
message: {
message: 'message3',
query: 'question3',
answer: 'answer3'
}
}],
total: 200
}
res.send(data)
})
// get chat-conversations
app.get('/apps/:id/chat-conversations', async (req, res) => {
const data = {
data: [{
id: 1,
from_end_user_id: 'user 1',
summary: 'summary1',
created_at: '2023-10-11',
read_at: '2023-10-12',
annotated: true,
message_count: 100,
user_feedback_stats: {
like: 4, dislike: 5
},
admin_feedback_stats: {
like: 1, dislike: 2
},
message: {
message: 'message1',
query: 'question1',
answer: 'answer1'
}
}, {
id: 12,
from_end_user_id: 'user 2',
summary: 'summary2',
created_at: '2023-10-01',
annotated: false,
message_count: 10,
user_feedback_stats: {
like: 2, dislike: 20
},
admin_feedback_stats: {
like: 12, dislike: 21
},
message: {
message: 'message2',
query: 'question2',
answer: 'answer2'
}
}, {
id: 13,
from_end_user_id: 'user 3',
summary: 'summary3',
created_at: '2023-10-11',
annotated: false,
message_count: 20,
user_feedback_stats: {
like: 2, dislike: 0
},
admin_feedback_stats: {
like: 0, dislike: 21
},
message: {
message: 'message3',
query: 'question3',
answer: 'answer3'
}
}],
total: 200
}
res.send(data)
})
// get completion-conversation detail
app.get('/apps/:id/completion-conversations/:cid', async (req, res) => {
const data =
{
id: 1,
from_end_user_id: 'user 1',
summary: 'summary1',
created_at: '2023-10-11',
annotated: true,
message: {
message: 'question1',
// query: 'question1',
answer: 'answer1',
annotation: {
content: '这是一段纠正的内容'
}
},
model_config: {
provider: 'openai',
model_id: 'model_id',
configs: {
prompt_template: '你是我的翻译小助手,请把以下内容 {{langA}} 翻译成 {{langB}},以下的内容:{{content}}'
}
}
}
res.send(data)
})
// get chat-conversation detail
app.get('/apps/:id/chat-conversations/:cid', async (req, res) => {
const data =
{
id: 1,
from_end_user_id: 'user 1',
summary: 'summary1',
created_at: '2023-10-11',
annotated: true,
message: {
message: 'question1',
// query: 'question1',
answer: 'answer1',
created_at: '2023-08-09 13:00',
provider_response_latency: 130,
message_tokens: 230
},
model_config: {
provider: 'openai',
model_id: 'model_id',
configs: {
prompt_template: '你是我的翻译小助手,请把以下内容 {{langA}} 翻译成 {{langB}},以下的内容:{{content}}'
}
}
}
res.send(data)
})
// get chat-conversation message list
app.get('/apps/:id/chat-messages', async (req, res) => {
const data = {
data: [{
id: 1,
created_at: '2023-10-11 07:09',
message: '请说说人为什么会做梦?' + req.query.conversation_id,
answer: '梦境通常是个人内心深处的反映,很难确定每个人梦境的确切含义,因为它们可能会受到梦境者的文化背景、生活经验和情感状态等多种因素的影响。',
provider_response_latency: 450,
answer_tokens: 200,
annotation: {
content: 'string',
account: {
id: 'string',
name: 'string',
email: 'string'
}
},
feedbacks: {
rating: 'like',
content: 'string',
from_source: 'log'
}
}, {
id: 2,
created_at: '2023-10-11 8:23',
message: '夜里经常做梦会影响次日的精神状态吗?',
answer: '总之,这个梦境可能与梦境者的个人经历和情感状态有关,但在一般情况下,它可能表示一种强烈的情感反应,包括愤怒、不满和对于正义和自由的渴望。',
provider_response_latency: 400,
answer_tokens: 250,
annotation: {
content: 'string',
account: {
id: 'string',
name: 'string',
email: 'string'
}
},
// feedbacks: {
// rating: 'like',
// content: 'string',
// from_source: 'log'
// }
}, {
id: 3,
created_at: '2023-10-11 10:20',
message: '梦见在山上手撕鬼子,大师解解梦',
answer: '但是,一般来说,“手撕鬼子”这个场景可能是梦境者对于过去历史上的战争、侵略以及对于自己国家和族群的保护与维护的情感反应。在梦中,你可能会感到自己充满力量和勇气,去对抗那些看似强大的侵略者。',
provider_response_latency: 288,
answer_tokens: 100,
annotation: {
content: 'string',
account: {
id: 'string',
name: 'string',
email: 'string'
}
},
feedbacks: {
rating: 'dislike',
content: 'string',
from_source: 'log'
}
}],
limit: 20,
has_more: true
}
res.send(data)
})
app.post('/apps/:id/annotations', async (req, res) => {
res.send({ result: 'success' })
})
app.post('/apps/:id/feedbacks', async (req, res) => {
res.send({ result: 'success' })
})
}
module.exports = registerAPI