feat: content check
This commit is contained in:
parent
98444fd04b
commit
51a5d450b7
@ -16,6 +16,8 @@ aliTemplateCode=SMS_xxx
|
|||||||
TOKEN_KEY=xxx
|
TOKEN_KEY=xxx
|
||||||
# root key, 最高权限
|
# root key, 最高权限
|
||||||
ROOT_KEY=xxx
|
ROOT_KEY=xxx
|
||||||
|
# 是否进行安全校验(1: 开启,0: 关闭)
|
||||||
|
SENSITIVE_CHECK=1
|
||||||
# openai
|
# openai
|
||||||
# OPENAI_BASE_URL=https://api.openai.com/v1
|
# OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
# OPENAI_BASE_URL_AUTH=可选的安全凭证(不需要的时候,记得去掉)
|
# OPENAI_BASE_URL_AUTH=可选的安全凭证(不需要的时候,记得去掉)
|
||||||
|
|||||||
@ -52,6 +52,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|||||||
|
|
||||||
USER nextjs
|
USER nextjs
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "server.js"]
|
||||||
|
|||||||
@ -52,6 +52,10 @@ services:
|
|||||||
- aliTemplateCode=SMS_xxxx
|
- aliTemplateCode=SMS_xxxx
|
||||||
# token加密凭证(随便填,作为登录凭证)
|
# token加密凭证(随便填,作为登录凭证)
|
||||||
- TOKEN_KEY=xxxx
|
- TOKEN_KEY=xxxx
|
||||||
|
# root key, 最高权限
|
||||||
|
- ROOT_KEY=xxx
|
||||||
|
# 是否进行安全校验(1: 开启,0: 关闭)
|
||||||
|
- SENSITIVE_CHECK=1
|
||||||
# 和上方mongo镜像的username,password对应
|
# 和上方mongo镜像的username,password对应
|
||||||
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
|
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
|
||||||
- MONGODB_NAME=fastgpt
|
- MONGODB_NAME=fastgpt
|
||||||
|
|||||||
@ -10,34 +10,38 @@
|
|||||||
# proxy(可选)
|
# proxy(可选)
|
||||||
AXIOS_PROXY_HOST=127.0.0.1
|
AXIOS_PROXY_HOST=127.0.0.1
|
||||||
AXIOS_PROXY_PORT=7890
|
AXIOS_PROXY_PORT=7890
|
||||||
# openai 中转连接(可选)
|
# 是否开启队列任务。 1-开启,0-关闭(请求parentUrl去执行任务,单机时直接填1)
|
||||||
OPENAI_BASE_URL=https://api.openai.com/v1
|
|
||||||
OPENAI_BASE_URL_AUTH=可选的安全凭证
|
|
||||||
# 是否开启队列任务。 1-开启,0-关闭(请求 parentUrl 去执行任务,单机时直接填1)
|
|
||||||
queueTask=1
|
queueTask=1
|
||||||
parentUrl=https://hostname/api/openapi/startEvents
|
parentUrl=https://hostname/api/openapi/startEvents
|
||||||
# 发送邮箱验证码配置。用的是 QQ 邮箱。参考 nodeMail 获取MAILE_CODE,自行百度。
|
# email
|
||||||
MY_MAIL=xxxx@qq.com
|
MY_MAIL=xxx@qq.com
|
||||||
MAILE_CODE=xxxx
|
MAILE_CODE=xxx
|
||||||
# 阿里短信服务(邮箱和短信至少二选一)
|
# ali ems
|
||||||
aliAccessKeyId=xxxx
|
aliAccessKeyId=xxx
|
||||||
aliAccessKeySecret=xxxx
|
aliAccessKeySecret=xxx
|
||||||
aliSignName=xxxxx
|
aliSignName=xxx
|
||||||
aliTemplateCode=SMS_xxxx
|
aliTemplateCode=SMS_xxx
|
||||||
# token加密凭证(随便填,作为登录凭证)
|
# token
|
||||||
TOKEN_KEY=xxxx
|
TOKEN_KEY=xxx
|
||||||
queueTask=1
|
# root key, 最高权限
|
||||||
parentUrl=https://hostname/api/openapi/startEvents
|
ROOT_KEY=xxx
|
||||||
# 和mongo镜像的username,password对应
|
# 是否进行安全校验(1: 开启,0: 关闭)
|
||||||
MONGODB_URI=mongodb://username:passsword@0.0.0.0:27017/?authSource=admin
|
SENSITIVE_CHECK=1
|
||||||
MONGODB_NAME=xxx
|
# openai
|
||||||
|
# OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
|
# OPENAI_BASE_URL_AUTH=可选的安全凭证(不需要的时候,记得去掉)
|
||||||
|
OPENAIKEY=sk-xxx
|
||||||
|
GPT4KEY=sk-xxx
|
||||||
|
# claude
|
||||||
|
CLAUDE_BASE_URL=calude模型请求地址
|
||||||
|
CLAUDE_KEY=CLAUDE_KEY
|
||||||
|
# db
|
||||||
|
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
|
||||||
PG_PORT=8100
|
PG_PORT=8100
|
||||||
# 和PG镜像对应.
|
PG_USER=xxx
|
||||||
PG_USER=fastgpt # POSTGRES_USER
|
PG_PASSWORD=xxx
|
||||||
PG_PASSWORD=1234 # POSTGRES_PASSWORD
|
PG_DB_NAME=xxx
|
||||||
PG_DB_NAME=fastgpt # POSTGRES_DB
|
|
||||||
OPENAIKEY=sk-xxxxx
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 运行
|
## 运行
|
||||||
|
|||||||
@ -2,3 +2,13 @@ export enum SplitTextTypEnum {
|
|||||||
'qa' = 'qa',
|
'qa' = 'qa',
|
||||||
'subsection' = 'subsection'
|
'subsection' = 'subsection'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PluginTypeEnum {
|
||||||
|
LLM = 'LLM',
|
||||||
|
Text = 'Text',
|
||||||
|
Function = 'Function'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PluginParamsTypeEnum {
|
||||||
|
'Text' = 'text'
|
||||||
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { resStreamResponse } from '@/service/utils/chat';
|
|||||||
import { searchKb } from '@/service/plugins/searchKb';
|
import { searchKb } from '@/service/plugins/searchKb';
|
||||||
import { ChatRoleEnum } from '@/constants/chat';
|
import { ChatRoleEnum } from '@/constants/chat';
|
||||||
import { BillTypeEnum } from '@/constants/user';
|
import { BillTypeEnum } from '@/constants/user';
|
||||||
|
import { sensitiveCheck } from '@/service/api/text';
|
||||||
|
|
||||||
/* 发送提示词 */
|
/* 发送提示词 */
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
@ -44,6 +45,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
// 读取对话内容
|
// 读取对话内容
|
||||||
const prompts = [...content, prompt];
|
const prompts = [...content, prompt];
|
||||||
|
let systemPrompts: {
|
||||||
|
obj: ChatRoleEnum;
|
||||||
|
value: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
// 使用了知识库搜索
|
// 使用了知识库搜索
|
||||||
if (model.chat.relatedKbs.length > 0) {
|
if (model.chat.relatedKbs.length > 0) {
|
||||||
@ -60,15 +65,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
return res.send(searchPrompts[0]?.value);
|
return res.send(searchPrompts[0]?.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
prompts.splice(prompts.length - 3, 0, ...searchPrompts);
|
systemPrompts = searchPrompts;
|
||||||
} else {
|
} else if (model.chat.systemPrompt) {
|
||||||
// 没有用知识库搜索,仅用系统提示词
|
systemPrompts = [
|
||||||
model.chat.systemPrompt &&
|
{
|
||||||
prompts.splice(prompts.length - 3, 0, {
|
|
||||||
obj: ChatRoleEnum.System,
|
obj: ChatRoleEnum.System,
|
||||||
value: model.chat.systemPrompt
|
value: model.chat.systemPrompt
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
prompts.splice(prompts.length - 3, 0, ...systemPrompts);
|
||||||
|
|
||||||
|
// content check
|
||||||
|
await sensitiveCheck({
|
||||||
|
input: [...systemPrompts, prompt].map((item) => item.value).join('')
|
||||||
|
});
|
||||||
|
|
||||||
// 计算温度
|
// 计算温度
|
||||||
const temperature = (modelConstantsData.maxTemperature * (model.chat.temperature / 10)).toFixed(
|
const temperature = (modelConstantsData.maxTemperature * (model.chat.temperature / 10)).toFixed(
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { resStreamResponse } from '@/service/utils/chat';
|
|||||||
import { searchKb } from '@/service/plugins/searchKb';
|
import { searchKb } from '@/service/plugins/searchKb';
|
||||||
import { ChatRoleEnum } from '@/constants/chat';
|
import { ChatRoleEnum } from '@/constants/chat';
|
||||||
import { BillTypeEnum } from '@/constants/user';
|
import { BillTypeEnum } from '@/constants/user';
|
||||||
|
import { sensitiveCheck } from '@/service/api/text';
|
||||||
|
|
||||||
/* 发送提示词 */
|
/* 发送提示词 */
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
@ -41,6 +42,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
const modelConstantsData = ChatModelMap[model.chat.chatModel];
|
const modelConstantsData = ChatModelMap[model.chat.chatModel];
|
||||||
|
|
||||||
|
let systemPrompts: {
|
||||||
|
obj: ChatRoleEnum;
|
||||||
|
value: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
// 使用了知识库搜索
|
// 使用了知识库搜索
|
||||||
if (model.chat.relatedKbs.length > 0) {
|
if (model.chat.relatedKbs.length > 0) {
|
||||||
const { code, searchPrompts } = await searchKb({
|
const { code, searchPrompts } = await searchKb({
|
||||||
@ -56,15 +62,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
return res.send(searchPrompts[0]?.value);
|
return res.send(searchPrompts[0]?.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
prompts.splice(prompts.length - 3, 0, ...searchPrompts);
|
systemPrompts = searchPrompts;
|
||||||
} else {
|
} else if (model.chat.systemPrompt) {
|
||||||
// 没有用知识库搜索,仅用系统提示词
|
systemPrompts = [
|
||||||
model.chat.systemPrompt &&
|
{
|
||||||
prompts.splice(prompts.length - 3, 0, {
|
|
||||||
obj: ChatRoleEnum.System,
|
obj: ChatRoleEnum.System,
|
||||||
value: model.chat.systemPrompt
|
value: model.chat.systemPrompt
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
prompts.splice(prompts.length - 3, 0, ...systemPrompts);
|
||||||
|
|
||||||
|
// content check
|
||||||
|
await sensitiveCheck({
|
||||||
|
input: [...systemPrompts, prompts[prompts.length - 1]].map((item) => item.value).join('')
|
||||||
|
});
|
||||||
|
|
||||||
// 计算温度
|
// 计算温度
|
||||||
const temperature = (modelConstantsData.maxTemperature * (model.chat.temperature / 10)).toFixed(
|
const temperature = (modelConstantsData.maxTemperature * (model.chat.temperature / 10)).toFixed(
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { searchKb } from '@/service/plugins/searchKb';
|
|||||||
import { ChatRoleEnum } from '@/constants/chat';
|
import { ChatRoleEnum } from '@/constants/chat';
|
||||||
import { withNextCors } from '@/service/utils/tools';
|
import { withNextCors } from '@/service/utils/tools';
|
||||||
import { BillTypeEnum } from '@/constants/user';
|
import { BillTypeEnum } from '@/constants/user';
|
||||||
|
import { sensitiveCheck } from '@/service/api/text';
|
||||||
|
|
||||||
/* 发送提示词 */
|
/* 发送提示词 */
|
||||||
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
@ -62,13 +63,16 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
|||||||
|
|
||||||
const modelConstantsData = ChatModelMap[model.chat.chatModel];
|
const modelConstantsData = ChatModelMap[model.chat.chatModel];
|
||||||
|
|
||||||
|
let systemPrompts: {
|
||||||
|
obj: ChatRoleEnum;
|
||||||
|
value: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
// 使用了知识库搜索
|
// 使用了知识库搜索
|
||||||
if (model.chat.relatedKbs.length > 0) {
|
if (model.chat.relatedKbs.length > 0) {
|
||||||
const similarity = ModelVectorSearchModeMap[model.chat.searchMode]?.similarity || 0.22;
|
|
||||||
|
|
||||||
const { code, searchPrompts } = await searchKb({
|
const { code, searchPrompts } = await searchKb({
|
||||||
prompts,
|
prompts,
|
||||||
similarity,
|
similarity: ModelVectorSearchModeMap[model.chat.searchMode]?.similarity,
|
||||||
model,
|
model,
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
@ -77,18 +81,29 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
|||||||
if (code === 201) {
|
if (code === 201) {
|
||||||
return isStream
|
return isStream
|
||||||
? res.send(searchPrompts[0]?.value)
|
? res.send(searchPrompts[0]?.value)
|
||||||
: jsonRes(res, { data: searchPrompts[0]?.value });
|
: jsonRes(res, {
|
||||||
}
|
data: searchPrompts[0]?.value,
|
||||||
prompts.splice(prompts.length - 3, 0, ...searchPrompts);
|
message: searchPrompts[0]?.value
|
||||||
} else {
|
|
||||||
// 没有用知识库搜索,仅用系统提示词
|
|
||||||
model.chat.systemPrompt &&
|
|
||||||
prompts.splice(prompts.length - 3, 0, {
|
|
||||||
obj: ChatRoleEnum.System,
|
|
||||||
value: model.chat.systemPrompt
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systemPrompts = searchPrompts;
|
||||||
|
} else if (model.chat.systemPrompt) {
|
||||||
|
systemPrompts = [
|
||||||
|
{
|
||||||
|
obj: ChatRoleEnum.System,
|
||||||
|
value: model.chat.systemPrompt
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
prompts.splice(prompts.length - 3, 0, ...systemPrompts);
|
||||||
|
|
||||||
|
// content check
|
||||||
|
await sensitiveCheck({
|
||||||
|
input: [...systemPrompts, prompts[prompts.length - 1]].map((item) => item.value).join('')
|
||||||
|
});
|
||||||
|
|
||||||
// 计算温度
|
// 计算温度
|
||||||
const temperature = (modelConstantsData.maxTemperature * (model.chat.temperature / 10)).toFixed(
|
const temperature = (modelConstantsData.maxTemperature * (model.chat.temperature / 10)).toFixed(
|
||||||
2
|
2
|
||||||
|
|||||||
48
src/pages/api/openapi/text/sensitiveCheck.ts
Normal file
48
src/pages/api/openapi/text/sensitiveCheck.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import { jsonRes } from '@/service/response';
|
||||||
|
import { authUser, getSystemOpenAiKey } from '@/service/utils/auth';
|
||||||
|
import type { TextPluginRequestParams } from '@/types/plugin';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { axiosConfig } from '@/service/utils/tools';
|
||||||
|
|
||||||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
try {
|
||||||
|
if (process.env.SENSITIVE_CHECK !== '1') {
|
||||||
|
return jsonRes(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
await authUser({ req });
|
||||||
|
|
||||||
|
const { input } = req.body as TextPluginRequestParams;
|
||||||
|
|
||||||
|
const response = await axios({
|
||||||
|
...axiosConfig(getSystemOpenAiKey()),
|
||||||
|
method: 'POST',
|
||||||
|
url: `/moderations`,
|
||||||
|
data: {
|
||||||
|
input
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = (response.data.results?.[0]?.category_scores as Record<string, number>) || {};
|
||||||
|
|
||||||
|
const values = Object.values(data);
|
||||||
|
|
||||||
|
for (const val of values) {
|
||||||
|
if (val > 0.2) {
|
||||||
|
return jsonRes(res, {
|
||||||
|
code: 500,
|
||||||
|
message: '您的内容不合规'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonRes(res);
|
||||||
|
} catch (err) {
|
||||||
|
jsonRes(res, {
|
||||||
|
code: 500,
|
||||||
|
error: err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
110
src/service/api/request.ts
Normal file
110
src/service/api/request.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import axios, { Method, InternalAxiosRequestConfig, AxiosResponse } from 'axios';
|
||||||
|
|
||||||
|
interface ConfigType {
|
||||||
|
headers?: { [key: string]: string };
|
||||||
|
hold?: boolean;
|
||||||
|
}
|
||||||
|
interface ResponseDataType {
|
||||||
|
code: number;
|
||||||
|
message: string;
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求开始
|
||||||
|
*/
|
||||||
|
function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
|
||||||
|
if (config.headers) {
|
||||||
|
config.headers.rootkey = process.env.ROOT_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求成功,检查请求头
|
||||||
|
*/
|
||||||
|
function responseSuccess(response: AxiosResponse<ResponseDataType>) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 响应数据检查
|
||||||
|
*/
|
||||||
|
function checkRes(data: ResponseDataType) {
|
||||||
|
if (data === undefined) {
|
||||||
|
return Promise.reject('服务器异常');
|
||||||
|
} else if (data.code < 200 || data.code >= 400) {
|
||||||
|
return Promise.reject(data);
|
||||||
|
}
|
||||||
|
return data.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应错误
|
||||||
|
*/
|
||||||
|
function responseError(err: any) {
|
||||||
|
if (!err) {
|
||||||
|
return Promise.reject({ message: '未知错误' });
|
||||||
|
}
|
||||||
|
if (typeof err === 'string') {
|
||||||
|
return Promise.reject({ message: err });
|
||||||
|
}
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 创建请求实例 */
|
||||||
|
const instance = axios.create({
|
||||||
|
timeout: 60000, // 超时时间
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 请求拦截 */
|
||||||
|
instance.interceptors.request.use(requestStart, (err) => Promise.reject(err));
|
||||||
|
/* 响应拦截 */
|
||||||
|
instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err));
|
||||||
|
|
||||||
|
function request(url: string, data: any, config: ConfigType, method: Method): any {
|
||||||
|
/* 去空 */
|
||||||
|
for (const key in data) {
|
||||||
|
if (data[key] === null || data[key] === undefined) {
|
||||||
|
delete data[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance
|
||||||
|
.request({
|
||||||
|
baseURL: `http://localhost:${process.env.PORT || 3000}/api`,
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
data: method === 'GET' ? null : data,
|
||||||
|
params: method === 'GET' ? data : null, // get请求不携带data,params放在url上
|
||||||
|
...config // 用户自定义配置,可以覆盖前面的配置
|
||||||
|
})
|
||||||
|
.then((res) => checkRes(res.data))
|
||||||
|
.catch((err) => responseError(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api请求方式
|
||||||
|
* @param {String} url
|
||||||
|
* @param {Any} params
|
||||||
|
* @param {Object} config
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function GET<T>(url: string, params = {}, config: ConfigType = {}): Promise<T> {
|
||||||
|
return request(url, params, config, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function POST<T>(url: string, data = {}, config: ConfigType = {}): Promise<T> {
|
||||||
|
return request(url, data, config, 'POST');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PUT<T>(url: string, data = {}, config: ConfigType = {}): Promise<T> {
|
||||||
|
return request(url, data, config, 'PUT');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DELETE<T>(url: string, config: ConfigType = {}): Promise<T> {
|
||||||
|
return request(url, {}, config, 'DELETE');
|
||||||
|
}
|
||||||
5
src/service/api/text.ts
Normal file
5
src/service/api/text.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { POST } from './request';
|
||||||
|
import type { TextPluginRequestParams } from '@/types/plugin';
|
||||||
|
|
||||||
|
export const sensitiveCheck = (data: TextPluginRequestParams) =>
|
||||||
|
POST('/openapi/text/sensitiveCheck', data);
|
||||||
@ -66,8 +66,8 @@ export const authUser = async ({
|
|||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const parseRootKey = async (rootKey?: string, userId?: string) => {
|
const parseRootKey = async (rootKey?: string, userId = '') => {
|
||||||
if (!rootKey || !userId || !process.env.ROOT_KEY || rootKey !== process.env.ROOT_KEY) {
|
if (!rootKey || !process.env.ROOT_KEY || rootKey !== process.env.ROOT_KEY) {
|
||||||
return Promise.reject(ERROR_ENUM.unAuthorization);
|
return Promise.reject(ERROR_ENUM.unAuthorization);
|
||||||
}
|
}
|
||||||
return userId;
|
return userId;
|
||||||
@ -104,7 +104,7 @@ export const authUser = async ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* random get openai api key */
|
/* random get openai api key */
|
||||||
export const getOpenAiKey = () => {
|
export const getSystemOpenAiKey = () => {
|
||||||
// 纯字符串类型
|
// 纯字符串类型
|
||||||
const keys = process.env.OPENAIKEY?.split(',') || [];
|
const keys = process.env.OPENAIKEY?.split(',') || [];
|
||||||
const i = Math.floor(Math.random() * keys.length);
|
const i = Math.floor(Math.random() * keys.length);
|
||||||
@ -129,7 +129,7 @@ export const getApiKey = async ({
|
|||||||
const keyMap = {
|
const keyMap = {
|
||||||
[OpenAiChatEnum.GPT35]: {
|
[OpenAiChatEnum.GPT35]: {
|
||||||
userOpenAiKey: user.openaiKey || '',
|
userOpenAiKey: user.openaiKey || '',
|
||||||
systemAuthKey: getOpenAiKey() as string
|
systemAuthKey: getSystemOpenAiKey() as string
|
||||||
},
|
},
|
||||||
[OpenAiChatEnum.GPT4]: {
|
[OpenAiChatEnum.GPT4]: {
|
||||||
userOpenAiKey: user.openaiKey || '',
|
userOpenAiKey: user.openaiKey || '',
|
||||||
|
|||||||
@ -7,16 +7,14 @@ import { adaptChatItem_openAI } from '@/utils/chat/openai';
|
|||||||
import { modelToolMap } from '@/utils/chat';
|
import { modelToolMap } from '@/utils/chat';
|
||||||
import { ChatCompletionType, ChatContextFilter, StreamResponseType } from './index';
|
import { ChatCompletionType, ChatContextFilter, StreamResponseType } from './index';
|
||||||
import { ChatRoleEnum } from '@/constants/chat';
|
import { ChatRoleEnum } from '@/constants/chat';
|
||||||
import { getOpenAiKey } from '../auth';
|
import { getSystemOpenAiKey } from '../auth';
|
||||||
|
|
||||||
export const getOpenAIApi = (apiKey: string) => {
|
export const getOpenAIApi = () =>
|
||||||
const configuration = new Configuration({
|
new OpenAIApi(
|
||||||
apiKey,
|
new Configuration({
|
||||||
basePath: process.env.OPENAI_BASE_URL
|
basePath: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'
|
||||||
});
|
})
|
||||||
|
);
|
||||||
return new OpenAIApi(configuration);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 获取向量 */
|
/* 获取向量 */
|
||||||
export const openaiCreateEmbedding = async ({
|
export const openaiCreateEmbedding = async ({
|
||||||
@ -28,10 +26,10 @@ export const openaiCreateEmbedding = async ({
|
|||||||
userId: string;
|
userId: string;
|
||||||
textArr: string[];
|
textArr: string[];
|
||||||
}) => {
|
}) => {
|
||||||
const systemAuthKey = getOpenAiKey();
|
const systemAuthKey = getSystemOpenAiKey();
|
||||||
|
|
||||||
// 获取 chatAPI
|
// 获取 chatAPI
|
||||||
const chatAPI = getOpenAIApi(userOpenAiKey || systemAuthKey);
|
const chatAPI = getOpenAIApi();
|
||||||
|
|
||||||
// 把输入的内容转成向量
|
// 把输入的内容转成向量
|
||||||
const res = await chatAPI
|
const res = await chatAPI
|
||||||
@ -42,7 +40,7 @@ export const openaiCreateEmbedding = async ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
...axiosConfig()
|
...axiosConfig(userOpenAiKey || systemAuthKey)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((res) => ({
|
.then((res) => ({
|
||||||
@ -78,7 +76,7 @@ export const chatResponse = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const adaptMessages = adaptChatItem_openAI({ messages: filterMessages });
|
const adaptMessages = adaptChatItem_openAI({ messages: filterMessages });
|
||||||
const chatAPI = getOpenAIApi(apiKey);
|
const chatAPI = getOpenAIApi();
|
||||||
|
|
||||||
const response = await chatAPI.createChatCompletion(
|
const response = await chatAPI.createChatCompletion(
|
||||||
{
|
{
|
||||||
@ -93,7 +91,7 @@ export const chatResponse = async ({
|
|||||||
{
|
{
|
||||||
timeout: stream ? 60000 : 240000,
|
timeout: stream ? 60000 : 240000,
|
||||||
responseType: stream ? 'stream' : 'json',
|
responseType: stream ? 'stream' : 'json',
|
||||||
...axiosConfig()
|
...axiosConfig(apiKey)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -31,9 +31,11 @@ export const clearCookie = (res: NextApiResponse) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* openai axios config */
|
/* openai axios config */
|
||||||
export const axiosConfig = () => ({
|
export const axiosConfig = (apikey: string) => ({
|
||||||
|
baseURL: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1',
|
||||||
httpsAgent: global.httpsAgent,
|
httpsAgent: global.httpsAgent,
|
||||||
headers: {
|
headers: {
|
||||||
|
Authorization: `Bearer ${apikey}`,
|
||||||
auth: process.env.OPENAI_BASE_URL_AUTH || ''
|
auth: process.env.OPENAI_BASE_URL_AUTH || ''
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
20
src/types/plugin.d.ts
vendored
20
src/types/plugin.d.ts
vendored
@ -1,10 +1,12 @@
|
|||||||
import type { kbSchema } from './mongoSchema';
|
import type { kbSchema } from './mongoSchema';
|
||||||
|
import { PluginTypeEnum } from '@/constants/plugin';
|
||||||
|
|
||||||
/* kb type */
|
/* kb type */
|
||||||
export interface KbItemType extends kbSchema {
|
export interface KbItemType extends kbSchema {
|
||||||
totalData: number;
|
totalData: number;
|
||||||
tags: string;
|
tags: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KbDataItemType {
|
export interface KbDataItemType {
|
||||||
id: string;
|
id: string;
|
||||||
status: 'waiting' | 'ready';
|
status: 'waiting' | 'ready';
|
||||||
@ -13,3 +15,21 @@ export interface KbDataItemType {
|
|||||||
kbId: string;
|
kbId: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* plugin */
|
||||||
|
export interface PluginConfig {
|
||||||
|
name: string;
|
||||||
|
desc: string;
|
||||||
|
url: string;
|
||||||
|
category: `${PluginTypeEnum}`;
|
||||||
|
uniPrice: 22; // 1k token
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: '';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TextPluginRequestParams = {
|
||||||
|
input: string;
|
||||||
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user