Skip to content

Commit d74647c

Browse files
feat: add Settings Modal components
1 parent cd3a1d0 commit d74647c

File tree

8 files changed

+109
-11
lines changed

8 files changed

+109
-11
lines changed

src/components/Generator.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ export default () => {
217217
const response = await fetch('/api/generate', {
218218
method: 'POST',
219219
body: JSON.stringify({
220+
model: localStorage.getItem('model') || 'gpt-3.5-turbo-1106',
220221
messages: requestMessageList,
221222
time: timestamp,
222223
pass: storagePassword,
@@ -226,6 +227,7 @@ export default () => {
226227
}),
227228
}),
228229
signal: controller.signal,
230+
headers: { authorization: `Bearer ${localStorage.getItem('apiKey')}` },
229231
})
230232
if (!response.ok) {
231233
const error = await response.json()

src/components/Header.svelte

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<script>
2+
import Settings from './Settings.svelte'
23
import Themetoggle from './Themetoggle.svelte'
4+
5+
let showSettings = false
36
</script>
47

58
<header>
@@ -12,12 +15,9 @@
1215
</a>
1316
</div>
1417
<div class="flex">
15-
<a class="grid h-10 w-10 place-items-center rounded-md transition-background-color hover:bg-$c-fg-5 <md:transition-colors" href="https://free-chat.asia/group.html">
16-
<span class="i-mdi-wechat text-lg" />
17-
</a>
18-
<a class="grid h-10 w-10 place-items-center rounded-md transition-background-color hover:bg-$c-fg-5 <md:transition-colors" href="https://free-chat.asia/sponsorship.html">
19-
<span class="i-mingcute-pig-money-fill text-lg" />
20-
</a>
18+
<button class="grid h-10 w-10 place-items-center rounded-md transition-background-color hover:bg-$c-fg-5 <md:transition-colors" on:click={() => (showSettings = !showSettings)}>
19+
<span class="i-ph-gear-six-fill text-lg transition-transform duration-300" class:rotate-30={showSettings} />
20+
</button>
2121
<Themetoggle />
2222
</div>
2323
</div>
@@ -27,3 +27,5 @@
2727
</div>
2828
{/if}
2929
</header>
30+
31+
<Settings bind:show={showSettings}></Settings>

src/components/Modal.svelte

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script lang="ts">
2+
export let show = false
3+
export let icon: string
4+
</script>
5+
6+
<div class="pointer-events-none fixed inset-0 z-100 bg-black/10 transition-opacity duration-800 dark:bg-black/50" class:pointer-events-none={!show} class:op-0={!show} />
7+
<section class="pointer-events-none fixed bottom-0 left-0 right-0 z-1000 flex flex-row select-none justify-center tracking-wide transition-opacity duration-500" class:pointer-events-none={!show} class:op-0={!show}>
8+
<div class="m-5vw w-xl flex flex-col gap-3 rounded-lg bg-$c-bg p-5 shadow-xl backdrop-blur-15 [&_a]:(mx-1 border-b-1.5 border-$c-fg-20 pb-0.3 transition-border-color dark:border-$c-fg) [&_a:hover]:(border-$c-fg-60 dark:border-$c-fg-40) dark:bg-#212129c0">
9+
<div class="relative flex flex-row items-center gap-3 text-4xl">
10+
<div class="{icon} absolute right-1/2 translate-x-1/2 -translate-y-1/2" />
11+
<div class="{icon} absolute right-1/2 translate-x-1/2 scale-60 blur-15 -translate-y-1/4" />
12+
</div>
13+
14+
<slot />
15+
16+
{#if $$slots.inside}
17+
<div>
18+
<button type="button" class="grid mt-1 h-fit w-full place-items-center rounded-md bg-$c-fg-5 p-2 outline-none transition-all ease-out active:scale-96 hover:scale-98 hover:bg-$c-fg hover:text-$c-bg focus:(ring-1.5 ring-$c-fg-20) hover:!ring-transparent" on:click={() => (show = !show)}>
19+
<slot name="inside" />
20+
</button>
21+
</div>
22+
{/if}
23+
</div>
24+
</section>

src/components/Settings.svelte

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script lang="ts">
2+
import { slide } from 'svelte/transition'
3+
import { quintIn, quintOut } from 'svelte/easing'
4+
import Modal from './Modal.svelte'
5+
import Selector from './controls/ModelSelector.svelte'
6+
import APIKeyInput from './controls/APIKeyInput.svelte'
7+
8+
export let show: boolean
9+
</script>
10+
11+
<Modal bind:show icon="i-fluent-emoji-flat-eight-pointed-star">
12+
<div class="i-fluent-thumb-like-24-filled text-lg" slot="inside"></div>
13+
{#if show}
14+
<div class="w-full flex flex-col gap-2 -mt-3" in:slide|global={{ easing: quintOut, duration: 800 }} out:slide|global={{ easing: quintIn, duration: 400 }}>
15+
<h3>选择 LLM</h3>
16+
<Selector />
17+
<hr class="mx-0.5 my-3 h-0.5 b-0 rounded-full bg-$c-fg-50 op-10" />
18+
<h3>使用自己的 OpenAI API Key</h3>
19+
<APIKeyInput />
20+
<hr class="mx-0.5 my-3 h-0.5 b-0 rounded-full bg-$c-fg-50 op-10" />
21+
</div>
22+
{/if}
23+
</Modal>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script lang="ts">
2+
import { onMount } from 'svelte'
3+
4+
let apiKey: string
5+
6+
onMount(() => (apiKey = localStorage.getItem('apiKey') ?? ''))
7+
$: typeof localStorage !== 'undefined' && typeof apiKey !== 'undefined' && localStorage.setItem('apiKey', apiKey)
8+
</script>
9+
10+
<input bind:value={apiKey} type="text" placeholder="sk-******** / sess-********" class="rounded-md bg-$c-fg-5 px-2.5 py-2 text-sm font-light font-mono outline-none placeholder:text-$c-fg-30" />
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script lang="ts">
2+
import { onMount } from 'svelte'
3+
import { fly } from 'svelte/transition'
4+
5+
type Model = 'gpt-3.5-turbo-0301' | 'gpt-3.5-turbo-0613' | 'gpt-3.5-turbo-1106';
6+
let model: Model
7+
8+
onMount(() => (model = (localStorage.getItem('model') as Model) || 'gpt-3.5-turbo-1106'))
9+
$: typeof localStorage !== 'undefined' && model && localStorage.setItem('model', model)
10+
</script>
11+
12+
<div class="w-full flex flex-row justify-between gap-1.5 rounded-md bg-$c-fg-5 p-1.5 text-sm">
13+
<input type="radio" name="model" id="0301" hidden on:click={() => (model = 'gpt-3.5-turbo-0301')} checked={model === 'gpt-3.5-turbo-0301'} />
14+
<label for="0301" in:fly={{ duration: 500, y: 10, delay: 200 }}>
15+
<h5 class="text-sm font-mono op-40">gpt-3.5-turbo</h5>
16+
<h4 class="text-2xl font-bold font-mono">0301</h4>
17+
<div class="text-3.2 -translate-y-0.5">梦开始的地方。只支持4K上下文</div>
18+
</label>
19+
<input type="radio" name="model" id="0613" hidden on:click={() => (model = 'gpt-3.5-turbo-0613')} checked={model === 'gpt-3.5-turbo-0613'}/>
20+
<label for="0613" in:fly={{ duration: 500, y: 10, delay: 300 }}>
21+
<h5 class="text-sm font-mono op-40">gpt-3.5-turbo</h5>
22+
<h4 class="text-2xl font-bold font-mono">0613</h4>
23+
<div class="text-3.2 -translate-y-0.5">较新的模型,初次针对系统消息加强了训练</div>
24+
</label>
25+
<input type="radio" name="model" id="1106" hidden on:click={() => (model = 'gpt-3.5-turbo-1106')} checked={model === 'gpt-3.5-turbo-1106'}/>
26+
<label for="1106" in:fly={{ duration: 500, y: 10, delay: 400 }}>
27+
<h5 class="text-sm font-mono op-40">gpt-3.5-turbo</h5>
28+
<h4 class="text-2xl font-bold font-mono">1106</h4>
29+
<div class="text-3.2 -translate-y-0.5">最新、最快、更便宜,但偶尔过于倾向拒绝回答</div>
30+
</label>
31+
</div>
32+
33+
<style>
34+
label {
35+
--uno: w-full flex flex-col rounded px-2 py-1 ring-$c-fg ring-inset transition-all duration-100 ease-out active:scale-95 hover:bg-$c-fg-15 hover:ring-1.5 [:checked+&]:(\!bg-$c-fg text-$c-bg hover:op-80);
36+
}
37+
</style>

src/pages/api/generate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const FORWARD_HEADERS = ['origin', 'referer', 'cookie', 'user-agent', 'via']
1515

1616
export const post: APIRoute = async({ request }) => {
1717
const body = await request.json()
18-
const { sign, time, messages, pass } = body
18+
const { sign, time, messages, pass, model } = body
1919
if (!messages) {
2020
return new Response(JSON.stringify({
2121
error: {
@@ -38,7 +38,7 @@ export const post: APIRoute = async({ request }) => {
3838
}), { status: 401 })
3939
}
4040

41-
const initOptions = generatePayload(request.headers.get('Authorization') ?? `Bearer ${apiKey}`, messages)
41+
const initOptions = generatePayload(request.headers.get('Authorization') ?? `Bearer ${apiKey}`, messages, model)
4242

4343
const headers = initOptions.headers
4444

src/utils/openAI.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import type { ParsedEvent, ReconnectInterval } from 'eventsource-parser'
33
import type { ChatMessage } from '@/types'
44
import type { RequestInit } from 'undici'
55

6-
const model = import.meta.env.OPENAI_API_MODEL || 'gpt-3.5-turbo-1106'
6+
const default_model = import.meta.env.OPENAI_API_MODEL || 'gpt-3.5-turbo-1106'
77
const temperature = Number(import.meta.env.OPENAI_API_TEMPERATURE) || 1
88

9-
export const generatePayload = (authorization: string, messages: ChatMessage[]): RequestInit & { headers: Record<string, string> } => ({
9+
export const generatePayload = (authorization: string, messages: ChatMessage[], model: string): RequestInit & { headers: Record<string, string> } => ({
1010
headers: { 'Content-Type': 'application/json', authorization },
1111
method: 'POST',
12-
body: JSON.stringify({ model, messages, temperature, stream: true }),
12+
body: JSON.stringify({ model: model || default_model, messages, temperature, stream: true }),
1313
})
1414

1515
export const parseOpenAIStream = (rawResponse: Response) => {

0 commit comments

Comments
 (0)