mirror of
https://github.com/coaidev/coai.git
synced 2025-05-26 08:20:13 +09:00
fix generation context and prompt
This commit is contained in:
parent
5bb1fca7eb
commit
f57b5710a0
@ -59,16 +59,14 @@
|
|||||||
.message-box {
|
.message-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: max-content;
|
height: max-content;
|
||||||
|
min-height: 120px;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
border: 1px solid hsl(var(--border));
|
border: 1px solid hsl(var(--border));
|
||||||
color: hsl(var(--text-secondary));
|
color: hsl(var(--text-secondary));
|
||||||
padding: 0.6rem 1rem;
|
padding: 0.6rem 1rem;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: pre-wrap;
|
text-overflow: ellipsis;
|
||||||
overflow-wrap: break-word;
|
|
||||||
word-wrap: break-word;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.quota-box {
|
.quota-box {
|
||||||
|
@ -100,7 +100,7 @@ const resources = {
|
|||||||
"free-price": "Free Forever",
|
"free-price": "Free Forever",
|
||||||
pro: "Pro",
|
pro: "Pro",
|
||||||
"pro-price": "8 CNY/Month",
|
"pro-price": "8 CNY/Month",
|
||||||
"free-gpt3": "GPT-3.5 Free Forever",
|
"free-gpt3": "GPT-3.5 (16k) Free Forever",
|
||||||
"free-dalle": "5 free quotas per day",
|
"free-dalle": "5 free quotas per day",
|
||||||
"free-web": "web searching feature",
|
"free-web": "web searching feature",
|
||||||
"free-conversation": "conversation storage",
|
"free-conversation": "conversation storage",
|
||||||
@ -243,7 +243,7 @@ const resources = {
|
|||||||
"free-price": "永久免费",
|
"free-price": "永久免费",
|
||||||
pro: "专业版",
|
pro: "专业版",
|
||||||
"pro-price": "8 元/月",
|
"pro-price": "8 元/月",
|
||||||
"free-gpt3": "GPT-3.5 永久免费",
|
"free-gpt3": "GPT-3.5 (16k) 永久免费",
|
||||||
"free-dalle": "每日 5 次免费绘图",
|
"free-dalle": "每日 5 次免费绘图",
|
||||||
"free-web": "联网搜索功能",
|
"free-web": "联网搜索功能",
|
||||||
"free-conversation": "对话存储记录",
|
"free-conversation": "对话存储记录",
|
||||||
@ -391,7 +391,7 @@ const resources = {
|
|||||||
"free-price": "Бесплатно навсегда",
|
"free-price": "Бесплатно навсегда",
|
||||||
pro: "Профессиональный",
|
pro: "Профессиональный",
|
||||||
"pro-price": "8 CNY/месяц",
|
"pro-price": "8 CNY/месяц",
|
||||||
"free-gpt3": "GPT-3.5 бесплатно навсегда",
|
"free-gpt3": "GPT-3.5 (16k) бесплатно навсегда",
|
||||||
"free-dalle": "5 бесплатных квот в день",
|
"free-dalle": "5 бесплатных квот в день",
|
||||||
"free-web": "веб-поиск",
|
"free-web": "веб-поиск",
|
||||||
"free-conversation": "хранение разговоров",
|
"free-conversation": "хранение разговоров",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import "../assets/generation.less";
|
import "../assets/generation.less";
|
||||||
import { useSelector } from "react-redux";
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
import { selectAuthenticated } from "../store/auth.ts";
|
import { selectAuthenticated } from "../store/auth.ts";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button } from "../components/ui/button.tsx";
|
import { Button } from "../components/ui/button.tsx";
|
||||||
@ -11,7 +11,8 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import SelectGroup from "../components/SelectGroup.tsx";
|
import SelectGroup from "../components/SelectGroup.tsx";
|
||||||
import {manager} from "../conversation/generation.ts";
|
import {manager} from "../conversation/generation.ts";
|
||||||
import {useToast} from "../components/ui/use-toast.ts";
|
import {useToast} from "../components/ui/use-toast.ts";
|
||||||
import {handleLine} from "../utils.ts";
|
import {handleGenerationData} from "../utils.ts";
|
||||||
|
import {selectModel, setModel} from "../store/chat.ts";
|
||||||
|
|
||||||
type WrapperProps = {
|
type WrapperProps = {
|
||||||
onSend?: (value: string, model: string) => boolean;
|
onSend?: (value: string, model: string) => boolean;
|
||||||
@ -19,14 +20,21 @@ type WrapperProps = {
|
|||||||
|
|
||||||
function Wrapper({ onSend }: WrapperProps) {
|
function Wrapper({ onSend }: WrapperProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
const [ stayed, setStayed ] = useState<boolean>(false);
|
const [ stayed, setStayed ] = useState<boolean>(false);
|
||||||
const [ hash, setHash ] = useState<string>("");
|
const [ hash, setHash ] = useState<string>("");
|
||||||
const [ data, setData ] = useState<string>("");
|
const [ data, setData ] = useState<string>("");
|
||||||
const [ quota, setQuota ] = useState<number>(0);
|
const [ quota, setQuota ] = useState<number>(0);
|
||||||
const [model, setModel] = useState("GPT-3.5");
|
const model = useSelector(selectModel);
|
||||||
|
const auth = useSelector(selectAuthenticated);
|
||||||
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (auth && model === "GPT-3.5") dispatch(setModel("GPT-3.5-16k"));
|
||||||
|
}, [auth]);
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
setData("");
|
setData("");
|
||||||
setQuota(0);
|
setQuota(0);
|
||||||
@ -52,14 +60,14 @@ function Wrapper({ onSend }: WrapperProps) {
|
|||||||
setHash(hash);
|
setHash(hash);
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleSend() {
|
function handleSend(model: string = "gpt-3.5-16k") {
|
||||||
const target = ref.current as HTMLInputElement | null;
|
const target = ref.current as HTMLInputElement | null;
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
const value = target.value.trim();
|
const value = target.value.trim();
|
||||||
if (!value.length) return;
|
if (!value.length) return;
|
||||||
|
|
||||||
if (onSend?.(value, model.toLowerCase())) {
|
if (onSend?.(value, model)) {
|
||||||
setStayed(true);
|
setStayed(true);
|
||||||
clear();
|
clear();
|
||||||
target.value = "";
|
target.value = "";
|
||||||
@ -68,13 +76,18 @@ function Wrapper({ onSend }: WrapperProps) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
ref.current && (ref.current as HTMLInputElement).focus();
|
ref.current && (ref.current as HTMLInputElement).focus();
|
||||||
|
ref.current && (ref.current as HTMLInputElement).removeEventListener("keydown", () => {});
|
||||||
ref.current &&
|
ref.current &&
|
||||||
(ref.current as HTMLInputElement).addEventListener("keydown", (e) => {
|
(ref.current as HTMLInputElement).addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
handleSend();
|
handleSend(model);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
return () => {
|
||||||
|
ref.current && (ref.current as HTMLInputElement).removeEventListener("keydown", () => {});
|
||||||
|
}
|
||||||
|
}, [ref]);
|
||||||
return (
|
return (
|
||||||
<div className={`generation-wrapper`}>
|
<div className={`generation-wrapper`}>
|
||||||
{
|
{
|
||||||
@ -85,7 +98,7 @@ function Wrapper({ onSend }: WrapperProps) {
|
|||||||
{quota}
|
{quota}
|
||||||
</div> }
|
</div> }
|
||||||
<pre className={`message-box`}>
|
<pre className={`message-box`}>
|
||||||
{ handleLine(data, 10) || t('generate.empty') }
|
{ handleGenerationData(data) || t('generate.empty') }
|
||||||
</pre>
|
</pre>
|
||||||
{
|
{
|
||||||
hash.length > 0 &&
|
hash.length > 0 &&
|
||||||
@ -110,7 +123,7 @@ function Wrapper({ onSend }: WrapperProps) {
|
|||||||
size={`icon`}
|
size={`icon`}
|
||||||
className={`action`}
|
className={`action`}
|
||||||
variant={`default`}
|
variant={`default`}
|
||||||
onClick={handleSend}
|
onClick={() => handleSend(model)}
|
||||||
>
|
>
|
||||||
<Send className={`h-5 w-5`} />
|
<Send className={`h-5 w-5`} />
|
||||||
</Button>
|
</Button>
|
||||||
@ -119,7 +132,9 @@ function Wrapper({ onSend }: WrapperProps) {
|
|||||||
<SelectGroup
|
<SelectGroup
|
||||||
current={model}
|
current={model}
|
||||||
list={["GPT-3.5", "GPT-3.5-16k", "GPT-4", "GPT-4-32k"]}
|
list={["GPT-3.5", "GPT-3.5-16k", "GPT-4", "GPT-4-32k"]}
|
||||||
onChange={setModel}
|
onChange={(value: string) => {
|
||||||
|
dispatch(setModel(value));
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -147,7 +162,8 @@ function Generation() {
|
|||||||
</Button>
|
</Button>
|
||||||
<Wrapper
|
<Wrapper
|
||||||
onSend={(prompt: string, model: string) => {
|
onSend={(prompt: string, model: string) => {
|
||||||
return manager.generateWithBlock(prompt, model)
|
console.debug(`[generation] create generation request (prompt: ${prompt}, model: ${model.toLowerCase()})`);
|
||||||
|
return manager.generateWithBlock(prompt, model.toLowerCase());
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -286,6 +286,10 @@ function ChatWrapper() {
|
|||||||
const target = useRef(null);
|
const target = useRef(null);
|
||||||
manager.setDispatch(dispatch);
|
manager.setDispatch(dispatch);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (auth && model === "GPT-3.5") dispatch(setModel("GPT-3.5-16k"));
|
||||||
|
}, [auth]);
|
||||||
|
|
||||||
function clearFile() {
|
function clearFile() {
|
||||||
clearEvent?.();
|
clearEvent?.();
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export const updateSW = registerSW({
|
|||||||
}).then(async (resp) => {
|
}).then(async (resp) => {
|
||||||
if (resp?.status === 200) {
|
if (resp?.status === 200) {
|
||||||
await registration.update();
|
await registration.update();
|
||||||
if (registration.onupdatefound) console.log("update found");
|
if (registration.onupdatefound) console.debug("update found");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -197,12 +197,22 @@ export function useDraggableInput(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function escapeRegExp(str: string): string {
|
||||||
|
// convert \n to [enter], \t to [tab], \r to [return], \s to [space], \" to [quote], \' to [single-quote]
|
||||||
|
return str.replace(/\\n/g, "\n").replace(/\\t/g, "\t").replace(/\\r/g, "\r").replace(/\\s/g, " ").replace(/\\"/g, "\"").replace(/\\'/g, "'");
|
||||||
|
}
|
||||||
|
|
||||||
export function handleLine(data: string, max_line: number, end?: boolean): string {
|
export function handleLine(data: string, max_line: number, end?: boolean): string {
|
||||||
const segment = data.split("\n");
|
const segment = data.split("\n");
|
||||||
const line = segment.length;
|
const line = segment.length;
|
||||||
if (line > max_line) {
|
if (line > max_line) {
|
||||||
return end ? segment.slice(line - max_line).join("\n") : segment.slice(0, max_line).join("\n");
|
return (end ?? true) ? segment.slice(line - max_line).join("\n") : segment.slice(0, max_line).join("\n");
|
||||||
} else {
|
} else {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function handleGenerationData(data: string): string {
|
||||||
|
data = data.replace(/{\s*"result":\s*{/g, "").trim().replace(/}\s*$/g, "");
|
||||||
|
return handleLine(escapeRegExp(data), 6);
|
||||||
|
}
|
||||||
|
@ -82,6 +82,7 @@ func GenerateAPI(c *gin.Context) {
|
|||||||
End: true,
|
End: true,
|
||||||
Error: "generation rate limit exceeded, the max generation rate is 30 per hour.",
|
Error: "generation rate limit exceeded, the max generation rate is 30 per hour.",
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
useReverse := auth.CanEnableSubscription(db, cache, user)
|
useReverse := auth.CanEnableSubscription(db, cache, user)
|
||||||
@ -91,6 +92,7 @@ func GenerateAPI(c *gin.Context) {
|
|||||||
Quota: 0,
|
Quota: 0,
|
||||||
End: true,
|
End: true,
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err := CreateGenerationWithCache(form.Model, form.Prompt, useReverse, func(data string) {
|
hash, err := CreateGenerationWithCache(form.Model, form.Prompt, useReverse, func(data string) {
|
||||||
|
@ -19,7 +19,7 @@ func CreateGeneration(model string, prompt string, path string, enableReverse bo
|
|||||||
{Role: "user", Content: "python后端"},
|
{Role: "user", Content: "python后端"},
|
||||||
{Role: "assistant", Content: "{\n \"result\": {\n \"app.py\": \"from flask import Flask\\n\\napp = Flask(__name__)\\n\\n\\n@app.route('/')\\ndef hello_world():\\n return 'Hello, World!'\\n\\n\\nif __name__ == '__main__':\\n app.run()\",\n \"requirements.txt\": \"flask\\n\",\n \"README.md\": \"# Python 后端\\n本项目是一个简单的python后端示例, 使用`flask`框架构建后端。\n你可以按照下列步骤运行此应用,flask将在本地服务器(默认是在http://127.0.0.1:5000/)上运行。当你在浏览器中访问该URL时,将看到显示Hello, World!的页面。\\n\\n这只是一个简单的项目,Flask还支持更多功能和路由规则,你可以提供更多的信息和需要进一步扩展和定制Flask应用。\\n\\n### 1. 初始化: \\n```shell\\npip install -r requirements.txt\\n```\\n### 2. 运行\\n```shell\\npython app.py\\n```\"\n }\n}"},
|
{Role: "assistant", Content: "{\n \"result\": {\n \"app.py\": \"from flask import Flask\\n\\napp = Flask(__name__)\\n\\n\\n@app.route('/')\\ndef hello_world():\\n return 'Hello, World!'\\n\\n\\nif __name__ == '__main__':\\n app.run()\",\n \"requirements.txt\": \"flask\\n\",\n \"README.md\": \"# Python 后端\\n本项目是一个简单的python后端示例, 使用`flask`框架构建后端。\n你可以按照下列步骤运行此应用,flask将在本地服务器(默认是在http://127.0.0.1:5000/)上运行。当你在浏览器中访问该URL时,将看到显示Hello, World!的页面。\\n\\n这只是一个简单的项目,Flask还支持更多功能和路由规则,你可以提供更多的信息和需要进一步扩展和定制Flask应用。\\n\\n### 1. 初始化: \\n```shell\\npip install -r requirements.txt\\n```\\n### 2. 运行\\n```shell\\npython app.py\\n```\"\n }\n}"},
|
||||||
{Role: "user", Content: "golang fiber websocket项目"},
|
{Role: "user", Content: "golang fiber websocket项目"},
|
||||||
{Role: "assistant", Content: "{\n \"result\": {\n \"main.go\": \"package main\\n\\nimport (\\n\\t\"log\\\"\\n\\n\\t\"github.com/gofiber/fiber/v2\\\"\\n\\t\"github.com/gofiber/websocket/v2\\\"\\n)\\n\\nfunc main() {\\n\\tapp := fiber.New()\\n\\n\\tapp.Get(\\\"/\\\", func(c *fiber.Ctx) error {\\n\\t\\treturn c.SendString(\\\"Hello, World!\\\")\\n\\t})\\n\\n\\tapp.Get(\\\"/ws\\\", websocket.New(func(c *websocket.Conn) {\\n\\t\\tfor {\\n\\t\\t\\tmt, message, err := c.ReadMessage()\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tlog.Println(\\\"read error:\\\", err)\\n\\t\\t\\t\\tbreak\\n\\t\\t\\t}\\n\\t\\t\\tlog.Printf(\\\"received: %s\\\", message)\\n\\t\\t\\terr = c.WriteMessage(mt, message)\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tlog.Println(\\\"write error:\\\", err)\\n\\t\\t\\t\\tbreak\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}))\\n\\n\\tlog.Fatal(app.Listen(\\\":3000\\\"))\\n}\",\n \"go.mod\": \"module fiber-websocket\\n\\ngo 1.16\\n\\nrequire (\\n\\tgithub.com/gofiber/fiber/v2 v2.12.1\\n\\tgithub.com/gofiber/websocket/v2 v2.10.2\\n)\",\n \"README.md\": \"# Golang Fiber WebSocket项目\\n\\n这个项目是一个使用Golang和Fiber框架构建的WebSocket服务器示例。\\n\\n### 1. 初始化:\\n```shell\\ngo mod init fiber-websocket\\n```\\n\\n### 2. 安装依赖:\\n```shell\\ngo get github.com/gofiber/fiber/v2\\n``` \\n```shell\\ngo get github.com/gofiber/websocket/v2\\n```\\n\\n### 3. 创建main.go文件,将以下代码复制粘贴:\\n\\n```go\\npackage main\\n\\nimport (\\n\\t\\\"log\\\"\\n\\n\\t\\\"github.com/gofiber/fiber/v2\\\"\\n\\t\\\"github.com/gofiber/websocket/v2\\\"\\n)\\n\\nfunc main() {\\n\\tapp := fiber.New()\\n\\n\\tapp.Get(\\\"/\\\", func(c *fiber.Ctx) error {\\n\\t\\treturn c.SendString(\\\"Hello, World!\\\")\\n\\t})\\n\\n\\tapp.Get(\\\"/ws\\\", websocket.New(func(c *websocket.Conn) {\\n\\t\\tfor {\\n\\t\\t\\tmt, message, err := c.ReadMessage()\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tlog.Println(\\\"read error:\\\", err)\\n\\t\\t\\t\\tbreak\\n\\t\\t\\t}\\n\\t\\t\\tlog.Printf(\\\"received: %s\\\", message)\\n\\t\\t\\terr = c.WriteMessage(mt, message)\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tlog.Println(\\\"write error:\\\", err)\\n\\t\\t\\t\\tbreak\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}))\\n\\n\\tlog.Fatal(app.Listen(\\\":3000\\\"))\\n}\\n```\\n\\n### 4. 运行应用程序:\\n```shell\\ngo run main.go\\n```\\n\\n应用程序将在本地服务器(默认是在http://localhost:3000)上运行。当你在浏览器中访问`http://localhost:3000`时,将看到显示\"Hello, World!\"的页面。你还可以访问`http://localhost:3000/ws`来测试WebSocket功能。\n\n这只是一个简单的示例,Fiber框架提供了更多的功能和路由规则,你可以在此基础上进行进一步扩展和定制。\n\n注意:在运行应用程序之前,请确保已经安装了Go语言开发环境。"},
|
{Role: "assistant", Content: "{\n \"result\": {\n \"main.go\": \"package main\\n\\nimport (\\n\\t\"log\\\"\\n\\n\\t\"github.com/gofiber/fiber/v2\\\"\\n\\t\"github.com/gofiber/websocket/v2\\\"\\n)\\n\\nfunc main() {\\n\\tapp := fiber.New()\\n\\n\\tapp.Get(\\\"/\\\", func(c *fiber.Ctx) error {\\n\\t\\treturn c.SendString(\\\"Hello, World!\\\")\\n\\t})\\n\\n\\tapp.Get(\\\"/ws\\\", websocket.New(func(c *websocket.Conn) {\\n\\t\\tfor {\\n\\t\\t\\tmt, message, err := c.ReadMessage()\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tlog.Println(\\\"read error:\\\", err)\\n\\t\\t\\t\\tbreak\\n\\t\\t\\t}\\n\\t\\t\\tlog.Printf(\\\"received: %s\\\", message)\\n\\t\\t\\terr = c.WriteMessage(mt, message)\\n\\t\\t\\tif err != nil {\\n\\t\\t\\t\\tlog.Println(\\\"write error:\\\", err)\\n\\t\\t\\t\\tbreak\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}))\\n\\n\\tlog.Fatal(app.Listen(\\\":3000\\\"))\\n}\",\n \"go.mod\": \"module fiber-websocket\\n\\ngo 1.16\\n\\nrequire (\\n\\tgithub.com/gofiber/fiber/v2 v2.12.1\\n\\tgithub.com/gofiber/websocket/v2 v2.10.2\\n)\",\n \"README.md\": \"# Golang Fiber WebSocket项目\\n\\n这个项目是一个使用 Golang 和 Fiber 框架构建的 WebSocket 服务器示例。\\n\\n### 运行应用程序:\\n```shell\\ngo run main.go\\n```\\n\\n应用程序将在本地服务器(默认是在http://localhost:3000)上运行。当你在浏览器中访问`http://localhost:3000`时,将看到显示\"Hello, World!\"的页面。你还可以访问`http://localhost:3000/ws`来测试 WebSocket 连接。\n\n注意:在运行应用程序之前,请确保已经安装了Go语言开发环境。\"\n }\n}"},
|
||||||
{Role: "user", Content: prompt},
|
{Role: "user", Content: prompt},
|
||||||
}, -1, func(data string) {
|
}, -1, func(data string) {
|
||||||
hook(data)
|
hook(data)
|
||||||
|
Loading…
Reference in New Issue
Block a user