| # Logs | |||||
| logs | |||||
| *.log | |||||
| npm-debug.log* | |||||
| yarn-debug.log* | |||||
| yarn-error.log* | |||||
| lerna-debug.log* | |||||
| # Diagnostic reports (https://nodejs.org/api/report.html) | |||||
| report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | |||||
| # Runtime data | |||||
| pids | |||||
| *.pid | |||||
| *.seed | |||||
| *.pid.lock | |||||
| # Directory for instrumented libs generated by jscoverage/JSCover | |||||
| lib-cov | |||||
| # Coverage directory used by tools like istanbul | |||||
| coverage | |||||
| *.lcov | |||||
| # nyc test coverage | |||||
| .nyc_output | |||||
| # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | |||||
| .grunt | |||||
| # Bower dependency directory (https://bower.io/) | |||||
| bower_components | |||||
| # node-waf configuration | |||||
| .lock-wscript | |||||
| # Compiled binary addons (https://nodejs.org/api/addons.html) | |||||
| build/Release | |||||
| # Dependency directories | |||||
| node_modules/ | |||||
| jspm_packages/ | |||||
| # TypeScript v1 declaration files | |||||
| typings/ | |||||
| # TypeScript cache | |||||
| *.tsbuildinfo | |||||
| # Optional npm cache directory | |||||
| .npm | |||||
| # Optional eslint cache | |||||
| .eslintcache | |||||
| # Microbundle cache | |||||
| .rpt2_cache/ | |||||
| .rts2_cache_cjs/ | |||||
| .rts2_cache_es/ | |||||
| .rts2_cache_umd/ | |||||
| # Optional REPL history | |||||
| .node_repl_history | |||||
| # Output of 'npm pack' | |||||
| *.tgz | |||||
| # Yarn Integrity file | |||||
| .yarn-integrity | |||||
| # dotenv environment variables file | |||||
| .env | |||||
| .env.test | |||||
| # parcel-bundler cache (https://parceljs.org/) | |||||
| .cache | |||||
| # Next.js build output | |||||
| .next | |||||
| # Nuxt.js build / generate output | |||||
| .nuxt | |||||
| dist | |||||
| # Gatsby files | |||||
| .cache/ | |||||
| # Comment in the public line in if your project uses Gatsby and *not* Next.js | |||||
| # https://nextjs.org/blog/next-9-1#public-directory-support | |||||
| # public | |||||
| # vuepress build output | |||||
| .vuepress/dist | |||||
| # Serverless directories | |||||
| .serverless/ | |||||
| # FuseBox cache | |||||
| .fusebox/ | |||||
| # DynamoDB Local files | |||||
| .dynamodb/ | |||||
| # TernJS port file | |||||
| .tern-port | |||||
| # npm | |||||
| package-lock.json | |||||
| # yarn | |||||
| .pnp.cjs | |||||
| .pnp.loader.mjs | |||||
| .yarn/ | |||||
| yarn.lock | |||||
| .yarnrc.yml | |||||
| # pmpm | |||||
| pnpm-lock.yaml |
| # Mock Server |
| 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 |
| const registerAPI = function (app) { | |||||
| app.post('/login', async (req, res) => { | |||||
| res.send({ | |||||
| result: 'success' | |||||
| }) | |||||
| }) | |||||
| // get user info | |||||
| app.get('/account/profile', async (req, res) => { | |||||
| res.send({ | |||||
| id: '11122222', | |||||
| name: 'Joel', | |||||
| email: 'iamjoel007@gmail.com' | |||||
| }) | |||||
| }) | |||||
| // logout | |||||
| app.get('/logout', async (req, res) => { | |||||
| res.send({ | |||||
| result: 'success' | |||||
| }) | |||||
| }) | |||||
| // Langgenius version | |||||
| app.get('/version', async (req, res) => { | |||||
| res.send({ | |||||
| current_version: 'v1.0.0', | |||||
| latest_version: 'v1.0.0', | |||||
| upgradeable: true, | |||||
| compatible_upgrade: true | |||||
| }) | |||||
| }) | |||||
| } | |||||
| module.exports = registerAPI | |||||
| const registerAPI = function (app) { | |||||
| app.get("/datasets/:id/documents", async (req, res) => { | |||||
| if (req.params.id === "0") res.send({ data: [] }); | |||||
| else { | |||||
| res.send({ | |||||
| data: [ | |||||
| { | |||||
| id: 1, | |||||
| name: "Steve Jobs' life", | |||||
| words: "70k", | |||||
| word_count: 100, | |||||
| updated_at: 1681801029, | |||||
| indexing_status: "completed", | |||||
| archived: true, | |||||
| enabled: false, | |||||
| data_source_info: { | |||||
| upload_file: { | |||||
| // id: string | |||||
| // name: string | |||||
| // size: number | |||||
| // mime_type: string | |||||
| // created_at: number | |||||
| // created_by: string | |||||
| extension: "pdf", | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: "Steve Jobs' life", | |||||
| word_count: "10k", | |||||
| hit_count: 10, | |||||
| updated_at: 1681801029, | |||||
| indexing_status: "waiting", | |||||
| archived: true, | |||||
| enabled: false, | |||||
| data_source_info: { | |||||
| upload_file: { | |||||
| extension: "json", | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: "Steve Jobs' life xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", | |||||
| word_count: "100k", | |||||
| hit_count: 0, | |||||
| updated_at: 1681801029, | |||||
| indexing_status: "indexing", | |||||
| archived: false, | |||||
| enabled: true, | |||||
| data_source_info: { | |||||
| upload_file: { | |||||
| extension: "txt", | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| id: 4, | |||||
| name: "Steve Jobs' life xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", | |||||
| word_count: "100k", | |||||
| hit_count: 0, | |||||
| updated_at: 1681801029, | |||||
| indexing_status: "splitting", | |||||
| archived: false, | |||||
| enabled: true, | |||||
| data_source_info: { | |||||
| upload_file: { | |||||
| extension: "md", | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| id: 5, | |||||
| name: "Steve Jobs' life", | |||||
| word_count: "100k", | |||||
| hit_count: 0, | |||||
| updated_at: 1681801029, | |||||
| indexing_status: "error", | |||||
| archived: false, | |||||
| enabled: false, | |||||
| data_source_info: { | |||||
| upload_file: { | |||||
| extension: "html", | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| total: 100, | |||||
| id: req.params.id, | |||||
| }); | |||||
| } | |||||
| }); | |||||
| app.get("/datasets/:id/documents/:did/segments", async (req, res) => { | |||||
| if (req.params.id === "0") res.send({ data: [] }); | |||||
| else { | |||||
| res.send({ | |||||
| data: new Array(100).fill({ | |||||
| id: 1234, | |||||
| content: `他的坚持让我很为难。众所周知他非常注意保护自己的隐私,而我想他应该从来没有看过我写的书。也许将来的某个时候吧,我还是这么说。但是,到了2009年,他的妻子劳伦·鲍威尔(Laurene Powell)直言不讳地对我说:“如果你真的打算写一本关于史蒂夫的书,最好现在就开始。”他当时刚刚第二次因病休假。我向劳伦坦承,当乔布斯第一次提出这个想法时,我并不知道他病了。几乎没有人知道,她说。他是在接受癌症手术之前给我打的电话,直到今天他还将此事作为一个秘密,她这么解释道。\n | |||||
| 他的坚持让我很为难。众所周知他非常注意保护自己的隐私,而我想他应该从来没有看过我写的书。也许将来的某个时候吧,我还是这么说。但是,到了2009年,他的妻子劳伦·鲍威尔(Laurene Powell)直言不讳地对我说:“如果你真的打算写一本关于史蒂夫的书,最好现在就开始。”他当时刚刚第二次因病休假。我向劳伦坦承,当乔布斯第一次提出这个想法时,我并不知道他病了。几乎没有人知道,她说。他是在接受癌症手术之前给我打的电话,直到今天他还将此事作为一个秘密,她这么解释道。`, | |||||
| enabled: true, | |||||
| keyWords: [ | |||||
| "劳伦·鲍威尔", | |||||
| "劳伦·鲍威尔", | |||||
| "手术", | |||||
| "秘密", | |||||
| "癌症", | |||||
| "乔布斯", | |||||
| "史蒂夫", | |||||
| "书", | |||||
| "休假", | |||||
| "坚持", | |||||
| "隐私", | |||||
| ], | |||||
| word_count: 120, | |||||
| hit_count: 100, | |||||
| status: "ok", | |||||
| index_node_hash: "index_node_hash value", | |||||
| }), | |||||
| limit: 100, | |||||
| has_more: true, | |||||
| }); | |||||
| } | |||||
| }); | |||||
| // get doc detail | |||||
| app.get("/datasets/:id/documents/:did", async (req, res) => { | |||||
| const fixedParams = { | |||||
| // originInfo: { | |||||
| originalFilename: "Original filename", | |||||
| originalFileSize: "16mb", | |||||
| uploadDate: "2023-01-01", | |||||
| lastUpdateDate: "2023-01-05", | |||||
| source: "Source", | |||||
| // }, | |||||
| // technicalParameters: { | |||||
| segmentSpecification: "909090", | |||||
| segmentLength: 100, | |||||
| avgParagraphLength: 130, | |||||
| }; | |||||
| const bookData = { | |||||
| doc_type: "book", | |||||
| doc_metadata: { | |||||
| title: "机器学习实战", | |||||
| language: "zh", | |||||
| author: "Peter Harrington", | |||||
| publisher: "人民邮电出版社", | |||||
| publicationDate: "2013-01-01", | |||||
| ISBN: "9787115335500", | |||||
| category: "技术", | |||||
| }, | |||||
| }; | |||||
| const webData = { | |||||
| doc_type: "webPage", | |||||
| doc_metadata: { | |||||
| title: "深度学习入门教程", | |||||
| url: "https://www.example.com/deep-learning-tutorial", | |||||
| language: "zh", | |||||
| publishDate: "2020-05-01", | |||||
| authorPublisher: "张三", | |||||
| topicsKeywords: "深度学习, 人工智能, 教程", | |||||
| description: | |||||
| "这是一篇详细的深度学习入门教程,适用于对人工智能和深度学习感兴趣的初学者。", | |||||
| }, | |||||
| }; | |||||
| const postData = { | |||||
| doc_type: "socialMediaPost", | |||||
| doc_metadata: { | |||||
| platform: "Twitter", | |||||
| authorUsername: "example_user", | |||||
| publishDate: "2021-08-15", | |||||
| postURL: "https://twitter.com/example_user/status/1234567890", | |||||
| topicsTags: | |||||
| "AI, DeepLearning, Tutorial, Example, Example2, Example3, AI, DeepLearning, Tutorial, Example, Example2, Example3, AI, DeepLearning, Tutorial, Example, Example2, Example3,", | |||||
| }, | |||||
| }; | |||||
| res.send({ | |||||
| id: "550e8400-e29b-41d4-a716-446655440000", | |||||
| position: 1, | |||||
| dataset_id: "550e8400-e29b-41d4-a716-446655440002", | |||||
| data_source_type: "upload_file", | |||||
| data_source_info: { | |||||
| upload_file: { | |||||
| extension: "html", | |||||
| id: "550e8400-e29b-41d4-a716-446655440003", | |||||
| }, | |||||
| }, | |||||
| dataset_process_rule_id: "550e8400-e29b-41d4-a716-446655440004", | |||||
| batch: "20230410123456123456", | |||||
| name: "example_document", | |||||
| created_from: "web", | |||||
| created_by: "550e8400-e29b-41d4-a716-446655440005", | |||||
| created_api_request_id: "550e8400-e29b-41d4-a716-446655440006", | |||||
| created_at: 1671269696, | |||||
| processing_started_at: 1671269700, | |||||
| word_count: 11, | |||||
| parsing_completed_at: 1671269710, | |||||
| cleaning_completed_at: 1671269720, | |||||
| splitting_completed_at: 1671269730, | |||||
| tokens: 10, | |||||
| indexing_latency: 5.0, | |||||
| completed_at: 1671269740, | |||||
| paused_by: null, | |||||
| paused_at: null, | |||||
| error: null, | |||||
| stopped_at: null, | |||||
| indexing_status: "completed", | |||||
| enabled: true, | |||||
| disabled_at: null, | |||||
| disabled_by: null, | |||||
| archived: false, | |||||
| archived_reason: null, | |||||
| archived_by: null, | |||||
| archived_at: null, | |||||
| updated_at: 1671269740, | |||||
| ...(req.params.did === "book" | |||||
| ? bookData | |||||
| : req.params.did === "web" | |||||
| ? webData | |||||
| : req.params.did === "post" | |||||
| ? postData | |||||
| : {}), | |||||
| segment_count: 10, | |||||
| hit_count: 9, | |||||
| status: "ok", | |||||
| }); | |||||
| }); | |||||
| // // logout | |||||
| // app.get("/logout", async (req, res) => { | |||||
| // res.send({ | |||||
| // result: "success", | |||||
| // }); | |||||
| // }); | |||||
| // // Langgenius version | |||||
| // app.get("/version", async (req, res) => { | |||||
| // res.send({ | |||||
| // current_version: "v1.0.0", | |||||
| // latest_version: "v1.0.0", | |||||
| // upgradeable: true, | |||||
| // compatible_upgrade: true, | |||||
| // }); | |||||
| // }); | |||||
| }; | |||||
| module.exports = registerAPI; |
| const registerAPI = function (app) { | |||||
| const coversationList = [ | |||||
| { | |||||
| id: '1', | |||||
| name: '梦的解析', | |||||
| inputs: { | |||||
| book: '《梦的解析》', | |||||
| callMe: '大师', | |||||
| }, | |||||
| chats: [] | |||||
| }, | |||||
| { | |||||
| id: '2', | |||||
| name: '生命的起源', | |||||
| inputs: { | |||||
| book: '《x x x》', | |||||
| } | |||||
| }, | |||||
| ] | |||||
| // site info | |||||
| app.get('/apps/site/info', async (req, res) => { | |||||
| // const id = req.params.id | |||||
| res.send({ | |||||
| enable_site: true, | |||||
| appId: '1', | |||||
| site: { | |||||
| title: 'Story Bot', | |||||
| description: '这是一款解梦聊天机器人,你可以选择你喜欢的解梦人进行解梦,这句话是客户端应用说明', | |||||
| }, | |||||
| prompt_public: true, //id === '1', | |||||
| prompt_template: '你是我的解梦小助手,请参考 {{book}} 回答我有关梦境的问题。在回答前请称呼我为 {{myName}}。', | |||||
| }) | |||||
| }) | |||||
| app.post('/apps/:id/chat-messages', async (req, res) => { | |||||
| const conversationId = req.body.conversation_id ? req.body.conversation_id : Date.now() + '' | |||||
| res.send({ | |||||
| id: Date.now() + '', | |||||
| conversation_id: Date.now() + '', | |||||
| answer: 'balabababab' | |||||
| }) | |||||
| }) | |||||
| app.post('/apps/:id/completion-messages', async (req, res) => { | |||||
| res.send({ | |||||
| id: Date.now() + '', | |||||
| answer: `做为一个AI助手,我可以为你提供随机生成的段落,这些段落可以用于测试、占位符、或者其他目的。以下是一个随机生成的段落: | |||||
| “随着科技的不断发展,越来越多的人开始意识到人工智能的重要性。人工智能已经成为我们生活中不可或缺的一部分,它可以帮助我们完成很多繁琐的工作,也可以为我们提供更智能、更便捷的服务。虽然人工智能带来了很多好处,但它也面临着很多挑战。例如,人工智能的算法可能会出现偏见,导致对某些人群不公平。此外,人工智能的发展也可能会导致一些工作的失业。因此,我们需要不断地研究人工智能的发展,以确保它能够为人类带来更多的好处。”` | |||||
| }) | |||||
| }) | |||||
| // share api | |||||
| // chat list | |||||
| app.get('/apps/:id/coversations', async (req, res) => { | |||||
| res.send({ | |||||
| data: coversationList | |||||
| }) | |||||
| }) | |||||
| app.get('/apps/:id/variables', async (req, res) => { | |||||
| res.send({ | |||||
| variables: [ | |||||
| { | |||||
| key: 'book', | |||||
| name: '书', | |||||
| value: '《梦境解析》', | |||||
| type: 'string' | |||||
| }, | |||||
| { | |||||
| key: 'myName', | |||||
| name: '称呼', | |||||
| value: '', | |||||
| type: 'string' | |||||
| } | |||||
| ], | |||||
| }) | |||||
| }) | |||||
| } | |||||
| module.exports = registerAPI | |||||
| // const chatList = [ | |||||
| // { | |||||
| // id: 1, | |||||
| // content: 'AI 开场白', | |||||
| // isAnswer: true, | |||||
| // }, | |||||
| // { | |||||
| // id: 2, | |||||
| // content: '梦见在山上手撕鬼子,大师解解梦', | |||||
| // more: { time: '5.6 秒' }, | |||||
| // }, | |||||
| // { | |||||
| // id: 3, | |||||
| // content: '梦境通常是个人内心深处的反映,很难确定每个人梦境的确切含义,因为它们可能会受到梦境者的文化背景、生活经验和情感状态等多种因素的影响。', | |||||
| // isAnswer: true, | |||||
| // more: { time: '99 秒' }, | |||||
| // }, | |||||
| // { | |||||
| // id: 4, | |||||
| // content: '梦见在山上手撕鬼子,大师解解梦', | |||||
| // more: { time: '5.6 秒' }, | |||||
| // }, | |||||
| // { | |||||
| // id: 5, | |||||
| // content: '梦见在山上手撕鬼子,大师解解梦', | |||||
| // more: { time: '5.6 秒' }, | |||||
| // }, | |||||
| // { | |||||
| // id: 6, | |||||
| // content: '梦见在山上手撕鬼子,大师解解梦', | |||||
| // more: { time: '5.6 秒' }, | |||||
| // }, | |||||
| // ] |
| const registerAPI = function (app) { | |||||
| app.get('/demo', async (req, res) => { | |||||
| res.send({ | |||||
| des: 'get res' | |||||
| }) | |||||
| }) | |||||
| app.post('/demo', async (req, res) => { | |||||
| res.send({ | |||||
| des: 'post res' | |||||
| }) | |||||
| }) | |||||
| } | |||||
| module.exports = registerAPI |
| const express = require('express') | |||||
| const app = express() | |||||
| const bodyParser = require('body-parser') | |||||
| var cors = require('cors') | |||||
| const commonAPI = require('./api/common') | |||||
| const demoAPI = require('./api/demo') | |||||
| const appsApi = require('./api/apps') | |||||
| const debugAPI = require('./api/debug') | |||||
| const datasetsAPI = require('./api/datasets') | |||||
| const port = 3001 | |||||
| app.use(bodyParser.json()) // for parsing application/json | |||||
| app.use(bodyParser.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded | |||||
| const corsOptions = { | |||||
| origin: true, | |||||
| credentials: true, | |||||
| } | |||||
| app.use(cors(corsOptions)) // for cross origin | |||||
| app.options('*', cors(corsOptions)) // include before other routes | |||||
| demoAPI(app) | |||||
| commonAPI(app) | |||||
| appsApi(app) | |||||
| debugAPI(app) | |||||
| datasetsAPI(app) | |||||
| app.get('/', (req, res) => { | |||||
| res.send('rootpath') | |||||
| }) | |||||
| app.listen(port, () => { | |||||
| console.log(`Mock run on port ${port}`) | |||||
| }) | |||||
| const sleep = (ms) => { | |||||
| return new Promise(resolve => setTimeout(resolve, ms)) | |||||
| } |
| { | |||||
| "name": "server", | |||||
| "version": "1.0.0", | |||||
| "description": "", | |||||
| "main": "index.js", | |||||
| "scripts": { | |||||
| "dev": "nodemon node app.js", | |||||
| "start": "node app.js", | |||||
| "tcp": "node tcp.js" | |||||
| }, | |||||
| "keywords": [], | |||||
| "author": "", | |||||
| "license": "MIT", | |||||
| "engines": { | |||||
| "node": ">=16.0.0" | |||||
| }, | |||||
| "dependencies": { | |||||
| "body-parser": "^1.20.2", | |||||
| "cors": "^2.8.5", | |||||
| "express": "4.18.2", | |||||
| "express-jwt": "8.4.1" | |||||
| }, | |||||
| "devDependencies": { | |||||
| "nodemon": "2.0.21" | |||||
| } | |||||
| } |
| export async function GET(_request: Request) { | |||||
| return new Response('Hello, Next.js!') | |||||
| } |
| datasetId: string | datasetId: string | ||||
| } | } | ||||
| export const fetcher = (url: string) => get(url, {}, { isMock: true }) | |||||
| export const fetcher = (url: string) => get(url, {}, {}) | |||||
| const Documents: FC<IDocumentsProps> = ({ datasetId }) => { | const Documents: FC<IDocumentsProps> = ({ datasetId }) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() |
| export const API_PREFIX: string = apiPrefix; | export const API_PREFIX: string = apiPrefix; | ||||
| export const PUBLIC_API_PREFIX: string = publicApiPrefix; | export const PUBLIC_API_PREFIX: string = publicApiPrefix; | ||||
| // mock server | |||||
| export const MOCK_API_PREFIX = 'http://127.0.0.1:3001' | |||||
| const EDITION = process.env.NEXT_PUBLIC_EDITION || globalThis.document?.body?.getAttribute('data-public-edition') | const EDITION = process.env.NEXT_PUBLIC_EDITION || globalThis.document?.body?.getAttribute('data-public-edition') | ||||
| export const IS_CE_EDITION = EDITION === 'SELF_HOSTED' | export const IS_CE_EDITION = EDITION === 'SELF_HOSTED' | ||||
| import { API_PREFIX, MOCK_API_PREFIX, PUBLIC_API_PREFIX, IS_CE_EDITION } from '@/config' | |||||
| import { API_PREFIX, PUBLIC_API_PREFIX, IS_CE_EDITION } from '@/config' | |||||
| import Toast from '@/app/components/base/toast' | import Toast from '@/app/components/base/toast' | ||||
| const TIME_OUT = 100000 | const TIME_OUT = 100000 | ||||
| type IOtherOptions = { | type IOtherOptions = { | ||||
| isPublicAPI?: boolean | isPublicAPI?: boolean | ||||
| isMock?: boolean | |||||
| needAllResponseContent?: boolean | needAllResponseContent?: boolean | ||||
| onData?: IOnData // for stream | onData?: IOnData // for stream | ||||
| onError?: IOnError | onError?: IOnError | ||||
| read() | read() | ||||
| } | } | ||||
| const baseFetch = (url: string, fetchOptions: any, { isPublicAPI = false, isMock = false, needAllResponseContent }: IOtherOptions) => { | |||||
| const baseFetch = ( | |||||
| url: string, | |||||
| fetchOptions: any, | |||||
| { | |||||
| isPublicAPI = false, | |||||
| needAllResponseContent | |||||
| }: IOtherOptions | |||||
| ) => { | |||||
| const options = Object.assign({}, baseOptions, fetchOptions) | const options = Object.assign({}, baseOptions, fetchOptions) | ||||
| if (isPublicAPI) { | if (isPublicAPI) { | ||||
| const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0] | const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0] | ||||
| } | } | ||||
| let urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX | let urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX | ||||
| if (isMock) | |||||
| urlPrefix = MOCK_API_PREFIX | |||||
| let urlWithPrefix = `${urlPrefix}${url.startsWith('/') ? url : `/${url}`}` | let urlWithPrefix = `${urlPrefix}${url.startsWith('/') ? url : `/${url}`}` | ||||
| const { method, params, body } = options | const { method, params, body } = options |