|
1 |
| -import { Button, Input, List, Tooltip, Typography } from "@material-tailwind/react" |
2 |
| -import { type ChangeEvent, Fragment, useState } from "react" |
3 |
| -import { toast } from "sonner/dist" |
| 1 | +import { List } from "@material-tailwind/react" |
| 2 | +import { type ChangeEvent, Fragment } from "react" |
4 | 3 | import type { StateProxy } from "~hooks/binding"
|
5 |
| -import type { LLMProviders, LLMTypes } from "~llms" |
6 |
| -import createLLMProvider from "~llms" |
7 | 4 | import ExperienmentFeatureIcon from "~options/components/ExperientmentFeatureIcon"
|
8 |
| -import Selector from "~options/components/Selector" |
9 | 5 | import SwitchListItem from "~options/components/SwitchListItem"
|
10 | 6 |
|
11 |
| - |
12 |
| - |
13 | 7 | export type AISchema = {
|
14 |
| - enabled: boolean |
15 |
| - provider: LLMTypes |
16 |
| - |
17 |
| - // cloudflare settings |
18 |
| - accountId?: string |
19 |
| - apiToken?: string |
| 8 | + summarizeEnabled: boolean |
20 | 9 | }
|
21 | 10 |
|
22 | 11 |
|
23 | 12 | export const aiDefaultSettings: Readonly<AISchema> = {
|
24 |
| - enabled: false, |
25 |
| - provider: 'worker' |
| 13 | + summarizeEnabled: false |
26 | 14 | }
|
27 | 15 |
|
28 | 16 |
|
29 | 17 | function AIFragment({ state, useHandler }: StateProxy<AISchema>): JSX.Element {
|
30 | 18 |
|
31 |
| - const [validating, setValidating] = useState(false) |
32 |
| - |
33 |
| - const handler = useHandler<ChangeEvent<HTMLInputElement>, string>((e) => e.target.value) |
34 | 19 | const checker = useHandler<ChangeEvent<HTMLInputElement>, boolean>((e) => e.target.checked)
|
35 | 20 |
|
36 |
| - const onValidate = async () => { |
37 |
| - setValidating(true) |
38 |
| - try { |
39 |
| - let provider: LLMProviders; |
40 |
| - if (state.provider === 'qwen') { |
41 |
| - provider = createLLMProvider(state.provider, state.accountId, state.apiToken) |
42 |
| - } else { |
43 |
| - provider = createLLMProvider(state.provider) |
44 |
| - } |
45 |
| - await provider.validate() |
46 |
| - toast.success('配置可用!') |
47 |
| - } catch (e) { |
48 |
| - toast.error('配置不可用: ' + e.message) |
49 |
| - } finally { |
50 |
| - setValidating(false) |
51 |
| - } |
52 |
| - } |
53 |
| - |
54 | 21 | return (
|
55 | 22 | <Fragment>
|
56 | 23 | <List className="col-span-2 border border-[#808080] rounded-md">
|
57 | 24 | <SwitchListItem
|
58 | 25 | data-testid="ai-enabled"
|
59 | 26 | label="启用同传字幕AI总结"
|
60 |
| - hint="此功能将采用通义大模型对同传字幕进行总结" |
61 |
| - value={state.enabled} |
62 |
| - onChange={checker('enabled')} |
| 27 | + hint="此功能将采用大语言模型对同传字幕进行总结" |
| 28 | + value={state.summarizeEnabled} |
| 29 | + onChange={checker('summarizeEnabled')} |
63 | 30 | marker={<ExperienmentFeatureIcon />}
|
64 | 31 | />
|
65 | 32 | </List>
|
66 |
| - {state.enabled && ( |
67 |
| - <Fragment> |
68 |
| - <Selector<typeof state.provider> |
69 |
| - className="col-span-2" |
70 |
| - data-testid="ai-provider" |
71 |
| - label="技术来源" |
72 |
| - value={state.provider} |
73 |
| - onChange={e => state.provider = e} |
74 |
| - options={[ |
75 |
| - { label: 'Cloudflare AI', value: 'qwen' }, |
76 |
| - { label: '有限度服务器', value: 'worker' }, |
77 |
| - { label: 'Chrome 浏览器内置 AI', value: 'nano' } |
78 |
| - ]} |
79 |
| - /> |
80 |
| - {state.provider === 'qwen' && ( |
81 |
| - <Fragment> |
82 |
| - <Typography |
83 |
| - className="flex items-center gap-1 font-normal dark:text-gray-200 col-span-2" |
84 |
| - > |
85 |
| - <svg |
86 |
| - xmlns="http://www.w3.org/2000/svg" |
87 |
| - viewBox="0 0 24 24" |
88 |
| - fill="currentColor" |
89 |
| - className="-mt-px h-6 w-6" |
90 |
| - > |
91 |
| - <path |
92 |
| - fillRule="evenodd" |
93 |
| - d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z" |
94 |
| - clipRule="evenodd" |
95 |
| - /> |
96 |
| - </svg> |
97 |
| - <Typography className="underline" as="a" href="https://linux.do/t/topic/34037" target="_blank">点击此处</Typography> |
98 |
| - 查看如何获得 Cloudflare API Token 和 Account ID |
99 |
| - </Typography> |
100 |
| - <Input |
101 |
| - data-testid="cf-account-id" |
102 |
| - crossOrigin="anonymous" |
103 |
| - variant="static" |
104 |
| - required |
105 |
| - label="Cloudflare Account ID" |
106 |
| - value={state.accountId} |
107 |
| - onChange={handler('accountId')} |
108 |
| - /> |
109 |
| - <Input |
110 |
| - data-testid="cf-api-token" |
111 |
| - crossOrigin="anonymous" |
112 |
| - variant="static" |
113 |
| - required |
114 |
| - label="Cloudflare API Token" |
115 |
| - value={state.apiToken} |
116 |
| - onChange={handler('apiToken')} |
117 |
| - /> |
118 |
| - </Fragment> |
119 |
| - )} |
120 |
| - </Fragment> |
121 |
| - )} |
122 |
| - <div className="col-span-2"> |
123 |
| - <Button disabled={validating} onClick={onValidate} color="blue" size="lg" className="group flex items-center justify-center gap-3 text-[1rem] hover:shadow-lg"> |
124 |
| - 验证是否可用 |
125 |
| - <Tooltip content="检查你目前的配置是否可用。若不可用,则无法启用AI总结功能。" placement="top-end"> |
126 |
| - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6"> |
127 |
| - <path strokeLinecap="round" strokeLinejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /> |
128 |
| - </svg> |
129 |
| - </Tooltip> |
130 |
| - </Button> |
131 |
| - </div> |
132 | 33 | </Fragment>
|
133 | 34 | )
|
134 | 35 | }
|
|
0 commit comments