Merge pull request #322 from alibaba/feat/optional-toolchoice
This commit is contained in:
@@ -21,6 +21,7 @@ export interface AdvancedConfig {
|
|||||||
maxSteps?: number
|
maxSteps?: number
|
||||||
systemInstruction?: string
|
systemInstruction?: string
|
||||||
experimentalLlmsTxt?: boolean
|
experimentalLlmsTxt?: boolean
|
||||||
|
disableNamedToolChoice?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtConfig extends LLMConfig, AdvancedConfig {
|
export interface ExtConfig extends LLMConfig, AdvancedConfig {
|
||||||
@@ -124,6 +125,7 @@ export function useAgent(): UseAgentResult {
|
|||||||
maxSteps,
|
maxSteps,
|
||||||
systemInstruction,
|
systemInstruction,
|
||||||
experimentalLlmsTxt,
|
experimentalLlmsTxt,
|
||||||
|
disableNamedToolChoice,
|
||||||
...llmConfig
|
...llmConfig
|
||||||
}: ExtConfig) => {
|
}: ExtConfig) => {
|
||||||
await chrome.storage.local.set({ llmConfig })
|
await chrome.storage.local.set({ llmConfig })
|
||||||
@@ -132,7 +134,12 @@ export function useAgent(): UseAgentResult {
|
|||||||
} else {
|
} else {
|
||||||
await chrome.storage.local.remove('language')
|
await chrome.storage.local.remove('language')
|
||||||
}
|
}
|
||||||
const advancedConfig: AdvancedConfig = { maxSteps, systemInstruction, experimentalLlmsTxt }
|
const advancedConfig: AdvancedConfig = {
|
||||||
|
maxSteps,
|
||||||
|
systemInstruction,
|
||||||
|
experimentalLlmsTxt,
|
||||||
|
disableNamedToolChoice,
|
||||||
|
}
|
||||||
await chrome.storage.local.set({ advancedConfig })
|
await chrome.storage.local.set({ advancedConfig })
|
||||||
setConfig({ ...llmConfig, ...advancedConfig, language })
|
setConfig({ ...llmConfig, ...advancedConfig, language })
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
const [experimentalLlmsTxt, setExperimentalLlmsTxt] = useState(
|
const [experimentalLlmsTxt, setExperimentalLlmsTxt] = useState(
|
||||||
config?.experimentalLlmsTxt ?? false
|
config?.experimentalLlmsTxt ?? false
|
||||||
)
|
)
|
||||||
|
const [disableNamedToolChoice, setDisableNamedToolChoice] = useState(
|
||||||
|
config?.disableNamedToolChoice ?? false
|
||||||
|
)
|
||||||
const [advancedOpen, setAdvancedOpen] = useState(false)
|
const [advancedOpen, setAdvancedOpen] = useState(false)
|
||||||
const [saving, setSaving] = useState(false)
|
const [saving, setSaving] = useState(false)
|
||||||
const [userAuthToken, setUserAuthToken] = useState<string>('')
|
const [userAuthToken, setUserAuthToken] = useState<string>('')
|
||||||
@@ -51,6 +54,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
setMaxSteps(config?.maxSteps)
|
setMaxSteps(config?.maxSteps)
|
||||||
setSystemInstruction(config?.systemInstruction ?? '')
|
setSystemInstruction(config?.systemInstruction ?? '')
|
||||||
setExperimentalLlmsTxt(config?.experimentalLlmsTxt ?? false)
|
setExperimentalLlmsTxt(config?.experimentalLlmsTxt ?? false)
|
||||||
|
setDisableNamedToolChoice(config?.disableNamedToolChoice ?? false)
|
||||||
}, [config])
|
}, [config])
|
||||||
|
|
||||||
// Poll for user auth token every second until found
|
// Poll for user auth token every second until found
|
||||||
@@ -96,6 +100,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
maxSteps: maxSteps || undefined,
|
maxSteps: maxSteps || undefined,
|
||||||
systemInstruction: systemInstruction || undefined,
|
systemInstruction: systemInstruction || undefined,
|
||||||
experimentalLlmsTxt,
|
experimentalLlmsTxt,
|
||||||
|
disableNamedToolChoice,
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false)
|
setSaving(false)
|
||||||
@@ -271,6 +276,11 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label className="flex items-center justify-between cursor-pointer">
|
||||||
|
<span className="text-xs text-muted-foreground">Disable named tool_choice</span>
|
||||||
|
<Switch checked={disableNamedToolChoice} onCheckedChange={setDisableNamedToolChoice} />
|
||||||
|
</label>
|
||||||
|
|
||||||
<label className="flex items-center justify-between cursor-pointer">
|
<label className="flex items-center justify-between cursor-pointer">
|
||||||
<span className="text-xs text-muted-foreground">Experimental llms.txt support</span>
|
<span className="text-xs text-muted-foreground">Experimental llms.txt support</span>
|
||||||
<Switch checked={experimentalLlmsTxt} onCheckedChange={setExperimentalLlmsTxt} />
|
<Switch checked={experimentalLlmsTxt} onCheckedChange={setExperimentalLlmsTxt} />
|
||||||
|
|||||||
@@ -29,16 +29,19 @@ export class OpenAIClient implements LLMClient {
|
|||||||
const openaiTools = Object.entries(tools).map(([name, t]) => zodToOpenAITool(name, t))
|
const openaiTools = Object.entries(tools).map(([name, t]) => zodToOpenAITool(name, t))
|
||||||
|
|
||||||
// Build request body
|
// Build request body
|
||||||
|
|
||||||
|
let toolChoice: unknown = 'required'
|
||||||
|
if (options?.toolChoiceName && !this.config.disableNamedToolChoice) {
|
||||||
|
toolChoice = { type: 'function', function: { name: options.toolChoiceName } }
|
||||||
|
}
|
||||||
|
|
||||||
const requestBody: Record<string, unknown> = {
|
const requestBody: Record<string, unknown> = {
|
||||||
model: this.config.model,
|
model: this.config.model,
|
||||||
temperature: this.config.temperature,
|
temperature: this.config.temperature,
|
||||||
messages,
|
messages,
|
||||||
tools: openaiTools,
|
tools: openaiTools,
|
||||||
parallel_tool_calls: false,
|
parallel_tool_calls: false,
|
||||||
// Require tool call: specific tool if provided, otherwise any tool
|
tool_choice: toolChoice,
|
||||||
tool_choice: options?.toolChoiceName
|
|
||||||
? { type: 'function', function: { name: options.toolChoiceName } }
|
|
||||||
: 'required',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
modelPatch(requestBody)
|
modelPatch(requestBody)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export function parseLLMConfig(config: LLMConfig): Required<LLMConfig> {
|
|||||||
apiKey: config.apiKey || '',
|
apiKey: config.apiKey || '',
|
||||||
temperature: config.temperature ?? DEFAULT_TEMPERATURE,
|
temperature: config.temperature ?? DEFAULT_TEMPERATURE,
|
||||||
maxRetries: config.maxRetries ?? LLM_MAX_RETRIES,
|
maxRetries: config.maxRetries ?? LLM_MAX_RETRIES,
|
||||||
|
disableNamedToolChoice: config.disableNamedToolChoice ?? false,
|
||||||
customFetch: (config.customFetch ?? fetch).bind(globalThis), // fetch will be illegal unless bound
|
customFetch: (config.customFetch ?? fetch).bind(globalThis), // fetch will be illegal unless bound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,12 @@ export interface LLMConfig {
|
|||||||
temperature?: number
|
temperature?: number
|
||||||
maxRetries?: number
|
maxRetries?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove the tool_choice field from the request.
|
||||||
|
* @note fix "Invalid tool_choice type: 'object'" for some LLMs.
|
||||||
|
*/
|
||||||
|
disableNamedToolChoice?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom fetch function for LLM API requests.
|
* Custom fetch function for LLM API requests.
|
||||||
* Use this to customize headers, credentials, proxy, etc.
|
* Use this to customize headers, credentials, proxy, etc.
|
||||||
|
|||||||
@@ -156,6 +156,14 @@ const result = await agent.execute('Fill in the form with test data')`}
|
|||||||
defaultValue: '3',
|
defaultValue: '3',
|
||||||
description: isZh ? 'API 调用失败时的最大重试次数' : 'Maximum retries on API failure',
|
description: isZh ? 'API 调用失败时的最大重试次数' : 'Maximum retries on API failure',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'disableNamedToolChoice',
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: 'false',
|
||||||
|
description: isZh
|
||||||
|
? '禁用命名 tool_choice,始终使用 "required" 字符串。适用于不支持 tool_choice 对象格式的 LLM 服务。'
|
||||||
|
: 'Disable named tool_choice, always use "required" string. For LLM services that don\'t support the object format of tool_choice.',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'customFetch',
|
name: 'customFetch',
|
||||||
type: 'typeof fetch',
|
type: 'typeof fetch',
|
||||||
|
|||||||
Reference in New Issue
Block a user