Compare commits
4
Commits
1abd2d1d59
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d157d34fca | ||
|
|
b888d3d3fb | ||
|
|
fa05cfded7 | ||
|
|
5e16a7049f |
+9
-4
@@ -82,17 +82,22 @@ console.log(`[startup] Listening on: http://0.0.0.0:${PORT}`);
|
|||||||
// History helpers
|
// History helpers
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
let historyCache = null;
|
||||||
|
|
||||||
async function readHistory() {
|
async function readHistory() {
|
||||||
|
if (historyCache !== null) return historyCache;
|
||||||
try {
|
try {
|
||||||
const raw = await readFile(HISTORY_FILE, 'utf-8');
|
const raw = await readFile(HISTORY_FILE, 'utf-8');
|
||||||
const parsed = JSON.parse(raw);
|
const parsed = JSON.parse(raw);
|
||||||
return Array.isArray(parsed) ? parsed : [];
|
historyCache = Array.isArray(parsed) ? parsed : [];
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
historyCache = [];
|
||||||
}
|
}
|
||||||
|
return historyCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeHistory(entries) {
|
async function writeHistory(entries) {
|
||||||
|
historyCache = entries;
|
||||||
await writeFile(HISTORY_FILE, JSON.stringify(entries, null, 2), 'utf-8');
|
await writeFile(HISTORY_FILE, JSON.stringify(entries, null, 2), 'utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,7 +406,7 @@ async function handleStyleRandom(req, res) {
|
|||||||
{ role: 'system', content: buildStylePrompt(mode, idea) },
|
{ role: 'system', content: buildStylePrompt(mode, idea) },
|
||||||
{ role: 'user', content: userMsg },
|
{ role: 'user', content: userMsg },
|
||||||
],
|
],
|
||||||
{ max_tokens: 800 },
|
{ max_tokens: 8192 },
|
||||||
signal,
|
signal,
|
||||||
);
|
);
|
||||||
const style = cleanStyleString(content);
|
const style = cleanStyleString(content);
|
||||||
@@ -495,7 +500,7 @@ async function handleGenerate(req, res) {
|
|||||||
{ role: 'system', content: buildSystemPrompt(body) },
|
{ role: 'system', content: buildSystemPrompt(body) },
|
||||||
{ role: 'user', content: buildUserMessage(body) },
|
{ role: 'user', content: buildUserMessage(body) },
|
||||||
],
|
],
|
||||||
{ max_tokens: 4000 },
|
{ max_tokens: 32768 },
|
||||||
signal,
|
signal,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+11
-7
@@ -1,20 +1,24 @@
|
|||||||
|
import { Suspense, lazy } from 'react';
|
||||||
import { Route, Routes } from 'react-router-dom';
|
import { Route, Routes } from 'react-router-dom';
|
||||||
import { HomePage } from './pages/HomePage';
|
|
||||||
import { SettingsPage } from './pages/SettingsPage';
|
|
||||||
import { ToastProvider } from './lib/toast';
|
import { ToastProvider } from './lib/toast';
|
||||||
import { I18nProvider } from './lib/i18n';
|
import { I18nProvider } from './lib/i18n';
|
||||||
import { ThemeProvider } from './lib/theme';
|
import { ThemeProvider } from './lib/theme';
|
||||||
|
|
||||||
|
const HomePage = lazy(() => import('./pages/HomePage').then(module => ({ default: module.HomePage })));
|
||||||
|
const SettingsPage = lazy(() => import('./pages/SettingsPage').then(module => ({ default: module.SettingsPage })));
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
<Routes>
|
<Suspense fallback={<div className="h-screen w-screen flex items-center justify-center bg-bg"><div className="w-8 h-8 rounded-full border-4 border-accent-primary border-t-transparent animate-spin" /></div>}>
|
||||||
<Route path="/" element={<HomePage />} />
|
<Routes>
|
||||||
<Route path="/settings" element={<SettingsPage />} />
|
<Route path="/" element={<HomePage />} />
|
||||||
<Route path="*" element={<HomePage />} />
|
<Route path="/settings" element={<SettingsPage />} />
|
||||||
</Routes>
|
<Route path="*" element={<HomePage />} />
|
||||||
|
</Routes>
|
||||||
|
</Suspense>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, type FormEvent, type KeyboardEvent } from "react";
|
import { useState, useEffect, type FormEvent, type KeyboardEvent } from "react";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import {
|
import {
|
||||||
faCircleNotch,
|
faCircleNotch,
|
||||||
@@ -51,7 +51,8 @@ const CRAZY_PAIRS: { idea: string; style: string; mood: string; vocals: Vocals }
|
|||||||
];
|
];
|
||||||
|
|
||||||
interface InputPanelProps {
|
interface InputPanelProps {
|
||||||
values: InputValues;
|
initialValues: InputValues;
|
||||||
|
forcedUpdate?: { count: number; values: InputValues };
|
||||||
onChange: (next: InputValues) => void;
|
onChange: (next: InputValues) => void;
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@@ -60,19 +61,32 @@ interface InputPanelProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function InputPanel({
|
export function InputPanel({
|
||||||
values,
|
initialValues,
|
||||||
|
forcedUpdate,
|
||||||
onChange,
|
onChange,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
loading,
|
loading,
|
||||||
disabled,
|
disabled,
|
||||||
cancelButton,
|
cancelButton,
|
||||||
}: InputPanelProps) {
|
}: InputPanelProps) {
|
||||||
|
const [values, setValues] = useState<InputValues>(initialValues);
|
||||||
const [styleLoading, setStyleLoading] = useState<null | "normal" | "crazy">(null);
|
const [styleLoading, setStyleLoading] = useState<null | "normal" | "crazy">(null);
|
||||||
const elapsed = useElapsed(loading);
|
const elapsed = useElapsed(loading);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const set = <K extends keyof InputValues>(key: K, value: InputValues[K]) =>
|
// Handle external updates (e.g. from loading history)
|
||||||
onChange({ ...values, [key]: value });
|
useEffect(() => {
|
||||||
|
if (forcedUpdate && forcedUpdate.count > 0) {
|
||||||
|
setValues(forcedUpdate.values);
|
||||||
|
onChange(forcedUpdate.values);
|
||||||
|
}
|
||||||
|
}, [forcedUpdate, onChange]);
|
||||||
|
|
||||||
|
const set = <K extends keyof InputValues>(key: K, value: InputValues[K]) => {
|
||||||
|
const next = { ...values, [key]: value };
|
||||||
|
setValues(next);
|
||||||
|
onChange(next);
|
||||||
|
};
|
||||||
|
|
||||||
const canSubmit = !loading && !disabled && values.idea.trim().length > 0;
|
const canSubmit = !loading && !disabled && values.idea.trim().length > 0;
|
||||||
|
|
||||||
@@ -99,22 +113,26 @@ export function InputPanel({
|
|||||||
setStyleLoading("normal");
|
setStyleLoading("normal");
|
||||||
try {
|
try {
|
||||||
const style = await randomStyle("normal", ctrl.signal, ideaToUse);
|
const style = await randomStyle("normal", ctrl.signal, ideaToUse);
|
||||||
onChange({
|
const nextValues = {
|
||||||
...values,
|
...values,
|
||||||
idea: ideaToUse,
|
idea: ideaToUse,
|
||||||
style_hint: style,
|
style_hint: style,
|
||||||
mood: hasIdea ? values.mood : ex.mood,
|
mood: hasIdea ? values.mood : ex.mood,
|
||||||
vocals: hasIdea ? values.vocals : ex.vocals
|
vocals: hasIdea ? values.vocals : ex.vocals
|
||||||
});
|
};
|
||||||
|
setValues(nextValues);
|
||||||
|
onChange(nextValues);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof DOMException && err.name === "AbortError") return;
|
if (err instanceof DOMException && err.name === "AbortError") return;
|
||||||
onChange({
|
const nextValues = {
|
||||||
...values,
|
...values,
|
||||||
idea: ideaToUse,
|
idea: ideaToUse,
|
||||||
style_hint: hasIdea ? values.style_hint : ex.style,
|
style_hint: hasIdea ? values.style_hint : ex.style,
|
||||||
mood: hasIdea ? values.mood : ex.mood,
|
mood: hasIdea ? values.mood : ex.mood,
|
||||||
vocals: hasIdea ? values.vocals : ex.vocals
|
vocals: hasIdea ? values.vocals : ex.vocals
|
||||||
});
|
};
|
||||||
|
setValues(nextValues);
|
||||||
|
onChange(nextValues);
|
||||||
} finally {
|
} finally {
|
||||||
setStyleLoading((curr) => (curr === "normal" ? null : curr));
|
setStyleLoading((curr) => (curr === "normal" ? null : curr));
|
||||||
}
|
}
|
||||||
@@ -131,22 +149,26 @@ export function InputPanel({
|
|||||||
setStyleLoading("crazy");
|
setStyleLoading("crazy");
|
||||||
try {
|
try {
|
||||||
const style = await randomStyle("crazy", ctrl.signal, ideaToUse);
|
const style = await randomStyle("crazy", ctrl.signal, ideaToUse);
|
||||||
onChange({
|
const nextValues = {
|
||||||
...values,
|
...values,
|
||||||
idea: ideaToUse,
|
idea: ideaToUse,
|
||||||
style_hint: style,
|
style_hint: style,
|
||||||
mood: hasIdea ? values.mood : ex.mood,
|
mood: hasIdea ? values.mood : ex.mood,
|
||||||
vocals: hasIdea ? values.vocals : ex.vocals
|
vocals: hasIdea ? values.vocals : ex.vocals
|
||||||
});
|
};
|
||||||
|
setValues(nextValues);
|
||||||
|
onChange(nextValues);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof DOMException && err.name === "AbortError") return;
|
if (err instanceof DOMException && err.name === "AbortError") return;
|
||||||
onChange({
|
const nextValues = {
|
||||||
...values,
|
...values,
|
||||||
idea: ideaToUse,
|
idea: ideaToUse,
|
||||||
style_hint: hasIdea ? values.style_hint : ex.style,
|
style_hint: hasIdea ? values.style_hint : ex.style,
|
||||||
mood: hasIdea ? values.mood : ex.mood,
|
mood: hasIdea ? values.mood : ex.mood,
|
||||||
vocals: hasIdea ? values.vocals : ex.vocals
|
vocals: hasIdea ? values.vocals : ex.vocals
|
||||||
});
|
};
|
||||||
|
setValues(nextValues);
|
||||||
|
onChange(nextValues);
|
||||||
} finally {
|
} finally {
|
||||||
setStyleLoading((curr) => (curr === "crazy" ? null : curr));
|
setStyleLoading((curr) => (curr === "crazy" ? null : curr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,18 +192,21 @@
|
|||||||
position: fixed; top: -20%; left: -15%; width: 70vw; height: 70vw;
|
position: fixed; top: -20%; left: -15%; width: 70vw; height: 70vw;
|
||||||
background: radial-gradient(circle, var(--accent-primary) 0%, transparent 65%);
|
background: radial-gradient(circle, var(--accent-primary) 0%, transparent 65%);
|
||||||
opacity: 0.18; filter: blur(130px); z-index: -1; pointer-events: none;
|
opacity: 0.18; filter: blur(130px); z-index: -1; pointer-events: none;
|
||||||
|
will-change: transform;
|
||||||
animation: blob-drift-1 18s ease-in-out infinite;
|
animation: blob-drift-1 18s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
.liquid-blob-2 {
|
.liquid-blob-2 {
|
||||||
position: fixed; bottom: -20%; right: -15%; width: 65vw; height: 65vw;
|
position: fixed; bottom: -20%; right: -15%; width: 65vw; height: 65vw;
|
||||||
background: radial-gradient(circle, var(--accent-secondary) 0%, transparent 65%);
|
background: radial-gradient(circle, var(--accent-secondary) 0%, transparent 65%);
|
||||||
opacity: 0.18; filter: blur(130px); z-index: -1; pointer-events: none;
|
opacity: 0.18; filter: blur(130px); z-index: -1; pointer-events: none;
|
||||||
|
will-change: transform;
|
||||||
animation: blob-drift-2 22s ease-in-out infinite;
|
animation: blob-drift-2 22s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
.liquid-blob-3 {
|
.liquid-blob-3 {
|
||||||
position: fixed; top: 30%; right: 20%; width: 40vw; height: 40vw;
|
position: fixed; top: 30%; right: 20%; width: 40vw; height: 40vw;
|
||||||
background: radial-gradient(circle, var(--accent-warm) 0%, transparent 65%);
|
background: radial-gradient(circle, var(--accent-warm) 0%, transparent 65%);
|
||||||
opacity: 0.10; filter: blur(100px); z-index: -1; pointer-events: none;
|
opacity: 0.10; filter: blur(100px); z-index: -1; pointer-events: none;
|
||||||
|
will-change: transform;
|
||||||
animation: blob-drift-3 26s ease-in-out infinite;
|
animation: blob-drift-3 26s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+32
-26
@@ -26,7 +26,6 @@ import { useI18n } from "../lib/i18n";
|
|||||||
import { useTheme } from "../lib/theme";
|
import { useTheme } from "../lib/theme";
|
||||||
|
|
||||||
const DRAFT_KEY = "melodymuse-draft";
|
const DRAFT_KEY = "melodymuse-draft";
|
||||||
const DRAFT_DEBOUNCE_MS = 400;
|
|
||||||
|
|
||||||
const DEFAULT_INPUT: InputValues = {
|
const DEFAULT_INPUT: InputValues = {
|
||||||
idea: "",
|
idea: "",
|
||||||
@@ -103,9 +102,8 @@ export function HomePage() {
|
|||||||
const { t, lang, setLang } = useI18n();
|
const { t, lang, setLang } = useI18n();
|
||||||
const { theme, toggleTheme } = useTheme();
|
const { theme, toggleTheme } = useTheme();
|
||||||
|
|
||||||
const [input, setInput] = useState<InputValues>(
|
const inputRef = useRef<InputValues>(loadDraft() ?? DEFAULT_INPUT);
|
||||||
() => loadDraft() ?? DEFAULT_INPUT,
|
const [forcedUpdate, setForcedUpdate] = useState<{ count: number; values: InputValues }>();
|
||||||
);
|
|
||||||
const [assets, setAssets] = useState<SongAssets | null>(null);
|
const [assets, setAssets] = useState<SongAssets | null>(null);
|
||||||
const [originalAssets, setOriginalAssets] = useState<SongAssets | null>(null);
|
const [originalAssets, setOriginalAssets] = useState<SongAssets | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -119,14 +117,14 @@ export function HomePage() {
|
|||||||
const abortRef = useRef<AbortController | null>(null);
|
const abortRef = useRef<AbortController | null>(null);
|
||||||
const anyRegenerating = isAnyBusy(loading, regenerating);
|
const anyRegenerating = isAnyBusy(loading, regenerating);
|
||||||
|
|
||||||
// Save draft
|
// Save draft periodically
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = window.setTimeout(() => {
|
const id = window.setInterval(() => {
|
||||||
try { window.localStorage.setItem(DRAFT_KEY, JSON.stringify(input)); }
|
try { window.localStorage.setItem(DRAFT_KEY, JSON.stringify(inputRef.current)); }
|
||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
}, DRAFT_DEBOUNCE_MS);
|
}, 1000);
|
||||||
return () => window.clearTimeout(id);
|
return () => window.clearInterval(id);
|
||||||
}, [input]);
|
}, []);
|
||||||
|
|
||||||
// Server health check
|
// Server health check
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -168,16 +166,19 @@ export function HomePage() {
|
|||||||
}, [anyRegenerating, cancel]);
|
}, [anyRegenerating, cancel]);
|
||||||
|
|
||||||
const buildRequest = useCallback(
|
const buildRequest = useCallback(
|
||||||
(section: string, extra: Record<string, unknown> = {}): GenerateCall => ({
|
(section: string, extra: Record<string, unknown> = {}): GenerateCall => {
|
||||||
input: input.idea.trim(),
|
const input = inputRef.current;
|
||||||
language: resolveLanguage(input),
|
return {
|
||||||
...(input.mood.trim() ? { mood: input.mood.trim() } : {}),
|
input: input.idea.trim(),
|
||||||
...(input.style_hint.trim() ? { style_hint: input.style_hint.trim() } : {}),
|
language: resolveLanguage(input),
|
||||||
vocals: input.vocals,
|
...(input.mood.trim() ? { mood: input.mood.trim() } : {}),
|
||||||
section,
|
...(input.style_hint.trim() ? { style_hint: input.style_hint.trim() } : {}),
|
||||||
...extra,
|
vocals: input.vocals,
|
||||||
} as unknown as GenerateCall),
|
section,
|
||||||
[input],
|
...extra,
|
||||||
|
} as unknown as GenerateCall;
|
||||||
|
},
|
||||||
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const runGeneration = useCallback(
|
const runGeneration = useCallback(
|
||||||
@@ -212,6 +213,7 @@ export function HomePage() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleGenerate = useCallback(async () => {
|
const handleGenerate = useCallback(async () => {
|
||||||
|
const input = inputRef.current;
|
||||||
if (!input.idea.trim()) return;
|
if (!input.idea.trim()) return;
|
||||||
setAssets(null);
|
setAssets(null);
|
||||||
setOriginalAssets(null);
|
setOriginalAssets(null);
|
||||||
@@ -228,9 +230,10 @@ export function HomePage() {
|
|||||||
setLoading,
|
setLoading,
|
||||||
t.assetsGenerated,
|
t.assetsGenerated,
|
||||||
);
|
);
|
||||||
}, [input, buildRequest, runGeneration, t]);
|
}, [buildRequest, runGeneration, t]);
|
||||||
|
|
||||||
const handleRegenerateAll = useCallback(async () => {
|
const handleRegenerateAll = useCallback(async () => {
|
||||||
|
const input = inputRef.current;
|
||||||
if (!input.idea.trim()) return;
|
if (!input.idea.trim()) return;
|
||||||
setAssets(null);
|
setAssets(null);
|
||||||
setOriginalAssets(null);
|
setOriginalAssets(null);
|
||||||
@@ -250,10 +253,11 @@ export function HomePage() {
|
|||||||
},
|
},
|
||||||
t.regeneratedAll,
|
t.regeneratedAll,
|
||||||
);
|
);
|
||||||
}, [input, buildRequest, runGeneration, t]);
|
}, [buildRequest, runGeneration, t]);
|
||||||
|
|
||||||
const handleRegenerateSection = useCallback(
|
const handleRegenerateSection = useCallback(
|
||||||
async (section: SectionKey, selectedText?: string) => {
|
async (section: SectionKey, selectedText?: string) => {
|
||||||
|
const input = inputRef.current;
|
||||||
if (!input.idea.trim() || !assets) return;
|
if (!input.idea.trim() || !assets) return;
|
||||||
|
|
||||||
const isPartialLyrics = section === "lyrics" && !!selectedText;
|
const isPartialLyrics = section === "lyrics" && !!selectedText;
|
||||||
@@ -299,7 +303,7 @@ export function HomePage() {
|
|||||||
`${t.regeneratedSection} ${SECTION_LABELS[section]}`,
|
`${t.regeneratedSection} ${SECTION_LABELS[section]}`,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[input, assets, buildRequest, runGeneration, t],
|
[assets, buildRequest, runGeneration, t],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Execute chained regeneration
|
// Execute chained regeneration
|
||||||
@@ -345,7 +349,8 @@ export function HomePage() {
|
|||||||
const handleLoadHistory = useCallback(
|
const handleLoadHistory = useCallback(
|
||||||
(entry: HistoryEntry) => {
|
(entry: HistoryEntry) => {
|
||||||
if (anyRegenerating) cancel();
|
if (anyRegenerating) cancel();
|
||||||
setInput(entry.input);
|
inputRef.current = entry.input;
|
||||||
|
setForcedUpdate((prev) => ({ count: (prev?.count ?? 0) + 1, values: entry.input }));
|
||||||
setAssets(entry.assets);
|
setAssets(entry.assets);
|
||||||
setOriginalAssets(entry.assets);
|
setOriginalAssets(entry.assets);
|
||||||
setSelectedTitleIndex(0);
|
setSelectedTitleIndex(0);
|
||||||
@@ -486,8 +491,9 @@ export function HomePage() {
|
|||||||
<div className="w-full md:w-[340px] xl:w-[380px] shrink-0 flex flex-col">
|
<div className="w-full md:w-[340px] xl:w-[380px] shrink-0 flex flex-col">
|
||||||
<div className="card p-4 flex flex-col flex-none md:flex-1 min-h-0">
|
<div className="card p-4 flex flex-col flex-none md:flex-1 min-h-0">
|
||||||
<InputPanel
|
<InputPanel
|
||||||
values={input}
|
initialValues={inputRef.current}
|
||||||
onChange={setInput}
|
forcedUpdate={forcedUpdate}
|
||||||
|
onChange={(next) => { inputRef.current = next; }}
|
||||||
onSubmit={handleGenerate}
|
onSubmit={handleGenerate}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={anyRegenerating}
|
disabled={anyRegenerating}
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import { createServer } from 'node:http';
|
|||||||
|
|
||||||
async function test() {
|
async function test() {
|
||||||
const LLM_ENDPOINT = 'https://api.minimax.io/v1';
|
const LLM_ENDPOINT = 'https://api.minimax.io/v1';
|
||||||
const LLM_API_KEY = 'sk-cp-UKWMS27cNQjuDxfHa14CsYKS1Q60ptZLhTtZYcB8iKgWJz9-C6st7jgmAsW7VTWQi83igf6mpc-6aIkt29wwWG_oCBYN0jITGAb06BA-MPjJgUEx7awu7zQ';
|
const LLM_API_KEY = process.env.MINIMAX_API_KEY;
|
||||||
const LLM_MODEL = 'MiniMax-M3';
|
const LLM_MODEL = 'MiniMax-M3';
|
||||||
|
|
||||||
const resp = await fetch(LLM_ENDPOINT + '/chat/completions', {
|
const resp = await fetch(LLM_ENDPOINT + '/chat/completions', {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createServer } from 'node:http';
|
|||||||
|
|
||||||
async function test() {
|
async function test() {
|
||||||
const LLM_ENDPOINT = 'https://api.minimax.io/v1';
|
const LLM_ENDPOINT = 'https://api.minimax.io/v1';
|
||||||
const LLM_API_KEY = 'sk-cp-UKWMS27cNQjuDxfHa14CsYKS1Q60ptZLhTtZYcB8iKgWJz9-C6st7jgmAsW7VTWQi83igf6mpc-6aIkt29wwWG_oCBYN0jITGAb06BA-MPjJgUEx7awu7zQ';
|
const LLM_API_KEY = process.env.MINIMAX_API_KEY;
|
||||||
const LLM_MODEL = 'MiniMax-M3';
|
const LLM_MODEL = 'MiniMax-M3';
|
||||||
|
|
||||||
const resp = await fetch(LLM_ENDPOINT + '/chat/completions', {
|
const resp = await fetch(LLM_ENDPOINT + '/chat/completions', {
|
||||||
|
|||||||
Reference in New Issue
Block a user