diff --git a/Makefile b/Makefile index 5f2c7d8f2..fac5d9045 100644 --- a/Makefile +++ b/Makefile @@ -34,13 +34,13 @@ run: ## Run a dev service from host. .PHONY: docker-build docker-build: ## Build docker image with the desktop-frontend. - docker build -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest . --network host --build-arg HTTP_PROXY=http://127.0.0.1:7890 --build-arg HTTPS_PROXY=http://127.0.0.1:7890 + docker build -t c121914yu/fast-gpt:latest . --network host --build-arg HTTP_PROXY=http://127.0.0.1:7890 --build-arg HTTPS_PROXY=http://127.0.0.1:7890 ##@ Deployment .PHONY: docker-run docker-run: ## Push docker image. - docker run -d -p 8008:3000 --name fastgpt -v /web_project/yjl/fastgpt/logs:/app/.next/logs registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest + docker run -d -p 8008:3000 --name fastgpt -v /web_project/yjl/fastgpt/logs:/app/.next/logs c121914yu/fast-gpt:latest #TODO: add support of docker push diff --git a/docs/deploy/fastgpt/docker-compose.yml b/docs/deploy/fastgpt/docker-compose.yml index 48aa2f164..d42162449 100644 --- a/docs/deploy/fastgpt/docker-compose.yml +++ b/docs/deploy/fastgpt/docker-compose.yml @@ -31,7 +31,9 @@ services: - /root/fastgpt/mongo/logs:/var/log/mongodb - /etc/localtime:/etc/localtime:ro fastgpt: - image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest + image: ghcr.io/c121914yu/fast-gpt:latest # github + # image: c121914yu/fast-gpt:latest # docker hub + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云 network_mode: host restart: always container_name: fastgpt diff --git a/public/docs/chatProblem.md b/public/docs/chatProblem.md index a0582206c..6a14c5d25 100644 --- a/public/docs/chatProblem.md +++ b/public/docs/chatProblem.md @@ -11,10 +11,10 @@ 移动端:点击对话头像,可以选择复制或删除该条内容。 **价格表** -如果使用了自己的 Api Key,不会计费。可以在账号页,看到详细账单。 +如果使用了自己的 Api Key,网页上 openai 模型聊天不会计费。可以在账号页,看到详细账单。 | 计费项 | 价格: 元/ 1K tokens(包含上下文)| | --- | --- | -| 知识库 - 索引 | 免费 | +| 知识库 - 索引 | 0.001 | | chatgpt - 对话 | 0.025 | | gpt4 - 对话 | 0.5 | | 文件拆分 | 0.025 | diff --git a/public/docs/intro.md b/public/docs/intro.md index d1253e29b..49bb21015 100644 --- a/public/docs/intro.md +++ b/public/docs/intro.md @@ -15,10 +15,10 @@ FastGpt 项目完全开源,可随意私有化部署,去除平台风险忧虑 ### 价格表 -如果使用了自己的 Api Key,不会计费。可以在账号页,看到详细账单。 +如果使用了自己的 Api Key,网页上 openai 模型聊天不会计费。可以在账号页,看到详细账单。 | 计费项 | 价格: 元/ 1K tokens(包含上下文)| | --- | --- | -| 知识库 - 索引 | 免费 | +| 知识库 - 索引 | 0.001 | | chatgpt - 对话 | 0.025 | | gpt4 - 对话 | 0.5 | | 文件拆分 | 0.025 | diff --git a/src/constants/model.ts b/src/constants/model.ts index 6909b595b..969609fb5 100644 --- a/src/constants/model.ts +++ b/src/constants/model.ts @@ -3,6 +3,7 @@ import type { ShareChatEditType } from '@/types/model'; import type { ModelSchema } from '@/types/mongoSchema'; export const embeddingModel = 'text-embedding-ada-002'; +export const embeddingPrice = 0.1; export type EmbeddingModelType = 'text-embedding-ada-002'; export enum OpenAiChatEnum { diff --git a/src/pages/api/openapi/plugin/openaiEmbedding.ts b/src/pages/api/openapi/plugin/openaiEmbedding.ts index 4923c723c..8c746dd02 100644 --- a/src/pages/api/openapi/plugin/openaiEmbedding.ts +++ b/src/pages/api/openapi/plugin/openaiEmbedding.ts @@ -1,6 +1,6 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { jsonRes } from '@/service/response'; -import { authUser, getSystemOpenAiKey } from '@/service/utils/auth'; +import { authUser, getApiKey } from '@/service/utils/auth'; import { withNextCors } from '@/service/utils/tools'; import { getOpenAIApi } from '@/service/utils/chat/openai'; import { embeddingModel } from '@/constants/model'; @@ -24,7 +24,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex } jsonRes(res, { - data: await openaiEmbedding({ userId, input, type }) + data: await openaiEmbedding({ userId, input, type, mustPay: true }) }); } catch (err) { console.log(err); @@ -38,9 +38,15 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex export async function openaiEmbedding({ userId, input, + mustPay = false, type = 'chat' -}: { userId: string } & Props) { - const apiKey = getSystemOpenAiKey(type); +}: { userId: string; mustPay?: boolean } & Props) { + const { userOpenAiKey, systemAuthKey } = await getApiKey({ + model: 'gpt-3.5-turbo', + userId, + mustPay, + type + }); // 获取 chatAPI const chatAPI = getOpenAIApi(); @@ -54,7 +60,7 @@ export async function openaiEmbedding({ }, { timeout: 60000, - ...axiosConfig(apiKey) + ...axiosConfig(userOpenAiKey || systemAuthKey) } ) .then((res) => ({ @@ -63,7 +69,7 @@ export async function openaiEmbedding({ })); pushGenerateVectorBill({ - isPay: false, + isPay: !userOpenAiKey, userId, text: input.join(''), tokenLen: result.tokenLen diff --git a/src/pages/kb/components/SelectFileModal.tsx b/src/pages/kb/components/SelectFileModal.tsx index 9ec490eb9..9db2919d2 100644 --- a/src/pages/kb/components/SelectFileModal.tsx +++ b/src/pages/kb/components/SelectFileModal.tsx @@ -22,20 +22,22 @@ import Radio from '@/components/Radio'; import { splitText_token } from '@/utils/file'; import { TrainingModeEnum } from '@/constants/plugin'; import { getErrText } from '@/utils/tools'; +import { ChatModelMap, OpenAiChatEnum, embeddingPrice } from '@/constants/model'; +import { formatPrice } from '@/utils/user'; const fileExtension = '.txt,.doc,.docx,.pdf,.md'; const modeMap = { [TrainingModeEnum.qa]: { - maxLen: 2800, - slideLen: 800, - price: 4, + maxLen: 2600, + slideLen: 700, + price: ChatModelMap[OpenAiChatEnum.GPT35].price, isPrompt: true }, [TrainingModeEnum.index]: { - maxLen: 800, + maxLen: 700, slideLen: 300, - price: 0.4, + price: embeddingPrice, isPrompt: false } }; @@ -58,18 +60,18 @@ const SelectFileModal = ({ { filename: '文本1', text: '' } ]); const [splitRes, setSplitRes] = useState<{ - tokens: number; + price: number; chunks: { filename: string; value: string }[]; successChunks: number; }>({ - tokens: 0, + price: 0, successChunks: 0, chunks: [] }); const { openConfirm, ConfirmChild } = useConfirm({ content: `确认导入该文件,需要一定时间进行拆解,该任务无法终止!QA 拆分仅能使用余额,如果余额不足,未完成的任务会被直接清除。一共 ${ splitRes.chunks.length - } 组。${splitRes.tokens ? `大约 ${splitRes.tokens} 个tokens。` : ''}` + } 组。${splitRes.price ? `大约 ${splitRes.price} 元。` : ''}` }); const onSelectFile = useCallback( @@ -166,8 +168,16 @@ const SelectFileModal = ({ })) .filter((item) => item.tokens > 0); + let price = formatPrice( + splitRes.reduce((sum, item) => sum + item.tokens, 0) * modeMap[mode].price + ); + + if (mode === 'qa') { + price *= 1.2; + } + setSplitRes({ - tokens: splitRes.reduce((sum, item) => sum + item.tokens, 0), + price, chunks: splitRes .map((item) => item.chunks.map((chunk) => ({ diff --git a/src/pages/number/components/PayModal.tsx b/src/pages/number/components/PayModal.tsx index f33ed6f79..7d28360ef 100644 --- a/src/pages/number/components/PayModal.tsx +++ b/src/pages/number/components/PayModal.tsx @@ -17,6 +17,7 @@ import { useToast } from '@/hooks/useToast'; import { useQuery } from '@tanstack/react-query'; import { useRouter } from 'next/router'; import { getErrText } from '@/utils/tools'; +import Markdown from '@/components/Markdown'; const PayModal = ({ onClose }: { onClose: () => void }) => { const router = useRouter(); @@ -78,7 +79,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => { }} > - + 充值 {!payId && } @@ -86,7 +87,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => { {!payId && ( <> - {[5, 10, 20, 50].map((item) => ( + {[10, 20, 50, 100].map((item) => ( ))} - + void }) => { }} > + )} {/* 付费二维码 */} diff --git a/src/service/events/generateVector.ts b/src/service/events/generateVector.ts index f4728a532..5a22e7b47 100644 --- a/src/service/events/generateVector.ts +++ b/src/service/events/generateVector.ts @@ -82,7 +82,8 @@ export async function generateVector(): Promise { const vectors = await openaiEmbedding({ input: dataItems.map((item) => item.q), userId, - type: 'training' + type: 'training', + mustPay: true }); // 生成结果插入到 pg diff --git a/src/service/events/pushBill.ts b/src/service/events/pushBill.ts index d6b070077..52f4171d1 100644 --- a/src/service/events/pushBill.ts +++ b/src/service/events/pushBill.ts @@ -1,5 +1,11 @@ import { connectToDatabase, Bill, User, ShareChat } from '../mongo'; -import { ChatModelMap, OpenAiChatEnum, ChatModelType, embeddingModel } from '@/constants/model'; +import { + ChatModelMap, + OpenAiChatEnum, + ChatModelType, + embeddingModel, + embeddingPrice +} from '@/constants/model'; import { BillTypeEnum } from '@/constants/user'; export const pushChatBill = async ({ @@ -145,11 +151,9 @@ export const pushGenerateVectorBill = async ({ await connectToDatabase(); try { - const unitPrice = 0.4; // 计算价格. 至少为1 - const price = 0; - // let price = unitPrice * tokenLen; - // price = price > 1 ? price : 1; + let price = embeddingPrice * tokenLen; + price = price > 1 ? price : 1; // 插入 Bill 记录 const res = await Bill.create({ diff --git a/src/service/models/user.ts b/src/service/models/user.ts index cebe58ace..c5b50ea6f 100644 --- a/src/service/models/user.ts +++ b/src/service/models/user.ts @@ -28,7 +28,7 @@ const UserSchema = new Schema({ balance: { // 平台余额,不可提现 type: Number, - default: 0.5 * PRICE_SCALE + default: 2 * PRICE_SCALE }, inviterId: { // 谁邀请注册的