mirror of
https://github.com/coaidev/coai.git
synced 2025-05-29 18:00:14 +09:00
feat: sync chatnio blob service ocr feature
This commit is contained in:
parent
72af27b26a
commit
1150ff2e29
@ -8,7 +8,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "chatnio",
|
||||
"version": "3.10.8"
|
||||
"version": "3.10.9"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
|
@ -187,13 +187,9 @@ export const ChannelInfos: Record<string, ChannelInfo> = {
|
||||
chatglm: {
|
||||
endpoint: "https://open.bigmodel.cn",
|
||||
format: "<api-key>",
|
||||
models: [
|
||||
"glm-4",
|
||||
"glm-4v",
|
||||
"glm-3-turbo"
|
||||
],
|
||||
models: ["glm-4", "glm-4v", "glm-3-turbo"],
|
||||
description:
|
||||
"> 智谱 ChatGLM 密钥格式为 **api-key**,接入点填写 *https://open.bigmodel.cn* \n"
|
||||
"> 智谱 ChatGLM 密钥格式为 **api-key**,接入点填写 *https://open.bigmodel.cn* \n",
|
||||
},
|
||||
qwen: {
|
||||
endpoint: "https://dashscope.aliyuncs.com",
|
||||
|
@ -173,7 +173,12 @@ export const pricing: PricingDataset = [
|
||||
currency: Currency.CNY,
|
||||
},
|
||||
{
|
||||
models: ["zhipu-chatglm-lite", "zhipu-chatglm-std", "zhipu-chatglm-turbo", "glm-3-turbo"],
|
||||
models: [
|
||||
"zhipu-chatglm-lite",
|
||||
"zhipu-chatglm-std",
|
||||
"zhipu-chatglm-turbo",
|
||||
"glm-3-turbo",
|
||||
],
|
||||
input: 0.005,
|
||||
output: 0.005,
|
||||
currency: Currency.CNY,
|
||||
|
@ -85,10 +85,14 @@ export async function doRegister(
|
||||
}
|
||||
}
|
||||
|
||||
export async function doVerify(email: string, checkout?: boolean): Promise<VerifyResponse> {
|
||||
export async function doVerify(
|
||||
email: string,
|
||||
checkout?: boolean,
|
||||
): Promise<VerifyResponse> {
|
||||
try {
|
||||
const response = await axios.post("/verify", {
|
||||
email, checkout,
|
||||
email,
|
||||
checkout,
|
||||
} as VerifyForm);
|
||||
return response.data as VerifyResponse;
|
||||
} catch (e) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import axios from "axios";
|
||||
import { blobEndpoint } from "@/conf/env.ts";
|
||||
import { trimSuffixes } from "@/utils/base.ts";
|
||||
|
||||
export type BlobParserResponse = {
|
||||
status: boolean;
|
||||
@ -15,11 +16,16 @@ export type FileObject = {
|
||||
|
||||
export type FileArray = FileObject[];
|
||||
|
||||
export async function blobParser(file: File): Promise<BlobParserResponse> {
|
||||
export async function blobParser(
|
||||
file: File,
|
||||
model: string,
|
||||
): Promise<BlobParserResponse> {
|
||||
const endpoint = trimSuffixes(blobEndpoint, ["/upload", "/"]);
|
||||
|
||||
try {
|
||||
const resp = await axios.post(
|
||||
`${blobEndpoint}/upload`,
|
||||
{ file },
|
||||
`${endpoint}/upload`,
|
||||
{ file, model },
|
||||
{
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
},
|
||||
|
@ -77,7 +77,7 @@ function FileProvider({ files, dispatch }: FileProviderProps) {
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
const resp = await blobParser(file);
|
||||
const resp = await blobParser(file, model);
|
||||
clearTimeout(timeout);
|
||||
|
||||
if (!resp.status) {
|
||||
|
@ -102,9 +102,9 @@ function reducer(state: ChargeProps, action: any): ChargeProps {
|
||||
if (action.payload.trim().length === 0) return state;
|
||||
return state.models.includes(action.payload)
|
||||
? {
|
||||
...state,
|
||||
models: state.models.filter((model) => model !== action.payload),
|
||||
}
|
||||
...state,
|
||||
models: state.models.filter((model) => model !== action.payload),
|
||||
}
|
||||
: { ...state, models: [...state.models, action.payload] };
|
||||
case "remove-model":
|
||||
return {
|
||||
|
@ -41,7 +41,7 @@ function Announcement() {
|
||||
>
|
||||
<Bell className={`h-4 w-4`} />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</DialogTrigger>
|
||||
<DialogContent className={`announcement-dialog flex-dialog`}>
|
||||
<DialogHeader notTextCentered>
|
||||
<DialogTitle className={"flex flex-row items-center select-none"}>
|
||||
|
@ -40,7 +40,7 @@ export function Combobox({
|
||||
const [open, setOpen] = React.useState(defaultOpen ?? false);
|
||||
const valueList = React.useMemo((): string[] => {
|
||||
// list set (if some element in current value is not in list, it will be added)
|
||||
const seq = [...list, (value ?? "")].filter((v) => v);
|
||||
const seq = [...list, value ?? ""].filter((v) => v);
|
||||
const set = new Set(seq);
|
||||
return [...set];
|
||||
}, [list]);
|
||||
|
@ -142,7 +142,6 @@ const DialogAction = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
);
|
||||
DialogAction.displayName = "DialogAction";
|
||||
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
import { syncSiteInfo } from "@/admin/api/info.ts";
|
||||
import { setAxiosConfig } from "@/conf/api.ts";
|
||||
|
||||
export const version = "3.10.8"; // version of the current build
|
||||
export const version = "3.10.9"; // version of the current build
|
||||
export const dev: boolean = getDev(); // is in development mode (for debugging, in localhost origin)
|
||||
export const deploy: boolean = true; // is production environment (for api endpoint)
|
||||
export const tokenField = getTokenField(deploy); // token field name for storing token
|
||||
|
@ -74,7 +74,7 @@ function Wrapper({ onSend }: WrapperProps) {
|
||||
const target = ref.current as HTMLInputElement | null;
|
||||
if (!target) return;
|
||||
target.focus();
|
||||
target.removeEventListener("keydown", () => { });
|
||||
target.removeEventListener("keydown", () => {});
|
||||
target.addEventListener("keydown", (e) => {
|
||||
if (isEnter(e)) {
|
||||
// cannot use model here, because model is not updated
|
||||
@ -86,7 +86,7 @@ function Wrapper({ onSend }: WrapperProps) {
|
||||
ref.current &&
|
||||
(ref.current as HTMLInputElement).removeEventListener(
|
||||
"keydown",
|
||||
() => { },
|
||||
() => {},
|
||||
);
|
||||
};
|
||||
}, [ref]);
|
||||
|
@ -845,7 +845,9 @@ function Search({ data, dispatch, onChange }: CompProps<SearchState>) {
|
||||
max={50}
|
||||
/>
|
||||
</ParagraphItem>
|
||||
<ParagraphDescription border>{t("admin.system.searchTip")}</ParagraphDescription>
|
||||
<ParagraphDescription border>
|
||||
{t("admin.system.searchTip")}
|
||||
</ParagraphDescription>
|
||||
<ParagraphFooter>
|
||||
<div className={`grow`} />
|
||||
<Button
|
||||
|
@ -94,7 +94,9 @@ export function isUrl(value: string): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
export function isEnter<T extends HTMLElement>(e: React.KeyboardEvent<T> | KeyboardEvent): boolean {
|
||||
export function isEnter<T extends HTMLElement>(
|
||||
e: React.KeyboardEvent<T> | KeyboardEvent,
|
||||
): boolean {
|
||||
return e.key === "Enter" && e.keyCode != 229;
|
||||
}
|
||||
|
||||
@ -125,3 +127,10 @@ export function getHostName(url: string): string {
|
||||
export function isB64Image(value: string): boolean {
|
||||
return /data:image\/([^;]+);base64,([a-zA-Z0-9+/=]+)/g.test(value);
|
||||
}
|
||||
|
||||
export function trimSuffixes(value: string, suffixes: string[]): string {
|
||||
for (const suffix of suffixes) {
|
||||
if (value.endsWith(suffix)) return value.slice(0, -suffix.length);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user