fix generation context and prompt

This commit is contained in:
Zhang Minghan 2023-09-24 09:20:37 +08:00
parent 5bb1fca7eb
commit f57b5710a0
8 changed files with 51 additions and 21 deletions

View File

@ -59,16 +59,14 @@
.message-box {
width: 100%;
height: max-content;
min-height: 120px;
border-radius: var(--radius);
border: 1px solid hsl(var(--border));
color: hsl(var(--text-secondary));
padding: 0.6rem 1rem;
font-size: 10px;
overflow: hidden;
white-space: pre-wrap;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
text-overflow: ellipsis;
}
.quota-box {

View File

@ -100,7 +100,7 @@ const resources = {
"free-price": "Free Forever",
pro: "Pro",
"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-web": "web searching feature",
"free-conversation": "conversation storage",
@ -243,7 +243,7 @@ const resources = {
"free-price": "永久免费",
pro: "专业版",
"pro-price": "8 元/月",
"free-gpt3": "GPT-3.5 永久免费",
"free-gpt3": "GPT-3.5 (16k) 永久免费",
"free-dalle": "每日 5 次免费绘图",
"free-web": "联网搜索功能",
"free-conversation": "对话存储记录",
@ -391,7 +391,7 @@ const resources = {
"free-price": "Бесплатно навсегда",
pro: "Профессиональный",
"pro-price": "8 CNY/месяц",
"free-gpt3": "GPT-3.5 бесплатно навсегда",
"free-gpt3": "GPT-3.5 (16k) бесплатно навсегда",
"free-dalle": "5 бесплатных квот в день",
"free-web": "веб-поиск",
"free-conversation": "хранение разговоров",

View File

@ -1,5 +1,5 @@
import "../assets/generation.less";
import { useSelector } from "react-redux";
import {useDispatch, useSelector} from "react-redux";
import { selectAuthenticated } from "../store/auth.ts";
import { useTranslation } from "react-i18next";
import { Button } from "../components/ui/button.tsx";
@ -11,7 +11,8 @@ import { useEffect, useRef, useState } from "react";
import SelectGroup from "../components/SelectGroup.tsx";
import {manager} from "../conversation/generation.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 = {
onSend?: (value: string, model: string) => boolean;
@ -19,14 +20,21 @@ type WrapperProps = {
function Wrapper({ onSend }: WrapperProps) {
const { t } = useTranslation();
const dispatch = useDispatch();
const ref = useRef(null);
const [ stayed, setStayed ] = useState<boolean>(false);
const [ hash, setHash ] = useState<string>("");
const [ data, setData ] = useState<string>("");
const [ quota, setQuota ] = useState<number>(0);
const [model, setModel] = useState("GPT-3.5");
const model = useSelector(selectModel);
const auth = useSelector(selectAuthenticated);
const { toast } = useToast();
useEffect(() => {
if (auth && model === "GPT-3.5") dispatch(setModel("GPT-3.5-16k"));
}, [auth]);
function clear() {
setData("");
setQuota(0);
@ -52,14 +60,14 @@ function Wrapper({ onSend }: WrapperProps) {
setHash(hash);
})
function handleSend() {
function handleSend(model: string = "gpt-3.5-16k") {
const target = ref.current as HTMLInputElement | null;
if (!target) return;
const value = target.value.trim();
if (!value.length) return;
if (onSend?.(value, model.toLowerCase())) {
if (onSend?.(value, model)) {
setStayed(true);
clear();
target.value = "";
@ -68,13 +76,18 @@ function Wrapper({ onSend }: WrapperProps) {
useEffect(() => {
ref.current && (ref.current as HTMLInputElement).focus();
ref.current && (ref.current as HTMLInputElement).removeEventListener("keydown", () => {});
ref.current &&
(ref.current as HTMLInputElement).addEventListener("keydown", (e) => {
if (e.key === "Enter") {
handleSend();
handleSend(model);
}
});
});
return () => {
ref.current && (ref.current as HTMLInputElement).removeEventListener("keydown", () => {});
}
}, [ref]);
return (
<div className={`generation-wrapper`}>
{
@ -85,7 +98,7 @@ function Wrapper({ onSend }: WrapperProps) {
{quota}
</div> }
<pre className={`message-box`}>
{ handleLine(data, 10) || t('generate.empty') }
{ handleGenerationData(data) || t('generate.empty') }
</pre>
{
hash.length > 0 &&
@ -110,7 +123,7 @@ function Wrapper({ onSend }: WrapperProps) {
size={`icon`}
className={`action`}
variant={`default`}
onClick={handleSend}
onClick={() => handleSend(model)}
>
<Send className={`h-5 w-5`} />
</Button>
@ -119,7 +132,9 @@ function Wrapper({ onSend }: WrapperProps) {
<SelectGroup
current={model}
list={["GPT-3.5", "GPT-3.5-16k", "GPT-4", "GPT-4-32k"]}
onChange={setModel}
onChange={(value: string) => {
dispatch(setModel(value));
}}
/>
</div>
</div>
@ -147,7 +162,8 @@ function Generation() {
</Button>
<Wrapper
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>

View File

@ -286,6 +286,10 @@ function ChatWrapper() {
const target = useRef(null);
manager.setDispatch(dispatch);
useEffect(() => {
if (auth && model === "GPT-3.5") dispatch(setModel("GPT-3.5-16k"));
}, [auth]);
function clearFile() {
clearEvent?.();
}

View File

@ -12,7 +12,7 @@ export const updateSW = registerSW({
}).then(async (resp) => {
if (resp?.status === 200) {
await registration.update();
if (registration.onupdatefound) console.log("update found");
if (registration.onupdatefound) console.debug("update found");
}
});
},

View File

@ -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 {
const segment = data.split("\n");
const line = segment.length;
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 {
return data;
}
}
export function handleGenerationData(data: string): string {
data = data.replace(/{\s*"result":\s*{/g, "").trim().replace(/}\s*$/g, "");
return handleLine(escapeRegExp(data), 6);
}

View File

@ -82,6 +82,7 @@ func GenerateAPI(c *gin.Context) {
End: true,
Error: "generation rate limit exceeded, the max generation rate is 30 per hour.",
})
return
}
useReverse := auth.CanEnableSubscription(db, cache, user)
@ -91,6 +92,7 @@ func GenerateAPI(c *gin.Context) {
Quota: 0,
End: true,
})
return
}
hash, err := CreateGenerationWithCache(form.Model, form.Prompt, useReverse, func(data string) {

View File

@ -19,7 +19,7 @@ func CreateGeneration(model string, prompt string, path string, enableReverse bo
{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: "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},
}, -1, func(data string) {
hook(data)