Feat: support query mode prefix in retrieval input

This commit is contained in:
yangdx
2025-04-23 01:26:34 +08:00
parent 6f064925eb
commit e97e54b7a5
6 changed files with 64 additions and 13 deletions

View File

@@ -10,6 +10,7 @@ import QuerySettings from '@/components/retrieval/QuerySettings'
import { ChatMessage, MessageWithError } from '@/components/retrieval/ChatMessage'
import { EraserIcon, SendIcon } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import type { QueryMode } from '@/api/lightrag'
export default function RetrievalTesting() {
const { t } = useTranslation()
@@ -18,6 +19,7 @@ export default function RetrievalTesting() {
)
const [inputValue, setInputValue] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [inputError, setInputError] = useState('') // Error message for input
// Reference to track if we should follow scroll during streaming (using ref for synchronous updates)
const shouldFollowScrollRef = useRef(true)
// Reference to track if user interaction is from the form area
@@ -47,7 +49,38 @@ export default function RetrievalTesting() {
e.preventDefault()
if (!inputValue.trim() || isLoading) return
// Parse query mode prefix
const allowedModes: QueryMode[] = ['naive', 'local', 'global', 'hybrid', 'mix', 'bypass']
const prefixMatch = inputValue.match(/^\/(\w+)\s+(.+)/)
let modeOverride: QueryMode | undefined = undefined
let actualQuery = inputValue
// If input starts with a slash, but does not match the valid prefix pattern, treat as error
if (/^\/\S+/.test(inputValue) && !prefixMatch) {
setInputError(t('retrievePanel.retrieval.queryModePrefixInvalid'))
return
}
if (prefixMatch) {
const mode = prefixMatch[1] as QueryMode
const query = prefixMatch[2]
if (!allowedModes.includes(mode)) {
setInputError(
t('retrievePanel.retrieval.queryModeError', {
modes: 'naive, local, global, hybrid, mix, bypass',
})
)
return
}
modeOverride = mode
actualQuery = query
}
// Clear error message
setInputError('')
// Create messages
// Save the original input (with prefix if any) in userMessage.content for display
const userMessage: Message = {
content: inputValue,
role: 'user'
@@ -103,11 +136,12 @@ export default function RetrievalTesting() {
const state = useSettingsStore.getState()
const queryParams = {
...state.querySettings,
query: userMessage.content,
query: actualQuery,
conversation_history: prevMessages
.filter((m) => m.isError !== true)
.slice(-(state.querySettings.history_turns || 0) * 2)
.map((m) => ({ role: m.role, content: m.content }))
.map((m) => ({ role: m.role, content: m.content })),
...(modeOverride ? { mode: modeOverride } : {})
}
try {
@@ -270,10 +304,17 @@ export default function RetrievalTesting() {
id="query-input"
className="w-full"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onChange={(e) => {
setInputValue(e.target.value)
if (inputError) setInputError('')
}}
placeholder={t('retrievePanel.retrieval.placeholder')}
disabled={isLoading}
/>
{/* Error message below input */}
{inputError && (
<div className="absolute left-0 top-full mt-1 text-xs text-red-500">{inputError}</div>
)}
</div>
<Button type="submit" variant="default" disabled={isLoading} size="sm">
<SendIcon />

View File

@@ -303,8 +303,10 @@
"startPrompt": "ابدأ الاسترجاع بكتابة استفسارك أدناه",
"clear": "مسح",
"send": "إرسال",
"placeholder": "اكتب استفسارك...",
"error": "خطأ: فشل الحصول على الرد"
"placeholder": "اكتب استفسارك... (بادئة وضع الاستعلام: /<Query Mode>)",
"error": "خطأ: فشل الحصول على الرد",
"queryModeError": "يُسمح فقط بأنماط الاستعلام التالية: {{modes}}",
"queryModePrefixInvalid": "بادئة وضع الاستعلام غير صالحة. استخدم: /<الوضع> [مسافة] استفسارك"
},
"querySettings": {
"parametersTitle": "المعلمات",

View File

@@ -303,8 +303,10 @@
"startPrompt": "Start a retrieval by typing your query below",
"clear": "Clear",
"send": "Send",
"placeholder": "Type your query...",
"error": "Error: Failed to get response"
"placeholder": "Type your query... (Query mode prefix: /<Query Mode>)",
"error": "Error: Failed to get response",
"queryModeError": "Only supports the following query modes: {{modes}}",
"queryModePrefixInvalid": "Invalid query mode prefix. Use: /<mode> [space] your query"
},
"querySettings": {
"parametersTitle": "Parameters",

View File

@@ -303,8 +303,10 @@
"startPrompt": "Démarrez une récupération en tapant votre requête ci-dessous",
"clear": "Effacer",
"send": "Envoyer",
"placeholder": "Tapez votre requête...",
"error": "Erreur : Échec de l'obtention de la réponse"
"placeholder": "Tapez votre requête... (Préfixe du mode de requête : /<Query Mode>)",
"error": "Erreur : Échec de l'obtention de la réponse",
"queryModeError": "Seuls les modes de requête suivants sont pris en charge : {{modes}}",
"queryModePrefixInvalid": "Préfixe de mode de requête invalide. Utilisez : /<mode> [espace] votre requête"
},
"querySettings": {
"parametersTitle": "Paramètres",

View File

@@ -304,8 +304,10 @@
"startPrompt": "输入查询开始检索",
"clear": "清空",
"send": "发送",
"placeholder": "输入查询...",
"error": "错误:获取响应失败"
"placeholder": "输入查询...(查询模式前缀:/<Query Mode>)",
"error": "错误:获取响应失败",
"queryModeError": "仅支持以下查询模式:{{modes}}",
"queryModePrefixInvalid": "无效的查询模式前缀。请使用:/<模式> [空格] 查询内容"
},
"querySettings": {
"parametersTitle": "参数",

View File

@@ -303,8 +303,10 @@
"startPrompt": "輸入查詢開始檢索",
"clear": "清空",
"send": "送出",
"placeholder": "輸入查詢...",
"error": "錯誤:取得回應失敗"
"placeholder": "輸入查詢...(查詢模式前綴:/<Query Mode>)",
"error": "錯誤:取得回應失敗",
"queryModeError": "僅支援以下查詢模式:{{modes}}",
"queryModePrefixInvalid": "無效的查詢模式前綴。請使用:/<模式> [空格] 查詢內容"
},
"querySettings": {
"parametersTitle": "參數",