mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
feat: add reasoning format processing to LLMNode for <think> tag handling (#23313)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@ -479,6 +479,10 @@ export const LLM_OUTPUT_STRUCT: Var[] = [
|
||||
variable: 'text',
|
||||
type: VarType.string,
|
||||
},
|
||||
{
|
||||
variable: 'reasoning_content',
|
||||
type: VarType.string,
|
||||
},
|
||||
{
|
||||
variable: 'usage',
|
||||
type: VarType.object,
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
|
||||
type ReasoningFormatConfigProps = {
|
||||
value?: 'tagged' | 'separated'
|
||||
onChange: (value: 'tagged' | 'separated') => void
|
||||
readonly?: boolean
|
||||
}
|
||||
|
||||
const ReasoningFormatConfig: FC<ReasoningFormatConfigProps> = ({
|
||||
value = 'tagged',
|
||||
onChange,
|
||||
readonly = false,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Field
|
||||
title={t('workflow.nodes.llm.reasoningFormat.title')}
|
||||
tooltip={t('workflow.nodes.llm.reasoningFormat.tooltip')}
|
||||
operations={
|
||||
// ON = separated, OFF = tagged
|
||||
<Switch
|
||||
defaultValue={value === 'separated'}
|
||||
onChange={enabled => onChange(enabled ? 'separated' : 'tagged')}
|
||||
size='md'
|
||||
disabled={readonly}
|
||||
key={value}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div />
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default ReasoningFormatConfig
|
||||
@ -17,6 +17,7 @@ import type { NodePanelProps } from '@/app/components/workflow/types'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
|
||||
import StructureOutput from './components/structure-output'
|
||||
import ReasoningFormatConfig from './components/reasoning-format-config'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import { RiAlertFill, RiQuestionLine } from '@remixicon/react'
|
||||
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
|
||||
@ -61,6 +62,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
handleStructureOutputEnableChange,
|
||||
handleStructureOutputChange,
|
||||
filterJinja2InputVar,
|
||||
handleReasoningFormatChange,
|
||||
} = useConfig(id, data)
|
||||
|
||||
const model = inputs.model
|
||||
@ -239,6 +241,14 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
config={inputs.vision?.configs}
|
||||
onConfigChange={handleVisionResolutionChange}
|
||||
/>
|
||||
|
||||
{/* Reasoning Format */}
|
||||
<ReasoningFormatConfig
|
||||
// Default to tagged for backward compatibility
|
||||
value={inputs.reasoning_format || 'tagged'}
|
||||
onChange={handleReasoningFormatChange}
|
||||
readonly={readOnly}
|
||||
/>
|
||||
</div>
|
||||
<Split />
|
||||
<OutputVars
|
||||
|
||||
@ -17,6 +17,7 @@ export type LLMNodeType = CommonNodeType & {
|
||||
}
|
||||
structured_output_enabled?: boolean
|
||||
structured_output?: StructuredOutput
|
||||
reasoning_format?: 'tagged' | 'separated'
|
||||
}
|
||||
|
||||
export enum Type {
|
||||
|
||||
@ -315,6 +315,14 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
||||
return [VarType.arrayObject, VarType.array, VarType.number, VarType.string, VarType.secret, VarType.arrayString, VarType.arrayNumber, VarType.file, VarType.arrayFile].includes(varPayload.type)
|
||||
}, [])
|
||||
|
||||
// reasoning format
|
||||
const handleReasoningFormatChange = useCallback((reasoningFormat: 'tagged' | 'separated') => {
|
||||
const newInputs = produce(inputs, (draft) => {
|
||||
draft.reasoning_format = reasoningFormat
|
||||
})
|
||||
setInputs(newInputs)
|
||||
}, [inputs, setInputs])
|
||||
|
||||
const {
|
||||
availableVars,
|
||||
availableNodesWithParent,
|
||||
@ -355,6 +363,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
||||
setStructuredOutputCollapsed,
|
||||
handleStructureOutputEnableChange,
|
||||
filterJinja2InputVar,
|
||||
handleReasoningFormatChange,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
instruction: 'Anleitung',
|
||||
regenerate: 'Regenerieren',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tooltip: 'Inhalte aus Denk-Tags extrahieren und im Feld reasoning_content speichern.',
|
||||
separated: 'Separate Denk tags',
|
||||
title: 'Aktivieren Sie die Trennung von Argumentations-Tags',
|
||||
tagged: 'Behalte die Denk-Tags',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Abfragevariable',
|
||||
|
||||
@ -449,6 +449,12 @@ const translation = {
|
||||
variable: 'Variable',
|
||||
},
|
||||
sysQueryInUser: 'sys.query in user message is required',
|
||||
reasoningFormat: {
|
||||
title: 'Enable reasoning tag separation',
|
||||
tagged: 'Keep think tags',
|
||||
separated: 'Separate think tags',
|
||||
tooltip: 'Extract content from think tags and store it in the reasoning_content field.',
|
||||
},
|
||||
jsonSchema: {
|
||||
title: 'Structured Output Schema',
|
||||
instruction: 'Instruction',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
import: 'Importar desde JSON',
|
||||
resetDefaults: 'Restablecer',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'Mantén las etiquetas de pensamiento',
|
||||
separated: 'Separar etiquetas de pensamiento',
|
||||
title: 'Habilitar la separación de etiquetas de razonamiento',
|
||||
tooltip: 'Extraer contenido de las etiquetas de pensamiento y almacenarlo en el campo reasoning_content.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Variable de consulta',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
fieldNamePlaceholder: 'نام میدان',
|
||||
generationTip: 'شما میتوانید از زبان طبیعی برای ایجاد سریع یک طرحواره JSON استفاده کنید.',
|
||||
},
|
||||
reasoningFormat: {
|
||||
separated: 'تگهای تفکر جداگانه',
|
||||
title: 'فعالسازی جداسازی برچسبهای استدلال',
|
||||
tagged: 'به فکر برچسبها باشید',
|
||||
tooltip: 'محتوا را از تگهای تفکر استخراج کرده و در فیلد reasoning_content ذخیره کنید.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'متغیر جستجو',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
generateJsonSchema: 'Générer un schéma JSON',
|
||||
resultTip: 'Voici le résultat généré. Si vous n\'êtes pas satisfait, vous pouvez revenir en arrière et modifier votre demande.',
|
||||
},
|
||||
reasoningFormat: {
|
||||
title: 'Activer la séparation des balises de raisonnement',
|
||||
tagged: 'Gardez les étiquettes de pensée',
|
||||
separated: 'Séparer les balises de réflexion',
|
||||
tooltip: 'Extraire le contenu des balises think et le stocker dans le champ reasoning_content.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Variable de requête',
|
||||
|
||||
@ -483,6 +483,12 @@ const translation = {
|
||||
required: 'आवश्यक',
|
||||
addChildField: 'बच्चे का क्षेत्र जोड़ें',
|
||||
},
|
||||
reasoningFormat: {
|
||||
title: 'कारण संबंध टैग विभाजन सक्षम करें',
|
||||
separated: 'अलग सोच टैग',
|
||||
tagged: 'टैग्स के बारे में सोचते रहें',
|
||||
tooltip: 'थिंक टैग से सामग्री निकाले और इसे reasoning_content क्षेत्र में संग्रहित करें।',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'प्रश्न वेरिएबल',
|
||||
|
||||
@ -487,6 +487,12 @@ const translation = {
|
||||
generating: 'Generazione dello schema JSON...',
|
||||
generatedResult: 'Risultato generato',
|
||||
},
|
||||
reasoningFormat: {
|
||||
title: 'Abilita la separazione dei tag di ragionamento',
|
||||
tagged: 'Continua a pensare ai tag',
|
||||
separated: 'Tag di pensiero separati',
|
||||
tooltip: 'Estrai il contenuto dai tag think e conservalo nel campo reasoning_content.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Variabile Query',
|
||||
|
||||
@ -477,6 +477,12 @@ const translation = {
|
||||
saveSchema: '編集中のフィールドを確定してから保存してください。',
|
||||
},
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'タグを考え続けてください',
|
||||
separated: '思考タグを分ける',
|
||||
title: '推論タグの分離を有効にする',
|
||||
tooltip: 'thinkタグから内容を抽出し、それをreasoning_contentフィールドに保存します。',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: '検索変数',
|
||||
|
||||
@ -497,6 +497,12 @@ const translation = {
|
||||
doc: '구조화된 출력에 대해 더 알아보세요.',
|
||||
import: 'JSON 에서 가져오기',
|
||||
},
|
||||
reasoningFormat: {
|
||||
title: '추론 태그 분리 활성화',
|
||||
separated: '추론 태그 분리',
|
||||
tooltip: '추론 태그에서 내용을 추출하고 이를 reasoning_content 필드에 저장합니다',
|
||||
tagged: '추론 태그 유지',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: '쿼리 변수',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
back: 'Tył',
|
||||
addField: 'Dodaj pole',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tooltip: 'Wyodrębnij treść z tagów think i przechowaj ją w polu reasoning_content.',
|
||||
separated: 'Oddziel tagi myślenia',
|
||||
tagged: 'Zachowaj myśl tagi',
|
||||
title: 'Włącz separację tagów uzasadnienia',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Zmienna zapytania',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
apply: 'Aplicar',
|
||||
required: 'obrigatório',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'Mantenha as tags de pensamento',
|
||||
title: 'Ativar separação de tags de raciocínio',
|
||||
separated: 'Separe as tags de pensamento',
|
||||
tooltip: 'Extraia o conteúdo das tags de pensamento e armazene-o no campo reasoning_content.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Variável de consulta',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
back: 'Înapoi',
|
||||
promptPlaceholder: 'Descrie schema ta JSON...',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'Ține minte etichetele',
|
||||
separated: 'Etichete de gândire separate',
|
||||
title: 'Activează separarea etichetelor de raționare',
|
||||
tooltip: 'Extrage conținutul din etichetele think și stochează-l în câmpul reasoning_content.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Variabilă de interogare',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
generating: 'Генерация схемы JSON...',
|
||||
promptTooltip: 'Преобразуйте текстовое описание в стандартизированную структуру JSON Schema.',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'Продолжайте думать о тегах',
|
||||
title: 'Включите разделение тегов на основе логики',
|
||||
tooltip: 'Извлечь содержимое из тегов think и сохранить его в поле reasoning_content.',
|
||||
separated: 'Отдельные теги для мышления',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Переменная запроса',
|
||||
|
||||
@ -477,6 +477,12 @@ const translation = {
|
||||
context: 'kontekst',
|
||||
addMessage: 'Dodaj sporočilo',
|
||||
vision: 'vizija',
|
||||
reasoningFormat: {
|
||||
tagged: 'Ohranite oznake za razmišljanje',
|
||||
title: 'Omogoči ločevanje oznak za razsojanje',
|
||||
tooltip: 'Izvleći vsebino iz miselnih oznak in jo shraniti v polje reasoning_content.',
|
||||
separated: 'Ločite oznake za razmišljanje',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
outputVars: {
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
stringValidations: 'การตรวจสอบสตริง',
|
||||
required: 'จำเป็นต้องใช้',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'รักษาความคิดเกี่ยวกับแท็ก',
|
||||
separated: 'แยกแท็กความคิดเห็น',
|
||||
tooltip: 'ดึงเนื้อหาจากแท็กคิดและเก็บไว้ในฟิลด์ reasoning_content.',
|
||||
title: 'เปิดใช้งานการแยกแท็กการเหตุผล',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'ตัวแปรแบบสอบถาม',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
addChildField: 'Çocuk Alanı Ekle',
|
||||
resultTip: 'İşte oluşturulan sonuç. Eğer memnun değilseniz, geri dönüp isteminizi değiştirebilirsiniz.',
|
||||
},
|
||||
reasoningFormat: {
|
||||
separated: 'Ayrı düşünce etiketleri',
|
||||
title: 'Akıl yürütme etiket ayrımını etkinleştir',
|
||||
tagged: 'Etiketleri düşünmeye devam et',
|
||||
tooltip: 'Düşünce etiketlerinden içeriği çıkarın ve bunu reasoning_content alanında saklayın.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Sorgu Değişkeni',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
title: 'Структурована схема виходу',
|
||||
doc: 'Дізнайтеся більше про структурований вихід',
|
||||
},
|
||||
reasoningFormat: {
|
||||
separated: 'Окремі теги для думок',
|
||||
tagged: 'Продовжуйте думати про мітки',
|
||||
title: 'Увімкніть розділення тегів для міркування',
|
||||
tooltip: 'Витягніть вміст з тегів think і зберігайте його в полі reasoning_content.',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Змінна запиту',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
addChildField: 'Thêm trường trẻ em',
|
||||
title: 'Sơ đồ đầu ra có cấu trúc',
|
||||
},
|
||||
reasoningFormat: {
|
||||
tagged: 'Giữ lại thẻ suy nghĩ',
|
||||
tooltip: 'Trích xuất nội dung từ các thẻ think và lưu nó vào trường reasoning_content.',
|
||||
separated: 'Tách biệt các thẻ suy nghĩ',
|
||||
title: 'Bật chế độ phân tách nhãn lý luận',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: 'Biến truy vấn',
|
||||
|
||||
@ -477,6 +477,12 @@ const translation = {
|
||||
saveSchema: '请先完成当前字段的编辑',
|
||||
},
|
||||
},
|
||||
reasoningFormat: {
|
||||
tooltip: '从think标签中提取内容,并将其存储在reasoning_content字段中。',
|
||||
title: '启用推理标签分离',
|
||||
tagged: '保持思考标签',
|
||||
separated: '分开思考标签',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: '查询变量',
|
||||
|
||||
@ -470,6 +470,12 @@ const translation = {
|
||||
required: '必需的',
|
||||
resultTip: '這是生成的結果。如果您不滿意,可以回去修改您的提示。',
|
||||
},
|
||||
reasoningFormat: {
|
||||
title: '啟用推理標籤分離',
|
||||
tooltip: '從 think 標籤中提取內容並將其存儲在 reasoning_content 欄位中。',
|
||||
tagged: '保持思考標籤',
|
||||
separated: '分開思考標籤',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
queryVariable: '查詢變量',
|
||||
|
||||
Reference in New Issue
Block a user