Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57df39e4ce | ||
|
|
496be1f032 | ||
|
|
4485b40633 |
@@ -458,12 +458,12 @@ pub async fn chat_send(
|
|||||||
app: AppHandle,
|
app: AppHandle,
|
||||||
state: State<'_, App>,
|
state: State<'_, App>,
|
||||||
payload: ChatSendPayload,
|
payload: ChatSendPayload,
|
||||||
) -> Result<(), String> {
|
) -> Result<serde_json::Value, String> {
|
||||||
let core = state.core.clone();
|
let core = state.core.clone();
|
||||||
let engine = state.engine.clone();
|
let engine = state.engine.clone();
|
||||||
let base = state.engine_base.clone();
|
let base = state.engine_base.clone();
|
||||||
|
|
||||||
let (history, model, engine_bin) = {
|
let (history, model, engine_bin, user_message_id) = {
|
||||||
let db = core.db.lock().unwrap();
|
let db = core.db.lock().unwrap();
|
||||||
if sessions_db::get_conversation(&db, &payload.conversation_id)
|
if sessions_db::get_conversation(&db, &payload.conversation_id)
|
||||||
.map_err(|e| e.to_string())?
|
.map_err(|e| e.to_string())?
|
||||||
@@ -479,7 +479,7 @@ pub async fn chat_send(
|
|||||||
)
|
)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
}
|
}
|
||||||
sessions_db::add_message(
|
let user_message_id = sessions_db::add_message(
|
||||||
&db,
|
&db,
|
||||||
&payload.conversation_id,
|
&payload.conversation_id,
|
||||||
"user",
|
"user",
|
||||||
@@ -508,7 +508,7 @@ pub async fn chat_send(
|
|||||||
let bin = settings_db::get(&db, "engine_bin")
|
let bin = settings_db::get(&db, "engine_bin")
|
||||||
.map_err(|e| e.to_string())?
|
.map_err(|e| e.to_string())?
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
(history, model, bin)
|
(history, model, bin, user_message_id)
|
||||||
};
|
};
|
||||||
|
|
||||||
let conversation_id = payload.conversation_id.clone();
|
let conversation_id = payload.conversation_id.clone();
|
||||||
@@ -523,13 +523,16 @@ pub async fn chat_send(
|
|||||||
core,
|
core,
|
||||||
engine,
|
engine,
|
||||||
base,
|
base,
|
||||||
conversation_id,
|
conversation_id.clone(),
|
||||||
history,
|
history,
|
||||||
model,
|
model,
|
||||||
engine_bin,
|
engine_bin,
|
||||||
payload.params,
|
payload.params,
|
||||||
));
|
));
|
||||||
Ok(())
|
Ok(serde_json::json!({
|
||||||
|
"conversation_id": conversation_id,
|
||||||
|
"message_id": user_message_id,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 统一的生成与流式转发:支持本地引擎 / 远程 API,统计首字延迟、token 数与耗时。
|
/// 统一的生成与流式转发:支持本地引擎 / 远程 API,统计首字延迟、token 数与耗时。
|
||||||
|
|||||||
+22
-8
@@ -188,18 +188,30 @@ export const api = {
|
|||||||
invoke<void>("deploy_model", { modelId, params }),
|
invoke<void>("deploy_model", { modelId, params }),
|
||||||
engineStop: () => invoke<void>("engine_stop"),
|
engineStop: () => invoke<void>("engine_stop"),
|
||||||
engineStatus: () => invoke<EngineStatus>("engine_status"),
|
engineStatus: () => invoke<EngineStatus>("engine_status"),
|
||||||
chatSend: (payload: ChatSendPayload) => invoke<string>("chat_send", { payload }),
|
chatSend: (payload: ChatSendPayload) =>
|
||||||
|
invoke<{ conversation_id: string; message_id: string }>("chat_send", { payload }),
|
||||||
regenerateMessage: (
|
regenerateMessage: (
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
messageId: string,
|
messageId: string,
|
||||||
params: ChatParams,
|
params: ChatParams,
|
||||||
) => invoke<void>("regenerate_message", { conversationId, messageId, params }),
|
) =>
|
||||||
|
invoke<void>("regenerate_message", {
|
||||||
|
payload: { conversation_id: conversationId, message_id: messageId, params },
|
||||||
|
}),
|
||||||
editMessage: (
|
editMessage: (
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
messageId: string,
|
messageId: string,
|
||||||
content: string,
|
content: string,
|
||||||
params: ChatParams,
|
params: ChatParams,
|
||||||
) => invoke<void>("edit_message", { conversationId, messageId, content, params }),
|
) =>
|
||||||
|
invoke<void>("edit_message", {
|
||||||
|
payload: {
|
||||||
|
conversation_id: conversationId,
|
||||||
|
message_id: messageId,
|
||||||
|
content,
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
}),
|
||||||
listMessageVersions: (messageId: string) =>
|
listMessageVersions: (messageId: string) =>
|
||||||
invoke<MessageVersion[]>("list_message_versions", { messageId }),
|
invoke<MessageVersion[]>("list_message_versions", { messageId }),
|
||||||
applyMessageVersion: (
|
applyMessageVersion: (
|
||||||
@@ -215,11 +227,13 @@ export const api = {
|
|||||||
source?: string,
|
source?: string,
|
||||||
) =>
|
) =>
|
||||||
invoke<string>("download_enqueue", {
|
invoke<string>("download_enqueue", {
|
||||||
url,
|
payload: {
|
||||||
fileName,
|
url,
|
||||||
sha256: sha256 ?? null,
|
file_name: fileName,
|
||||||
repoId: repoId ?? null,
|
sha256: sha256 ?? null,
|
||||||
source: source ?? null,
|
repo_id: repoId ?? null,
|
||||||
|
source: source ?? null,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
serverStart: (port: number, apiKey: string) =>
|
serverStart: (port: number, apiKey: string) =>
|
||||||
invoke<ServerStatus>("server_start", { port, apiKey }),
|
invoke<ServerStatus>("server_start", { port, apiKey }),
|
||||||
|
|||||||
@@ -219,21 +219,27 @@ export default function ChatPage() {
|
|||||||
await refreshConversations();
|
await refreshConversations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tempUserId = `user-${Date.now()}`;
|
||||||
setMessages((prev) => [
|
setMessages((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
{ id: `user-${Date.now()}`, role: "user", content, images },
|
{ id: tempUserId, role: "user", content, images },
|
||||||
{ id: `assistant-${Date.now()}`, role: "assistant", content: "", streaming: true },
|
{ id: `assistant-${Date.now()}`, role: "assistant", content: "", streaming: true },
|
||||||
]);
|
]);
|
||||||
setStreaming(true);
|
setStreaming(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.chatSend({
|
const result = await api.chatSend({
|
||||||
conversation_id: convId,
|
conversation_id: convId,
|
||||||
model_id: selectedModelId,
|
model_id: selectedModelId,
|
||||||
content,
|
content,
|
||||||
params,
|
params,
|
||||||
images,
|
images,
|
||||||
});
|
});
|
||||||
|
if (result?.message_id) {
|
||||||
|
setMessages((prev) =>
|
||||||
|
prev.map((m) => (m.id === tempUserId ? { ...m, id: result.message_id } : m)),
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setStreaming(false);
|
setStreaming(false);
|
||||||
setError(String(e));
|
setError(String(e));
|
||||||
@@ -718,15 +724,19 @@ function MessageBubble({
|
|||||||
) : isUser ? (
|
) : isUser ? (
|
||||||
<>
|
<>
|
||||||
<div className="whitespace-pre-wrap">{message.content}</div>
|
<div className="whitespace-pre-wrap">{message.content}</div>
|
||||||
{!streaming ? (
|
<div
|
||||||
|
className={`mt-1 flex justify-end transition-opacity ${
|
||||||
|
streaming ? "opacity-0" : "opacity-0 group-hover:opacity-100"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
className="absolute -left-8 top-2 hidden rounded p-1 text-slate-500 hover:text-slate-200 group-hover:block"
|
className="rounded px-1.5 py-0.5 text-[10px] text-white/60 hover:bg-white/10 hover:text-white"
|
||||||
onClick={() => onEditStart(message)}
|
onClick={() => onEditStart(message)}
|
||||||
title="编辑并重新提交"
|
title="编辑并重新提交(清空之后的生成)"
|
||||||
>
|
>
|
||||||
✎
|
编辑
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
</div>
|
||||||
</>
|
</>
|
||||||
) : message.content ? (
|
) : message.content ? (
|
||||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>{message.content}</ReactMarkdown>
|
<ReactMarkdown remarkPlugins={[remarkGfm]}>{message.content}</ReactMarkdown>
|
||||||
|
|||||||
Reference in New Issue
Block a user