fix: moonshot temperature=1, 20MB upload limit, file input FileList fix, rate limiter off
- workflow_integration: force temperature=1.0 for moonshot provider (Kimi K3 reasoning models reject other values), both agent node and orchestrator node - config: LOCAL_FILE_WRITE_MAX_BYTES 2MB -> 20MB (image uploads) - main: temporarily disable RateLimiterMiddleware - useFileUpload: copy FileList before resetting input (Chromium clears reference) - AgentChat/AgentChatPreview: attach button via ChatInputArea ref
This commit is contained in:
@@ -64,10 +64,15 @@ async def run_agent_node(
|
|||||||
formatted_prompt = raw_prompt
|
formatted_prompt = raw_prompt
|
||||||
|
|
||||||
# 3. 构建 Agent 配置
|
# 3. 构建 Agent 配置
|
||||||
|
_provider = node_data.get("provider", "openai")
|
||||||
|
temperature = float(node_data.get("temperature", 0.7))
|
||||||
|
# Kimi K3 等推理模型强制要求 temperature=1
|
||||||
|
if _provider == "moonshot":
|
||||||
|
temperature = 1.0
|
||||||
llm_config = AgentLLMConfig(
|
llm_config = AgentLLMConfig(
|
||||||
provider=node_data.get("provider", "openai"),
|
provider=_provider,
|
||||||
model=node_data.get("model", "gpt-4o-mini"),
|
model=node_data.get("model", "gpt-4o-mini"),
|
||||||
temperature=float(node_data.get("temperature", 0.7)),
|
temperature=temperature,
|
||||||
max_iterations=int(node_data.get("max_iterations", 10)),
|
max_iterations=int(node_data.get("max_iterations", 10)),
|
||||||
)
|
)
|
||||||
# 允许节点内联 api_key/base_url
|
# 允许节点内联 api_key/base_url
|
||||||
@@ -244,6 +249,10 @@ async def run_orchestrator_node(
|
|||||||
tools_whitelist = cfg.get("tools", tools_whitelist)
|
tools_whitelist = cfg.get("tools", tools_whitelist)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Kimi K3 等推理模型强制要求 temperature=1
|
||||||
|
if provider == "moonshot":
|
||||||
|
temperature = 1.0
|
||||||
|
|
||||||
agent_configs.append(OrchestratorAgentConfig(
|
agent_configs.append(OrchestratorAgentConfig(
|
||||||
id=agent.id,
|
id=agent.id,
|
||||||
name=agent.name or "Agent",
|
name=agent.name or "Agent",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class Settings(BaseSettings):
|
|||||||
# 本地文件工具(file_read / file_write):允许读写的根目录。空字符串表示使用「backend 的上一级目录」作为仓库根。
|
# 本地文件工具(file_read / file_write):允许读写的根目录。空字符串表示使用「backend 的上一级目录」作为仓库根。
|
||||||
LOCAL_FILE_TOOLS_ROOT: str = ""
|
LOCAL_FILE_TOOLS_ROOT: str = ""
|
||||||
LOCAL_FILE_READ_MAX_BYTES: int = 2_097_152 # 单次读取上限(默认 2MB)
|
LOCAL_FILE_READ_MAX_BYTES: int = 2_097_152 # 单次读取上限(默认 2MB)
|
||||||
LOCAL_FILE_WRITE_MAX_BYTES: int = 2_097_152 # 单次写入内容上限(UTF-8 字节)
|
LOCAL_FILE_WRITE_MAX_BYTES: int = 20_971_520 # 单次写入内容上限 20MB(含图片上传)
|
||||||
|
|
||||||
# http_request 工具:写入 LLM 上下文的响应体最大字符数(HTML/JSON 过大时截断,避免超过模型 context)
|
# http_request 工具:写入 LLM 上下文的响应体最大字符数(HTML/JSON 过大时截断,避免超过模型 context)
|
||||||
HTTP_REQUEST_MAX_BODY_CHARS: int = 32_000
|
HTTP_REQUEST_MAX_BODY_CHARS: int = 32_000
|
||||||
|
|||||||
@@ -191,7 +191,8 @@ app.add_middleware(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# API 限流中间件(在 CORS 之后、日志之前)
|
# API 限流中间件(在 CORS 之后、日志之前)
|
||||||
app.add_middleware(RateLimiterMiddleware)
|
# TODO: 暂时关闭限流,需要时恢复
|
||||||
|
# app.add_middleware(RateLimiterMiddleware)
|
||||||
|
|
||||||
# 安全响应头中间件(HSTS + X-Frame-Options + X-Content-Type-Options 等)
|
# 安全响应头中间件(HSTS + X-Frame-Options + X-Content-Type-Options 等)
|
||||||
app.add_middleware(SecurityHeadersMiddleware)
|
app.add_middleware(SecurityHeadersMiddleware)
|
||||||
|
|||||||
@@ -142,6 +142,7 @@
|
|||||||
|
|
||||||
<!-- Shared ChatInputArea -->
|
<!-- Shared ChatInputArea -->
|
||||||
<ChatInputArea
|
<ChatInputArea
|
||||||
|
ref="inputAreaRef"
|
||||||
v-model="inputMessage"
|
v-model="inputMessage"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:disabled="loading || !agentId"
|
:disabled="loading || !agentId"
|
||||||
@@ -182,7 +183,9 @@ import api, { WORKFLOW_EXECUTION_HTTP_TIMEOUT_MS } from '@/api'
|
|||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
// ---- Shared composables ----
|
// ---- Shared composables ----
|
||||||
const { pendingAttachments, fileInputRef, inputDragOver, uploadFiles, removeAttachment, clearAttachments, buildAttachmentContext, onFilesSelected, handleAttachFile } = useFileUpload()
|
const { pendingAttachments, inputDragOver, uploadFiles, removeAttachment, clearAttachments, buildAttachmentContext, onFilesSelected } = useFileUpload()
|
||||||
|
const inputAreaRef = ref<InstanceType<typeof ChatInputArea> | null>(null)
|
||||||
|
function handleAttachFile() { inputAreaRef.value?.fileInputEl?.click() }
|
||||||
const { stripMarkdownForTTS } = useMarkdown()
|
const { stripMarkdownForTTS } = useMarkdown()
|
||||||
const { isSpeaking, speak: ttsSpeak, stop: ttsStop } = useTTS()
|
const { isSpeaking, speak: ttsSpeak, stop: ttsStop } = useTTS()
|
||||||
|
|
||||||
|
|||||||
@@ -155,10 +155,12 @@ export function useFileUpload() {
|
|||||||
|
|
||||||
async function onFilesSelected(e: Event): Promise<PendingAttachment[]> {
|
async function onFilesSelected(e: Event): Promise<PendingAttachment[]> {
|
||||||
const input = e.target as HTMLInputElement
|
const input = e.target as HTMLInputElement
|
||||||
const files = input.files
|
const rawFiles = input.files
|
||||||
input.value = '' // Reset so the same file can be re-selected
|
if (!rawFiles?.length) return []
|
||||||
if (files?.length) return uploadFiles(Array.from(files))
|
// 必须先复制再重置 input,否则 Chromium 系清空 FileList 引用
|
||||||
return []
|
const fileArr = Array.from(rawFiles)
|
||||||
|
input.value = ''
|
||||||
|
return uploadFiles(fileArr)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAttachFile() {
|
function handleAttachFile() {
|
||||||
|
|||||||
@@ -486,7 +486,8 @@ import { useTTS } from '@/composables/useTTS'
|
|||||||
import { useSpeechRecognition } from '@/composables/useSpeechRecognition'
|
import { useSpeechRecognition } from '@/composables/useSpeechRecognition'
|
||||||
|
|
||||||
const { renderMarkdown, stripMarkdownForTTS } = useMarkdown()
|
const { renderMarkdown, stripMarkdownForTTS } = useMarkdown()
|
||||||
const { pendingAttachments, inputDragOver, uploadFiles, removeAttachment, clearAttachments, buildAttachmentContext, onFilesSelected, handleAttachFile } = useFileUpload()
|
const { pendingAttachments, inputDragOver, uploadFiles, removeAttachment, clearAttachments, buildAttachmentContext, onFilesSelected } = useFileUpload()
|
||||||
|
function handleAttachFile() { inputAreaRef.value?.fileInputEl?.click() }
|
||||||
const { isSpeaking, speak: ttsSpeak, stop: ttsStop } = useTTS()
|
const { isSpeaking, speak: ttsSpeak, stop: ttsStop } = useTTS()
|
||||||
const { isListening, transcript, error: voiceError, supported: voiceSupported, start: voiceStart, stop: voiceStop } = useSpeechRecognition()
|
const { isListening, transcript, error: voiceError, supported: voiceSupported, start: voiceStart, stop: voiceStop } = useSpeechRecognition()
|
||||||
const modelConfigStore = useModelConfigStore()
|
const modelConfigStore = useModelConfigStore()
|
||||||
|
|||||||
Reference in New Issue
Block a user