mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-24 22:03:54 +00:00
feat: openai base url
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
# proxy
|
# proxy
|
||||||
AXIOS_PROXY_HOST=127.0.0.1
|
AXIOS_PROXY_HOST=127.0.0.1
|
||||||
AXIOS_PROXY_PORT_FAST=7890
|
AXIOS_PROXY_PORT=7890
|
||||||
AXIOS_PROXY_PORT_NORMAL=7890
|
|
||||||
queueTask=1
|
queueTask=1
|
||||||
parentUrl=https://hostname/api/openapi/startEvents
|
parentUrl=https://hostname/api/openapi/startEvents
|
||||||
# email
|
# email
|
||||||
@@ -16,6 +15,7 @@ aliTemplateCode=SMS_xxx
|
|||||||
TOKEN_KEY=xxx
|
TOKEN_KEY=xxx
|
||||||
# openai
|
# openai
|
||||||
OPENAIKEY=sk-xxx
|
OPENAIKEY=sk-xxx
|
||||||
|
OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
# db
|
# db
|
||||||
MONGODB_URI=mongodb://username:password@0.0.0.0:27017/test?authSource=admin
|
MONGODB_URI=mongodb://username:password@0.0.0.0:27017/test?authSource=admin
|
||||||
PG_HOST=0.0.0.0
|
PG_HOST=0.0.0.0
|
||||||
|
16
README.md
16
README.md
@@ -11,8 +11,10 @@ Fast GPT 允许你使用自己的 openai API KEY 来快速的调用 openai 接
|
|||||||
```bash
|
```bash
|
||||||
# proxy(不需要代理可忽略)
|
# proxy(不需要代理可忽略)
|
||||||
AXIOS_PROXY_HOST=127.0.0.1
|
AXIOS_PROXY_HOST=127.0.0.1
|
||||||
AXIOS_PROXY_PORT_FAST=7890
|
AXIOS_PROXY_PORT=7890
|
||||||
AXIOS_PROXY_PORT_NORMAL=7890
|
# 中转方案,修改 openai 的 base url
|
||||||
|
OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
|
# 是否开启队列任务。 1-开启,0-关闭(请求parentUrl去执行任务,单机时直接填1)
|
||||||
queueTask=1
|
queueTask=1
|
||||||
parentUrl=https://hostname/api/openapi/startEvents
|
parentUrl=https://hostname/api/openapi/startEvents
|
||||||
# email,参考 nodeMail 获取参数
|
# email,参考 nodeMail 获取参数
|
||||||
@@ -181,24 +183,17 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
container_name: fast-gpt
|
container_name: fast-gpt
|
||||||
environment:
|
environment:
|
||||||
# 代理(不需要代理,可去掉下面三个参数)
|
|
||||||
- AXIOS_PROXY_HOST=127.0.0.1
|
- AXIOS_PROXY_HOST=127.0.0.1
|
||||||
- AXIOS_PROXY_PORT_FAST=7890
|
- AXIOS_PROXY_PORT=7890
|
||||||
- AXIOS_PROXY_PORT_NORMAL=7890
|
|
||||||
# 邮箱
|
|
||||||
- MY_MAIL=xxxx@qq.com
|
- MY_MAIL=xxxx@qq.com
|
||||||
- MAILE_CODE=xxxx
|
- MAILE_CODE=xxxx
|
||||||
# 阿里云短信
|
|
||||||
- aliAccessKeyId=xxxx
|
- aliAccessKeyId=xxxx
|
||||||
- aliAccessKeySecret=xxxx
|
- aliAccessKeySecret=xxxx
|
||||||
- aliSignName=xxxxx
|
- aliSignName=xxxxx
|
||||||
- aliTemplateCode=SMS_xxxx
|
- aliTemplateCode=SMS_xxxx
|
||||||
# 登录 key
|
|
||||||
- TOKEN_KEY=xxxx
|
- TOKEN_KEY=xxxx
|
||||||
# 是否开启队列任务。 1-开启,0-关闭(请求parentUrl去执行任务,单机时直接填1)
|
|
||||||
- queueTask=1
|
- queueTask=1
|
||||||
- parentUrl=https://hostname/api/openapi/startEvents
|
- parentUrl=https://hostname/api/openapi/startEvents
|
||||||
# db
|
|
||||||
- MONGODB_URI=mongodb://username:passsword@0.0.0.0:27017/?authSource=admin
|
- MONGODB_URI=mongodb://username:passsword@0.0.0.0:27017/?authSource=admin
|
||||||
- MONGODB_NAME=xxx
|
- MONGODB_NAME=xxx
|
||||||
- PG_HOST=0.0.0.0
|
- PG_HOST=0.0.0.0
|
||||||
@@ -206,7 +201,6 @@ services:
|
|||||||
- PG_USER=xxx
|
- PG_USER=xxx
|
||||||
- PG_PASSWORD=xxx
|
- PG_PASSWORD=xxx
|
||||||
- PG_DB_NAME=xxx
|
- PG_DB_NAME=xxx
|
||||||
# openai 账号
|
|
||||||
- OPENAIKEY=sk-xxxxx
|
- OPENAIKEY=sk-xxxxx
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:alpine3.17
|
image: nginx:alpine3.17
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { getOpenAIApi, authChat } from '@/service/utils/auth';
|
import { getOpenAIApi, authChat } from '@/service/utils/auth';
|
||||||
import { httpsAgent, openaiChatFilter } from '@/service/utils/tools';
|
import { axiosConfig, openaiChatFilter } from '@/service/utils/tools';
|
||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
@@ -88,7 +88,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
{
|
{
|
||||||
timeout: 40000,
|
timeout: 40000,
|
||||||
responseType: 'stream',
|
responseType: 'stream',
|
||||||
httpsAgent: httpsAgent(!userApiKey)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { authChat } from '@/service/utils/auth';
|
import { authChat } from '@/service/utils/auth';
|
||||||
import { httpsAgent, systemPromptFilter, openaiChatFilter } from '@/service/utils/tools';
|
import { axiosConfig, systemPromptFilter, openaiChatFilter } from '@/service/utils/tools';
|
||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
@@ -150,7 +150,7 @@ ${
|
|||||||
{
|
{
|
||||||
timeout: 40000,
|
timeout: 40000,
|
||||||
responseType: 'stream',
|
responseType: 'stream',
|
||||||
httpsAgent: httpsAgent(!userApiKey)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response';
|
|||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { authToken } from '@/service/utils/tools';
|
import { authToken } from '@/service/utils/tools';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { httpsAgent } from '@/service/utils/tools';
|
import { axiosConfig } from '@/service/utils/tools';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取网站的内容
|
* 读取网站的内容
|
||||||
@@ -22,7 +22,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
const data = await axios
|
const data = await axios
|
||||||
.get(url, {
|
.get(url, {
|
||||||
httpsAgent: httpsAgent(false)
|
httpsAgent: axiosConfig.httpsAgent
|
||||||
})
|
})
|
||||||
.then((res) => res.data as string);
|
.then((res) => res.data as string);
|
||||||
|
|
||||||
|
@@ -1,11 +1,7 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { Chat, Model, Training, connectToDatabase } from '@/service/mongo';
|
import { Chat, Model, connectToDatabase } from '@/service/mongo';
|
||||||
import { authToken } from '@/service/utils/tools';
|
import { authToken } from '@/service/utils/tools';
|
||||||
import { getUserApiOpenai } from '@/service/utils/openai';
|
|
||||||
import { TrainingStatusEnum } from '@/constants/model';
|
|
||||||
import { TrainingItemType } from '@/types/training';
|
|
||||||
import { httpsAgent } from '@/service/utils/tools';
|
|
||||||
import { PgClient } from '@/service/pg';
|
import { PgClient } from '@/service/pg';
|
||||||
|
|
||||||
/* 获取我的模型 */
|
/* 获取我的模型 */
|
||||||
@@ -47,31 +43,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
modelId
|
modelId
|
||||||
});
|
});
|
||||||
|
|
||||||
// 查看是否正在训练
|
|
||||||
const training: TrainingItemType | null = await Training.findOne({
|
|
||||||
modelId,
|
|
||||||
status: TrainingStatusEnum.pending
|
|
||||||
});
|
|
||||||
|
|
||||||
// 如果正在训练,需要删除openai上的相关信息
|
|
||||||
if (training) {
|
|
||||||
const { openai } = await getUserApiOpenai(userId);
|
|
||||||
// 获取训练记录
|
|
||||||
const tuneRecord = await openai.retrieveFineTune(training.tuneId, {
|
|
||||||
httpsAgent: httpsAgent(false)
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除训练文件
|
|
||||||
openai.deleteFile(tuneRecord.data.training_files[0].id, { httpsAgent: httpsAgent(false) });
|
|
||||||
// 取消训练
|
|
||||||
openai.cancelFineTune(training.tuneId, { httpsAgent: httpsAgent(false) });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除对应训练记录
|
|
||||||
await Training.deleteMany({
|
|
||||||
modelId
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除模型
|
// 删除模型
|
||||||
await Model.deleteOne({
|
await Model.deleteOne({
|
||||||
_id: modelId,
|
_id: modelId,
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
import { jsonRes } from '@/service/response';
|
|
||||||
import { connectToDatabase, Training } from '@/service/mongo';
|
|
||||||
import { authToken } from '@/service/utils/tools';
|
|
||||||
|
|
||||||
// 关闭next默认的bodyParser处理方式
|
|
||||||
export const config = {
|
|
||||||
api: {
|
|
||||||
bodyParser: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 获取模型训练记录 */
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
try {
|
|
||||||
const { authorization } = req.headers;
|
|
||||||
|
|
||||||
if (!authorization) {
|
|
||||||
throw new Error('无权操作');
|
|
||||||
}
|
|
||||||
const { modelId } = req.query;
|
|
||||||
if (!modelId) {
|
|
||||||
throw new Error('参数错误');
|
|
||||||
}
|
|
||||||
await authToken(authorization);
|
|
||||||
|
|
||||||
await connectToDatabase();
|
|
||||||
|
|
||||||
/* 获取 modelId 下的 training 记录 */
|
|
||||||
const records = await Training.find({
|
|
||||||
modelId
|
|
||||||
});
|
|
||||||
|
|
||||||
jsonRes(res, {
|
|
||||||
data: records
|
|
||||||
});
|
|
||||||
} catch (err: any) {
|
|
||||||
/* 清除上传的文件,关闭训练记录 */
|
|
||||||
// @ts-ignore
|
|
||||||
if (openai) {
|
|
||||||
// @ts-ignore
|
|
||||||
uploadFileId && openai.deleteFile(uploadFileId);
|
|
||||||
// @ts-ignore
|
|
||||||
trainId && openai.cancelFineTune(trainId);
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonRes(res, {
|
|
||||||
code: 500,
|
|
||||||
error: err
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,106 +0,0 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
import { jsonRes } from '@/service/response';
|
|
||||||
import { connectToDatabase, Model, Training } from '@/service/mongo';
|
|
||||||
import { authToken } from '@/service/utils/tools';
|
|
||||||
import { getUserApiOpenai } from '@/service/utils/openai';
|
|
||||||
import type { ModelSchema } from '@/types/mongoSchema';
|
|
||||||
import { TrainingItemType } from '@/types/training';
|
|
||||||
import { ModelStatusEnum, TrainingStatusEnum } from '@/constants/model';
|
|
||||||
import { OpenAiTuneStatusEnum } from '@/service/constants/training';
|
|
||||||
import { httpsAgent } from '@/service/utils/tools';
|
|
||||||
|
|
||||||
/* 更新训练状态 */
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
try {
|
|
||||||
const { authorization } = req.headers;
|
|
||||||
|
|
||||||
if (!authorization) {
|
|
||||||
throw new Error('无权操作');
|
|
||||||
}
|
|
||||||
const { modelId } = req.query as { modelId: string };
|
|
||||||
if (!modelId) {
|
|
||||||
throw new Error('参数错误');
|
|
||||||
}
|
|
||||||
const userId = await authToken(authorization);
|
|
||||||
|
|
||||||
await connectToDatabase();
|
|
||||||
|
|
||||||
// 获取模型
|
|
||||||
const model = await Model.findById<ModelSchema>(modelId);
|
|
||||||
|
|
||||||
if (!model || model.status !== 'training') {
|
|
||||||
throw new Error('模型不在训练中');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询正在训练中的训练记录
|
|
||||||
const training: TrainingItemType | null = await Training.findOne({
|
|
||||||
modelId,
|
|
||||||
status: 'pending'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!training) {
|
|
||||||
throw new Error('找不到训练记录');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户的 openai 实例
|
|
||||||
const { openai } = await getUserApiOpenai(userId);
|
|
||||||
|
|
||||||
// 获取 openai 的训练情况
|
|
||||||
const { data } = await openai.retrieveFineTune(training.tuneId, {
|
|
||||||
httpsAgent: httpsAgent(false)
|
|
||||||
});
|
|
||||||
// console.log(data);
|
|
||||||
if (data.status === OpenAiTuneStatusEnum.succeeded) {
|
|
||||||
// 删除训练文件
|
|
||||||
openai.deleteFile(data.training_files[0].id, { httpsAgent: httpsAgent(false) });
|
|
||||||
|
|
||||||
// 更新模型状态和模型内容
|
|
||||||
await Model.findByIdAndUpdate(modelId, {
|
|
||||||
status: ModelStatusEnum.running,
|
|
||||||
updateTime: new Date(),
|
|
||||||
service: {
|
|
||||||
...model.service,
|
|
||||||
trainId: data.fine_tuned_model, // 训练完后,再次训练和对话使用的 model 是一样的
|
|
||||||
chatModel: data.fine_tuned_model
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 更新训练数据
|
|
||||||
await Training.findByIdAndUpdate(training._id, {
|
|
||||||
status: TrainingStatusEnum.succeed
|
|
||||||
});
|
|
||||||
|
|
||||||
return jsonRes(res, {
|
|
||||||
data: '模型微调完成'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 取消微调 */
|
|
||||||
if (data.status === OpenAiTuneStatusEnum.cancelled) {
|
|
||||||
// 删除训练文件
|
|
||||||
openai.deleteFile(data.training_files[0].id, { httpsAgent: httpsAgent(false) });
|
|
||||||
|
|
||||||
// 更新模型
|
|
||||||
await Model.findByIdAndUpdate(modelId, {
|
|
||||||
status: ModelStatusEnum.running,
|
|
||||||
updateTime: new Date()
|
|
||||||
});
|
|
||||||
// 更新训练数据
|
|
||||||
await Training.findByIdAndUpdate(training._id, {
|
|
||||||
status: TrainingStatusEnum.canceled
|
|
||||||
});
|
|
||||||
|
|
||||||
return jsonRes(res, {
|
|
||||||
data: '模型微调已取消'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonRes(res, {
|
|
||||||
data: '模型还在训练中'
|
|
||||||
});
|
|
||||||
} catch (err: any) {
|
|
||||||
jsonRes(res, {
|
|
||||||
code: 500,
|
|
||||||
error: err
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,130 +0,0 @@
|
|||||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
|
||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
import { jsonRes } from '@/service/response';
|
|
||||||
import { connectToDatabase, Model, Training } from '@/service/mongo';
|
|
||||||
import formidable from 'formidable';
|
|
||||||
import { authToken } from '@/service/utils/tools';
|
|
||||||
import { getUserApiOpenai } from '@/service/utils/openai';
|
|
||||||
import { join } from 'path';
|
|
||||||
import fs from 'fs';
|
|
||||||
import type { ModelSchema } from '@/types/mongoSchema';
|
|
||||||
import type { OpenAIApi } from 'openai';
|
|
||||||
import { ModelStatusEnum, TrainingStatusEnum } from '@/constants/model';
|
|
||||||
import { httpsAgent } from '@/service/utils/tools';
|
|
||||||
|
|
||||||
// 关闭next默认的bodyParser处理方式
|
|
||||||
export const config = {
|
|
||||||
api: {
|
|
||||||
bodyParser: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 上传文件,开始微调 */
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
let openai: OpenAIApi, trainId: string, uploadFileId: string;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { authorization } = req.headers;
|
|
||||||
|
|
||||||
if (!authorization) {
|
|
||||||
throw new Error('无权操作');
|
|
||||||
}
|
|
||||||
const { modelId } = req.query;
|
|
||||||
|
|
||||||
if (!modelId) {
|
|
||||||
throw new Error('参数错误');
|
|
||||||
}
|
|
||||||
const userId = await authToken(authorization);
|
|
||||||
|
|
||||||
await connectToDatabase();
|
|
||||||
|
|
||||||
// 获取模型的状态
|
|
||||||
const model = await Model.findById<ModelSchema>(modelId);
|
|
||||||
|
|
||||||
if (!model || model.status !== 'running') {
|
|
||||||
throw new Error('模型正忙');
|
|
||||||
}
|
|
||||||
|
|
||||||
// const trainingType = model.service.modelType
|
|
||||||
const trainingType = model.service.trainId; // 目前都默认是 openai text-davinci-03
|
|
||||||
|
|
||||||
// 获取用户的 API Key 实例化后的对象
|
|
||||||
const user = await getUserApiOpenai(userId);
|
|
||||||
openai = user.openai;
|
|
||||||
|
|
||||||
// 接收文件并保存
|
|
||||||
const form = formidable({
|
|
||||||
uploadDir: join(process.cwd(), 'public/trainData'),
|
|
||||||
keepExtensions: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const { files } = await new Promise<{
|
|
||||||
fields: formidable.Fields;
|
|
||||||
files: formidable.Files;
|
|
||||||
}>((resolve, reject) => {
|
|
||||||
form.parse(req, (err, fields, files) => {
|
|
||||||
if (err) return reject(err);
|
|
||||||
resolve({ fields, files });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const file = files.file;
|
|
||||||
|
|
||||||
// 上传文件到 openai
|
|
||||||
// @ts-ignore
|
|
||||||
const uploadRes = await openai.createFile(
|
|
||||||
// @ts-ignore
|
|
||||||
fs.createReadStream(file.filepath),
|
|
||||||
'fine-tune',
|
|
||||||
{ httpsAgent: httpsAgent(false) }
|
|
||||||
);
|
|
||||||
uploadFileId = uploadRes.data.id; // 记录上传文件的 ID
|
|
||||||
|
|
||||||
// 开始训练
|
|
||||||
const trainRes = await openai.createFineTune(
|
|
||||||
{
|
|
||||||
training_file: uploadFileId,
|
|
||||||
model: trainingType,
|
|
||||||
suffix: model.name,
|
|
||||||
n_epochs: 4
|
|
||||||
},
|
|
||||||
{ httpsAgent: httpsAgent(false) }
|
|
||||||
);
|
|
||||||
|
|
||||||
trainId = trainRes.data.id; // 记录训练 ID
|
|
||||||
|
|
||||||
// 创建训练记录
|
|
||||||
await Training.create({
|
|
||||||
serviceName: 'openai',
|
|
||||||
tuneId: trainId,
|
|
||||||
status: TrainingStatusEnum.pending,
|
|
||||||
modelId
|
|
||||||
});
|
|
||||||
|
|
||||||
// 修改模型状态
|
|
||||||
await Model.findByIdAndUpdate(modelId, {
|
|
||||||
$inc: {
|
|
||||||
trainingTimes: +1
|
|
||||||
},
|
|
||||||
updateTime: new Date(),
|
|
||||||
status: ModelStatusEnum.training
|
|
||||||
});
|
|
||||||
|
|
||||||
jsonRes(res, {
|
|
||||||
data: 'start training'
|
|
||||||
});
|
|
||||||
} catch (err: any) {
|
|
||||||
/* 清除上传的文件,关闭训练记录 */
|
|
||||||
// @ts-ignore
|
|
||||||
if (openai) {
|
|
||||||
// @ts-ignore
|
|
||||||
uploadFileId && openai.deleteFile(uploadFileId, { httpsAgent: httpsAgent(false) });
|
|
||||||
// @ts-ignore
|
|
||||||
trainId && openai.cancelFineTune(trainId, { httpsAgent: httpsAgent(false) });
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonRes(res, {
|
|
||||||
code: 500,
|
|
||||||
error: err
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +1,7 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { connectToDatabase, Model } from '@/service/mongo';
|
import { connectToDatabase, Model } from '@/service/mongo';
|
||||||
import { getOpenAIApi } from '@/service/utils/auth';
|
import { getOpenAIApi } from '@/service/utils/auth';
|
||||||
import { httpsAgent, openaiChatFilter, authOpenApiKey } from '@/service/utils/tools';
|
import { axiosConfig, openaiChatFilter, authOpenApiKey } from '@/service/utils/tools';
|
||||||
import { ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum } from 'openai';
|
|
||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
@@ -101,7 +100,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
{
|
{
|
||||||
timeout: 40000,
|
timeout: 40000,
|
||||||
responseType: isStream ? 'stream' : 'json',
|
responseType: isStream ? 'stream' : 'json',
|
||||||
httpsAgent: httpsAgent(true)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
|||||||
import { connectToDatabase, Model } from '@/service/mongo';
|
import { connectToDatabase, Model } from '@/service/mongo';
|
||||||
import { getOpenAIApi } from '@/service/utils/auth';
|
import { getOpenAIApi } from '@/service/utils/auth';
|
||||||
import { authOpenApiKey } from '@/service/utils/tools';
|
import { authOpenApiKey } from '@/service/utils/tools';
|
||||||
import { httpsAgent, openaiChatFilter, systemPromptFilter } from '@/service/utils/tools';
|
import { axiosConfig, openaiChatFilter, systemPromptFilter } from '@/service/utils/tools';
|
||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
@@ -120,7 +120,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout: 180000,
|
timeout: 180000,
|
||||||
httpsAgent: httpsAgent(true)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
{
|
{
|
||||||
timeout: 180000,
|
timeout: 180000,
|
||||||
responseType: isStream ? 'stream' : 'json',
|
responseType: isStream ? 'stream' : 'json',
|
||||||
httpsAgent: httpsAgent(true)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { connectToDatabase, Model } from '@/service/mongo';
|
import { connectToDatabase, Model } from '@/service/mongo';
|
||||||
import {
|
import {
|
||||||
httpsAgent,
|
axiosConfig,
|
||||||
systemPromptFilter,
|
systemPromptFilter,
|
||||||
authOpenApiKey,
|
authOpenApiKey,
|
||||||
openaiChatFilter
|
openaiChatFilter
|
||||||
} from '@/service/utils/tools';
|
} from '@/service/utils/tools';
|
||||||
import { ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum } from 'openai';
|
|
||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
@@ -172,7 +171,7 @@ ${
|
|||||||
{
|
{
|
||||||
timeout: 180000,
|
timeout: 180000,
|
||||||
responseType: isStream ? 'stream' : 'json',
|
responseType: isStream ? 'stream' : 'json',
|
||||||
httpsAgent: httpsAgent(true)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -119,31 +119,27 @@ const InputDataModal = ({
|
|||||||
pb={2}
|
pb={2}
|
||||||
>
|
>
|
||||||
<Box flex={2} mr={[0, 4]} mb={[4, 0]} h={['230px', '100%']}>
|
<Box flex={2} mr={[0, 4]} mb={[4, 0]} h={['230px', '100%']}>
|
||||||
<Box h={'30px'}>问题</Box>
|
<Box h={'30px'}>{'匹配的知识点'}</Box>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder={
|
placeholder={'匹配的知识点。这部分内容会被搜索,请把控内容的质量。最多 1000 字。'}
|
||||||
'相关问题,可以输入多个问法, 最多 1000 字。例如:\n1. laf 是什么?\n2. laf 可以做什么?\n3. laf怎么用'
|
maxLength={2000}
|
||||||
}
|
|
||||||
maxLength={1000}
|
|
||||||
resize={'none'}
|
resize={'none'}
|
||||||
h={'calc(100% - 30px)'}
|
h={'calc(100% - 30px)'}
|
||||||
{...register(`q`, {
|
{...register(`q`, {
|
||||||
required: '相关问题,可以回车输入多个问法'
|
required: true
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flex={3} h={['330px', '100%']}>
|
<Box flex={3} h={['330px', '100%']}>
|
||||||
<Box h={'30px'}>知识点</Box>
|
<Box h={'30px'}>补充知识</Box>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder={
|
placeholder={
|
||||||
'知识点,最多 2000 字。例如:\n1. laf是一个云函数开发平台。\n2. laf 什么都能做。\n3. 下面是使用 laf 的例子: ……'
|
'补充知识。这部分内容不会被搜索,但会作为"匹配的知识点"的内容补充,你可以讲一些细节的内容填写在这里。最多 2000 字。'
|
||||||
}
|
}
|
||||||
maxLength={2000}
|
maxLength={2000}
|
||||||
resize={'none'}
|
resize={'none'}
|
||||||
h={'calc(100% - 30px)'}
|
h={'calc(100% - 30px)'}
|
||||||
{...register(`a`, {
|
{...register('a')}
|
||||||
required: '知识点'
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -204,8 +204,8 @@ const ModelDataCard = ({ modelId }: { modelId: string }) => {
|
|||||||
<Table variant={'simple'} w={'100%'}>
|
<Table variant={'simple'} w={'100%'}>
|
||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>{'匹配内容(问题)'}</Th>
|
<Th>{'匹配的知识点'}</Th>
|
||||||
<Th>对应答案</Th>
|
<Th>补充知识</Th>
|
||||||
<Th>状态</Th>
|
<Th>状态</Th>
|
||||||
<Th>操作</Th>
|
<Th>操作</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { DataItem } from '@/service/mongo';
|
import { DataItem } from '@/service/mongo';
|
||||||
import { getOpenAIApi } from '@/service/utils/auth';
|
import { getOpenAIApi } from '@/service/utils/auth';
|
||||||
import { httpsAgent } from '@/service/utils/tools';
|
import { axiosConfig } from '@/service/utils/tools';
|
||||||
import { getOpenApiKey } from '../utils/openai';
|
import { getOpenApiKey } from '../utils/openai';
|
||||||
import type { ChatCompletionRequestMessage } from 'openai';
|
import type { ChatCompletionRequestMessage } from 'openai';
|
||||||
import { DataItemSchema } from '@/types/mongoSchema';
|
import { DataItemSchema } from '@/types/mongoSchema';
|
||||||
@@ -80,8 +80,8 @@ export async function generateAbstract(next = false): Promise<any> {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout: 120000,
|
timeout: 180000,
|
||||||
httpsAgent: httpsAgent(!userApiKey)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { SplitData } from '@/service/mongo';
|
import { SplitData } from '@/service/mongo';
|
||||||
import { getOpenAIApi } from '@/service/utils/auth';
|
import { getOpenAIApi } from '@/service/utils/auth';
|
||||||
import { httpsAgent } from '@/service/utils/tools';
|
import { axiosConfig } from '@/service/utils/tools';
|
||||||
import { getOpenApiKey } from '../utils/openai';
|
import { getOpenApiKey } from '../utils/openai';
|
||||||
import type { ChatCompletionRequestMessage } from 'openai';
|
import type { ChatCompletionRequestMessage } from 'openai';
|
||||||
import { ChatModelEnum } from '@/constants/model';
|
import { ChatModelEnum } from '@/constants/model';
|
||||||
@@ -97,7 +97,7 @@ A2:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout: 180000,
|
timeout: 180000,
|
||||||
httpsAgent: httpsAgent(!userApiKey)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
@@ -31,21 +31,11 @@ export async function connectToDatabase(): Promise<void> {
|
|||||||
generateVector(true);
|
generateVector(true);
|
||||||
|
|
||||||
// 创建代理对象
|
// 创建代理对象
|
||||||
if (
|
if (process.env.AXIOS_PROXY_HOST && process.env.AXIOS_PROXY_PORT) {
|
||||||
process.env.AXIOS_PROXY_HOST &&
|
global.httpsAgent = tunnel.httpsOverHttp({
|
||||||
process.env.AXIOS_PROXY_PORT_FAST &&
|
|
||||||
process.env.AXIOS_PROXY_PORT_NORMAL
|
|
||||||
) {
|
|
||||||
global.httpsAgentFast = tunnel.httpsOverHttp({
|
|
||||||
proxy: {
|
proxy: {
|
||||||
host: process.env.AXIOS_PROXY_HOST,
|
host: process.env.AXIOS_PROXY_HOST,
|
||||||
port: +process.env.AXIOS_PROXY_PORT_FAST
|
port: +process.env.AXIOS_PROXY_PORT
|
||||||
}
|
|
||||||
});
|
|
||||||
global.httpsAgentNormal = tunnel.httpsOverHttp({
|
|
||||||
proxy: {
|
|
||||||
host: process.env.AXIOS_PROXY_HOST,
|
|
||||||
port: +process.env.AXIOS_PROXY_PORT_NORMAL
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,8 @@ import mongoose from 'mongoose';
|
|||||||
|
|
||||||
export const getOpenAIApi = (apiKey: string) => {
|
export const getOpenAIApi = (apiKey: string) => {
|
||||||
const configuration = new Configuration({
|
const configuration = new Configuration({
|
||||||
apiKey
|
apiKey,
|
||||||
|
basePath: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'
|
||||||
});
|
});
|
||||||
|
|
||||||
return new OpenAIApi(configuration, undefined);
|
return new OpenAIApi(configuration, undefined);
|
||||||
|
@@ -2,7 +2,7 @@ import type { NextApiResponse } from 'next';
|
|||||||
import type { PassThrough } from 'stream';
|
import type { PassThrough } from 'stream';
|
||||||
import { createParser, ParsedEvent, ReconnectInterval } from 'eventsource-parser';
|
import { createParser, ParsedEvent, ReconnectInterval } from 'eventsource-parser';
|
||||||
import { getOpenAIApi } from '@/service/utils/auth';
|
import { getOpenAIApi } from '@/service/utils/auth';
|
||||||
import { httpsAgent } from './tools';
|
import { axiosConfig } from './tools';
|
||||||
import { User } from '../models/user';
|
import { User } from '../models/user';
|
||||||
import { formatPrice } from '@/utils/user';
|
import { formatPrice } from '@/utils/user';
|
||||||
import { embeddingModel } from '@/constants/model';
|
import { embeddingModel } from '@/constants/model';
|
||||||
@@ -85,7 +85,7 @@ export const openaiCreateEmbedding = async ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
httpsAgent: httpsAgent(isPay)
|
...axiosConfig
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((res) => ({
|
.then((res) => ({
|
||||||
|
@@ -84,9 +84,10 @@ export const authOpenApiKey = async (req: NextApiRequest) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 代理 */
|
/* openai axios config */
|
||||||
export const httpsAgent = (fast: boolean) =>
|
export const axiosConfig = {
|
||||||
fast ? global.httpsAgentFast : global.httpsAgentNormal;
|
httpsAgent: global.httpsAgent
|
||||||
|
};
|
||||||
|
|
||||||
/* delete invalid symbol */
|
/* delete invalid symbol */
|
||||||
const simplifyStr = (str: string) =>
|
const simplifyStr = (str: string) =>
|
||||||
|
3
src/types/index.d.ts
vendored
3
src/types/index.d.ts
vendored
@@ -11,8 +11,7 @@ declare global {
|
|||||||
var generatingAbstract: boolean;
|
var generatingAbstract: boolean;
|
||||||
var generatingVector: boolean;
|
var generatingVector: boolean;
|
||||||
var QRCode: any;
|
var QRCode: any;
|
||||||
var httpsAgentFast: Agent;
|
var httpsAgent: Agent;
|
||||||
var httpsAgentNormal: Agent;
|
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
['pdfjs-dist/build/pdf']: any;
|
['pdfjs-dist/build/pdf']: any;
|
||||||
|
Reference in New Issue
Block a user