Compare commits
5 Commits
dev
...
feat/reaso
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d7578a980 | ||
|
|
f14fd37398 | ||
|
|
371a0dd6ec | ||
|
|
a8ca0d6418 | ||
|
|
13a8727552 |
@ -8,6 +8,7 @@ export interface chatCompletionRequestMessage {
|
|||||||
content: string | null | Content[] // Content can be a string OR an array of content parts
|
content: string | null | Content[] // Content can be a string OR an array of content parts
|
||||||
reasoning?: string | null // Some models return reasoning in completed responses
|
reasoning?: string | null // Some models return reasoning in completed responses
|
||||||
reasoning_content?: string | null // Some models return reasoning in completed responses
|
reasoning_content?: string | null // Some models return reasoning in completed responses
|
||||||
|
reasoning_effort?: string | null
|
||||||
name?: string
|
name?: string
|
||||||
tool_calls?: any[] // Simplified tool_call_id?: string
|
tool_calls?: any[] // Simplified tool_call_id?: string
|
||||||
}
|
}
|
||||||
@ -281,5 +282,5 @@ export abstract class AIEngine extends BaseExtension {
|
|||||||
* Check if a tool is supported by the model
|
* Check if a tool is supported by the model
|
||||||
* @param modelId
|
* @param modelId
|
||||||
*/
|
*/
|
||||||
abstract isToolSupported(modelId: string): Promise<boolean>
|
abstract isModelCapabilitySupported(modelId: string, capability: string): Promise<boolean>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,7 @@ type LlamacppConfig = {
|
|||||||
ubatch_size: number
|
ubatch_size: number
|
||||||
device: string
|
device: string
|
||||||
split_mode: string
|
split_mode: string
|
||||||
|
chat_template_kwargs: string
|
||||||
main_gpu: number
|
main_gpu: number
|
||||||
flash_attn: boolean
|
flash_attn: boolean
|
||||||
cont_batching: boolean
|
cont_batching: boolean
|
||||||
@ -71,6 +72,7 @@ type LlamacppConfig = {
|
|||||||
rope_scale: number
|
rope_scale: number
|
||||||
rope_freq_base: number
|
rope_freq_base: number
|
||||||
rope_freq_scale: number
|
rope_freq_scale: number
|
||||||
|
reasoning_budget: boolean
|
||||||
ctx_shift: boolean
|
ctx_shift: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,6 +1391,12 @@ export default class llamacpp_extension extends AIEngine {
|
|||||||
// This is an expert level settings and should only be used by people
|
// This is an expert level settings and should only be used by people
|
||||||
// who knows what they are doing.
|
// who knows what they are doing.
|
||||||
// Takes a regex with matching tensor name as input
|
// Takes a regex with matching tensor name as input
|
||||||
|
if (!cfg.reasoning_budget) {
|
||||||
|
args.push('--reasoning-budget', '0')
|
||||||
|
}
|
||||||
|
if (cfg.chat_template_kwargs) {
|
||||||
|
args.push('--chat-template-kwargs', cfg.chat_template_kwargs)
|
||||||
|
}
|
||||||
if (cfg.override_tensor_buffer_t)
|
if (cfg.override_tensor_buffer_t)
|
||||||
args.push('--override-tensor', cfg.override_tensor_buffer_t)
|
args.push('--override-tensor', cfg.override_tensor_buffer_t)
|
||||||
// offload multimodal projector model to the GPU by default. if there is not enough memory
|
// offload multimodal projector model to the GPU by default. if there is not enough memory
|
||||||
@ -1827,7 +1835,10 @@ export default class llamacpp_extension extends AIEngine {
|
|||||||
* @param modelId
|
* @param modelId
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async isToolSupported(modelId: string): Promise<boolean> {
|
async isModelCapabilitySupported(
|
||||||
|
modelId: string,
|
||||||
|
capability: string
|
||||||
|
): Promise<boolean> {
|
||||||
const janDataFolderPath = await getJanDataFolderPath()
|
const janDataFolderPath = await getJanDataFolderPath()
|
||||||
const modelConfigPath = await joinPath([
|
const modelConfigPath = await joinPath([
|
||||||
this.providerPath,
|
this.providerPath,
|
||||||
@ -1846,7 +1857,7 @@ export default class llamacpp_extension extends AIEngine {
|
|||||||
])
|
])
|
||||||
return (await readGgufMetadata(modelPath)).metadata?.[
|
return (await readGgufMetadata(modelPath)).metadata?.[
|
||||||
'tokenizer.chat_template'
|
'tokenizer.chat_template'
|
||||||
]?.includes('tools')
|
]?.includes(capability)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
IconEye,
|
IconEye,
|
||||||
IconTool,
|
IconTool,
|
||||||
IconAtom,
|
IconBrain,
|
||||||
IconWorld,
|
IconWorld,
|
||||||
IconCodeCircle2,
|
IconCodeCircle2,
|
||||||
} from '@tabler/icons-react'
|
} from '@tabler/icons-react'
|
||||||
@ -30,7 +30,7 @@ const Capabilities = ({ capabilities }: CapabilitiesProps) => {
|
|||||||
} else if (capability === 'tools') {
|
} else if (capability === 'tools') {
|
||||||
icon = <IconTool className="size-3.5" />
|
icon = <IconTool className="size-3.5" />
|
||||||
} else if (capability === 'reasoning') {
|
} else if (capability === 'reasoning') {
|
||||||
icon = <IconAtom className="size-3.5" />
|
icon = <IconBrain className="size-3.5" />
|
||||||
} else if (capability === 'embeddings') {
|
} else if (capability === 'embeddings') {
|
||||||
icon = <IconCodeCircle2 className="size-3.5" />
|
icon = <IconCodeCircle2 className="size-3.5" />
|
||||||
} else if (capability === 'web_search') {
|
} else if (capability === 'web_search') {
|
||||||
|
|||||||
@ -12,15 +12,22 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from '@/components/ui/tooltip'
|
} from '@/components/ui/tooltip'
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/components/ui/popover'
|
||||||
import { ArrowRight } from 'lucide-react'
|
import { ArrowRight } from 'lucide-react'
|
||||||
import {
|
import {
|
||||||
IconPhoto,
|
IconPhoto,
|
||||||
IconWorld,
|
IconWorld,
|
||||||
IconAtom,
|
IconBrain,
|
||||||
IconTool,
|
IconTool,
|
||||||
IconCodeCircle2,
|
IconCodeCircle2,
|
||||||
IconPlayerStopFilled,
|
IconPlayerStopFilled,
|
||||||
IconX,
|
IconX,
|
||||||
|
IconChevronUp,
|
||||||
|
IconChevronDown,
|
||||||
} from '@tabler/icons-react'
|
} from '@tabler/icons-react'
|
||||||
import { useTranslation } from '@/i18n/react-i18next-compat'
|
import { useTranslation } from '@/i18n/react-i18next-compat'
|
||||||
import { useGeneralSetting } from '@/hooks/useGeneralSetting'
|
import { useGeneralSetting } from '@/hooks/useGeneralSetting'
|
||||||
@ -33,7 +40,7 @@ import DropdownModelProvider from '@/containers/DropdownModelProvider'
|
|||||||
import { ModelLoader } from '@/containers/loaders/ModelLoader'
|
import { ModelLoader } from '@/containers/loaders/ModelLoader'
|
||||||
import DropdownToolsAvailable from '@/containers/DropdownToolsAvailable'
|
import DropdownToolsAvailable from '@/containers/DropdownToolsAvailable'
|
||||||
import { getConnectedServers } from '@/services/mcp'
|
import { getConnectedServers } from '@/services/mcp'
|
||||||
import { checkMmprojExists } from '@/services/models'
|
import { checkMmprojExists, stopModel } from '@/services/models'
|
||||||
|
|
||||||
type ChatInputProps = {
|
type ChatInputProps = {
|
||||||
className?: string
|
className?: string
|
||||||
@ -61,6 +68,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
const maxRows = 10
|
const maxRows = 10
|
||||||
|
|
||||||
const { selectedModel, selectedProvider } = useModelProvider()
|
const { selectedModel, selectedProvider } = useModelProvider()
|
||||||
|
|
||||||
const { sendMessage } = useChat()
|
const { sendMessage } = useChat()
|
||||||
const [message, setMessage] = useState('')
|
const [message, setMessage] = useState('')
|
||||||
const [dropdownToolsAvailable, setDropdownToolsAvailable] = useState(false)
|
const [dropdownToolsAvailable, setDropdownToolsAvailable] = useState(false)
|
||||||
@ -77,6 +85,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
const [connectedServers, setConnectedServers] = useState<string[]>([])
|
const [connectedServers, setConnectedServers] = useState<string[]>([])
|
||||||
const [isDragOver, setIsDragOver] = useState(false)
|
const [isDragOver, setIsDragOver] = useState(false)
|
||||||
const [hasMmproj, setHasMmproj] = useState(false)
|
const [hasMmproj, setHasMmproj] = useState(false)
|
||||||
|
const [reasoningEffortOpen, setReasoningEffortOpen] = useState(false)
|
||||||
|
|
||||||
// Check for connected MCP servers
|
// Check for connected MCP servers
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -654,6 +663,112 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{selectedModel?.capabilities?.includes('reasoning') && (
|
||||||
|
<div className="flex gap-0.5 items-center">
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div
|
||||||
|
className="h-7 p-1 flex items-center justify-center rounded-sm hover:bg-main-view-fg/10 transition-all duration-200 ease-in-out gap-1 cursor-pointer"
|
||||||
|
onClick={async () => {
|
||||||
|
if (
|
||||||
|
selectedModel?.reasoning &&
|
||||||
|
selectedProvider
|
||||||
|
) {
|
||||||
|
// Toggle reasoning budget
|
||||||
|
selectedModel.reasoning.reasoning_budget =
|
||||||
|
!selectedModel.reasoning.reasoning_budget
|
||||||
|
|
||||||
|
// If model is loaded, restart it with new settings
|
||||||
|
try {
|
||||||
|
await stopModel(selectedModel.id)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
'Error restarting model with new reasoning budget:',
|
||||||
|
error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconBrain
|
||||||
|
size={18}
|
||||||
|
className={
|
||||||
|
selectedModel?.reasoning?.reasoning_budget
|
||||||
|
? 'text-main-view-fg/50'
|
||||||
|
: 'text-main-view-fg/20'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>
|
||||||
|
{t('reasoning')}:{' '}
|
||||||
|
{selectedModel?.reasoning?.reasoning_budget
|
||||||
|
? 'On'
|
||||||
|
: 'Off'}
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
{selectedModel?.reasoning?.reasoning_budget &&
|
||||||
|
selectedModel?.reasoning?.reasoning_effort && (
|
||||||
|
<Popover
|
||||||
|
open={reasoningEffortOpen}
|
||||||
|
onOpenChange={setReasoningEffortOpen}
|
||||||
|
>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<div className="h-7 mr-1 text-sm rounded-sm text-main-view-fg/70 cursor-pointer flex items-center gap-1">
|
||||||
|
<span className="capitalize">
|
||||||
|
{selectedModel?.reasoning?.reasoning_effort ||
|
||||||
|
'medium'}
|
||||||
|
</span>
|
||||||
|
{reasoningEffortOpen ? (
|
||||||
|
<IconChevronUp
|
||||||
|
size={12}
|
||||||
|
className="text-main-view-fg/50"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<IconChevronDown
|
||||||
|
size={12}
|
||||||
|
className="text-main-view-fg/50"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-24 p-0" align="start">
|
||||||
|
<div className="py-1">
|
||||||
|
{['low', 'medium', 'high'].map((effort) => (
|
||||||
|
<div
|
||||||
|
key={effort}
|
||||||
|
className="px-2 py-1.5 text-sm cursor-pointer hover:bg-main-view-fg/20 capitalize"
|
||||||
|
onClick={async () => {
|
||||||
|
if (selectedModel?.reasoning) {
|
||||||
|
selectedModel.reasoning.reasoning_effort =
|
||||||
|
effort
|
||||||
|
setReasoningEffortOpen(false)
|
||||||
|
// Restart model with new reasoning effort
|
||||||
|
try {
|
||||||
|
await stopModel(selectedModel.id)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
'Error restarting model with new reasoning effort:',
|
||||||
|
error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{effort}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{selectedModel?.capabilities?.includes('tools') &&
|
{selectedModel?.capabilities?.includes('tools') &&
|
||||||
hasActiveMCPServers && (
|
hasActiveMCPServers && (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
@ -728,23 +843,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
)}
|
)}
|
||||||
{selectedModel?.capabilities?.includes('reasoning') && (
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<div className="h-7 p-1 flex items-center justify-center rounded-sm hover:bg-main-view-fg/10 transition-all duration-200 ease-in-out gap-1">
|
|
||||||
<IconAtom
|
|
||||||
size={18}
|
|
||||||
className="text-main-view-fg/50"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>{t('reasoning')}</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -393,7 +393,7 @@ const DropdownModelProvider = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover open={open} onOpenChange={onOpenChange}>
|
<Popover open={open} onOpenChange={onOpenChange}>
|
||||||
<div className="bg-main-view-fg/5 hover:bg-main-view-fg/8 px-2 py-1 flex items-center gap-1.5 rounded-sm max-h-[32px] mr-0.5">
|
<div className="bg-main-view-fg/5 hover:bg-main-view-fg/8 px-2 py-1 flex items-center gap-1.5 rounded-sm max-h-[32px] mr-1">
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<button
|
<button
|
||||||
title={displayModel}
|
title={displayModel}
|
||||||
|
|||||||
@ -77,6 +77,7 @@ export const useModelProvider = create<ModelProviderState>()(
|
|||||||
('id' in e || 'model' in e) &&
|
('id' in e || 'model' in e) &&
|
||||||
typeof (e.id ?? e.model) === 'string'
|
typeof (e.id ?? e.model) === 'string'
|
||||||
)
|
)
|
||||||
|
console.log(models, 'models')
|
||||||
const mergedModels = [
|
const mergedModels = [
|
||||||
...(provider?.models ?? []).filter(
|
...(provider?.models ?? []).filter(
|
||||||
(e) =>
|
(e) =>
|
||||||
@ -99,7 +100,10 @@ export const useModelProvider = create<ModelProviderState>()(
|
|||||||
return {
|
return {
|
||||||
...model,
|
...model,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
capabilities: existingModel?.capabilities || model.capabilities,
|
capabilities:
|
||||||
|
provider.provider === 'llamacpp'
|
||||||
|
? model.capabilities
|
||||||
|
: existingModel?.capabilities || model.capabilities,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@ vi.mock('../models', () => ({
|
|||||||
{ id: 'llama-2-7b', name: 'Llama 2 7B', description: 'Llama model' },
|
{ id: 'llama-2-7b', name: 'Llama 2 7B', description: 'Llama model' },
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
isToolSupported: vi.fn(() => Promise.resolve(false)),
|
isModelCapabilitySupported: vi.fn(() => Promise.resolve(false)),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/lib/extension', () => ({
|
vi.mock('@/lib/extension', () => ({
|
||||||
|
|||||||
@ -415,14 +415,23 @@ export const startModel = async (
|
|||||||
return keyMappings[key] || key
|
return keyMappings[key] || key
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = modelConfig?.settings
|
const settings = {
|
||||||
? Object.fromEntries(
|
...(modelConfig?.settings
|
||||||
Object.entries(modelConfig.settings).map(([key, value]) => [
|
? Object.fromEntries(
|
||||||
mapSettingKey(key),
|
Object.entries(modelConfig.settings).map(([key, value]) => [
|
||||||
value.controller_props?.value,
|
mapSettingKey(key),
|
||||||
])
|
value.controller_props?.value,
|
||||||
)
|
])
|
||||||
: undefined
|
)
|
||||||
|
: {}),
|
||||||
|
...(modelConfig?.reasoning?.reasoning_budget !== undefined && {
|
||||||
|
reasoning_budget: modelConfig.reasoning.reasoning_budget,
|
||||||
|
}),
|
||||||
|
...(modelConfig?.reasoning?.reasoning_budget &&
|
||||||
|
modelConfig?.reasoning?.reasoning_effort !== undefined && {
|
||||||
|
chat_template_kwargs: `{"reasoning_effort":"${modelConfig.reasoning.reasoning_effort}"}`,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
return engine.load(model, settings).catch((error) => {
|
return engine.load(model, settings).catch((error) => {
|
||||||
console.error(
|
console.error(
|
||||||
@ -439,11 +448,14 @@ export const startModel = async (
|
|||||||
* @param modelId
|
* @param modelId
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const isToolSupported = async (modelId: string): Promise<boolean> => {
|
export const isModelCapabilitySupported = async (
|
||||||
|
modelId: string,
|
||||||
|
capability: string
|
||||||
|
): Promise<boolean> => {
|
||||||
const engine = getEngine()
|
const engine = getEngine()
|
||||||
if (!engine) return false
|
if (!engine) return false
|
||||||
|
|
||||||
return engine.isToolSupported(modelId)
|
return engine.isModelCapabilitySupported(modelId, capability)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { predefinedProviders } from '@/consts/providers'
|
|||||||
import { EngineManager, SettingComponentProps } from '@janhq/core'
|
import { EngineManager, SettingComponentProps } from '@janhq/core'
|
||||||
import { ModelCapabilities } from '@/types/models'
|
import { ModelCapabilities } from '@/types/models'
|
||||||
import { modelSettings } from '@/lib/predefined'
|
import { modelSettings } from '@/lib/predefined'
|
||||||
import { fetchModels, isToolSupported } from './models'
|
import { fetchModels, isModelCapabilitySupported } from './models'
|
||||||
import { ExtensionManager } from '@/lib/extension'
|
import { ExtensionManager } from '@/lib/extension'
|
||||||
import { fetch as fetchTauri } from '@tauri-apps/plugin-http'
|
import { fetch as fetchTauri } from '@tauri-apps/plugin-http'
|
||||||
|
|
||||||
@ -63,39 +63,54 @@ export const getProviders = async (): Promise<ModelProvider[]> => {
|
|||||||
}
|
}
|
||||||
}) as ProviderSetting[],
|
}) as ProviderSetting[],
|
||||||
models: await Promise.all(
|
models: await Promise.all(
|
||||||
models.map(
|
models.map(async (model) => {
|
||||||
async (model) =>
|
return {
|
||||||
({
|
id: model.id,
|
||||||
id: model.id,
|
model: model.id,
|
||||||
model: model.id,
|
name: model.name,
|
||||||
name: model.name,
|
description: model.description,
|
||||||
description: model.description,
|
capabilities: [
|
||||||
capabilities:
|
...((await isModelCapabilitySupported(model.id, 'tools'))
|
||||||
'capabilities' in model
|
? [ModelCapabilities.TOOLS]
|
||||||
? (model.capabilities as string[])
|
: []),
|
||||||
: (await isToolSupported(model.id))
|
...((await isModelCapabilitySupported(model.id, 'reasoning'))
|
||||||
? [ModelCapabilities.TOOLS]
|
? [ModelCapabilities.REASONING]
|
||||||
: [],
|
: []),
|
||||||
provider: providerName,
|
],
|
||||||
settings: Object.values(modelSettings).reduce(
|
provider: providerName,
|
||||||
(acc, setting) => {
|
settings: Object.values(modelSettings).reduce(
|
||||||
let value = setting.controller_props.value
|
(acc, setting) => {
|
||||||
if (setting.key === 'ctx_len') {
|
let value = setting.controller_props.value
|
||||||
value = 8192 // Default context length for Llama.cpp models
|
if (setting.key === 'ctx_len') {
|
||||||
}
|
value = 8192 // Default context length for Llama.cpp models
|
||||||
acc[setting.key] = {
|
}
|
||||||
...setting,
|
acc[setting.key] = {
|
||||||
controller_props: {
|
...setting,
|
||||||
...setting.controller_props,
|
controller_props: {
|
||||||
value: value,
|
...setting.controller_props,
|
||||||
},
|
value: value,
|
||||||
}
|
},
|
||||||
return acc
|
}
|
||||||
},
|
return acc
|
||||||
{} as Record<string, ProviderSetting>
|
},
|
||||||
),
|
{} as Record<string, ProviderSetting>
|
||||||
}) as Model
|
),
|
||||||
)
|
...(model.capabilities?.includes(ModelCapabilities.REASONING) ||
|
||||||
|
(await isModelCapabilitySupported(model.id, 'reasoning'))
|
||||||
|
? {
|
||||||
|
reasoning: {
|
||||||
|
reasoning_budget: true,
|
||||||
|
...((await isModelCapabilitySupported(
|
||||||
|
model.id,
|
||||||
|
'reasoning_effort'
|
||||||
|
))
|
||||||
|
? { reasoning_effort: 'medium' }
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
} as Model
|
||||||
|
})
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
runtimeProviders.push(provider)
|
runtimeProviders.push(provider)
|
||||||
|
|||||||
2
web-app/src/types/modelProviders.d.ts
vendored
2
web-app/src/types/modelProviders.d.ts
vendored
@ -33,6 +33,8 @@ type Model = {
|
|||||||
format?: string
|
format?: string
|
||||||
capabilities?: string[]
|
capabilities?: string[]
|
||||||
settings?: Record<string, ProviderSetting>
|
settings?: Record<string, ProviderSetting>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
reasoning?: Record<string, any>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -7,6 +7,7 @@ export enum ModelCapabilities {
|
|||||||
COMPLETION = 'completion',
|
COMPLETION = 'completion',
|
||||||
TOOLS = 'tools',
|
TOOLS = 'tools',
|
||||||
EMBEDDINGS = 'embeddings',
|
EMBEDDINGS = 'embeddings',
|
||||||
|
REASONING = 'reasoning',
|
||||||
IMAGE_GENERATION = 'image_generation',
|
IMAGE_GENERATION = 'image_generation',
|
||||||
AUDIO_GENERATION = 'audio_generation',
|
AUDIO_GENERATION = 'audio_generation',
|
||||||
TEXT_TO_IMAGE = 'text_to_image',
|
TEXT_TO_IMAGE = 'text_to_image',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user