mirror of
https://github.com/AstrBotDevs/AstrBot.git
synced 2026-10-16 15:06:04 +08:00
feat(webchat): enable reasoning display by default (#10020)
* feat(webchat): enable reasoning display by default * fix(webchat): sync reasoning flag expectations and API docs
This commit is contained in:
@@ -152,6 +152,10 @@ class InternalAgentSubStage(Stage):
|
||||
if (enable_streaming := event.get_extra("enable_streaming")) is not None:
|
||||
streaming_response = bool(enable_streaming)
|
||||
|
||||
show_reasoning = self.show_reasoning
|
||||
if (enable_reasoning := event.get_extra("enable_reasoning")) is not None:
|
||||
show_reasoning = bool(enable_reasoning)
|
||||
|
||||
has_provider_request = event.get_extra("provider_request") is not None
|
||||
has_valid_message = bool(event.message_str and event.message_str.strip())
|
||||
has_media_content = any(
|
||||
@@ -300,7 +304,7 @@ class InternalAgentSubStage(Stage):
|
||||
self.max_step,
|
||||
self.show_tool_use,
|
||||
self.show_tool_call_result,
|
||||
show_reasoning=self.show_reasoning,
|
||||
show_reasoning=show_reasoning,
|
||||
buffer_intermediate_messages=self.buffer_intermediate_messages,
|
||||
),
|
||||
),
|
||||
@@ -331,7 +335,7 @@ class InternalAgentSubStage(Stage):
|
||||
self.max_step,
|
||||
self.show_tool_use,
|
||||
self.show_tool_call_result,
|
||||
show_reasoning=self.show_reasoning,
|
||||
show_reasoning=show_reasoning,
|
||||
buffer_intermediate_messages=self.buffer_intermediate_messages,
|
||||
),
|
||||
),
|
||||
@@ -362,7 +366,7 @@ class InternalAgentSubStage(Stage):
|
||||
self.show_tool_use,
|
||||
self.show_tool_call_result,
|
||||
stream_to_general,
|
||||
show_reasoning=self.show_reasoning,
|
||||
show_reasoning=show_reasoning,
|
||||
buffer_intermediate_messages=self.buffer_intermediate_messages,
|
||||
):
|
||||
yield
|
||||
|
||||
@@ -286,9 +286,13 @@ class ResultDecorateStage(Stage):
|
||||
"provider configured.",
|
||||
)
|
||||
|
||||
show_reasoning = self.show_reasoning
|
||||
if (enable_reasoning := event.get_extra("enable_reasoning")) is not None:
|
||||
show_reasoning = bool(enable_reasoning)
|
||||
|
||||
if (
|
||||
not should_tts
|
||||
and self.show_reasoning
|
||||
and show_reasoning
|
||||
and event.get_extra("_llm_reasoning_content")
|
||||
):
|
||||
# inject reasoning content to chain
|
||||
|
||||
@@ -4,6 +4,7 @@ WEBCHAT_REQUEST_FLAG_DEFAULTS = {
|
||||
"enable_inline_genui": True,
|
||||
"enable_default_system_prompt": True,
|
||||
"enable_streaming": True,
|
||||
"enable_reasoning": True,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ class ChatFlags(BaseModel):
|
||||
enable_inline_genui: bool = True
|
||||
enable_default_system_prompt: bool = True
|
||||
enable_streaming: bool = True
|
||||
enable_reasoning: bool = True
|
||||
|
||||
|
||||
class ChatMessageRegenerateRequest(OpenModel):
|
||||
|
||||
@@ -83,6 +83,10 @@ export type ChatFlags = {
|
||||
* Enable streaming model output for this request. This value takes priority over the legacy top-level enable_streaming field.
|
||||
*/
|
||||
enable_streaming?: boolean;
|
||||
/**
|
||||
* Display reasoning content for this WebChat request independently of the global display_reasoning_text setting.
|
||||
*/
|
||||
enable_reasoning?: boolean;
|
||||
};
|
||||
|
||||
export type ChatMessagePatchRequest = {
|
||||
|
||||
@@ -364,6 +364,7 @@
|
||||
:staged-files="stagedNonImageFiles"
|
||||
:disabled="sending"
|
||||
:enable-streaming="enableStreaming"
|
||||
:enable-reasoning="enableReasoning"
|
||||
:is-recording="isRecording"
|
||||
:is-running="
|
||||
Boolean(currSessionId && isSessionRunning(currSessionId))
|
||||
@@ -378,6 +379,7 @@
|
||||
@send="sendCurrentMessage"
|
||||
@stop="stopCurrentSession"
|
||||
@toggle-streaming="toggleStreaming"
|
||||
@toggle-reasoning="enableReasoning = !enableReasoning"
|
||||
@remove-image="removeImage"
|
||||
@remove-audio="removeAudio"
|
||||
@remove-file="removeFile"
|
||||
@@ -449,6 +451,7 @@
|
||||
:staged-files="stagedNonImageFiles"
|
||||
:disabled="sending"
|
||||
:enable-streaming="enableStreaming"
|
||||
:enable-reasoning="enableReasoning"
|
||||
:is-recording="isRecording"
|
||||
:is-running="
|
||||
Boolean(currSessionId && isSessionRunning(currSessionId))
|
||||
@@ -465,6 +468,7 @@
|
||||
@send="sendCurrentMessage"
|
||||
@stop="stopCurrentSession"
|
||||
@toggle-streaming="toggleStreaming"
|
||||
@toggle-reasoning="enableReasoning = !enableReasoning"
|
||||
@remove-image="removeImage"
|
||||
@remove-audio="removeAudio"
|
||||
@remove-file="removeFile"
|
||||
@@ -743,6 +747,7 @@ const threadSelection = reactive<{
|
||||
selectedText: "",
|
||||
});
|
||||
const enableStreaming = ref(true);
|
||||
const enableReasoning = ref(true);
|
||||
const sendShortcut = ref<"enter" | "shift_enter">("enter");
|
||||
let composerResizeObserver: ResizeObserver | null = null;
|
||||
const {
|
||||
@@ -1400,6 +1405,7 @@ async function sendCurrentMessage() {
|
||||
parts: outgoingParts,
|
||||
transport: transportMode.value,
|
||||
enableStreaming: enableStreaming.value,
|
||||
enableReasoning: enableReasoning.value,
|
||||
selectedProvider: selection?.providerId || "",
|
||||
selectedModel: selection?.modelName || "",
|
||||
userRecord,
|
||||
@@ -1521,6 +1527,7 @@ async function saveMessageEdit() {
|
||||
sessionId: currSessionId.value,
|
||||
sourceRecord: target,
|
||||
enableStreaming: enableStreaming.value,
|
||||
enableReasoning: enableReasoning.value,
|
||||
selectedProvider: selection?.providerId || "",
|
||||
selectedModel: selection?.modelName || "",
|
||||
});
|
||||
@@ -1556,6 +1563,7 @@ async function handleRegenerateMessage(
|
||||
effectiveSelection?.providerId || "",
|
||||
effectiveSelection?.modelName || "",
|
||||
enableStreaming.value,
|
||||
enableReasoning.value,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,22 @@
|
||||
}}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
class="styled-menu-item"
|
||||
rounded="md"
|
||||
@click="$emit('toggleReasoning')"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<v-icon icon="mdi-brain" size="small"></v-icon>
|
||||
</template>
|
||||
<v-list-item-title>
|
||||
{{
|
||||
enableReasoning
|
||||
? tm("reasoning.enabled")
|
||||
: tm("reasoning.disabled")
|
||||
}}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</StyledMenu>
|
||||
|
||||
</div>
|
||||
@@ -355,6 +371,7 @@ interface Props {
|
||||
stagedFiles?: StagedFileInfo[];
|
||||
disabled: boolean;
|
||||
enableStreaming: boolean;
|
||||
enableReasoning: boolean;
|
||||
isRecording: boolean;
|
||||
isRunning: boolean;
|
||||
sessionId?: string | null;
|
||||
@@ -383,6 +400,7 @@ const emit = defineEmits<{
|
||||
send: [];
|
||||
stop: [];
|
||||
toggleStreaming: [];
|
||||
toggleReasoning: [];
|
||||
removeImage: [index: number];
|
||||
removeAudio: [];
|
||||
removeFile: [index: number];
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
:staged-files="stagedNonImageFiles"
|
||||
:disabled="sending || initializing"
|
||||
:enable-streaming="enableStreaming"
|
||||
:enable-reasoning="enableReasoning"
|
||||
:is-recording="false"
|
||||
:is-running="Boolean(currSessionId && isSessionRunning(currSessionId))"
|
||||
:session-id="currSessionId || null"
|
||||
@@ -186,6 +187,7 @@
|
||||
@send="sendCurrentMessage"
|
||||
@stop="stopCurrentSession"
|
||||
@toggle-streaming="enableStreaming = !enableStreaming"
|
||||
@toggle-reasoning="enableReasoning = !enableReasoning"
|
||||
@remove-image="removeImage"
|
||||
@remove-audio="removeAudio"
|
||||
@remove-file="removeFile"
|
||||
@@ -258,6 +260,7 @@ const currentSession = ref<Session | null>(null);
|
||||
const draft = ref("");
|
||||
const initializing = ref(false);
|
||||
const enableStreaming = ref(true);
|
||||
const enableReasoning = ref(true);
|
||||
const shouldStickToBottom = ref(true);
|
||||
const messagesContainer = ref<HTMLElement | null>(null);
|
||||
const inputRef = ref<InstanceType<typeof ChatInput> | null>(null);
|
||||
@@ -362,6 +365,7 @@ async function sendCurrentMessage() {
|
||||
parts,
|
||||
transport: transportMode.value,
|
||||
enableStreaming: enableStreaming.value,
|
||||
enableReasoning: enableReasoning.value,
|
||||
selectedProvider: selection?.providerId || "",
|
||||
selectedModel: selection?.modelName || "",
|
||||
userRecord,
|
||||
|
||||
@@ -4,11 +4,15 @@ import { fetchWithAuth } from "@/api/http";
|
||||
|
||||
export type TransportMode = "sse" | "websocket";
|
||||
|
||||
export function buildChatRequestFlags(enableStreaming = true) {
|
||||
export function buildChatRequestFlags(
|
||||
enableStreaming = true,
|
||||
enableReasoning = true,
|
||||
) {
|
||||
return {
|
||||
enable_inline_genui: true,
|
||||
enable_default_system_prompt: true,
|
||||
enable_streaming: enableStreaming,
|
||||
enable_reasoning: enableReasoning,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -109,6 +113,7 @@ interface SendMessageStreamOptions {
|
||||
parts: MessagePart[];
|
||||
transport: TransportMode;
|
||||
enableStreaming?: boolean;
|
||||
enableReasoning?: boolean;
|
||||
selectedProvider?: string;
|
||||
selectedModel?: string;
|
||||
userRecord?: ChatRecord;
|
||||
@@ -121,6 +126,7 @@ interface ContinueEditedMessageOptions {
|
||||
sessionId: string;
|
||||
sourceRecord: ChatRecord;
|
||||
enableStreaming?: boolean;
|
||||
enableReasoning?: boolean;
|
||||
selectedProvider?: string;
|
||||
selectedModel?: string;
|
||||
}
|
||||
@@ -374,6 +380,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
parts,
|
||||
transport,
|
||||
enableStreaming = true,
|
||||
enableReasoning = true,
|
||||
selectedProvider = "",
|
||||
selectedModel = "",
|
||||
botRecord,
|
||||
@@ -389,6 +396,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
botRecord,
|
||||
userRecord,
|
||||
enableStreaming,
|
||||
enableReasoning,
|
||||
selectedProvider,
|
||||
selectedModel,
|
||||
);
|
||||
@@ -401,6 +409,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
botRecord,
|
||||
userRecord,
|
||||
enableStreaming,
|
||||
enableReasoning,
|
||||
selectedProvider,
|
||||
selectedModel,
|
||||
skipUserHistory,
|
||||
@@ -449,6 +458,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
sessionId,
|
||||
sourceRecord,
|
||||
enableStreaming = true,
|
||||
enableReasoning = true,
|
||||
selectedProvider = "",
|
||||
selectedModel = "",
|
||||
}: ContinueEditedMessageOptions) {
|
||||
@@ -476,6 +486,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
botRecord,
|
||||
undefined,
|
||||
enableStreaming,
|
||||
enableReasoning,
|
||||
selectedProvider,
|
||||
selectedModel,
|
||||
true,
|
||||
@@ -489,6 +500,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
selectedProvider = "",
|
||||
selectedModel = "",
|
||||
enableStreaming = true,
|
||||
enableReasoning = true,
|
||||
) {
|
||||
if (!sessionId || botRecord.id == null) return;
|
||||
const targetMessageId = botRecord.id;
|
||||
@@ -524,7 +536,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
body: JSON.stringify({
|
||||
selected_provider: selectedProvider,
|
||||
selected_model: selectedModel,
|
||||
flags: buildChatRequestFlags(enableStreaming),
|
||||
flags: buildChatRequestFlags(enableStreaming, enableReasoning),
|
||||
}),
|
||||
signal: abort.signal,
|
||||
},
|
||||
@@ -619,6 +631,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
botRecord: ChatRecord,
|
||||
userRecord: ChatRecord | undefined,
|
||||
enableStreaming: boolean,
|
||||
enableReasoning: boolean,
|
||||
selectedProvider: string,
|
||||
selectedModel: string,
|
||||
skipUserHistory = false,
|
||||
@@ -645,7 +658,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
body: JSON.stringify({
|
||||
session_id: sessionId,
|
||||
message: parts.map(partToPayload),
|
||||
flags: buildChatRequestFlags(enableStreaming),
|
||||
flags: buildChatRequestFlags(enableStreaming, enableReasoning),
|
||||
selected_provider: selectedProvider,
|
||||
selected_model: selectedModel,
|
||||
_skip_user_history: skipUserHistory,
|
||||
@@ -770,6 +783,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
botRecord: ChatRecord,
|
||||
userRecord: ChatRecord | undefined,
|
||||
enableStreaming: boolean,
|
||||
enableReasoning: boolean,
|
||||
selectedProvider: string,
|
||||
selectedModel: string,
|
||||
) {
|
||||
@@ -795,7 +809,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
session_id: sessionId,
|
||||
message_id: messageId,
|
||||
message: parts.map(partToPayload),
|
||||
flags: buildChatRequestFlags(enableStreaming),
|
||||
flags: buildChatRequestFlags(enableStreaming, enableReasoning),
|
||||
selected_provider: selectedProvider,
|
||||
selected_model: selectedModel,
|
||||
});
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
"title": "Config"
|
||||
},
|
||||
"reasoning": {
|
||||
"enabled": "Reasoning enabled",
|
||||
"disabled": "Reasoning disabled",
|
||||
"thinking": "Thinking Process",
|
||||
"summarySeparator": ", ",
|
||||
"thinkSummary": "Thought {count} times",
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
"title": "設定"
|
||||
},
|
||||
"reasoning": {
|
||||
"enabled": "思考内容の表示:オン",
|
||||
"disabled": "思考内容の表示:オフ",
|
||||
"thinking": "思考プロセス",
|
||||
"summarySeparator": "、",
|
||||
"thinkSummary": "思考 {count} 回",
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
"title": "Конфигурация"
|
||||
},
|
||||
"reasoning": {
|
||||
"enabled": "Рассуждения включены",
|
||||
"disabled": "Рассуждения выключены",
|
||||
"thinking": "Рассуждение",
|
||||
"summarySeparator": ", ",
|
||||
"thinkSummary": "Размышлений: {count}",
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
"title": "配置文件"
|
||||
},
|
||||
"reasoning": {
|
||||
"enabled": "思考内容已开启",
|
||||
"disabled": "思考内容已关闭",
|
||||
"thinking": "思考过程",
|
||||
"summarySeparator": ",",
|
||||
"thinkSummary": "思考了 {count} 次",
|
||||
|
||||
@@ -7118,6 +7118,11 @@
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable streaming model output for this request. This value takes priority over the legacy top-level enable_streaming field."
|
||||
},
|
||||
"enable_reasoning": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Display reasoning content for this WebChat request independently of the global display_reasoning_text setting."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -5547,6 +5547,10 @@ components:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Enable streaming model output for this request. This value takes priority over the legacy top-level enable_streaming field.
|
||||
enable_reasoning:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Display reasoning content for this WebChat request independently of the global display_reasoning_text setting.
|
||||
additionalProperties: false
|
||||
|
||||
ChatRequest:
|
||||
|
||||
@@ -448,6 +448,7 @@ async def test_chat_stream_forwards_normalized_request_flags(chat_service_instan
|
||||
"enable_inline_genui": True,
|
||||
"enable_default_system_prompt": False,
|
||||
"enable_streaming": False,
|
||||
"enable_reasoning": True,
|
||||
}
|
||||
assert "enable_streaming" not in payload
|
||||
finally:
|
||||
|
||||
@@ -10,6 +10,7 @@ def test_webchat_request_flags_use_defaults():
|
||||
"enable_inline_genui": True,
|
||||
"enable_default_system_prompt": True,
|
||||
"enable_streaming": True,
|
||||
"enable_reasoning": True,
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +30,7 @@ def test_webchat_request_flags_prefer_nested_flags():
|
||||
"enable_inline_genui": False,
|
||||
"enable_default_system_prompt": False,
|
||||
"enable_streaming": True,
|
||||
"enable_reasoning": True,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user