1.4.0 dev mode support more ops and args
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
const CHATGPT_API_WEB_VERSION = "v1.3.0";
|
const CHATGPT_API_WEB_VERSION = "v1.4.0";
|
||||||
|
|
||||||
export default CHATGPT_API_WEB_VERSION;
|
export default CHATGPT_API_WEB_VERSION;
|
||||||
|
|||||||
14
src/app.tsx
14
src/app.tsx
@@ -27,6 +27,11 @@ export interface ChatStore {
|
|||||||
model: string;
|
model: string;
|
||||||
responseModelName: string;
|
responseModelName: string;
|
||||||
cost: number;
|
cost: number;
|
||||||
|
temperature: number;
|
||||||
|
top_p: number;
|
||||||
|
presence_penalty: number;
|
||||||
|
frequency_penalty: number;
|
||||||
|
develop_mode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _defaultAPIEndpoint = "https://api.openai.com/v1/chat/completions";
|
const _defaultAPIEndpoint = "https://api.openai.com/v1/chat/completions";
|
||||||
@@ -35,7 +40,9 @@ const newChatStore = (
|
|||||||
systemMessageContent = "Follow my instructions carefully",
|
systemMessageContent = "Follow my instructions carefully",
|
||||||
apiEndpoint = _defaultAPIEndpoint,
|
apiEndpoint = _defaultAPIEndpoint,
|
||||||
streamMode = true,
|
streamMode = true,
|
||||||
model = "gpt-3.5-turbo-0613"
|
model = "gpt-3.5-turbo-0613",
|
||||||
|
temperature = 1.0,
|
||||||
|
dev = false
|
||||||
): ChatStore => {
|
): ChatStore => {
|
||||||
return {
|
return {
|
||||||
chatgpt_api_web_version: CHATGPT_API_WEB_VERSION,
|
chatgpt_api_web_version: CHATGPT_API_WEB_VERSION,
|
||||||
@@ -51,6 +58,11 @@ const newChatStore = (
|
|||||||
model: getDefaultParams("model", model),
|
model: getDefaultParams("model", model),
|
||||||
responseModelName: "",
|
responseModelName: "",
|
||||||
cost: 0,
|
cost: 0,
|
||||||
|
temperature: getDefaultParams("temp", temperature),
|
||||||
|
top_p: 1,
|
||||||
|
presence_penalty: 0,
|
||||||
|
frequency_penalty: 0,
|
||||||
|
develop_mode: getDefaultParams("dev", dev),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,19 @@ export default function ChatBOX(props: {
|
|||||||
|
|
||||||
const client = new ChatGPT(chatStore.apiKey);
|
const client = new ChatGPT(chatStore.apiKey);
|
||||||
|
|
||||||
|
const update_total_tokens = () => {
|
||||||
|
// manually estimate token
|
||||||
|
client.total_tokens = calculate_token_length(
|
||||||
|
chatStore.systemMessageContent
|
||||||
|
);
|
||||||
|
for (const msg of chatStore.history
|
||||||
|
.filter(({ hide }) => !hide)
|
||||||
|
.slice(chatStore.postBeginIndex)) {
|
||||||
|
client.total_tokens += msg.token;
|
||||||
|
}
|
||||||
|
chatStore.totalTokens = client.total_tokens;
|
||||||
|
};
|
||||||
|
|
||||||
const _completeWithStreamMode = async (response: Response) => {
|
const _completeWithStreamMode = async (response: Response) => {
|
||||||
chatStore.streamMode = true;
|
chatStore.streamMode = true;
|
||||||
// call api, return reponse text
|
// call api, return reponse text
|
||||||
@@ -121,14 +134,7 @@ export default function ChatBOX(props: {
|
|||||||
// manually copy status from client to chatStore
|
// manually copy status from client to chatStore
|
||||||
chatStore.maxTokens = client.max_tokens;
|
chatStore.maxTokens = client.max_tokens;
|
||||||
chatStore.tokenMargin = client.tokens_margin;
|
chatStore.tokenMargin = client.tokens_margin;
|
||||||
// manually estimate token
|
update_total_tokens();
|
||||||
client.total_tokens = 0;
|
|
||||||
for (const msg of chatStore.history
|
|
||||||
.filter(({ hide }) => !hide)
|
|
||||||
.slice(chatStore.postBeginIndex)) {
|
|
||||||
client.total_tokens += msg.token;
|
|
||||||
}
|
|
||||||
chatStore.totalTokens = client.total_tokens;
|
|
||||||
setChatStore({ ...chatStore });
|
setChatStore({ ...chatStore });
|
||||||
setGeneratingMessage("");
|
setGeneratingMessage("");
|
||||||
setShowGenerating(false);
|
setShowGenerating(false);
|
||||||
@@ -407,6 +413,42 @@ export default function ChatBOX(props: {
|
|||||||
>
|
>
|
||||||
Send
|
Send
|
||||||
</button>
|
</button>
|
||||||
|
{chatStore.develop_mode && (
|
||||||
|
<button
|
||||||
|
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
|
||||||
|
disabled={showGenerating || !chatStore.apiKey}
|
||||||
|
onClick={() => {
|
||||||
|
chatStore.history.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: inputMsg,
|
||||||
|
token: calculate_token_length(inputMsg),
|
||||||
|
hide: false,
|
||||||
|
});
|
||||||
|
update_total_tokens();
|
||||||
|
setChatStore({ ...chatStore });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Assistant
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{chatStore.develop_mode && (
|
||||||
|
<button
|
||||||
|
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
|
||||||
|
disabled={showGenerating || !chatStore.apiKey}
|
||||||
|
onClick={() => {
|
||||||
|
chatStore.history.push({
|
||||||
|
role: "user",
|
||||||
|
content: inputMsg,
|
||||||
|
token: calculate_token_length(inputMsg),
|
||||||
|
hide: false,
|
||||||
|
});
|
||||||
|
update_total_tokens();
|
||||||
|
setChatStore({ ...chatStore });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
User
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ function getDefaultParams(param: any, val: any) {
|
|||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
return get ?? val;
|
return get ?? val;
|
||||||
} else if (typeof val === "number") {
|
} else if (typeof val === "number") {
|
||||||
return parseInt(get ?? `${val}`);
|
return parseFloat(get ?? `${val}`);
|
||||||
} else if (typeof val === "boolean") {
|
} else if (typeof val === "boolean") {
|
||||||
if (get === "stream") return true;
|
if (get === "stream") return true;
|
||||||
if (get === "fetch") return false;
|
if (get === "fetch") return false;
|
||||||
|
if (get === "true") return true;
|
||||||
|
if (get === "false") return false;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export default function Message(props: Props) {
|
|||||||
chat.role === "assistant" ? "justify-start" : "justify-end"
|
chat.role === "assistant" ? "justify-start" : "justify-end"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<div className=" bg-">
|
||||||
<div
|
<div
|
||||||
className={`relative w-fit p-2 rounded my-2 ${
|
className={`relative w-fit p-2 rounded my-2 ${
|
||||||
chat.role === "assistant"
|
chat.role === "assistant"
|
||||||
@@ -58,13 +59,52 @@ export default function Message(props: Props) {
|
|||||||
: "bg-green-400"
|
: "bg-green-400"
|
||||||
} ${chat.hide ? "opacity-50" : ""}`}
|
} ${chat.hide ? "opacity-50" : ""}`}
|
||||||
>
|
>
|
||||||
|
{chatStore.develop_mode ? (
|
||||||
|
<textarea
|
||||||
|
className="message-content"
|
||||||
|
value={
|
||||||
|
chat.hide
|
||||||
|
? chat.content.split("\n")[0].slice(0, 16) + "... (deleted)"
|
||||||
|
: chat.content
|
||||||
|
}
|
||||||
|
onChange={(event: any) => {
|
||||||
|
chatStore.history[messageIndex].content = event.target.value;
|
||||||
|
setChatStore({ ...chatStore });
|
||||||
|
}}
|
||||||
|
></textarea>
|
||||||
|
) : (
|
||||||
<p className="message-content">
|
<p className="message-content">
|
||||||
{chat.hide
|
{chat.hide
|
||||||
? chat.content.split("\n")[0].slice(0, 16) + "... (deleted)"
|
? chat.content.split("\n")[0].slice(0, 16) + "... (deleted)"
|
||||||
: chat.content}
|
: chat.content}
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
token {chatStore.history[messageIndex].token}
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
chatStore.history.splice(messageIndex, 1);
|
||||||
|
chatStore.postBeginIndex = Math.max(
|
||||||
|
chatStore.postBeginIndex - 1,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
//chatStore.totalTokens =
|
||||||
|
chatStore.totalTokens = 0;
|
||||||
|
for (const i of chatStore.history
|
||||||
|
.filter(({ hide }) => !hide)
|
||||||
|
.slice(chatStore.postBeginIndex)
|
||||||
|
.map(({ token }) => token)) {
|
||||||
|
chatStore.totalTokens += i;
|
||||||
|
}
|
||||||
|
setChatStore({ ...chatStore });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
❌
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -45,10 +45,30 @@ const SelectModel = (props: {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const LongInput = (props: {
|
||||||
|
chatStore: ChatStore;
|
||||||
|
setChatStore: (cs: ChatStore) => void;
|
||||||
|
field: "systemMessageContent";
|
||||||
|
help: string;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Help help={props.help}>
|
||||||
|
<textarea
|
||||||
|
className="m-2 p-2 border rounded focus w-full"
|
||||||
|
value={props.chatStore[props.field]}
|
||||||
|
onChange={(event: any) => {
|
||||||
|
props.chatStore[props.field] = event.target.value;
|
||||||
|
props.setChatStore({ ...props.chatStore });
|
||||||
|
}}
|
||||||
|
></textarea>
|
||||||
|
</Help>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Input = (props: {
|
const Input = (props: {
|
||||||
chatStore: ChatStore;
|
chatStore: ChatStore;
|
||||||
setChatStore: (cs: ChatStore) => void;
|
setChatStore: (cs: ChatStore) => void;
|
||||||
field: "apiKey" | "systemMessageContent" | "apiEndpoint";
|
field: "apiKey" | "apiEndpoint";
|
||||||
help: string;
|
help: string;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
@@ -68,7 +88,15 @@ const Input = (props: {
|
|||||||
const Number = (props: {
|
const Number = (props: {
|
||||||
chatStore: ChatStore;
|
chatStore: ChatStore;
|
||||||
setChatStore: (cs: ChatStore) => void;
|
setChatStore: (cs: ChatStore) => void;
|
||||||
field: "totalTokens" | "maxTokens" | "tokenMargin" | "postBeginIndex";
|
field:
|
||||||
|
| "totalTokens"
|
||||||
|
| "maxTokens"
|
||||||
|
| "tokenMargin"
|
||||||
|
| "postBeginIndex"
|
||||||
|
| "temperature"
|
||||||
|
| "top_p"
|
||||||
|
| "presence_penalty"
|
||||||
|
| "frequency_penalty";
|
||||||
readOnly: boolean;
|
readOnly: boolean;
|
||||||
help: string;
|
help: string;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -82,7 +110,7 @@ const Number = (props: {
|
|||||||
value={props.chatStore[props.field]}
|
value={props.chatStore[props.field]}
|
||||||
onChange={(event: any) => {
|
onChange={(event: any) => {
|
||||||
console.log("type", typeof event.target.value);
|
console.log("type", typeof event.target.value);
|
||||||
let newNumber = parseInt(event.target.value);
|
let newNumber = parseFloat(event.target.value);
|
||||||
if (newNumber < 0) newNumber = 0;
|
if (newNumber < 0) newNumber = 0;
|
||||||
props.chatStore[props.field] = newNumber;
|
props.chatStore[props.field] = newNumber;
|
||||||
props.setChatStore({ ...props.chatStore });
|
props.setChatStore({ ...props.chatStore });
|
||||||
@@ -94,7 +122,7 @@ const Number = (props: {
|
|||||||
const Choice = (props: {
|
const Choice = (props: {
|
||||||
chatStore: ChatStore;
|
chatStore: ChatStore;
|
||||||
setChatStore: (cs: ChatStore) => void;
|
setChatStore: (cs: ChatStore) => void;
|
||||||
field: "streamMode";
|
field: "streamMode" | "develop_mode";
|
||||||
help: string;
|
help: string;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
@@ -119,7 +147,7 @@ export default (props: {
|
|||||||
setShow: StateUpdater<boolean>;
|
setShow: StateUpdater<boolean>;
|
||||||
selectedChatStoreIndex: number;
|
selectedChatStoreIndex: number;
|
||||||
}) => {
|
}) => {
|
||||||
const link =
|
let link =
|
||||||
location.protocol +
|
location.protocol +
|
||||||
"//" +
|
"//" +
|
||||||
location.host +
|
location.host +
|
||||||
@@ -131,6 +159,9 @@ export default (props: {
|
|||||||
}&model=${props.chatStore.model}&sys=${encodeURIComponent(
|
}&model=${props.chatStore.model}&sys=${encodeURIComponent(
|
||||||
props.chatStore.systemMessageContent
|
props.chatStore.systemMessageContent
|
||||||
)}`;
|
)}`;
|
||||||
|
if (props.chatStore.develop_mode) {
|
||||||
|
link = link + `&dev=true`;
|
||||||
|
}
|
||||||
|
|
||||||
const importFileRef = createRef();
|
const importFileRef = createRef();
|
||||||
const [totalCost, setTotalCost] = useState(getTotalCost());
|
const [totalCost, setTotalCost] = useState(getTotalCost());
|
||||||
@@ -157,7 +188,7 @@ export default (props: {
|
|||||||
Total cost in this session ${props.chatStore.cost.toFixed(4)}
|
Total cost in this session ${props.chatStore.cost.toFixed(4)}
|
||||||
</p>
|
</p>
|
||||||
<div className="box">
|
<div className="box">
|
||||||
<Input
|
<LongInput
|
||||||
field="systemMessageContent"
|
field="systemMessageContent"
|
||||||
help="系统消息,用于指示ChatGPT的角色和一些前置条件,例如“你是一个有帮助的人工智能助理”,或者“你是一个专业英语翻译,把我的话全部翻译成英语”,详情参考 OPEAN AI API 文档"
|
help="系统消息,用于指示ChatGPT的角色和一些前置条件,例如“你是一个有帮助的人工智能助理”,或者“你是一个专业英语翻译,把我的话全部翻译成英语”,详情参考 OPEAN AI API 文档"
|
||||||
{...props}
|
{...props}
|
||||||
@@ -177,6 +208,11 @@ export default (props: {
|
|||||||
help="流模式,使用 stream mode 将可以动态看到生成内容,但无法准确计算 token 数量,在 token 数量过多时可能会裁切过多或过少历史消息"
|
help="流模式,使用 stream mode 将可以动态看到生成内容,但无法准确计算 token 数量,在 token 数量过多时可能会裁切过多或过少历史消息"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
<Choice
|
||||||
|
field="develop_mode"
|
||||||
|
help="开发者模式,拥有更多选项及功能"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
<SelectModel
|
<SelectModel
|
||||||
help="模型,默认 3.5。不同模型性能和定价也不同,请参考 API 文档。(GPT-4 模型处于内测阶段,需要向 OPENAI 申请, 请确保您有访问权限)"
|
help="模型,默认 3.5。不同模型性能和定价也不同,请参考 API 文档。(GPT-4 模型处于内测阶段,需要向 OPENAI 申请, 请确保您有访问权限)"
|
||||||
{...props}
|
{...props}
|
||||||
@@ -205,6 +241,20 @@ export default (props: {
|
|||||||
readOnly={true}
|
readOnly={true}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
<Number field="temperature" help="温度" readOnly={false} {...props} />
|
||||||
|
<Number field="top_p" help="top_p" readOnly={false} {...props} />
|
||||||
|
<Number
|
||||||
|
field="presence_penalty"
|
||||||
|
help="presence_penalty"
|
||||||
|
readOnly={false}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<Number
|
||||||
|
field="frequency_penalty"
|
||||||
|
help="frequency_penalty"
|
||||||
|
readOnly={false}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
<p className="flex justify-evenly">
|
<p className="flex justify-evenly">
|
||||||
<button
|
<button
|
||||||
className="p-2 m-2 rounded bg-amber-500"
|
className="p-2 m-2 rounded bg-amber-500"
|
||||||
|
|||||||
Reference in New Issue
Block a user