fix: conflict

This commit is contained in:
archer
2023-03-24 12:55:51 +08:00
15 changed files with 226 additions and 24 deletions

View File

@@ -8,11 +8,12 @@ export const introPage = `
[Git 仓库](https://github.com/c121914yu/FastGPT)
时间比较赶,介绍没来得及完善,先直接上怎么使用:
### 快速开始
1. 使用邮箱注册账号。
2. 进入账号页面,添加关联账号,目前只有 openai 的账号可以添加,直接去 openai 官网,把 API Key 粘贴过来。
3. 进入模型页,创建一个模型,建议直接用 ChatGPT。
4. 在模型列表点击【对话】,即可使用 API 进行聊天
3. 如果填写了自己的 openai 账号,使用时会直接用你的账号。如果没有填写,需要付费使用平台的账号。
4. 进入模型页,创建一个模型,建议直接用 ChatGPT
5. 在模型列表点击【对话】,即可使用 API 进行聊天。
### 模型配置

View File

@@ -16,7 +16,7 @@ export type ModelConstantsData = {
price: number; // 多少钱 / 1字单位: 0.00001元
};
export const ModelList: ModelConstantsData[] = [
export const modelList: ModelConstantsData[] = [
{
serviceCompany: 'openai',
name: 'chatGPT',

View File

@@ -8,7 +8,7 @@ import { ChatItemType } from '@/types/chat';
import { jsonRes } from '@/service/response';
import type { ModelSchema } from '@/types/mongoSchema';
import { PassThrough } from 'stream';
import { ModelList } from '@/constants/model';
import { modelList } from '@/constants/model';
import { pushBill } from '@/service/events/bill';
/* 发送提示词 */
@@ -74,7 +74,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
// 计算温度
const modelConstantsData = ModelList.find((item) => item.model === model.service.modelName);
const modelConstantsData = modelList.find((item) => item.model === model.service.modelName);
if (!modelConstantsData) {
throw new Error('模型异常');
}

View File

@@ -5,7 +5,7 @@ import { connectToDatabase } from '@/service/mongo';
import { getOpenAIApi, authChat } from '@/service/utils/chat';
import { ChatItemType } from '@/types/chat';
import { httpsAgent } from '@/service/utils/tools';
import { ModelList } from '@/constants/model';
import { modelList } from '@/constants/model';
import { pushBill } from '@/service/events/bill';
/* 发送提示词 */
@@ -31,7 +31,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const formatPrompts = prompt.map((item) => `${item.value}\n\n###\n\n`).join('');
// 计算温度
const modelConstantsData = ModelList.find((item) => item.model === model.service.modelName);
const modelConstantsData = modelList.find((item) => item.model === model.service.modelName);
if (!modelConstantsData) {
throw new Error('模型异常');
}

View File

@@ -3,7 +3,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase } from '@/service/mongo';
import { authToken } from '@/service/utils/tools';
import { ModelStatusEnum, ModelList, ChatModelNameEnum } from '@/constants/model';
import { ModelStatusEnum, modelList, ChatModelNameEnum } from '@/constants/model';
import { Model } from '@/service/models/model';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
// 凭证校验
const userId = await authToken(authorization);
const modelItem = ModelList.find((item) => item.model === serviceModelName);
const modelItem = modelList.find((item) => item.model === serviceModelName);
if (!modelItem) {
throw new Error('模型不存在');

View File

@@ -0,0 +1,103 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Data } from '@/service/mongo';
import { getOpenAIApi } from '@/service/utils/chat';
import { httpsAgent, getOpenApiKey } from '@/service/utils/tools';
import type { ChatCompletionRequestMessage, CreateChatCompletionResponse } from 'openai';
import fs from 'fs';
import { v4 } from 'uuid';
/* 定时删除那些不活跃的内容 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const systemPrompt: ChatCompletionRequestMessage = {
role: 'system',
content: `总结助手。我会向你发送一段长文本请从中总结出10个以上问题和答案并转化成中文请按以下格式返回
"Q1:"
"A1:"
######
"Q2:"
"A2:"
######
`
};
try {
const { text } = req.body as { text: string };
const { authorization } = req.headers;
const replaceText = text.replace(/\n/g, ' ');
await connectToDatabase();
const { userId, userApiKey, systemKey } = await getOpenApiKey(authorization);
const chatAPI = getOpenAIApi(userApiKey || systemKey);
const docId = v4();
const queue: {
requestPrompts: ChatCompletionRequestMessage;
temperature: number;
}[] = [
{
requestPrompts: {
role: 'user',
content: `跟 AI ChatGPT 聊了 11 个我过去关心的话题\n原创 刘飞Lufy 刘言飞语 2022-12-05 21:40 发表于浙江\n收录于合集\n#行业观察\n33\n个\n#AIGC\n11\n个\n\n\n\n\n这几天沉浸式体验 ChatGPTOpenAI发布的一款人工智能对话引擎突发奇想想知道它对我曾经聊的话题都怎么看。于是我用一些过去公众号发过的文章主题跟它进行了一轮对话。\n\n以下是我们聊天的内容原始记录没有做文字篡改为方便没有用截图做了文本排版。各位可以直观体会下它的智能程度。\n\n\n本文内容都是在以上这样的界面里完成的\n\n\n——\n\n参考微信搜索的未来\n\n刘飞\n\n微信搜索现在的使用量大吗\n\nChatGPT\n\n微信搜索是一项非常流行的功能它可以帮助用户快速搜索到想要的信息。由于微信是中国最流行的社交软件微信搜索的使用量也非常大。根据官方数据截至2022年微信的日活跃用户数量已经超过10亿其中每天都会有大量用户使用微信搜索功能搜索各种信息。因此微信搜索的使用量非常大。\n\n刘飞\n\n跟百度搜索比呢\n\nChatGPT\n\n微信搜索和百度搜索都是帮助用户快速搜索到想要的信息的工具。但是两者有着明显的不同。\n\n首先微信搜索和百度搜索的使用场景不同。微信搜索主要用于社交场景因此它更多地用于搜索好友、群聊、文章等信息而百度搜索则更加注重为用户提供更丰富的信息因此它更多地用于搜索各种知识信息和新闻信息。\n\n\n其次微信搜索和百度搜索的搜索结果也不同。微信搜索的搜索结果主要是来自用户自己的微信聊天记录和朋友圈发布的信息而百度搜索的搜索结果则是来自互联网上的各种信息包括网站、新闻、论坛等。因此微信搜索的搜索结果更加个性化而百度搜索的搜索结果则更加全面。\n\n总之微信搜索和百度搜索都是帮助用户快速搜索到想要的信息的工具但是它们在使用场景、搜索结果等方面存在明显的差异。\n\n刘飞\n\n那字节跳动的搜索跟它们相比呢\n\nChatGPT\n\n字节跳动的搜索也是一款帮助用户快速搜索到想要的信息的工具。但是字节跳动的搜索主要是针对短视频内容而设计的因此它的搜索结果主要是来自抖音、头条等短视频平台上的视频内容。与微信搜索和百度搜索相比字节跳动的搜索更加专注于短视频内容并且搜索结果也更加丰富多样。\n\n——\n\n\n参考我们离财务自由的距离\n\n\n刘飞\n\n怎样才算财务自由\n\nChatGPT\n\n财务自由是指一个人在不必工作的情况下能够通过自己的财富维持生活的质量和生活水平。通常情况下一个人可以通过节约开支、投资理财等方式来实现财务自由。\n\n具体来说要达到财务自由一个人需要符合以下几个条件\n\n\n实现收入和支出平衡。要想实现财务自由首先需要通过节约开支来控制支出并通过提高收入来提升生活水平。\n\n\n建立良好的投资理财计划。要想实现财务自由需要通过投资理财来增加财富的增长速度并且要有一个完善的理财计划来指导投资决策。\n\n\n控制风险。在投资理财的过程中要尽量降低风险并通过多样化投资来降低投资的风险。`
},
temperature: 0.5
}
];
/**
* 生成QA
*/
const generateQA = async () => {
const prompt = queue.pop();
if (!prompt) return;
try {
const response = await chatAPI.createChatCompletion(
{
model: 'gpt-3.5-turbo',
temperature: prompt.temperature,
n: 1,
messages: [systemPrompt, prompt.requestPrompts]
},
{
timeout: 60000,
httpsAgent
}
);
return response.data.choices[0].message?.content;
} catch (error) {
console.log('部分训练出现错误');
}
};
// 格式化文本长度
// for (let i = 0; i <= replaceText.length / 2048; i++) {
// const slicePrompts: ChatCompletionRequestMessage = {
// role: 'user',
// content: replaceText.slice(i * 2048, (i + 1) * 2048)
// };
// [0.1, 0.3, 0.5, 0.7, 0.9].forEach((temperature) => {
// queue.push({
// temperature,
// requestPrompts: slicePrompts
// });
// });
// }
jsonRes(res, {
data: await generateQA()
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}
/**
* 检查文本是否按格式返回
*/
function splitText(text: string) {}

View File

@@ -18,7 +18,7 @@ import {
import { useForm } from 'react-hook-form';
import { postCreateModel } from '@/api/model';
import type { ModelSchema } from '@/types/mongoSchema';
import { ModelList } from '@/constants/model';
import { modelList } from '@/constants/model';
import { formatPrice } from '@/utils/user';
interface CreateFormType {
@@ -45,7 +45,7 @@ const CreateModel = ({
formState: { errors }
} = useForm<CreateFormType>({
defaultValues: {
serviceModelName: ModelList[0].model
serviceModelName: modelList[0].model
}
});
@@ -98,7 +98,7 @@ const CreateModel = ({
required: '底层模型不能为空'
})}
>
{ModelList.map((item) => (
{modelList.map((item) => (
<option key={item.model} value={item.model}>
{item.name}
</option>
@@ -110,7 +110,7 @@ const CreateModel = ({
</FormControl>
<Box mt={3} textAlign={'center'} fontSize={'sm'} color={'blackAlpha.600'}>
{formatPrice(
ModelList.find((item) => item.model === getValues('serviceModelName'))?.price || 0
modelList.find((item) => item.model === getValues('serviceModelName'))?.price || 0
) * 1000}
/1000()
</Box>

View File

@@ -13,7 +13,7 @@ import { Card, Box, Flex, Button, Tag, Grid } from '@chakra-ui/react';
import { useToast } from '@/hooks/useToast';
import { useConfirm } from '@/hooks/useConfirm';
import { useForm } from 'react-hook-form';
import { formatModelStatus, ModelStatusEnum, ModelList, defaultModel } from '@/constants/model';
import { formatModelStatus, ModelStatusEnum, modelList, defaultModel } from '@/constants/model';
import { useGlobalStore } from '@/store/global';
import { useScreen } from '@/hooks/useScreen';
import ModelEditForm from './components/ModelEditForm';
@@ -38,7 +38,7 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
});
const canTrain = useMemo(() => {
const openai = ModelList.find((item) => item.model === model?.service.modelName);
const openai = modelList.find((item) => item.model === model?.service.modelName);
return openai && openai.trainName;
}, [model]);

View File

@@ -14,7 +14,7 @@ import { useUserStore } from '@/store/user';
const CreateModel = dynamic(() => import('./components/CreateModel'));
const ModelList = () => {
const modelList = () => {
const { toast } = useToast();
const { isPc } = useScreen();
const router = useRouter();
@@ -87,4 +87,4 @@ const ModelList = () => {
);
};
export default ModelList;
export default modelList;

View File

@@ -10,12 +10,21 @@ import {
Button,
Input,
Box,
Grid
Grid,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
TableContainer
} from '@chakra-ui/react';
import { getPayCode, checkPayResult } from '@/api/user';
import { useToast } from '@/hooks/useToast';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { modelList } from '@/constants/model';
import { formatPrice } from '../../../utils/user';
const PayModal = ({ onClose }: { onClose: () => void }) => {
const router = useRouter();
@@ -82,9 +91,28 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
<ModalHeader></ModalHeader>
{!payId && <ModalCloseButton />}
<ModalBody>
<ModalBody py={0}>
{!payId && (
<>
{/* 价格表 */}
<TableContainer mb={4}>
<Table>
<Thead>
<Tr>
<Th></Th>
<Th>(/1000)</Th>
</Tr>
</Thead>
<Tbody>
{modelList.map((item, i) => (
<Tr key={item.model}>
<Td>{item.name}</Td>
<Td>{formatPrice(item.price) * 1000}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
<Grid gridTemplateColumns={'repeat(4,1fr)'} gridGap={5} mb={4}>
{[5, 10, 20, 50].map((item) => (
<Button

View File

@@ -123,6 +123,9 @@ const NumberSetting = () => {
</Button>
</Flex>
<Box fontSize={'xs'} color={'blackAlpha.500'}>
openai
</Box>
</Box>
</Card>
<Card mt={6} px={6} py={4}>

View File

@@ -1,5 +1,5 @@
import { connectToDatabase, Bill, User } from '../mongo';
import { ModelList } from '@/constants/model';
import { modelList } from '@/constants/model';
export const pushBill = async ({
modelName,
@@ -12,16 +12,23 @@ export const pushBill = async ({
chatId: string;
textLen: number;
}) => {
await connectToDatabase();
const modelItem = modelList.find((item) => item.model === modelName);
if (!modelItem) return;
let billId;
try {
await connectToDatabase();
const modelItem = ModelList.find((item) => item.model === modelName);
const modelItem = modelList.find((item) => item.model === modelName);
if (!modelItem) return;
const price = modelItem.price * textLen;
let billId;
try {
// 插入 Bill 记录
const res = await Bill.create({

View File

@@ -0,0 +1,27 @@
import { Schema, model, models } from 'mongoose';
const DataSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
docId: {
type: String,
required: true
},
createTime: {
type: Date,
default: () => new Date()
},
q: {
type: String,
required: true
},
a: {
type: String,
required: true
}
});
export const Data = models['data'] || model('data', DataSchema);

View File

@@ -32,3 +32,4 @@ export * from './models/user';
export * from './models/training';
export * from './models/bill';
export * from './models/pay';
export * from './models/data';

View File

@@ -2,6 +2,8 @@ import crypto from 'crypto';
import jwt from 'jsonwebtoken';
import { User } from '../models/user';
import tunnel from 'tunnel';
import type { UserModelSchema } from '@/types/mongoSchema';
import { formatPrice } from '@/utils/user';
/* 密码加密 */
export const hashPassword = (psw: string) => {
@@ -49,7 +51,37 @@ export const getUserOpenaiKey = async (userId: string) => {
return Promise.reject('缺少ApiKey, 无法请求');
}
return Promise.resolve(userApiKey);
return Promise.resolve(userApiKey as string);
};
/* 获取key如果没有就用平台的用平台记得加账单 */
export const getOpenApiKey = async (authorization?: string) => {
const userId = await authToken(authorization);
const user = await User.findById<UserModelSchema>(userId);
if (!user) return Promise.reject('用户不存在');
const userApiKey = user.accounts?.find((item: any) => item.type === 'openai')?.value;
// 有自己的key 直接使用
if (userApiKey) {
return {
userId,
userApiKey: await getUserOpenaiKey(userId),
systemKey: ''
};
}
// 余额校验
if (formatPrice(user.balance) <= 0) {
return Promise.reject('该账号余额不足');
}
return {
userId,
userApiKey: '',
systemKey: process.env.OPENAIKEY as string
};
};
/* 代理 */