Merge remote-tracking branch 'upstream/main'

# Conflicts:
#	app/api/common.ts
This commit is contained in:
sijinhui 2024-03-28 16:07:23 +08:00
commit e6912f5be8
9 changed files with 72 additions and 22 deletions

View File

@ -63,7 +63,7 @@ dist
# Gatsby files # Gatsby files
.cache/ .cache/
public
# Vuepress build output # Vuepress build output
.vuepress/dist .vuepress/dist

View File

@ -2,7 +2,7 @@
# Your openai api key. (required) # Your openai api key. (required)
OPENAI_API_KEY=sk-xxxx OPENAI_API_KEY=sk-xxxx
# Access passsword, separated by comma. (optional) # Access password, separated by comma. (optional)
CODE=your-password CODE=your-password
# You can start service behind a proxy # You can start service behind a proxy

View File

@ -51,10 +51,6 @@ export async function requestOpenai(
// console.log("[Proxy] ", path); // console.log("[Proxy] ", path);
// console.log("[Base Url]", baseUrl); // console.log("[Base Url]", baseUrl);
// // this fix [Org ID] undefined in server side if not using custom point
// if (serverConfig.openaiOrgId !== undefined) {
// console.log("[Org ID]", serverConfig.openaiOrgId);
// }
const timeoutId = setTimeout( const timeoutId = setTimeout(
() => { () => {
@ -110,12 +106,29 @@ export async function requestOpenai(
try { try {
const res = await fetch(fetchUrl, fetchOptions); const res = await fetch(fetchUrl, fetchOptions);
// Extract the OpenAI-Organization header from the response
const openaiOrganizationHeader = res.headers.get("OpenAI-Organization");
// Check if serverConfig.openaiOrgId is defined and not an empty string
if (serverConfig.openaiOrgId && serverConfig.openaiOrgId.trim() !== "") {
// If openaiOrganizationHeader is present, log it; otherwise, log that the header is not present
console.log("[Org ID]", openaiOrganizationHeader);
} else {
console.log("[Org ID] is not set up.");
}
// to prevent browser prompt for credentials // to prevent browser prompt for credentials
const newHeaders = new Headers(res.headers); const newHeaders = new Headers(res.headers);
newHeaders.delete("www-authenticate"); newHeaders.delete("www-authenticate");
// to disable nginx buffering // to disable nginx buffering
newHeaders.set("X-Accel-Buffering", "no"); newHeaders.set("X-Accel-Buffering", "no");
// Conditionally delete the OpenAI-Organization header from the response if [Org ID] is undefined or empty (not setup in ENV)
// Also, this is to prevent the header from being sent to the client
if (!serverConfig.openaiOrgId || serverConfig.openaiOrgId.trim() === "") {
newHeaders.delete("OpenAI-Organization");
}
// The latest version of the OpenAI API forced the content-encoding to be "br" in json response // The latest version of the OpenAI API forced the content-encoding to be "br" in json response
// So if the streaming is disabled, we need to remove the content-encoding header // So if the streaming is disabled, we need to remove the content-encoding header
// Because Vercel uses gzip to compress the response, if we don't remove the content-encoding header // Because Vercel uses gzip to compress the response, if we don't remove the content-encoding header

View File

@ -239,19 +239,31 @@ export class ChatGPTApi implements LLMApi {
} }
const text = msg.data; const text = msg.data;
try { try {
const json = JSON.parse(text) as { const json = JSON.parse(text);
choices: Array<{ const choices = json.choices as Array<{
delta: { delta: { content: string };
content: string; }>;
}; const delta = choices[0]?.delta?.content;
}>; const textmoderation = json?.prompt_filter_results;
};
const delta = json.choices[0]?.delta?.content;
if (delta) { if (delta) {
remainText += delta; remainText += delta;
} }
if (
textmoderation &&
textmoderation.length > 0 &&
ServiceProvider.Azure
) {
const contentFilterResults =
textmoderation[0]?.content_filter_results;
console.log(
`[${ServiceProvider.Azure}] [Text Moderation] flagged categories result:`,
contentFilterResults,
);
}
} catch (e) { } catch (e) {
console.error("[Request] parse error", text); console.error("[Request] parse error", text, msg);
} }
}, },
onclose() { onclose() {

View File

@ -12,7 +12,7 @@ import {
import { useChatStore } from "../store"; import { useChatStore } from "../store";
import Locale from "../locales"; import Locale from "../locales";
import { Link, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import { Path } from "../constant"; import { Path } from "../constant";
import { MaskAvatar } from "./mask"; import { MaskAvatar } from "./mask";
import { Mask } from "../store/mask"; import { Mask } from "../store/mask";
@ -40,12 +40,16 @@ export function ChatItem(props: {
}); });
} }
}, [props.selected]); }, [props.selected]);
const { pathname: currentPath } = useLocation();
return ( return (
<Draggable draggableId={`${props.id}`} index={props.index}> <Draggable draggableId={`${props.id}`} index={props.index}>
{(provided) => ( {(provided) => (
<div <div
className={`${styles["chat-item"]} ${ className={`${styles["chat-item"]} ${
props.selected && styles["chat-item-selected"] props.selected &&
(currentPath === Path.Chat || currentPath === Path.Home) &&
styles["chat-item-selected"]
}`} }`}
onClick={props.onClick} onClick={props.onClick}
ref={(ele) => { ref={(ele) => {

View File

@ -404,7 +404,16 @@ export function MaskPage() {
const maskStore = useMaskStore(); const maskStore = useMaskStore();
const chatStore = useChatStore(); const chatStore = useChatStore();
const [filterLang, setFilterLang] = useState<Lang>(); const [filterLang, setFilterLang] = useState<Lang | undefined>(
localStorage.getItem("Mask-language") as Lang | undefined,
);
useEffect(() => {
if (filterLang) {
localStorage.setItem("Mask-language", filterLang);
} else {
localStorage.removeItem("Mask-language");
}
}, [filterLang]);
const allMasks = maskStore const allMasks = maskStore
.getAll() .getAll()

View File

@ -227,7 +227,7 @@ export function MessageSelector(props: {
</div> </div>
<div className={styles["checkbox"]}> <div className={styles["checkbox"]}>
<input type="checkbox" checked={isSelected}></input> <input type="checkbox" checked={isSelected} readOnly></input>
</div> </div>
</div> </div>
); );

View File

@ -865,6 +865,7 @@ export const useChatStore = createPersistStore(
messages: topicMessages, messages: topicMessages,
config: { config: {
model: getSummarizeModel(session.mask.modelConfig.model), model: getSummarizeModel(session.mask.modelConfig.model),
stream: false,
}, },
onFinish(message) { onFinish(message) {
get().updateCurrentSession( get().updateCurrentSession(
@ -908,6 +909,10 @@ export const useChatStore = createPersistStore(
historyMsgLength > modelConfig.compressMessageLengthThreshold && historyMsgLength > modelConfig.compressMessageLengthThreshold &&
modelConfig.sendMemory modelConfig.sendMemory
) { ) {
/** Destruct max_tokens while summarizing
* this param is just shit
**/
const { max_tokens, ...modelcfg } = modelConfig;
api.llm.chat({ api.llm.chat({
messages: toBeSummarizedMsgs.concat( messages: toBeSummarizedMsgs.concat(
createMessage({ createMessage({
@ -917,7 +922,7 @@ export const useChatStore = createPersistStore(
}), }),
), ),
config: { config: {
...modelConfig, ...modelcfg,
stream: true, stream: true,
model: getSummarizeModel(session.mask.modelConfig.model), model: getSummarizeModel(session.mask.modelConfig.model),
}, },

View File

@ -18,8 +18,15 @@ export function createWebDavClient(store: SyncStore) {
method: "MKCOL", method: "MKCOL",
headers: this.headers(), headers: this.headers(),
}); });
console.log("[WebDav] check", res.status, res.statusText); const success = [201, 200, 404, 405, 301, 302, 307, 308].includes(
return [201, 200, 404, 301, 302, 307, 308].includes(res.status); res.status,
);
console.log(
`[WebDav] check ${success ? "success" : "failed"}, ${res.status} ${
res.statusText
}`,
);
return success;
} catch (e) { } catch (e) {
console.error("[WebDav] failed to check", e); console.error("[WebDav] failed to check", e);
} }