local inference: stricter GGUF requirements, auto detection of tool calling support, fixed thinking output parsing (#9442)
Signed-off-by: jh-block <jhugo@block.xyz>
This commit is contained in:
+94
-6
@@ -1993,6 +1993,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/local-inference/chat-templates/builtin": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"super::routes::local_inference"
|
||||
],
|
||||
"operationId": "list_builtin_chat_templates",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "llama.cpp built-in chat template names",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/local-inference/download": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -4260,6 +4283,63 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChatTemplate": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"embedded"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"builtin"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"template",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"template": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"custom_inline"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"discriminator": {
|
||||
"propertyName": "type"
|
||||
}
|
||||
},
|
||||
"CheckProviderRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -6716,6 +6796,9 @@
|
||||
"ModelSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chat_template": {
|
||||
"$ref": "#/components/schemas/ChatTemplate"
|
||||
},
|
||||
"context_size": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
@@ -6766,9 +6849,6 @@
|
||||
"format": "int32",
|
||||
"nullable": true
|
||||
},
|
||||
"native_tool_calling": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"presence_penalty": {
|
||||
"type": "number",
|
||||
"format": "float"
|
||||
@@ -6784,15 +6864,15 @@
|
||||
"sampling": {
|
||||
"$ref": "#/components/schemas/SamplingConfig"
|
||||
},
|
||||
"use_jinja": {
|
||||
"type": "boolean"
|
||||
"tool_calling": {
|
||||
"$ref": "#/components/schemas/ToolCallingMode"
|
||||
},
|
||||
"use_mlock": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"vision_capable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether this model architecture supports vision input.\nDerived from the featured model table, not user-configurable."
|
||||
"description": "Whether this model architecture supports vision input.\nDerived from associated mmproj metadata, not user-configurable."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8797,6 +8877,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ToolCallingMode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"auto",
|
||||
"force_native",
|
||||
"force_emulated"
|
||||
]
|
||||
},
|
||||
"ToolConfirmationRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -76,6 +76,16 @@ export type ChatRequest = {
|
||||
user_message: Message;
|
||||
};
|
||||
|
||||
export type ChatTemplate = {
|
||||
type: 'embedded';
|
||||
} | {
|
||||
name: string;
|
||||
type: 'builtin';
|
||||
} | {
|
||||
template: string;
|
||||
type: 'custom_inline';
|
||||
};
|
||||
|
||||
export type CheckProviderRequest = {
|
||||
provider: string;
|
||||
};
|
||||
@@ -863,6 +873,7 @@ export type ModelInfoResponse = {
|
||||
};
|
||||
|
||||
export type ModelSettings = {
|
||||
chat_template?: ChatTemplate;
|
||||
context_size?: number | null;
|
||||
enable_thinking?: boolean;
|
||||
flash_attention?: boolean | null;
|
||||
@@ -880,16 +891,15 @@ export type ModelSettings = {
|
||||
n_batch?: number | null;
|
||||
n_gpu_layers?: number | null;
|
||||
n_threads?: number | null;
|
||||
native_tool_calling?: boolean;
|
||||
presence_penalty?: number;
|
||||
repeat_last_n?: number;
|
||||
repeat_penalty?: number;
|
||||
sampling?: SamplingConfig;
|
||||
use_jinja?: boolean;
|
||||
tool_calling?: ToolCallingMode;
|
||||
use_mlock?: boolean;
|
||||
/**
|
||||
* Whether this model architecture supports vision input.
|
||||
* Derived from the featured model table, not user-configurable.
|
||||
* Derived from associated mmproj metadata, not user-configurable.
|
||||
*/
|
||||
vision_capable?: boolean;
|
||||
};
|
||||
@@ -1544,6 +1554,8 @@ export type ToolAnnotations = {
|
||||
title?: string;
|
||||
};
|
||||
|
||||
export type ToolCallingMode = 'auto' | 'force_native' | 'force_emulated';
|
||||
|
||||
export type ToolConfirmationRequest = {
|
||||
arguments: JsonObject;
|
||||
id: string;
|
||||
@@ -3241,6 +3253,22 @@ export type StartTetrateSetupResponses = {
|
||||
|
||||
export type StartTetrateSetupResponse = StartTetrateSetupResponses[keyof StartTetrateSetupResponses];
|
||||
|
||||
export type ListBuiltinChatTemplatesData = {
|
||||
body?: never;
|
||||
path?: never;
|
||||
query?: never;
|
||||
url: '/local-inference/chat-templates/builtin';
|
||||
};
|
||||
|
||||
export type ListBuiltinChatTemplatesResponses = {
|
||||
/**
|
||||
* llama.cpp built-in chat template names
|
||||
*/
|
||||
200: Array<string>;
|
||||
};
|
||||
|
||||
export type ListBuiltinChatTemplatesResponse = ListBuiltinChatTemplatesResponses[keyof ListBuiltinChatTemplatesResponses];
|
||||
|
||||
export type DownloadHfModelData = {
|
||||
body: DownloadModelRequest;
|
||||
path?: never;
|
||||
|
||||
@@ -4,9 +4,12 @@ import { Button } from '../../ui/button';
|
||||
import { Switch } from '../../ui/switch';
|
||||
import {
|
||||
getModelSettings,
|
||||
listBuiltinChatTemplates,
|
||||
updateModelSettings,
|
||||
type ChatTemplate,
|
||||
type ModelSettings,
|
||||
type SamplingConfig,
|
||||
type ToolCallingMode,
|
||||
} from '../../../api';
|
||||
import { defineMessages, useIntl } from '../../../i18n';
|
||||
|
||||
@@ -161,16 +164,59 @@ const i18n = defineMessages({
|
||||
},
|
||||
toolCalling: {
|
||||
id: 'modelSettingsPanel.toolCalling',
|
||||
defaultMessage: 'Tool Calling',
|
||||
defaultMessage: 'Tool calling',
|
||||
},
|
||||
nativeToolCalling: {
|
||||
id: 'modelSettingsPanel.nativeToolCalling',
|
||||
defaultMessage: 'Native tool calling',
|
||||
toolCallingDescription: {
|
||||
id: 'modelSettingsPanel.toolCallingDescription',
|
||||
defaultMessage: 'Choose how local models select native or emulated tool calling',
|
||||
},
|
||||
nativeToolCallingDescription: {
|
||||
id: 'modelSettingsPanel.nativeToolCallingDescription',
|
||||
defaultMessage:
|
||||
"Use the model's built-in tool-call format instead of the shell-command emulator. Enable for large models that reliably support tool calling.",
|
||||
toolCallingAuto: {
|
||||
id: 'modelSettingsPanel.toolCallingAuto',
|
||||
defaultMessage: 'Auto',
|
||||
},
|
||||
toolCallingForceNative: {
|
||||
id: 'modelSettingsPanel.toolCallingForceNative',
|
||||
defaultMessage: 'Force native',
|
||||
},
|
||||
toolCallingForceEmulated: {
|
||||
id: 'modelSettingsPanel.toolCallingForceEmulated',
|
||||
defaultMessage: 'Force emulated',
|
||||
},
|
||||
chatTemplate: {
|
||||
id: 'modelSettingsPanel.chatTemplate',
|
||||
defaultMessage: 'Chat template',
|
||||
},
|
||||
chatTemplateDescription: {
|
||||
id: 'modelSettingsPanel.chatTemplateDescription',
|
||||
defaultMessage: 'Use embedded GGUF metadata, a llama.cpp built-in template, or inline Jinja',
|
||||
},
|
||||
chatTemplateEmbedded: {
|
||||
id: 'modelSettingsPanel.chatTemplateEmbedded',
|
||||
defaultMessage: 'Embedded',
|
||||
},
|
||||
chatTemplateBuiltin: {
|
||||
id: 'modelSettingsPanel.chatTemplateBuiltin',
|
||||
defaultMessage: 'Built-in',
|
||||
},
|
||||
chatTemplateCustomInline: {
|
||||
id: 'modelSettingsPanel.chatTemplateCustomInline',
|
||||
defaultMessage: 'Custom inline',
|
||||
},
|
||||
builtinChatTemplate: {
|
||||
id: 'modelSettingsPanel.builtinChatTemplate',
|
||||
defaultMessage: 'Built-in template',
|
||||
},
|
||||
builtinChatTemplateDescription: {
|
||||
id: 'modelSettingsPanel.builtinChatTemplateDescription',
|
||||
defaultMessage: 'Select a llama.cpp built-in template name',
|
||||
},
|
||||
customChatTemplate: {
|
||||
id: 'modelSettingsPanel.customChatTemplate',
|
||||
defaultMessage: 'Custom chat template',
|
||||
},
|
||||
customChatTemplateDescription: {
|
||||
id: 'modelSettingsPanel.customChatTemplateDescription',
|
||||
defaultMessage: 'Paste the full Jinja chat template source',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -194,10 +240,12 @@ const DEFAULT_SETTINGS: ModelSettings = {
|
||||
use_mlock: false,
|
||||
flash_attention: null,
|
||||
n_threads: null,
|
||||
native_tool_calling: false,
|
||||
tool_calling: 'auto',
|
||||
chat_template: { type: 'embedded' },
|
||||
};
|
||||
|
||||
type SamplingType = SamplingConfig['type'];
|
||||
type ChatTemplateMode = 'embedded' | 'builtin' | 'custom_inline';
|
||||
|
||||
function NumberField({
|
||||
label,
|
||||
@@ -302,16 +350,59 @@ function SelectField<T extends string>({
|
||||
);
|
||||
}
|
||||
|
||||
function TextAreaField({
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
onChange,
|
||||
onBlur,
|
||||
}: {
|
||||
label: string;
|
||||
description?: string;
|
||||
value: string;
|
||||
onChange: (v: string) => void;
|
||||
onBlur: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-xs font-medium text-text-default">{label}</label>
|
||||
{description && <span className="text-xs text-text-muted">{description}</span>}
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
onBlur={onBlur}
|
||||
spellCheck={false}
|
||||
className="min-h-32 rounded border border-border-subtle bg-background-default px-2 py-1 font-mono text-xs text-text-default"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
const intl = useIntl();
|
||||
const [settings, setSettings] = useState<ModelSettings>(DEFAULT_SETTINGS);
|
||||
const [chatTemplateDraft, setChatTemplateDraft] = useState('');
|
||||
const [builtinTemplateDraft, setBuiltinTemplateDraft] = useState('chatml');
|
||||
const [builtinTemplateOptions, setBuiltinTemplateOptions] = useState<string[]>(['chatml']);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
const res = await getModelSettings({ path: { model_id: modelId } });
|
||||
if (res.data) setSettings(res.data);
|
||||
const [settingsResult, builtinsResult] = await Promise.allSettled([
|
||||
getModelSettings({ path: { model_id: modelId } }),
|
||||
listBuiltinChatTemplates(),
|
||||
]);
|
||||
if (builtinsResult.status === 'fulfilled' && builtinsResult.value.data?.length) {
|
||||
setBuiltinTemplateOptions(builtinsResult.value.data);
|
||||
}
|
||||
if (settingsResult.status === 'fulfilled' && settingsResult.value.data) {
|
||||
setSettings({
|
||||
...settingsResult.value.data,
|
||||
tool_calling: settingsResult.value.data.tool_calling ?? 'auto',
|
||||
chat_template: settingsResult.value.data.chat_template ?? { type: 'embedded' },
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// use defaults
|
||||
} finally {
|
||||
@@ -323,6 +414,18 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
load();
|
||||
}, [load]);
|
||||
|
||||
useEffect(() => {
|
||||
const chatTemplate = settings.chat_template;
|
||||
if (chatTemplate?.type === 'custom_inline') {
|
||||
setChatTemplateDraft(chatTemplate.template ?? '');
|
||||
} else {
|
||||
setChatTemplateDraft('');
|
||||
}
|
||||
if (chatTemplate?.type === 'builtin') {
|
||||
setBuiltinTemplateDraft(chatTemplate.name ?? 'chatml');
|
||||
}
|
||||
}, [settings.chat_template]);
|
||||
|
||||
const save = async (updated: ModelSettings) => {
|
||||
setSettings(updated);
|
||||
setSaving(true);
|
||||
@@ -342,6 +445,38 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
};
|
||||
|
||||
const samplingType: SamplingType = settings.sampling?.type ?? 'Temperature';
|
||||
const chatTemplate = settings.chat_template ?? { type: 'embedded' };
|
||||
const chatTemplateMode: ChatTemplateMode =
|
||||
chatTemplate.type === 'custom_inline'
|
||||
? 'custom_inline'
|
||||
: chatTemplate.type === 'builtin'
|
||||
? 'builtin'
|
||||
: 'embedded';
|
||||
|
||||
const setChatTemplateMode = (mode: ChatTemplateMode) => {
|
||||
let next: ChatTemplate;
|
||||
if (mode === 'custom_inline') {
|
||||
next = { type: 'custom_inline', template: chatTemplateDraft };
|
||||
} else if (mode === 'builtin') {
|
||||
next = { type: 'builtin', name: builtinTemplateDraft.trim() || builtinTemplateOptions[0] || 'chatml' };
|
||||
} else {
|
||||
next = { type: 'embedded' };
|
||||
}
|
||||
updateField('chat_template', next);
|
||||
};
|
||||
|
||||
const setBuiltinTemplateName = (name: string) => {
|
||||
setBuiltinTemplateDraft(name);
|
||||
if (chatTemplateMode === 'builtin') {
|
||||
updateField('chat_template', { type: 'builtin', name });
|
||||
}
|
||||
};
|
||||
|
||||
const saveChatTemplateDraft = () => {
|
||||
if (chatTemplateMode === 'custom_inline') {
|
||||
updateField('chat_template', { type: 'custom_inline', template: chatTemplateDraft });
|
||||
}
|
||||
};
|
||||
|
||||
const setSamplingType = (type: SamplingType) => {
|
||||
let sampling: SamplingConfig;
|
||||
@@ -366,6 +501,10 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
save({ ...settings, sampling: { ...settings.sampling!, ...partial } as SamplingConfig });
|
||||
};
|
||||
|
||||
const visibleBuiltinTemplateOptions = builtinTemplateOptions.includes(builtinTemplateDraft)
|
||||
? builtinTemplateOptions
|
||||
: [builtinTemplateDraft, ...builtinTemplateOptions].filter(Boolean);
|
||||
|
||||
if (loading) {
|
||||
return <div className="py-2 text-xs text-text-muted">{intl.formatMessage(i18n.loadingSettings)}</div>;
|
||||
}
|
||||
@@ -585,16 +724,52 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
]}
|
||||
onChange={(v) => updateField('flash_attention', v === 'auto' ? null : v === 'on')}
|
||||
/>
|
||||
</div>
|
||||
{/* Tool Calling */}
|
||||
<div className="space-y-2">
|
||||
<h5 className="text-xs font-medium text-text-default">{intl.formatMessage(i18n.toolCalling)}</h5>
|
||||
<ToggleField
|
||||
label={intl.formatMessage(i18n.nativeToolCalling)}
|
||||
description={intl.formatMessage(i18n.nativeToolCallingDescription)}
|
||||
value={settings.native_tool_calling ?? false}
|
||||
onChange={(v) => updateField('native_tool_calling', v)}
|
||||
<SelectField<ToolCallingMode>
|
||||
label={intl.formatMessage(i18n.toolCalling)}
|
||||
description={intl.formatMessage(i18n.toolCallingDescription)}
|
||||
value={settings.tool_calling ?? 'auto'}
|
||||
options={[
|
||||
{ value: 'auto', label: intl.formatMessage(i18n.toolCallingAuto) },
|
||||
{ value: 'force_native', label: intl.formatMessage(i18n.toolCallingForceNative) },
|
||||
{ value: 'force_emulated', label: intl.formatMessage(i18n.toolCallingForceEmulated) },
|
||||
]}
|
||||
onChange={(v) => updateField('tool_calling', v)}
|
||||
/>
|
||||
<SelectField<ChatTemplateMode>
|
||||
label={intl.formatMessage(i18n.chatTemplate)}
|
||||
description={intl.formatMessage(i18n.chatTemplateDescription)}
|
||||
value={chatTemplateMode}
|
||||
options={[
|
||||
{ value: 'embedded', label: intl.formatMessage(i18n.chatTemplateEmbedded) },
|
||||
{ value: 'builtin', label: intl.formatMessage(i18n.chatTemplateBuiltin) },
|
||||
{
|
||||
value: 'custom_inline',
|
||||
label: intl.formatMessage(i18n.chatTemplateCustomInline),
|
||||
},
|
||||
]}
|
||||
onChange={setChatTemplateMode}
|
||||
/>
|
||||
{chatTemplateMode === 'builtin' && (
|
||||
<SelectField<string>
|
||||
label={intl.formatMessage(i18n.builtinChatTemplate)}
|
||||
description={intl.formatMessage(i18n.builtinChatTemplateDescription)}
|
||||
value={builtinTemplateDraft}
|
||||
options={visibleBuiltinTemplateOptions.map((template) => ({
|
||||
value: template,
|
||||
label: template,
|
||||
}))}
|
||||
onChange={setBuiltinTemplateName}
|
||||
/>
|
||||
)}
|
||||
{chatTemplateMode === 'custom_inline' && (
|
||||
<TextAreaField
|
||||
label={intl.formatMessage(i18n.customChatTemplate)}
|
||||
description={intl.formatMessage(i18n.customChatTemplateDescription)}
|
||||
value={chatTemplateDraft}
|
||||
onChange={setChatTemplateDraft}
|
||||
onBlur={saveChatTemplateDraft}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2183,6 +2183,27 @@
|
||||
"modelSettingsPanel.batchSizeDescription": {
|
||||
"defaultMessage": "Prompt processing batch"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplate": {
|
||||
"defaultMessage": "Built-in template"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplateDescription": {
|
||||
"defaultMessage": "Select a llama.cpp built-in template name"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplate": {
|
||||
"defaultMessage": "Chat template"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateBuiltin": {
|
||||
"defaultMessage": "Built-in"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateCustomInline": {
|
||||
"defaultMessage": "Custom inline"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateDescription": {
|
||||
"defaultMessage": "Use embedded GGUF metadata, a llama.cpp built-in template, or inline Jinja"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateEmbedded": {
|
||||
"defaultMessage": "Embedded"
|
||||
},
|
||||
"modelSettingsPanel.contextAndGeneration": {
|
||||
"defaultMessage": "Context & Generation"
|
||||
},
|
||||
@@ -2192,6 +2213,12 @@
|
||||
"modelSettingsPanel.contextSizeDescription": {
|
||||
"defaultMessage": "Max context window (0 = model default)"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplate": {
|
||||
"defaultMessage": "Custom chat template"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplateDescription": {
|
||||
"defaultMessage": "Paste the full Jinja chat template source"
|
||||
},
|
||||
"modelSettingsPanel.etaLearningRate": {
|
||||
"defaultMessage": "Eta (learning rate)"
|
||||
},
|
||||
@@ -2231,12 +2258,6 @@
|
||||
"modelSettingsPanel.minP": {
|
||||
"defaultMessage": "Min P"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCalling": {
|
||||
"defaultMessage": "Native tool calling"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCallingDescription": {
|
||||
"defaultMessage": "Use the model's built-in tool-call format instead of the shell-command emulator. Enable for large models that reliably support tool calling."
|
||||
},
|
||||
"modelSettingsPanel.performance": {
|
||||
"defaultMessage": "Performance"
|
||||
},
|
||||
@@ -2289,7 +2310,19 @@
|
||||
"defaultMessage": "CPU threads for generation"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "Tool Calling"
|
||||
"defaultMessage": "Tool calling"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingAuto": {
|
||||
"defaultMessage": "Auto"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingDescription": {
|
||||
"defaultMessage": "Choose how local models select native or emulated tool calling"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceEmulated": {
|
||||
"defaultMessage": "Force emulated"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceNative": {
|
||||
"defaultMessage": "Force native"
|
||||
},
|
||||
"modelSettingsPanel.topK": {
|
||||
"defaultMessage": "Top K"
|
||||
|
||||
@@ -2201,6 +2201,48 @@
|
||||
"modelSettingsPanel.flashAttentionDescription": {
|
||||
"defaultMessage": "Включить оптимизацию flash attention"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplate": {
|
||||
"defaultMessage": "Встроенный шаблон"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplateDescription": {
|
||||
"defaultMessage": "Выберите имя встроенного шаблона llama.cpp"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplate": {
|
||||
"defaultMessage": "Шаблон чата"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateBuiltin": {
|
||||
"defaultMessage": "Встроенный"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateCustomInline": {
|
||||
"defaultMessage": "Пользовательский inline"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateDescription": {
|
||||
"defaultMessage": "Использовать встроенные метаданные GGUF, встроенный шаблон llama.cpp или inline-шаблон Jinja"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateEmbedded": {
|
||||
"defaultMessage": "Встроенный"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplate": {
|
||||
"defaultMessage": "Пользовательский шаблон чата"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplateDescription": {
|
||||
"defaultMessage": "Вставьте полный исходный код шаблона Jinja"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "Вызов инструментов"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingAuto": {
|
||||
"defaultMessage": "Авто"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingDescription": {
|
||||
"defaultMessage": "Выберите, как локальные модели используют нативный или эмулируемый вызов инструментов"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceEmulated": {
|
||||
"defaultMessage": "Принудительно эмулируемый"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceNative": {
|
||||
"defaultMessage": "Принудительно нативный"
|
||||
},
|
||||
"modelSettingsPanel.frequencyPenalty": {
|
||||
"defaultMessage": "Штраф частоты"
|
||||
},
|
||||
@@ -2231,12 +2273,6 @@
|
||||
"modelSettingsPanel.minP": {
|
||||
"defaultMessage": "Min P"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCalling": {
|
||||
"defaultMessage": "Нативный вызов инструментов"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCallingDescription": {
|
||||
"defaultMessage": "Использовать встроенный формат вызова инструментов модели вместо эмулятора shell-команд. Включайте для крупных моделей, надежно поддерживающих вызов tool calling."
|
||||
},
|
||||
"modelSettingsPanel.performance": {
|
||||
"defaultMessage": "Производительность"
|
||||
},
|
||||
@@ -2288,9 +2324,6 @@
|
||||
"modelSettingsPanel.threadsDescription": {
|
||||
"defaultMessage": "Потоки CPU для генерации"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "Вызов инструментов"
|
||||
},
|
||||
"modelSettingsPanel.topK": {
|
||||
"defaultMessage": "Top K"
|
||||
},
|
||||
|
||||
@@ -2279,6 +2279,48 @@
|
||||
"modelSettingsPanel.flashAttentionDescription": {
|
||||
"defaultMessage": "Flaş dikkati optimizasyonunu etkinleştir"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplate": {
|
||||
"defaultMessage": "Yerleşik şablon"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplateDescription": {
|
||||
"defaultMessage": "Bir llama.cpp yerleşik şablon adı seçin"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplate": {
|
||||
"defaultMessage": "Sohbet şablonu"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateBuiltin": {
|
||||
"defaultMessage": "Yerleşik"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateCustomInline": {
|
||||
"defaultMessage": "Özel satır içi"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateDescription": {
|
||||
"defaultMessage": "Gömülü GGUF meta verilerini, llama.cpp yerleşik şablonunu veya satır içi Jinja şablonunu kullan"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateEmbedded": {
|
||||
"defaultMessage": "Gömülü"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplate": {
|
||||
"defaultMessage": "Özel sohbet şablonu"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplateDescription": {
|
||||
"defaultMessage": "Tam Jinja sohbet şablonu kaynağını yapıştır"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "Araç çağırma"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingAuto": {
|
||||
"defaultMessage": "Otomatik"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingDescription": {
|
||||
"defaultMessage": "Yerel modellerin yerel veya emüle araç çağırmayı nasıl seçeceğini belirleyin"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceEmulated": {
|
||||
"defaultMessage": "Emüle etmeye zorla"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceNative": {
|
||||
"defaultMessage": "Yereli zorla"
|
||||
},
|
||||
"modelSettingsPanel.frequencyPenalty": {
|
||||
"defaultMessage": "Frekans cezası"
|
||||
},
|
||||
@@ -2309,12 +2351,6 @@
|
||||
"modelSettingsPanel.minP": {
|
||||
"defaultMessage": "Min P"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCalling": {
|
||||
"defaultMessage": "Yerel araç çağrısı"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCallingDescription": {
|
||||
"defaultMessage": "Kabuk komutu emülatörü yerine modelin yerleşik araç çağrısı formatını kullanın. Araç çağırmayı güvenilir şekilde destekleyen büyük modeller için etkinleştirin."
|
||||
},
|
||||
"modelSettingsPanel.performance": {
|
||||
"defaultMessage": "Performans"
|
||||
},
|
||||
@@ -2366,9 +2402,6 @@
|
||||
"modelSettingsPanel.threadsDescription": {
|
||||
"defaultMessage": "Nesil için CPU iş parçacıkları"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "Takım Çağırma"
|
||||
},
|
||||
"modelSettingsPanel.topK": {
|
||||
"defaultMessage": "En İyi K"
|
||||
},
|
||||
|
||||
@@ -2150,6 +2150,48 @@
|
||||
"modelSettingsPanel.flashAttentionDescription": {
|
||||
"defaultMessage": "启用 Flash Attention 优化"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplate": {
|
||||
"defaultMessage": "内置模板"
|
||||
},
|
||||
"modelSettingsPanel.builtinChatTemplateDescription": {
|
||||
"defaultMessage": "选择 llama.cpp 内置模板名称"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplate": {
|
||||
"defaultMessage": "聊天模板"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateBuiltin": {
|
||||
"defaultMessage": "内置"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateCustomInline": {
|
||||
"defaultMessage": "自定义内联"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateDescription": {
|
||||
"defaultMessage": "使用嵌入式 GGUF 元数据、llama.cpp 内置模板或内联 Jinja 模板"
|
||||
},
|
||||
"modelSettingsPanel.chatTemplateEmbedded": {
|
||||
"defaultMessage": "嵌入式"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplate": {
|
||||
"defaultMessage": "自定义聊天模板"
|
||||
},
|
||||
"modelSettingsPanel.customChatTemplateDescription": {
|
||||
"defaultMessage": "粘贴完整的 Jinja 聊天模板源码"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "工具调用"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingAuto": {
|
||||
"defaultMessage": "自动"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingDescription": {
|
||||
"defaultMessage": "选择本地模型如何使用原生或模拟工具调用"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceEmulated": {
|
||||
"defaultMessage": "强制模拟"
|
||||
},
|
||||
"modelSettingsPanel.toolCallingForceNative": {
|
||||
"defaultMessage": "强制原生"
|
||||
},
|
||||
"modelSettingsPanel.frequencyPenalty": {
|
||||
"defaultMessage": "频率惩罚"
|
||||
},
|
||||
@@ -2180,12 +2222,6 @@
|
||||
"modelSettingsPanel.minP": {
|
||||
"defaultMessage": "Min P"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCalling": {
|
||||
"defaultMessage": "原生工具调用"
|
||||
},
|
||||
"modelSettingsPanel.nativeToolCallingDescription": {
|
||||
"defaultMessage": "使用模型内置的工具调用格式,而不是 shell 命令模拟器。对可靠支持工具调用的大模型建议启用。"
|
||||
},
|
||||
"modelSettingsPanel.performance": {
|
||||
"defaultMessage": "性能"
|
||||
},
|
||||
@@ -2237,9 +2273,6 @@
|
||||
"modelSettingsPanel.threadsDescription": {
|
||||
"defaultMessage": "用于生成的 CPU 线程数"
|
||||
},
|
||||
"modelSettingsPanel.toolCalling": {
|
||||
"defaultMessage": "工具调用"
|
||||
},
|
||||
"modelSettingsPanel.topK": {
|
||||
"defaultMessage": "Top K"
|
||||
},
|
||||
|
||||
@@ -97,7 +97,6 @@ export function getTextAndImageContent(message: Message): {
|
||||
// Strip assistant-only markup that shouldn't appear in rendered text
|
||||
if (message.role === 'assistant') {
|
||||
textContent = stripToolCallMarkers(textContent);
|
||||
textContent = textContent.replace(/<think>[\s\S]*?<\/think>/gi, '');
|
||||
}
|
||||
|
||||
return { textContent, imagePaths };
|
||||
@@ -122,20 +121,6 @@ export function getThinkingContent(message: Message): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
// Inline <think> tags in assistant text content
|
||||
if (message.role === 'assistant') {
|
||||
for (const content of message.content) {
|
||||
if (content.type === 'text') {
|
||||
const regex = /<think>([\s\S]*?)<\/think>/gi;
|
||||
let match;
|
||||
while ((match = regex.exec(content.text)) !== null) {
|
||||
const text = match[1].trim();
|
||||
if (text) parts.push(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parts.length > 0 ? parts.join('') : null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user