tools fix
This commit is contained in:
@@ -1600,6 +1600,9 @@ func scrubToolMarkers(text string) string {
|
||||
reEmptyFences := regexp.MustCompile("(?s)```(?:xml|json|ya?ml)?\\s*```")
|
||||
s = reEmptyFences.ReplaceAllString(s, "")
|
||||
|
||||
reCitationDisclaimer := regexp.MustCompile(`(?i)\*?Web evidence was retrieved[^\n*]*\.\*?`)
|
||||
s = reCitationDisclaimer.ReplaceAllString(s, "")
|
||||
|
||||
trimmed := strings.TrimSpace(s)
|
||||
if trimmed == "```xml" || trimmed == "```json" || trimmed == "```" {
|
||||
return ""
|
||||
@@ -1618,8 +1621,10 @@ func scrubToolMarkers(text string) string {
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
func ExtractToolCallBlocks(content string) (blocks []string, remaining string) {
|
||||
func ExtractToolCallBlocks(content string) (blocks []string, preCallText string, remaining string) {
|
||||
remaining = content
|
||||
var firstPreamble string
|
||||
firstBlockFound := false
|
||||
|
||||
reDynamicOpen := regexp.MustCompile(`(?i)<(?:tool_calls?|toolCalls?|function_calls?|functionCalls?|invoke|call|command|commands|action|function)(?:\s+[^>]*)?>|<(?:call|tool_call|function_call):[a-zA-Z0-9_-]+(?:\s+[^>]*)?>|<function=[a-zA-Z0-9_-]+>|\[TOOL_CALLS?\]`)
|
||||
|
||||
@@ -1670,9 +1675,21 @@ func ExtractToolCallBlocks(content string) (blocks []string, remaining string) {
|
||||
before = reFenceOpen.ReplaceAllString(before, "")
|
||||
after = reFenceClose.ReplaceAllString(after, "")
|
||||
}
|
||||
if !firstBlockFound {
|
||||
preClean := reFenceOpen.ReplaceAllString(before, "")
|
||||
firstPreamble = strings.TrimRight(preClean, "\r\n ")
|
||||
firstBlockFound = true
|
||||
}
|
||||
remaining = strings.TrimSpace(before + after)
|
||||
} else {
|
||||
nextLoc := reDynamicOpen.FindStringIndex(rest)
|
||||
before := remaining[:sIdx]
|
||||
reFenceOpen := regexp.MustCompile("(?s)\\n?\\s*```(?:xml|json|ya?ml)?\\s*$")
|
||||
if !firstBlockFound {
|
||||
preClean := reFenceOpen.ReplaceAllString(before, "")
|
||||
firstPreamble = strings.TrimRight(preClean, "\r\n ")
|
||||
firstBlockFound = true
|
||||
}
|
||||
if nextLoc != nil {
|
||||
blockEndPos := loc[1] + nextLoc[0]
|
||||
blockText = remaining[sIdx:blockEndPos]
|
||||
@@ -1692,16 +1709,17 @@ func ExtractToolCallBlocks(content string) (blocks []string, remaining string) {
|
||||
blockText := remaining[loc[0]:loc[1]]
|
||||
before := remaining[:loc[0]]
|
||||
after := remaining[loc[1]:]
|
||||
firstPreamble = strings.TrimSpace(before)
|
||||
remaining = strings.TrimSpace(before + " " + after)
|
||||
blocks = append(blocks, blockText)
|
||||
}
|
||||
}
|
||||
|
||||
return blocks, remaining
|
||||
return blocks, firstPreamble, remaining
|
||||
}
|
||||
|
||||
func DetectToolCalls(content string) ([]ToolCall, string, bool) {
|
||||
blocks, remaining := ExtractToolCallBlocks(content)
|
||||
blocks, preCallText, _ := ExtractToolCallBlocks(content)
|
||||
var calls []ToolCall
|
||||
|
||||
for _, block := range blocks {
|
||||
@@ -1711,25 +1729,29 @@ func DetectToolCalls(content string) ([]ToolCall, string, bool) {
|
||||
}
|
||||
|
||||
if len(calls) > 0 {
|
||||
remaining = scrubToolMarkers(remaining)
|
||||
return calls, remaining, true
|
||||
return calls, scrubToolMarkers(preCallText), true
|
||||
}
|
||||
|
||||
reFenced := regexp.MustCompile("(?s)```(?:json|xml)?\\s*([\\s\\S]*?)\\s*```")
|
||||
matches := reFenced.FindAllStringSubmatchIndex(content, -1)
|
||||
if len(matches) > 0 {
|
||||
var fencedCalls []ToolCall
|
||||
rem := content
|
||||
firstFenceStart := -1
|
||||
for _, loc := range matches {
|
||||
fenceTotal := content[loc[0]:loc[1]]
|
||||
fenceInner := strings.TrimSpace(content[loc[2]:loc[3]])
|
||||
if tcs, ok := parseMultipleToolCalls(fenceInner); ok && len(tcs) > 0 {
|
||||
if firstFenceStart == -1 {
|
||||
firstFenceStart = loc[0]
|
||||
}
|
||||
fencedCalls = append(fencedCalls, tcs...)
|
||||
rem = strings.Replace(rem, fenceTotal, "", 1)
|
||||
}
|
||||
}
|
||||
if len(fencedCalls) > 0 {
|
||||
return fencedCalls, scrubToolMarkers(rem), true
|
||||
pre := ""
|
||||
if firstFenceStart > 0 {
|
||||
pre = content[:firstFenceStart]
|
||||
}
|
||||
return fencedCalls, scrubToolMarkers(pre), true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1744,22 +1766,33 @@ func DetectToolCalls(content string) ([]ToolCall, string, bool) {
|
||||
callLocs := reCallInContent.FindAllStringIndex(content, -1)
|
||||
if len(callLocs) > 0 {
|
||||
var pyCalls []ToolCall
|
||||
rem := content
|
||||
firstCallStart := -1
|
||||
for _, loc := range callLocs {
|
||||
callStr := strings.TrimSpace(content[loc[0]:loc[1]])
|
||||
if tc, ok := parsePythonFunctionCall(callStr); ok {
|
||||
if firstCallStart == -1 {
|
||||
firstCallStart = loc[0]
|
||||
}
|
||||
pyCalls = append(pyCalls, tc)
|
||||
rem = strings.Replace(rem, content[loc[0]:loc[1]], "", 1)
|
||||
}
|
||||
}
|
||||
if len(pyCalls) > 0 {
|
||||
return pyCalls, scrubToolMarkers(rem), true
|
||||
pre := ""
|
||||
if firstCallStart > 0 {
|
||||
pre = content[:firstCallStart]
|
||||
}
|
||||
return pyCalls, scrubToolMarkers(pre), true
|
||||
}
|
||||
}
|
||||
|
||||
if tc, ok := parseReActToolCall(content); ok {
|
||||
rem := scrubToolMarkers(content)
|
||||
return []ToolCall{tc}, rem, true
|
||||
reAction := regexp.MustCompile(`(?i)(?:Action|Command):\s*[a-zA-Z0-9_.-]+`)
|
||||
loc := reAction.FindStringIndex(content)
|
||||
pre := ""
|
||||
if loc != nil && loc[0] > 0 {
|
||||
pre = content[:loc[0]]
|
||||
}
|
||||
return []ToolCall{tc}, scrubToolMarkers(pre), true
|
||||
}
|
||||
|
||||
if tcs, ok := parseMultiplePythonFunctionCalls(trimmed); ok && len(tcs) > 0 {
|
||||
@@ -2363,7 +2396,7 @@ func (f *StreamToolCallFilter) Feed(chunk string, onContent func(string), onTool
|
||||
} else {
|
||||
before = strings.TrimRight(before, "\r\n")
|
||||
}
|
||||
if before != "" {
|
||||
if before != "" && !f.emittedCall {
|
||||
onContent(before)
|
||||
}
|
||||
f.inToolCall = true
|
||||
@@ -2385,7 +2418,7 @@ func (f *StreamToolCallFilter) Feed(chunk string, onContent func(string), onTool
|
||||
safe = reTrailingFence.ReplaceAllString(safe, "")
|
||||
safe = strings.TrimRight(safe, "\r\n")
|
||||
}
|
||||
if strings.TrimSpace(safe) != "" {
|
||||
if strings.TrimSpace(safe) != "" && !f.emittedCall {
|
||||
onContent(safe)
|
||||
}
|
||||
f.buf = f.buf[len(f.buf)-holdLen:]
|
||||
@@ -2393,7 +2426,9 @@ func (f *StreamToolCallFilter) Feed(chunk string, onContent func(string), onTool
|
||||
} else if len(f.buf) < 16 && strings.TrimSpace(f.buf) == "" {
|
||||
break
|
||||
} else {
|
||||
onContent(f.buf)
|
||||
if !f.emittedCall {
|
||||
onContent(f.buf)
|
||||
}
|
||||
f.buf = ""
|
||||
break
|
||||
}
|
||||
@@ -2432,7 +2467,7 @@ func (f *StreamToolCallFilter) Feed(chunk string, onContent func(string), onTool
|
||||
f.toolIndex++
|
||||
f.emittedCall = true
|
||||
onToolCall(tc4)
|
||||
} else {
|
||||
} else if !f.emittedCall {
|
||||
onContent(f.activePair.Start + f.toolCallBuf + f.activePair.End)
|
||||
}
|
||||
f.toolCallBuf = ""
|
||||
@@ -2484,18 +2519,13 @@ func (f *StreamToolCallFilter) Flush(onContent func(string), onToolCall func(Too
|
||||
f.toolIndex++
|
||||
f.emittedCall = true
|
||||
onToolCall(tc4)
|
||||
} else {
|
||||
} else if !f.emittedCall {
|
||||
onContent(f.activePair.Start + f.toolCallBuf)
|
||||
}
|
||||
f.toolCallBuf = ""
|
||||
}
|
||||
if len(f.buf) > 0 {
|
||||
if f.emittedCall {
|
||||
clean := scrubToolMarkers(f.buf)
|
||||
if strings.TrimSpace(clean) != "" {
|
||||
onContent(strings.TrimSpace(clean))
|
||||
}
|
||||
} else {
|
||||
if !f.emittedCall {
|
||||
onContent(f.buf)
|
||||
}
|
||||
f.buf = ""
|
||||
@@ -2576,8 +2606,9 @@ type SpaceParamMapping struct {
|
||||
ComponentType string `json:"component_type,omitempty"`
|
||||
Label string `json:"label,omitempty"`
|
||||
ParamName string `json:"param_name,omitempty"`
|
||||
ParamType string `json:"param_type"` // "message", "history", "system_prompt", "temperature", "max_tokens", "top_p", "think_level", "tools", "stream", "state", "other"
|
||||
ParamType string `json:"param_type"` // "message", "history", "system_prompt", "temperature", "max_tokens", "top_p", "think_level", "tools", "stream", "state", "web_search", "other"
|
||||
DefaultValue interface{} `json:"default_value,omitempty"`
|
||||
Choices []string `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
type SpaceDiscovery struct {
|
||||
@@ -2609,6 +2640,7 @@ type SpaceDiscovery struct {
|
||||
ThinkLevelIndex int `json:"think_level_index"` // -1 if none
|
||||
FunctionsJSONIndex int `json:"functions_json_index"` // -1 if none
|
||||
PreservedThinkingIndex int `json:"preserved_thinking_index"` // -1 if none
|
||||
WebSearchIndex int `json:"web_search_index"` // -1 if none
|
||||
IsHunyuan3 bool `json:"is_hunyuan3"`
|
||||
HistoryFormat string `json:"history_format"` // "messages", "pairs", "gradio_messages", "none"
|
||||
ToolCallMode string `json:"tool_call_mode"` // "native_slot", "prompt_augmented_system", "prompt_augmented_first_turn", "prompt_augmented_single_prompt"
|
||||
@@ -2758,6 +2790,7 @@ func NewDefaultSpaceDiscovery(spaceURL string) *SpaceDiscovery {
|
||||
ThinkLevelIndex: -1,
|
||||
FunctionsJSONIndex: -1,
|
||||
PreservedThinkingIndex: -1,
|
||||
WebSearchIndex: -1,
|
||||
HistoryFormat: "messages",
|
||||
ToolCallMode: "prompt_augmented_single_prompt",
|
||||
LastDiscovered: time.Now(),
|
||||
@@ -3293,6 +3326,29 @@ func InspectSpace(client *http.Client, rawURL, userAgent string) (*SpaceDiscover
|
||||
discovery.DefaultInputs[idx] = val
|
||||
mapping.DefaultValue = val
|
||||
}
|
||||
if chList, ok := comp.Props["choices"].([]interface{}); ok {
|
||||
for _, ch := range chList {
|
||||
if chStr, ok := ch.(string); ok {
|
||||
mapping.Choices = append(mapping.Choices, chStr)
|
||||
} else if chPair, ok := ch.([]interface{}); ok && len(chPair) > 0 {
|
||||
if chStr, ok := chPair[0].(string); ok {
|
||||
mapping.Choices = append(mapping.Choices, chStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if bestEndpointInfo != nil && idx < len(bestEndpointInfo.Parameters) && len(mapping.Choices) == 0 {
|
||||
p := bestEndpointInfo.Parameters[idx]
|
||||
if typeMap, ok := p.Type.(map[string]interface{}); ok {
|
||||
if enumArr, ok := typeMap["enum"].([]interface{}); ok {
|
||||
for _, e := range enumArr {
|
||||
if s, ok := e.(string); ok {
|
||||
mapping.Choices = append(mapping.Choices, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(pName, "function") || strings.Contains(pName, "tool") || strings.Contains(pLabel, "tool") || strings.Contains(pLabel, "function") || strings.Contains(cLabel, "tool") || strings.Contains(cLabel, "function") {
|
||||
@@ -3335,6 +3391,9 @@ func InspectSpace(client *http.Client, rawURL, userAgent string) (*SpaceDiscover
|
||||
} else if strings.Contains(pName, "stream") || strings.Contains(cLabel, "stream") {
|
||||
mapping.ParamType = "stream"
|
||||
discovery.StreamIndex = idx
|
||||
} else if strings.Contains(pName, "search") || strings.Contains(pLabel, "search") || strings.Contains(cLabel, "search") || strings.Contains(pName, "browse") || strings.Contains(pLabel, "browse") || strings.Contains(cLabel, "browse") || strings.Contains(pName, "web") || strings.Contains(pLabel, "web") || strings.Contains(cLabel, "web") {
|
||||
mapping.ParamType = "web_search"
|
||||
discovery.WebSearchIndex = idx
|
||||
} else if cType == "state" {
|
||||
mapping.ParamType = "state"
|
||||
}
|
||||
@@ -3402,6 +3461,9 @@ func InspectSpace(client *http.Client, rawURL, userAgent string) (*SpaceDiscover
|
||||
if discovery.StreamIndex >= discovery.TotalInputs {
|
||||
discovery.StreamIndex = -1
|
||||
}
|
||||
if discovery.WebSearchIndex >= discovery.TotalInputs {
|
||||
discovery.WebSearchIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3501,6 +3563,19 @@ func InspectSpace(client *http.Client, rawURL, userAgent string) (*SpaceDiscover
|
||||
} else if strings.Contains(pName, "stream") || strings.Contains(pLabel, "stream") {
|
||||
discovery.StreamIndex = idx
|
||||
mapping.ParamType = "stream"
|
||||
} else if strings.Contains(pName, "search") || strings.Contains(pLabel, "search") || strings.Contains(pName, "browse") || strings.Contains(pLabel, "browse") || strings.Contains(pName, "web") || strings.Contains(pLabel, "web") {
|
||||
discovery.WebSearchIndex = idx
|
||||
mapping.ParamType = "web_search"
|
||||
}
|
||||
|
||||
if typeMap, ok := p.Type.(map[string]interface{}); ok {
|
||||
if enumArr, ok := typeMap["enum"].([]interface{}); ok {
|
||||
for _, e := range enumArr {
|
||||
if s, ok := e.(string); ok {
|
||||
mapping.Choices = append(mapping.Choices, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
discovery.ParamMappings = append(discovery.ParamMappings, mapping)
|
||||
@@ -4043,6 +4118,38 @@ func (g *GradioGateway) BuildGradioPayload(disc *SpaceDiscovery, req ChatComplet
|
||||
data[disc.FunctionsJSONIndex] = functionsJSONStr
|
||||
}
|
||||
|
||||
if disc.WebSearchIndex >= 0 && disc.WebSearchIndex != disc.MessageIndex && disc.WebSearchIndex != disc.HistoryIndex && disc.WebSearchIndex != disc.SystemIndex && disc.WebSearchIndex < len(data) && len(req.Tools) > 0 {
|
||||
var mapping *SpaceParamMapping
|
||||
for i := range disc.ParamMappings {
|
||||
if disc.ParamMappings[i].InputIndex == disc.WebSearchIndex {
|
||||
mapping = &disc.ParamMappings[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
disabledSet := false
|
||||
if mapping != nil && len(mapping.Choices) > 0 {
|
||||
for _, choice := range mapping.Choices {
|
||||
cLower := strings.ToLower(choice)
|
||||
if cLower == "direct" || cLower == "off" || cLower == "disabled" || cLower == "none" || cLower == "false" || cLower == "no" || strings.Contains(cLower, "direct") || strings.Contains(cLower, "no search") || strings.Contains(cLower, "disable") {
|
||||
data[disc.WebSearchIndex] = choice
|
||||
disabledSet = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !disabledSet {
|
||||
switch data[disc.WebSearchIndex].(type) {
|
||||
case bool:
|
||||
data[disc.WebSearchIndex] = false
|
||||
case string:
|
||||
strVal := strings.ToLower(data[disc.WebSearchIndex].(string))
|
||||
if strings.Contains(strVal, "search") {
|
||||
data[disc.WebSearchIndex] = "Direct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user