Spaces:
Sleeping
Sleeping
adapt to using ERNIE models
Browse filesSigned-off-by: Zhang Jun <jzhang533@gmail.com>
- .gitattributes +1 -0
- README.md +1 -1
- app/api/ask-ai/route.ts +18 -10
- components/editor/ask-ai/index.tsx +8 -21
- components/editor/ask-ai/settings.tsx +26 -129
- components/editor/footer/index.tsx +8 -10
- lib/providers.ts +10 -3
.gitattributes
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
|
| 2 |
|
| 3 |
|
| 4 |
# DeepSite v2 π
|
|
|
|
| 1 |
+
This is being adapted for using ERNIE4.5 models
|
| 2 |
|
| 3 |
|
| 4 |
# DeepSite v2 π
|
app/api/ask-ai/route.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
| 1 |
-
/* eslint-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import type { NextRequest } from "next/server";
|
| 3 |
import { NextResponse } from "next/server";
|
| 4 |
import OpenAI from "openai";
|
|
@@ -45,6 +52,7 @@ export async function POST(request: NextRequest) {
|
|
| 45 |
try {
|
| 46 |
const chatCompletion = await openai.chat.completions.create({
|
| 47 |
model,
|
|
|
|
| 48 |
stream: true,
|
| 49 |
messages: [
|
| 50 |
{ role: "system", content: INITIAL_SYSTEM_PROMPT },
|
|
@@ -71,14 +79,13 @@ export async function POST(request: NextRequest) {
|
|
| 71 |
encoder.encode("\n[ERROR] Model returned empty response.\n")
|
| 72 |
);
|
| 73 |
}
|
| 74 |
-
} catch (error:
|
| 75 |
await writer.write(
|
| 76 |
encoder.encode(
|
| 77 |
JSON.stringify({
|
| 78 |
ok: false,
|
| 79 |
message:
|
| 80 |
-
error.message
|
| 81 |
-
"An error occurred while processing your request.",
|
| 82 |
})
|
| 83 |
)
|
| 84 |
);
|
|
@@ -88,12 +95,12 @@ export async function POST(request: NextRequest) {
|
|
| 88 |
})();
|
| 89 |
|
| 90 |
return response;
|
| 91 |
-
} catch (error:
|
| 92 |
return NextResponse.json(
|
| 93 |
{
|
| 94 |
ok: false,
|
| 95 |
message:
|
| 96 |
-
error
|
| 97 |
},
|
| 98 |
{ status: 500 }
|
| 99 |
);
|
|
@@ -113,8 +120,8 @@ export async function PUT(request: NextRequest) {
|
|
| 113 |
} = body;
|
| 114 |
|
| 115 |
const openai = new OpenAI({
|
| 116 |
-
apiKey:
|
| 117 |
-
baseURL:
|
| 118 |
});
|
| 119 |
|
| 120 |
if (!prompt || !html) {
|
|
@@ -127,6 +134,7 @@ export async function PUT(request: NextRequest) {
|
|
| 127 |
try {
|
| 128 |
const response = await openai.chat.completions.create({
|
| 129 |
model,
|
|
|
|
| 130 |
messages: [
|
| 131 |
{ role: "system", content: FOLLOW_UP_SYSTEM_PROMPT },
|
| 132 |
{
|
|
@@ -213,12 +221,12 @@ export async function PUT(request: NextRequest) {
|
|
| 213 |
html: newHtml,
|
| 214 |
updatedLines,
|
| 215 |
});
|
| 216 |
-
} catch (error:
|
| 217 |
return NextResponse.json(
|
| 218 |
{
|
| 219 |
ok: false,
|
| 220 |
message:
|
| 221 |
-
error.message
|
| 222 |
},
|
| 223 |
{ status: 500 }
|
| 224 |
);
|
|
|
|
| 1 |
+
/* eslint-disab const { prompt, model, redesignMarkdown, html, apiKey, baseUrl, maxTokens } = body;
|
| 2 |
+
|
| 3 |
+
const openai = new OpenAI({
|
| 4 |
+
apiKey: process.env.OPENAI_API_KEY || apiKey || "",
|
| 5 |
+
baseURL: process.env.OPENAI_BASE_URL || baseUrl,
|
| 6 |
+
});
|
| 7 |
+
|
| 8 |
+
if (!model || (!prompt && !redesignMarkdown)) {script-eslint/no-explicit-any */
|
| 9 |
import type { NextRequest } from "next/server";
|
| 10 |
import { NextResponse } from "next/server";
|
| 11 |
import OpenAI from "openai";
|
|
|
|
| 52 |
try {
|
| 53 |
const chatCompletion = await openai.chat.completions.create({
|
| 54 |
model,
|
| 55 |
+
max_completion_tokens: 64000,
|
| 56 |
stream: true,
|
| 57 |
messages: [
|
| 58 |
{ role: "system", content: INITIAL_SYSTEM_PROMPT },
|
|
|
|
| 79 |
encoder.encode("\n[ERROR] Model returned empty response.\n")
|
| 80 |
);
|
| 81 |
}
|
| 82 |
+
} catch (error: unknown) {
|
| 83 |
await writer.write(
|
| 84 |
encoder.encode(
|
| 85 |
JSON.stringify({
|
| 86 |
ok: false,
|
| 87 |
message:
|
| 88 |
+
error instanceof Error ? error.message : "An error occurred while processing your request.",
|
|
|
|
| 89 |
})
|
| 90 |
)
|
| 91 |
);
|
|
|
|
| 95 |
})();
|
| 96 |
|
| 97 |
return response;
|
| 98 |
+
} catch (error: unknown) {
|
| 99 |
return NextResponse.json(
|
| 100 |
{
|
| 101 |
ok: false,
|
| 102 |
message:
|
| 103 |
+
error instanceof Error ? error.message : "An error occurred while processing your request.",
|
| 104 |
},
|
| 105 |
{ status: 500 }
|
| 106 |
);
|
|
|
|
| 120 |
} = body;
|
| 121 |
|
| 122 |
const openai = new OpenAI({
|
| 123 |
+
apiKey: process.env.OPENAI_API_KEY || apiKey || "",
|
| 124 |
+
baseURL: process.env.OPENAI_BASE_URL || baseUrl,
|
| 125 |
});
|
| 126 |
|
| 127 |
if (!prompt || !html) {
|
|
|
|
| 134 |
try {
|
| 135 |
const response = await openai.chat.completions.create({
|
| 136 |
model,
|
| 137 |
+
max_completion_tokens: 64000,
|
| 138 |
messages: [
|
| 139 |
{ role: "system", content: FOLLOW_UP_SYSTEM_PROMPT },
|
| 140 |
{
|
|
|
|
| 221 |
html: newHtml,
|
| 222 |
updatedLines,
|
| 223 |
});
|
| 224 |
+
} catch (error: unknown) {
|
| 225 |
return NextResponse.json(
|
| 226 |
{
|
| 227 |
ok: false,
|
| 228 |
message:
|
| 229 |
+
error instanceof Error ? error.message : "An error occurred while processing your request.",
|
| 230 |
},
|
| 231 |
{ status: 500 }
|
| 232 |
);
|
components/editor/ask-ai/index.tsx
CHANGED
|
@@ -54,24 +54,24 @@ export function AskAI({
|
|
| 54 |
const [hasAsked, setHasAsked] = useState(false);
|
| 55 |
const [previousPrompt, setPreviousPrompt] = useState("");
|
| 56 |
const [provider, setProvider] = useLocalStorage("provider", "auto");
|
| 57 |
-
const [openProvider, setOpenProvider] = useState(false);
|
| 58 |
-
const [providerError, setProviderError] = useState("");
|
| 59 |
const [think, setThink] = useState<string | undefined>(undefined);
|
| 60 |
const [openThink, setOpenThink] = useState(false);
|
| 61 |
const [isThinking, setIsThinking] = useState(true);
|
| 62 |
const [controller, setController] = useState<AbortController | null>(null);
|
| 63 |
const [isFollowUp, setIsFollowUp] = useState(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
-
const getModel = () =>
|
| 66 |
-
typeof window !== "undefined"
|
| 67 |
-
? localStorage.getItem("openai_model") || "gpt-4o-mini"
|
| 68 |
-
: "gpt-4o-mini";
|
| 69 |
|
| 70 |
const callAi = async (redesignMarkdown?: string) => {
|
| 71 |
if (isAiWorking) return;
|
| 72 |
if (!redesignMarkdown && !prompt.trim()) return;
|
| 73 |
setisAiWorking(true);
|
| 74 |
-
setProviderError("");
|
| 75 |
setThink("");
|
| 76 |
setOpenThink(false);
|
| 77 |
setIsThinking(true);
|
|
@@ -88,8 +88,6 @@ export function AskAI({
|
|
| 88 |
const selectedElementHtml = selectedElement
|
| 89 |
? selectedElement.outerHTML
|
| 90 |
: "";
|
| 91 |
-
const apiKey = localStorage.getItem("openai_api_key");
|
| 92 |
-
const baseUrl = localStorage.getItem("openai_base_url");
|
| 93 |
const model = getModel();
|
| 94 |
const request = await fetch("/api/ask-ai", {
|
| 95 |
method: "PUT",
|
|
@@ -100,8 +98,6 @@ export function AskAI({
|
|
| 100 |
model,
|
| 101 |
html,
|
| 102 |
selectedElementHtml,
|
| 103 |
-
apiKey,
|
| 104 |
-
baseUrl,
|
| 105 |
}),
|
| 106 |
headers: {
|
| 107 |
"Content-Type": "application/json",
|
|
@@ -124,8 +120,6 @@ export function AskAI({
|
|
| 124 |
if (audio.current) audio.current.play();
|
| 125 |
}
|
| 126 |
} else {
|
| 127 |
-
const apiKey = localStorage.getItem("openai_api_key");
|
| 128 |
-
const baseUrl = localStorage.getItem("openai_base_url");
|
| 129 |
const model = getModel();
|
| 130 |
const request = await fetch("/api/ask-ai", {
|
| 131 |
method: "POST",
|
|
@@ -135,8 +129,6 @@ export function AskAI({
|
|
| 135 |
model,
|
| 136 |
html: isSameHtml ? "" : html,
|
| 137 |
redesignMarkdown,
|
| 138 |
-
apiKey,
|
| 139 |
-
baseUrl,
|
| 140 |
}),
|
| 141 |
headers: {
|
| 142 |
"Content-Type": "application/json",
|
|
@@ -413,16 +405,11 @@ export function AskAI({
|
|
| 413 |
</div>
|
| 414 |
<div className="flex items-center justify-end gap-2">
|
| 415 |
<Settings
|
| 416 |
-
provider={provider as string}
|
| 417 |
model={getModel()}
|
| 418 |
-
onChange={setProvider}
|
| 419 |
onModelChange={(newModel: string) => {
|
|
|
|
| 420 |
localStorage.setItem("openai_model", newModel);
|
| 421 |
}}
|
| 422 |
-
open={openProvider}
|
| 423 |
-
error={providerError}
|
| 424 |
-
isFollowUp={!isSameHtml && isFollowUp}
|
| 425 |
-
onClose={setOpenProvider}
|
| 426 |
/>
|
| 427 |
<Button
|
| 428 |
size="iconXs"
|
|
|
|
| 54 |
const [hasAsked, setHasAsked] = useState(false);
|
| 55 |
const [previousPrompt, setPreviousPrompt] = useState("");
|
| 56 |
const [provider, setProvider] = useLocalStorage("provider", "auto");
|
|
|
|
|
|
|
| 57 |
const [think, setThink] = useState<string | undefined>(undefined);
|
| 58 |
const [openThink, setOpenThink] = useState(false);
|
| 59 |
const [isThinking, setIsThinking] = useState(true);
|
| 60 |
const [controller, setController] = useState<AbortController | null>(null);
|
| 61 |
const [isFollowUp, setIsFollowUp] = useState(true);
|
| 62 |
+
const [currentModel, setCurrentModel] = useState(() => {
|
| 63 |
+
if (typeof window !== "undefined") {
|
| 64 |
+
return localStorage.getItem("openai_model") || MODELS[0].value;
|
| 65 |
+
}
|
| 66 |
+
return MODELS[0].value;
|
| 67 |
+
});
|
| 68 |
|
| 69 |
+
const getModel = () => currentModel;
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
const callAi = async (redesignMarkdown?: string) => {
|
| 72 |
if (isAiWorking) return;
|
| 73 |
if (!redesignMarkdown && !prompt.trim()) return;
|
| 74 |
setisAiWorking(true);
|
|
|
|
| 75 |
setThink("");
|
| 76 |
setOpenThink(false);
|
| 77 |
setIsThinking(true);
|
|
|
|
| 88 |
const selectedElementHtml = selectedElement
|
| 89 |
? selectedElement.outerHTML
|
| 90 |
: "";
|
|
|
|
|
|
|
| 91 |
const model = getModel();
|
| 92 |
const request = await fetch("/api/ask-ai", {
|
| 93 |
method: "PUT",
|
|
|
|
| 98 |
model,
|
| 99 |
html,
|
| 100 |
selectedElementHtml,
|
|
|
|
|
|
|
| 101 |
}),
|
| 102 |
headers: {
|
| 103 |
"Content-Type": "application/json",
|
|
|
|
| 120 |
if (audio.current) audio.current.play();
|
| 121 |
}
|
| 122 |
} else {
|
|
|
|
|
|
|
| 123 |
const model = getModel();
|
| 124 |
const request = await fetch("/api/ask-ai", {
|
| 125 |
method: "POST",
|
|
|
|
| 129 |
model,
|
| 130 |
html: isSameHtml ? "" : html,
|
| 131 |
redesignMarkdown,
|
|
|
|
|
|
|
| 132 |
}),
|
| 133 |
headers: {
|
| 134 |
"Content-Type": "application/json",
|
|
|
|
| 405 |
</div>
|
| 406 |
<div className="flex items-center justify-end gap-2">
|
| 407 |
<Settings
|
|
|
|
| 408 |
model={getModel()}
|
|
|
|
| 409 |
onModelChange={(newModel: string) => {
|
| 410 |
+
setCurrentModel(newModel);
|
| 411 |
localStorage.setItem("openai_model", newModel);
|
| 412 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 413 |
/>
|
| 414 |
<Button
|
| 415 |
size="iconXs"
|
components/editor/ask-ai/settings.tsx
CHANGED
|
@@ -1,142 +1,39 @@
|
|
| 1 |
-
import { PiGearSixFill } from "react-icons/pi";
|
| 2 |
-
import { useState, useEffect } from "react";
|
| 3 |
-
|
| 4 |
import {
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
import {
|
| 12 |
-
import { useUpdateEffect } from "react-use";
|
| 13 |
-
import { Input } from "@/components/ui/input";
|
| 14 |
-
import { toast } from "sonner";
|
| 15 |
|
| 16 |
export function Settings({
|
| 17 |
-
open,
|
| 18 |
-
onClose,
|
| 19 |
-
provider,
|
| 20 |
model,
|
| 21 |
-
|
| 22 |
-
onChange,
|
| 23 |
}: {
|
| 24 |
-
open: boolean;
|
| 25 |
-
provider: string;
|
| 26 |
model: string;
|
| 27 |
-
error?: string;
|
| 28 |
-
isFollowUp?: boolean;
|
| 29 |
-
onClose: React.Dispatch<React.SetStateAction<boolean>>;
|
| 30 |
-
onChange: (provider: string) => void;
|
| 31 |
onModelChange: (model: string) => void;
|
| 32 |
}) {
|
| 33 |
-
const
|
| 34 |
-
|
| 35 |
-
const [customModel, setCustomModel] = useState("");
|
| 36 |
-
|
| 37 |
-
useEffect(() => {
|
| 38 |
-
setApiKey(localStorage.getItem("openai_api_key") || "");
|
| 39 |
-
setBaseUrl(localStorage.getItem("openai_base_url") || "");
|
| 40 |
-
setCustomModel(localStorage.getItem("openai_model") || "");
|
| 41 |
-
}, [open]);
|
| 42 |
-
|
| 43 |
-
const modelAvailableProviders = useMemo(() => {
|
| 44 |
-
const availableProviders = MODELS.find(
|
| 45 |
-
(m: { value: string }) => m.value === model
|
| 46 |
-
)?.providers;
|
| 47 |
-
if (!availableProviders) return Object.keys(PROVIDERS);
|
| 48 |
-
return Object.keys(PROVIDERS).filter((id) =>
|
| 49 |
-
availableProviders.includes(id)
|
| 50 |
-
);
|
| 51 |
-
}, [model]);
|
| 52 |
-
|
| 53 |
-
useUpdateEffect(() => {
|
| 54 |
-
if (provider !== "auto" && !modelAvailableProviders.includes(provider)) {
|
| 55 |
-
onChange("auto");
|
| 56 |
-
}
|
| 57 |
-
}, [model, provider]);
|
| 58 |
-
|
| 59 |
-
const handleSaveSettings = () => {
|
| 60 |
-
localStorage.setItem("openai_api_key", apiKey);
|
| 61 |
-
localStorage.setItem("openai_base_url", baseUrl);
|
| 62 |
-
localStorage.setItem("openai_model", customModel);
|
| 63 |
-
toast.success("Settings saved!");
|
| 64 |
-
onClose(false);
|
| 65 |
};
|
| 66 |
|
| 67 |
return (
|
| 68 |
-
<
|
| 69 |
-
<
|
| 70 |
-
<
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
{error !== "" && (
|
| 85 |
-
<p className="text-red-500 text-sm font-medium mb-2 flex items-center justify-between bg-red-500/10 p-2 rounded-md">
|
| 86 |
-
{error}
|
| 87 |
-
</p>
|
| 88 |
-
)}
|
| 89 |
-
<label className="block">
|
| 90 |
-
<p className="text-neutral-300 text-sm mb-2.5">
|
| 91 |
-
API Key
|
| 92 |
-
</p>
|
| 93 |
-
<Input
|
| 94 |
-
type="password"
|
| 95 |
-
placeholder="Enter your api key"
|
| 96 |
-
value={apiKey}
|
| 97 |
-
onChange={(e) => setApiKey(e.target.value)}
|
| 98 |
-
className="!bg-neutral-800 !border-neutral-700 !text-neutral-200"
|
| 99 |
-
/>
|
| 100 |
-
</label>
|
| 101 |
-
<label className="block">
|
| 102 |
-
<p className="text-neutral-300 text-sm mb-2.5">
|
| 103 |
-
Base URL
|
| 104 |
-
</p>
|
| 105 |
-
<Input
|
| 106 |
-
type="text"
|
| 107 |
-
placeholder="e.g., http://127.0.0.1:11434/v1"
|
| 108 |
-
value={baseUrl}
|
| 109 |
-
onChange={(e) => setBaseUrl(e.target.value)}
|
| 110 |
-
className="!bg-neutral-800 !border-neutral-700 !text-neutral-200"
|
| 111 |
-
/>
|
| 112 |
-
</label>
|
| 113 |
-
<label className="block">
|
| 114 |
-
<p className="text-neutral-300 text-sm mb-2.5">
|
| 115 |
-
Custom Model
|
| 116 |
-
</p>
|
| 117 |
-
<Input
|
| 118 |
-
type="text"
|
| 119 |
-
placeholder="e.g., gemma3:1b"
|
| 120 |
-
value={customModel || "gemma3:1b"}
|
| 121 |
-
onChange={(e) => setCustomModel(e.target.value)}
|
| 122 |
-
className="!bg-neutral-800 !border-neutral-700 !text-neutral-200"
|
| 123 |
-
/>
|
| 124 |
-
</label>
|
| 125 |
-
<Button
|
| 126 |
-
variant="default"
|
| 127 |
-
size="sm"
|
| 128 |
-
onClick={handleSaveSettings}
|
| 129 |
-
className="mt-2 w-full"
|
| 130 |
-
>
|
| 131 |
-
Save Settings
|
| 132 |
-
</Button>
|
| 133 |
-
<div className="bg-amber-500/10 border-amber-500/10 p-3 text-xs text-amber-500 border rounded-lg">
|
| 134 |
-
Accepts any OpenAI-compatible provider. Enter the corresponding API key and base URL (e.g., OpenRouter, DeepSeek, etc.).
|
| 135 |
-
</div>
|
| 136 |
-
|
| 137 |
-
</main>
|
| 138 |
-
</PopoverContent>
|
| 139 |
-
</Popover>
|
| 140 |
-
</div>
|
| 141 |
);
|
| 142 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import {
|
| 2 |
+
Select,
|
| 3 |
+
SelectContent,
|
| 4 |
+
SelectItem,
|
| 5 |
+
SelectTrigger,
|
| 6 |
+
SelectValue,
|
| 7 |
+
} from "@/components/ui/select";
|
| 8 |
+
import { MODELS } from "@/lib/providers";
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
export function Settings({
|
|
|
|
|
|
|
|
|
|
| 11 |
model,
|
| 12 |
+
onModelChange,
|
|
|
|
| 13 |
}: {
|
|
|
|
|
|
|
| 14 |
model: string;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
onModelChange: (model: string) => void;
|
| 16 |
}) {
|
| 17 |
+
const handleModelChange = (newModel: string) => {
|
| 18 |
+
onModelChange(newModel);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
};
|
| 20 |
|
| 21 |
return (
|
| 22 |
+
<Select value={model} onValueChange={handleModelChange}>
|
| 23 |
+
<SelectTrigger className="bg-neutral-800 border-neutral-700 text-neutral-200 h-8 min-w-[180px]">
|
| 24 |
+
<SelectValue placeholder="Select a model" />
|
| 25 |
+
</SelectTrigger>
|
| 26 |
+
<SelectContent className="bg-neutral-800 border-neutral-700">
|
| 27 |
+
{MODELS.map((modelOption) => (
|
| 28 |
+
<SelectItem
|
| 29 |
+
key={modelOption.value}
|
| 30 |
+
value={modelOption.value}
|
| 31 |
+
className="text-neutral-200 hover:bg-neutral-700 focus:bg-neutral-700"
|
| 32 |
+
>
|
| 33 |
+
{modelOption.label}
|
| 34 |
+
</SelectItem>
|
| 35 |
+
))}
|
| 36 |
+
</SelectContent>
|
| 37 |
+
</Select>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
);
|
| 39 |
}
|
components/editor/footer/index.tsx
CHANGED
|
@@ -51,16 +51,7 @@ export function Footer({
|
|
| 51 |
return (
|
| 52 |
<footer className="border-t bg-slate-200 border-slate-300 dark:bg-neutral-950 dark:border-neutral-800 px-3 py-2 flex items-center justify-between sticky bottom-0 z-20">
|
| 53 |
<div className="flex items-center gap-2">
|
| 54 |
-
{user &&
|
| 55 |
-
(user?.isLocalUse ? (
|
| 56 |
-
<>
|
| 57 |
-
<div className="max-w-max bg-amber-500/10 rounded-full px-3 py-1 text-amber-500 border border-amber-500/20 text-sm font-semibold">
|
| 58 |
-
Local Usage
|
| 59 |
-
</div>
|
| 60 |
-
</>
|
| 61 |
-
) : (
|
| 62 |
-
<UserMenu className="!p-1 !pr-3 !h-auto" />
|
| 63 |
-
))}
|
| 64 |
{user && <p className="text-neutral-700">|</p>}
|
| 65 |
<Button size="sm" variant="secondary" onClick={onReset}>
|
| 66 |
<MdAdd className="text-sm" />
|
|
@@ -81,6 +72,13 @@ export function Footer({
|
|
| 81 |
50% { opacity: 0.2; }
|
| 82 |
}
|
| 83 |
`}</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
<span className="max-lg:hidden"><a
|
| 85 |
href="https://github.com/MartinsMessias/deepsite-locally"
|
| 86 |
target="_blank"
|
|
|
|
| 51 |
return (
|
| 52 |
<footer className="border-t bg-slate-200 border-slate-300 dark:bg-neutral-950 dark:border-neutral-800 px-3 py-2 flex items-center justify-between sticky bottom-0 z-20">
|
| 53 |
<div className="flex items-center gap-2">
|
| 54 |
+
{user && <UserMenu className="!p-1 !pr-3 !h-auto" />}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
{user && <p className="text-neutral-700">|</p>}
|
| 56 |
<Button size="sm" variant="secondary" onClick={onReset}>
|
| 57 |
<MdAdd className="text-sm" />
|
|
|
|
| 72 |
50% { opacity: 0.2; }
|
| 73 |
}
|
| 74 |
`}</style>
|
| 75 |
+
<span className="max-lg:hidden"><a
|
| 76 |
+
href="https://github.com/MartinsMessias/deepsite-locally"
|
| 77 |
+
target="_blank"
|
| 78 |
+
className="text-xs lg:text-sm font-medium py-2 px-3 lg:px-4 rounded-lg flex items-center transition-all duration-100 cursor-pointer"
|
| 79 |
+
>
|
| 80 |
+
<span style={{ animation: 'blink-star 2s infinite' }}>β¨</span> <span>Visit ERNIE Bot</span>
|
| 81 |
+
</a></span>
|
| 82 |
<span className="max-lg:hidden"><a
|
| 83 |
href="https://github.com/MartinsMessias/deepsite-locally"
|
| 84 |
target="_blank"
|
lib/providers.ts
CHANGED
|
@@ -8,10 +8,17 @@ export const PROVIDERS = {
|
|
| 8 |
|
| 9 |
export const MODELS = [
|
| 10 |
{
|
| 11 |
-
value: "
|
| 12 |
-
label: "
|
| 13 |
providers: ["openai-compatible"],
|
| 14 |
autoProvider: "openai-compatible",
|
| 15 |
-
isThinker:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
},
|
| 17 |
];
|
|
|
|
| 8 |
|
| 9 |
export const MODELS = [
|
| 10 |
{
|
| 11 |
+
value: "ernie-x1.1-preview",
|
| 12 |
+
label: "ERNIE X1.1 Preview",
|
| 13 |
providers: ["openai-compatible"],
|
| 14 |
autoProvider: "openai-compatible",
|
| 15 |
+
isThinker: true,
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
value: "ernie-4.5-21b-a3b-thinking",
|
| 19 |
+
label: "ERNIE-4.5-21B-A3B-Thinking",
|
| 20 |
+
providers: ["openai-compatible"],
|
| 21 |
+
autoProvider: "openai-compatible",
|
| 22 |
+
isThinker: true,
|
| 23 |
},
|
| 24 |
];
|